2012-11-08
| 02:42 | seannetbook | ibdknox: replied to your email... still having problems on win8 x64 |
| 02:42 | ibdknox | ugh |
| 02:43 | ibdknox | seannetbook: anything unique about your setup? |
| 02:44 | seannetbook | hardly... it's vanilla win8 release preview on a parallels VM |
| 02:44 | seannetbook | i know next to nothing about windows so i haven't customized it :) |
| 02:44 | ibdknox | ironically me neither ;) |
| 02:44 | ibdknox | I'm on a fresh install of win8 on parallels x64 |
| 02:44 | seannetbook | is there any debug flag i can set or logs or something? |
| 02:45 | ibdknox | Not that I can find, it seems to be deep down in node territory |
| 02:45 | ibdknox | I have a couple other guesses on what might be wrong |
| 02:45 | ibdknox | and how I can fix it |
| 02:46 | ibdknox | I'll give them a shot and ping you when I have something worth trying |
| 02:46 | ibdknox | thanks a ton for helping out with this btw |
| 02:46 | seannetbook | 'k... anything i can do to help, just let me know |
| 02:46 | seannetbook | i'm probably buying a win8 convertible tablet as my main travel device so i'll need light table to work on that :) |
| 02:48 | seannetbook | i have lein, clojure, java, emacs, nrepl all working on win8 on the vm so light table is the last piece of the puzzle! |
| 02:52 | ibdknox | seannetbook: you mean a surface? |
| 02:53 | seannetbook | not sure yet - MS haven't confirmed specs or pricing on the Pro |
| 02:53 | ibdknox | I think the surface doesn't *actually* run most apps |
| 02:53 | seannetbook | right now i'm leaning toward the Dell XPS 12 Ultrabook Convertible |
| 02:53 | ibdknox | it's an arm device |
| 02:54 | seannetbook | the Surface RT doesn't, but the Pro is a full Intel/Win8 Pro machine |
| 02:54 | Urthwhyte | I've got an RT if you have questions |
| 02:54 | seannetbook | my spec is an i7, 8GB RAM, 256GB SSD |
| 02:55 | seannetbook | dell, sony, toshiba all have convertibles with that spec for $1,500 |
| 02:55 | ibdknox | nice |
| 02:55 | seannetbook | the asus taichi is a possibility too but more expensive |
| 02:56 | seannetbook | (and i'm a lifelong apple guy) |
| 02:56 | Urthwhyte | I'm still waiting for better Linux support of retina displays :/ |
| 02:57 | Urthwhyte | Won an rMBP at a hackathon and had to give up Linux |
| 02:57 | Urthwhyte | Losing xmonad has been quite the chore |
| 02:58 | seannetbook | my alternative is a MacBook Air 11 fully loaded but i would prefer a tablet hybrid |
| 02:59 | Urthwhyte | My concern with going to W8 is losing the shell |
| 03:00 | Urthwhyte | Cygwin doesn't really cut it |
| 03:00 | seannetbook | use emacs and eshell :) |
| 03:01 | Urthwhyte | vim guy at heart, nty |
| 03:05 | ibdknox | seannetbook: just to make sure, can you try deleting .lighttable and running it? |
| 03:06 | seannetbook | just a sec i'll go try that |
| 03:07 | Urthwhyte | Oh, is that the Lt author? |
| 03:08 | ibdknox | it is :) |
| 03:08 | Urthwhyte | Always surprises me how populous this channel is |
| 03:09 | seannetbook | ok, deleted .lighttable and ran the new download again - same error |
| 03:09 | ibdknox | k, just wanted to be certain |
| 03:09 | ibdknox | thanks |
| 03:10 | seannetbook | anything else tonight or can i go to bed? :) |
| 03:12 | Urthwhyte | Now I'm tempted to retry some 4clj problems with LT v. vimclojure and see which goes faster hah |
| 03:12 | brainproxy | &(let [lazy-seq* #'clojure.core/lazy-seq] (lazy-seq* [1 2 3])) |
| 03:12 | lazybot | clojure.lang.ArityException: Wrong number of args (1) passed to: core$lazy-seq |
| 03:12 | ibdknox | seannetbook: head out, I'm not far behind |
| 03:12 | brainproxy | ^ what's the correct way to "alias" a macro in another namespace? |
| 03:13 | seannetbook | 'k man.. are you gonna be at rich's talk tomorrow in town? |
| 03:13 | amalloy | usually the answer is to not define aliases for things that already exist |
| 03:13 | amalloy | for sure you can do it, but... |
| 03:13 | brainproxy | amalloy: sure, well let's just assume I have a really good reason to do it |
| 03:16 | tomoj | (:require [clojure.core :as core]) ? |
| 03:16 | tomoj | (core/lazy-seq [1 2 3]) |
| 03:19 | brainproxy | tomoj, thanks, but not quite what I was after |
| 03:19 | brainproxy | amalloy: this works `(def #^{:macro true} lazy-seq* #'clojure.core/lazy-seq)` |
| 03:19 | tomoj | why do that? |
| 03:20 | brainproxy | tomoj: just learning some things... |
| 03:42 | jyu | hi, are there any awesome bdd style test framework |
| 04:41 | pingtimeout | Hello world ! |
| 04:41 | _ulises|away | pingtimeout: pong |
| 04:42 | ejackson | sssh.... its meditation hour in #clojure |
| 04:43 | pingtimeout | Hmm ok |
| 04:43 | pingtimeout | I'll be quiet |
| 04:43 | ejackson | just kidding, its usually quiet in here until the American wander in with their spurs and big hats :P |
| 04:44 | pingtimeout | :) |
| 04:44 | pingtimeout | Ok so lets go |
| 04:44 | pingtimeout | I'm wondering : is it possible to start a clojure nREPL and connect to it using telnet ? |
| 04:46 | pingtimeout | The point is : I have a webapp where you can send code to a node.js server |
| 04:46 | pingtimeout | (Only for training purpose) |
| 04:46 | pingtimeout | So currently it supports only javascript code, and I would like to add clojure support |
| 04:47 | pingtimeout | And here I am, trying to figure out how nREPL works |
| 04:48 | pingtimeout | Do you have any advice or pointers about how I could achieve that ? |
| 04:48 | ejackson | you connect to an nrepl directly |
| 04:48 | ejackson | over so long as you can see the port |
| 04:48 | ejackson | I have a couple of machines with an embedded nrepl server, forward the port over ssh, and then connect directly |
| 04:49 | ejackson | couldn't be easier |
| 04:49 | pingtimeout | Yeah but, what do you use to connect to the nREPL ? |
| 04:50 | ejackson | aaah, I see, I'm doing it from emacs |
| 04:50 | ejackson | using nrepl.el |
| 04:50 | ejackson | if you dig into that I'm sure you'd find your answers |
| 04:51 | pingtimeout | Ok thanks :) |
| 04:52 | pingtimeout | For instance, I connected a telnet to the nrepl server and typed "(println :foo)" but it did nothing |
| 04:52 | ejackson | yeah, I imagine there may be more to it than that :) |
| 04:53 | pingtimeout | Yeah obviously, but that would be my goal : have a server that evaluates clojure expressions and return the result over HTTP or something like that |
| 04:54 | ejackson | pingtimeout: there are a couple of existing projects that do it in embedded clojurescript: session being the most interesting |
| 04:54 | ejackson | so cljs sends clj to server, its eval'd, and the result sent back to cljs in the browser |
| 04:57 | pingtimeout | Ok thx, I'm going to dig that :) |
| 04:57 | clgv | pingtimeout: there is a HTTP transport for nrepl |
| 04:58 | ejackson | aaah, and there's the answer :) |
| 04:59 | clgv | pingtimeout: and telnet should work to. but "(println :foo)" is a command you want to execute but the server expects message of his nrepl-protocol. hence you have to wrap the clojure command in the appropriate nrepl message |
| 05:00 | pingtimeout | clgv So to summarize : I could either use clojurescript in my node.js server to connect to the repl, or try to write a http client using the http nrepl protocol |
| 05:01 | ejackson | the first doesn't require the the repl - you can just send use an http server yourself |
| 05:01 | clgv | pingtimeout: I dont know much about that first option but you can certainly use the second and talk to the nrepl server via the nrepl protocol |
| 05:02 | pingtimeout | Yeah http would be easier I think |
| 05:02 | pingtimeout | Do you know where i can find the documentation of the nrepl http protocol ? |
| 05:03 | pingtimeout | I found this but not sure it is relevant : https://bitbucket.org/kotarak/nrepl |
| 05:05 | clgv | pingtimeout: maybe a bit outdated since nrepl made a jump to 0.2.0 which might have broken apis |
| 05:06 | clgv | pingtimeout: https://github.com/cemerick/drawbridge |
| 05:07 | clgv | pingtimeout: if you are stuck try to ping cemerick this afternoon |
| 05:09 | pingtimeout | Ok |
| 05:09 | pingtimeout | Many thanks ! |
| 05:34 | luxbock | why does ((fn [a b] [a b]) 1 2) give me [1 2] but (#([%1 %2]) 1 2) throws an exception? |
| 05:36 | scottj | luxbock: because #(a) is the equivalent of (fn [] (a)) not (fn [] a) |
| 05:39 | luxbock | hmm I see |
| 05:47 | alexnixon | luxbock: I disagree with scottj, rather it's because the #() form tries to evaluate the stuff within |
| 05:52 | alexnixon | luxbock: in this case it's trying to evaluate a vector |
| 05:54 | luxbock | alright |
| 05:54 | rcg-work | huh |
| 05:54 | rcg-work | err |
| 05:58 | alexnixon | ,(#(vector %1 %2) 1 2) |
| 05:58 | clojurebot | [1 2] |
| 07:14 | clgv | luxbock: just for the record, scottj had the right explanation |
| 07:16 | alexnixon | clgv: he did - I misunderstood |
| 07:17 | luxbock | next question: how do I exit an infinite loop in Emacs, using nREPL? is there a way beyond killing the buffer and the process with it? |
| 07:18 | antares_ | luxbock: unlikely |
| 07:23 | clgv | luxbock: nREPL supports that but the question is if nREPL.el has support for that already |
| 07:23 | clgv | in CCW there is a button to kill the current execution in the REPLView |
| 07:24 | luxbock | what's CCW? |
| 07:24 | clgv | Counterclockwise a plugin for Clojure development in eclipse |
| 07:25 | luxbock | ah |
| 07:25 | clgv | so you have to check nrepl.el documentation or source to find out whether there is a keybinding for that |
| 07:31 | luxbock | C-c C-b seems to work |
| 07:37 | zakwilson | Lighttable actually runs for me now. Yay. Instarepl doesn't seem to like it when I call in-ns though. |
| 07:59 | frawr | hi, looking for some help with enfocus. |
| 08:27 | solussd | Anyone else here use noir-cljs for clojurescript? When I deploy to heroku everything is AOT compiled, but the clojurescript compiler blows up at runtime if I AOT. Any else experience this? |
| 08:41 | magius_pendragon | hey everyone ; I'm having some trouble with genclass. It's throwing a class not found exception on the class I'm trying to subclass... it's fully qualified (I think? I don't know java very well) and the containing jar is in my projects.clj file as a dependency. |
| 08:42 | _ulises | magius_pendragon: can you paste the code somewhere? |
| 08:42 | magius_pendragon | _ulises: yeah, is there any preference on where? |
| 08:42 | magius_pendragon | I vaguely remember a clojure pastebin last time I hopped in here, but don't have the address on hand |
| 08:43 | _ulises | magius_pendragon: refheap, friendpaste, they're all fine |
| 08:43 | magius_pendragon | https://www.refheap.com/paste/6483 |
| 08:44 | magius_pendragon | I'm aware that this example in particular could use proxy instead, but it was simpler than the one that I'm working on that I think does (needs to access a protected field of a superclass, where the superclass doesn't provide a getter) |
| 08:45 | _ulises | magius_pendragon: I don't have much experience with gen-class et al, but I've generally seen it used inside the (ns ...) form |
| 08:46 | magius_pendragon | docs say it can be outside. It's throwing the error on the name of the superclass, rather than the name of the generated class as well |
| 08:47 | _ulises | magius_pendragon: have you tried the import in a repl? |
| 08:48 | magius_pendragon | _ulises: the import was working when I used proxy instead |
| 08:48 | _ulises | magius_pendragon: interesting |
| 08:48 | magius_pendragon | can't get it in a repl right now cuz the code won't compile, and linking all of the libraries to a fresh repl would be a headache |
| 08:48 | _ulises | oh |
| 08:49 | cmdrdats | hey guys, i have a vector of maps, like [{:age 31} {:age 20}] - what's the idiomatic way to run a function against all the :age values and 'update' the value - resulting in [{:age 32} {:age 21}], if i run it using inc? |
| 08:50 | madsy | cmdrdats: map should work fine |
| 08:50 | cmdrdats | (map #(inc (:age %)) items) ? |
| 08:51 | cmdrdats | was hoping for something like (update-walk [:age] inc items) |
| 08:53 | magius_pendragon | _ulises: any other ideas ? |
| 08:53 | joegallo | ,(map (update-in % [:age] inc)) [{:age 1} {:age 2} {:age 3}]) |
| 08:53 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: % in this context, compiling:(NO_SOURCE_PATH:0)> |
| 08:53 | joegallo | ,(map #(update-in % [:age] inc)) [{:age 1} {:age 2} {:age 3}]) |
| 08:53 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$map> |
| 08:53 | joegallo | ,(map #(update-in % [:age] inc) [{:age 1} {:age 2} {:age 3}]) |
| 08:53 | clojurebot | ({:age 2} {:age 3} {:age 4}) |
| 08:54 | _ulises | magius_pendragon: not from the top of my head unfortunately |
| 08:54 | joegallo | which is basically (map #(update-in instead of the idate of update-walk. you only lose a few characters, it's not so bad. |
| 08:54 | joegallo | s/idate/idea/ |
| 08:54 | cmdrdats | i was hoping to drop the anonymous function :/ |
| 08:55 | cmdrdats | but oh well, no biggie |
| 08:55 | cmdrdats | i'll just roll my own, just wanted to check that I'm not missing some super obvious function that already does it |
| 09:06 | magius_pendragon | _ulises: figured it out. Apparently removing the []'s around the superclass was needed. |
| 09:07 | magius_pendragon | _ulises: but thanks for your help :) |
| 09:11 | luxbock | is there a way to auto-load certain libraries with REPL? more specifically I'd like to be able to do it in Emacs with nrepl |
| 09:19 | AWizzArd | luxbock: What you mean by „auto-load”? |
| 09:20 | luxbock | so that I can use the library straight away, without having to import it |
| 09:23 | clgv | luxbock: you could put a require or use in project.clj as :injections "(require '[my.lib :as lib])" |
| 09:23 | clgv | args no. :injections [(require '[my.lib :as lib])] |
| 09:28 | luxbock | ah, hadn't seen that option before |
| 09:28 | luxbock | while googling it I found this: |
| 09:28 | luxbock | http://stackoverflow.com/questions/12329713/how-to-load-ns-by-default-when-starting-repl |
| 09:29 | luxbock | seems like I can also use :repl-options |
| 09:31 | clgv | oh right :init^^ |
| 10:04 | Anderkent | Anyone familar with sqlkorma? Is it alive? |
| 10:04 | clgv | Anderkent: well, chris granger is busy with light table ;) |
| 10:07 | pandeiro | can you program clojurescript with lighttable, anyone know? |
| 10:10 | pandeiro | i would see for myself but i get an error about libudev.so missing :( |
| 10:19 | jsabeaudry | Short way of doing (into {} (map #(vec [% (foo %)]) #{:a :b :c})) ? |
| 10:19 | jsabeaudry | Or more idiomatic |
| 10:22 | ejackson | jsabeaudry: maybe you like (into {} (map (juxt identity f) #{:a :b :c}) |
| 10:23 | Anderkent | (zipmap my_vector (map foo my_vector)) maybe? |
| 10:24 | jsabeaudry | ejackson, Anderkent, thanks, I think I'll go with the zipmap |
| 10:24 | ejackson | yeah, its nicer :) |
| 10:26 | apwalk | or the venerable: (reduce #(assoc % %2 (f %2)) {} #{:a :b :c}) |
| 10:29 | alexnixon | does this function look 'generally useful'? I've needed it a few times myself, just wondering if anyone else has too: https://www.refheap.com/paste/6484 |
| 10:31 | alexnixon | the context is when using the threading macro to store the results of sequential computations in a 'state' map: (->> state (assoc-if some-opt :foo (compute-foo)) (assoc-if other-opt :bar (compute-bar))) |
| 10:37 | Anderkent | shouldn't it be a macro in case compute-foo has side effects? |
| 10:43 | alexnixon | Anderkent: that's a good point - and also for efficiency |
| 10:47 | TimMc | alexnixon: I believe test-> or whatever it is called would help with that. |
| 10:49 | alexnixon | TimMc: I haven't come across that before - can you point to the source? |
| 10:49 | TimMc | https://gist.github.com/3885504 |
| 10:49 | TimMc | It's not in any released code yet, I think. |
| 10:51 | alexnixon | yes that would help. Is that slated for 1.5? |
| 10:51 | TimMc | (test-> state some-opt (assoc :foo (compute-foo)) other-opt (assoc :bar (compute-bar))) |
| 10:52 | TimMc | Let me check the chatlog. |
| 10:53 | hyPiRion | groan.. Now I remember why I went from Common Lisp to Clojure. |
| 10:54 | hyPiRion | TimMc: https://github.com/clojure/clojure/commit/026691e2f6cc8d1bab4feb7e577530a9f06fd85e |
| 10:56 | TimMc | oh, sweet |
| 10:56 | alexnixon | cool so that's in the 1.5 beta |
| 10:57 | gtrak | when-> is like -?> and let-> is like -<> ? |
| 10:58 | S11001001 | is let-> anaphoric, gtrak? |
| 10:59 | gtrak | what's anaphoric? |
| 10:59 | hyPiRion | ~anaphoric |
| 10:59 | clojurebot | Titim gan éirí ort. |
| 10:59 | S11001001 | gtrak: that is, it would have to do proper form replacement, not just bind a let with a variable |
| 10:59 | S11001001 | gtrak: introduces a binding implicitly |
| 10:59 | gtrak | it looks like it replaces it in top-level forms, but also binds it |
| 10:59 | S11001001 | gtrak: well that's nasty |
| 11:00 | gtrak | S11001001: wait, I think I'm reading it wrong, it doesn't place it in the form, but it does bind it |
| 11:01 | S11001001 | gtrak: that's the opposite of -<> |
| 11:01 | Mr_Bond | I need to get a clojure book, all these operators are like greek to me |
| 11:01 | Mr_Bond | :) |
| 11:01 | S11001001 | Mr_Bond: you won't find these in any book |
| 11:01 | S11001001 | Mr_Bond: and they're just names; it's no harder to find out what -<> does than what "reductions" does (notwithstanding google being crap, but grep is always better for that anyway) |
| 11:02 | gtrak | Mr_Bond: blow your mind: https://github.com/rplevy/swiss-arrows |
| 11:02 | Mr_Bond | yeah, that's true |
| 11:02 | gtrak | -<><:p |
| 11:02 | Mr_Bond | thanks, nice overview. I'm not a big fan of such it's like $_, $-, $!, $<, etc in perl and ruby |
| 11:02 | hyPiRion | heh |
| 11:03 | hyPiRion | It's moving into APL-land. |
| 11:03 | S11001001 | Mr_Bond: anaphora have problems, but they're typically much safer than the globals perl offers |
| 11:04 | Mr_Bond | Ah, I ment more in terms of readability |
| 11:04 | S11001001 | Mr_Bond: I can say entirely empirically that -<> is highly intuitive to readers |
| 11:04 | Mr_Bond | hehe :) |
| 11:05 | gtrak | let-> seems like a good alternative |
| 11:05 | Mr_Bond | yeah |
| 11:05 | S11001001 | gtrak: when it works. |
| 11:05 | S11001001 | Mr_Bond: you don't get the benefit of people using it in a sentence here; we're just talking about it abstractly |
| 11:05 | gtrak | is it broken in some way? |
| 11:06 | S11001001 | gtrak: making a let binding is fundamentally different from form replacement |
| 11:06 | TimMc | Looks fine to me. |
| 11:06 | DaReaper5 | Basic clojure question: What is the best way to pass json to java in a method's parameters? |
| 11:06 | S11001001 | for example, if <<- did binding instead of form replacement, you couldn't use it as a replacement for let-else |
| 11:07 | TimMc | DaReaper5: That doesn't sound very basic. |
| 11:07 | S11001001 | (<<- (let [x 42]) (when (= x 42)) (if (on?) "on") x) |
| 11:07 | TimMc | What do you mean by "json"? |
| 11:07 | DaReaper5 | haha thought it was |
| 11:07 | S11001001 | instant depth reduction |
| 11:07 | DaReaper5 | TimMc json is javascript object notation |
| 11:07 | gtrak | S11001001: I'm not sure I'm deep enough into this to undertand why that matters. I always thought of form-replacement as a nice hack, but I prefer to think in values and bindings anyway. |
| 11:07 | TimMc | DaReaper5: Not what I meant. |
| 11:07 | S11001001 | gtrak: see above for usage; it's not at all just a hack |
| 11:08 | DaReaper5 | i want to pass a json object to a java method |
| 11:08 | TimMc | S11001001: And then you have a kind of non-locality of control flow that smells really bad. |
| 11:08 | DaReaper5 | should i do the conversion on the clojure end or java end |
| 11:08 | S11001001 | TimMc: it's no worse than let-else |
| 11:08 | DaReaper5 | can cheshire do this? |
| 11:08 | S11001001 | TimMc: if you're desperate to reduce expression depth it's the shortest path |
| 11:09 | dakrone | DaReaper5: it's not quite clear what you're asking about |
| 11:10 | gtrak | S11001001: it's totally not clear to me what that's doing, so there's that |
| 11:10 | S11001001 | gtrak: copy and paste it and put newlines in between the args |
| 11:10 | DaReaper5 | On the clojure side i have a json object. I want to pass this in a java method's parameter. |
| 11:11 | DaReaper5 | Java does not recognize json so i have to convert |
| 11:11 | TimMc | DaReaper5: Are you having trouble with Java interop syntax? |
| 11:11 | gtrak | S11001001: so it's threading them from the bottom up? |
| 11:11 | S11001001 | gtrak: you've got it |
| 11:11 | gtrak | not sure what the benefit is though |
| 11:11 | DaReaper5 | Does the java interop have a way of converting json? |
| 11:11 | ohpauleez | DaReaper5: You mean you have a JSON string? Or you've parsed the JSON into a Clojure map? |
| 11:12 | S11001001 | gtrak: do the expansion, and imagine it's longer |
| 11:12 | DaReaper5 | ohpauleez i can have either on the clojure side |
| 11:12 | DaReaper5 | i already have a way of converting json to and from a string |
| 11:13 | ohpauleez | DaReaper5: Ok, well if the Java method expects a JSON string, just pass it in. If it expects a map-like thing, just pass in the hashmap |
| 11:13 | DaReaper5 | i can pass a string but... can i pass a clojure map to a java method |
| 11:13 | gtrak | so it's good if you're nesting a lot of forms with no branching in the tree |
| 11:13 | DaReaper5 | ok |
| 11:13 | Anderkent | you can pass a clojure map to a java method that wants a map |
| 11:13 | DaReaper5 | so it just behaves like a hashmap |
| 11:13 | gtrak | I think I rarely do that |
| 11:13 | DaReaper5 | no conversion necessary |
| 11:13 | ohpauleez | correct |
| 11:13 | gtrak | I'll just make functions usually |
| 11:13 | TimMc | DaReaper5: Everything you're asking about depends on what the Java method expects, which you haven't xplained at all. |
| 11:14 | DaReaper5 | so the answer to my question is: The best way to pass json to a java method is to pass the json object as a clojure map which will be the equivilant of a hashmap |
| 11:14 | ohpauleez | TimMc: I think it expects a map-like |
| 11:14 | DaReaper5 | TimMC i can have the java method retrieve anything |
| 11:14 | ohpauleez | DaReaper5: Don't use "json" like that |
| 11:14 | DaReaper5 | but a string would be impractical because a conversion would still have to be done |
| 11:14 | DaReaper5 | ophauleez, sorry like what? |
| 11:15 | Anderkent | you need to do the json string -> hash map conversion somewhere anyway |
| 11:15 | gtrak | S11001001: seems like it's equivalent to not indenting properly :-). |
| 11:15 | Anderkent | whether you do it in java or in clojure does not really change much |
| 11:15 | DaReaper5 | anderkent i have cheshire for that i believe |
| 11:15 | S11001001 | gtrak: you'll note there's a branch in my example |
| 11:15 | ohpauleez | JSON is a string format. A data exchange. You want to say: "If my Java method expects a map, I need to parse the JSON string into a Clojure map before passing it on to Java" |
| 11:15 | gtrak | is it more readable? https://gist.github.com/d7b45e347df19d9e808f |
| 11:16 | ohpauleez | "If the Java method expects a JSON string, I should pass the string directly in" |
| 11:16 | DaReaper5 | ohpauleex yes you are right but i was unaware of the possiblity of using a clojure map in the context |
| 11:16 | S11001001 | gtrak: and it autoindents correctly |
| 11:17 | gtrak | right, I just think I'd prefer the auto-indented version of the second thing I wrote. |
| 11:17 | S11001001 | gtrak: sure; <<- is for longer series |
| 11:17 | DaReaper5 | anderkent it does matter because if i can use a bult in converter on the clojure side it would be easier :) |
| 11:18 | S11001001 | or if you want to use ->> but backwards |
| 11:18 | S11001001 | because that's all it is |
| 11:18 | DaReaper5 | but i believe i know what to do now so thanks! |
| 11:18 | gtrak | yes. I could see it being useful for deep nesting. |
| 11:18 | TimMc | S11001001: That "if" is hella confusing. |
| 11:19 | gtrak | but the benefit of ->> and -> for me is the value-flow, and it's slightly nicer than lots of let's. I don't have to reason about stack-frames. |
| 11:19 | TimMc | Especially because "<<-" looks like it puts things at the beginning of the form, not the end. |
| 11:19 | ohpauleez | DaReaper5: totally welcome |
| 11:19 | gtrak | I see it as macroized comp |
| 11:19 | S11001001 | TimMc: what else would you call backwards ->>? |
| 11:19 | TimMc | >>-, duh :-P |
| 11:20 | djcoin | gtrak: oh, awesome, your logo from keen commander, I love this game :) |
| 11:20 | gtrak | it's classic! |
| 11:20 | gtrak | keen commander? is that a foreign language version? :-) |
| 11:21 | ohpauleez | haha |
| 11:21 | djcoin | gtrak: don't know, what is your version ? maybe I don't recall it exactly :) |
| 11:21 | gtrak | Commander Keen |
| 11:22 | ohpauleez | I don't think I ever realized that was a Carmack and Romero game |
| 11:22 | gtrak | we were talking about threading and ordering after all |
| 11:22 | djcoin | Well Commander Keen then must be the exact name |
| 11:22 | pandeiro | in JoC, there's a brief part on PersistentQueue that says "repeatedly check a work queue to see if there’s an item of work to be popped off, or if |
| 11:22 | pandeiro | you want to use a queue to send a task to another thread, you do not want the |
| 11:22 | pandeiro | PersistentQueue discussed in this section. |
| 11:23 | pandeiro | -- my question: if that's what i want, what *should* i use? |
| 11:23 | gtrak | (-> Keen Commander) |
| 11:23 | gtrak | pandeiro: probably an agent |
| 11:23 | ohpauleez | pandeiro: and a priority queue |
| 11:24 | pandeiro | ohpauleez: that is a java class? |
| 11:24 | ohpauleez | or an atom with with a watcher |
| 11:26 | ohpauleez | pandeiro: http://clojure.github.com/clojure-contrib/branch-master/priority-map-api.html |
| 11:26 | ohpauleez | Dig around to see where this went to, and use watchers |
| 11:26 | gtrak | commander keen was the birth of smooth side-scrolling on pc, like mario 2. |
| 11:28 | pandeiro | ohpauleez: gracias |
| 11:34 | ohpauleez | pandeiro: Certainly! happy to help |
| 11:36 | ejackson | gtrak: hard to believe that after Keen they then did Doom ! |
| 11:36 | djcoin | :) |
| 11:37 | gtrak | ejackson: wolfenstein |
| 11:37 | ejackson | yeeeeeeees |
| 11:37 | ejackson | still, from collecting pizza to topping nazis.... |
| 11:40 | gtrak | keen 4-6 was pretty great, too |
| 11:41 | djcoin | I mostly played to keen4 as a kid, love the universe |
| 11:44 | ejackson | the book "Masters of Doom", about the iD mob, is a great read |
| 12:04 | deg | Is there any codewalker that I can use, e.g. to find the body in a defn form? (That is, something smart enough to peel away the arglist, metadata map, doc string, etc., and leave me with just the body forms?. (I know that I can copy the source code of defn itself, but I'm looking for a more elegant solution). |
| 12:05 | gtrak | deg: if it's on functions you write yourself, you can create a macro to attach it as metadata |
| 12:06 | deg | gtrak: Not sure what you meant, especially the "it" at the end. |
| 12:07 | gtrak | make your own defn that does what you wan |
| 12:07 | gtrak | t |
| 12:07 | deg | I see. Nope. I need to walk existing code, separating the function body from everything else. |
| 12:07 | gtrak | ah |
| 12:07 | gtrak | that sounds harder :-) |
| 12:07 | deg | It's not rocket science, but does involve a bunch of detailed rules... |
| 12:08 | gtrak | you might want to look at the clojurescript analyzer, or consider hacking the clojure compiler? |
| 12:09 | deg | I've looked at the definition of defn. I could copy that code but it is, for obvious reasons, written using very blunt instruments, since it comes into play before most of the Clojure runtime is loaded. |
| 12:09 | gtrak | hack your own dist of clojure/core.clj might be easier, too |
| 12:10 | deg | I've not played with clojurescript at all. Do you happen to know where can I find the clojurescript analyzer source? |
| 12:11 | gtrak | not off-hand |
| 12:11 | gtrak | there are some projects that use it though |
| 12:11 | gtrak | https://github.com/jonase/kibit |
| 12:11 | deg | k, I'll poke around. Might be higher-level than the def'n of defn |
| 12:12 | andrewmcveigh | Isn't it here https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj ? |
| 12:13 | deg | thanks. I'll take a look at it. Off for a bit now while I put on my reading cap. |
| 12:13 | ohpauleez | deg: Kibit and Ambrose's analyzer should get you there |
| 12:14 | ohpauleez | https://github.com/jonase/eastwood, https://github.com/jonase/kibit, https://github.com/frenchy64/analyze |
| 12:14 | ohpauleez | deg: ^ |
| 12:14 | ohpauleez | eastwood is an example on how to use analyze |
| 12:14 | ohpauleez | but if you can match the forms, you can use kibit (see how cljx uses kibit) |
| 12:16 | deg | Thanks! |
| 12:16 | ohpauleez | np |
| 12:19 | antoineB | hello, for doing (map and [true true false]) i need to do (map #(and %1 %2) [true true false]), is there another way? |
| 12:20 | raek | antoineB: you don't want to do 'and' element wise, so 'map' is the wrong higher order function to use here |
| 12:20 | ohpauleez | antoineB: so you want to and the pairs? or and the whole thing? |
| 12:21 | ohpauleez | ,(apply and [true true false]) |
| 12:21 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0)> |
| 12:21 | raek | antoineB: your pattern seems to be 'reduce': (reduce and [true true false]) |
| 12:21 | ohpauleez | yes |
| 12:22 | joegallo | ,(every? identity [true true true]) |
| 12:22 | clojurebot | true |
| 12:22 | joegallo | ,(every? identity [true true false]) |
| 12:22 | clojurebot | false |
| 12:22 | raek | ('reduce' is what 'and' uses internally when given many arguments) |
| 12:22 | antoineB | and the whole thing |
| 12:22 | ohpauleez | yeah, i'd use identity |
| 12:23 | antoineB | raek: you are right i mistype, i want to use reduce |
| 12:23 | joegallo | every? has the benefit of returning false early even if you have very long seq of trues but a false at the beginning |
| 12:23 | raek | hrm, sorry. 'and' is not a function, so you can pass it to apply or reduce directly |
| 12:23 | joegallo | not sure if that's a concern for you |
| 12:23 | raek | ,(reduce #(and %1 %2) [true true false]) |
| 12:23 | clojurebot | false |
| 12:24 | raek | ,(macroexpand '(reduce #(and %1 %2) [true true false])) |
| 12:24 | clojurebot | (reduce (fn* [p1__135# p2__136#] (and p1__135# p2__136#)) [true true false]) |
| 12:24 | ohpauleez | expand more |
| 12:25 | raek | ,(macroexpand '#(and %1 %2) [true true false]) |
| 12:25 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$macroexpand> |
| 12:25 | raek | ,(macroexpand '#(and %1 %2)) |
| 12:25 | clojurebot | (fn* [p1__191# p2__192#] (and p1__191# p2__192#)) |
| 12:25 | raek | ,(macroexpand '(and %1 %2)) |
| 12:25 | clojurebot | (let* [and__2241__auto__ %1] (if and__2241__auto__ (clojure.core/and %2) and__2241__auto__)) |
| 12:25 | ohpauleez | ,(macroexpand-1 '(reduce #(and %1 %2) [true true false])) |
| 12:25 | clojurebot | (reduce (fn* [p1__245# p2__246#] (and p1__245# p2__246#)) [true true false]) |
| 12:25 | ohpauleez | ahh that's what I was looking for, thank you |
| 12:26 | ohpauleez | But yes, antoineB I'd use every? and identity |
| 12:26 | raek | anyway! you can't apply and, because it's a macro (and that would be like trying to apply 'if') |
| 12:26 | antoineB | every? is fine |
| 12:28 | antoineB | that seems bizar to see and implemented by an if |
| 12:28 | antoineB | logical, but bizar |
| 12:34 | gtrak | antoineB: of course it's logical! |
| 12:35 | gtrak | it's also not bizarre. and/or are short-circuiting in all languages I know of. |
| 12:35 | gtrak | the only way to short-circuit is with control-flow/branches/if |
| 12:36 | TimMc | and lambda-wrapping |
| 12:36 | gtrak | lambda-wrapping? |
| 12:36 | antoineB | bizar in sense of in other language it seen an operator implemented in the compiler not in the language |
| 12:36 | TimMc | but that requires "if" at some level for selection |
| 12:36 | gtrak | jump-tables are branches |
| 12:37 | TimMc | (if-fn true #(println "true") #(println "false")) |
| 12:37 | TimMc | (def if-fn [test then else] (if test (then) (else))) |
| 12:37 | gtrak | turtles |
| 12:38 | TimMc | (def if-fn [test then else] (if-fn test #(then) #(else))) :-P |
| 12:38 | gtrak | haha |
| 12:39 | gtrak | goto/branch/jump are fundamental |
| 12:39 | gtrak | I was thinking maybe lambda calculus has something to say about this, though? |
| 12:41 | gtrak | anyway it's a very useful construct on a von-neumann architecture |
| 12:42 | ForSpareParts | Have you guys ever seen an exception like this? "java.lang.ClassCastException: Cannot cast java.lang.Float to [F" |
| 12:42 | TimMc | Sure. [F is a float array. |
| 12:43 | TimMc | 25 cents on varargs. |
| 12:43 | ForSpareParts | TimMc, Thanks. I had no clue, and Google for [F is a non-starter. |
| 12:43 | gtrak | symbolhound? |
| 12:43 | ciphergoth | I can do (vec "foo") to turn a string into a vector of characters - what's the neatest way to go the other way? (clojure.string/join "" [\a \b])? |
| 12:44 | TimMc | gtrak: Doesn't help here. |
| 12:44 | gtrak | yea... was just about to say, that's unfortunate |
| 12:44 | TimMc | ciphergoth: apply str |
| 12:44 | ciphergoth | ForSpareParts: FWIW that's a Java thing, not a Clojure thing |
| 12:44 | TimMc | ciphergoth: Not exactly, it's a JVM thing. |
| 12:44 | ciphergoth | TimMc: indeed |
| 12:45 | ciphergoth | will have to get more used to making that distinction now I'm learning Clojure... |
| 12:46 | TimMc | And things in java.lang... are kind of both Java and JVM at the same time. |
| 12:46 | ForSpareParts | TimMc, So, this is a varargs issue, I believe. But how do I deal with that? I mean, AFAIK I'm passing in the types I want for the specific method overload I'm looking for. |
| 12:47 | TimMc | ~varargs |
| 12:47 | clojurebot | I don't understand. |
| 12:47 | maleghast | Evenin' All |
| 12:48 | maleghast | otfrom: You about, old bean? |
| 12:48 | maleghast | otfrom: (Don't worry not about to tap you up for extended support requests) |
| 12:48 | otfrom | maleghast: after a fashion |
| 12:49 | otfrom | pfft... so many better on this channel to get support from |
| 12:49 | maleghast | otfrom: OK, good - just wanted to ask you a question - will send prig message... |
| 12:49 | TimMc | clojurebot: varargs is a fiction of the Java compiler -- from Clojure, you'll need to pass in an array of the appropriate type. See into-array and float-array, etc. |
| 12:49 | clojurebot | c'est bon! |
| 12:50 | gtrak | fiction! lies! |
| 12:50 | TimMc | ForSpareParts: ^ |
| 12:51 | ForSpareParts | TimMc, scratch that, I was wrong. This isn't a varargs method -- I should've googled that term first. My bad. |
| 12:51 | gtrak | java is just an obfuscation over the C stdlib! burn them! |
| 12:51 | TimMc | Dammit, I lost 25 cents. |
| 12:51 | TimMc | What's the exchange rate with lazybot karma? |
| 12:52 | ciphergoth | OK style question: I have a list of things which are ether like [:a this that] or [:l this] or such like. Should they be vectors? Or something else, like tuples? |
| 12:52 | gtrak | hiccup is just like that |
| 12:52 | gtrak | (html [:div#foo.bar.baz "bang"]) |
| 12:53 | gtrak | what's a tuple? |
| 12:54 | maleghast | gtrak: http://en.wikipedia.org/wiki/Tuple |
| 12:54 | ciphergoth | what I'm looking for is the best way do to something like algebraic data types |
| 12:54 | TimMc | ciphergoth: I guess it depends on how you're going to use them. |
| 12:54 | ciphergoth | TimMc: clojure.core.match and dispatch on what sort I'm looking at |
| 12:54 | gtrak | records? |
| 12:54 | clojurebot | Records are (and, long ago, structs were) "advanced features", which can cause significant pain if you don't get all the subtleties. If you're using them to create "classes" because classes are awesome, then you are probably better off just using plain old hashmaps, possibly with a :type key if you want to be clear about what type they are. |
| 12:55 | AWizzArd | Ceshire users: (json/decode "{\"keyword_example\":1}" true) ==> {:keyword_example 1} is already supported. But can the following be done easier, without specifying this explicit FN? (json/decode "{\"keyword_example\":1}" #(keyword (.replaceAll ^String % "_" "-"))) ==> {:keyword-example 1} |
| 12:59 | pandeiro | is there an obvious way to create a 'singleton function', ie i have a fn used as a watch but i only want it to be called if it is not already 'running' from a previous invocation |
| 12:59 | gtrak | pandeiro: set a flag somewhere, like an atom |
| 12:59 | dakrone | pandeiro: defonce |
| 13:00 | SegFaultAX | dakrone: What? |
| 13:00 | pandeiro | gtrak: ok, thought of that, so the fn 'closes the door behind it' when it finishes |
| 13:00 | scriptor | not sure if defonce would be useful here |
| 13:00 | pandeiro | dakrone: didn't get how that would work |
| 13:00 | SegFaultAX | It's not even related to the question. |
| 13:01 | dakrone | SegFaultAX: pandeiro: hah, sorry, I misunderstood the question |
| 13:01 | pandeiro | dakrone: np |
| 13:01 | gtrak | pandeiro: yes. |
| 13:01 | joegallo | do you want other callers to block until the first call exits? |
| 13:01 | joegallo | or just pass through with no effect? |
| 13:01 | pandeiro | joegallo: right, i don't even want it to get called |
| 13:02 | pandeiro | i thought the atom solution was 'dirty' but i will go with it |
| 13:02 | SegFaultAX | pandeiro: For the record, this doesn't sound like a good idea. |
| 13:02 | pandeiro | it's literally my first time trying to implement a queue of sorts, no idea what i am doing really |
| 13:02 | pandeiro | SegFaultAX: i appreciate that :) |
| 13:02 | gtrak | pandeiro: if you want to make it cleaner, perhaps wrap the check/update in a lock |
| 13:02 | joegallo | if you want the calls to queue up, maybe you should be sending to an agent? |
| 13:03 | gtrak | serialize access to the atom, in other words |
| 13:03 | pandeiro | gtrak: right, not sure how though |
| 13:03 | pandeiro | joegallo: also very unfamiliar with using agents |
| 13:04 | gtrak | there's a convenient 'locking' utility, can lock on the atom or the var or whatever |
| 13:04 | gtrak | I've only used it once really... for serializing calls to a println |
| 13:05 | pandeiro | basically i have a singlular 'connection' and i want to take requests to use it but process them serially, while also 'sleeping' and automatically 'waking up' when there are requests to be processed |
| 13:05 | gtrak | pandeiro: that sounds like a perfect use-case for an agent |
| 13:05 | pandeiro | gtrak: i have been thinking that and reading about agents for the last few days and it just doesn't click in my head |
| 13:06 | pandeiro | i would send the request to the agent? |
| 13:06 | SegFaultAX | pandeiro: Sounds like you're implementing a blocking queue. |
| 13:06 | gtrak | an agent is a queue with a threadpool |
| 13:06 | gtrak | non-blocking though |
| 13:06 | pandeiro | SegFaultAX: i think i am, basically |
| 13:06 | joegallo | you really should probably look into agents more, just a suggestion |
| 13:06 | joegallo | seems like most of us think that, which you should probably take as a sign ;) |
| 13:07 | gtrak | pandeiro: if you want to block on the agent, you can use await or promise/deliver |
| 13:07 | gtrak | promise/deliver are implemented with CountdownLatch |
| 13:07 | TimMc | Agents are supposed to be value-oriented, and receive fns to operate on them. |
| 13:08 | TimMc | Maybe you want a queue + a while loop. |
| 13:08 | pandeiro | TimMc: that is what i was implementing just now |
| 13:08 | ForSpareParts | TimMc, I found my problem, by the way. I was being an idiot and giving the wrong arguments. |
| 13:08 | gtrak | TimMc: in my case the 'value' is the job store itself. If I want to wait on an intermediate value, I can do that in the function I send to the agent. |
| 13:08 | pandeiro | (while (peek (deref persistent-queue-atom)) (do-stuff ...)) |
| 13:08 | AWizzArd | So, 8 minutes after his question pandeiro got 29 different strategies. I guess this means that there is no obvious way to create a „singleton function” (-: |
| 13:09 | gtrak | I think it's analagous to datomic's single writer strategy, the value of the agent being the DB |
| 13:09 | pandeiro | AWizzArd: yes i can tag this question as answered :) |
| 13:09 | TimMc | What we need is a singleton strategy for creating singleton functions. |
| 13:09 | SegFaultAX | TimMc: :) |
| 13:10 | pandeiro | TimMc: the limitation i have with a queue + while loop is the 'sleep' and 'wake up' part |
| 13:10 | pandeiro | hence the original question |
| 13:10 | pandeiro | i could create a watch |
| 13:10 | gtrak | sleep and wake up bits are taken care of in the agent |
| 13:10 | TimMc | pandeiro: LinkedBlockingQueue |
| 13:11 | raek | pandeiro: you could do (def running (atom false)) (defn try-to-acquire [a] (compare-and-set! a false true)) (defn singleton-fn [f] (fn [& args] (when (try-to-acquire running) (try (apply f args) (finally (reset! running false)))))) |
| 13:12 | pandeiro | raek: that looks like a much more elegant way to do it dirty than i could've come up with |
| 13:12 | SegFaultAX | raek: Or you could use a monitor and locking, which is basically what you just tried to re-invent. :) |
| 13:12 | TimMc | pandeiro: Will it run forever? |
| 13:12 | raek | well, my version simply returns nil if the atom was "occupied" |
| 13:12 | pandeiro | TimMc: yes |
| 13:12 | raek | no blocking |
| 13:13 | SegFaultAX | raek: But he wants the calling thread to sleep (enqueue in the monitor) if it can't acquire the condition variable. |
| 13:13 | raek | ah, a lock then |
| 13:14 | SegFaultAX | I think. Actually he hasn't really described what he wants clearly other than using a meaningless term "singleton function" |
| 13:14 | raek | (or monitor) |
| 13:14 | TimMc | Oh, the caller needs to block? |
| 13:14 | pandeiro | singleton fn was specific to the implementation of using while and a persistent queue |
| 13:14 | pandeiro | the queue would be an atom with a watcher |
| 13:14 | SegFaultAX | pandeiro: That term isn't really a thing in this context. |
| 13:14 | gtrak | (let [p (promise)] (send my-agent (fn [val] (deliver p something) val) @p) |
| 13:14 | SegFaultAX | pandeiro: You just want a synchronized function. |
| 13:15 | TimMc | For some reason I imagined that this was async. |
| 13:16 | jsabeaudry | What do you use to do SVG in a noir context? Is analemma the recommended tool? |
| 13:18 | andrewmcveigh | jsabeaudry: I found using hiccup to generate the xml easier tbh. |
| 13:19 | raek | (defonce running (atom false)) (defonce running-monitor (Object.)) (defn singleton-fn [f] (locking running-monitor (while (compare-and-set! runngin false true) (.wait running-monitor))) (try (apply f args) (locking running-monitor (.notify running-monitor)))) |
| 13:20 | raek | sorry (defn singleton-fn [f] ... (try (apply f args) (finally (locking running-monitor (.notify running-monitor) (reset! running false))))) |
| 13:21 | pandeiro | gtrak: i pasted that (let...) in my REPL and locked myself out :) |
| 13:21 | gtrak | haha |
| 13:22 | gtrak | you can deref with a time-limit by the way |
| 13:22 | pandeiro | i really wish there were some concurrency materials for beginners dealing with real world scenarios |
| 13:22 | gtrak | I've used it to great effect in testing |
| 13:23 | raek | pandeiro: Java Concurrency in Practice is a really good book in the subject |
| 13:24 | pandeiro | raek: i've seen it mentioned, i will try to hunt it down |
| 13:24 | gtrak | CTMCP covers the async stuff pretty well |
| 13:24 | pandeiro | coming from JS my experience is all single threaded or async |
| 13:24 | pandeiro | i really don't see how to apply things like agents, promises, even futures |
| 13:24 | gtrak | http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695 |
| 13:25 | gtrak | JCIP was more gotchas building-blocks, CTMCP is cohesive mental-model stuff |
| 13:25 | raek | pandeiro: fyi, agents, promises and futures are not the basic building blocks. they are what Clojure add on top of the regular JVM features |
| 13:26 | raek | it's good to know something about what's in java.util.concurrent |
| 13:26 | pandeiro | raek: i see the roads all leading there, yeah |
| 13:27 | hiredman | b |
| 13:28 | raek | it feels nice that most stuff that Java Concurrency in Practice warns about can't happen in Clojure (it's a good guide to the j.u.c classes (even from a Clojure perspective) though) |
| 13:29 | raek | hrm. (defonce running (Object.)) (defn singleton-fn [f] (fn [& args] (locking running (apply f args)))) |
| 13:30 | raek | this, as well as the previous version, deadlocks on recursion though |
| 13:30 | gtrak | reentrantreadwritelock? |
| 13:30 | gtrak | or just RenetrantLock I guess |
| 13:31 | gtrak | Reentrant* |
| 13:32 | gtrak | if I remember correctly, JCIP says all the locks are built from http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/AbstractQueuedSynchronizer.html |
| 13:33 | gtrak | yea, in ReentrantLock there's a subclass: abstract static class Sync extends AbstractQueuedSynchronizer |
| 13:35 | gtrak | CountdownLatch, Semaphore, and Futures as well |
| 13:42 | daniel__ | I have a file src/backend/communication.clj and also a directory src/backend/communication |
| 13:42 | daniel__ | is that going to cause problems? |
| 13:42 | daniel__ | on requires/use |
| 13:43 | pandeiro | daniel__: no |
| 13:43 | raek | daniel__: no. |
| 13:43 | daniel__ | ah wait, think i found my problem |
| 13:43 | daniel__ | i move a file into communication but didnt change the ns |
| 13:43 | daniel__ | my cpu is at 130% |
| 13:45 | daniel__ | for some reason my repl wont launch, keeps timing out |
| 13:45 | daniel__ | lein repl that is |
| 13:46 | pandeiro | so i just need to read 811 pages and i will be able to implement this basic queue |
| 13:51 | daniel__ | any ideas why lein is consuming all my cpu? |
| 13:51 | gtrak | pandeiro: I think it's good to bring a certain fear to concurrency discussions. |
| 13:53 | pandeiro | gtrak: i have been avoiding it, really |
| 13:54 | pandeiro | but my current task involves interacting with a webapp in a headless browser using htmlunit, and the Rhino engine takes 15 seconds just to load it, on my machine |
| 13:54 | pandeiro | so either i learn to keep it loaded and queue my interactions with it, or i die of boredom |
| 13:58 | gtrak | why queue? why not synchronous? |
| 13:58 | gtrak | with callbacks and things |
| 13:59 | pandeiro | gtrak: hmm |
| 13:59 | gtrak | I see async and queues as a tearing apart of call stacks, a reifying of the ordering |
| 13:59 | gtrak | into a data structure |
| 14:00 | pandeiro | gtrak: not sure i see how else to do it |
| 14:00 | gtrak | not sure I get the details of it, then |
| 14:00 | pandeiro | server starts, instantiates connection, listens for requests and processes them with the single connection |
| 14:01 | pandeiro | the server could get two requests at the same time |
| 14:01 | gtrak | ah, it's in a different process? |
| 14:01 | pandeiro | no, it's in the same process now |
| 14:02 | pandeiro | i guess it makes sense to just set it up as an atom or something |
| 14:02 | pandeiro | is 'locking' to be used with atoms? |
| 14:03 | gtrak | so, here's what I do with agents, it might be relevant. The value of the agent is an object of some sort that represents a job store. I've created a protocol and extended it to a couple of custom types. I have functions that modify the job store, and I also have functions that perform side effects. The role of the agent in the side-effect case is only to guarantee ordering. |
| 14:04 | gtrak | so, to enqueue, I just send it a function. If I want some result, I deliver on promises within that function. |
| 14:04 | gtrak | If I want to read from the job store directly, I just use the value of the agent. |
| 14:05 | pandeiro | i follow everything but the delivering and promise part |
| 14:05 | pandeiro | the point of that is that it executes on another thread? or that it delays execution until necessary? |
| 14:05 | gtrak | yes, web requests come in and enqueue actions, which happen on the agent's thread pool. |
| 14:06 | gtrak | I don't want to block the web request unless I care about the result. |
| 14:06 | gtrak | promises are objects that you pass along. If you try to deref them, it will block your thread until another (only 1) delivers a value to them, then it returns the value. |
| 14:07 | gtrak | in CTMCP, they are described as dataflow variables along with futures |
| 14:07 | gtrak | they represent a value to be determined later |
| 14:08 | gtrak | so, when you hung your REPL, it was because you blocked the thread. |
| 14:08 | gtrak | In testing, everything I use has timeouts. |
| 14:08 | gtrak | agents also have the benefit of centralized error-handling. |
| 14:08 | gtrak | So, I've created a function that checks for errors during a test run, then rethrows the exception if any. |
| 14:09 | pandeiro | k this is starting to make sense |
| 14:10 | gtrak | futures decouple value from execution. Promises reify that into an object you can pass around. |
| 14:10 | gtrak | or rather, they decouple execution from the evaluation |
| 14:10 | gtrak | I think you can still pass around futures. |
| 14:11 | pandeiro | and there is no analog for 'deliver' with futures? |
| 14:11 | gtrak | but futures care about how they're executed, promises are just placeholders. |
| 14:11 | gtrak | nope |
| 14:11 | gtrak | futures manage their own threads, with java Futures you can pass an executor I think. |
| 14:12 | gtrak | with promises, you can use the agent's queue or whatever you want. |
| 14:12 | pandeiro | great, ok. thanks for the hand-holding :) |
| 14:12 | gtrak | a 'deliver' for futures is the return value of the thread-stack :-) |
| 14:13 | gtrak | promises decouple that |
| 14:13 | pandeiro | the abstractions make sense to me now |
| 14:14 | pandeiro | gtrak: i will probably share some code here tomorrow if you're around, see what monstrosity i come up with ;) |
| 14:28 | gtrak | pandeiro: sure, this stuff is still fun for me :-) |
| 14:31 | gtrak | I just find the reification of a thread stack as data to be helpful in understanding async. We do the same with lazy-seqs. |
| 14:31 | gtrak | an iteration is then a sequence of values. |
| 14:32 | gtrak | a tail-recursion is an iteration, etc.. |
| 14:33 | gtrak | data-dependency is expressed as return values, when decoupled, when the thread stack is split apart, it must be made explicit. |
| 14:42 | jamii | Does anyone know how to turn off the math symbols in emacs-live (lambda for fn etc) |
| 14:46 | TimMc | gtrak: Man, I bet you love continuations. |
| 14:47 | gtrak | I haven't done much with them yet, but in theory, yes :-) |
| 14:51 | gtrak | TimMc: stacks are poor man's gotos |
| 14:51 | TimMc | haha |
| 14:56 | mudge | how do I add a checkout dependancy to my project.clj file? |
| 14:57 | TimMc | mudge: You do it like a normal dependency as far as project.clj is concerned. |
| 14:57 | TimMc | then you add the symlink in ./checkouts/ |
| 14:57 | mudge | TimMc: the symlink goes to the root of the project I am depending on correct? |
| 14:58 | mudge | TimMc: in my project.clj file I have the project listed in dependancies like this: [im-client "0.1.0-SNAPSHOT"] does it have any group id? or just artifact that is the project name? |
| 15:01 | gfredericks | what's the latest clojure version? |
| 15:02 | TimMc | mudge: I think the ID group defaults to the artifact ID. |
| 15:03 | TimMc | mudge: Right, you'd have a symlink like ~/repos/foo/checkouts/bar -> ~/repos/bar/ |
| 15:04 | mudge | TimMc: thanks. So I created a checkouts directory and put in a symlink to the root of the project I depend on and put the dependancy in my project.clj file. However when I run lein compile, it says that the artifact is not found in maven or clojars |
| 15:05 | TimMc | gfredericks: 1.4.0, I believe. |
| 15:05 | mudge | not found in maven or clojars repositorys. |
| 15:06 | TimMc | gfredericks: http://search.maven.org/#search|gav|1|g%3A%22org.clojure%22%20AND%20a%3A%22clojure%22 |
| 15:06 | raek | mudge: the dependency needs to exist first. one quick solution is to run 'lein install' in the dependency project |
| 15:06 | gfredericks | TimMc sonatype has 1.5.0-beta1 |
| 15:07 | TimMc | gfredericks: Sure, but that's not a release. |
| 15:07 | gfredericks | why is lein run -m foo.bar/baz not working for me? it says class not found |
| 15:07 | gfredericks | I thought you could call a specific var with lein run |
| 15:07 | hiredman | gfredericks: have you tried loading foo.bar in a repl? |
| 15:07 | TimMc | I remember someone having trouble with that feature. |
| 15:07 | gfredericks | nope :) |
| 15:08 | hiredman | I guess it will throw an error |
| 15:08 | mudge | raek: do you mean that the dependacy needs to be in the local repository? |
| 15:08 | gfredericks | indeed it does |
| 15:08 | hiredman | of course not the class not found error, but some other error that lein is swallowing |
| 15:08 | Sgeo | Using a global atom containing a map. |
| 15:08 | gfredericks | hiredman: thanks! |
| 15:09 | Sgeo | Wait, that idea does not work as intended. |
| 15:09 | Sgeo | And I _just_ realized it now |
| 15:09 | mudge | when I make a checked out dependancy, does the dependancy have to be in the local maven repository? |
| 15:09 | raek | mudge: it needs to be in some repository |
| 15:09 | mudge | raek: i see, I didn't know that |
| 15:09 | frawr | Hi, I'm trying the enfocus exawple, but they don't seew to work, the interposed alerts do though. what might be some common pitfalls? |
| 15:10 | mudge | raek: I have two projects and one project depends on the other. So should I put the project that is depended on into the local repository? |
| 15:10 | TimMc | raek: I didn't know that either. :-/ |
| 15:10 | raek | mudge: yes |
| 15:10 | raek | mudge: or start with one project and split them later |
| 15:10 | mudge | I thought the point of checked out dependacies was so that you didn't have to continually update your repository when you are working on two projects at the same time |
| 15:11 | raek | yes. you only need to install it locally once |
| 15:11 | mudge | raek: but what happens if I make changes to the dependancy project, don't I then have to update the repository? |
| 15:12 | raek | I think checkouts is more useful for testing bugfixes in dependencies than for hacking on an unreleased project and an unrelease library at the same time |
| 15:12 | raek | mudge: no |
| 15:13 | raek | mudge: lein will use any dependency information from the version in the repo, but the source code can be updated |
| 15:13 | mudge | raek: Okay, I think I understand then. So I put the dependacy in the project.clj, but lein doesn't look there for that project, it looks at the project via the symlink in checkouts directory |
| 15:14 | mudge | raek: does that sound right? |
| 15:14 | raek | well, it does look for the version it finds in the project.clj |
| 15:15 | raek | if I recall correctly it just puts the src/ of the checkout dependency first in the classpath (which overrides the repo version) |
| 15:15 | raek | well, this would be clear from the output from 'lein classpath' |
| 15:15 | mudge | raek: thanks |
| 15:17 | mudge | I'm confused by another thing. I know want to put my project into the local repository and so I looked at the command lein install. The documentation says that lein install puts your project into the local repository, but when I ran it, it just wrote a pom file and jar to the target directory of the project |
| 15:17 | mudge | Isn't lein install supposed to put your project into the local repository? |
| 15:17 | raek | mudge: it isn't in your ~/.m2/ directory? |
| 15:18 | mudge | raek: I checked, and it is in my local repository --- lein install just didn't tell me that it put it there. sorry, it works |
| 15:20 | TimMc | I don't think there's any good reason that lein needs a jar somewhere for the dependency -- it's just a quirk of the system. |
| 15:21 | raek | yeah |
| 15:22 | TimMc | Maybe someone can make a patch to plumb checkout deps info through the deps downloading code. |
| 15:28 | mudge | I am still getting a classNotFoundException with my checkout dependancy, I checked the classpath and the class is in the path |
| 15:29 | raek | mudge: what is the name of the namespace and how do you require it? |
| 15:31 | mudge | raek: this is the namespace: com.perfectabstractions.im-client.components.ImComponent |
| 15:31 | TimMc | That hy[hen looks like trouble. |
| 15:31 | raek | are you generating classes or is that last segment a namespace? |
| 15:32 | mudge | raek: I import it in :import like this: (com.perfectabstractions.im-client.components ImComponent) |
| 15:32 | mudge | (ns (import: (com.perfectabstractions.im-client.components ImComponent))) |
| 15:32 | mudge | (ns mynamespace (import: (com.perfectabstractions.im-client.components ImComponent))) |
| 15:32 | raek | it should be ":import" |
| 15:32 | mudge | raek: yes, sorry, it is :import |
| 15:33 | raek | and the directory should be called im_client if the namespace segment is called im-client |
| 15:33 | mudge | raek: right, it is im_client |
| 15:33 | raek | mudge: are you using gen-class? |
| 15:33 | mudge | raek: yes I am |
| 15:33 | mudge | raek: i'll put the code in a gist |
| 15:34 | raek | then I think you need to compile that namespace first (I'm not very sure about the details since I haven't used gen-class much) |
| 15:34 | mudge | raek: https://gist.github.com/4041394 |
| 15:35 | mudge | raek: yes, that namespace has been compiled |
| 15:35 | raek | hrm. maybe this is one of these cases when you need to use an underscore in Clojure |
| 15:35 | mudge | raek: well I'll try it |
| 15:35 | raek | since you're using Java interop to access the generated class |
| 15:36 | raek | (:import (com.perfectabstractions.im_client.components ImComponent)) |
| 15:36 | mudge | raek: oh my gosh, yes that is it |
| 15:36 | mudge | raek: this works: (:import (com.perfectabstractions.im_client.components ImComponent) |
| 15:36 | mudge | with the underscore like you said |
| 15:37 | raek | ok, great! |
| 15:37 | mudge | yea! |
| 15:37 | mudge | thanks very much for your help |
| 15:37 | raek | np. :) |
| 15:37 | moogatronic | Emacs/nrepl question: Is there a way to re-start a jacked-in nrepl session? In the past, with swank, reissuing clojure-jack-in would kill and restart. I've tried killing the nrepl buffers, but I can never seem to re-establish a working repl. |
| 15:39 | technomancy | moogatronic: killing *nrepl-server* and re-running M-x nrepl-jack-in works for me |
| 15:40 | moogatronic | When i do that, and try to re-compile a class, I get "Namespace not found" |
| 15:41 | moogatronic | it seems to start the repl just fine however. |
| 15:41 | brainproxy | when spec'ing metadata map for (def ...) is there any difference in using #^{...} vs ^{} |
| 15:42 | moogatronic | weird. I just switched to repl, and issued (in-ns 'the-namespace), switched back to the buffer, and C-c C-k and it worked. |
| 15:42 | raek | brainproxy: ^{} is the pre-Clojure 1.2 syntax |
| 15:43 | raek | sorry, there reverse! |
| 15:43 | brainproxy | okay |
| 15:43 | raek | man. |
| 15:43 | raek | ^{} is what you use these days |
| 15:43 | brainproxy | cool... both seem to work w/ clojure 1.4 |
| 15:52 | piranha | I have strange situation: some code works in REPL when I execute it, but when I do same in tests, it does not work |
| 15:53 | piranha | and I really can't understand what's going on there... any clues? maybe some insights? I'll post some example soon |
| 15:54 | piranha | ah |
| 15:54 | piranha | I'm sorry |
| 15:54 | piranha | for + repl are doing strange things sometimes |
| 15:54 | moogatronic | Example code? |
| 15:54 | raek | for returns values as a lazy seq. the for body is not evaluated until needed. |
| 15:54 | piranha | yes |
| 15:54 | raek | use 'doseq' if you're after the side-effects |
| 15:54 | amalloy | don't use for to do side effects |
| 15:55 | piranha | and in repl it's evaluated because I see return value :) |
| 15:55 | raek | exactly. :) |
| 15:55 | piranha | yes, I know, I just need to get used to that :) |
| 15:55 | piranha | it's already second time for a week when it brings me almost to panic :)) |
| 16:02 | TimMc | I wonder if there's a kibit rule for hyphens in :import package names. |
| 16:07 | daniel__ | can't i include a namespace (use 'backend.communication.zmq) which has a defrecord and then reference that defrecord in the repl? |
| 16:08 | daniel__ | user=> (extends? CommunicationProtocol ZeroMQ) 9 (close [context] nil)) │CompilerException java.lang.RuntimeException: Unable to resolve symbol: ZeroM |
| 16:11 | TimMc | daniel__: I think you need to also import the class the defrecord created. |
| 16:11 | TimMc | This was certainly true in 1.2. |
| 16:12 | daniel__ | thanks, works :D |
| 16:13 | uvtc | I was just looking at the docs for `letfn`, and it appears to be a shortcut for using `let` with func names and `(fn ...)`. But looking at `(source letfn)`, the impl uses `letfn*`. But I can't find the docs for `letfn*` in the repl nor at <http://clojure.github.com/clojure/>. |
| 16:14 | uvtc | And the repl tells me there *is* no `letfn*`: unable to resolve symbol. |
| 16:14 | uvtc | Is there a `letfn*`, or am I not understanding the macro in the source for `letfn`? |
| 16:14 | raek | uvtc: 'letfn*' is a special form. it is implemented in the compiler. |
| 16:15 | TimMc | &#'clojure.core/letfn* |
| 16:15 | lazybot | java.lang.RuntimeException: Unable to resolve var: clojure.core/letfn* in this context |
| 16:15 | raek | so there is not letfn* var |
| 16:15 | TimMc | Oh, OK. |
| 16:15 | raek | (like there is no 'if' var) |
| 16:15 | TimMc | I guess letfn has to have compiler support. |
| 16:16 | uvtc | Oh. Hm. Ok. Thanks, raek. I suppose then that I'll have to look in the source for the docs on `letfn*`. |
| 16:17 | raek | I suspect 'letfn*' relates to 'letfn' as 'fn*' relates to 'fn' |
| 16:17 | pjstadig | i believe its because the fns are all aware of each other |
| 16:17 | pjstadig | like you can reference one of the later fns in an earlier fn |
| 16:18 | uvtc | Oh, ok. Thank you. :) |
| 16:18 | daniel__ | user=> (def foo (ZeroMQ. "test" "test")) │#'user/foo |
| 16:19 | daniel__ | so i instantiated my defrecord, how do i call methods on it? |
| 16:19 | raek | daniel__: you use the protocol functions (which you require/use like ordinary functions) |
| 16:19 | daniel__ | raek, where do i require/use them from |
| 16:20 | pjstadig | in the ns form where you want to use them |
| 16:20 | daniel__ | i want to use them in the repl for now |
| 16:21 | raek | then you use the 'require' or 'use' functions |
| 16:21 | daniel__ | i have foo which is an instantiated protocol: user=> (def foo (ZeroMQ. "test" "test")) │#'user/foo |
| 16:21 | raek | (and quote the argument) |
| 16:21 | raek | daniel__: in what ns does the protocol live? |
| 16:21 | daniel__ | the defprotocol lives in backend.communication and the defrecord lives in backend.communication.zmq |
| 16:22 | pjstadig | (use '[backend.communication :only [THE-FUNCTION]]) |
| 16:22 | pjstadig | (THE-FUNCTION foo) |
| 16:22 | raek | then you need to do something like (require '[backend.communication :as comm] 'backend.communication.zmq) (import 'backend.communication.zmq.ZeroMQ) |
| 16:23 | raek | (comm/protocol-method foo arg1 arg2) |
| 16:23 | daniel__ | i see, so the protocol is the function and i pass it the implementation |
| 16:24 | daniel__ | (protocol-method implementation ... ) |
| 16:24 | raek | precisely |
| 16:29 | jweiss | what's the shortest path to making all print-method output readable by the reader? overriding print-method or using the extensible reader? i'm not too concerned about exactly how things are read in, just as long as it reads something |
| 16:31 | daniel__ | user=> (require '[backend.communication :as comm] 'backend.communication.zmq) |
| 16:31 | daniel__ | user=> (import 'backend.communication.zmq.ZeroMQ) |
| 16:31 | daniel__ | user=> (comm/receive (ZeroMQ. "test" "test") "test") |
| 16:31 | daniel__ | CompilerException java.lang.IllegalArgumentException: No single method: receive of interface: backend.communication.CommunicationProtocol found for functisrc/backend/communication/zmq.clj on: receive of protocol: CommunicationProtocol, compiling:(NO_SOURCE_PATH:1) |
| 16:32 | hiredman | daniel__: pastebin |
| 16:32 | daniel__ | should just return "test" |
| 16:32 | daniel__ | http://pastebin.com/USQfhKGC |
| 16:34 | raek | daniel__: and the ZeroMQ type/record implements the protocol? |
| 16:35 | daniel__ | yeah |
| 16:35 | daniel__ | wait, ill paste both bits of code |
| 16:36 | daniel__ | https://gist.github.com/4041813 |
| 16:36 | daniel__ | im just testing receive at the moment, it should just return it's argument |
| 16:37 | raek | hrm, I can't see anything odd |
| 16:37 | raek | wait |
| 16:38 | raek | daniel__: in the protocol (and the implementation) the function takes one arg, but you give it two |
| 16:38 | raek | you need to include the "this" argument in the protocol |
| 16:38 | daniel__ | but the defrecord takes two arguments |
| 16:38 | raek | oh wait, you did that |
| 16:38 | daniel__ | receive takes 1 |
| 16:38 | raek | daniel__: send indeed takes two args, but receive takes 1 |
| 16:39 | raek | and you pass reveive 2 |
| 16:39 | raek | *receive |
| 16:39 | raek | the instance and the string "test" |
| 16:39 | raek | try (comm/receive (ZeroMQ. "test" "test")) |
| 16:39 | raek | it should return the ZeroMQ instace |
| 16:40 | daniel__ | this gives me #backend.communication.zmq.ZeroMQ{:context "test", :package "test"} |
| 16:40 | daniel__ | what do i do with that? |
| 16:40 | raek | daniel__: but that's what you wrote in (defrecord ZeroMQ ... (receive [context] context) ...) |
| 16:41 | raek | the receive method, when invoked on a context, returns the context |
| 16:41 | daniel__ | ok, thats not what i intended |
| 16:41 | daniel__ | i intended that it would just return "test" since this is what i passed in as context |
| 16:42 | daniel__ | i think i fundamentally mistunderstand something |
| 16:42 | raek | oh, I see |
| 16:42 | raek | daniel__: you have too "context" variables in your code |
| 16:42 | raek | one is the record field |
| 16:42 | raek | the other is the first argument to the methdo |
| 16:42 | daniel__ | yeah, it gets passed through as the argument? |
| 16:42 | daniel__ | i thought the methods would wrap their context in a closure |
| 16:43 | raek | yeah, the first argument is the "this" object |
| 16:44 | raek | daniel__: let's rename the "receive" argument: (defrecord ZeroMQ [context package] (receive [context2] context2) ...) |
| 16:44 | raek | does it make sense now? |
| 16:44 | daniel__ | the first argument to defrecord is this? |
| 16:44 | daniel__ | not really |
| 16:44 | daniel__ | :( |
| 16:45 | daniel__ | whatever i pass through to defrecord should be used in each of the methods |
| 16:45 | raek | if you have (defprotocol FooProto (foo-method [a b c])) |
| 16:45 | daniel__ | i intended for these contexts to be the same |
| 16:45 | raek | and (defrecord BarRec [x y] FooProto (foo-method [a b c] ...)) |
| 16:46 | raek | when you call (def bar (BarRec. 1 2)) (foo-method bar 3 4) |
| 16:46 | daniel__ | bar is passed to foo-method as a |
| 16:46 | daniel__ | i get it |
| 16:46 | raek | then you have x=1, y=2, a=<BarRec object with x=1, y=2>, b=3, and c=4 |
| 16:47 | raek | since you have access to the fields of the record implicitly, it's common to structure the code like this: (defrecord ZeroMQ [context package] ... (receive [_] context) ...) |
| 16:48 | daniel__ | ok, let me give this a try |
| 16:48 | daniel__ | thanks |
| 16:49 | raek | the field "context" and the first argument to the protocol functions can never be the same |
| 16:49 | raek | I mean, one is a part of the other |
| 16:50 | raek | it would be like having a vector [a b] and call it a |
| 16:53 | daniel__ | yaaay, got it working |
| 16:55 | daniel__ | so in the defprotocol, the first argument i give the methods needs to be 'this' |
| 16:55 | daniel__ | so instead of (receive [context] it should be (receive [this context] ? |
| 16:56 | daniel__ | in the defrecord it seems to work with one argument, as long as ignore it (receive [_] context) |
| 16:56 | romanandreg | hey do you know if the semantics of subvecs in cljs are different from the ones of clojure on purpose? |
| 16:56 | dnolen_ | romanandreg: what's the issue? |
| 16:57 | tomoj | anyone seen an ":protocol/unsupported Unsupported protocol :ddb" error from datomic? |
| 16:57 | romanandreg | dnolen_: in cljs `(subvec [1 2 3 4] 0 30)` => [1 2 3 4 nil nil nil …] |
| 16:57 | romanandreg | dnolen_: in clojure… IndexOutOfBound exception |
| 16:58 | daniel__ | its a bit like explicit self in python methods |
| 17:00 | daniel__ | i dont quite see why having this is ever useful? |
| 17:00 | daniel__ | having 'this' |
| 17:00 | daniel__ | (defprotocol Proto (meth [this arg1 arg2])) |
| 17:00 | daniel__ | when am i going to want to have this inside the method? |
| 17:01 | daniel__ | how is that useful? |
| 17:01 | dnolen_ | romanandreg: no explicit reason that I'm aware. patch welcome of course. |
| 17:02 | romanandreg | dnolen_: I'm wondering if doing the check would incur in performance issues |
| 17:03 | dnolen_ | romanandreg: not sure how since vectors keep track of their count. |
| 17:03 | dnolen_ | romanandreg: very likely an oversight - that's all. |
| 17:03 | tomoj | daniel__: suppose for example that you extend a protocol to String. how could the protocol function impl do anything useful without access to the String itself? |
| 17:04 | romanandreg | dnolen_: awesome… yes, we'll try to have one ready soonish, one of our test broke (port from clojure to clojurescript) because of this fact (yay testing!) |
| 17:05 | dnolen_ | romanandreg: seems likes a simple patch too - subvec just doesn't check bounds at the moment. |
| 17:07 | amalloy | aw man. i wrote subvec |
| 17:07 | daniel__ | ok tomoj, are there any examples of protocols extending strings? |
| 17:07 | daniel__ | i think a real world example or two might help me get my head around it |
| 17:11 | tomoj | well, there are plenty of other cases where you want this |
| 17:11 | tomoj | here's one example from core.cljs https://www.refheap.com/paste/037765df5f84e7ae012b27e8e |
| 17:11 | tomoj | you need this to be able to tell whether it's equal to other for IEquiv |
| 17:13 | daniel__ | thanks tomoj, bookmarked |
| 17:13 | daniel__ | gunna call it a night |
| 17:14 | tomoj | `mvn install` in datomic-pro seems to not work |
| 17:14 | tomoj | but `mvn install:install-file -Dfile=...jar -DpomFile=pom.xml` does |
| 17:15 | tomoj | I guess that is not surprising |
| 17:45 | pendlepants | can someone tell me what the idiomatic way would be to share a db instance across a clojure app? |
| 17:46 | pendlepants | so if I'm using something like korma where am I putting my defdb and entities definitions, and am I just using require to share those throughout the app? |
| 17:49 | ivan | I would pass the db around into everything, regardless of what other people's macros are encouraging |
| 17:55 | bosie | i just switched to vimclojure (in vim, ofc). is there a way to go to the fucntion definition somehow? |
| 17:56 | ToBeReplaced | pendlepants: i was bothered by that too... you can avoid it by not defdb and instead passing around your connections to your entities |
| 17:56 | ToBeReplaced | pendlepants: for me, i ended up scrapping it and using java.jdbc and c3p0 directly |
| 17:57 | ToBeReplaced | way to parse the cookies out of a ring-response? i'm assuming there's something in clj-http but i can't seem to find it |
| 17:58 | pendlepants | thanks, ivan/ToBeReplaced. I'll try it out w/o korma. |
| 17:58 | ToBeReplaced | for when response is ... :headers {"Set-Cookie" ("ring-session=yaddayadda")} |
| 17:58 | ivan | my korma is patched to take a pool created by bonecp |
| 17:59 | ivan | haven't used it much other than to confirm it works |
| 18:00 | ibdknox | fwiw, I've been looking for someone who has a vested interest in SQL to take Korma over |
| 18:00 | ibdknox | I simply don't have time for it, especially given that I don't see in any SQL work in my future anytime soon |
| 18:01 | ToBeReplaced | yeah; it seems like a high-maintenance project |
| 18:01 | ibdknox | not overly |
| 18:01 | ibdknox | There's not really *that* much that needs to happen to appease just about everyone |
| 18:02 | wingy | is there a way to stop jetty server programmatically? |
| 18:02 | tomoj | ToBeReplaced: clj-http.cookies/wrap-cookies ? |
| 18:02 | wingy | is start it using (run-jetty #'handler {:port port :join? false}) |
| 18:03 | tomoj | wingy: call .stop on the return value of that, iirc |
| 18:03 | wingy | ok |
| 18:03 | tomoj | if you lost the return value, I think you have to kill the jvm :( |
| 18:03 | ToBeReplaced | wingy: def it before you start it, then .stop your-symbol |
| 18:04 | wingy | tomoj ToBeReplaced: so it returns a java object? |
| 18:04 | wingy | i think i should use an atom here |
| 18:04 | ToBeReplaced | wingy: yes |
| 18:08 | ToBeReplaced | tomoj: yes that's it, if you also use wrap-lower-case-headers, thanks |
| 18:12 | wingy | does this look ok: (swap! server #(run-jetty #'handler {:port port :join? false})) |
| 18:12 | wingy | im starting the server and updates the atom in the same time |
| 18:14 | bbloom | wingy: you can use reset! if you don't need the prior value of server |
| 18:14 | bbloom | ,(let [a (atom 1)] (reset! a 2) a) |
| 18:14 | clojurebot | #<Atom@542c47d7: 2> |
| 18:15 | wingy | yeah it worked thx |
| 18:16 | gtrak | wingy, teh problem with the first is the atom's value is getting passed in as an arg, though you haven't used it anywhere. It won't work. |
| 18:16 | wingy | yepp i noticed |
| 18:21 | wingy | what is weird is that i get "No matching field found: stop for class clojure.lang.Atom" when i try to stop the jetty server with (.stop server) |
| 18:21 | gtrak | deref |
| 18:22 | wingy | i updated the atom using (reset! server #(run-jetty #'handler {:port port :join? false})) |
| 18:22 | wingy | ah |
| 18:22 | egghead | does anyone use paredit with slime/nrepl? how can I make a newline without it submitting :( |
| 18:22 | technomancy | egghead: C-o should work |
| 18:23 | TimMc | Does C-q help? |
| 18:23 | TimMc | wait, nvm |
| 18:23 | wingy | gtrak: you mean (.stop @server) |
| 18:23 | egghead | ah thanks guys |
| 18:23 | gtrak | yes |
| 18:23 | gtrak | the atom evals to itself, vars eval to what they point to |
| 18:24 | egghead | i'm a paredit noob, I only use it for killing expressions and balancing parens |
| 18:24 | gtrak | symbols rather |
| 18:24 | gtrak | symbols eval to var lookups |
| 18:24 | wingy | I get No matching field found: stop for class clojure.lang.PersistentArrayMap |
| 18:24 | gtrak | wingy: perhaps run-jetty returns a map |
| 18:24 | wingy | (def server (atom {})) |
| 18:25 | amalloy | egghead: C-j |
| 18:25 | gtrak | hmm? did your reset never happen then? |
| 18:25 | wingy | my reset did happen |
| 18:26 | wingy | here is my code: https://www.refheap.com/paste/6494 |
| 18:29 | wingy | a better one: https://www.refheap.com/paste/6495 |
| 18:31 | wingy | ToBeReplaced: do you know why i can't call .stop on the returned server? |
| 18:34 | ToBeReplaced | you didn't reset the server in your refheap |
| 18:34 | ToBeReplaced | you used a multimethod, and followed the second path |
| 18:34 | ToBeReplaced | oh config somewhere nvm |
| 18:41 | ToBeReplaced | wingy: issue resolved yet? why the reader macro in the reset! ? |
| 18:41 | wingy | ToBeReplaced: what reader macro? |
| 18:41 | wingy | i can't get stop working yet |
| 18:45 | ToBeReplaced | wingy: take the # off of (reset! server #(yadda)) |
| 18:45 | wingy | ToBeReplaced: but that creates an anonymous fn |
| 18:45 | wingy | hm |
| 18:46 | ToBeReplaced | i don't know if you can set an atom to an anonymous function, but either way, it's not what you're trying to do |
| 18:49 | bosie | how do you guys debug clojure, preferably with vim? |
| 18:50 | wingy | ToBeReplaced: wohoo worked |
| 18:54 | Somelauw | bosie: I use tslime + tmux |
| 18:55 | mattmoss | &(let [x (atom nil)] (reset! x #(+ 3 4)) x) |
| 18:55 | lazybot | ⇒ #<Atom@5d3011: #<sandbox7657$eval476836$fn__476837 sandbox7657$eval476836$fn__476837@aa003d>> |
| 18:55 | mattmoss | &(let [x (atom nil)] (reset! x #(+ 3 4)) @x) |
| 18:55 | lazybot | ⇒ #<sandbox7657$eval476858$fn__476859 sandbox7657$eval476858$fn__476859@a56d69> |
| 18:55 | Somelauw | and I actually think it is elegant that way, but emacs people tell me it is not a real repl |
| 18:56 | mattmoss | You can put a fn in an atom w/ reset!, but it doesn't eval the func. |
| 18:56 | mattmoss | &(let [x (atom nil)] (reset! x #(+ 3 4)) (@x)) |
| 18:56 | lazybot | ⇒ 7 |
| 18:57 | mattmoss | However... |
| 18:58 | mattmoss | &(let [x (atom nil)] (swap! x (fn [_] (+ 3 4))) @x) |
| 18:58 | lazybot | ⇒ 7 |
| 20:04 | bbloom | dnolen: ping |
| 20:13 | holo | hi! |
| 20:14 | egghead | hi holo |
| 20:17 | holo | what is the name of that app hosted on heroku accounting the number of clojure library instances for each library being used at the moment? |
| 20:18 | brehaut | http://www.clojuresphere.com ← holo |
| 20:19 | holo | ha yes! that's it.. thanks brehaut |
| 20:19 | tomoj | grr https://www.refheap.com/paste/6fcd5e37b489c0e08f9a20ec7 |
| 20:20 | tomoj | oh, that was fixed 2 months ago |
| 20:23 | holo | hey! i'm going to be the first one using metis.. |
| 20:24 | tomoj | coincidence? "inspired by Active Record Validations" |
| 20:29 | holo | >.> |
| 21:19 | tomoj | dakrone: thanks! |
| 21:19 | dakrone | tomoj: no problem! (for what?) |
| 21:19 | tomoj | the cheshire fix |
| 21:20 | dakrone | tomoj: :) thanks for finding it, silly mistake on my part |
| 21:57 | bbloom | if i never see an enum again, it will be too soon |
| 21:57 | bbloom | #{:mmmm :set :of :keywords} |
| 21:57 | nightfly_ | yes, keywords for the win |
| 21:58 | bbloom | blows my mind when i see java files that have a big enum up top, then repeat every key to add it so some map for dynamic dispatch, then have a setter and getter for every key, then have another map for converting them to strings |
| 21:59 | bbloom | it's crazy how much work you need to do to get something half as useful as print and read |
| 21:59 | bbloom | and assoc :-) |
| 22:00 | Sgeo | bbloom, what about Haskell data types with several constructors which each take 0 arguments? |
| 22:00 | bbloom | I don't know enough Haskell to comment, but I do remember thinking "instance Show" wtf? |
| 22:01 | shachaf | instance Show? |
| 22:01 | bbloom | shachaf: show is sorta like print |
| 22:02 | shachaf | bbloom: Yes, I know. |
| 22:02 | Sgeo | bbloom, you can tell Haskell to try to automatically make an instance of Show |
| 22:02 | shachaf | What's the context? |
| 22:02 | bbloom | Sgeo: like i said, i don't know much haskell |
| 22:02 | bbloom | i just know i <3 keywords :-) |
| 22:14 | ChongLi | the crazier thing is Haskell's Read |
| 22:16 | ChongLi | read :: Read a => String -> a |
| 22:16 | shachaf | What's crazy about Read? |
| 22:16 | ChongLi | that it's polymorphic on a value rather than an argument |
| 22:17 | shachaf | Oh, well, sure. |
| 22:17 | ChongLi | a lot of languages can't do that |
| 22:17 | shachaf | You can take a simpler example: class Bounded a where minBound, maxBound :: a |
| 22:17 | shachaf | minBound :: Int = -9223372036854775808, etc. |
| 22:17 | ChongLi | yeah that's pretty weird too |
| 22:19 | ChongLi | I wish there were some way to do that in Clojure |
| 22:19 | ChongLi | would make monads easier |
| 22:20 | shachaf | It's a bit tricky with dynamic types. :-) |
| 22:20 | ChongLi | yeah it's one of those tradeoffs |
| 22:20 | ChongLi | like the tradeoff between currying and arity overloading |
| 22:21 | shachaf | Speaking of crazy things in Haskell, there's Text.Printf. |
| 22:22 | ChongLi | yeah, a crazy hack |
| 22:22 | ChongLi | haha |
| 22:22 | brehaut | also HLists |
| 22:23 | shachaf | Pft, HList is too easy with modern GHC extensions. |
| 22:24 | shachaf | data HList :: [*] -> * where { Nill :: HList '[]; Cons :: t -> HList ts -> HList (t ': ts) } |
| 22:24 | shachaf | s/ll/l/ |
| 22:24 | shachaf | Cons True (Cons 'a' (Cons "hi" Nil)) :: HList '[Bool, Char, String] |
| 22:25 | ChongLi | hmm that's weird |
| 22:26 | brehaut | kids these days with their modern extensions. |
| 22:27 | ChongLi | the type system has gotten pretty crazy with them |
| 22:27 | shachaf | Way too crazy. |
| 22:27 | shachaf | I like my type system simple, like Agda's. |
| 22:27 | brehaut | O_o |
| 22:33 | bbloom | I'm not sure that dynamic is what makes return type polymorphism hard, i think it's laziness |
| 22:33 | bbloom | lisps choose configurable laziness: functions vs macros |
| 22:33 | bbloom | where as haskell chooses always lazy, but you can't get the ast |
| 22:33 | brehaut | bbloom: qi weakens your argument |
| 22:33 | shachaf | I don't think you mean the same thing by "laziness" that Haskell people do... |
| 22:34 | ChongLi | how do you know which function to dispatch to if you don't know the type? |
| 22:34 | bbloom | sorry, brb |
| 22:35 | brehaut | ChongLi: how do protocols work? |
| 22:35 | ChongLi | they dispatch on the type of an argument |
| 22:35 | brehaut | right, so a dynamic typed language can do that just fine; it just has to do it at runtime |
| 22:35 | ChongLi | but with return type polymorphism you don't know the type |
| 22:35 | shachaf | Yes, but that's not what we're talking about here. |
| 22:35 | shachaf | maxBound :: Word8 -- 255 |
| 22:36 | shachaf | maxBound :: Word16 -- 65535 |
| 22:36 | shachaf | That thing isn't a function at all. It's just a value. |
| 22:36 | ChongLi | yeah |
| 22:36 | ChongLi | it's set at compile time when the type is inferred |
| 22:36 | shachaf | ChongLi: Or at runtime. |
| 22:36 | brehaut | every method in the jvm has a return type; yes, those functions have no arguments but it doesnt mean the information is not available |
| 22:36 | shachaf | Sometimes you can't figure it out at compiletime. |
| 22:37 | ChongLi | if it can't be determined at compile time, doesn't haskell give an ambiguous type error? |
| 22:38 | shachaf | Not necessarily. The constraints will just be propagated. |
| 22:38 | ChongLi | ambiguous type variable |
| 22:38 | ChongLi | right |
| 22:38 | ChongLi | but if it never converges to a type somewhere down the line, it is ambiguous |
| 22:39 | shachaf | Sure, but you can compile a function that uses a Bounded on its own. |
| 22:40 | shachaf | And in practice in the compiled code minBound might turn into a function instead of a constant. But that doesn't really matter. |
| 22:40 | ChongLi | sure, but the result will still be based on whatever types are inferred |
| 22:40 | ChongLi | at compile time |
| 22:40 | shachaf | Right, eventually. |
| 22:40 | ChongLi | all of the type information is gone at runtime (unless you're doing stuff with Data.Typeable) |
| 22:41 | shachaf | Sure. |
| 22:41 | ChongLi | I like to think of it as the type system just setting up all the plumbing |
| 22:41 | shachaf | But a polymorphic-over-Bounded function might get an extra argument with a Bounded dictionary. |
| 22:41 | ChongLi | yeah |
| 22:42 | shachaf | But that's just compilation details. :-) |
| 22:42 | ChongLi | I saw one article a guy wrote that talks about how to get rid of type classes in your code |
| 22:42 | ChongLi | by passing dictionaries explicitly |
| 22:43 | shachaf | Sometimes that's a much nicer approach. |
| 22:43 | ChongLi | it's pretty weird |
| 22:43 | ChongLi | it's basically just desugaring |
| 22:43 | shachaf | Are you thinking of http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/ ? |
| 22:44 | shachaf | I think he makes a good argument. |
| 22:44 | shachaf | As far as existential types + type classes are concerned, it's often simpler not to use either. |
| 22:44 | ChongLi | I haven't read this one, but I think the one I read reached the same conclusion |
| 22:44 | shachaf | Well, the one I linked to argues for a specific use case. |
| 22:45 | shachaf | Just an extension of the idea that [exists a. Show a *> a] ~ [String]. :-) |
| 22:46 | Sgeo | This conversation is now over my head. |
| 22:47 | shachaf | Then raise your head! |
| 22:47 | shachaf | I have the feeling all I ever end up doing in this channel is talking about Haskell. |
| 22:47 | ChongLi | the example he gives is pretty silly |
| 22:48 | ChongLi | it's rube-goldberg with types |
| 22:48 | shachaf | Which example? |
| 22:48 | shachaf | That's an actual library. |
| 22:48 | ChongLi | the first code snippet |
| 22:48 | ChongLi | oh I'm not saying it isn't a valid example |
| 22:48 | ChongLi | just that people who write that stuff are being silly |
| 22:48 | shachaf | Well, yes. |
| 22:48 | shachaf | That's his point. :-) |
| 22:48 | shachaf | Sometimes classes aren't the right solution. |
| 22:49 | ChongLi | it's akin to people who, upon learning clojure, make tons of records |
| 22:49 | ChongLi | instead of just using maps and vectors |
| 22:49 | shachaf | "Advanced type system features have their place, but plain old functions go a long, long way. Functions are the masters of reuse: when you use an advanced feature, you need a yet more advanced feature to abstract over it (think: classes < existential types < universally quantified constraints < unknown). But all you need to abstract over a function is another function." |
| 22:49 | shachaf | Sure. |
| 22:51 | ChongLi | I'm trying to characterize the mindset that goes into these sorts of antipatterns |
| 22:52 | ChongLi | some kind of desire to be idiomatic? |
| 22:53 | ChongLi | it's the idea that if something's exists you have to use it |
| 22:53 | shachaf | I think the Haskell thing just comes from the idea that type classes are the natural/only way to abstract over different things that have similar behaviors. |
| 22:54 | ChongLi | hmm, maybe |
| 22:55 | ChongLi | you know what bothers me? |
| 22:55 | ChongLi | the word "variable" and how it's misused so much |
| 22:55 | ChongLi | in clojure's documentation, it says that a lot of things are "not variables" |
| 22:56 | ChongLi | such as let-bound names |
| 22:56 | shachaf | It's misused constantly. |
| 22:56 | ChongLi | whereas in haskell they're called variables, using the mathematical definition of the term |
| 22:56 | shachaf | I don't really care what words you use for something as long as you define them clearly and use them consistently. |
| 22:57 | ChongLi | it can be confusing for beginners though |
| 22:57 | shachaf | Most things are. :-) |
| 22:58 | ChongLi | I've actually discussed this a lot with my friend |
| 22:58 | ChongLi | we argue over the philosophy of language |
| 22:58 | shachaf | I like the way Haskell takes almost every name from OO -- class, instance, method, etc. -- and uses it to refer to a completely different concept. |
| 22:58 | ChongLi | he calls me a Wittgensteinian |
| 22:58 | ChongLi | well, Haskell has a right to |
| 22:58 | ChongLi | it's old enough |
| 22:58 | shachaf | It is? |
| 22:59 | shachaf | 1989 isn't that old. |
| 22:59 | brehaut | its not like OO took those terms from a vacuum |
| 22:59 | ChongLi | it's old enough that such terms weren't nearly as widely used as they are today |
| 22:59 | shachaf | Hmm, I didn't think so. But I wouldn't really know, not having been around at the time. :-) |
| 23:00 | ChongLi | same goes for vi and emacs |
| 23:00 | ChongLi | people complain about their "non-standard" key bindings |
| 23:00 | shachaf | Uh oh. No editor wars in here. |
| 23:01 | bbloom | speaking of types.... |
| 23:01 | technomancy | the standard WIMP definitions of "window" and "frame" really don't make any sense |
| 23:02 | ChongLi | nah I'm not a na editor wars type |
| 23:02 | bbloom | i've got the closure script backend completely reworked to emit a javascript AST instead of printing strings! |
| 23:02 | ChongLi | I use both editors |
| 23:02 | bbloom | just need to figure out the closure compiler type system, so that i stop getting horrible failures in advanced compilation mode :-) |
| 23:02 | ChongLi | they're both infinitely superior to mouse-based notepad clones :) |
| 23:02 | bbloom | https://github.com/brandonbloom/clojurescript/blob/js-ast/src/clj/cljs/compiler.clj |
| 23:03 | bbloom | lots more work to do cleaning it up & also want to write up some design notes |
| 23:03 | ChongLi | javascript makes my blood boil |
| 23:04 | ChongLi | ugh I don't want to think about it |
| 23:04 | bbloom | as expected, it's much slower, but i think i'll also get the expected speed improvement if i skip the to-string step |
| 23:04 | jonasen | bbloom: cool! |
| 23:05 | ChongLi | great work though |
| 23:05 | ChongLi | clojurescript is really cool |
| 23:05 | bbloom | yeah, this is more or less a direct port of the string emitting version |
| 23:05 | bbloom | now that it's "pure" there are lots of opportunities for cleanup and simplification |
| 23:05 | jonasen | bbloom: what are the advantages over emitting strings |
| 23:06 | jonasen | bbloom: is the ast standardized? |
| 23:06 | bbloom | jonasen: i should be able to wire it up to automatically generate source maps ;-) |
| 23:06 | ChongLi | manipulating strings is always bad :) |
| 23:06 | bbloom | jonasen: the AST is rhino's |
| 23:06 | bbloom | it seems relatively stable |
| 23:06 | shachaf | What about stringing manipulations? |
| 23:06 | ChongLi | it's why we love lisp languages |
| 23:06 | bbloom | i gotta run, but i'll provide more details as this evolves :-) |
| 23:06 | ChongLi | ok, so it's not always bad |
| 23:06 | Drakeson | Question about Clojure java-interop syntax: Would the alternative syntax (foo-object .method param1 param2) have worked instead of (.method foo-object param1 param2)? The first form could have provided a way to get "method completion" which the current syntax doesn't. |
| 23:06 | bbloom | probably on the mailing list |
| 23:06 | bbloom | cya |
| 23:07 | ChongLi | but it's much easier to manipulate data structures like ASTs than strings |
| 23:15 | unnali | Drakeson: it wouldn't really be very Lispy (where the function is always first) |
| 23:15 | tomoj | I get method completion anyway, sorta |
| 23:16 | tomoj | I think with swank, you can complete to any methods on any classes that are imported |
| 23:16 | unnali | (-> foo-object (...)) gets you half-way there ;) |
| 23:17 | brehaut | rearranging the method / object order wouldnt really help either; theres infrequently enough static type information to restricted it just to one class or interface |
| 23:18 | unnali | indeed! |
| 23:19 | ChongLi | yeah I'm not sure what is gained by such rearranging |
| 23:19 | ChongLi | help with auto-completion? |
| 23:19 | ChongLi | that's all I can really think of |
| 23:19 | ChongLi | type in an object and auto-complete on its methods |
| 23:20 | ChongLi | but that's a very different style of programming |
| 23:20 | ChongLi | that's "thinking in nouns" rather than verbs |
| 23:20 | brehaut | except that its not going to help with autocompletion |
| 23:20 | ChongLi | why not? |
| 23:21 | brehaut | because to restrict autocompletion to a particular class or interface requires knowing what that class or interface is, and much clojure code doesnt have that information statically available |
| 23:21 | ChongLi | oh I wasn't referring to clojure specifically |
| 23:22 | ChongLi | but to "traditional" OO languages like java |
| 23:22 | brehaut | the other thing is that parametric polymorphism makes it less useful |
| 23:22 | ChongLi | yeah |
| 23:23 | ChongLi | to really learn to be a functional prgrammer (when coming from a traditional OO background) requires a change in mindset |
| 23:23 | ChongLi | from nouns to verbs |
| 23:24 | ChongLi | I think that sort of conflict is evident in the people that desire such a change |
| 23:24 | ChongLi | conflict is too strong a word |
| 23:25 | Drakeson | brehaut: I *slightly* disagree: If you place have type hints, you might be able to single out the type of an object. If you don't, you might at least be able narrow it down to multiple possible types, and offer all their methods. |
| 23:26 | brehaut | well yeah, obviously if you typehint, but… |
| 23:26 | Drakeson | and about it being not lispy, methods are not exactly functions, they are very stubborn about what you pass onto them ... |
| 23:27 | ChongLi | Drakeson: the point is that lisp considers the car (or first element) of a list to be a function |
| 23:28 | ChongLi | if you make some special case where the second element is now a method and the first is just a value |
| 23:28 | ChongLi | how do you implement that? it seems really messy |
| 23:28 | brehaut | well, clojure does use the . special form to indicate that it is a OO interop with .whatever desugaring to it anyway |
| 23:28 | brehaut | but yes |
| 23:29 | Drakeson | IMHO both `java-obj java-method ...' and `java-method java-obj ...' are messy and non-lispy. |
| 23:29 | ChongLi | so you'd still have to have the . special form occupy that position |
| 23:29 | brehaut | well you do anyway |
| 23:29 | brehaut | it would just be the second and third arguments that switch position |
| 23:30 | ChongLi | Drakeson was talking about doing (my-object .mymethod) |
| 23:30 | brehaut | i realise that |
| 23:30 | brehaut | but that could be (. my-object mymethod) |
| 23:30 | Drakeson | well, you could also do it as (java-obj. :java-method ...), and find something else for `new'. |
| 23:30 | ChongLi | oh, yeah |
| 23:31 | ChongLi | well you could write a new macro to flip the arguments if you wanted |
| 23:31 | brehaut | trivially |
| 23:32 | ChongLi | I don't see the advantage though |
| 23:32 | Drakeson | ChongLi: a new macro is moot. A reader macro would have been useful though, which I understand why it is not allowed. |
| 23:32 | twobitsprite | why does it bother me that docstrings come between the function name and the argument list? I mean, I get it, variable arity, but... it bothers me for some reason |
| 23:32 | ChongLi | the auto-completion type issue still remains |
| 23:33 | brehaut | twobitsprite: they dont have to |
| 23:33 | ChongLi | I like that clojure's reader doesn't have a huge amount of special syntax |
| 23:33 | twobitsprite | brehaut: no? I can put them after the args list? |
| 23:33 | brehaut | ,(fn [a b] "docstring" (+ a b)) |
| 23:33 | clojurebot | #<sandbox$eval27$fn__28 sandbox$eval27$fn__28@77409080> |
| 23:33 | Drakeson | As I said, you might be able to narrow down possible types of the object and offer a union of all the types' methods. |
| 23:34 | twobitsprite | ooohh :) |
| 23:34 | brehaut | but its kinda weird these days to do so |
| 23:35 | twobitsprite | maybe it'll be one of those things that I'll do at first, run in to problems with, and it'll click why it's done the other way, and eventually I won't be able to stand docstrings after the args list... but for now, it just feels more natural :) |
| 23:35 | ChongLi | also I think it could get confusing |
| 23:35 | twobitsprite | so, what about: |
| 23:35 | Drakeson | ChongLi: I am arguing that that wouldn't need more special syntax. |
| 23:36 | Drakeson | It would merely rearrange the meaning of a couple special forms. |
| 23:36 | twobitsprite | ,(fn ([a b] "docstring1" (+ a b)) ([c d e] "docstring2" (- c d e))) |
| 23:36 | clojurebot | #<sandbox$eval55$fn__56 sandbox$eval55$fn__56@61254e91> |
| 23:37 | ChongLi | Drakeson: could you give me an example? |
| 23:37 | TimMc | twobitsprite, brehaut: I'm pretty sure that's a no-op. |
| 23:37 | Drakeson | of what? |
| 23:37 | ChongLi | of your proposed syntax |
| 23:38 | TimMc | twobitsprite: Try (defn foo [bar] "docs go here?" bar) in your REPL, followed by (doc foo). |
| 23:38 | TimMc | The string is taken to be the first expression in the fn body. |
| 23:39 | twobitsprite | I just tried that, for some reasoning I'm get cannot resolve symbol: doc |
| 23:39 | TimMc | Try (use 'clojure.repl) |
| 23:40 | twobitsprite | yeah, you're right |
| 23:40 | twobitsprite | just says nil |
| 23:40 | Drakeson | Well, one of these: 1. (obj. :method ...), 2. (obj :method ...). (2 requires implementing on infering callables on all java objects, considerably more than a syntax change) |
| 23:41 | twobitsprite | ohh well... guess I'll have to get used to reading the args list after the docstring... |
| 23:41 | ChongLi | yeah I don't like 2 |
| 23:41 | TimMc | twobitsprite: I came to appreciate it. |
| 23:42 | TimMc | docs before impl |
| 23:42 | Drakeson | ChongLi: why? (really looking for reasons, not to troll or anything) |
| 23:42 | TimMc | Well, no. Intent before specifics. |
| 23:42 | sjl | anyone know why (= #{-1 "-1" :-1} #{-1 "-1" :-1}) would return true in the REPL, but false when it's run as part of a test case? |
| 23:42 | ChongLi | because of how lisp treats the first element of a list |
| 23:43 | ChongLi | this would dramatically complicate that, making code a lot less readable |
| 23:43 | twobitsprite | TimMc: I can see that... but I just like to have the args count and names to have some context before reading the docs... often just the args list is enough to convey the gist |
| 23:44 | TimMc | sjl: Works for me in lein test. |
| 23:44 | twobitsprite | anyways, in an unrelated note... is there any way to get lein to use the nailgun server? possibly to speed it up a bit? It's unbearably slow :( |
| 23:45 | Drakeson | ChongLi: How about really making all java objects be callable with first arg the name of the method/`message'? (thinking about the lisp side for now, ignore how to do so). |
| 23:45 | tomoj | twobitsprite: well, when you do (doc foo), you get the name, args, then docs, at least |
| 23:46 | twobitsprite | tomoj: but that almost makes it worse... now it's just inconsistent... |
| 23:46 | ChongLi | Drakeson: in lisp you don't call objects |
| 23:46 | ChongLi | you call functions (and special forms) |
| 23:46 | twobitsprite | it's just a minor nit pick... but it's just kind of bothersome :-\ |
| 23:46 | ChongLi | putting an object (a noun) at the front of a list just makes it really confusing and arbitrary |
| 23:47 | sjl | TimMc: okay now it's returning false at the repl |
| 23:47 | sjl | argggh |
| 23:47 | tomoj | (defn foo [] "doc") |
| 23:47 | TimMc | sjl: At the REPL, try *clojure-version* |
| 23:47 | tomoj | is that an empty function with a docstring, or a function that returns "doc" with no docstring? |
| 23:47 | sjl | TimMc: http://i.imgur.com/dd1bM.png |
| 23:48 | twobitsprite | tomoj: I'm not saying it *should* be that way.. I'm just lamenting that the current way seems awkward |
| 23:48 | xeqi | ChongLi: do you disapprove of ##({:a 1} :a) ? |
| 23:48 | lazybot | ⇒ 1 |
| 23:48 | ChongLi | xeqi: no, because {:a 1} is a function |
| 23:49 | ChongLi | mathematically, a map is just a synonym for a function |
| 23:49 | TimMc | sjl: Ah, so it's the output of a fn. Try (map class (c/to-keys "-1")). I think you'll be surprised. |
| 23:50 | sjl | TimMc: Oh cool, one is an Integer and one is a Long |
| 23:50 | sjl | "Simple" |
| 23:50 | TimMc | In 1.4, that shouldn't matter... |
| 23:50 | sjl | and people wonder why I say you need to know Java to write Clojure... |
| 23:50 | tomoj | &[*clojure-version* (= (Long. "1") (Integer. "1"))] |
| 23:50 | lazybot | ⇒ [{:major 1, :minor 4, :incremental 0, :qualifier nil} true] |
| 23:51 | TimMc | &(= #{(Integer. -1) "-1" :-1} #{(Long. -1) "-1" :-1}) |
| 23:51 | lazybot | ⇒ false |
| 23:51 | TimMc | Oho, so it is! |
| 23:51 | tomoj | hah |
| 23:51 | sjl | lol |
| 23:51 | TimMc | I had figured that one was a Symbol, since that would print the same way. |
| 23:51 | TimMc | Is this a regression? |
| 23:52 | tomoj | appears still broken in 1.5.0-alpha4 |
| 23:52 | sjl | &[(= (Integer. "1") (Long. "1")) (= #{(Integer. "1") (Long. "1")})] |
| 23:52 | lazybot | java.lang.IllegalArgumentException: Duplicate key: 1 |
| 23:52 | sjl | &[(= (Integer. "1") (Long. "1")) (= #{(Integer. "1")} #{(Long. "1")})] |
| 23:52 | lazybot | ⇒ [true true] |
| 23:52 | sjl | wait what |
| 23:53 | TimMc | &(= {(Integer. -1) :val} {(Long. -1) :val}) |
| 23:53 | lazybot | ⇒ true |
| 23:53 | Drakeson | ChongLi: I am suggesting that you can consider java objects as functions that have a first parameter that specify what to do. Not very much so with simple objects for which clojure functions work far better. I would consider a BufferedOutputStream something that should occupy the first place in the form as there are few clojure functions that make sanse to call on it. |
| 23:53 | ChongLi | I wouldn't mind the syntax if it was something like this |
| 23:53 | ChongLi | ((object :method) ...) |
| 23:53 | tomoj | whoa, bizarre |
| 23:54 | jkkramer | it's java's fault |
| 23:54 | jkkramer | &[(.hashCode (Integer. "-1")) (.hashCode (Long. "-1"))] |
| 23:54 | lazybot | ⇒ [-1 0] |
| 23:54 | TimMc | loljure |
| 23:54 | ChongLi | it'd be like object was just a map |
| 23:54 | sjl | oh man |
| 23:54 | twobitsprite | ChongLi: a "method dispatch" map? |
| 23:54 | sjl | it's only negative numbers |
| 23:54 | ChongLi | yeah |
| 23:55 | sjl | dram.test.context> (= #{(Integer. -1)} #{(Long. -1)}) |
| 23:55 | sjl | er |
| 23:55 | sjl | &(= #{(Integer. -1)} #{(Long. -1)}) |
| 23:55 | lazybot | ⇒ false |
| 23:55 | sjl | &(= #{(Integer. 1)} #{(Long. 1)}) |
| 23:55 | lazybot | ⇒ true |
| 23:55 | sjl | dammit clojure |
| 23:55 | TimMc | jkkramer: Right, but I thought 1.3 or 1.4 fixed this. |
| 23:55 | jkkramer | there was a debate about whether/how to handle this |
| 23:55 | twobitsprite | ChongLi: are you familiar with dylan? they had an interesting method dispatch system, might be good to look at for something similar in clojure |
| 23:55 | ChongLi | I've heard of dylan, not familiar with it though |
| 23:56 | ChongLi | you could probably write a macro that'd turn java objects into method dispatch maps |
| 23:56 | ChongLi | I still wouldn't use it though :) |
| 23:56 | ChongLi | I'm pretty happy with the way things are, just trying to help Drakeson |
| 23:57 | Drakeson | ChongLi: Yeah, a dispatch map also makes. |
| 23:58 | twobitsprite | well... it's similar to the idea of abstractions... except dylan uses typed dispatch... but just like with maps, the type of the map being "called" would determine how the "argument" is dispatched |
| 23:58 | ChongLi | it'd be a companion to import-static |
| 23:58 | tomoj | https://groups.google.com/d/msg/clojure/7-hARL5c1lI/6Na-3J8fdFgJ one post about long/integer hashcode |
| 23:58 | twobitsprite | so, thinking of objects as maps of their methods seems fairly natural actually |
| 23:59 | tomoj | I guess the 'fix' was ##(class 1) ? |
| 23:59 | lazybot | ⇒ java.lang.Long |
| 23:59 | twobitsprite | ##(class -1) |
| 23:59 | lazybot | ⇒ java.lang.Long |