#clojure logs

2012-11-08

02:42seannetbookibdknox: replied to your email... still having problems on win8 x64
02:42ibdknoxugh
02:43ibdknoxseannetbook: anything unique about your setup?
02:44seannetbookhardly... it's vanilla win8 release preview on a parallels VM
02:44seannetbooki know next to nothing about windows so i haven't customized it :)
02:44ibdknoxironically me neither ;)
02:44ibdknoxI'm on a fresh install of win8 on parallels x64
02:44seannetbookis there any debug flag i can set or logs or something?
02:45ibdknoxNot that I can find, it seems to be deep down in node territory
02:45ibdknoxI have a couple other guesses on what might be wrong
02:45ibdknoxand how I can fix it
02:46ibdknoxI'll give them a shot and ping you when I have something worth trying
02:46ibdknoxthanks a ton for helping out with this btw
02:46seannetbook'k... anything i can do to help, just let me know
02:46seannetbooki'm probably buying a win8 convertible tablet as my main travel device so i'll need light table to work on that :)
02:48seannetbooki have lein, clojure, java, emacs, nrepl all working on win8 on the vm so light table is the last piece of the puzzle!
02:52ibdknoxseannetbook: you mean a surface?
02:53seannetbooknot sure yet - MS haven't confirmed specs or pricing on the Pro
02:53ibdknoxI think the surface doesn't *actually* run most apps
02:53seannetbookright now i'm leaning toward the Dell XPS 12 Ultrabook Convertible
02:53ibdknoxit's an arm device
02:54seannetbookthe Surface RT doesn't, but the Pro is a full Intel/Win8 Pro machine
02:54UrthwhyteI've got an RT if you have questions
02:54seannetbookmy spec is an i7, 8GB RAM, 256GB SSD
02:55seannetbookdell, sony, toshiba all have convertibles with that spec for $1,500
02:55ibdknoxnice
02:55seannetbookthe asus taichi is a possibility too but more expensive
02:56seannetbook(and i'm a lifelong apple guy)
02:56UrthwhyteI'm still waiting for better Linux support of retina displays :/
02:57UrthwhyteWon an rMBP at a hackathon and had to give up Linux
02:57UrthwhyteLosing xmonad has been quite the chore
02:58seannetbookmy alternative is a MacBook Air 11 fully loaded but i would prefer a tablet hybrid
02:59UrthwhyteMy concern with going to W8 is losing the shell
03:00UrthwhyteCygwin doesn't really cut it
03:00seannetbookuse emacs and eshell :)
03:01Urthwhytevim guy at heart, nty
03:05ibdknoxseannetbook: just to make sure, can you try deleting .lighttable and running it?
03:06seannetbookjust a sec i'll go try that
03:07UrthwhyteOh, is that the Lt author?
03:08ibdknoxit is :)
03:08UrthwhyteAlways surprises me how populous this channel is
03:09seannetbookok, deleted .lighttable and ran the new download again - same error
03:09ibdknoxk, just wanted to be certain
03:09ibdknoxthanks
03:10seannetbookanything else tonight or can i go to bed? :)
03:12UrthwhyteNow I'm tempted to retry some 4clj problems with LT v. vimclojure and see which goes faster hah
03:12brainproxy&(let [lazy-seq* #'clojure.core/lazy-seq] (lazy-seq* [1 2 3]))
03:12lazybotclojure.lang.ArityException: Wrong number of args (1) passed to: core$lazy-seq
03:12ibdknoxseannetbook: head out, I'm not far behind
03:12brainproxy^ what's the correct way to "alias" a macro in another namespace?
03:13seannetbook'k man.. are you gonna be at rich's talk tomorrow in town?
03:13amalloyusually the answer is to not define aliases for things that already exist
03:13amalloyfor sure you can do it, but...
03:13brainproxyamalloy: sure, well let's just assume I have a really good reason to do it
03:16tomoj(:require [clojure.core :as core]) ?
03:16tomoj(core/lazy-seq [1 2 3])
03:19brainproxytomoj, thanks, but not quite what I was after
03:19brainproxyamalloy: this works `(def #^{:macro true} lazy-seq* #'clojure.core/lazy-seq)`
03:19tomojwhy do that?
03:20brainproxytomoj: just learning some things...
03:42jyuhi, are there any awesome bdd style test framework
04:41pingtimeoutHello world !
04:41_ulises|awaypingtimeout: pong
04:42ejacksonsssh.... its meditation hour in #clojure
04:43pingtimeoutHmm ok
04:43pingtimeoutI'll be quiet
04:43ejacksonjust kidding, its usually quiet in here until the American wander in with their spurs and big hats :P
04:44pingtimeout:)
04:44pingtimeoutOk so lets go
04:44pingtimeoutI'm wondering : is it possible to start a clojure nREPL and connect to it using telnet ?
04:46pingtimeoutThe point is : I have a webapp where you can send code to a node.js server
04:46pingtimeout(Only for training purpose)
04:46pingtimeoutSo currently it supports only javascript code, and I would like to add clojure support
04:47pingtimeoutAnd here I am, trying to figure out how nREPL works
04:48pingtimeoutDo you have any advice or pointers about how I could achieve that ?
04:48ejacksonyou connect to an nrepl directly
04:48ejacksonover so long as you can see the port
04:48ejacksonI have a couple of machines with an embedded nrepl server, forward the port over ssh, and then connect directly
04:49ejacksoncouldn't be easier
04:49pingtimeoutYeah but, what do you use to connect to the nREPL ?
04:50ejacksonaaah, I see, I'm doing it from emacs
04:50ejacksonusing nrepl.el
04:50ejacksonif you dig into that I'm sure you'd find your answers
04:51pingtimeoutOk thanks :)
04:52pingtimeoutFor instance, I connected a telnet to the nrepl server and typed "(println :foo)" but it did nothing
04:52ejacksonyeah, I imagine there may be more to it than that :)
04:53pingtimeoutYeah 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:54ejacksonpingtimeout: there are a couple of existing projects that do it in embedded clojurescript: session being the most interesting
04:54ejacksonso cljs sends clj to server, its eval'd, and the result sent back to cljs in the browser
04:57pingtimeoutOk thx, I'm going to dig that :)
04:57clgvpingtimeout: there is a HTTP transport for nrepl
04:58ejacksonaaah, and there's the answer :)
04:59clgvpingtimeout: 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:00pingtimeoutclgv 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:01ejacksonthe first doesn't require the the repl - you can just send use an http server yourself
05:01clgvpingtimeout: 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:02pingtimeoutYeah http would be easier I think
05:02pingtimeoutDo you know where i can find the documentation of the nrepl http protocol ?
05:03pingtimeoutI found this but not sure it is relevant : https://bitbucket.org/kotarak/nrepl
05:05clgvpingtimeout: maybe a bit outdated since nrepl made a jump to 0.2.0 which might have broken apis
05:06clgvpingtimeout: https://github.com/cemerick/drawbridge
05:07clgvpingtimeout: if you are stuck try to ping cemerick this afternoon
05:09pingtimeoutOk
05:09pingtimeoutMany thanks !
05:34luxbockwhy does ((fn [a b] [a b]) 1 2) give me [1 2] but (#([%1 %2]) 1 2) throws an exception?
05:36scottjluxbock: because #(a) is the equivalent of (fn [] (a)) not (fn [] a)
05:39luxbockhmm I see
05:47alexnixonluxbock: I disagree with scottj, rather it's because the #() form tries to evaluate the stuff within
05:52alexnixonluxbock: in this case it's trying to evaluate a vector
05:54luxbockalright
05:54rcg-workhuh
05:54rcg-workerr
05:58alexnixon,(#(vector %1 %2) 1 2)
05:58clojurebot[1 2]
07:14clgvluxbock: just for the record, scottj had the right explanation
07:16alexnixonclgv: he did - I misunderstood
07:17luxbocknext 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:18antares_luxbock: unlikely
07:23clgvluxbock: nREPL supports that but the question is if nREPL.el has support for that already
07:23clgvin CCW there is a button to kill the current execution in the REPLView
07:24luxbockwhat's CCW?
07:24clgvCounterclockwise a plugin for Clojure development in eclipse
07:25luxbockah
07:25clgvso you have to check nrepl.el documentation or source to find out whether there is a keybinding for that
07:31luxbockC-c C-b seems to work
07:37zakwilsonLighttable actually runs for me now. Yay. Instarepl doesn't seem to like it when I call in-ns though.
07:59frawrhi, looking for some help with enfocus.
08:27solussdAnyone 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:41magius_pendragonhey 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_ulisesmagius_pendragon: can you paste the code somewhere?
08:42magius_pendragon_ulises: yeah, is there any preference on where?
08:42magius_pendragonI vaguely remember a clojure pastebin last time I hopped in here, but don't have the address on hand
08:43_ulisesmagius_pendragon: refheap, friendpaste, they're all fine
08:43magius_pendragonhttps://www.refheap.com/paste/6483
08:44magius_pendragonI'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_ulisesmagius_pendragon: I don't have much experience with gen-class et al, but I've generally seen it used inside the (ns ...) form
08:46magius_pendragondocs 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_ulisesmagius_pendragon: have you tried the import in a repl?
08:48magius_pendragon_ulises: the import was working when I used proxy instead
08:48_ulisesmagius_pendragon: interesting
08:48magius_pendragoncan'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_ulisesoh
08:49cmdrdatshey 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:50madsycmdrdats: map should work fine
08:50cmdrdats(map #(inc (:age %)) items) ?
08:51cmdrdatswas hoping for something like (update-walk [:age] inc items)
08:53magius_pendragon_ulises: any other ideas ?
08:53joegallo,(map (update-in % [:age] inc)) [{:age 1} {:age 2} {:age 3}])
08:53clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: % in this context, compiling:(NO_SOURCE_PATH:0)>
08:53joegallo,(map #(update-in % [:age] inc)) [{:age 1} {:age 2} {:age 3}])
08:53clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$map>
08:53joegallo,(map #(update-in % [:age] inc) [{:age 1} {:age 2} {:age 3}])
08:53clojurebot({:age 2} {:age 3} {:age 4})
08:54_ulisesmagius_pendragon: not from the top of my head unfortunately
08:54joegallowhich is basically (map #(update-in instead of the idate of update-walk. you only lose a few characters, it's not so bad.
08:54joegallos/idate/idea/
08:54cmdrdatsi was hoping to drop the anonymous function :/
08:55cmdrdatsbut oh well, no biggie
08:55cmdrdatsi'll just roll my own, just wanted to check that I'm not missing some super obvious function that already does it
09:06magius_pendragon_ulises: figured it out. Apparently removing the []'s around the superclass was needed.
09:07magius_pendragon_ulises: but thanks for your help :)
09:11luxbockis 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:19AWizzArdluxbock: What you mean by „auto-load”?
09:20luxbockso that I can use the library straight away, without having to import it
09:23clgvluxbock: you could put a require or use in project.clj as :injections "(require '[my.lib :as lib])"
09:23clgvargs no. :injections [(require '[my.lib :as lib])]
09:28luxbockah, hadn't seen that option before
09:28luxbockwhile googling it I found this:
09:28luxbockhttp://stackoverflow.com/questions/12329713/how-to-load-ns-by-default-when-starting-repl
09:29luxbockseems like I can also use :repl-options
09:31clgvoh right :init^^
10:04AnderkentAnyone familar with sqlkorma? Is it alive?
10:04clgvAnderkent: well, chris granger is busy with light table ;)
10:07pandeirocan you program clojurescript with lighttable, anyone know?
10:10pandeiroi would see for myself but i get an error about libudev.so missing :(
10:19jsabeaudryShort way of doing (into {} (map #(vec [% (foo %)]) #{:a :b :c})) ?
10:19jsabeaudryOr more idiomatic
10:22ejacksonjsabeaudry: maybe you like (into {} (map (juxt identity f) #{:a :b :c})
10:23Anderkent(zipmap my_vector (map foo my_vector)) maybe?
10:24jsabeaudryejackson, Anderkent, thanks, I think I'll go with the zipmap
10:24ejacksonyeah, its nicer :)
10:26apwalkor the venerable: (reduce #(assoc % %2 (f %2)) {} #{:a :b :c})
10:29alexnixondoes 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:31alexnixonthe 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:37Anderkentshouldn't it be a macro in case compute-foo has side effects?
10:43alexnixonAnderkent: that's a good point - and also for efficiency
10:47TimMcalexnixon: I believe test-> or whatever it is called would help with that.
10:49alexnixonTimMc: I haven't come across that before - can you point to the source?
10:49TimMchttps://gist.github.com/3885504
10:49TimMcIt's not in any released code yet, I think.
10:51alexnixonyes that would help. Is that slated for 1.5?
10:51TimMc(test-> state some-opt (assoc :foo (compute-foo)) other-opt (assoc :bar (compute-bar)))
10:52TimMcLet me check the chatlog.
10:53hyPiRiongroan.. Now I remember why I went from Common Lisp to Clojure.
10:54hyPiRionTimMc: https://github.com/clojure/clojure/commit/026691e2f6cc8d1bab4feb7e577530a9f06fd85e
10:56TimMcoh, sweet
10:56alexnixoncool so that's in the 1.5 beta
10:57gtrakwhen-> is like -?> and let-> is like -<> ?
10:58S11001001is let-> anaphoric, gtrak?
10:59gtrakwhat's anaphoric?
10:59hyPiRion~anaphoric
10:59clojurebotTitim gan éirí ort.
10:59S11001001gtrak: that is, it would have to do proper form replacement, not just bind a let with a variable
10:59S11001001gtrak: introduces a binding implicitly
10:59gtrakit looks like it replaces it in top-level forms, but also binds it
10:59S11001001gtrak: well that's nasty
11:00gtrakS11001001: wait, I think I'm reading it wrong, it doesn't place it in the form, but it does bind it
11:01S11001001gtrak: that's the opposite of -<>
11:01Mr_BondI need to get a clojure book, all these operators are like greek to me
11:01Mr_Bond:)
11:01S11001001Mr_Bond: you won't find these in any book
11:01S11001001Mr_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:02gtrakMr_Bond: blow your mind: https://github.com/rplevy/swiss-arrows
11:02Mr_Bondyeah, that's true
11:02gtrak-<><:p
11:02Mr_Bondthanks, nice overview. I'm not a big fan of such it's like $_, $-, $!, $<, etc in perl and ruby
11:02hyPiRionheh
11:03hyPiRionIt's moving into APL-land.
11:03S11001001Mr_Bond: anaphora have problems, but they're typically much safer than the globals perl offers
11:04Mr_BondAh, I ment more in terms of readability
11:04S11001001Mr_Bond: I can say entirely empirically that -<> is highly intuitive to readers
11:04Mr_Bondhehe :)
11:05gtraklet-> seems like a good alternative
11:05Mr_Bondyeah
11:05S11001001gtrak: when it works.
11:05S11001001Mr_Bond: you don't get the benefit of people using it in a sentence here; we're just talking about it abstractly
11:05gtrakis it broken in some way?
11:06S11001001gtrak: making a let binding is fundamentally different from form replacement
11:06TimMcLooks fine to me.
11:06DaReaper5Basic clojure question: What is the best way to pass json to java in a method's parameters?
11:06S11001001for example, if <<- did binding instead of form replacement, you couldn't use it as a replacement for let-else
11:07TimMcDaReaper5: That doesn't sound very basic.
11:07S11001001(<<- (let [x 42]) (when (= x 42)) (if (on?) "on") x)
11:07TimMcWhat do you mean by "json"?
11:07DaReaper5haha thought it was
11:07S11001001instant depth reduction
11:07DaReaper5TimMc json is javascript object notation
11:07gtrakS11001001: 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:07TimMcDaReaper5: Not what I meant.
11:07S11001001gtrak: see above for usage; it's not at all just a hack
11:08DaReaper5i want to pass a json object to a java method
11:08TimMcS11001001: And then you have a kind of non-locality of control flow that smells really bad.
11:08DaReaper5should i do the conversion on the clojure end or java end
11:08S11001001TimMc: it's no worse than let-else
11:08DaReaper5can cheshire do this?
11:08S11001001TimMc: if you're desperate to reduce expression depth it's the shortest path
11:09dakroneDaReaper5: it's not quite clear what you're asking about
11:10gtrakS11001001: it's totally not clear to me what that's doing, so there's that
11:10S11001001gtrak: copy and paste it and put newlines in between the args
11:10DaReaper5On the clojure side i have a json object. I want to pass this in a java method's parameter.
11:11DaReaper5Java does not recognize json so i have to convert
11:11TimMcDaReaper5: Are you having trouble with Java interop syntax?
11:11gtrakS11001001: so it's threading them from the bottom up?
11:11S11001001gtrak: you've got it
11:11gtraknot sure what the benefit is though
11:11DaReaper5Does the java interop have a way of converting json?
11:11ohpauleezDaReaper5: You mean you have a JSON string? Or you've parsed the JSON into a Clojure map?
11:12S11001001gtrak: do the expansion, and imagine it's longer
11:12DaReaper5ohpauleez i can have either on the clojure side
11:12DaReaper5i already have a way of converting json to and from a string
11:13ohpauleezDaReaper5: 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:13DaReaper5i can pass a string but... can i pass a clojure map to a java method
11:13gtrakso it's good if you're nesting a lot of forms with no branching in the tree
11:13DaReaper5ok
11:13Anderkentyou can pass a clojure map to a java method that wants a map
11:13DaReaper5so it just behaves like a hashmap
11:13gtrakI think I rarely do that
11:13DaReaper5no conversion necessary
11:13ohpauleezcorrect
11:13gtrakI'll just make functions usually
11:13TimMcDaReaper5: Everything you're asking about depends on what the Java method expects, which you haven't xplained at all.
11:14DaReaper5so 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:14ohpauleezTimMc: I think it expects a map-like
11:14DaReaper5TimMC i can have the java method retrieve anything
11:14ohpauleezDaReaper5: Don't use "json" like that
11:14DaReaper5but a string would be impractical because a conversion would still have to be done
11:14DaReaper5ophauleez, sorry like what?
11:15Anderkentyou need to do the json string -> hash map conversion somewhere anyway
11:15gtrakS11001001: seems like it's equivalent to not indenting properly :-).
11:15Anderkentwhether you do it in java or in clojure does not really change much
11:15DaReaper5anderkent i have cheshire for that i believe
11:15S11001001gtrak: you'll note there's a branch in my example
11:15ohpauleezJSON 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:15gtrakis it more readable? https://gist.github.com/d7b45e347df19d9e808f
11:16ohpauleez"If the Java method expects a JSON string, I should pass the string directly in"
11:16DaReaper5ohpauleex yes you are right but i was unaware of the possiblity of using a clojure map in the context
11:16S11001001gtrak: and it autoindents correctly
11:17gtrakright, I just think I'd prefer the auto-indented version of the second thing I wrote.
11:17S11001001gtrak: sure; <<- is for longer series
11:17DaReaper5anderkent it does matter because if i can use a bult in converter on the clojure side it would be easier :)
11:18S11001001or if you want to use ->> but backwards
11:18S11001001because that's all it is
11:18DaReaper5but i believe i know what to do now so thanks!
11:18gtrakyes. I could see it being useful for deep nesting.
11:18TimMcS11001001: That "if" is hella confusing.
11:19gtrakbut 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:19TimMcEspecially because "<<-" looks like it puts things at the beginning of the form, not the end.
11:19ohpauleezDaReaper5: totally welcome
11:19gtrakI see it as macroized comp
11:19S11001001TimMc: what else would you call backwards ->>?
11:19TimMc>>-, duh :-P
11:20djcoingtrak: oh, awesome, your logo from keen commander, I love this game :)
11:20gtrakit's classic!
11:20gtrakkeen commander? is that a foreign language version? :-)
11:21ohpauleezhaha
11:21djcoingtrak: don't know, what is your version ? maybe I don't recall it exactly :)
11:21gtrakCommander Keen
11:22ohpauleezI don't think I ever realized that was a Carmack and Romero game
11:22gtrakwe were talking about threading and ordering after all
11:22djcoinWell Commander Keen then must be the exact name
11:22pandeiroin 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:22pandeiroyou want to use a queue to send a task to another thread, you do not want the
11:22pandeiroPersistentQueue discussed in this section.
11:23pandeiro-- my question: if that's what i want, what *should* i use?
11:23gtrak(-> Keen Commander)
11:23gtrakpandeiro: probably an agent
11:23ohpauleezpandeiro: and a priority queue
11:24pandeiroohpauleez: that is a java class?
11:24ohpauleezor an atom with with a watcher
11:26ohpauleezpandeiro: http://clojure.github.com/clojure-contrib/branch-master/priority-map-api.html
11:26ohpauleezDig around to see where this went to, and use watchers
11:26gtrakcommander keen was the birth of smooth side-scrolling on pc, like mario 2.
11:28pandeiroohpauleez: gracias
11:34ohpauleezpandeiro: Certainly! happy to help
11:36ejacksongtrak: hard to believe that after Keen they then did Doom !
11:36djcoin:)
11:37gtrakejackson: wolfenstein
11:37ejacksonyeeeeeeees
11:37ejacksonstill, from collecting pizza to topping nazis....
11:40gtrakkeen 4-6 was pretty great, too
11:41djcoinI mostly played to keen4 as a kid, love the universe
11:44ejacksonthe book "Masters of Doom", about the iD mob, is a great read
12:04degIs 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:05gtrakdeg: if it's on functions you write yourself, you can create a macro to attach it as metadata
12:06deggtrak: Not sure what you meant, especially the "it" at the end.
12:07gtrakmake your own defn that does what you wan
12:07gtrakt
12:07degI see. Nope. I need to walk existing code, separating the function body from everything else.
12:07gtrakah
12:07gtrakthat sounds harder :-)
12:07degIt's not rocket science, but does involve a bunch of detailed rules...
12:08gtrakyou might want to look at the clojurescript analyzer, or consider hacking the clojure compiler?
12:09degI'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:09gtrakhack your own dist of clojure/core.clj might be easier, too
12:10degI've not played with clojurescript at all. Do you happen to know where can I find the clojurescript analyzer source?
12:11gtraknot off-hand
12:11gtrakthere are some projects that use it though
12:11gtrakhttps://github.com/jonase/kibit
12:11degk, I'll poke around. Might be higher-level than the def'n of defn
12:12andrewmcveighIsn't it here https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj ?
12:13degthanks. I'll take a look at it. Off for a bit now while I put on my reading cap.
12:13ohpauleezdeg: Kibit and Ambrose's analyzer should get you there
12:14ohpauleezhttps://github.com/jonase/eastwood, https://github.com/jonase/kibit, https://github.com/frenchy64/analyze
12:14ohpauleezdeg: ^
12:14ohpauleezeastwood is an example on how to use analyze
12:14ohpauleezbut if you can match the forms, you can use kibit (see how cljx uses kibit)
12:16degThanks!
12:16ohpauleeznp
12:19antoineBhello, for doing (map and [true true false]) i need to do (map #(and %1 %2) [true true false]), is there another way?
12:20raekantoineB: you don't want to do 'and' element wise, so 'map' is the wrong higher order function to use here
12:20ohpauleezantoineB: so you want to and the pairs? or and the whole thing?
12:21ohpauleez,(apply and [true true false])
12:21clojurebot#<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0)>
12:21raekantoineB: your pattern seems to be 'reduce': (reduce and [true true false])
12:21ohpauleezyes
12:22joegallo,(every? identity [true true true])
12:22clojurebottrue
12:22joegallo,(every? identity [true true false])
12:22clojurebotfalse
12:22raek('reduce' is what 'and' uses internally when given many arguments)
12:22antoineBand the whole thing
12:22ohpauleezyeah, i'd use identity
12:23antoineBraek: you are right i mistype, i want to use reduce
12:23joegalloevery? has the benefit of returning false early even if you have very long seq of trues but a false at the beginning
12:23raekhrm, sorry. 'and' is not a function, so you can pass it to apply or reduce directly
12:23joegallonot sure if that's a concern for you
12:23raek,(reduce #(and %1 %2) [true true false])
12:23clojurebotfalse
12:24raek,(macroexpand '(reduce #(and %1 %2) [true true false]))
12:24clojurebot(reduce (fn* [p1__135# p2__136#] (and p1__135# p2__136#)) [true true false])
12:24ohpauleezexpand more
12:25raek,(macroexpand '#(and %1 %2) [true true false])
12:25clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (2) passed to: core$macroexpand>
12:25raek,(macroexpand '#(and %1 %2))
12:25clojurebot(fn* [p1__191# p2__192#] (and p1__191# p2__192#))
12:25raek,(macroexpand '(and %1 %2))
12:25clojurebot(let* [and__2241__auto__ %1] (if and__2241__auto__ (clojure.core/and %2) and__2241__auto__))
12:25ohpauleez,(macroexpand-1 '(reduce #(and %1 %2) [true true false]))
12:25clojurebot(reduce (fn* [p1__245# p2__246#] (and p1__245# p2__246#)) [true true false])
12:25ohpauleezahh that's what I was looking for, thank you
12:26ohpauleezBut yes, antoineB I'd use every? and identity
12:26raekanyway! you can't apply and, because it's a macro (and that would be like trying to apply 'if')
12:26antoineBevery? is fine
12:28antoineBthat seems bizar to see and implemented by an if
12:28antoineBlogical, but bizar
12:34gtrakantoineB: of course it's logical!
12:35gtrakit's also not bizarre. and/or are short-circuiting in all languages I know of.
12:35gtrakthe only way to short-circuit is with control-flow/branches/if
12:36TimMcand lambda-wrapping
12:36gtraklambda-wrapping?
12:36antoineBbizar in sense of in other language it seen an operator implemented in the compiler not in the language
12:36TimMcbut that requires "if" at some level for selection
12:36gtrakjump-tables are branches
12:37TimMc(if-fn true #(println "true") #(println "false"))
12:37TimMc(def if-fn [test then else] (if test (then) (else)))
12:37gtrakturtles
12:38TimMc(def if-fn [test then else] (if-fn test #(then) #(else))) :-P
12:38gtrakhaha
12:39gtrakgoto/branch/jump are fundamental
12:39gtrakI was thinking maybe lambda calculus has something to say about this, though?
12:41gtrakanyway it's a very useful construct on a von-neumann architecture
12:42ForSparePartsHave you guys ever seen an exception like this? "java.lang.ClassCastException: Cannot cast java.lang.Float to [F"
12:42TimMcSure. [F is a float array.
12:43TimMc25 cents on varargs.
12:43ForSparePartsTimMc, Thanks. I had no clue, and Google for [F is a non-starter.
12:43gtraksymbolhound?
12:43ciphergothI 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:44TimMcgtrak: Doesn't help here.
12:44gtrakyea... was just about to say, that's unfortunate
12:44TimMcciphergoth: apply str
12:44ciphergothForSpareParts: FWIW that's a Java thing, not a Clojure thing
12:44TimMcciphergoth: Not exactly, it's a JVM thing.
12:44ciphergothTimMc: indeed
12:45ciphergothwill have to get more used to making that distinction now I'm learning Clojure...
12:46TimMcAnd things in java.lang... are kind of both Java and JVM at the same time.
12:46ForSparePartsTimMc, 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:47TimMc~varargs
12:47clojurebotI don't understand.
12:47maleghastEvenin' All
12:48maleghastotfrom: You about, old bean?
12:48maleghastotfrom: (Don't worry not about to tap you up for extended support requests)
12:48otfrommaleghast: after a fashion
12:49otfrompfft... so many better on this channel to get support from
12:49maleghastotfrom: OK, good - just wanted to ask you a question - will send prig message...
12:49TimMcclojurebot: 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:49clojurebotc'est bon!
12:50gtrakfiction! lies!
12:50TimMcForSpareParts: ^
12:51ForSparePartsTimMc, scratch that, I was wrong. This isn't a varargs method -- I should've googled that term first. My bad.
12:51gtrakjava is just an obfuscation over the C stdlib! burn them!
12:51TimMcDammit, I lost 25 cents.
12:51TimMcWhat's the exchange rate with lazybot karma?
12:52ciphergothOK 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:52gtrakhiccup is just like that
12:52gtrak(html [:div#foo.bar.baz "bang"])
12:53gtrakwhat's a tuple?
12:54maleghastgtrak: http://en.wikipedia.org/wiki/Tuple
12:54ciphergothwhat I'm looking for is the best way do to something like algebraic data types
12:54TimMcciphergoth: I guess it depends on how you're going to use them.
12:54ciphergothTimMc: clojure.core.match and dispatch on what sort I'm looking at
12:54gtrakrecords?
12:54clojurebotRecords 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:55AWizzArdCeshire 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:59pandeirois 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:59gtrakpandeiro: set a flag somewhere, like an atom
12:59dakronepandeiro: defonce
13:00SegFaultAXdakrone: What?
13:00pandeirogtrak: ok, thought of that, so the fn 'closes the door behind it' when it finishes
13:00scriptornot sure if defonce would be useful here
13:00pandeirodakrone: didn't get how that would work
13:00SegFaultAXIt's not even related to the question.
13:01dakroneSegFaultAX: pandeiro: hah, sorry, I misunderstood the question
13:01pandeirodakrone: np
13:01gtrakpandeiro: yes.
13:01joegallodo you want other callers to block until the first call exits?
13:01joegalloor just pass through with no effect?
13:01pandeirojoegallo: right, i don't even want it to get called
13:02pandeiroi thought the atom solution was 'dirty' but i will go with it
13:02SegFaultAXpandeiro: For the record, this doesn't sound like a good idea.
13:02pandeiroit's literally my first time trying to implement a queue of sorts, no idea what i am doing really
13:02pandeiroSegFaultAX: i appreciate that :)
13:02gtrakpandeiro: if you want to make it cleaner, perhaps wrap the check/update in a lock
13:02joegalloif you want the calls to queue up, maybe you should be sending to an agent?
13:03gtrakserialize access to the atom, in other words
13:03pandeirogtrak: right, not sure how though
13:03pandeirojoegallo: also very unfamiliar with using agents
13:04gtrakthere's a convenient 'locking' utility, can lock on the atom or the var or whatever
13:04gtrakI've only used it once really... for serializing calls to a println
13:05pandeirobasically 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:05gtrakpandeiro: that sounds like a perfect use-case for an agent
13:05pandeirogtrak: i have been thinking that and reading about agents for the last few days and it just doesn't click in my head
13:06pandeiroi would send the request to the agent?
13:06SegFaultAXpandeiro: Sounds like you're implementing a blocking queue.
13:06gtrakan agent is a queue with a threadpool
13:06gtraknon-blocking though
13:06pandeiroSegFaultAX: i think i am, basically
13:06joegalloyou really should probably look into agents more, just a suggestion
13:06joegalloseems like most of us think that, which you should probably take as a sign ;)
13:07gtrakpandeiro: if you want to block on the agent, you can use await or promise/deliver
13:07gtrakpromise/deliver are implemented with CountdownLatch
13:07TimMcAgents are supposed to be value-oriented, and receive fns to operate on them.
13:08TimMcMaybe you want a queue + a while loop.
13:08pandeiroTimMc: that is what i was implementing just now
13:08ForSparePartsTimMc, I found my problem, by the way. I was being an idiot and giving the wrong arguments.
13:08gtrakTimMc: 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:08pandeiro(while (peek (deref persistent-queue-atom)) (do-stuff ...))
13:08AWizzArdSo, 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:09gtrakI think it's analagous to datomic's single writer strategy, the value of the agent being the DB
13:09pandeiroAWizzArd: yes i can tag this question as answered :)
13:09TimMcWhat we need is a singleton strategy for creating singleton functions.
13:09SegFaultAXTimMc: :)
13:10pandeiroTimMc: the limitation i have with a queue + while loop is the 'sleep' and 'wake up' part
13:10pandeirohence the original question
13:10pandeiroi could create a watch
13:10gtraksleep and wake up bits are taken care of in the agent
13:10TimMcpandeiro: LinkedBlockingQueue
13:11raekpandeiro: 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:12pandeiroraek: that looks like a much more elegant way to do it dirty than i could've come up with
13:12SegFaultAXraek: Or you could use a monitor and locking, which is basically what you just tried to re-invent. :)
13:12TimMcpandeiro: Will it run forever?
13:12raekwell, my version simply returns nil if the atom was "occupied"
13:12pandeiroTimMc: yes
13:12raekno blocking
13:13SegFaultAXraek: But he wants the calling thread to sleep (enqueue in the monitor) if it can't acquire the condition variable.
13:13raekah, a lock then
13:14SegFaultAXI think. Actually he hasn't really described what he wants clearly other than using a meaningless term "singleton function"
13:14raek(or monitor)
13:14TimMcOh, the caller needs to block?
13:14pandeirosingleton fn was specific to the implementation of using while and a persistent queue
13:14pandeirothe queue would be an atom with a watcher
13:14SegFaultAXpandeiro: That term isn't really a thing in this context.
13:14gtrak(let [p (promise)] (send my-agent (fn [val] (deliver p something) val) @p)
13:14SegFaultAXpandeiro: You just want a synchronized function.
13:15TimMcFor some reason I imagined that this was async.
13:16jsabeaudryWhat do you use to do SVG in a noir context? Is analemma the recommended tool?
13:18andrewmcveighjsabeaudry: I found using hiccup to generate the xml easier tbh.
13:19raek(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:20raeksorry (defn singleton-fn [f] ... (try (apply f args) (finally (locking running-monitor (.notify running-monitor) (reset! running false)))))
13:21pandeirogtrak: i pasted that (let...) in my REPL and locked myself out :)
13:21gtrakhaha
13:22gtrakyou can deref with a time-limit by the way
13:22pandeiroi really wish there were some concurrency materials for beginners dealing with real world scenarios
13:22gtrakI've used it to great effect in testing
13:23raekpandeiro: Java Concurrency in Practice is a really good book in the subject
13:24pandeiroraek: i've seen it mentioned, i will try to hunt it down
13:24gtrakCTMCP covers the async stuff pretty well
13:24pandeirocoming from JS my experience is all single threaded or async
13:24pandeiroi really don't see how to apply things like agents, promises, even futures
13:24gtrakhttp://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695
13:25gtrakJCIP was more gotchas building-blocks, CTMCP is cohesive mental-model stuff
13:25raekpandeiro: fyi, agents, promises and futures are not the basic building blocks. they are what Clojure add on top of the regular JVM features
13:26raekit's good to know something about what's in java.util.concurrent
13:26pandeiroraek: i see the roads all leading there, yeah
13:27hiredmanb
13:28raekit 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:29raekhrm. (defonce running (Object.)) (defn singleton-fn [f] (fn [& args] (locking running (apply f args))))
13:30raekthis, as well as the previous version, deadlocks on recursion though
13:30gtrakreentrantreadwritelock?
13:30gtrakor just RenetrantLock I guess
13:31gtrakReentrant*
13:32gtrakif 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:33gtrakyea, in ReentrantLock there's a subclass: abstract static class Sync extends AbstractQueuedSynchronizer
13:35gtrakCountdownLatch, Semaphore, and Futures as well
13:42daniel__I have a file src/backend/communication.clj and also a directory src/backend/communication
13:42daniel__is that going to cause problems?
13:42daniel__on requires/use
13:43pandeirodaniel__: no
13:43raekdaniel__: no.
13:43daniel__ah wait, think i found my problem
13:43daniel__i move a file into communication but didnt change the ns
13:43daniel__my cpu is at 130%
13:45daniel__for some reason my repl wont launch, keeps timing out
13:45daniel__lein repl that is
13:46pandeiroso i just need to read 811 pages and i will be able to implement this basic queue
13:51daniel__any ideas why lein is consuming all my cpu?
13:51gtrakpandeiro: I think it's good to bring a certain fear to concurrency discussions.
13:53pandeirogtrak: i have been avoiding it, really
13:54pandeirobut 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:54pandeiroso either i learn to keep it loaded and queue my interactions with it, or i die of boredom
13:58gtrakwhy queue? why not synchronous?
13:58gtrakwith callbacks and things
13:59pandeirogtrak: hmm
13:59gtrakI see async and queues as a tearing apart of call stacks, a reifying of the ordering
13:59gtrakinto a data structure
14:00pandeirogtrak: not sure i see how else to do it
14:00gtraknot sure I get the details of it, then
14:00pandeiroserver starts, instantiates connection, listens for requests and processes them with the single connection
14:01pandeirothe server could get two requests at the same time
14:01gtrakah, it's in a different process?
14:01pandeirono, it's in the same process now
14:02pandeiroi guess it makes sense to just set it up as an atom or something
14:02pandeirois 'locking' to be used with atoms?
14:03gtrakso, 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:04gtrakso, to enqueue, I just send it a function. If I want some result, I deliver on promises within that function.
14:04gtrakIf I want to read from the job store directly, I just use the value of the agent.
14:05pandeiroi follow everything but the delivering and promise part
14:05pandeirothe point of that is that it executes on another thread? or that it delays execution until necessary?
14:05gtrakyes, web requests come in and enqueue actions, which happen on the agent's thread pool.
14:06gtrakI don't want to block the web request unless I care about the result.
14:06gtrakpromises 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:07gtrakin CTMCP, they are described as dataflow variables along with futures
14:07gtrakthey represent a value to be determined later
14:08gtrakso, when you hung your REPL, it was because you blocked the thread.
14:08gtrakIn testing, everything I use has timeouts.
14:08gtrakagents also have the benefit of centralized error-handling.
14:08gtrakSo, I've created a function that checks for errors during a test run, then rethrows the exception if any.
14:09pandeirok this is starting to make sense
14:10gtrakfutures decouple value from execution. Promises reify that into an object you can pass around.
14:10gtrakor rather, they decouple execution from the evaluation
14:10gtrakI think you can still pass around futures.
14:11pandeiroand there is no analog for 'deliver' with futures?
14:11gtrakbut futures care about how they're executed, promises are just placeholders.
14:11gtraknope
14:11gtrakfutures manage their own threads, with java Futures you can pass an executor I think.
14:12gtrakwith promises, you can use the agent's queue or whatever you want.
14:12pandeirogreat, ok. thanks for the hand-holding :)
14:12gtraka 'deliver' for futures is the return value of the thread-stack :-)
14:13gtrakpromises decouple that
14:13pandeirothe abstractions make sense to me now
14:14pandeirogtrak: i will probably share some code here tomorrow if you're around, see what monstrosity i come up with ;)
14:28gtrakpandeiro: sure, this stuff is still fun for me :-)
14:31gtrakI just find the reification of a thread stack as data to be helpful in understanding async. We do the same with lazy-seqs.
14:31gtrakan iteration is then a sequence of values.
14:32gtraka tail-recursion is an iteration, etc..
14:33gtrakdata-dependency is expressed as return values, when decoupled, when the thread stack is split apart, it must be made explicit.
14:42jamiiDoes anyone know how to turn off the math symbols in emacs-live (lambda for fn etc)
14:46TimMcgtrak: Man, I bet you love continuations.
14:47gtrakI haven't done much with them yet, but in theory, yes :-)
14:51gtrakTimMc: stacks are poor man's gotos
14:51TimMchaha
14:56mudgehow do I add a checkout dependancy to my project.clj file?
14:57TimMcmudge: You do it like a normal dependency as far as project.clj is concerned.
14:57TimMcthen you add the symlink in ./checkouts/
14:57mudgeTimMc: the symlink goes to the root of the project I am depending on correct?
14:58mudgeTimMc: 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:01gfrederickswhat's the latest clojure version?
15:02TimMcmudge: I think the ID group defaults to the artifact ID.
15:03TimMcmudge: Right, you'd have a symlink like ~/repos/foo/checkouts/bar -> ~/repos/bar/
15:04mudgeTimMc: 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:05TimMcgfredericks: 1.4.0, I believe.
15:05mudgenot found in maven or clojars repositorys.
15:06TimMcgfredericks: http://search.maven.org/#search|gav|1|g%3A%22org.clojure%22%20AND%20a%3A%22clojure%22
15:06raekmudge: the dependency needs to exist first. one quick solution is to run 'lein install' in the dependency project
15:06gfredericksTimMc sonatype has 1.5.0-beta1
15:07TimMcgfredericks: Sure, but that's not a release.
15:07gfrederickswhy is lein run -m foo.bar/baz not working for me? it says class not found
15:07gfredericksI thought you could call a specific var with lein run
15:07hiredmangfredericks: have you tried loading foo.bar in a repl?
15:07TimMcI remember someone having trouble with that feature.
15:07gfredericksnope :)
15:08hiredmanI guess it will throw an error
15:08mudgeraek: do you mean that the dependacy needs to be in the local repository?
15:08gfredericksindeed it does
15:08hiredmanof course not the class not found error, but some other error that lein is swallowing
15:08SgeoUsing a global atom containing a map.
15:08gfrederickshiredman: thanks!
15:09SgeoWait, that idea does not work as intended.
15:09SgeoAnd I _just_ realized it now
15:09mudgewhen I make a checked out dependancy, does the dependancy have to be in the local maven repository?
15:09raekmudge: it needs to be in some repository
15:09mudgeraek: i see, I didn't know that
15:09frawrHi, 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:10mudgeraek: 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:10TimMcraek: I didn't know that either. :-/
15:10raekmudge: yes
15:10raekmudge: or start with one project and split them later
15:10mudgeI 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:11raekyes. you only need to install it locally once
15:11mudgeraek: but what happens if I make changes to the dependancy project, don't I then have to update the repository?
15:12raekI 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:12raekmudge: no
15:13raekmudge: lein will use any dependency information from the version in the repo, but the source code can be updated
15:13mudgeraek: 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:14mudgeraek: does that sound right?
15:14raekwell, it does look for the version it finds in the project.clj
15:15raekif I recall correctly it just puts the src/ of the checkout dependency first in the classpath (which overrides the repo version)
15:15raekwell, this would be clear from the output from 'lein classpath'
15:15mudgeraek: thanks
15:17mudgeI'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:17mudgeIsn't lein install supposed to put your project into the local repository?
15:17raekmudge: it isn't in your ~/.m2/ directory?
15:18mudgeraek: 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:20TimMcI 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:21raekyeah
15:22TimMcMaybe someone can make a patch to plumb checkout deps info through the deps downloading code.
15:28mudgeI am still getting a classNotFoundException with my checkout dependancy, I checked the classpath and the class is in the path
15:29raekmudge: what is the name of the namespace and how do you require it?
15:31mudgeraek: this is the namespace: com.perfectabstractions.im-client.components.ImComponent
15:31TimMcThat hy[hen looks like trouble.
15:31raekare you generating classes or is that last segment a namespace?
15:32mudgeraek: I import it in :import like this: (com.perfectabstractions.im-client.components ImComponent)
15:32mudge(ns (import: (com.perfectabstractions.im-client.components ImComponent)))
15:32mudge(ns mynamespace (import: (com.perfectabstractions.im-client.components ImComponent)))
15:32raekit should be ":import"
15:32mudgeraek: yes, sorry, it is :import
15:33raekand the directory should be called im_client if the namespace segment is called im-client
15:33mudgeraek: right, it is im_client
15:33raekmudge: are you using gen-class?
15:33mudgeraek: yes I am
15:33mudgeraek: i'll put the code in a gist
15:34raekthen 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:34mudgeraek: https://gist.github.com/4041394
15:35mudgeraek: yes, that namespace has been compiled
15:35raekhrm. maybe this is one of these cases when you need to use an underscore in Clojure
15:35mudgeraek: well I'll try it
15:35raeksince you're using Java interop to access the generated class
15:36raek(:import (com.perfectabstractions.im_client.components ImComponent))
15:36mudgeraek: oh my gosh, yes that is it
15:36mudgeraek: this works: (:import (com.perfectabstractions.im_client.components ImComponent)
15:36mudgewith the underscore like you said
15:37raekok, great!
15:37mudgeyea!
15:37mudgethanks very much for your help
15:37raeknp. :)
15:37moogatronicEmacs/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:39technomancymoogatronic: killing *nrepl-server* and re-running M-x nrepl-jack-in works for me
15:40moogatronicWhen i do that, and try to re-compile a class, I get "Namespace not found"
15:41moogatronicit seems to start the repl just fine however.
15:41brainproxywhen spec'ing metadata map for (def ...) is there any difference in using #^{...} vs ^{}
15:42moogatronicweird. 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:42raekbrainproxy: ^{} is the pre-Clojure 1.2 syntax
15:43raeksorry, there reverse!
15:43brainproxyokay
15:43raekman.
15:43raek^{} is what you use these days
15:43brainproxycool... both seem to work w/ clojure 1.4
15:52piranhaI have strange situation: some code works in REPL when I execute it, but when I do same in tests, it does not work
15:53piranhaand I really can't understand what's going on there... any clues? maybe some insights? I'll post some example soon
15:54piranhaah
15:54piranhaI'm sorry
15:54piranhafor + repl are doing strange things sometimes
15:54moogatronicExample code?
15:54raekfor returns values as a lazy seq. the for body is not evaluated until needed.
15:54piranhayes
15:54raekuse 'doseq' if you're after the side-effects
15:54amalloydon't use for to do side effects
15:55piranhaand in repl it's evaluated because I see return value :)
15:55raekexactly. :)
15:55piranhayes, I know, I just need to get used to that :)
15:55piranhait's already second time for a week when it brings me almost to panic :))
16:02TimMcI wonder if there's a kibit rule for hyphens in :import package names.
16:07daniel__can't i include a namespace (use 'backend.communication.zmq) which has a defrecord and then reference that defrecord in the repl?
16:08daniel__user=> (extends? CommunicationProtocol ZeroMQ) 9 (close [context] nil)) │CompilerException java.lang.RuntimeException: Unable to resolve symbol: ZeroM
16:11TimMcdaniel__: I think you need to also import the class the defrecord created.
16:11TimMcThis was certainly true in 1.2.
16:12daniel__thanks, works :D
16:13uvtcI 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/&gt;.
16:14uvtcAnd the repl tells me there *is* no `letfn*`: unable to resolve symbol.
16:14uvtcIs there a `letfn*`, or am I not understanding the macro in the source for `letfn`?
16:14raekuvtc: 'letfn*' is a special form. it is implemented in the compiler.
16:15TimMc&#'clojure.core/letfn*
16:15lazybotjava.lang.RuntimeException: Unable to resolve var: clojure.core/letfn* in this context
16:15raekso there is not letfn* var
16:15TimMcOh, OK.
16:15raek(like there is no 'if' var)
16:15TimMcI guess letfn has to have compiler support.
16:16uvtcOh. Hm. Ok. Thanks, raek. I suppose then that I'll have to look in the source for the docs on `letfn*`.
16:17raekI suspect 'letfn*' relates to 'letfn' as 'fn*' relates to 'fn'
16:17pjstadigi believe its because the fns are all aware of each other
16:17pjstadiglike you can reference one of the later fns in an earlier fn
16:18uvtcOh, ok. Thank you. :)
16:18daniel__user=> (def foo (ZeroMQ. "test" "test")) │#'user/foo
16:19daniel__so i instantiated my defrecord, how do i call methods on it?
16:19raekdaniel__: you use the protocol functions (which you require/use like ordinary functions)
16:19daniel__raek, where do i require/use them from
16:20pjstadigin the ns form where you want to use them
16:20daniel__i want to use them in the repl for now
16:21raekthen you use the 'require' or 'use' functions
16:21daniel__i have foo which is an instantiated protocol: user=> (def foo (ZeroMQ. "test" "test")) │#'user/foo
16:21raek(and quote the argument)
16:21raekdaniel__: in what ns does the protocol live?
16:21daniel__the defprotocol lives in backend.communication and the defrecord lives in backend.communication.zmq
16:22pjstadig(use '[backend.communication :only [THE-FUNCTION]])
16:22pjstadig(THE-FUNCTION foo)
16:22raekthen you need to do something like (require '[backend.communication :as comm] 'backend.communication.zmq) (import 'backend.communication.zmq.ZeroMQ)
16:23raek(comm/protocol-method foo arg1 arg2)
16:23daniel__i see, so the protocol is the function and i pass it the implementation
16:24daniel__(protocol-method implementation ... )
16:24raekprecisely
16:29jweisswhat'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:31daniel__user=> (require '[backend.communication :as comm] 'backend.communication.zmq)
16:31daniel__user=> (import 'backend.communication.zmq.ZeroMQ)
16:31daniel__user=> (comm/receive (ZeroMQ. "test" "test") "test")
16:31daniel__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:32hiredmandaniel__: pastebin
16:32daniel__should just return "test"
16:32daniel__http://pastebin.com/USQfhKGC
16:34raekdaniel__: and the ZeroMQ type/record implements the protocol?
16:35daniel__yeah
16:35daniel__wait, ill paste both bits of code
16:36daniel__https://gist.github.com/4041813
16:36daniel__im just testing receive at the moment, it should just return it's argument
16:37raekhrm, I can't see anything odd
16:37raekwait
16:38raekdaniel__: in the protocol (and the implementation) the function takes one arg, but you give it two
16:38raekyou need to include the "this" argument in the protocol
16:38daniel__but the defrecord takes two arguments
16:38raekoh wait, you did that
16:38daniel__receive takes 1
16:38raekdaniel__: send indeed takes two args, but receive takes 1
16:39raekand you pass reveive 2
16:39raek*receive
16:39raekthe instance and the string "test"
16:39raektry (comm/receive (ZeroMQ. "test" "test"))
16:39raekit should return the ZeroMQ instace
16:40daniel__this gives me #backend.communication.zmq.ZeroMQ{:context "test", :package "test"}
16:40daniel__what do i do with that?
16:40raekdaniel__: but that's what you wrote in (defrecord ZeroMQ ... (receive [context] context) ...)
16:41raekthe receive method, when invoked on a context, returns the context
16:41daniel__ok, thats not what i intended
16:41daniel__i intended that it would just return "test" since this is what i passed in as context
16:42daniel__i think i fundamentally mistunderstand something
16:42raekoh, I see
16:42raekdaniel__: you have too "context" variables in your code
16:42raekone is the record field
16:42raekthe other is the first argument to the methdo
16:42daniel__yeah, it gets passed through as the argument?
16:42daniel__i thought the methods would wrap their context in a closure
16:43raekyeah, the first argument is the "this" object
16:44raekdaniel__: let's rename the "receive" argument: (defrecord ZeroMQ [context package] (receive [context2] context2) ...)
16:44raekdoes it make sense now?
16:44daniel__the first argument to defrecord is this?
16:44daniel__not really
16:44daniel__:(
16:45daniel__whatever i pass through to defrecord should be used in each of the methods
16:45raekif you have (defprotocol FooProto (foo-method [a b c]))
16:45daniel__i intended for these contexts to be the same
16:45raekand (defrecord BarRec [x y] FooProto (foo-method [a b c] ...))
16:46raekwhen you call (def bar (BarRec. 1 2)) (foo-method bar 3 4)
16:46daniel__bar is passed to foo-method as a
16:46daniel__i get it
16:46raekthen you have x=1, y=2, a=<BarRec object with x=1, y=2>, b=3, and c=4
16:47raeksince 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:48daniel__ok, let me give this a try
16:48daniel__thanks
16:49raekthe field "context" and the first argument to the protocol functions can never be the same
16:49raekI mean, one is a part of the other
16:50raekit would be like having a vector [a b] and call it a
16:53daniel__yaaay, got it working
16:55daniel__so in the defprotocol, the first argument i give the methods needs to be 'this'
16:55daniel__so instead of (receive [context] it should be (receive [this context] ?
16:56daniel__in the defrecord it seems to work with one argument, as long as ignore it (receive [_] context)
16:56romanandreghey do you know if the semantics of subvecs in cljs are different from the ones of clojure on purpose?
16:56dnolen_romanandreg: what's the issue?
16:57tomojanyone seen an ":protocol/unsupported Unsupported protocol :ddb" error from datomic?
16:57romanandregdnolen_: in cljs `(subvec [1 2 3 4] 0 30)` => [1 2 3 4 nil nil nil …]
16:57romanandregdnolen_: in clojure… IndexOutOfBound exception
16:58daniel__its a bit like explicit self in python methods
17:00daniel__i dont quite see why having this is ever useful?
17:00daniel__having 'this'
17:00daniel__(defprotocol Proto (meth [this arg1 arg2]))
17:00daniel__when am i going to want to have this inside the method?
17:01daniel__how is that useful?
17:01dnolen_romanandreg: no explicit reason that I'm aware. patch welcome of course.
17:02romanandregdnolen_: I'm wondering if doing the check would incur in performance issues
17:03dnolen_romanandreg: not sure how since vectors keep track of their count.
17:03dnolen_romanandreg: very likely an oversight - that's all.
17:03tomojdaniel__: 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:04romanandregdnolen_: 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:05dnolen_romanandreg: seems likes a simple patch too - subvec just doesn't check bounds at the moment.
17:07amalloyaw man. i wrote subvec
17:07daniel__ok tomoj, are there any examples of protocols extending strings?
17:07daniel__i think a real world example or two might help me get my head around it
17:11tomojwell, there are plenty of other cases where you want this
17:11tomojhere's one example from core.cljs https://www.refheap.com/paste/037765df5f84e7ae012b27e8e
17:11tomojyou need this to be able to tell whether it's equal to other for IEquiv
17:13daniel__thanks tomoj, bookmarked
17:13daniel__gunna call it a night
17:14tomoj`mvn install` in datomic-pro seems to not work
17:14tomojbut `mvn install:install-file -Dfile=...jar -DpomFile=pom.xml` does
17:15tomojI guess that is not surprising
17:45pendlepantscan someone tell me what the idiomatic way would be to share a db instance across a clojure app?
17:46pendlepantsso 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:49ivanI would pass the db around into everything, regardless of what other people's macros are encouraging
17:55bosiei just switched to vimclojure (in vim, ofc). is there a way to go to the fucntion definition somehow?
17:56ToBeReplacedpendlepants: i was bothered by that too... you can avoid it by not defdb and instead passing around your connections to your entities
17:56ToBeReplacedpendlepants: for me, i ended up scrapping it and using java.jdbc and c3p0 directly
17:57ToBeReplacedway 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:58pendlepantsthanks, ivan/ToBeReplaced. I'll try it out w/o korma.
17:58ToBeReplacedfor when response is ... :headers {"Set-Cookie" ("ring-session=yaddayadda")}
17:58ivanmy korma is patched to take a pool created by bonecp
17:59ivanhaven't used it much other than to confirm it works
18:00ibdknoxfwiw, I've been looking for someone who has a vested interest in SQL to take Korma over
18:00ibdknoxI simply don't have time for it, especially given that I don't see in any SQL work in my future anytime soon
18:01ToBeReplacedyeah; it seems like a high-maintenance project
18:01ibdknoxnot overly
18:01ibdknoxThere's not really *that* much that needs to happen to appease just about everyone
18:02wingyis there a way to stop jetty server programmatically?
18:02tomojToBeReplaced: clj-http.cookies/wrap-cookies ?
18:02wingyis start it using (run-jetty #'handler {:port port :join? false})
18:03tomojwingy: call .stop on the return value of that, iirc
18:03wingyok
18:03tomojif you lost the return value, I think you have to kill the jvm :(
18:03ToBeReplacedwingy: def it before you start it, then .stop your-symbol
18:04wingytomoj ToBeReplaced: so it returns a java object?
18:04wingyi think i should use an atom here
18:04ToBeReplacedwingy: yes
18:08ToBeReplacedtomoj: yes that's it, if you also use wrap-lower-case-headers, thanks
18:12wingydoes this look ok: (swap! server #(run-jetty #'handler {:port port :join? false}))
18:12wingyim starting the server and updates the atom in the same time
18:14bbloomwingy: you can use reset! if you don't need the prior value of server
18:14bbloom,(let [a (atom 1)] (reset! a 2) a)
18:14clojurebot#<Atom@542c47d7: 2>
18:15wingyyeah it worked thx
18:16gtrakwingy, 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:16wingyyepp i noticed
18:21wingywhat 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:21gtrakderef
18:22wingyi updated the atom using (reset! server #(run-jetty #'handler {:port port :join? false}))
18:22wingyah
18:22eggheaddoes anyone use paredit with slime/nrepl? how can I make a newline without it submitting :(
18:22technomancyegghead: C-o should work
18:23TimMcDoes C-q help?
18:23TimMcwait, nvm
18:23wingygtrak: you mean (.stop @server)
18:23eggheadah thanks guys
18:23gtrakyes
18:23gtrakthe atom evals to itself, vars eval to what they point to
18:24eggheadi'm a paredit noob, I only use it for killing expressions and balancing parens
18:24gtraksymbols rather
18:24gtraksymbols eval to var lookups
18:24wingyI get No matching field found: stop for class clojure.lang.PersistentArrayMap
18:24gtrakwingy: perhaps run-jetty returns a map
18:24wingy(def server (atom {}))
18:25amalloyegghead: C-j
18:25gtrakhmm? did your reset never happen then?
18:25wingymy reset did happen
18:26wingyhere is my code: https://www.refheap.com/paste/6494
18:29wingya better one: https://www.refheap.com/paste/6495
18:31wingyToBeReplaced: do you know why i can't call .stop on the returned server?
18:34ToBeReplacedyou didn't reset the server in your refheap
18:34ToBeReplacedyou used a multimethod, and followed the second path
18:34ToBeReplacedoh config somewhere nvm
18:41ToBeReplacedwingy: issue resolved yet? why the reader macro in the reset! ?
18:41wingyToBeReplaced: what reader macro?
18:41wingyi can't get stop working yet
18:45ToBeReplacedwingy: take the # off of (reset! server #(yadda))
18:45wingyToBeReplaced: but that creates an anonymous fn
18:45wingyhm
18:46ToBeReplacedi 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:49bosiehow do you guys debug clojure, preferably with vim?
18:50wingyToBeReplaced: wohoo worked
18:54Somelauwbosie: I use tslime + tmux
18:55mattmoss&(let [x (atom nil)] (reset! x #(+ 3 4)) x)
18:55lazybot⇒ #<Atom@5d3011: #<sandbox7657$eval476836$fn__476837 sandbox7657$eval476836$fn__476837@aa003d>>
18:55mattmoss&(let [x (atom nil)] (reset! x #(+ 3 4)) @x)
18:55lazybot⇒ #<sandbox7657$eval476858$fn__476859 sandbox7657$eval476858$fn__476859@a56d69>
18:55Somelauwand I actually think it is elegant that way, but emacs people tell me it is not a real repl
18:56mattmossYou can put a fn in an atom w/ reset!, but it doesn't eval the func.
18:56mattmoss&(let [x (atom nil)] (reset! x #(+ 3 4)) (@x))
18:56lazybot⇒ 7
18:57mattmossHowever...
18:58mattmoss&(let [x (atom nil)] (swap! x (fn [_] (+ 3 4))) @x)
18:58lazybot⇒ 7
20:04bbloomdnolen: ping
20:13holohi!
20:14eggheadhi holo
20:17holowhat 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:18brehauthttp://www.clojuresphere.com ← holo
20:19holoha yes! that's it.. thanks brehaut
20:19tomojgrr https://www.refheap.com/paste/6fcd5e37b489c0e08f9a20ec7
20:20tomojoh, that was fixed 2 months ago
20:23holohey! i'm going to be the first one using metis..
20:24tomojcoincidence? "inspired by Active Record Validations"
20:29holo>.>
21:19tomojdakrone: thanks!
21:19dakronetomoj: no problem! (for what?)
21:19tomojthe cheshire fix
21:20dakronetomoj: :) thanks for finding it, silly mistake on my part
21:57bbloomif i never see an enum again, it will be too soon
21:57bbloom#{:mmmm :set :of :keywords}
21:57nightfly_yes, keywords for the win
21:58bbloomblows 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:59bbloomit's crazy how much work you need to do to get something half as useful as print and read
21:59bbloomand assoc :-)
22:00Sgeobbloom, what about Haskell data types with several constructors which each take 0 arguments?
22:00bbloomI don't know enough Haskell to comment, but I do remember thinking "instance Show" wtf?
22:01shachafinstance Show?
22:01bbloomshachaf: show is sorta like print
22:02shachafbbloom: Yes, I know.
22:02Sgeobbloom, you can tell Haskell to try to automatically make an instance of Show
22:02shachafWhat's the context?
22:02bbloomSgeo: like i said, i don't know much haskell
22:02bbloomi just know i <3 keywords :-)
22:14ChongLithe crazier thing is Haskell's Read
22:16ChongLiread :: Read a => String -> a
22:16shachafWhat's crazy about Read?
22:16ChongLithat it's polymorphic on a value rather than an argument
22:17shachafOh, well, sure.
22:17ChongLia lot of languages can't do that
22:17shachafYou can take a simpler example: class Bounded a where minBound, maxBound :: a
22:17shachafminBound :: Int = -9223372036854775808, etc.
22:17ChongLiyeah that's pretty weird too
22:19ChongLiI wish there were some way to do that in Clojure
22:19ChongLiwould make monads easier
22:20shachafIt's a bit tricky with dynamic types. :-)
22:20ChongLiyeah it's one of those tradeoffs
22:20ChongLilike the tradeoff between currying and arity overloading
22:21shachafSpeaking of crazy things in Haskell, there's Text.Printf.
22:22ChongLiyeah, a crazy hack
22:22ChongLihaha
22:22brehautalso HLists
22:23shachafPft, HList is too easy with modern GHC extensions.
22:24shachafdata HList :: [*] -> * where { Nill :: HList '[]; Cons :: t -> HList ts -> HList (t ': ts) }
22:24shachafs/ll/l/
22:24shachafCons True (Cons 'a' (Cons "hi" Nil)) :: HList '[Bool, Char, String]
22:25ChongLihmm that's weird
22:26brehautkids these days with their modern extensions.
22:27ChongLithe type system has gotten pretty crazy with them
22:27shachafWay too crazy.
22:27shachafI like my type system simple, like Agda's.
22:27brehautO_o
22:33bbloomI'm not sure that dynamic is what makes return type polymorphism hard, i think it's laziness
22:33bbloomlisps choose configurable laziness: functions vs macros
22:33bbloomwhere as haskell chooses always lazy, but you can't get the ast
22:33brehautbbloom: qi weakens your argument
22:33shachafI don't think you mean the same thing by "laziness" that Haskell people do...
22:34ChongLihow do you know which function to dispatch to if you don't know the type?
22:34bbloomsorry, brb
22:35brehautChongLi: how do protocols work?
22:35ChongLithey dispatch on the type of an argument
22:35brehautright, so a dynamic typed language can do that just fine; it just has to do it at runtime
22:35ChongLibut with return type polymorphism you don't know the type
22:35shachafYes, but that's not what we're talking about here.
22:35shachafmaxBound :: Word8 -- 255
22:36shachafmaxBound :: Word16 -- 65535
22:36shachafThat thing isn't a function at all. It's just a value.
22:36ChongLiyeah
22:36ChongLiit's set at compile time when the type is inferred
22:36shachafChongLi: Or at runtime.
22:36brehautevery method in the jvm has a return type; yes, those functions have no arguments but it doesnt mean the information is not available
22:36shachafSometimes you can't figure it out at compiletime.
22:37ChongLiif it can't be determined at compile time, doesn't haskell give an ambiguous type error?
22:38shachafNot necessarily. The constraints will just be propagated.
22:38ChongLiambiguous type variable
22:38ChongLiright
22:38ChongLibut if it never converges to a type somewhere down the line, it is ambiguous
22:39shachafSure, but you can compile a function that uses a Bounded on its own.
22:40shachafAnd in practice in the compiled code minBound might turn into a function instead of a constant. But that doesn't really matter.
22:40ChongLisure, but the result will still be based on whatever types are inferred
22:40ChongLiat compile time
22:40shachafRight, eventually.
22:40ChongLiall of the type information is gone at runtime (unless you're doing stuff with Data.Typeable)
22:41shachafSure.
22:41ChongLiI like to think of it as the type system just setting up all the plumbing
22:41shachafBut a polymorphic-over-Bounded function might get an extra argument with a Bounded dictionary.
22:41ChongLiyeah
22:42shachafBut that's just compilation details. :-)
22:42ChongLiI saw one article a guy wrote that talks about how to get rid of type classes in your code
22:42ChongLiby passing dictionaries explicitly
22:43shachafSometimes that's a much nicer approach.
22:43ChongLiit's pretty weird
22:43ChongLiit's basically just desugaring
22:43shachafAre you thinking of http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/ ?
22:44shachafI think he makes a good argument.
22:44shachafAs far as existential types + type classes are concerned, it's often simpler not to use either.
22:44ChongLiI haven't read this one, but I think the one I read reached the same conclusion
22:44shachafWell, the one I linked to argues for a specific use case.
22:45shachafJust an extension of the idea that [exists a. Show a *> a] ~ [String]. :-)
22:46SgeoThis conversation is now over my head.
22:47shachafThen raise your head!
22:47shachafI have the feeling all I ever end up doing in this channel is talking about Haskell.
22:47ChongLithe example he gives is pretty silly
22:48ChongLiit's rube-goldberg with types
22:48shachafWhich example?
22:48shachafThat's an actual library.
22:48ChongLithe first code snippet
22:48ChongLioh I'm not saying it isn't a valid example
22:48ChongLijust that people who write that stuff are being silly
22:48shachafWell, yes.
22:48shachafThat's his point. :-)
22:48shachafSometimes classes aren't the right solution.
22:49ChongLiit's akin to people who, upon learning clojure, make tons of records
22:49ChongLiinstead of just using maps and vectors
22:49shachaf"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:49shachafSure.
22:51ChongLiI'm trying to characterize the mindset that goes into these sorts of antipatterns
22:52ChongLisome kind of desire to be idiomatic?
22:53ChongLiit's the idea that if something's exists you have to use it
22:53shachafI 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:54ChongLihmm, maybe
22:55ChongLiyou know what bothers me?
22:55ChongLithe word "variable" and how it's misused so much
22:55ChongLiin clojure's documentation, it says that a lot of things are "not variables"
22:56ChongLisuch as let-bound names
22:56shachafIt's misused constantly.
22:56ChongLiwhereas in haskell they're called variables, using the mathematical definition of the term
22:56shachafI don't really care what words you use for something as long as you define them clearly and use them consistently.
22:57ChongLiit can be confusing for beginners though
22:57shachafMost things are. :-)
22:58ChongLiI've actually discussed this a lot with my friend
22:58ChongLiwe argue over the philosophy of language
22:58shachafI 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:58ChongLihe calls me a Wittgensteinian
22:58ChongLiwell, Haskell has a right to
22:58ChongLiit's old enough
22:58shachafIt is?
22:59shachaf1989 isn't that old.
22:59brehautits not like OO took those terms from a vacuum
22:59ChongLiit's old enough that such terms weren't nearly as widely used as they are today
22:59shachafHmm, I didn't think so. But I wouldn't really know, not having been around at the time. :-)
23:00ChongLisame goes for vi and emacs
23:00ChongLipeople complain about their "non-standard" key bindings
23:00shachafUh oh. No editor wars in here.
23:01bbloomspeaking of types....
23:01technomancythe standard WIMP definitions of "window" and "frame" really don't make any sense
23:02ChongLinah I'm not a na editor wars type
23:02bbloomi've got the closure script backend completely reworked to emit a javascript AST instead of printing strings!
23:02ChongLiI use both editors
23:02bbloomjust need to figure out the closure compiler type system, so that i stop getting horrible failures in advanced compilation mode :-)
23:02ChongLithey're both infinitely superior to mouse-based notepad clones :)
23:02bbloomhttps://github.com/brandonbloom/clojurescript/blob/js-ast/src/clj/cljs/compiler.clj
23:03bbloomlots more work to do cleaning it up & also want to write up some design notes
23:03ChongLijavascript makes my blood boil
23:04ChongLiugh I don't want to think about it
23:04bbloomas expected, it's much slower, but i think i'll also get the expected speed improvement if i skip the to-string step
23:04jonasenbbloom: cool!
23:05ChongLigreat work though
23:05ChongLiclojurescript is really cool
23:05bbloomyeah, this is more or less a direct port of the string emitting version
23:05bbloomnow that it's "pure" there are lots of opportunities for cleanup and simplification
23:05jonasenbbloom: what are the advantages over emitting strings
23:06jonasenbbloom: is the ast standardized?
23:06bbloomjonasen: i should be able to wire it up to automatically generate source maps ;-)
23:06ChongLimanipulating strings is always bad :)
23:06bbloomjonasen: the AST is rhino's
23:06bbloomit seems relatively stable
23:06shachafWhat about stringing manipulations?
23:06ChongLiit's why we love lisp languages
23:06bbloomi gotta run, but i'll provide more details as this evolves :-)
23:06ChongLiok, so it's not always bad
23:06DrakesonQuestion 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:06bbloomprobably on the mailing list
23:06bbloomcya
23:07ChongLibut it's much easier to manipulate data structures like ASTs than strings
23:15unnaliDrakeson: it wouldn't really be very Lispy (where the function is always first)
23:15tomojI get method completion anyway, sorta
23:16tomojI think with swank, you can complete to any methods on any classes that are imported
23:16unnali(-> foo-object (...)) gets you half-way there ;)
23:17brehautrearranging the method / object order wouldnt really help either; theres infrequently enough static type information to restricted it just to one class or interface
23:18unnaliindeed!
23:19ChongLiyeah I'm not sure what is gained by such rearranging
23:19ChongLihelp with auto-completion?
23:19ChongLithat's all I can really think of
23:19ChongLitype in an object and auto-complete on its methods
23:20ChongLibut that's a very different style of programming
23:20ChongLithat's "thinking in nouns" rather than verbs
23:20brehautexcept that its not going to help with autocompletion
23:20ChongLiwhy not?
23:21brehautbecause 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:21ChongLioh I wasn't referring to clojure specifically
23:22ChongLibut to "traditional" OO languages like java
23:22brehautthe other thing is that parametric polymorphism makes it less useful
23:22ChongLiyeah
23:23ChongLito really learn to be a functional prgrammer (when coming from a traditional OO background) requires a change in mindset
23:23ChongLifrom nouns to verbs
23:24ChongLiI think that sort of conflict is evident in the people that desire such a change
23:24ChongLiconflict is too strong a word
23:25Drakesonbrehaut: 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:26brehautwell yeah, obviously if you typehint, but…
23:26Drakesonand about it being not lispy, methods are not exactly functions, they are very stubborn about what you pass onto them ...
23:27ChongLiDrakeson: the point is that lisp considers the car (or first element) of a list to be a function
23:28ChongLiif you make some special case where the second element is now a method and the first is just a value
23:28ChongLihow do you implement that? it seems really messy
23:28brehautwell, clojure does use the . special form to indicate that it is a OO interop with .whatever desugaring to it anyway
23:28brehautbut yes
23:29DrakesonIMHO both `java-obj java-method ...' and `java-method java-obj ...' are messy and non-lispy.
23:29ChongLiso you'd still have to have the . special form occupy that position
23:29brehautwell you do anyway
23:29brehautit would just be the second and third arguments that switch position
23:30ChongLiDrakeson was talking about doing (my-object .mymethod)
23:30brehauti realise that
23:30brehautbut that could be (. my-object mymethod)
23:30Drakesonwell, you could also do it as (java-obj. :java-method ...), and find something else for `new'.
23:30ChongLioh, yeah
23:31ChongLiwell you could write a new macro to flip the arguments if you wanted
23:31brehauttrivially
23:32ChongLiI don't see the advantage though
23:32DrakesonChongLi: a new macro is moot. A reader macro would have been useful though, which I understand why it is not allowed.
23:32twobitspritewhy 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:32ChongLithe auto-completion type issue still remains
23:33brehauttwobitsprite: they dont have to
23:33ChongLiI like that clojure's reader doesn't have a huge amount of special syntax
23:33twobitspritebrehaut: no? I can put them after the args list?
23:33brehaut,(fn [a b] "docstring" (+ a b))
23:33clojurebot#<sandbox$eval27$fn__28 sandbox$eval27$fn__28@77409080>
23:33DrakesonAs I said, you might be able to narrow down possible types of the object and offer a union of all the types' methods.
23:34twobitspriteooohh :)
23:34brehautbut its kinda weird these days to do so
23:35twobitspritemaybe 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:35ChongLialso I think it could get confusing
23:35twobitspriteso, what about:
23:35DrakesonChongLi: I am arguing that that wouldn't need more special syntax.
23:36DrakesonIt would merely rearrange the meaning of a couple special forms.
23:36twobitsprite,(fn ([a b] "docstring1" (+ a b)) ([c d e] "docstring2" (- c d e)))
23:36clojurebot#<sandbox$eval55$fn__56 sandbox$eval55$fn__56@61254e91>
23:37ChongLiDrakeson: could you give me an example?
23:37TimMctwobitsprite, brehaut: I'm pretty sure that's a no-op.
23:37Drakesonof what?
23:37ChongLiof your proposed syntax
23:38TimMctwobitsprite: Try (defn foo [bar] "docs go here?" bar) in your REPL, followed by (doc foo).
23:38TimMcThe string is taken to be the first expression in the fn body.
23:39twobitspriteI just tried that, for some reasoning I'm get cannot resolve symbol: doc
23:39TimMcTry (use 'clojure.repl)
23:40twobitspriteyeah, you're right
23:40twobitspritejust says nil
23:40DrakesonWell, 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:41twobitspriteohh well... guess I'll have to get used to reading the args list after the docstring...
23:41ChongLiyeah I don't like 2
23:41TimMctwobitsprite: I came to appreciate it.
23:42TimMcdocs before impl
23:42DrakesonChongLi: why? (really looking for reasons, not to troll or anything)
23:42TimMcWell, no. Intent before specifics.
23:42sjlanyone 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:42ChongLibecause of how lisp treats the first element of a list
23:43ChongLithis would dramatically complicate that, making code a lot less readable
23:43twobitspriteTimMc: 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:44TimMcsjl: Works for me in lein test.
23:44twobitspriteanyways, 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:45DrakesonChongLi: 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:45tomojtwobitsprite: well, when you do (doc foo), you get the name, args, then docs, at least
23:46twobitspritetomoj: but that almost makes it worse... now it's just inconsistent...
23:46ChongLiDrakeson: in lisp you don't call objects
23:46ChongLiyou call functions (and special forms)
23:46twobitspriteit's just a minor nit pick... but it's just kind of bothersome :-\
23:46ChongLiputting an object (a noun) at the front of a list just makes it really confusing and arbitrary
23:47sjlTimMc: okay now it's returning false at the repl
23:47sjlargggh
23:47tomoj(defn foo [] "doc")
23:47TimMcsjl: At the REPL, try *clojure-version*
23:47tomojis that an empty function with a docstring, or a function that returns "doc" with no docstring?
23:47sjlTimMc: http://i.imgur.com/dd1bM.png
23:48twobitspritetomoj: I'm not saying it *should* be that way.. I'm just lamenting that the current way seems awkward
23:48xeqiChongLi: do you disapprove of ##({:a 1} :a) ?
23:48lazybot⇒ 1
23:48ChongLixeqi: no, because {:a 1} is a function
23:49ChongLimathematically, a map is just a synonym for a function
23:49TimMcsjl: Ah, so it's the output of a fn. Try (map class (c/to-keys "-1")). I think you'll be surprised.
23:50sjlTimMc: Oh cool, one is an Integer and one is a Long
23:50sjl"Simple"
23:50TimMcIn 1.4, that shouldn't matter...
23:50sjland people wonder why I say you need to know Java to write Clojure...
23:50tomoj&[*clojure-version* (= (Long. "1") (Integer. "1"))]
23:50lazybot⇒ [{:major 1, :minor 4, :incremental 0, :qualifier nil} true]
23:51TimMc&(= #{(Integer. -1) "-1" :-1} #{(Long. -1) "-1" :-1})
23:51lazybot⇒ false
23:51TimMcOho, so it is!
23:51tomojhah
23:51sjllol
23:51TimMcI had figured that one was a Symbol, since that would print the same way.
23:51TimMcIs this a regression?
23:52tomojappears still broken in 1.5.0-alpha4
23:52sjl&[(= (Integer. "1") (Long. "1")) (= #{(Integer. "1") (Long. "1")})]
23:52lazybotjava.lang.IllegalArgumentException: Duplicate key: 1
23:52sjl&[(= (Integer. "1") (Long. "1")) (= #{(Integer. "1")} #{(Long. "1")})]
23:52lazybot⇒ [true true]
23:52sjlwait what
23:53TimMc&(= {(Integer. -1) :val} {(Long. -1) :val})
23:53lazybot⇒ true
23:53DrakesonChongLi: 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:53ChongLiI wouldn't mind the syntax if it was something like this
23:53ChongLi((object :method) ...)
23:53tomojwhoa, bizarre
23:54jkkramerit's java's fault
23:54jkkramer&[(.hashCode (Integer. "-1")) (.hashCode (Long. "-1"))]
23:54lazybot⇒ [-1 0]
23:54TimMcloljure
23:54ChongLiit'd be like object was just a map
23:54sjloh man
23:54twobitspriteChongLi: a "method dispatch" map?
23:54sjlit's only negative numbers
23:54ChongLiyeah
23:55sjldram.test.context> (= #{(Integer. -1)} #{(Long. -1)})
23:55sjler
23:55sjl&(= #{(Integer. -1)} #{(Long. -1)})
23:55lazybot⇒ false
23:55sjl&(= #{(Integer. 1)} #{(Long. 1)})
23:55lazybot⇒ true
23:55sjldammit clojure
23:55TimMcjkkramer: Right, but I thought 1.3 or 1.4 fixed this.
23:55jkkramerthere was a debate about whether/how to handle this
23:55twobitspriteChongLi: are you familiar with dylan? they had an interesting method dispatch system, might be good to look at for something similar in clojure
23:55ChongLiI've heard of dylan, not familiar with it though
23:56ChongLiyou could probably write a macro that'd turn java objects into method dispatch maps
23:56ChongLiI still wouldn't use it though :)
23:56ChongLiI'm pretty happy with the way things are, just trying to help Drakeson
23:57DrakesonChongLi: Yeah, a dispatch map also makes.
23:58twobitspritewell... 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:58ChongLiit'd be a companion to import-static
23:58tomojhttps://groups.google.com/d/msg/clojure/7-hARL5c1lI/6Na-3J8fdFgJ one post about long/integer hashcode
23:58twobitspriteso, thinking of objects as maps of their methods seems fairly natural actually
23:59tomojI guess the 'fix' was ##(class 1) ?
23:59lazybot⇒ java.lang.Long
23:59twobitsprite##(class -1)
23:59lazybot⇒ java.lang.Long