2014-09-12
| 00:27 | sdegutis | is Delegate a horrible name for an app? |
| 00:33 | TEttinger | sdegutis: it is great if you want to make a blame-passing app. like, I don't want to do this, let me consult Delegate to see who to give the project to |
| 00:33 | sdegutis | :) |
| 00:33 | rpaulo | heheh |
| 00:40 | craigglennie | What’s the current state-of-the-art for web-scraping - is it Enlive? |
| 00:42 | danielcompton | sdegutis: make sure it doesn't violate the single responsibility principle and you're fine |
| 00:43 | sdegutis | heh |
| 00:43 | sdegutis | I have given up on naming my app. |
| 00:43 | danielcompton | craigglennie: think it's Amazon Turk still |
| 00:43 | sdegutis | I'm just going to call it Concierge.app and be done with it. |
| 00:43 | danielcompton | sdegutis: Mac app? |
| 00:43 | sdegutis | yes |
| 00:43 | craigglennie | danielcompton: You mean MTurk? I’m thinking more of something equiavlent to Python’s beautifulsoup or lxml |
| 00:44 | craigglennie | danielcompton: Something to help me parse data out of HTML |
| 00:44 | jarjar_prime | hello all! |
| 00:46 | seancorfield | craigglennie sure sounds like Enlive to me... |
| 00:46 | danielcompton | sdegutis: cool, what does it do? |
| 00:47 | sdegutis | you give it a script and it runs your script, and it gives you an api for your script to use that hooks into low-level GUI APIs |
| 00:47 | sdegutis | or something |
| 00:48 | danielcompton | sdegutis: what's the use case? |
| 00:48 | sdegutis | scripting your gui |
| 00:48 | sdegutis | i.e. write 4 lines so that any time you press a global hotkey, your mouse cursor moves to the center of the focused window |
| 00:48 | craigglennie | seancorfield: thanks |
| 00:48 | sdegutis | or bind some global hotkeys to move windows around |
| 00:50 | sdegutis | is there a version of Clojure for embedding in a C app? |
| 00:51 | sm0ke | https://github.com/raph-amiard/clojurescript-lua |
| 00:51 | sdegutis | requires a jvm still? |
| 00:52 | sm0ke | i guess you could compile it , but yes for dev jvm would be required |
| 00:52 | sdegutis | why oh why jvm do you have to be so different, fricken hipster |
| 00:53 | sdegutis | everything is written in C except suddenly theres java and now nothings compatible with anything else |
| 00:53 | sm0ke | java is written in C you know |
| 00:53 | sdegutis | thats the worst part! |
| 00:53 | p_l | actually what is really incompatible... is C++ |
| 00:53 | sdegutis | its like its mocking us! just sitting there like "haha im written in C but completely incompatible with C" |
| 00:54 | sm0ke | :P |
| 00:54 | p_l | Java got JNI and I had seen stuff that looked like it had embedded Java |
| 00:54 | sm0ke | have you looked ar jnr |
| 00:54 | sdegutis | welp |
| 00:54 | sdegutis | gonna name my app Concierge.app |
| 00:54 | sm0ke | its frekin awesome |
| 00:54 | sm0ke | https://github.com/jnr/jnr-ffi |
| 00:54 | sdegutis | although someone told me it has, umm, certain connotations |
| 00:55 | sdegutis | but i cant find anything bad in the dictionary or wikipedia page about it |
| 00:56 | sm0ke | why would you want to write in clojure if your stack doesnt have jvm |
| 00:56 | sm0ke | write in ocaml, haskell, scheme, guile |
| 00:56 | sm0ke | and a hundered more |
| 00:56 | sdegutis | +1 |
| 00:57 | sm0ke | sdegutis: still here? |
| 00:57 | sdegutis | hi |
| 00:57 | sm0ke | oh i though you will part from #clojure |
| 00:57 | sdegutis | why |
| 00:58 | sm0ke | nothin |
| 00:58 | sdegutis | k |
| 00:58 | danielcompton | sdegutis: "Adult" concierges exist and mean pretty much what you think they mean |
| 00:58 | sdegutis | crap |
| 00:58 | sdegutis | ugh |
| 00:59 | sdegutis | there are no names. |
| 00:59 | sdegutis | all names are taken. |
| 00:59 | sdegutis | i have been trying to name this app for like 4 months no |
| 00:59 | sdegutis | *now |
| 01:00 | sm0ke | chauffer |
| 01:00 | sdegutis | i wanted to do Minion.app but everyone will think of those dumb yellow things |
| 01:00 | sdegutis | i might do Lackey.app |
| 01:00 | sdegutis | but i have no idea what people think when they hear lackey |
| 01:00 | danielcompton | sdegutis: OTOH adding adult to any word makes it sound bad. Concierge sounds pretty good to me |
| 01:01 | sm0ke | sdegutis: Sevak.app |
| 01:03 | sdegutis | lol Manager.app |
| 01:03 | sdegutis | yeah ill stick with Concierge |
| 01:04 | sdegutis | if at least 20% of the people i tell this to say the adult-concierge thing, its gone. otherwise ill keep it |
| 01:10 | TEttinger | YourNameIsToby.app |
| 01:10 | sdegutis | correct |
| 01:12 | dorkmafia | technomancy: https://github.com/rplevy/clojure-python found this |
| 01:13 | dorkmafia | i'm going to give it a spin now |
| 01:57 | TheMonarc | greetings, is there a good clojure book for someone who is new to both clojure and FP? |
| 01:58 | TheMonarc | new to FP part not as important (did a little LISP in college) |
| 01:59 | dbasch | TheMonarc: you may like http://joyofclojure.com/ |
| 02:00 | dbasch | actually http://www.amazon.com/The-Joy-Clojure-Michael-Fogus/dp/1617291412/ |
| 02:16 | zanes | TheMonarc: You might also like http://www.braveclojure.com/ |
| 02:16 | zanes | Has the added benefit of talking about tooling. |
| 03:08 | zot | morning :) i'm new to it, and seeking the most natural/elegant way to iterate through a string, splitting at a regex, but iterating through both matches, and the goo in between |
| 03:09 | zot | thus: regex: "\d" with an input of "asdf 2 ff 33" -> seq ["asdf ", "2", " ff ", "3", "3"] |
| 03:09 | zot | is there something that i'm not finding to do this cleanly? |
| 03:09 | zot | (i can make my own groupings both inside and outside of the expression, but thought there might already be a better way |
| 03:13 | engblom | zot: http://clojuredocs.org/clojure_core/clojure.string/split |
| 03:14 | zot | engblom: i found that, but it drops the matching bit. re-seq appears to only yield the matching bit, and i haven't found a single thing threads them (or keeps them) together :) |
| 03:20 | Bronsa | zot: you can use interpose on c.s/split and re-seq if you don't mind running over the string twice |
| 03:22 | Bronsa | err, interleave |
| 03:22 | zot | interesting, but the matching expression isn't fixed |
| 03:22 | zot | yeah, that looks much better. have to do first match manually to see which seq leads, but that's the right idea :) |
| 03:23 | Bronsa | ,(require '[clojure.string :as s]) |
| 03:23 | clojurebot | nil |
| 03:23 | Bronsa | ,(defn f [p s] (interleave (s/split s p) (re-seq p s))) |
| 03:23 | clojurebot | #'sandbox/f |
| 03:23 | Bronsa | ,(map (partial f #"\d") ["1 a 2 b" "a 1 b 2"]) |
| 03:23 | clojurebot | (("" "1" " a " "2") ("a " "1" " b " "2")) |
| 03:24 | Bronsa | uhm |
| 03:24 | zot | looks pretty good to me :) |
| 03:24 | zot | thanks!! |
| 03:24 | Bronsa | zot: it's dropping the last match on the first string |
| 03:24 | zot | doh. missed that. |
| 03:25 | zot | your karma is still on the up for this weekend ;) |
| 03:25 | zot | but i'm curious about the dropping bit |
| 03:25 | babygau | https://www.refheap.com/90139 |
| 03:27 | tobik | zot: if you change your regexp you can probably do this with re-seq |
| 03:27 | tobik | ,(re-seq #"\d|[^\d]*" "asdf 2 ff 33") |
| 03:27 | clojurebot | ("asdf " "2" " ff " "3" "3" ...) |
| 03:28 | Bronsa | nice tobik |
| 03:28 | zot | tobik: i was playing with that idea already, but my regex is much more complicated, so it was more like: #"(.*)(?:({{[…]}})|(.*))*" |
| 03:28 | zot | but failing, as complicated regexs often do |
| 03:29 | zot | i needed a quick and dirty way to do some light templating, including env var substitution, and file content substitution. perhaps the other approach is to ask what already exists :) |
| 03:30 | zot | and i'm missing a * after the inner [token_letters] |
| 03:31 | zot | actual code i'm trying: (print (re-seq #"(.*)(?:({{@[A-Za-z0-9_]+}})(.*))*" "ao {{FOO_BAR}} do") |
| 03:31 | zot | but doesn't compile |
| 03:36 | tobik | ,(re-seq #"\{\{@[A-Za-z0-9_]+\}\}|[^\{\{@[A-Za-z0-9_]\}\}]+" "ao {{FOO_BAR}} do") |
| 03:36 | clojurebot | ("ao " "FOO_BAR" " do") |
| 03:38 | zot | tobik: thanks :) it hurts my brain. |
| 03:39 | zot | i dno't see how the second half of the expression works though — it's a multi-character match. |
| 03:39 | zot | is there a way to make .* not greedy? |
| 03:40 | tobik | i don't think so |
| 03:40 | zot | then i think i just have to split on "{{|}}" and do a tiny "parser" with the interleave thing as input stream |
| 03:41 | zot | maybe easier in the end |
| 03:41 | tobik | can't you just use a templating library for this? |
| 03:41 | zot | that's what i was asking before — i hadn't found sometihng that does what i need, and originally hoped it would be 15m of (learning experience) code to write. naïve. |
| 03:42 | tobik | you can probably adapt selmer to your needs |
| 03:42 | tobik | https://github.com/yogthos/Selmer |
| 03:46 | babygau | https://www.refheap.com/90139 |
| 03:56 | Bronsa | zot: http://sprunge.us/EEKh?clj if you're curious, this should work as expected for every input string |
| 03:59 | Bronsa | babygau: repeatedly pasting the same link won't help you getting answers if you first don't tell us what's not working |
| 04:00 | babygau | Bronsa, sorry bro, I thought put my question in the link make my question look cleaner :( |
| 04:00 | babygau | Bronsa, I can't compile #clojurescript to normal #javascript |
| 04:01 | babygau | Bronsa, the output (as you can see over the link) looks weird >.< |
| 04:04 | Bronsa | babygau: I have never used cljsbuild, but reading gulpfile.js it looks like you should find the output of your ns in gulpjs/core.js |
| 04:06 | babygau | Bronsa, you're right, I found the compiled core.js but I don't know why it doesn't compile to `gulpfile.js` but `core.js`??? |
| 04:06 | lazybot | babygau: Yes, 100% for sure. |
| 04:09 | Bronsa | babygau: as I said, I don't use cljsbuild so I can't really answer that question. you might want to wait until people in the US start waking up and ask that again |
| 04:09 | babygau | Bronsa, what do you use then :-P |
| 04:09 | Bronsa | I don't use cljs at all |
| 04:10 | babygau | Bronsa, tks bro :) |
| 04:18 | PeakCode | I get a 404 page when I try that link (https://www.refheap.com/90139). Do you have to be signed in? |
| 04:19 | tobik | its gone now |
| 04:19 | PeakCode | OK, I see. |
| 04:21 | babygau | PeakCode, https://www.refheap.com/22172234ac498cee3cc18214d |
| 04:25 | PeakCode | babygau: What is the path to the core.cljs file? |
| 04:29 | PeakCode | babygau: I suspect that :source-paths should be just ["src"] instead of ["src/gulpjs"]. |
| 04:30 | babygau | PeakCode, nope, as I read in #clojurescript up & running, it must be src/gulpjs because my namespace is gulpjs.core |
| 04:35 | PeakCode | babygau: So the path to core.cljs is src/gulpjs/gulpjs/core.cljs then? |
| 04:37 | babygau | PeakCode, it is src/gulpjs/core.cljs |
| 04:38 | PeakCode | babygau: I'm pretty sure you have to either change :source-paths or the path to core.cljs. :source-paths should point to the root of your source tree. |
| 04:39 | babygau | PeakCode, tks bro, pls give me a sec, I will check it out immediately |
| 04:43 | babygau | PeakCode, I changed `:source-paths ["src"]` but the code in `gulpfile.js` is still the same |
| 04:47 | tobik | babygau: try this https://www.refheap.com/f946f21767954ea1b1afe82a6 |
| 04:48 | babygau | tobik, I will try it now |
| 04:50 | babygau | tobik, it WORKED! |
| 04:51 | babygau | tobik, I don't even have to put :target :node, I think the prob is in :optimizations |
| 04:51 | babygau | tobik, PeakCode, I changed :optimizations :simple the the code run |
| 04:52 | djcoin | babygau: tobik pretty cool experiment :) |
| 04:56 | babygau | tobik, PeakCode, tks you guys |
| 04:56 | PeakCode | babygau: OK, great! Perhaps adding :output-dir would have worked with :optimizations :none. You can also try :optimizations :whitespace. |
| 05:05 | babygau | PeakCode, it doesn't work bro :) |
| 05:26 | zot | Bronsa: thanks, this is awesome :) |
| 05:34 | AeroNotix | when I run component/stop on a component system, does it call stop on every component? |
| 06:56 | thesaskwatch | Hi .. I can use (source x) to view source of x ... but what if it's defmulti .. can I list / view defmethods of it in repl? |
| 07:09 | sm0ke | is there a variant of (let [..]) which signifies non ordered declaration? |
| 07:10 | Bronsa | sm0ke: letfn is parallel, but as its name suggests, can only bind functions |
| 07:10 | sm0ke | Bronsa: i am not really concerned if its parallel, more on readability |
| 07:11 | Bronsa | then no |
| 07:11 | sm0ke | like i use (if) for two condition and (when) for one |
| 07:11 | sm0ke | ok |
| 07:12 | Bronsa | sm0ke: maybe you want if-let/when-let? |
| 07:13 | sm0ke | no thats not the point, |
| 07:13 | sm0ke | my point it |
| 07:13 | Bronsa | sm0ke: your last phrase seemed to suggest that :) |
| 07:13 | clgv | AeroNotix: hopefully, isnt that the point of that hierarchical composition? |
| 07:14 | Bronsa | sm0ke: you want (let [a b b 1] a) ;=> 1 right? |
| 07:14 | sm0ke | if i see a (let [a .. b ,..]) i cannot say if a and b are dependent on each other |
| 07:14 | sm0ke | not without looking deeply into what a and b does |
| 07:14 | Bronsa | sorry I have to run |
| 07:14 | sm0ke | no prob |
| 07:14 | clgv | sm0ke: but you know that "a" cannot depend on "b" |
| 07:15 | sm0ke | clgv : (let [a 1 b (inc a)[) |
| 07:15 | clgv | yeah the otherway round is possible ;) |
| 07:15 | sm0ke | -.- |
| 07:15 | clgv | so you want that common lisp let back? |
| 07:16 | sm0ke | no i just want to have a code convetion, lets say there is a (let ) for bindings which depend on each other and (let**) for non dependent bindings |
| 07:16 | clgv | sm0ke: is writing that yourself an option? I could give you a hint how to achieve it |
| 07:17 | sm0ke | yes it is easy |
| 07:17 | sm0ke | but my point was if other people are foloowing something |
| 07:17 | sm0ke | what will i do alone in my own world |
| 07:18 | clgv | well, the question is if other people do rank this as important as you do |
| 07:18 | clgv | I for myself do not |
| 07:19 | sm0ke | yep not critical but would be nice for readability imo |
| 07:19 | clgv | but could also lead to pretty awful nesting of let and let* |
| 07:20 | clgv | ah "let**" you said ^^ |
| 07:33 | SagiCZ1 | hi |
| 07:34 | SagiCZ1 | ,(= (conj [[5 6] [7 8]] [0 1]) (conj '([5 6] [7 8]) [0 1]) |
| 07:34 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 07:34 | SagiCZ1 | ,(= (conj [[5 6] [7 8]] [0 1]) (conj '([5 6] [7 8]) [0 1])) |
| 07:34 | clojurebot | false |
| 07:34 | SagiCZ1 | i need to do the first thing, but with list and not vector |
| 07:35 | SagiCZ1 | append element to the end of list |
| 07:36 | SagiCZ1 | ,(cons 4 '(0 1)) |
| 07:36 | clojurebot | (4 0 1) |
| 07:36 | SagiCZ1 | ,(conj '(0 1) 4) |
| 07:36 | clojurebot | (4 0 1) |
| 07:36 | SagiCZ1 | they both do the same thing |
| 07:36 | SagiCZ1 | how is that useful? |
| 07:37 | clgv | SagiCZ1: thats not possible efficiently. why do you need that for a list exactly? |
| 07:38 | SagiCZ1 | well one of my functions is returning list |
| 07:38 | SagiCZ1 | ,(vector '(4 5 6)) |
| 07:38 | clojurebot | [(4 5 6)] |
| 07:38 | clgv | cant you change it to a vector and keep it a vector? |
| 07:38 | SagiCZ1 | ,(vec '(4 5 6)) |
| 07:38 | clojurebot | [4 5 6] |
| 07:38 | SagiCZ1 | okay then.. |
| 07:39 | clgv | most of the time you want vectors anyway |
| 07:39 | TEttinger | ,(concat '(0 1) '(4)) |
| 07:39 | clojurebot | (0 1 4) |
| 07:39 | clgv | TEttinger: not efficiently though and not type preserving ;) |
| 07:39 | TEttinger | yep |
| 07:39 | TEttinger | ,(class (concat '(0 1) '(4))) |
| 07:39 | clojurebot | clojure.lang.LazySeq |
| 07:39 | clgv | and not arbitrarily stackable ;) |
| 07:41 | SagiCZ1 | and adding to end of vector is O(1) ? |
| 07:41 | clgv | yes |
| 07:42 | SagiCZ1 | is vector also implemented by some tree? |
| 07:42 | clgv | yeah. son in fact its log_{32}(n) |
| 07:58 | SagiCZ1 | is there a print statement that also returns what it printed? something like (defn print-return [x] (println x) x) ? |
| 07:58 | SagiCZ1 | ,(defn print-return [x] (println x) x) |
| 07:58 | clojurebot | #'sandbox/print-return |
| 07:59 | clgv | nope, but probably defined hundreds of times ;) |
| 07:59 | SagiCZ1 | (print-return {:b 4 :a 5}) |
| 07:59 | SagiCZ1 | clgv: okay :) |
| 07:59 | clgv | there is the "spyscope" library that does something similar |
| 08:17 | inad922 | Hi |
| 08:17 | inad922 | How can I go left and write in the interpreter? |
| 08:18 | inad922 | + up/down for walking history? |
| 08:19 | engblom | inad922: Do you mean inside of REPL? Is not the arrow keys working for you? |
| 08:22 | clgv | inad922: do you use leiningen? if not, you should definitely change that |
| 08:24 | clgv | inad922: just with "java -jar clojure.jar" you wont' get those features |
| 08:27 | inad922 | engblom: Yes, well I think inside the repl. I'm new to this. I run "clj" on the cli |
| 08:27 | clgv | inad922: how did you "install" clojure? |
| 08:28 | clgv | inad922: I recommend following the steps under "install" here http://leiningen.org/ and then use "lein repl" |
| 08:28 | inad922 | clgv: pacman -S clojure. So via the package manager |
| 08:28 | clgv | inad922: probably not optimal. |
| 08:29 | clgv | inad922: what's your goal? learning the language with a quickly setup environment? |
| 08:29 | clgv | inad922: if so, give lighttable a try http://www.lighttable.com/ |
| 08:29 | inad922 | clgv: I want to use clojurescript for frontend development |
| 08:30 | clgv | inad922: so are you sold on any editor/IDE yet? |
| 08:30 | inad922 | clgv: Yea, I use sublime. Light table seems to be the same |
| 08:31 | clgv | clgv: no lightable is definitely distinct from sublime ;) |
| 08:31 | inad922 | clgv: I'm a python dev mainly, I just want to learn something more usable for frontend than js. That's just bad |
| 08:32 | clgv | but try it out, it gets you setup pretty quickly. other options are eclipse with counterclockwise, intellij with cursive, vim with vim-fireplace and emacs with cider |
| 08:32 | inad922 | umm |
| 08:32 | clgv | too much choices? ;) |
| 08:32 | inad922 | Why would I need anything better than a plain editor? |
| 08:33 | clgv | because of integration of editor and repl |
| 08:33 | inad922 | I mean does clojure have code quality standards like pep8 for python? Static code checkers, etc.? |
| 08:33 | clgv | e.g. evaluating the content in the editor or the selected function in the repl by pressing a shortcut combination |
| 08:33 | inad922 | I don't need editor integration |
| 08:33 | xemdetia | do you not use python repl for python dev? |
| 08:33 | clgv | integration of editor and repl is a must-have |
| 08:34 | inad922 | xemdetia: Nah |
| 08:34 | inad922 | not really it isn't |
| 08:34 | clgv | in clojure it is |
| 08:35 | inad922 | Why how do imports work in this language? |
| 08:35 | inad922 | and modules |
| 08:35 | inad922 | namespaces, stuff like that |
| 08:36 | inad922 | Is this leiningen like a package manager for clojure? |
| 08:37 | xemdetia | inad922, it's closer to maven if you are familiar with that |
| 08:37 | clgv | inad922: kind of. it fetches the dependencies you declared, from default (or specified) repositories |
| 08:38 | clgv | inad922: it starts a repl for you where all dependencies are present and you can build deployable jar archives with it |
| 08:38 | holo | inad922 yeah leiningen is awesome. do you know the story?: http://www.classicshorts.com/stories/lvta.html really worth reading. The original author is like Leiningen who defeated the ants. sometimes he lurks in this # |
| 08:38 | clgv | inad922: for clojurescript there is "lein cljsbuild" |
| 08:38 | inad922 | xemdetia: Ah maven. This stuff only runs on JVM? |
| 08:39 | clgv | holo: lol what? the background is that he defeated the "ants" :P :D |
| 08:40 | holo | clgv, sure! |
| 08:40 | clgv | inad922: your dev environment will run on JVM. you'll compile javascript files from clojurescript via leiningen |
| 08:40 | clgv | holo: damn, that one took long to notice (~3 years) ;) |
| 08:41 | holo | clgv haha :D |
| 08:41 | clgv | so leiningen defeats ants but is afraid of mavens? |
| 08:42 | holo | well, every brave man has a fear to conquer! |
| 08:42 | xemdetia | inad922, the main thing to note with a functional language is that not using a repl for interactive development makes it very difficult to determine that given what input, what does this function provide as output |
| 08:43 | TimMc | holo: Every brave woman as well. |
| 08:43 | xemdetia | this is also important because the idea is 'many little functions chained together' and not 'one big code block' |
| 08:43 | TimMc | *person |
| 08:43 | holo | TimMc, sure, brave women are awesome! |
| 08:45 | TimMc | Wasn't quite what I was driving at, but I guess I'll take it. |
| 08:46 | inad922 | xemdetia: I don't say you should not use a repl. I obviously do with python. I'm saying that editor integration doesn't do too much good for me. |
| 08:49 | clgv | inad922: just try one of those options and experience the benefits ;) |
| 08:52 | clgv | inad922: just using "cli" from your package manager will be a pretty poor setup as you have already noticed |
| 08:53 | inad922 | clgv: Yea, I just downloaded the leiningen script |
| 08:53 | inad922 | Running lein repl |
| 08:53 | inad922 | It does what I wanted |
| 08:54 | clgv | :) |
| 08:54 | clgv | one step forward. but I'd go the next steps as well |
| 08:54 | inad922 | Also I'm a bit frightened about the fact that this stuff runs on the JVM |
| 08:54 | inad922 | Java is horrific... |
| 08:54 | xemdetia | only if you are clumsy |
| 08:54 | hyPiRion | inad922: java != JVM |
| 08:54 | clgv | as hyPiRion said! |
| 08:54 | inad922 | xemdetia: I don't want to start a flame war. I don't like that language, that's it. |
| 08:55 | tbaldridge | inad922: who does? Good thing Clojure means you don't have to write in Java. |
| 08:55 | inad922 | JVM is the bytecoder interpreter that runs the compiled Java code isn't it? |
| 08:55 | holo | inad922, just be afraid of the bootstrap times. if you follow the Stuart Sierra workflow though, you may save so much time |
| 08:55 | clgv | inad922: so you would not use a properly working program only because it is written in java? that's a strange world view |
| 08:55 | hyPiRion | inad922: the compiled JVM code*, but yes, that's right |
| 08:56 | inad922 | clgv: If there is an alternative :) |
| 08:57 | holo | inad922 hy is fine. there is also rhine, on the llvm |
| 08:57 | clgv | ouch! |
| 08:58 | tbaldridge | holo: sadly hy is "mutation everywhere!", that's the reason I never really used it. |
| 08:58 | hyPiRion | holo: rhine is not working yet |
| 08:58 | TimMc | inad922: The JVM is a pretty different beast from Java. |
| 08:58 | TimMc | Sun did a reasonably good job making them separate. |
| 08:59 | holo | tbaldridge, I'm integrating hy with fn.py now for that reason. maybe it will be awesome |
| 08:59 | inad922 | TimMc: Yes, probably you're right. I don't know much about this topic. |
| 08:59 | TimMc | xemdetia: Most people are clumsy most of the time, so that's no excuse for a poorly designed language. :-) |
| 09:00 | TimMc | inad922: For instance, the JVM doesn't know what inner classes or checked exceptions are. |
| 09:00 | xemdetia | TimMc, fair enough. |
| 09:00 | tbaldridge | inad922: the Clojure/JVM thing is an interesting beast. On one hand I'm not crazy about the JVM. On the other hand I've integrated fairly large libraries in Clojure. |
| 09:01 | tbaldridge | Being able to say " you can use this mountain of existing code from clojure " is huge in the "real" world. |
| 09:02 | inad922 | tbaldridge: Yes, I have to agree with that. |
| 09:03 | holo | yeah, I integrated two of my own. it's a huge win |
| 09:03 | hyPiRion | inad922: I'll just say you should try out Clojure, and if you like it, stay with it. Just be aware that, although it runs on the JVM and has Java interop, it's not related to Java the language. |
| 09:05 | hyPiRion | And if you don't like it, then that's perfectly fine too :) |
| 09:06 | clgv | he actually wants to use CLJS ;) |
| 09:06 | inad922 | hyPiRion: Yeah well. I give it a try. I really like how well clojurescript integrates with already written js libraries. Also it seems like a well designed language unlike js. I just want to find an alternative |
| 09:06 | hyPiRion | clgv: oh well, cljs then! |
| 09:07 | tbaldridge | inad922: personally I enjoy working with CLJS more than CLJ. You fire up cljsbuild and set it to auto re-compile. Then as you edit files they recompile in about 0.5 sec. Refresh the browser and you're on your way |
| 09:07 | clgv | btw. are the days of the "hashcode versions" of cljs counted? |
| 09:07 | tbaldridge | clgv: I highly doubt it |
| 09:08 | clgv | tbaldridge: is there a definied/described state for it to reach 1.0? |
| 09:09 | tbaldridge | clgv: so I'll give you the reasoning I got from Rich once when I asked when core.async would hit beta... |
| 09:09 | inad922 | tbaldridge: Nice. That's good for testing. Do you use clojure on the backend too? |
| 09:10 | tbaldridge | "Why are people so concerned about alpha,beta, etc.? Are they thinking that it somehow won't change after it hits beta? We try not to change public APIs, so why does beta matter? It's not magically stable or perfect because someone sticks 1.0 on it" |
| 09:11 | tbaldridge | clgv: so I think the idea on that stuff is, if it works for you, use it. CLJS only gets more stable, version numbers are meaningless. :-) |
| 09:11 | clgv | tbaldridge: well it expresses the confidence of the maintainer. so we are lucky clojure has releases at all? :P |
| 09:13 | xemdetia | gmail set the groundwork for the mostly permanent beta future |
| 09:13 | tbaldridge | clgv: but that would suggest that the confidence of the maintainer is something that has an absolute value. |
| 09:14 | clgv | tbaldridge: well it is at least indirect communication between maintainer and user |
| 09:15 | tbaldridge | clgv: examples...Games from Blizzard are playable in alpha and beta. While games from EA often crap on the day after release. Gmail got out of beta after 10 years? |
| 09:15 | clgv | tbaldridge: I mean there is a version scheme and from the usual context it implies that there should be a 0.1 or 1.0 at some point ;) |
| 09:16 | clgv | tbaldridge: ok on that argument, why not just counting up from 1 for release numbers but instead employ a version scheme that implies some magical future versions that won't happen? |
| 09:16 | tbaldridge | clgv: I get what you're saying, and I'm just arguing to make a point. But I do agree with those who state version numbers are rather worthless things, and it bugs me when managers say things like "Eh...don't use Kafka, it's only at v0.8" |
| 09:17 | clgv | tbaldridge: hehe, managers are why you need internal and external versions :P |
| 09:17 | clgv | use "the new ClojureScript 2014/04" :P |
| 09:18 | dnolen_ | clgv: that is in fact what Google Closure Compiler / Library does |
| 09:18 | clgv | dnolen_: the counting-up version scheme? |
| 09:19 | dnolen_ | clgv: no version is just the date |
| 09:19 | truebuddi | newbie here so wanted to check if this can be written using thread-first -> macro??? (remove-person "Krishna" (add-person "Krishna" default-trip)) ... where add-person and remove-person both take a string and a map |
| 09:19 | dnolen_ | com.google.javascript:closure-compiler v20140814, http://search.maven.org/#artifactdetails%7Ccom.google.javascript%7Cclosure-compiler%7Cv20140814%7Cjar |
| 09:21 | SagiCZ1 | how do i load a file in clojure using relative path? |
| 09:24 | SagiCZ1 | nvm got ti |
| 09:24 | SagiCZ1 | *t |
| 09:24 | SagiCZ1 | *it |
| 09:24 | clgv | truebuddi: you probably need ->> since the map is last position |
| 09:28 | SagiCZ1 | how can i find an element by tag after using xml/parse? |
| 09:28 | AeroNotix | with midje teardown/setup is there a way to make something run before all the facts and after all the facts? |
| 09:28 | truebuddi | clgv: I was playing around with -> .. (-> data fn1 fn2) ... right? so i was trying to use (partial ...) and i get results I dont understand .. |
| 09:28 | truebuddi | ((-> (add-person "Krishna" default-trip) (partial remove-person "Krishna"))) => "Krishna" |
| 09:29 | truebuddi | ((->> (add-person "Krishna" default-trip) (partial remove-person "Krishna"))) ==> gives me a map that I originally wanted |
| 09:29 | truebuddi | (->> (add-person "Krishna" default-trip) (partial remove-person "Krishna")) gives me back a partial :( |
| 09:30 | ToxicFrog | ...yes, it does |
| 09:30 | ToxicFrog | Because that gets rearranged into (partial remove-person "Krishna" (add-person "Krishna" default-trip)) |
| 09:30 | ToxicFrog | Did you mean (->> default-trip (add-person "Krishna") (remove-person "Krishna")) ? |
| 09:31 | ToxicFrog | truebuddi: ^ |
| 09:32 | truebuddi | ToxicFrog: (->> default-trip (add-person "Krishna") (remove-person "Krishna")) this is what I wanted ... now I have to analyze it |
| 09:33 | truebuddi | ToxicFrog: (add-person "Krishna") as is throws arity mismatch exceptions .. but it can be used in ->> without using partial ... thats interesting |
| 09:33 | clgv | truebuddi: usually for usage in threading macros, map and plain values that might be threaded should be the first argument and sequences/sequential ds should be the last argument |
| 09:33 | ToxicFrog | truebuddi: -> and ->> are macros, they rearrange the code before it gets evaluated. |
| 09:33 | milos_cohagen | truebuddi: use macroexpand to help your understanding |
| 09:33 | milos_cohagen | ,(macroexpand-1 '(->> default-trip (add-person "Krishna") (remove-person "Krishna"))) |
| 09:33 | clojurebot | (remove-person "Krishna" (add-person "Krishna" default-trip)) |
| 09:33 | ToxicFrog | Yes, that |
| 09:35 | truebuddi | clgv: i had add-person [person trip] where trip is a map .. and you recommend trip to be first and person to be the later argument? |
| 09:36 | ToxicFrog | truebuddi: that would be more consistent with the clojure stdlib, yes |
| 09:36 | clgv | truebuddi: if it shall be used in threading often, then yes |
| 09:36 | ToxicFrog | e.g. assoc/dissoc take arguments [map key] rather than [key map] |
| 09:36 | truebuddi | ToxicFrog: in that case how would ->> work out? |
| 09:37 | clgv | truebuddi: ->> is the reserved for sequential datastructures and clojure's sequence functions, e.g. map, filter ... |
| 09:37 | clgv | "reserved" ;) |
| 09:39 | truebuddi | clgv: once i swapped the order of params like you suggested, i can use the -> as in (-> default-trip (add-person "person1") (remove-person "person1")) |
| 09:41 | truebuddi | to understand how -> rearranged .. i am using macroexpand but it gives me what looks like =====> (remove-person (clojure.core/-> default-trip (add-person "person1")) "person1") |
| 09:42 | truebuddi | is there anyway i can see that it actually did a (remove-person (add-person default-trip "person1") "person1") |
| 09:42 | ToxicFrog | -> has more expansion stages, IIRC. |
| 09:43 | ToxicFrog | ,(macroexpand-all '(-> default-trip (add-person "person1") (remove-person "person1"))) |
| 09:43 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: macroexpand-all in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 09:43 | ToxicFrog | Huh. |
| 09:43 | ToxicFrog | ,(macroexpand '(-> default-trip (add-person "person1") (remove-person "person1"))) |
| 09:43 | clojurebot | (remove-person (add-person default-trip "person1") "person1") |
| 09:43 | ToxicFrog | truebuddi: ^ |
| 09:44 | truebuddi | ToxicFrog: I get ... but the inner -> isnt expanded ... (remove-person (clojure.core/-> default-trip (add-person "person1")) "person1") |
| 09:45 | ToxicFrog | truebuddi: using macroexpand-1 or macroexpand |
| 09:45 | ToxicFrog | ,(macroexpand-1 '(-> default-trip (add-person "person1") (remove-person "person1"))) |
| 09:45 | clojurebot | (remove-person (add-person default-trip "person1") "person1") |
| 09:45 | ToxicFrog | Huh. |
| 09:46 | ToxicFrog | Also, what version of clojure are you using, the internals of -> may be different between your version and the bot's version |
| 09:47 | truebuddi | pretty old i guess [org.clojure/clojure "1.5.1"] ... just did a lein new and playing with cursive .. did not look at which version . thought lein new will take care of using the latest |
| 09:47 | clgv | truebuddi: if you see the recursive expansion you have an older clojure than 1.6 |
| 09:49 | truebuddi | Fixing my project.clj to use latest version but is there a clojure function that returns the version? .. something like (version ) ?? |
| 09:49 | lazybot | truebuddi: Uh, no. Why would you even ask? |
| 09:49 | truebuddi | lazybot: sorry? |
| 09:50 | zerokarmaleft | ,*clojure-version* |
| 09:50 | clojurebot | {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"} |
| 09:50 | augustl | truebuddi: lazybot is a bot :) |
| 09:51 | truebuddi | augustl : new here .. so easily fooled :( |
| 09:53 | truebuddi | gotta go .. thank you all..learned a few things today ... will be back again in the evening with more questions.. thanks again |
| 09:57 | clgv | ,(clojure-version) |
| 09:57 | clojurebot | "1.7.0-master-SNAPSHOT" |
| 10:01 | inad922 | This lighttable is pretty cool |
| 10:01 | inad922 | I like it |
| 10:01 | TimMc | I should give it another shot some time. |
| 10:03 | SagiCZ1 | can i simplify this or make it nicer? |
| 10:03 | SagiCZ1 | ,(drop-last 1 (drop 1 (range 10))) |
| 10:03 | clojurebot | (1 2 3 4 5 ...) |
| 10:04 | verma | ,(doc range) |
| 10:04 | clojurebot | "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity. When step is equal to 0, returns an infinite sequence of start. When start is equal to end, returns empty list." |
| 10:04 | TimMc | ,(range 1 (dec 10) |
| 10:04 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 10:04 | verma | ,(range 1 10) |
| 10:04 | clojurebot | (1 2 3 4 5 ...) |
| 10:04 | TimMc | ,(range 1 (dec 10)) |
| 10:04 | clojurebot | (1 2 3 4 5 ...) |
| 10:04 | TimMc | SagiCZ1: But you probably mean a seq that is not a range. :-) |
| 10:04 | SagiCZ1 | sorry that i didnt specify it but its should work for any coll.. i want to drop first and last |
| 10:05 | SagiCZ1 | can i use -> somehow? |
| 10:05 | TimMc | That only rearranges your syntax. |
| 10:05 | TimMc | Is that all you want? |
| 10:06 | verma | ,(doc butlast) |
| 10:06 | clojurebot | "([coll]); Return a seq of all but the last item in coll, in linear time" |
| 10:06 | verma | ,((comp rest butlast) (range 10)) |
| 10:06 | clojurebot | (1 2 3 4 5 ...) |
| 10:06 | SagiCZ1 | verma: thanks, that looks pretty good |
| 10:07 | SagiCZ1 | any reason to prefer rest to next? |
| 10:07 | verma | (-> (range 10) butlast rest) |
| 10:07 | verma | ,(-> (range 10) butlast rest) |
| 10:07 | clojurebot | (1 2 3 4 5 ...) |
| 10:07 | verma | SagiCZ1, rest is lazy, but I guess wouldn't matter since we want the last element out as well |
| 10:07 | SagiCZ1 | ,(-> (range 10) drop 1 drop-last 1) |
| 10:07 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 10:08 | SagiCZ1 | threading -> doesnt work with more than 1 param? |
| 10:08 | TimMc | SagiCZ1: -> doesn't magically know which things are arguments to fns |
| 10:08 | verma | SagiCZ1, you gotta parent them |
| 10:08 | verma | SagiCZ1, you gotta paren them |
| 10:09 | SagiCZ1 | ,(-> (range 10) (drop 1) (drop-last 1)) |
| 10:09 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> |
| 10:09 | verma | ,(doc drop) |
| 10:09 | clojurebot | "([n] [n coll]); Returns a lazy sequence of all but the first n items in coll. Returns a stateful transducer when no collection is provided." |
| 10:09 | verma | SagiCZ1, use ->> |
| 10:09 | SagiCZ1 | ,(->> (range 10) (drop 1) (drop-last 1)) |
| 10:09 | clojurebot | (1 2 3 4 5 ...) |
| 10:10 | SagiCZ1 | so -> and ->> difference is only if it appends the param as last or first right? |
| 10:10 | verma | SagiCZ1, yeah |
| 10:10 | SagiCZ1 | cool stuff |
| 10:10 | verma | :) |
| 10:11 | TimMc | SagiCZ1: Well... last, or second. |
| 10:11 | SagiCZ1 | so it generally works for functions with params like [n coll] or [coll n] .. |
| 10:14 | verma | SagiCZ1, not necessarily, you can do much more with -> and ->> |
| 10:15 | verma | SagiCZ1, there's no need to use them with just seq's, they are meant to insert things into expressions, so you can use them pretty much any way you like |
| 10:15 | TimMc | SagiCZ1: You can really abuse them. |
| 10:16 | verma | (-> (go (get-me-food)) <! (print)) |
| 10:16 | TimMc | &(-> [a 1] (let a)) |
| 10:16 | lazybot | ⇒ 1 |
| 10:16 | verma | nice TimMc :) |
| 10:17 | TimMc | Even this is an abuse: ##(-> + var meta :since) |
| 10:17 | lazybot | ⇒ nil |
| 10:17 | TimMc | &(-> + var meta :added) |
| 10:17 | lazybot | ⇒ "1.2" |
| 10:18 | verma | :) |
| 10:21 | TimMc | (var is not even a macro, it's a special form) |
| 10:22 | szymanowski | hello, i've implemented a custom vector-like data structure and I would like the "count" function works on it, how can i do this? |
| 10:22 | tbaldridge | szymanowski: have it implement clojure.lang.ICounted |
| 10:23 | szymanowski | thank you tbaldridge |
| 10:23 | tbaldridge | szymanowski: actually it's just Counted: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Counted.java |
| 10:23 | szymanowski | ok thank you |
| 10:28 | CookedGryphon | Hey, I'm writing a test.check generator and have a vector of events. What I want to do now is batch those events to simulate the way they arrive in my real app, anyone know how i'd do that? |
| 10:28 | CookedGryphon | (so I have the full stream of events that i'd like to arrive, now I want to randomly slice up that vector so they arrive in batches |
| 10:32 | TimMc | CookedGryphon: I would get test.check to also a generate for you a vector of chunk sizes, and then have the inner portion of your test chunk the vector "deterministically" based on that chunk size list. |
| 10:33 | TimMc | so ask for a pair of data, chunking instructions. |
| 10:34 | legittalon | What do Clojure wielding developers call themselves? |
| 10:34 | CookedGryphon | that makes sense |
| 10:41 | Fender | hi there, is there some best practice how to program async stuff? |
| 10:41 | Fender | for example debug go-loops - once created they kind of run forever unless I implement a channel specific stop command |
| 10:41 | Fender | but this is also cumbersome |
| 10:42 | smizell | Hello all, I came in here a few days ago talking about an idea where you could use JSON as code (Lisp flavored). I threw a very minimal example together for fun and thought I'd just link it here. Feel free to throw your head back in laughter. https://github.com/smizell/geneva |
| 10:42 | Fender | also, sometimes my channel msgs are printlned and they overwhelm my emacs when there are many of them |
| 10:44 | stw | SegFaultAX: thanks for the help yesterday, I was able to isolate the process in it's own thread and then interrupt it after a timeout |
| 10:46 | CookedGryphon | TimMc: I'm generating my chunks such-that the sum of the vector of ints adds up to the length of the vector, but in most cases this means I generate a much longer vector than I need... Any ideas as to how I can generate a chunking vector that works with the number of elements I actually have? |
| 10:48 | stompyj | legittalon: clojurians |
| 10:48 | stompyj | note: I made that up |
| 10:49 | stompyj | iclojoclasts |
| 10:49 | ToxicFrog | Goddamnit, core.typed |
| 10:50 | legittalon | I’m tryna decide if I want to go all in on Haskell or Clojure, first. |
| 10:51 | clgv | and that depends on the nicknames? |
| 10:51 | legittalon | Yes. |
| 10:51 | legittalon | No. |
| 10:51 | cbp | clojodites |
| 10:51 | clgv | ah well, throw a coin ;) |
| 10:52 | ddellacosta | legittalon: Haskell is incredible, seriously mindbending, and insanely deep. Clojure is awesome and has a great community. |
| 10:53 | TimMc | CookedGryphon: If you've said more than your 2 messages as 10:34 and 10:45 ET, I missed them due to a probably router reboot. |
| 10:54 | legittalon | My native tongue is Javascript. Right now I’m interested in Clojurescript which seems pretty cool. But the parens are annoying but not insurmountably so. I’m also interested in Elm which is heavly influenced by Haskell. |
| 10:55 | legittalon | I think the resources for Clojure are way better. I want a Haskell Koans. |
| 10:55 | ddellacosta | legittalon: fear of parens is absolutely the worst reason to not choose a lisp. |
| 10:55 | legittalon | It wouldn’t be the main reason. |
| 10:56 | legittalon | Or really a reason. |
| 10:56 | TimMc | CookedGryphon: Can you give an example of the kind of test data you would like to send, and what the invariants are? |
| 10:56 | cbp | you get more twitter cred if you choose haskell |
| 10:56 | ddellacosta | legittalon: gotcha. Wasn't sure from your statement above, just wanted to make that clear... |
| 10:56 | ToxicFrog | I should try out clojurescript one of these days, now that I have an actual use for Javascript (specifically, making Android apps) |
| 10:56 | legittalon | Honestly I really WANT to learn Haskell first but I can’t find very good beginner resources. |
| 10:57 | dnolen_ | legittalon: the classic books are good starting points, Simon Thompson or the Paul Hudak one |
| 10:58 | ddellacosta | legittalon: some Haskell folks are jerks but there are also a lot of friendly Haskell folks in #haskell. #nothaskell is also work a look. |
| 10:58 | dnolen_ | I think both have relatively recent editions |
| 10:58 | ddellacosta | legittalon: which is to say, I bet they could give you some good tips too. |
| 10:58 | hyPiRion | legittalon: https://github.com/bitemyapp/learnhaskell/ and LYAH |
| 10:58 | cbp | there's that fp complete site and a bunch of online haskell courses |
| 10:58 | legittalon | Lol at the Clojure community being more helpful at learning Haskell than the Haskell community. |
| 10:59 | zerokarmaleft | legittalon: there's also an entire youtube series of lectures taught by wadler |
| 10:59 | legittalon | Awesome! Thanks for your resources. |
| 11:00 | hyPiRion | You've also got Real World Haskell, which I've heard is less theoretical than the other books. Not sure if that helps or not, but at least both are available online for free |
| 11:01 | ddellacosta | hyPiRion: I've heard that RWH is a bit dated, but that's hearsay from some folks in #haskell |
| 11:01 | CookedGryphon | TimMc: The current test is generating multi-touch input, each pointer starts with a :down, might have some number of :move events and ends with an :up or :cancel event. Each event coming through has a unique :touch-id and a persistent vector of all the touch coordinates since that pointer went :down |
| 11:02 | hyPiRion | ddellacosta: Hmm, maybe? I pick a bit here and there based on what I need to learn, but what I've seen so far in RWH is okay |
| 11:02 | CookedGryphon | TimMc: I am then checking that once all the events have run through, my system state is coherent (i.e. no buttons are stuck down or anything) |
| 11:03 | ddellacosta | hyPiRion: yeah, I just remember hearing someone mention the way it approaches exceptions, perhaps? Anyways, not to invalidate your point, probably still a great resource for beginners |
| 11:03 | CookedGryphon | and the chunking comes because in my actual implementation, for efficiency, I might skip any number of the events apart from the :up or :cancel |
| 11:04 | hyPiRion | ddellacosta: No worries, that may be the case. I'm not a good Haskell programmer, so it may very well be true |
| 11:04 | CookedGryphon | TimMc: ooh, I have just thought of a much more efficient way I could do this. I generate it as if there's an event coming through for every last coordinate, and then I randomly sample from that vector, as long as I can guarantee that I get the last point |
| 11:05 | ddellacosta | hyPiRion: I'm barely a Haskell programmer, so there is even less point for me to be talking about it...haha |
| 11:06 | TimMc | CookedGryphon: Careful with that "randomly sample" part. |
| 11:07 | CookedGryphon | TimMc: yeah, that's the bit I need help with, I know I need to make a reproducible generator |
| 11:07 | TimMc | Any randomness should be coming through test.check so that it can report the exact conditions of a failure and shrink the failures. |
| 11:07 | TimMc | Or does test.check have a sampler? |
| 11:08 | hyPiRion | ddellacosta: heh. Sometimes I get an error with the message "Maybe you wanted to add the language extension X?", I add X and it works. And I how no idea why. |
| 11:10 | zerokarmaleft | ddellacosta: RWH is a bit dated, but the pedagogical approach is very good in places |
| 11:10 | CookedGryphon | TimMc: don't think so, but then I can always do what I was going to do before with the chunker vector |
| 11:10 | CookedGryphon | It would be nice if there was a cleaner way of doing it though |
| 11:11 | zerokarmaleft | hyPiRion: I've come to enjoy GHC's prescriptive error messages |
| 11:12 | ddellacosta | hyPiRion: I may possibly have had that experience using ghc... |
| 11:12 | ddellacosta | zerokarmaleft: gotcha, good to know |
| 11:12 | ddellacosta | zerokarmaleft: I do have to say, ghc's error messages kick the butt of Clojure's |
| 11:13 | ddellacosta | but that's not really a fair competition |
| 11:13 | TimMc | CookedGryphon: Just ask for a sufficiently long list of random numbers that you can then massage into skips, repeats, chunkings, whatever. |
| 11:14 | hyPiRion | zerokarmaleft: it's good error messages, I just don't understand what RankNTypes are, for instance |
| 11:15 | hyPiRion | Or well, I kinda get it now, but eh |
| 11:26 | ToxicFrog | The type of something that returns [{} [] "a"] is (HVec Map Vec String), right? |
| 11:28 | seabre | ddellacosta: ghc is almost 22 years old, after all. |
| 11:28 | ddellacosta | seabre: what is that in regard to? that's amazing though, I didn't realize it was *that* old |
| 11:29 | seabre | ddellacosta: Well, you'd hope that in 22 years they'd figure out how to do error messages right. |
| 11:29 | seabre | and clojure is pretty young |
| 11:29 | ddellacosta | seabre: ah, yeah |
| 11:29 | seabre | Like 7 I think? |
| 11:29 | ddellacosta | seabre: but I think Clojure still has a bit of an unfair advantage there, considering we're dealing with the JVM here |
| 11:30 | ddellacosta | in terms of exceptions. A sore spot for Clojure. ClojureScript error messages can be frustrating too. I mean, you certainly get used to them, but they are a weak point. |
| 11:31 | boodle | Hi, new to core.async, have ~100 values in a channel, can do all kinds of side-effect-ty things with them but want to return them as a seq/coll.. or sum them (transducers) but using 1.6.. any way to do this? |
| 11:31 | ddellacosta | er, I guess I meant Clojure has an unfair *disadvantage* |
| 11:32 | ToxicFrog | ddellacosta: while this is true to some extent, it does not excuse e.g. the compiler reporting syntax errors by crashing |
| 11:33 | ddellacosta | ToxicFrog: are you talking about ghc or clojure here? |
| 11:33 | tbaldridge | boodle: look at clojure.core.async/into |
| 11:34 | ToxicFrog | ddellacosta: clojure |
| 11:36 | boodle | tbaldridge: I did try that.. called close! on the chan before calling it but still getting an empty vector.. it doesn't need to be a go block or anything? |
| 11:37 | tbaldridge | boodle: I'd need to see some code |
| 11:37 | tbaldridge | boodle: can you post a gist? |
| 11:38 | boodle | oh wait, it returns a chan, correct? |
| 11:38 | tbaldridge | boodle: yes |
| 11:38 | boodle | ah.. trying |
| 11:51 | boodle | tbaldridge: here's what I'm getting: https://www.refheap.com/90157 versus https://www.refheap.com/90159 |
| 11:52 | tbaldridge | boodle, can I see the code thats writing to the channel? |
| 11:52 | tbaldridge | boodle: I'm pretty sure you have a race condition somewhere |
| 11:55 | boodle | tbaldridge: probably due to this then: https://www.refheap.com/90160 |
| 11:56 | tbaldridge | boodle: yeah, if you're getting an empty vector that probably means that whatever is closing the channel is closing it before the put! code completes |
| 11:57 | boodle | ah, any way to force put! to complete before taking? <!! ? |
| 12:00 | tbaldridge | not really (I haven't seen enough of your code to know for sure) but this code is async....so things will be async ;-) |
| 12:00 | tbaldridge | boodle: the key is to not close the channel until all put!s are done |
| 12:01 | boodle | tbaldridge: sure but a bit stuck on the 'how'.. this is all being generated wihtin a page render (selmer template 'filters' acting as callbacks) |
| 12:02 | boodle | tbaldridge: well thank you for your time and help! Will look at redo-ing the selmer/filter stuff another way |
| 12:25 | lavokad | hi, what a is more "valuable, better" to learn for a studen of computer science in university. "Computer engineering" or "Software Engineering"? |
| 12:26 | daniel___ | lavokad: what r u on about? |
| 12:26 | xemdetia | depends on your uni, but most unis 'computer engineering' is closer to EE stuff while software engineering is usually closer to CS |
| 12:27 | xemdetia | value depends on what you are trying to do |
| 12:29 | lavokad | here in Spain "Computer Engineering" module has Desing of operating systems, design of digital systems, technologies of networks, advanced architectures, embbeded systems, security, languages of parrelel computing, configuration of networks, distributed systems application develpment, real time |
| 12:29 | lavokad | it is far from EE |
| 12:29 | lavokad | that is why I cant decide... |
| 12:30 | jcsims | lavokad: which program sounds more interesting? |
| 12:31 | xemdetia | it also depends on your background too- uni is a great place to shore up where you are weak |
| 12:31 | xemdetia | when I went back to uni I focused more on math because I had a good foundation in systems programming |
| 12:32 | clgv | lavokad: software engineering usually has a lot of courses on how software projects should be organized |
| 12:32 | lavokad | well I think that sofware engineering is what I will need to know, when I start working, but the classes of "Software Engineering" are all about models, quality sofware, software design ...it is all about sofware organization |
| 12:33 | lavokad | so maybe one can learn this reading a few books? |
| 12:33 | xemdetia | organizing the infrastructure to make good software is just as hard as writing code |
| 12:33 | lavokad | In this case i would choose "computer engineering" couse it will teach a lot of concepts about programming and computer in general |
| 12:34 | lavokad | xemdetia: |
| 12:34 | lavokad | ok :) |
| 12:34 | lavokad | this is what I needed to hear |
| 12:34 | lavokad | :D |
| 12:34 | xemdetia | lavokad, it's never wrong to actually go to the uni and ask |
| 12:34 | clgv | xemdetia: and even worse to measure ;) |
| 12:34 | xemdetia | something I did was look online at the syllabus for some of these classes and see what books they were using and what are the current 'popular books' on the outside |
| 12:35 | lavokad | I watched presentation videos, read their stuff, but it didnt make me decide |
| 12:35 | clgv | lavokad: yeah they usually have students counselors you can talk to |
| 12:36 | xemdetia | that's something that really helped me- some of the classes I took solely because it was a book I had not even heard of and it was very interesting (compiler theory, some computer crime law, etc) |
| 12:36 | xemdetia | it's not always obvious what the course covers by the syllabus at the higher levels |
| 13:17 | owengalenjones | can anyone see what is wrong with this ring/friend/compojure setup? basically any routes in public return an empty response /home works and /authorized seems to work but only redirects to /login which is empty https://www.refheap.com/90164 |
| 13:17 | owengalenjones | if I remove the call to authorize / authenticate then those routes work as well, something with how I'm using friend? |
| 13:27 | xeqi | owengalenjones: friend requires one of the params middleware, so it needs to be inside the site or api middleware |
| 13:27 | xeqi | and I don't see a credential-fn, but maybe this is from a stripped down example |
| 13:38 | jeffterrell | Woohoo, Cognitect's webinar on Transit is starting in 20 minutes! http://go.cognitect.com/transitwebinar |
| 13:39 | mdrogalis | Webinar is one of my least favorite words. D: |
| 13:39 | mdrogalis | Right up there with 'synergy'. |
| 13:41 | tbaldridge | mdrogalis: you need to embrace cross platform webinars in order to synergize your backward overflows |
| 13:41 | kenrestivo | refactor your webinar with synergy. it's agile |
| 13:41 | tbaldridge | mdrogalis: better yet: http://www.atrixnet.com/bs-generator.html |
| 13:41 | mdrogalis | tbaldridge: Gonna reach right through my monitor and slap you for that sentence. |
| 13:41 | kenrestivo | tbaldridge: beat me to it |
| 13:42 | mdrogalis | Oh this is lovely. |
| 13:42 | mdrogalis | "efficiently reconceptualize resource maximizing networks" |
| 13:42 | dorkmafia | there are more people in #clojure than in ##java |
| 13:43 | tbaldridge | dorkmafia: might say more about the types of people that use IRC than anything else ;-) |
| 13:43 | dogonthehorizon | dorkmafia: I think that recently speaks to the go-getter, upward trending nature of the Clojure language |
| 13:43 | dogonthehorizon | recently -> really |
| 13:43 | dorkmafia | heh |
| 13:43 | dorkmafia | do irc rooms have a limit to the number of people? |
| 13:43 | tbaldridge | case-in-point, whenever I mention IRC to someone not in the fringes of programming the reaction I get is "IRC is still a thing?" |
| 13:44 | xemdetia | there are other groups that still use irc heavily aside from programmers |
| 13:44 | jeffterrell | I was pretty impressed at the last Cognitect webinar, on core.async. |
| 13:44 | dorkmafia | freenode is the place to be |
| 13:45 | jeffterrell | It's not a sales presentation, but a technical one, for Clojure folks like us. |
| 13:45 | technomancy | java channels are sad places where questions come to die |
| 13:45 | dogonthehorizon | It could also be that #clojure is an official channel while ##java is technically not? I don't know, I'm newer to the irc culture than most :P |
| 13:45 | kenrestivo | stackoverflow seems to have stolen a lot of the "how the hell do i...?" juice |
| 13:46 | xemdetia | irc just attracts a certain type of person |
| 13:46 | kenrestivo | quite honestly i feel a lot less stupid asking stackoverflow than asking on irc. |
| 13:46 | technomancy | kenrestivo: but then your question is memorialized for all time |
| 13:47 | kenrestivo | indeed, but so is the answer, and everyone else's too |
| 13:47 | kenrestivo | and by "ask" i mean "google' |
| 13:47 | technomancy | oh, I thought you meant like if you were worried it was a stupid question |
| 13:47 | mdrogalis | tbaldridge: How do I use core.async channels with webinars? Is there an API for that? |
| 13:47 | kenrestivo | there's just such a volume of answers for common things, in languages like java and html, css, javascript, android, etc, on stackoverflow. |
| 13:48 | mdrogalis | tbaldridge: I think someone needs a cup of coffee. |
| 13:49 | kenrestivo | but what irc does well is interspersing entertaining banter amongst the technical q&a's |
| 13:50 | xemdetia | irc also gets visibility to weird corner cases |
| 13:50 | xemdetia | which can be very interesting |
| 13:51 | technomancy | it's good for learning by osmosis |
| 13:51 | technomancy | I feel almost qualified to answer certain clojurescript questions despite having never used it |
| 13:51 | onielfa | Hello, I need a book recommendation. I'd like to learn Clojure and I have 0 experience with lisp-like languages, but I have an intermediate experience with functional programming, Haskell in particular. I have access in a local book store to Clojure Programming, Programming Clojure and The joy of clojure 2edition. Which book you think will be better suit for me? Thanks in advance |
| 13:52 | xemdetia | onielfa, what's your favorite kind of pet project |
| 13:52 | oubiwann | onielfa: if you learn by looking at code, the Clojure Cookbook is a fantastic resource |
| 13:52 | aka | yeah the clojure cookbook is great |
| 13:52 | sorbo_ | onielfa: I’ve read and liked The Joy of Clojure |
| 13:53 | oubiwann | onielfa: otherwise, all of the books you've mentioned are great (I own them all) |
| 13:53 | dogonthehorizon | onielfa: Currently working through the three you mentioned, Joy of Clojure 2ed has been my favorite so far. The pace is much quicker than the other two IMO. |
| 13:53 | sorbo_ | what do y’all use for debugging Clojure? I mostly use tools.trace and the REPL, but not sure if there are better tools available |
| 13:53 | sorbo_ | some have recommended hooking into the Java Debug Interface |
| 13:54 | sorbo_ | but I sort of like to keep Java interop to a “use it when I need it” level |
| 13:54 | tbaldridge | onielfa: Joy of Clojure is probably the best Clojure book and it's a bit more advanced than the others. I'd start there and move to a different book of JoC is too advanced. |
| 13:54 | onielfa | xemdetia: Writing small backend services, for example |
| 13:54 | xemdetia | onielfa, hmm. not sure which is the best towards that end |
| 13:54 | onielfa | well |
| 13:54 | justin_smith | sorbo_: cursive is a clojure plugin for intellij idea that supports extensive debugging |
| 13:54 | aka | the webinar wll begin shortly please remain on the line... |
| 13:55 | onielfa | I am not interested in this kind of pet project |
| 13:55 | sorbo_ | justin_smith: nice! I’ll look into it |
| 13:55 | sorbo_ | I do like IntelliJ |
| 13:55 | onielfa | I am interested in learning the clojure way |
| 13:55 | onielfa | the lisps concepts |
| 13:55 | xemdetia | there's nothing wrong with doing what you know the clojure way :) |
| 13:55 | onielfa | to change my mindset, the same way that Haskell did it |
| 13:55 | tbaldridge | onielfa: have you watched all the Rich Hickey talks/ |
| 13:56 | xemdetia | yes that's probably a good concept starting place |
| 13:56 | justin_smith | sorbo_: there is also schmetterling, that hooks into jdi, and lets you interactively investigate state in stack frames in a very clojury way when exceptions are thrown. This is all done via websockets and a browser via clojurescript |
| 13:56 | sorbo_ | I actually found that some of my philosophy courses from college were super helpful in understanding Clojure |
| 13:56 | sorbo_ | particularly endurantism vs. perdurantism |
| 13:56 | owengalenjones | xeqi: sorry got called away, not sure I understand, friend/authenticate is getting called after the app routes get wrapped by the api-defaults |
| 13:56 | sorbo_ | e.g. “this man is the same man as 10 years ago, only he’s changed since then” |
| 13:56 | sorbo_ | and “‘this man’ is a process applied to two atoms from different points in time |
| 13:56 | justin_smith | sorbo_: no resume or step options in schmetterling though (I think cursive supports these) |
| 13:56 | sorbo_ | “ |
| 13:57 | sorbo_ | justin_smith: hmm, ok |
| 13:57 | justin_smith | sorbo_: Hickey references these concepts in some of his talks |
| 13:57 | sorbo_ | still interesting, I’ll look at that one too |
| 13:57 | justin_smith | regarding state and identity |
| 13:57 | sorbo_ | yeah |
| 13:57 | sorbo_ | I need to watch more of Rich’s talks |
| 13:57 | tbaldridge | onielfa: I'd suggest watching most of these: http://thechangelog.com/rich-hickeys-greatest-hits/ |
| 13:57 | sorbo_ | coming from Ruby, I like having all the Lispy things I loved about Ruby |
| 13:58 | tbaldridge | onielfa: Rich really goes through and explains a lot of the reasoning behind Clojure |
| 13:58 | sorbo_ | but also I think the Clojure way of thinking about state and identity is, if not “more correct,” easier for handling large distributed systems |
| 13:58 | justin_smith | sorbo_: very much so |
| 13:58 | bbloom | sorbo_: it's easier for handling tiny systems too :-P |
| 13:58 | sorbo_ | bbloom: haha I believe it |
| 13:58 | sorbo_ | I converted a Node project to Clojure and it was a genuinely delightful process |
| 13:59 | Bronsa | tbaldridge: I tried to link you this 2 times in the past but you were never here, take a look at this when you have a chance http://dev.clojure.org/jira/browse/ASYNC-86 :) |
| 14:00 | TimMc | sorbo_: I could really get into a presentation like "Identities and values as explained on Welcoem to Nightvale". |
| 14:00 | TimMc | *Welcome |
| 14:00 | tbaldridge | Bronsa: thanks! I'll take a look and try to get it applied soon. |
| 14:00 | sorbo_ | TimMc: oh man, that would be awesome |
| 14:01 | TimMc | "This man is the same man you knew yesterday... and yet he is not..." |
| 14:02 | Bronsa | tbaldridge: let me know if you have issues with that patch, it should fix a bunch of edge-cases around loops but also changes how some errors are handled |
| 14:02 | justin_smith | "ve have pervected ze prozess ov controlled mutation" |
| 14:02 | justin_smith | (que evil cackle) |
| 14:03 | Bronsa | tbaldridge: i.e before (go (fn [] (<! ..))) was a "whatever not found for dispatch value :fn", now it compiles fine and throws at runtime -- old behaviour can be restored if you want, just let me know |
| 14:03 | dbasch | TimMc: (not= myself (yesterday-me / 2)) |
| 14:03 | dbasch | I mean (/ yesterday-me 2) |
| 14:04 | justin_smith | hah |
| 14:05 | justin_smith | arguably the implied meaning of < rather than not= |
| 14:05 | dbasch | yeah, (< myself (/ yesterday-me 2 |
| 14:05 | dbasch | )) ;; can't type |
| 14:09 | justin_smith | clearly your irc client lacks paredit |
| 14:09 | sorbo_ | I wonder if you can get paredit in irc from inside emacs |
| 14:09 | sorbo_ | the answer is probably yes |
| 14:10 | xemdetia | sorbo_, erc is actually pretty nice |
| 14:10 | justin_smith | definitely yes |
| 14:10 | Bronsa | paredit on erc in my experience is unusable |
| 14:10 | justin_smith | also pretty useless |
| 14:10 | sorbo_ | haha I see |
| 14:10 | justin_smith | "can you do <foo> in emacs" quickly becomes "is it actually sane to do <foo>"? |
| 14:11 | xemdetia | I use erc about 50% of the time actually |
| 14:11 | xemdetia | having autocomplete from irc chatter to whatever I'm working on is handy |
| 14:12 | justin_smith | it's my only client - it lowers cognitive overhead to have the same UI wherever the activity is primarily textual |
| 14:12 | xemdetia | justin_smith, I totally agree. |
| 14:13 | Jaood | irssi has basic emacs keybindings :P |
| 14:14 | Jaood | the same ones you get in bash I guess |
| 14:14 | nullptr | i use erc and while i don't use paredit you at least get the general purpose paren highlighting |
| 14:14 | justin_smith | Jaood: lack of M-y kills it for me |
| 14:14 | xemdetia | Jaood, the point is that any tool I'm used to using is always there no matter what |
| 14:14 | justin_smith | to coin a phrase |
| 14:14 | nullptr | show-paren-mode |
| 14:15 | justin_smith | nullptr: or rainbow parens! |
| 14:15 | ToxicFrog | That' |
| 14:15 | zot | anybody use clostache, and happen to know of a simple way to use partials in a way that doesn't require knowing-in-advance which other templates have to be loaded? (i could use a regex parser to see, and load per template, but maybe i'm missing a more obvious/cleaner sol'n) |
| 14:15 | ToxicFrog | s something I really miss in ST. No rainbowparens. |
| 14:17 | onielfa | Sorry, I was away from the computer. Coming back to the clojure book recomendations. I have watched some of the Rich Hickey videos, and that's why I have so much interest in learning Clojure. I am very tempted to buy the The joy of Clojure but I don't know if it will be too much to start off. |
| 14:19 | justin_smith | onielfa: its a good book if you already have lisp background, but not a great intro level book |
| 14:19 | dbasch | onielfa: you should check it out, and if it's too much leave it for later. It's definitely worth reading at some point |
| 14:19 | Jaood | any opinions on smartparens vs paraedit? I started with smartparens and I haven't tried paraedit yet |
| 14:20 | technomancy | Jaood: afaict smartparens has the edge with non-lisps |
| 14:20 | technomancy | Jaood: smartparens behaviour out of the box is pretty crap though |
| 14:20 | Jaood | technomancy: even using their default config? |
| 14:20 | technomancy | Jaood: last I checked |
| 14:22 | onielfa | justin_smith: so I buy joy and which one also to start off? |
| 14:22 | Jaood | I'm still tweaking it but their recommended default config didn't seem so bad to start with ;) |
| 14:23 | Jaood | but maybe is just me not being a power user of that style of editing yet |
| 14:23 | justin_smith | ,(shuffle ["clojure" "programming"]) ; onielfa |
| 14:23 | clojurebot | ["clojure" "programming"] |
| 14:23 | justin_smith | it could have been the opposite easily :) |
| 14:24 | dogonthehorizon | Clojure Programming is a bit shorter in length, FWIW |
| 14:24 | dogonthehorizon | sorry, reverse that |
| 14:24 | dogonthehorizon | Programming Clojure* |
| 14:24 | Jaood | onielfa: Clojure programming is nice to start with, you really only need like half of book ;) |
| 14:24 | Jaood | +the |
| 14:25 | justin_smith | glad to hear the shuffle chose wisely |
| 14:28 | dbasch | onielfa: you can also start with a good intro on the web, and move on to tjoc when you feel ready |
| 14:29 | dbasch | onielfa: e.g. http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome or http://www.braveclojure.com/ |
| 14:31 | dorkmafia | when you use a create a checkouts dir and use a local library does it pick up that projects deps? |
| 14:33 | justin_smith | dorkmafia: I find using "lein install" to add my lib to the private local repo and then adding it as a normal dep to be much simpler than checkouts |
| 14:35 | technomancy | dorkmafia: checkout deps are not transitive |
| 14:35 | guest889 | any clojurians from Egypt¿ |
| 14:37 | dorkmafia | justin_smith: if i do that and update the lib will it just pick up the changes? |
| 14:37 | justin_smith | dorkmafia: no, you will need to re-run "lein install" |
| 14:38 | justin_smith | dorkmafia: that is the drawback |
| 14:38 | justin_smith | but that is still simpler than checkouts, in my experience |
| 14:38 | dorkmafia | ah ic well checkouts isn't so bad then heh |
| 14:38 | dorkmafia | justin_smith: have you ever used jython? |
| 14:38 | justin_smith | I've used tools that embedded it, but I have not programmed with it directly |
| 14:39 | dorkmafia | i'm trying to figure out how to get it to use my lib |
| 14:39 | dorkmafia | well the skype4py lib |
| 14:40 | blaenk | I'm trying to figure out why my project hangs on lein uberjar on a separate computer |
| 14:40 | blaenk | it works perfectly fine on mine |
| 14:41 | blaenk | I diff'ed lein deps :tree from both and they're identical, if that's any indication of anything |
| 14:41 | justin_smith | lein versions? |
| 14:41 | justin_smith | writable directory? |
| 14:41 | blaenk | I also looked around for anything that may be evaluating at compile-time but I didn't find anything, and afterall the same exact code is working on the one computer |
| 14:41 | blaenk | will check |
| 14:41 | mdrogalis | Can anyone think of a way to use something like Schema to validate that a map is solely composed of keywords? |
| 14:42 | mdrogalis | (arbitrarily deeply map) |
| 14:42 | blaenk | justin_smith: yeah they're identical versions. 2.4.3, perms are fine too |
| 14:43 | justin_smith | weird |
| 14:43 | blaenk | yeah, very |
| 14:43 | blaenk | it just prints out one message, 'compiling <some.ns>' but there's nothing unusual about that ns |
| 14:43 | hiredman | blaenk: likely you are doing something sideeffecty in a top level form, which clojure executes, and it happens to hang on one computer and not the other |
| 14:43 | hiredman | (def db (connect-to-db-with-infinite-retries)) |
| 14:43 | blaenk | they're the same compilers too though. but yeah I looked around for something like that and the only thing I could find was a kroma defdb form |
| 14:44 | blaenk | ahh, wasn't aware of retries |
| 14:44 | blaenk | will try removing that for now |
| 14:44 | justin_smith | blaenk: you can use jstack to find out what lein is doing while hung |
| 14:44 | hiredman | I mean, I dunno |
| 14:44 | blaenk | thanks I'll check that out |
| 14:45 | justin_smith | jstack <pid-of-lein> |
| 14:45 | blaenk | awesome |
| 14:46 | hiredman | well, the lein pid won't tell you much, you need the pid of the child jvm |
| 14:46 | hiredman | (project jvm or whatever lein calls it) |
| 14:46 | justin_smith | hiredman: good point |
| 14:47 | blaenk | yeah I got that one |
| 14:47 | dorkmafia | is there a way to force clojure to run on 32 bit jvm? |
| 14:48 | hiredman | dorkmafia: if you use a 32bit jvm to run clojure it runs on a 32bit jvm |
| 14:48 | justin_smith | dorkmafia: you can tell lein which jvm to use :jvm-cmd |
| 14:48 | justin_smith | (in project.clj) |
| 14:48 | hiredman | clojure doesn't pick a jvm to run on, it is just a jar |
| 14:48 | justin_smith | there is an env var too |
| 14:48 | blaenk | I think I got the correct pid, and it seems like it's waiting for something https://gist.github.com/blaenk/bf8edfea2b2b3b2599a9 |
| 14:48 | hiredman | clojurebot: lein |
| 14:48 | clojurebot | lein is http://github.com/technomancy/leiningen |
| 14:48 | hiredman | clojurebot: lein |is not| clojure |
| 14:48 | clojurebot | A nod, you know, is as good as a wink to a blind horse. |
| 14:49 | hiredman | blaenk: that is the lein jvm, not the project jvm |
| 14:49 | dorkmafia | coo i'll check out the jvm-cmd thanks |
| 14:49 | justin_smith | dorkmafia: env LEIN_JAVA_CMD="/path/to/32bit/jvm" lein ... |
| 14:49 | blaenk | hmm |
| 14:49 | hiredman | jps will list the pids of running jvms |
| 14:49 | blaenk | thanks |
| 14:49 | dorkmafia | can i put that in my .lein profiles? |
| 14:49 | hiredman | unfortunately clojure jvms tend to just show up with the name "main" |
| 14:49 | blaenk | yeah haha |
| 14:50 | sorbo_ | just coming back to this, +1 for http://www.braveclojure.com/ |
| 14:50 | blaenk | I think I found the project one. it's the one with a large classpath right? |
| 14:50 | dorkmafia | there is also jvm-opts |
| 14:50 | blaenk | with all my project's dependencies |
| 14:50 | sorbo_ | sort of a spiritual successor to _why’s guide (Ruby) |
| 14:50 | justin_smith | blaenk: yes, probably |
| 14:51 | blaenk | alright I updated it https://gist.github.com/blaenk/bf8edfea2b2b3b2599a9 |
| 14:52 | blaenk | looks like line 130 |
| 14:52 | justin_smith | blaenk: that thread that is at FileDescriptor.sync looks suspicious to me - it should not be spending very long on that |
| 14:52 | justin_smith | blaenk: oh yeah, 130 does look suspicious :) |
| 14:52 | blaenk | seems like something with pandect |
| 14:52 | blaenk | line 107 I think more so |
| 14:52 | SegFaultAX | sorbo_: Haven't thought about _why's stuff in a while. |
| 14:52 | blaenk | yeah I think it's pandect |
| 14:53 | blaenk | look at line 61, pandect |
| 14:53 | sorbo_ | SegFaultAX: yeah, ditto. I think about him and his work every now and then |
| 14:53 | sorbo_ | wonder what he’s up to these days |
| 14:53 | justin_smith | blaenk: so I had the right stack trace, just alerted to a different suspicious part of it :) |
| 14:53 | SegFaultAX | sorbo_: Probably still being awesome. :) |
| 14:54 | sorbo_ | hopefully! |
| 14:54 | blaenk | weird thing is I'm using pandect on my computer too, and it doesn't cause any problems there |
| 14:54 | justin_smith | blaenk: it is trying to download something, maybe it is a cached download, so you don't notice it locally |
| 14:55 | blaenk | wow, surprised it's trying to download something |
| 14:55 | justin_smith | maybe I am misreading that... |
| 14:55 | blaenk | definitely seems like pandect though no? |
| 14:55 | blaenk | https://github.com/xsc/pandect |
| 14:56 | amalloy | justin_smith: what?? what makes you think it's trying to download something? it looks like it's trying to write a classfile while AOT compiling |
| 14:56 | elben | I need to (do a b c), but return b. On the top of my head, I can think of using try/finally, or a temp atom, or (let [_ a r b _ c] r). Any other idea? |
| 14:56 | hiredman | yeah, I see nothing in the stacktrace about downloading anything |
| 14:57 | technomancy | elben: sometimes doto can be handy for that |
| 14:57 | amalloy | one of the namespaces that pandect.impl.message-digest depends on could be generating arbitrarily-many classfiles, via some infinite loop at compile time |
| 14:57 | justin_smith | amalloy: oh, right. I totally misread what was happening there. |
| 14:58 | elben | technomancy: not useful here, because ‘a’ and ‘b’ are java interops for resetting and closing a stream object |
| 14:58 | amalloy | https://github.com/xsc/pandect/blob/master/src/clojure/pandect/gen/hash_generator.clj looks vaguely suspicious with the nested defprotocols, but i don't think it's really an issue |
| 14:58 | blaenk | there's a new stacktrace, I'll paste it |
| 14:58 | blaenk | I mean, it's been running and I just noticed that jstack shows something new, same style though |
| 14:58 | blaenk | okay, it's actually compiling the rest of the files now, it's like it was caught up on something |
| 14:59 | blaenk | it's like it took ages to compile pandect, or something |
| 14:59 | amalloy | blaenk: are you running this on a really slow filesystem, like over sshfs or something silly like that? |
| 14:59 | hiredman | maybe pandect probes the jvm to see what digests it supports and generates class files based on that and the jvms are different and one supports lots of digests |
| 14:59 | blaenk | nah, well I'm ssh'ed to the other computer but no not on a mounted remote fs or anything |
| 14:59 | blaenk | sounds plausible |
| 15:01 | blaenk | it's compiling stuff, it seems, from running jstack multiple times, it's just going very slow |
| 15:01 | blaenk | the computer is much faster than mine however |
| 15:02 | blaenk | barely 2/64GBs used |
| 15:02 | blaenk | and very low load across the 8 cores |
| 15:02 | amalloy | GBs...used...? what does that have to do with faster? |
| 15:02 | amalloy | blaenk: the disk is the bottleneck here, nothing else |
| 15:02 | blaenk | nothing, I was wondering if maybe it was low on memory and so it was going to disk? idk |
| 15:02 | justin_smith | amalloy: less data fighting for CPU cache lines? |
| 15:04 | blaenk | well at least now that the files are cached, it doesn't take too long to rebuild |
| 15:04 | blaenk | I guess at first I thought it was hung since it was taking forever, waited 5 minutes for it on the same ns |
| 15:06 | TimMc | amalloy_: I've been wonderinf if my encrypted filesystem is why compiling CLojure is so slow on my machine. |
| 15:06 | hiredman | definitely |
| 15:07 | TimMc | Is that based on write-then-read latency? Throughput is generally good on this fs... |
| 15:07 | justin_smith | TimMc: I have had much luck with putting non-sensitive / higher data throughput needed stuff on a secondary drive. Luckily those things often go together for me. |
| 15:08 | hiredman | compared to what? |
| 15:09 | TimMc | hiredman: I dunno, I just don't have trouble reading/writing large files. |
| 15:09 | TimMc | justin_smith: I've seriously considered mounting a ramdisk for target... |
| 15:12 | hiredman | encrypted filesystems encrypt things, non-encrypted filesystems don't, encrypted filesystems do more, doing more takes more, qed |
| 15:13 | hiredman | I could easily imagine an encrypted filesystem were large files are the optimal case |
| 15:13 | TimMc | hiredman: Right, but it doesn't noticeably impact most operations on my computer -- compiling Clojure is ht eonly thing that seems to be a problem. |
| 15:14 | Jaood | all those little class files |
| 15:14 | TimMc | I sprinkled a codebase with printlns and :verboses and it was compiling a defn once a second. :-( |
| 15:15 | hiredman | that does seem excesively slow |
| 15:15 | TimMc | (possibly a factor 2 on either side of that) |
| 15:15 | TimMc | Another reason to get rid of AOT! |
| 15:16 | hiredman | I would check to see if you have the same problem outside of lein |
| 15:16 | TimMc | Maybe write a program to slurp all the classfiles out of a target/ and spit them somewhere else? |
| 15:16 | TimMc | or you mean compile "manually" |
| 15:17 | hiredman | that |
| 15:17 | TimMc | Worth a try. |
| 15:17 | owengalenjones | can anyone see what is wrong with this ring/friend/compojure setup? basically any routes in public return an empty response; /home works and /authorized seems to work but only redirects to /login which is empty https://www.refheap.com/90164 If I remove the call to authorize / authenticate then those routes work as well, some problem with how I'm using friend? |
| 15:18 | TimMc | I should also try compiling on a ramdisk. |
| 15:29 | xeqi | owengalenjones: (-> app defaults authenticate) does authenticate first, then the default middleware, then the app routes |
| 15:30 | xeqi | for getting an opportunity to modify/handle the request |
| 15:30 | xeqi | but friend needs the params middleware to have already happened |
| 15:31 | owengalenjones | xeqi: if I reverse the threading so that authenticate is first, then any of the routes results in chrome downloading an empty file |
| 15:32 | xeqi | you don't need to reverse all of them. You still want app to be the last one to handle the request |
| 15:33 | xeqi | just defaults and authenticate. That way the default middlewares handle the request first, then friend gets to look at it, then your app handles it |
| 15:34 | owengalenjones | xeqi: sorry I mean if the app-site threading is reversed https://www.refheap.com/90174 then hitting any route except for /home results in chrome downloading an empty file instead of displaying html |
| 15:39 | hiredman | that defroutes at the bottom looks weird |
| 15:39 | hiredman | (but maybe that works to concatenate routes, and I've just never done it) |
| 15:39 | owengalenjones | hiredman: I believe so, at least I have found several examples of people combining routes like that |
| 15:40 | xeqi | owengalenjones: what happens if you switch the order the routes in site-and-api? |
| 15:41 | xeqi | so that public-site is first |
| 15:42 | bulters | anyone here watched the videos from purelyfunctional.tv? |
| 15:43 | owengalenjones | xeqi: then the routes from public work but the ones from app return an empty response :-/ |
| 15:44 | amalloy | TimMc: the clojure compiler calls fsync all the time. that's probably not the optimized-for usage on an encrypted fs |
| 15:44 | TimMc | amalloy: Aha. |
| 15:44 | amalloy | (note, eg, that blaenk's compiler was stuck on fsync every time he got a stacktrace from it) |
| 15:45 | amalloy | owengalenjones: having two different routes wrapped with handler/site-defaults looks super-sketchy |
| 15:46 | amalloy | that sounds like the kind of route that wants to be last and only-once |
| 15:46 | owengalenjones | amalloy: right thats an artifact, Im trying to wrap one in site-defaults and the other in api-defaults |
| 15:48 | amalloy | you can't just have two top-level-looking routes one after another. like if your route/not-found is before any of your other routes, it will trigger before them and cause them never to be looked at. the stuff in wrap-defaults could be similar |
| 15:54 | arohner | is there a way to check if a core.async channel has something in it, without taking? |
| 15:54 | arohner | or blocking |
| 15:57 | bbloom | arohner: any such query would risk a race condition |
| 15:58 | amalloy | bbloom: only if you presume that the next <! should be guaranteed to not block |
| 15:58 | amalloy | it could be useful as a diagnostic feature for approximating stuff, like is my channel usually full or usually empty |
| 15:59 | fifosine | Here: http://clojuredocs.org/clojure_core/clojure.core/defstruct, someone has commented that it's preferred to use defrecord over defstruct as defstruct is obsolete. Is this true? |
| 15:59 | amalloy | yes |
| 15:59 | arohner | ok, acquiring the lock is fine. I don't want to take, and I don't want to block until a value goes on the chan |
| 15:59 | hiredman | I think it is better to think of channels as a synchronization point, not as a collection that contains things |
| 15:59 | amalloy | arohner: you want to not block, but acquiring a lock is fine?? |
| 15:59 | lazybot | amalloy: Definitely not. |
| 16:00 | hiredman | that said, there is value in able to ask "is someone waiting here?" |
| 16:00 | arohner | amalloy: I changed my mind about 'block' |
| 16:00 | dnolen_ | arohner: there's no way to do that and there is unlikely to ever be. |
| 16:00 | bbloom | arohner: rewind a step and explain more generally about what you're trying to accomplish |
| 16:01 | hiredman | juc has some nice things for that, I find phasers are very useful |
| 16:01 | arohner | I have a thread that's in an infinite loop processing events as they arrive. I need a signal to stop the thread |
| 16:01 | stuartsierra | arohner: Closest you can get is `alt!` with a default and :priority true. |
| 16:01 | arohner | I know I can use a second go-loop, just felt verbose |
| 16:01 | bbloom | arohner: yeah, use two channels + alt |
| 16:02 | hiredman | arohner: either close the channel it recieves on, or have another channel to signal close |
| 16:11 | tbaldridge | arohner: the problem with looking but not taking is that the answer will often be wrong. Perfect way to create a race condition. |
| 16:16 | xeqi | owengalenjones: working example - https://www.refheap.com/90176 |
| 16:18 | xeqi | it looks like handler/site-defaults happening twice would cause a problem |
| 16:18 | xeqi | probably something similar for site-defaults and api-defaults |
| 16:19 | xeqi | I usually try to use a `context` to move all of the authenticated routes somewhere, so that the different middlewares can be applied safely once |
| 16:20 | xeqi | something like (routes (context "/app" (-> app-routes friend api-middleware)) (-> public-routes site-middleware)) |
| 16:22 | xeqi | possibly with a 404 as the last one in app-routes, since there is an url difference between app and public |
| 16:24 | owengalenjones | xeqi: ahhhh yes |
| 16:25 | owengalenjones | also |
| 16:26 | xemdetia | Is there anything better than base64 |
| 16:26 | xemdetia | for doing base64 things |
| 16:27 | TimMc | base65 |
| 16:27 | owengalenjones | xeqi: thank you so much, this was driving me crazy |
| 16:29 | xemdetia | TimMc, the sad thing is I see a base65 on github |
| 16:29 | xemdetia | now I don't know if you are lying to me or not |
| 16:33 | TimMc | :-D |
| 16:34 | TimMc | Base64 is good because 6 and 8 have a relatively high GCD. |
| 16:34 | TimMc | err |
| 16:34 | xeqi | owengalenjones: np. I seem to have gottne the flash stuff wrong, but hopefully you can take it in the way you need from here |
| 16:34 | TimMc | not 1, that is :-) |
| 16:38 | amalloy | huh, interesting. if you disassemble (fn [] [0]), it turns out that the value [0] is stored in the class's constant pool as an AFn. i would have expected either PersistentVector or Object; something in the middle is weird |
| 16:38 | xemdetia | yeah TimMc I'm just suddenly faced with the problem of 'base64 isn't quite small enough' |
| 16:40 | TimMc | xemdetia: What bytes *can't* you use? |
| 16:40 | xemdetia | exactly all of them are important |
| 16:40 | xemdetia | I need to squeeze the source more |
| 16:40 | amalloy | just use base2. send it in binary |
| 16:40 | technomancy | pff--morse code, come on |
| 16:40 | amalloy | it turns out this is the underlying transport used by ethernet |
| 16:41 | dbasch | xemdetia: bitcoin uses base58 |
| 16:41 | xemdetia | amalloy, for what I am doing the underlying transport is humanz |
| 16:41 | xemdetia | hence base64 |
| 16:41 | amalloy | so use like, base 26 |
| 16:41 | amalloy | maybe 36 |
| 16:41 | dbasch | xemdetia: base58 was meant to remove human ambiguity when reading |
| 16:41 | xemdetia | dbasch, that's interesting |
| 16:42 | amalloy | dbasch: i see. 58 removes O0o Il1 or something? |
| 16:42 | dbasch | amalloy: yes http://en.wikipedia.org/wiki/Base58 |
| 16:42 | technomancy | base25; remove the ambiguity between U and V for ancient roman users. |
| 16:42 | amalloy | technomancy: you need to scale down to 24 for rome |
| 16:43 | technomancy | sorry, "AMBIGVITY" |
| 16:43 | technomancy | amalloy: oh right, I and J too |
| 16:43 | clojurenoob | greetings! |
| 16:44 | nairobi | clojurenoob: hello |
| 16:44 | clojurenoob | I have a very simple question that I've been unable to resolve with stack overflow inquries... |
| 16:44 | clojurenoob | If I have two vectors, how do I determine which entries appear on one vector but not on theh other? |
| 16:45 | clojurenoob | I've been playing with map and .indexOf and filters but they all seem to fail on me for some reason |
| 16:45 | bbloom | clojurenoob: what else can you tell us about the vectors? size, order, etc |
| 16:45 | clojurenoob | lets say for example, twenty items in each vector |
| 16:46 | clojurenoob | order does not matter |
| 16:46 | bbloom | do the simplest possible thing: convert to a set, use filter, etc |
| 16:46 | bbloom | ,(require 'clojure.set) |
| 16:46 | clojurebot | nil |
| 16:46 | nullptr | ,(difference (set [1 2 3]) (set [2 3 4])) |
| 16:46 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: difference in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 16:46 | TimMc | amalloy: What do you mean [0] gets stored as an AFn? Like, something that implements IPersistentVector and so forth? |
| 16:47 | clojurenoob | alright lets try that. |
| 16:47 | nullptr | ,(clojure.set/difference (set [1 2 3]) (set [2 3 4])) |
| 16:47 | clojurebot | #{1} |
| 16:47 | amalloy | TimMc: i mean, the concrete class is obviously PersistentVector. but it's stored like: public static AFn const__0; |
| 16:47 | dbasch | ,(remove (into #{} [1 2 3 4 5]) [2 3 4 5 6 7]) |
| 16:47 | clojurebot | (6 7) |
| 16:47 | clojurenoob | thanks, brb, let me try this out |
| 16:48 | bbloom | dbasch: (into #{} ...) is just clojure.core/set |
| 16:48 | dbasch | bbloom: yes, but shorter :) |
| 16:49 | amalloy | and then the static initializer is something boring like static {const__0 = new PersistentVector(new Object[] {0});}, of course. i just found it interesting that the declared type is AFn |
| 16:49 | dbasch | bbloom: actually longer, never mind |
| 16:49 | dbasch | habit |
| 16:52 | clojurenoob | YAY! Fantastic thanks for your help. |
| 16:52 | clojurenoob | both solutions worked |
| 16:52 | clojurenoob | So thank dbasch and nullptr |
| 16:53 | TimMc | amalloy: Ah, weird indeed. |
| 16:53 | clojurenoob | much appreciated |
| 16:54 | dbasch | bbloom: actually into #{} is much faster than set |
| 16:54 | bbloom | (source set) |
| 16:54 | bbloom | ,(source set) |
| 16:54 | clojurebot | Source not found\n |
| 16:54 | bbloom | &(source set) |
| 16:54 | lazybot | java.lang.RuntimeException: Unable to resolve symbol: source in this context |
| 16:54 | bbloom | $source set |
| 16:54 | lazybot | set is http://is.gd/Mya7JM |
| 16:55 | bbloom | dbasch: if that's the case, it sounds like clojure.core/set is just broken |
| 16:55 | amalloy | bbloom: yes |
| 16:55 | amalloy | it doesn't use transients |
| 16:55 | technomancy | it's just old |
| 16:55 | bbloom | surely there should be a ticket for this.... |
| 16:56 | amalloy | so maybe i'm stupid, but i only today realized i can use no.disassemble to disassemble arbitrary java objects, not just clojure functions |
| 17:01 | noncom|2 | if (def my-symbol "java.io.File") then how do i pass it to import so that (import my-sympol) would be equal to (import 'java.io.File") ? |
| 17:01 | clojurenoob | I am really enjoying functional programming. Once you get past theh mindscrew of not having loops, vars, mutability, etc... It can be quite a bit of fun! |
| 17:02 | bbloom | clojurenoob: more of a mind UNscrew :-) |
| 17:05 | clojurenoob | yeah, when you putit htat way... |
| 17:05 | noncom|2 | figured out: (eval `(import ~my-symbol)) |
| 17:06 | amalloy | noncom|2: that is just a totally bizarre thing to do. you don't need to import a class to use it |
| 17:06 | amalloy | all import does is let you save some characters when typing the class's name; if you don't know the name at compile time, you're obviously never typing it, so what is the import buying you? |
| 17:06 | amalloy | if for some reason you really wanted to do it, you don't need to eval: import is just a function: (import (symbol my-symbol)) |
| 17:06 | noncom|2 | amalloy: really.. |
| 17:07 | noncom|2 | right, i do not have to import it.. |
| 17:08 | noncom|2 | i can do (.newInstance (Class/forName "ClassName")) |
| 17:09 | noncom|2 | yeah.. |
| 17:09 | amalloy | what are you doing that makes you think you want to use eval, class/forName, and runtime import? if you're not writing an IDE or a repl or something, or *maybe* a plugin system, you probably don't need any of those things |
| 17:13 | noncom|2 | amalloy: an kind of an ide, right. :) |
| 17:13 | rweir | highly recommend explaining precisely what you're doing, since it feels very XY-y |
| 17:14 | rweir | (same thing happens in python a lot - people discover eval/exec/__import__/etc and start using them when there are much simpler solutions for whatever they're doing) |
| 17:16 | noncom|2 | rweir: umm.. well, i have a media software development IDE built on top of the jmonkeyengine 3 which has to load and run java sketches written in processing in order to pass the texture they generato into a jmonkey texture in real time.. |
| 17:16 | noncom|2 | so the sketches can be dynamically loaded from files in any time too |
| 17:16 | noncom|2 | since textures for sketches can be created in real time |
| 17:17 | noncom|2 | so them are like plugins too... yeah, i guess youre right |
| 17:19 | noncom|2 | still i think that using a classloader for the java source files will prove right in the end.. |
| 17:30 | ghadishayban | bbloom: there is in fact a ticket for set+transient |
| 17:30 | ghadishayban | as well as zipmap |
| 17:46 | noncom|2 | oh no, again i am having the problem with leiningen being unable to find javac... could somebody please remind a fix to this.. |
| 17:46 | noncom|2 | i have added jdk path to PATH |
| 17:47 | zot | is there a way to cross this java/class boundary? (filter .isFile (file-seq (io/file "/tmp"))) |
| 17:47 | zot | CompilerException java.lang.RuntimeException: Unable to resolve symbol: .isFile in this context, ... |
| 17:50 | tuft | zot: (filter #(.isFile %) []) |
| 17:51 | zot | ironically i just thought to try that. and while it does compile, it returned directories. i must be doing sth else stupid. |
| 17:53 | ghadishayban | ,*clojure-version* |
| 17:53 | clojurebot | {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"} |
| 17:54 | ghadishayban | ,(transduce (map inc) |
| 17:54 | ghadishayban | (completing conj! persistent!) |
| 17:54 | ghadishayban | (transient []) |
| 17:54 | ghadishayban | [1 2 3 4 5]) |
| 17:54 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 17:54 | ghadishayban | ,(transduce (map inc) (completing conj! persistent!) (transient []) [1 2 3 4 5]) |
| 17:54 | clojurebot | [2 3 4 5 6] |
| 17:54 | ghadishayban | love that new idiom |
| 17:54 | amalloy | i don't think it's so much an idiom as a function |
| 17:54 | justin_smith | very cool |
| 17:59 | noncom|2 | does anyone use ccw here ? how do i setup the path for javac for ccw ? |
| 17:59 | justin_smith | noncom|2: any particular reason to using ccw instead of cursive? |
| 18:00 | justin_smith | oh, different IDE, never mind |
| 18:00 | noncom|2 | yeah, just being an eclipse fan... idea is good too, but historically i happen to use eclipse.. would you advice trying cursive ? |
| 18:01 | noncom|2 | i also try emacs.. |
| 18:01 | justin_smith | emacs is a whole other fish, if you already have a favorite environment it makes sense to stick with that |
| 18:01 | justin_smith | I just forgot that ccw wasn't for idea |
| 18:28 | celwell | Hi, if I have a vector of maps, what is an idiomatic way to get the map that contains a certain value for a specific key? (e.g., get the map that has an :id of 5 in [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}], ultimately I need to get "Tom".) |
| 18:32 | amalloy | celwell: ideally you would use a more suitable data structure, like a map from ids to attributes |
| 18:32 | celwell | amalloy: well it's coming from another func that get's it from a database |
| 18:33 | justin_smith | celwell: group-by helps |
| 18:33 | amalloy | sure, and once you're done reading from the database, put it into a useable data structure |
| 18:33 | amalloy | you don't want your whole program to be scanning back and forth over rows forever just because that's how the database gives you values |
| 18:34 | celwell | group-by should work nicely, thanks forgot about that |
| 18:34 | falafel | ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}] |
| 18:34 | falafel | (filter #(= (:id %) 5)) |
| 18:34 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 18:34 | falafel | ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}] (filter #(= (:id %) 5)) |
| 18:34 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 18:34 | falafel | ok |
| 18:35 | falafel | (->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}](filter #(= (:id %) 5))) |
| 18:35 | falafel | ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}] (filter #(= (:id %) 5)) |
| 18:35 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 18:36 | falafel | ,(->> [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}](filter #(= (:id %) 5))) |
| 18:36 | clojurebot | ({:name "Tom", :id 5}) |
| 18:36 | falafel | finally! |
| 18:36 | amalloy | falafel: type it into a real repl, get it working, then demonstrate here :P |
| 18:36 | falafel | lol |
| 18:36 | falafel | amalloy: I did, but I was copy/pasting from vim from the wrong buffer |
| 18:37 | justin_smith | ,((group-by :name [{:id 1 :name "Chris"}{:id 3 :name "Jon"}{:id 5 :name "Tom"}]) "Tom") |
| 18:37 | clojurebot | [{:name "Tom", :id 5}] |
| 18:37 | celwell | falafel: every vim buffer is wrong, should have used emacs. thanks though. |
| 18:37 | falafel | lol, carpal tunnel no thanks |
| 18:44 | justin_smith | turning caps lock into a control key, and control into xcomponse, has had very nice results |
| 18:44 | amalloy | thumb? hitting Ctl with a thumb seems pretty hard |
| 18:45 | p_l | amalloy: the trick is to use opposite hands |
| 18:45 | celwell | justin_smith: I had caps for C- but i still had pinky pain, i guess i'm just weak |
| 18:45 | justin_smith | maybe you just type more than me |
| 18:45 | p_l | though I'll admit to remapping caps from habit :) |
| 18:46 | amalloy | p_l: i'm aware of that trick, but i still dno't know how i would hit either control key with either thumb, without having to go way off home row |
| 18:46 | justin_smith | also, I have a kinesis freestyle, which allows my hands to be further apart, which helps with just about everything |
| 18:46 | amalloy | justin_smith: i've had caps-as-ctl for years now, but i've just left ctl as another control. i guess compose sounds pretty nice, maybe i should try it |
| 18:46 | p_l | amalloy: doesn't help that many modern keyboards, well, suck |
| 18:47 | amalloy | mine sucks, but it's full size. not a mac mini keyboard lite |
| 18:47 | celwell | justin_smith: i play guitar and piano in my downtime so my fingers don't really get a break |
| 18:47 | justin_smith | celwell: viola here |
| 18:48 | clojurenoob | question, how reaistic is using lighttable for a smaller clojure project? |
| 18:49 | clojurenoob | is it normal to have so many people joining and leaving in such short intervals? |
| 18:49 | p_l | clojurenoob: do you need to deal with non-clojure parts? |
| 18:49 | p_l | and yes, that's why many people have filters that hide joins/parts |
| 18:49 | clojurenoob | p_l some text files, but I haven't hit too many issues so far. |
| 18:50 | amalloy | clojurenoob: yes, that's pretty normal. it's a crowded room. you want to configure your client to hide at least most of those |
| 18:50 | p_l | clojurenoob: I meant mostly in terms of "calling java" :) |
| 18:50 | p_l | my experience was rather... bad |
| 18:50 | amalloy | mine hides join/part of anyone who hasn't been talking ni the last few minutes |
| 18:50 | clojurenoob | ah right, nope. NO real libraries I plan on using |
| 18:50 | clojurenoob | I'd use eclipse or something to navigate the infinite namespace that is the java core... |
| 18:50 | celwell | clojurenoob: ibdknox (creator) seems to be online. |
| 18:50 | justin_smith | clojurenoob: for a small enough project, you could probably get away with using ed. light table should be fine. |
| 18:51 | clojurenoob | seriously, celwell? That's awesome. |
| 18:51 | justin_smith | in the channel doesn't mean paying attention to the channel, but yeah ibdknox is logged in |
| 18:58 | amalloy | justin_smith: now that i've turned on my compose key, i can type devilments like this: (let [a 1, a 2] a) ;=> 1 |
| 18:59 | justin_smith | see, the benefits start already |
| 18:59 | justin_smith | luckily, emacs displays nbsp in a bright underlined face |
| 19:00 | amalloy | yeah. i have a hard time telling it apart from underscore, in emacs, but i guess it is different |
| 19:03 | Bronsa | _ |
| 19:03 | Bronsa | you can definitely tell them apart when they're near |
| 19:49 | stompyj | whats the “correct” way to require the “HEAD” version of a lib that has fixes you need, but hasn’t been pushed to clojars yet/ |
| 19:49 | stompyj | fork+self-publish? |
| 19:50 | amalloy | stompyj: yeah |
| 19:50 | stompyj | danke |
| 19:56 | dbasch | bbloom: you probably saw this ticket already http://dev.clojure.org/jira/browse/CLJ-1384 |
| 19:56 | noonian | can also just lein install locally if you don't need to publish your code right now |
| 19:56 | splunk | is there an easy way to identify namespace dependency cycles |
| 19:57 | justin_smith | splunk: don't they fail to compile? |
| 19:57 | johncash | why does (keyword INT) return nil rather than throw exception? |
| 19:57 | splunk | justin_smith: not clear--possibly? |
| 19:58 | splunk | justin_smith: not sure what type of error message to expect with a cycle |
| 19:58 | noonian | splunk: you won't be able to run the code or load it in a repl, it will give some message about a dependency cycle hehe |
| 19:58 | splunk | noonian: ah okay thanks. so what I have must be something else. |
| 19:58 | splunk | noonian: thanks!! |
| 19:59 | noonian | splunk: welcome! |
| 19:59 | noonian | ,(keyword INT) |
| 19:59 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: INT in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 20:00 | noonian | ,(keyword 8) |
| 20:00 | clojurebot | nil |
| 20:00 | justin_smith | splunk: Caused by: java.lang.Exception: Cyclic load dependency: [ /cyclic/core ]->/cyclic/big->/cyclic/apple->[ /cyclic/core ] |
| 20:00 | justin_smith | that's with a three way dependency circle |
| 20:01 | justin_smith | first line of the exception: Exception in thread "main" java.lang.Exception: Cyclic load dependency: [ /cyclic/core ]->/cyclic/big->/cyclic/apple->[ /cyclic/core ], compiling:(cyclic/big.clj:1:1) |
| 20:01 | justin_smith | much clearer than most clojure errors actually |
| 20:04 | splunk | haha indeed |
| 20:05 | splunk | I'm working with `lein test-refresh` and all of a sudden it's giving me protocol loading errors. Probably something I just broke. Thanks. |
| 20:05 | noonian | splunk: i'd recommend running lein clean every once in a while |
| 20:05 | noonian | if you are aot compiling you can get protocol errors similar to that |
| 20:06 | justin_smith | splunk: protocols and reloading code don't work together very nicely |
| 20:06 | justin_smith | noonian: well, lein test-refresh stays running, reloading namespaces and rerunning tests, that is going to break with protocols I would think |
| 20:06 | amalloy | it's just the angry spirit of technomancy, come alive in your code to remind you that he hates protocols |
| 20:06 | justin_smith | heh |
| 20:07 | splunk | curssesss!!! |
| 20:08 | technomancy | don't say I didn't warn you |
| 20:08 | splunk | holy smokes, yes, we tried to turn on AOT for uberjar, and yes lein clean just fixed a whole bunch of it |
| 20:09 | noonian | justin_smith: yeah, i work around those issues by using a 'reloaded'ish workflow, but i don't use anything as fancy as test-refresh |
| 20:09 | technomancy | every time someone says "lein clean fixed my problem" I hear "lein clean removed the symptoms of my problem so I can continue without addressing the actual cause" |
| 20:10 | splunk | technomancy: what in your mind is the problem? the protocols, as opposed to the reloading? |
| 20:10 | splunk | or the reloading is the problem? |
| 20:10 | technomancy | reloading is what makes programming not unbearably tedious |
| 20:11 | dbasch | technomancy: bearably tedious? |
| 20:11 | justin_smith | technomancy: http://i.imgur.com/tXkAcGY.jpg |
| 20:11 | splunk | okay, so it's just a question of making the protocols compatible with the reloading. I've heard, as noonian just mentioned, that the "reloaded" workflow is supposed to solve this |
| 20:12 | technomancy | but supporting reloading well has a cost in terms of performance in very tight bottlenecks; protocols are designed to allow you to improve performance in exchange for reloading support, which is what you have to do to get self-hosted |
| 20:12 | splunk | because, something something, objects/values in memory get re-initialized with proper references to the properly reloaded protocols |
| 20:15 | splunk | okay, so the goal would be get abstractions and/or polymorphic dispatch without the protocols. |
| 20:15 | splunk | multimethods being available the solve the latter, and like, something else longer discussion for the former about what it means to flexibly support abstractions / expression problem, whatever. |
| 20:16 | noonian | splunk: i'd also try to avoid storing state in Vars and just have your entry point function build your system |
| 20:22 | splunk | noonian: yeah I have to dig into somebody else's code to uproot that |
| 20:23 | jfojtl | hi, is there any sample web application written in clojure? Something that could server as a tutorial, but complete app? |
| 20:24 | technomancy | jfojtl: https://syme.herokuapp.com maybe; it's ~500 lines but complete and nontrivial. |
| 20:25 | splunk | jfojtl: also, see more: https://github.com/clojure-cookbook/clojure-cookbook/tree/master/07_webapps |
| 20:25 | dbasch | jfojtl: and https://devcenter.heroku.com/articles/clojure-web-application |
| 20:26 | jfojtl | thanks guys |
| 20:26 | jfojtl | will check it out. I knew about the cookbook, however I did not consider that as a complete app |
| 20:28 | jfojtl | technomancy: that's what I like about clojure. Non trivial things solved in trivial/simple/short ways |
| 20:46 | bbloom | here's a crazy question one of you fun crazy people may be able to answer.... YourKit's memory profiler can tell me which objects are highly referenced, but is there a way to get it (or something else) to tell me which / how-many / what-percentage-of objects have a ref count of 1? |
| 20:48 | ghadishayban | bbloom: step one, jmap -dump for a heap dump |
| 20:48 | ghadishayban | step two: browse the generated heap dump with 'jhat', another built in tool |
| 20:49 | bbloom | ghadishayban: ok thanks i'll check those two out |
| 20:50 | ghadishayban | it starts a webserver that allows you to (among other things) run a little SQL dialect over the heap graph |
| 20:52 | bbloom | ghadishayban: holy hell, this is awesome |
| 20:54 | ghadishayban | I don't know how to do it with YourKit, but jhat and jmap are built into openjdk |
| 20:54 | bbloom | ghadishayban: do you know if there is a way to run such a query without the browser? |
| 20:54 | bbloom | ie in the console & get plain text out? |
| 21:07 | ghadishayban | might take like 10 minutes to start depending on the size of the dumped heap |
| 21:11 | cfleming | bbloom: Eclipse MAT is also really useful for those sorts of things, it also has a query language |
| 21:11 | Bird|otherbox | will add-break-thread! allow a thread to be broken into via Ctrl-C if it's stuck in code completely outside the JVM's purview? (i.e. passing something to a native library that leads to a runaway exercise bike of sorts, my personal experience was with SQLite + JDBC taking a day or more to produce an OutOfMemoryException after a buggy join generated a result set almost 4 *billion* rows long) |
| 21:12 | cfleming | bbloom: An ex-workmate of mine was a wizard with the OQL, but I never played with it much myself. |
| 21:13 | zenoli | Anyone else having an issue with CIDER? I just updated, and I'm now getting "No response handler with id nil found". |
| 21:13 | zenoli | The debug output points to nrepl-client-filter as the origin. |
| 21:16 | zenoli | The error happens when trying to connect to an externally started REPL, and connection does not complete. |
| 21:17 | zenoli | Version is 2014912.503. |
| 21:17 | zeitue | question what book would be good for a beginner who has no programming knowledge to learn Clojure? |
| 21:18 | Bird|otherbox | I'd probably be more inclined to start them in another language first |
| 21:18 | Bird|otherbox | Clojure is still in a phase where the tooling is a bit immature and even intimidating |
| 21:18 | TEttinger | Bird|otherbox, yeah like java maybe. java's a surprisingly good language for beginners |
| 21:19 | Bird|otherbox | (some of the exceptions I get at the REPL somedays leave me scratching *my* head) |
| 21:19 | zeitue | yeah the java exceptions are pretty bad |
| 21:19 | Bird|otherbox | TEttinger: I'd personally argue that Python would be a better starting point. Java's *too* limiting |
| 21:20 | TEttinger | or even javascript, since you really need almost nothing to get started and can apply the knowledge quickly |
| 21:20 | zeitue | I see your point guys |
| 21:44 | technomancy | racket is great for beginner programmers |
| 21:44 | technomancy | http://htdp.org <3 |
| 21:45 | technomancy | much easier to transition to clojure from later since they already have homoiconicity and immutability by default |
| 21:45 | technomancy | plus the educational materials are top notch |
| 21:45 | technomancy | oh, he left =( |
| 21:48 | catern | but muh sicp |
| 21:53 | kenrestivo | huh, start-stop-daemon really hates lein bin. |
| 21:54 | kenrestivo | i guess lein bin emits things that look like ":;exec java -XX:PerfDataSamplingInterval=10000 -client -D .....", and start-stop-daemon can't exec them |
| 21:55 | truebuddi | technomancy: any advice for experienced OO dev to "thinking in clojure" ? |
| 21:55 | justin_s` | agreed Re: racket for new programmers |
| 21:55 | justin_s` | (inc racket) |
| 21:56 | justin_smith | (inc technomancy) |
| 21:56 | justin_smith | (for the racket suggestion) |
| 22:00 | truebuddi | justin_smith: based on yday discussion wrote some clj at https://gist.github.com/krishnabhargav/2a92da3f5f161c7da197 .. you mind taking a quick review for some expert tips? |
| 22:01 | justin_smith | truebuddi: checking it out |
| 22:02 | akhudek | truebuddi: I slightly prefer update-in rather than how you use assoc in +people and -people |
| 22:02 | justin_smith | truebuddi: or assoc-in |
| 22:02 | justin_smith | agreed |
| 22:03 | truebuddi | akhudek: will try it |
| 22:04 | justin_smith | also, something like name - for one, it is shadowing clojure.core/name which will cause an annoying warning message, for another, it is kind of pointless, it is better to document the :name key and expect it to be used directly |
| 22:04 | justin_smith | I understand the urge to abstract, but assoc is already abstracted - it works on maps or records |
| 22:05 | akhudek | yes, agreed |
| 22:05 | justin_smith | the way you use default-trip is definitely good - but take out the static magic (the call to (t/today) - because it makes the time the app booted "magic" |
| 22:06 | justin_smith | you can use a defn if you want it to always make the current day default |
| 22:06 | truebuddi | so instead of a def defaut-trip make a defn default-trip ? |
| 22:06 | justin_smith | truebuddi: remember that unlike ie. python/php/ruby you probably have one app instance that stays running for months at a time |
| 22:06 | justin_smith | right |
| 22:07 | truebuddi | but then doesnt it "go against" FP that function call each time returns a different value? |
| 22:07 | justin_smith | though immutible/static is better than dynamic when possible - it's just not compatible with the "today" thing |
| 22:07 | justin_smith | right, but you are the one who decided it should be today, and today is not immutible |
| 22:08 | justin_smith | a good compromise would be to make default-trip immutible and leave out the datas, then new-trip attach the dynamic defaults (the date part) |
| 22:08 | justin_smith | *parts |
| 22:09 | justin_smith | overall, for beginner clojure code, it's quite excellent though |
| 22:10 | justin_smith | what I like to do for usage examples is put the whole working code fragment inside (comment ...) |
| 22:10 | truebuddi | justin_smith: thank you ... ok |
| 22:10 | justin_smith | that way their editor will syntax highlight it like normal code |
| 22:10 | akhudek | good old bottom of the file tests |
| 22:11 | truebuddi | if conj for multiple items is "into" whats for "disj" ? |
| 22:11 | justin_smith | not a test, really - I see a usage example as a special form of added documentation :) |
| 22:11 | akhudek | in this case, yes :-) |
| 22:11 | justin_smith | truebuddi: conj already works with multiple items |
| 22:11 | justin_smith | and dissoc works with multiple items too |
| 22:11 | justin_smith | if they are in a collection, you can use apply |
| 22:12 | justin_smith | ,(apply dissoc {:a 0 :b 1 :c 2} [:a :b]) |
| 22:12 | clojurebot | {:c 2} |
| 22:12 | truebuddi | hmm ... |
| 22:12 | justin_smith | oh, but these are sets, calling disj |
| 22:13 | justin_smith | ,(apply disj #{:a :b :c :d} [:a :b :d]) |
| 22:13 | clojurebot | #{:c} |
| 22:13 | justin_smith | though into is just fine - just pointing out that apply conj works too |
| 22:13 | truebuddi | also if i use update-in .. i did a (update-in trip [:people] into persons) ... adds all persons into ;people set .. but if i replace into with conj it adds one item into set |
| 22:14 | akhudek | truebuddi: yes, you want into there |
| 22:14 | justin_smith | remember I said apply conj |
| 22:15 | akhudek | apply conj won’t work well with update-in |
| 22:15 | justin_smith | ,,(apply conj #{:a} [:b :c :d :e]) |
| 22:15 | clojurebot | #{:e :c :b :d :a} |
| 22:15 | akhudek | since it will thread the previous value after apply |
| 22:15 | justin_smith | yeah, good point, into is a better choice all around |
| 22:15 | truebuddi | so whats for "-person" .. into puts in .. anything to take out ? |
| 22:16 | justin_smith | there is apply disj, or clojure.set/difference |
| 22:16 | akhudek | not that difference expects two sets |
| 22:16 | justin_smith | ,,(clojure.set/difference #{:a :b :c :d :e} [:a :b]) |
| 22:16 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set> |
| 22:17 | justin_smith | ,(do (require 'clojure.set) (clojure.set/difference #{:a :b :c :d :e} [:a :b])) ;; akhudek: nope |
| 22:17 | clojurebot | #{:e :c :d} |
| 22:17 | akhudek | oh interesting |
| 22:17 | justin_smith | just the first arg matters there |
| 22:18 | justin_smith | one thing I love about clojure is how fast you can become an "expert" if you have a small bit of curiosity and an open repl all the time |
| 22:18 | justin_smith | (inc clojure) |
| 22:18 | justin_smith | lazy-ass lazybot |
| 22:19 | justin_smith | probably out partying |
| 22:19 | truebuddi | whats a lazybot? |
| 22:19 | justin_smith | it's a bot on this channel, that implements our silly "karma" system |
| 22:19 | truebuddi | i see you can exec clojure code with "," ... interesting |
| 22:19 | justin_smith | yeah, it's a great tool for demonstrating how things work, or proving who is right without needing to dig up hyperlinks |
| 22:20 | justin_smith | you can also message clojurebot (though usually using your own repl will be more convenient I am sure) |
| 22:22 | truebuddi | good to know ... |
| 22:25 | ncthom91 | hey y'all. How can I apply two forms to the "logical true" case of an if block? |
| 22:25 | justin_smith | ncthom91: do |
| 22:25 | justin_smith | ,(if 1 (do (print :OK) 2)) |
| 22:25 | clojurebot | :OK2 |
| 22:26 | ncthom91 | justin_smith thanks :) |
| 22:29 | truebuddi | updated https://gist.github.com/krishnabhargav/2a92da3f5f161c7da197 with your comments |
| 22:31 | truebuddi | is the thread-first -> in the usage a good practice? |
| 22:31 | justin_smith | truebuddi: one more little thing - assoc is varargs |
| 22:31 | justin_smith | (in the example that is) |
| 22:31 | justin_smith | ,(assoc {} ;a 0 :b 1 :c 2) |
| 22:31 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 22:32 | justin_smith | ,(assoc {} :a 0 :b 1 :c 2) |
| 22:32 | clojurebot | {:c 2, :b 1, :a 0} |
| 22:33 | truebuddi | thanks for the input .. |
| 22:35 | justin_smith | oh, and I used clojure.set/difference in my code for laziness / convenience purposes here, but it's best to require clojure.set :as set in your ns block, and use set/difference |
| 22:37 | ncthom91 | can anyone explain a quick syntax thing to me? in the memoize source code (http://clojuredocs.org/clojure_core/clojure.core/memoize) there's a call `(find @mem args)` |
| 22:37 | ncthom91 | what is the @ symbol for? |
| 22:38 | justin_smith | ncthom91: it is a a reader syntax for (deref ...) |
| 22:38 | justin_smith | ,(macroexpand @foo) |
| 22:38 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 22:38 | justin_smith | ,(macroexpand '@foo) |
| 22:38 | clojurebot | (clojure.core/deref foo) |
| 22:38 | justin_smith | there we go |
| 22:38 | justin_smith | macroexpand will often help with the weirder parts of clojure |
| 22:38 | truebuddi | btw clojuredocs.org is outdated and theres a new docs site with some complex name ... saw it on r/clojure the otherday |
| 22:38 | ncthom91 | interesting |
| 22:39 | justin_smith | truebuddi: ncthom91: yeah grimoire |
| 22:39 | justin_smith | http://grimoire.arrdem.com/ |
| 22:39 | ncthom91 | so (let [mem (atom {})]) assigns a reference to `mem`, not an actual map |
| 22:39 | ncthom91 | makes sense |
| 22:39 | justin_smith | yeah, that's what atom does |
| 22:39 | ncthom91 | reminds me of my ocaml days |
| 22:39 | justin_smith | yeah, ocaml and clojure share some important concepts |
| 22:39 | justin_smith | though sadly ocaml never figured out how to do proper concurrent gc |
| 22:40 | ncthom91 | i never got that far into ocaml :P |
| 22:41 | truebuddi | justin_smith: when i do a (def current-trip (default-trip)) I am actually executing the function only once right? |
| 22:41 | truebuddi | and I remember reading somewhere that you can "redef" the same by doing a (def ...) again ... |
| 22:43 | justin_smith | truebuddi: true on both counts - you can use defonce if the ns may get reloaded but it is important for correcness that the def not be re-bound |
| 22:43 | justin_smith | *correctness (ironic typo) |
| 22:44 | justin_smith | truebuddi: but remember that this would make the boot time of your app "magic" - your app doesn't start up fresh for each request unlike some languages |
| 22:45 | justin_smith | I have sites that have uptimes of months before being restarted |
| 22:45 | truebuddi | I am just trying to now think where i would use a ref here |
| 22:45 | justin_smith | why would you use a ref? |
| 22:45 | truebuddi | exactly ... am trying to find a use case for ref .. |
| 22:45 | justin_smith | haha |
| 22:45 | tbaldridge | truebuddi: and now you have reached enlightenment.... |
| 22:46 | michaniskin | truebuddi: justin_smith conj.io is easier to remember than grimoire |
| 22:46 | truebuddi | like i have a (def app-state []) ... technically i can "redef" it anytime i want to add to my app-state right? |
| 22:46 | justin_smith | michaniskin: cool, did not know about that URL |
| 22:46 | tbaldridge | people come to Clojure for the STM, and stay for everything else |
| 22:46 | justin_smith | truebuddi: don't use def at runtime, it has no sane concurrency semantics |
| 22:47 | justin_smith | truebuddi: that said, you usually don't need STM, atoms and maybe the occasional lock should suffice |
| 22:47 | justin_smith | (inc tbaldridge) |
| 22:47 | justin_smith | I am so inc-happy tonight, and no lazybot |
| 22:47 | tbaldridge | lol, it's the thought that counts |
| 22:48 | truebuddi | let me get this ... [] is immutable .. so any modification doesnt effect other concurrent users .. and in the worst case the def again will give stale values right? |
| 22:48 | justin_smith | truebuddi: right, but you can lose updates |
| 22:48 | truebuddi | yes .. in case of concurrent updates ... true |
| 22:48 | justin_smith | think of what happens if two threads read the current value, calculate a new one, and redef, at nearly the same time |
| 22:48 | justin_smith | right |
| 22:49 | justin_smith | you can solve this with atoms, refs, locks, or even local state in a core.async go block, depending on what you are attempting to do |
| 22:50 | justin_smith | in our experience, usually refs are not needed |
| 22:50 | truebuddi | also i have a general Java question about asynchronous IO in java ... in the .NET world, we have async calls where in the thread doesnt get blocked and there is a IO completion port that handles the "waiting" so to speak and calls back when the call is completed ... i cant find such a thing in Java .. usual recommendation is make a call on a diff thread or a thread pool thread ... |
| 22:50 | tbaldridge | truebuddi: that's kindof what core.async is for |
| 22:51 | tbaldridge | not Java, but clojure |
| 22:51 | justin_smith | truebuddi: there is also java.nio, but core.async is a much better api |
| 22:51 | justin_smith | java.nio is the more async-friendly update to java.io that comes with java 7 |
| 22:51 | truebuddi | so if i make 1000 async server calls ... it isnt really going to spawn 1000 background threads right? |
| 22:51 | justin_smith | truebuddi: not with core.async, no |
| 22:51 | tbaldridge | with core.async, no |
| 22:52 | tbaldridge | lol |
| 22:52 | justin_smith | it's the #clojure chorus |
| 22:52 | truebuddi | what about jdbc calls? does core.async help here as well> |
| 22:52 | tbaldridge | you'd need an async DB interface, but using that with core.async isn't hard |
| 22:52 | justin_smith | truebuddi: it can, if you wrap your jdbc usage in channel usage - I can see that working |
| 22:54 | tbaldridge | lol, go ahead justin_smith |
| 22:54 | truebuddi | what do you mean by async DB interface? I thought the whole JDBC protocol doesnt have anything non-blocking in design? |
| 22:57 | sarcher | database access at the jdbc layer is not asynchronous |
| 22:57 | justin_smith | to quote tbaldridge https://groups.google.com/d/msg/clojure/Aj2njGQtPN0/PMVOigU2fDAJ |
| 22:57 | justin_smith | (regarding what tbaldridge would have meant by async db interface) |
| 22:58 | sarcher | you can asynchronously perform db updates though using jdbc and core async i would assume. |
| 22:58 | justin_smith | right, as shown in some code in the link above |
| 22:58 | truebuddi | thanks for the link . but there you can see (thread ... ) .. so there is indeed a thread being created |
| 22:58 | justin_smith | for the db interaction, yes |
| 22:59 | justin_smith | but it's not a thread per interaction |
| 22:59 | justin_smith | it's a thread that handles the interactions |
| 22:59 | justin_smith | you can create as many as you like, and if they read/write the same channels, they scale transperently |
| 22:59 | truebuddi | so a thread is spawned ... it receives input through channels .. and for each input does some "db" work |
| 22:59 | truebuddi | right? |
| 22:59 | justin_smith | so you can decide how many need to exist |
| 23:00 | justin_smith | right |
| 23:00 | truebuddi | so if channel has a queue then long running db op can block the others in the same channel ... |
| 23:00 | justin_smith | and any number of threads can be spawning queries on the db based on grabbing them from the same channel |
| 23:00 | justin_smith | no |
| 23:00 | justin_smith | channels don't work like that |
| 23:01 | justin_smith | if you have two threads reading from the channel, you can have two requests at a given time. Given that your bottleneck isn't CPU, it's network bandwidth (and some latency on the db end that scales with the nubmer of requests) a fixed size thread pool works nicely |
| 23:02 | justin_smith | you can experiment to find the number of threads that performs optimally - beyond a certain count, you should see throughput drop when you increase the concurrency (due to the i/o bottlenecks) |
| 23:03 | truebuddi | hmm |
| 23:03 | truebuddi | so when you do a (chan 4) ... channel with buffer of size 4 is created right? |
| 23:03 | justin_smith | right |
| 23:06 | truebuddi | so in tbaldridge example, he spawns 4 threads all reading from the same channel ... so 4 db operations could be done in parallel on 4 threads |
| 23:06 | justin_smith | right |
| 23:08 | justin_smith | but unlike most thread pools, you wouldn't tune the pool size based on CPUs available, but based on the performance of the db (and factors like whether it is remote, network latency, db engine latency, etc.). |
| 23:09 | truebuddi | in a web app where you own/manage the deployment and constantly monitor .. may be tuning it by yourself is sufficient but imagine you are making servers that gets "sold" and the customer does his/her deployments ... tuning is going to be tricky |
| 23:11 | justin_smith | right, but you should be able to get a very good picture of the performance characteristics with load testing |
| 23:11 | justin_smith | and with a well designed app, you can access the back end and configure things like the thread count without a redeploy |
| 23:11 | justin_smith | (of course telling them "never ever touch this config" and finally telling them how to do it if it is needed) |
| 23:12 | truebuddi | but things like these only comes with experience (or getting burnt before) so when you build something you dont really worry about these until late (atleast where I work) |
| 23:12 | justin_smith | right, but you can design such that these things can be flexible in the future |
| 23:12 | justin_smith | and clojure has some nice features that ease that |
| 23:13 | justin_smith | clojure is very good at helping you prevent brittleness in apps, if you let it help you |
| 23:13 | truebuddi | anyway point is .. with all the cool innovations that happens on JVM .. it's a little surprising of not having a non-blocking db access ... |
| 23:13 | justin_smith | truebuddi: it would just end up being some defaults on top of threads anyway. It's not like the jvm implementors have access to something you as a dev don't functionality wise. |
| 23:14 | justin_smith | on this count at least |
| 23:14 | justin_smith | though, a good easy to use async db lib would be awesome. I bet you could write it if you put your mind to it :) |
| 23:15 | justin_smith | (in clojure, of course) |
| 23:15 | truebuddi | haha..honestly i dont see how adding any layer ontop of jdbc can smooth it out ... |
| 23:15 | justin_smith | I say in Clojure because the bottlenecks are emphatically not in the CPU or heap usage of the app, so switching to java would be unlikely to gain you much |
| 23:16 | justin_smith | the layer just makes it easier - the bottleneck isn't in the jvm, so a layer of abstraction will be a small constant factor, not a complexity increasing performance drain |
| 23:17 | truebuddi | layer cannot make something blocking at heart, non-blocking ... whether you see it blocking or not depends on the layer i guess |
| 23:17 | truebuddi | anyway you use a lot of "promise"/"future" in clojure? or does core.async replace all those |
| 23:17 | justin_smith | on the contrary, if it uses threads it can - and that is how your hypothetical java async db api would have to work |
| 23:18 | justin_smith | I use future a lot |
| 23:18 | justin_smith | I consider promise an implementation detail that creates futures |
| 23:18 | justin_smith | future is good sometimes, core.async others - I don't consider future out of date at all |
| 23:18 | justin_smith | agents are great too |
| 23:19 | justin_smith | in fact agents for an async db api would likely be a pretty good match |
| 23:19 | truebuddi | i always get confused between future ånd a promise |
| 23:19 | justin_smith | agents use a thread pool, you can deref a specific agent to get its result, or query as to whether it is ready... |
| 23:19 | justin_smith | a promise is just a thing you can deliver to |
| 23:20 | justin_smith | futures use the promises as an implementation detail, and deliver to the promise from another thread |
| 23:20 | justin_smith | or that's how I think of it, it might not be precisely and literally like that in clojure |
| 23:21 | justin_smith | yeah, future doesn't literally use promises |
| 23:21 | justin_smith | but that's the relationship - future is explicitly about threads, promises are more general |
| 23:22 | truebuddi | future { result = somework; result} .. somework is done only once .. and promise is just a placeholder that someone else delivers the value .. right? |
| 23:22 | justin_smith | or you could deliver to it yourself |
| 23:22 | justin_smith | it's just a thing that goes from not yet having a derefable value, to later having one |
| 23:23 | justin_smith | for example you could have one promise, and spawn N futures that could each fill the promise, first one to find an answer wins |
| 23:23 | truebuddi | any simple example of future with a thread? |
| 23:23 | justin_smith | future uses a thread, always |
| 23:23 | truebuddi | so i dont have to create a thread myself? |
| 23:24 | justin_smith | (dotimes [_ 10] (future (mapv println (range 10)))) |
| 23:24 | justin_smith | I can't make clojurebot do that, he hates threads |
| 23:25 | truebuddi | and future uses threadpool? |
| 23:26 | justin_smith | it creates a java.util.concurrent.Future |
| 23:26 | justin_smith | http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html |
| 23:27 | xeqi | it uses the agent send-off pool |
| 23:27 | justin_smith | $source future |
| 23:28 | justin_smith | xeqi: yeah, I am seeing that now |
| 23:28 | justin_smith | (.submit clojure.lang.Agent/soloExecutor ^Callable f) |
| 23:28 | truebuddi | whats that? |
| 23:28 | justin_smith | that is a quote from the source of future |
| 23:29 | justin_smith | and here is the definition of soloeExecutor https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Agent.java#L53 |
| 23:29 | justin_smith | it is a pool |
| 23:30 | justin_smith | a static field on Agent |
| 23:30 | truebuddi | and do we have things like .. when-all .. when-any ? |
| 23:30 | justin_smith | we have realized? |
| 23:30 | justin_smith | (every? realized? futures) |
| 23:30 | justin_smith | (filter realized? futures) |
| 23:30 | justin_smith | etc. |
| 23:31 | justin_smith | if futures is a list of futures that have been spawned |
| 23:31 | justin_smith | err. sequential, I mean sequential of course :) |
| 23:31 | justin_smith | hell, maybe even group-by would be useful here |
| 23:32 | truebuddi | that only allows u to check if they are ready to read from or not ... my intent with when-any was like (when-any future-list #(str %1 " retuns answer : " %2)) |
| 23:33 | truebuddi | where i "assumed" it returns a future and its answer in the result ... jus as an example |
| 23:34 | justin_smith | ok, use (filter realized?) and act on the first, or map on all results |
| 23:35 | justin_smith | or group-by realized, so you can act on all the ones that are done, and set aside all that are not done to check later |
| 23:35 | justin_smith | (by which I mean call recur with the list under the false key) |
| 23:37 | truebuddi | say i have 5 futures each of which talks to a http mirror ... we r really interested in only one answer and the first one to answer is what we are interested about .. if i do a filter .. none of them may be realized yet .. so i try again .. and again ... and again ... but this is basically spinning and spinning ... |
| 23:38 | justin_smith | truebuddi: you can poll, or as I mentioned above, ask them all to attempt to fulfill the same promise, and then block on the promise |
| 23:38 | justin_smith | then, cancel all futures once the promise comes through (cancel on a finished future is fine, it's a no-op) |
| 23:39 | truebuddi | i m going to try it out .. anyway cancellation is not guaranteed right |
| 23:39 | justin_smith | (doc future-cancel) |
| 23:39 | clojurebot | "([f]); Cancels the future, if possible." |
| 23:39 | justin_smith | that doc string is pure poetry, I swear |
| 23:40 | truebuddi | lol |
| 23:40 | justin_smith | it's been a favorite of mine, before I ever needed to use future-cancel |
| 23:45 | xeqi | future-cancel => if the future hasn't started, it won't be, but if the future has been started then the code would have to cooperate with shutting down |
| 23:46 | xeqi | by checking Thread/interrupted and handling it gracefully |
| 23:46 | xeqi | irrc |
| 23:51 | justin_smith | xeqi: cool, good to know |
| 23:52 | justin_smith | as I think about that task more - I wonder how often the latency at the other end of the http request is the main bottleneck (such that starting multiple requests and cancelling all but the one that finished makes sense) |
| 23:52 | justin_smith | also, if I was running the service you were hitting with that kind of usage pattern, I would probably be annoyed |
| 23:54 | justin_smith | at a certain point, fewer parallel requests will perform better, as your interface or network saturate. The interesting question is whether that point is > 2 or not |
| 23:58 | catern | the (or foo bar default) trick is so useful and I can even use it in Python |
| 23:58 | justin_smith | heh, indeed |
| 23:58 | catern | are there any other such cross-language tricks that I could learn about from Clojure? |
| 23:59 | justin_smith | the value of immutible data (the trick is how well the language can fake immutibility of course) |