#clojure logs

2011-07-15

01:46Demosthenesso i'm a lisp scripter (history of common lisp and racket) looking to distribute binaries to multiple platforms, any feedback on doing that for clojure (ie: windows w/ msi, linux?)
02:43ihodesDemosthenes: maybe I don't understand you, but can't you send off a jar?
03:36dans_can you clever folks give me some book recommendations?
03:40DranikPractical Clojure and then The Joy of Clojure
03:43dans_reading practical clojure :)
03:43dans_but i didnt mean just clojure or programming....just in general
03:46Dranikhave a look at rich hickey clojure bookshelf
03:47Dranikhttp://www.amazon.com/Clojure-Bookshelf/lm/R3LG3ZBZS4GCTH
03:49dans_thanks
03:50dans_ah nice
05:54tsdhDoes (:foo {:foo "bla"}) work because maps implement clojure.lang.ILookup?
06:04bsteuberyes
06:04teromtsdh: I think so, yes, at least based on skimming clojure.lang.Keyword source
06:04bsteuber if(obj instanceof ILookup)
06:04bsteuber return ((ILookup)obj).valAt(this);
06:04bsteuber return RT.get(obj, this);
06:05tsdhHm, would it be possible to make that interface a protocol, so that you could extend other types to support keyword lookup?
06:06tsdhFor example, I'd love to write (:name myNode) instead of (value myNode :name).
06:08bsteubertsdh: how about using a record?
06:08bsteuberor is it a java type you don't own?
06:19Pupeno_Hello.
06:21Pupeno_Anyone using Clojure+Slime on Aquamacs?
06:25tsdhbsteuber: It's a java type I do know.
06:32bsteubertsdh: then you're screwed basially
06:33bsteuberyou could subclass it oO
06:33bsteuberbut probably you just want to use your own ILookup replacement without the syntactic sugar
06:34tsdhbsteuber: Well, basically, the java types are in my control, so I could implement ILookup. But I don't want to create a dependency to clojure only because of some syntactic sugar.
06:42tibbeanyone know why PersistentHashMap uses hash collision leaves instead of extended hashing?
07:06Dranikhi all!
07:06bendlashi
07:07DranikI'm still struggling with utf8
07:07Dranikthis is what I'm doing
07:07Dranikhttps://gist.github.com/1084495
07:07Dranikthe encoding is still broken.
07:08Dranikhow to fix the encoding?
07:13cemerickDranik: Seems like that should be [:headers "Content-Type"]
07:13Draniklet me try...
07:15Dranikcemerick: didn't work :-(
07:17cemerickDranik: Clojure will load your source file as UTF8; is it saved in some other encoding?
07:18Dranikit shouldn't be bcs I use linux with LANG="ru_RU.UTF-8"
07:18cemerick(BTW, you can use the ring.util.response/content-type fn instead of rolling your own assoc-in)
07:19cemerickI'd double check in any case :-)
07:19Dranikcemerick: can you show how?
07:19cemerickhow what? Check the file encoding?
07:20Dranikok, wait, I'll try the content-type fn
07:21cemerickThat shouldn't do anything different than what you have, it's just better to use a standard fn instead of rolling your own.
07:21Dranikagree
07:22Dranikthough I still can't understend why it doesn't work
07:22cemerickAnyway, `file -I foo.txt` will (usually) report the encoding of files for me. (OS X here) Presumably the linux file command is similar enough.
07:23Dranikroutes.clj: text/html; charset=utf-8
07:23cemericknext, I'd curl -v the URL to see exactly what is being sent
07:23Dranikmoment...
07:25DranikContent-Type: text/html; charset=iso-8859-1
07:25Dranikand question marks in conent instead of unicode letters
07:27cemerickah, progress
07:27bendlasDranik: that's because most user agents send smth like "Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3"
07:27bendlasnotice that ISO-8859-1 is preferred over utf-8
07:28cemerickoh, hah
07:28bendlasand web servers oblige
07:28cemerickYou're setting the content type on the *request*, not the response.
07:28Dranikok, how to set it on the response?
07:29bendlasthe charset is subject to content negotiation
07:29bendlasAFAIR the served variant is chosen by the highest score
07:29Dranikbtw, how to get the user's input in utf-8 if he posts a form?
07:30cemerickbendlas: That's if the server supports the Accept headers; Ring doesn't, at least not out of the box (though I'm sure there's middleware somewhere that does).
07:31bendlascemerick: for the mime type that's true
07:31cemerickDranik: Something like (assoc-in (handler request) [:headers "Content-Type"] "text/html; charset=utf-8") will set it on the response, though you need to ensure that the handler's return value is coerced into a response object if necessary (it could be a String or File, etc).
07:31bendlasbut I always supposed, that the accept-charset stuff is handled by jetty, ...
07:32cemerickGood point, I'm not sure.
07:32cemerickHowever, if you're setting Content-Type as a ring header, I really doubt that jetty will quash it down to ISO-XXXX.
07:32bendlasbecause that happens between Reader/Writer land and IOStream land
07:32bendlaslet me check tough
07:33Dranikcemerick! yeah! that works!
07:33Dranikthanks!
07:34Dranikand how about the users input? will it be utf-8 out of the box?
07:34bendlashttps://github.com/mmcgrana/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L71
07:34bendlasDranik: java Strings are always unicode
07:35bendlasUTF-16 though (which doesn't have to bother you)
07:35Fossiexept for the boms ;)
07:35Dranikgreat!
07:36Dranikbendlas: thanks
07:36bendlasyou only need to be careful when reading from an InputStream
07:36Dranikis there anywhere an architecture description of Ring?
07:36bendlasi.e. slurp
07:36FossiDranik: yes, should be first or second hit on google
07:39bendlasDranik: hmm actually, you do get user input as an InputStream
07:39bendlasthe :body key on the request
07:40bendlasfortunately the request has a :character-encoding key to
07:40Dranikbendlas: so how to set it correctly?
07:40bendlasso you can do (InputStreamReader. (:body req) (:character-encoding req))
07:41bendlasto get a Reader Object from which you get properly decoded character data
07:41DranikOMG, isn't there a simplier way?
07:42bendlasyou need to read the inputstream anyway
07:43bendlasbecause you can't do anything with a plain inputstream
07:43Dranikwhy? if the user has just supplied his text in, for instance, in cyrillic encoding, I can access the form's fields
07:44Dranikthe question is: whether it will work the same way for utf8
07:44bendlasyou're talking about form data?
07:44Dranikyep
07:45bendlasthat is handled by ring.middleware.params
07:45bendlaswhich does the decoding at https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/params.clj#L50
07:46bendlasso yeah, it should work
07:46Dranikbut who does set the utf8 encoding there?
07:47bendlasthe utf8 _decoding_ is done by slurp
07:47Dranikok, great!
07:47bendlaswhich is aproximately (read-into-string (InputStreamReader. %))
07:47Dranikthanks!
07:47bendlasnp
08:42bsteuberwhat parsing libraries exist for clojure now?
08:42bsteuberlast time I checked there was only fnparse
08:43bsteuberbut I guess there's more now
08:45bendlasbsteuber: last I've heard, CCW switched to cgrand's parsley
08:46bendlashttps://github.com/cgrand/parsley
08:47bsteuberbendlas: thanks, looks interesting
08:48bendlasyw
09:03jcromartieinteresting... https://github.com/SergeyDidenko/Simple-Persistence-for-Clojure this is exactly the sort of thing (replaying simple transactions/events) I was thinking about lately
09:04jcromartieone small step out of the tarpit, actually :)
09:07jcromartienow if you add invariants you've got something
09:31jcromartieIs there any sense in maintaining my own `clj' script or /Library/Clojure or any of the other nonsense I've cobbled together?
09:31jcromartieit seems to confuse lein
09:37wjlroeI'm trying to do some web dev with clojure and I want the code to reload through slime obviously but running this - `(future (run-jetty example {:port 8080}))` results in a stacktrace (java.lang.IllegalMonitorStateException) (I'm following the examples from http://techbehindtech.com/2010/08/24/compojure-demystified-with-an-example-part-4/ )
09:40chrissbxIs it better style to write [a b] instead of (vector a b) to return multiple values?
09:41Chousukeyes
09:41Chousukeuse literals
09:42Chousukevector literals are a popular alternative for (list a b) as well
09:44chrissbxOk. BTW to my understanding "literal" means "constant", I find it a tad strange to say that vector syntax is a literal.
09:45chrissbx(The way you say it makes me guess that Clojure people are using the term this way freely, though.)
09:49Chousukechrissbx: if it were a constant I'd say constant :P
09:50Chousukethough in a way, it is a constant. as code, it's a vector of two symbols
09:51Chousukethe resulf of evaluating such a form is context-dependent though :)
09:51Chousukeresult*
09:53chrissbxWell, with this reasoning many expressions would be constant.
09:53chrissbxWhen I say literal, then I mean that the value of an expression is literally what I typed. Which isn't the case if symbols are replaced with values transparently.
09:54Chousuke[a b] is literally a vector of two symbols. it just evaluates to something else.
09:54chrissbxIf there would be some way to capture the expression before the symbols are replaced, then calling it a literal would have some validity.
09:55Chousukethat's (quote [a b]). but that's literally a list of a symbol and a vector :P
09:55chrissbxSo, you're saying that just a is a literal, too?
09:56Scriptor,(class (quote [a b]))
09:56clojurebotclojure.lang.PersistentVector
09:56ChousukeI'm not so sure about that.
09:56chrissbxNah, quote really makes it a constant.
09:56Chousukethe value of [a b] is constant after evaluating it though
09:57Chousukeso it's kind of difficult
09:57chrissbxWell, any value from an expression is constant after evaluating the expression.
09:57ChousukeI'm not sure what you would call a vector form if not a literal
09:57chrissbxAs long as the language is functional.
09:57chrissbxJust vector *syntax*.
09:57chrissbxBut maybe this is just me.
09:58Scriptorwhat's this discussion about?
09:58Chousukethe syntax is irrelevant to it actually being a vector though.
09:58Chousuke[a b] is not equivalent to (vector a b)
09:58Scriptorhuh, depends on the context, doesn't it?
09:58Chousuke(though they evaluate to the same thing)
09:59Scriptorif you're using a function, both will be evalauted to the same thing before you can do anything
09:59Chousukein the end I guess it doesn't matter too much but it's interesting to think about
09:59Scriptorbut if you use a macro they will be different lists
09:59Scriptorwell, not lists per se
09:59ChousukeScriptor: (vector a b) actually calls a function though. [a b] might do something else
10:00ScriptorChousuke: ah, right
10:01joegalloi think we mean vector literal in the sense that c has string literals and java has array literals and javascript has array and object and regex literals -- that is, this isn't some made up clojure thing :)
10:01joegallobut yeah, it's just syntax
10:01Scriptorlooks like when you pass [a b] to a macro it will pass an actual vector data structure
10:02Chousukeof course
10:02Scriptorbut vector needs to evaluate before it passes that, which is why if you try to use it with let it will complain that it got a list instead
10:02Chousukebecause [a b] *is* a vector :)
10:02Scriptoryep
10:02Scriptorhmm, this discussion is kind of like determinging whether
10:02Chousukesimilarly if you give #{:foo :bar} to a macro you will get an actual set
10:03Scriptor5 is equivalent to (+ 2 3)
10:03chrissbxMore like whether (infix 2 + 3) is equivalent to (+ 2 3)
10:03chrissbx(assuming that there's an infix form that translates to the latter)
10:03ChousukeScriptor: the evaluated results of both forms are identical
10:04ScriptorChousuke: right
10:04Scriptorbut passed to a macro they're different data structures
10:04Scriptorthe literal equals the result of the latter's evaluation
10:04Chousukein other languages this probably is a non-issue but lisps are funny like that :P it actually matters what your code is
10:05mdeboardhomoiconicity
10:05ScriptorI think it's a difference in how programmers read the code
10:05chrissbxWell, Clojure is probably the only lisp that has the vector syntax.
10:05Chousukecommon lisp has too
10:05Scriptorsomeone might see (vector 2 3) and thinks "the vector of 2 and 3"
10:05chrissbxAt least as source code (i.e. "literals" ;)
10:06Chousuke#(foo bar)... the difference is, they don't have evaluation semantics
10:06Chousukeor rather, it's just "return object as is"
10:06Scriptorwhereas we would see "the vectorization of 2 and 3" if we're passing it to a macro
10:06Chousukewhereas in clojure the evaluation strategy for a vector is to return the vector you get from evaluating all elements in the vector.
10:08Demosthenesso i'm a lisp scripter (history of common lisp and racket) looking to distribute binaries to multiple platforms, any feedback on doing that for clojure (ie: windows w/ msi, linux?)
10:08chrissbxI wasn't aware that you can have vector syntax in source code in CL; but yes it is implicitely quoted (i.e. a real constant..)
10:08ChousukeDemosthenes: I think the most common way is to just do it the Java way. ie. jars
10:09ChousukeDemosthenes: it's not quite the same as native packages, but it works
10:09mdeboardunless you're compiling to javascript
10:09mdeboardright?
10:09mdeboardor how does that work for clj on other platforms
10:10Scriptorwith CLI you can probably use one of the installer-builders that visual studio has
10:10Demosthenesmy issue is i commonly use scripting languages, and i need to distribute a stand alone binary to customers for a project
10:11Demosthenesand racket might fit the bill because it can make exe's
10:11Demosthenesbut libraries are an issue
10:11Scriptoryou can use jars to pack all the libraries into it
10:11Chousukeleiningen can make uberjars for you
10:11Scriptor^
10:11mdeboard(inc Chousuke)
10:11sexpbot⟹ 1
10:12Demosthenesdidn't someone just say they weren't like native packages?
10:12Scriptorquick question, how does the jvm know what code to start with in a jar/uberjar?
10:12Scriptorthere aren't any main methods as far I see
10:12Demosthenesand can a windows user just doubleclick a jar to launch?
10:13pjstadigit writes the main method to call to the jar manifest or something
10:16cemerickDemosthenes: If they have the Sun/Oracle JRE installed, yes, a double-click should run it.
10:18ChousukeDemosthenes: they are, in that they don't integrate with native package management
10:18Demosthenesah
10:19Chousukethough I'm pretty sure there are tools to put the jars in an MSI and creating launcher executables
10:19Chousukeafter all, java is pretty popular in the enterprise :P
10:19Chousuke+for
10:21Demostheneshrm, that could be a selling point
10:21ChousukeI don't know much about such tools but you will probably find something if you search
10:21mdeboardYeah I'm 100% certain jars in MSIs is pretty standard
10:21Demosthenesi've had great luck with scripting languages for my projects, but i can't expect an end user to install all the runtimes
10:22ChousukeClojure's pretty decent in that you can just include clojure.jar with your project. though the executable will tend to be somewhat large. :P
10:22jcromartiethere are good examples of native-ish Java apps out there... like Minecraft
10:23Chousukealso make sure you comply with all the licences when you bundle things. In Clojure's case the EPL should not be a problem (unless you modify Clojure itself)
10:24Chousukemost clojure-based libraries tend to use the EPL too
10:28cemerickDemosthenes: I've shipped the JRE wholesale to customers plenty in the past.
10:29Demosthenesinteresting ;]
10:29Demosthenesthat's an ability i've lacked with scripting languages
10:52Demosthenesi guess i oughtt o install a clojure environment and try out a few jars
11:02jcromartiey'all might find this useful: https://gist.github.com/1084860
11:15cemericktechnomancy: I had to do this to get javac running after AOT: https://gist.github.com/225e07be131eb8635d84
11:15cemerickDoes that seem idiomatic to you?
11:17cemerickDemosthenes: Yeah, you can put together an installer with the JRE + your app + a native launcher that works pretty well. I've used NSIS in the past for building launchers and installers, but there are comparable tools. A lot depends on your specific requirements.
11:22chrissbxI need to translate this Scheme code to Clojure, how would you do it?: (call-with-input-file foo read-all)
11:23joegallohttp://launch4j.sourceforge.net/
11:23chrissbxi.e. give a list of all s-exprs that are in the file named in foo
11:35joegallo(read-string (slurp foo))?
11:35chrissbxI can't even find how to open a file. I've looked in the navigation of the reference (and various pages) and the "cheatsheet".
11:35chrissbxslurp, aha
11:36joegalloread-string only reads the first object though
11:36chrissbxThat's a problem, yeah.
11:36chrissbxI've found with-in-str, but same problem
11:36joegallothen you would need to look at with-open, binding *in*, and read.
11:36chrissbxI mean, I've only found read, no read-all
11:37joegallokeep calling read repeatedly
11:37chrissbxwell can wrap this
11:37chrissbxyep
11:41chrissbxHow do you take optional arguments in a function?
11:41chrissbxother than "mis-using" &
11:42chrissbxsomething like (fn [a b &optional (c 1) (d 2)] ...)
11:42jcromartiechrissbx: you can use (fn ([arg list one] body one) ([arg list number two] body two)) to overload arity
11:42chrissbxwhere 1 and 2 are the default values for c and d if no argument is passed for those.
11:43chrissbxYes, I've learned about that already, but then I'd have to define an external function to allow me sharing code between the cases;
11:43chrissbxis this how you're doing things in Clojure?
11:45chrissbx(Also, that means to duplicate part of the argument lists, which can be a bit tedious in some cases)
11:46jcromartiechrissbx: there are some other defn varieities
11:46jcromartieI'm not sure if there's anything as extensive as CL's
11:47jcromartiebut you can user write your own :)
11:47jcromarties/user/sure/
11:47sexpbot<jcromartie> but you can sure write your own :)
11:47chrissbxI could, but then I'd be alone.
11:47jcromartieor you could contribute it back
11:47chrissbxWhere are those other defn varieties?
11:48jcromartiethere's defnk in clojure.contrib.def
11:48jcromartiethat's a keyword argument defn
11:49jcromartiewhat kind of argument bindings do you want?
11:49chrissbxJust an optional argument or two.
11:50jcromartieok so as an example
11:51jcromartielike what would your fn be
11:51jcromartie(paste it somewhere)
11:51jcromartiesorry
11:51jcromartiechrissbx: something like (fn [a b &optional (c 1) (d 2)] ...)
11:52chrissbxok, will do in a couple moments
12:00chrissbxjcromartie: http://paste.lisp.org/display/123288
12:00chrissbxWell, current-input-port is Scheme, dunno how to translate this.
12:00chrissbxAlso, I guess read in Clojure doesn't take a port argument?
12:00chrissbxAlso, I know I should use the loop macro instead of fn rec.
12:01jcromartieport? no... input stream yes
12:01chrissbxWell, that's the same thing I guess.
12:01chrissbxaka filehandle
12:02jcromartie,(doc read)
12:02clojurebot"([] [stream] [stream eof-error? eof-value] [stream eof-error? eof-value recursive?]); Reads the next object from stream, which must be an instance of java.io.PushbackReader or some derivee. stream defaults to the current value of *in* ."
12:02chrissbxok
12:03chrissbxSo I guess (aside these errors) what I wrote is how you'd do it?
12:03jcromartiesomething like that
12:03jcromartiewell hold on
12:04jcromartieyou might as well put the body of read-all-1 in the body of your 1-ary read-all
12:04chrissbxhm, that's true. Recurse to read-all.
12:06jcromartiehere's an idea
12:06jcromartie(take-while identity (repeatedly read))
12:08amalloyjcromartie: not very good. input forms could be nil or false
12:08jcromartietrue
12:10amalloyyou need something more like (let [in (PushbackReader. (reader filename)), sentinel (Object.)] (take-while (complement #{sentinel} (repeatedly #(read in false sentinel)))))
12:10amalloyor, slurp the whole thing into a string, slap [] around it, and then a single read-string will give you a vector of the objects
12:11technomancycemerick: you're leaving :java-source-path out of defproject explicitly in order to avoid pre-aot javac?
12:12technomancycemerick: it looks reasonable. my understanding is that 90+% of mixed-source projects have java as the lower level (legacy stuff) with clojure on top, which is why your use case is not more streamlined. is this something you see or expect to see commonly?
12:12technomancythis is only the second time I've heard of it.
12:14technomancycemerick: there is an open issue for this actually: https://github.com/technomancy/leiningen/issues/180 fwiw
12:14amalloylooks like my parens in the sample code above don't balance properly. adjust as necessary
12:15technomancyamalloy: what, you don't have paredit in irc?
12:15amalloytechnomancy: well, i got the right number of each kind
12:15amalloybut i nested them wrong
12:15technomancyoic
12:16amalloyi just installed paredit as a brain upgrade. seemed simpler than installing it for every editor i use (go ahead and ~guards me for not using erc)
12:19mdeboardAnyone know if there's a clojure wrapper lib for github api?
12:19mdeboardI asked before searching github obv
12:20amalloy$google clj-github
12:20sexpbot[alienscience/form-dot-clj - GitHub] https://github.com/alienscience/form-dot-clj
12:20amalloyhm
12:20amalloywell, yes, there is
12:20amalloybut it's for v2, maybe even v1
12:20cemericktechnomancy: Yes, I'm aiming to suppress the usual pre-AOT javac. I don't need it, but it's a helpful pattern to present to an audience that is more likely to have that sort of interop requirement.
12:20Scriptornothing clojure-y on here: http://develop.github.com/p/libraries.html
12:21Scriptorthough there's the java api
12:21technomancycemerick: yeah, especially if you're looking to demo hooks then that's spot-on.
12:21cemerickI've done it myself a couple of times in the past, but obviously didn't know the best way to do it in lein right off.
12:22cemerickWe'll have a bit dedicated to hooke in a different chapter unrelated to lein, FWIW.
12:22technomancycool
12:22minouhello, im new guys, when i do a load-file on slime does it takes much long or does it quit the user input on slime?
12:22cemerickpart of the "translating specialized design patterns into regular ol' clojure code" chapter
12:23technomancy"in which the gang of four are overthrown"
12:23cemerickheh, yeah, something like that
12:23cemerickThe chapter is currently called "Design patterns in Clojure"
12:23cemerickafter reading it, one could reasonably play the "It's a trap!" clip. :-D
12:24technomancyheh.
12:24cemerickSort of emblematic of the book as a whole, really.
12:25cemericktechnomancy: anyway, thanks for the help and pointers to fill in my lein coverage. :-)
12:27technomancyno problem; looking forward to seeing it completed
12:28cemerickas am I!
12:34DranikI can't wait when "Clojure Programming" is ready!..
12:40mdeboardDranik: Why
12:40mdeboardWhat about it makes you anticipate it
12:41Dranikit is focused on practical ways and tools for everyday programming
12:42Dranikin contrast, all the other published clojure books are mostly about the language itself
12:42mdeboardI see, that makes sense.
12:42mdeboardAnd web resources for practical programming in clojure are very slim
12:43Dranikclojuredocs.org is the best one for me
12:47chrissbxIs it bad to use the slash in symbols for anything other than namespaces? (I guess so?)
12:47amalloychrissbx: it's worse than bad: it's undefined behavior
12:47chrissbxLike, I often use names like foo/2 for a function foo that takes 2 arguments.
12:48chrissbxSo, do I have to replace this with foo:2 or something, I guess.
12:48amalloy*2 sounds a little clearer to me than :2, personally
12:49amalloybut i'm not sure you need this as much in clojure? i mean, sure, a little hungarian can be nice if it helps you remember. but clojure has :arglists metadata, so slime will prompt you with the right number of args anyway
12:50chrissbxI'm mainly using it in argument names to library functions, to indicate how many arguments are expected by a higher-order function.
12:50amalloyah. sensible
12:50amalloy&(class /)
12:50sexpbot⟹ clojure.core$_SLASH_
12:51chrissbxi.e. (defn myspecialfold [fn/3 & lists] ...)
12:51amalloyright
12:52chrissbxso I'm going to use * instead
12:57chrissbxHow do you append symbol names? i.e. (symbol-append 'a 'b) -> ab
12:58CozeyHello. Is (set (map ... )) lazy ?
12:58amalloy&(symbol (str 'a 'b))
12:58sexpbot⟹ ab
12:58amalloyCozey: no. sets can't be lazy
12:59amalloychrissbx: so, i guess, (def symbol-append (comp symbol str))
12:59Cozeyit seems so, but i wanted to be sure :)
13:00bsteuberbut cats can be lazy!
13:00amalloy&(doc lazy-cat)
13:00sexpbot⟹ "Macro ([& colls]); Expands to code which yields a lazy sequence of the concatenation of the supplied colls. Each coll expr is not evaluated until it is needed. (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))"
13:01ssideris_hello. in clojure 1.3, the (doc) function seems to be missing... anyone know what the new way is?
13:04jolyI'm curious about this too. When I start a new REPL, (doc map) works fine. If I switch namespaces, it doesn't work
13:05joly"Unable to resolve symbol: doc in this context..."
13:05ssideris_oh I didn't realize that it works initially
13:05ssideris_maybe it's a bug
13:06ssideris_https://github.com/technomancy/swank-clojure/issues/45
13:06amalloyjoly: a number of namespaces are automatically use'd in the <user> namespace, as a special convenience for you
13:07amalloyis what i recall
13:07amalloybut doc is in clojure.repl, so if you want it somewhere else, you should be able to (use 'clojure.repl)
13:07jolyamalloy: I thought core functions were imported into new namespaces, at least before 1.3
13:07amalloyjoly: it's not in core
13:07amalloyis it?
13:07amalloy&#'doc
13:07sexpbot⟹ #'clojure.core/doc
13:07amalloyoh, i lied
13:08ssideris_(use 'clojure.repl) worked for me
13:08ssideris_thanks!
13:08amalloymaybe it moved to repl in 1.3 then
13:09jolyoh, maybe that's it. (use 'clojure.repl) works for me too
13:09jolythanks
13:13bendlasMbleHey folks
13:16bendlasMble_I wonder: has the issue been raised, that one can't develop clojure applications under the GPL?
13:21jweissis there a straightforward way of recursively traversing a clojure.zip tree? (i can visit all nodes with zip/next, but I want to have an action performed when all the nodes in a subtree have been visited, which suggests recursion to me)
13:25hugodAnyone have opinions on how to control which exceptions break into the debugger in ritz? https://github.com/pallet/ritz/issues/14
13:33joegallobendlasMble_, what makes you think you can't?
13:41bendlasMblejoegallo, because clojure is epl
13:42chouserbendlasMble: yes. The party line is that that's the GPL's fault, not EPL's.
13:42bendlasMbleYou can't rerelease epl code under gpl
13:42joegallocan't i write a gpl program and add an exception to my own code saying it's okay to link with clojure, for instance?
13:43bendlasMbleMaybe. That's the reason i think i can't, anyway
13:44bendlasMbleHmm, interesting thought
13:44joegallohttp://en.wikipedia.org/wiki/GPL_linking_exception
13:44scgilardilooks relevant: http://stackoverflow.com/questions/168254/can-you-write-gpl-software-using-cpl-libraries
13:45joegallothe highest rated comment there seems to be about copying and pasting cpl code into your gpl program, though
13:45joegallowhich is missing the point of the question
13:46scgilardicpl faq reference may help.
13:46scgilardiif it weren't dead...
13:46joegalloheh
13:47joegallohttp://www.eclipse.org/legal/eplfaq.php#USEINANOTHER
13:47joegalloseems to be the same stuff at a different place
13:49joegallofwiw they seem to take the attitude there that using epl licensed code to write some program doesn't make that program a derivative work of the epl code, and that you can license your stuff however you'd like
13:51bendlas`IMHO the only real solution would be to dual licence clojure
13:52hvIs there an automatic way of generating clojure-api style docs for open source java libraries?
13:53joegallohttp://tomfaulhaber.github.com/autodoc/
13:55bendlas`I'm thinking about this, because I'm doing a project for which I'd really like strong copyleft
13:56bendlas`i.e. an end user program in an educational area
13:59pjstadigjoegallo: ?
13:59joegallohmmm???
13:59pjstadigthe epl is a weak copyleft license... changes to the original code must be released under EPL
14:00joegalloright, so if create a sweet new version of clojure, then that needs to be epl
14:00pjstadigyou can combine it with whatever code you want, distribute it as a binary, and use whatever license you want
14:00joegalloexactly
14:00pjstadigyou can also combine it at a source code level
14:00pjstadigbut any modifications to the files from the original project must be released under the EPL
14:01joegalloright, the problem is that the gpl side isn't as friendly, and wants everything to be gpl, but if you are the copyright holder, then you can license it as gpl+exception for clojure
14:01joegalloso i don't see the problem
14:01pjstadigand of course the original code must stay under the EPL, so you can't re-license it as GPL
14:01pjstadigjoegallo: yeah that was my thought, use gpl+exception
14:01joegallonow, if you are trying to take someone else's gpled program and combine it with someone else's epled program, then you are out of luck
14:02pjstadigbut i think you can only do gpl+exception in binary form
14:03joegallothe other way to do this is to just do what you want and wait for the letters from lawyers :)
14:03pjstadighehe
14:03bendlas`:)
14:03joegalloit's like linus and the proprietary drivers issue, if he refuses to stop you from releasing them, then does it really matter if the gpl says you are allowed to or not?
14:04joegalloin the end, the epl for clojure means whatever people are willing to sue over
14:04joegalloif the core is too busy to sue you, then i guess you escape
14:04joegallobut that's not really being a good citizen, and we all want to play fair
14:05hvjoegallo: thanks. Does autodoc generate APIs for java libraries, too?
14:05joegalloi dunno
14:05pjstadighv: doubt it
14:06hvjoegallo: thanks. I couldn't find anything related to java in it, so I asked to be sure.
14:06amalloy$javadoc
14:06hvpjstadig: thanks.
14:06amalloy$javadoc Integer
14:06sexpbothttp://download.oracle.com/javase/6/docs/api/java/lang/Integer.html
14:06amalloy(that is: you can use the built-in javadoc tool for that)
14:08hvamalloy: I want the API in a clojure-friendly format, not the ordinary javadoc.
14:08amalloywhat is "clojure-friendly"? if you're looking up java APIs for use with clojure, you better not be allergic to javadoc
14:11bendlas`I think the clojure autodoc format reflects the fact, that a clojure API prett much consists of functions in namespaces
14:12bendlas`where as in java you have packages, classes, methods in any combination of static, non-static, public, protected
14:12hvI use javadoc everyday. But for the future, clojure community will definitely need to have a place for reformatted java APIs (at least the important ones) for someone that does not know the least about java the language.
14:12bendlas`then the occasional member
14:12bendlas`not to mention types
14:13pjstadigmaybe it will change, but for now it is hard to totally avoid Java APIs in clojure, and there's no point in trying to hide that
14:13hvcurrently people are encouraged to learn some java and only then start learning clojure. That cannot go on forever.
14:14Scriptorthey are?
14:14Scriptorthis explains some confusion...
14:14amalloyi don't think that's true
14:14Scriptorhonestly though, as long as someone reads up on java pckaging and namespaces they should be more than fine
14:15amalloylearn clojure, and then when you run into some bits that need java, learn that
14:16hvamalloy: I believe for anything serious you will run into java apis fairly quickly, so you find it difficult to hold back learning java more than one week into learning clojure.
14:17amalloyhv: so? that's no reason to impose a strict "first java, then clojure" order
14:17amalloyif you do that, you'll never know which bits of java "matter"
14:19hvI would say first some java intro (hopefully written by someone who knows clojure) and then you can go on and learn clojure.
14:19Scriptoramalloy: to be honest, enough to know from looking at some java code what's what
14:20Scriptormost java code has plenty in common
14:20bendlas`i suggest, we have that talk about host platform doc, as soon as we have every java bit in clojure.lang behind protocols
14:20bendlas`and an impl of those protocols, that compiles to machine code
14:21bendlas`:D
14:24hvamalloy: the bottom line is, you need to know some java, and the amount of java that you need to know should be clear for a new student.
14:25amalloy*shrug* you may well be right. i came from java, so i'm not the target audience
14:26joegallostart with ejbs, that's what i always say
14:30Demosthenesyou know, i have avoided java apps for years... the only reason i'm considering clojure is it seems to be the only lisp i can package for my target audience without buying one of the commercial compilers.
14:31chouserDemosthenes: that is not a coincidence. That's a core Clojure goal.
14:32Demosthenesi'm not opposed to buying one, but as a small dev i can't outlay $1500-2500 bucks just to publish an app
14:32joegallohttp://www.gnu.org/licenses/gpl-faq.html#InterpreterIncompat
14:32joegallohttp://www.gnu.org/licenses/gpl-faq.html#GPLPluginsInNF
14:32Demosthenesi'd drop $500 in a heartbeat
14:32joegalloi was trying to find those earlier, but my google-fu was weak
14:33hvDemosthenes: you are not alone! I think more people have avoided java apps than people who liked them.
14:33Demostheneshv: well, all the "enterprise" apps i see in java (1.4!) are HORRIBLE
14:33Demosthenesmemory leaking, cpu sucking pigs.
14:33Demosthenesand the native java syntax makes my skin crawl.
14:34Demosthenesbut.... a lisp on jvm? i'm open to that
14:34pjstadigjoegallo: the FSF has a very precise and nuanced worldview
14:34joegalloitym gnu/worldview, but yes :)
14:35pjstadigdamn!
14:35hodappthe biggest problem with RMS is that he's ever right about anything.
14:44parasebais (class (int 42)) supposed to be a Long in clj 1.3.0?
14:45amalloyprobably
14:46parasebaamalloy: it's a little surprising
14:46parasebaI'd be ok with (class 42) being Long, but (int 42) too?
14:47amalloyparaseba: there's a related ticket on jira somewhere. something about aset-int breaking with the change to make ints autobox to Long
14:47amalloy$google clojure jira aset-int box long
14:47sexpbot[Overview - Clojure v1.2 API documentation] http://clojure.github.com/clojure/
14:47parasebait probably brings a lot of interop problems (I know I'm having them)
14:48Scriptorwhere's the clojure 1.3.0 repo?
14:49parasebaamalloy: maybe this? http://dev.clojure.org/jira/browse/CLJ-820
14:50parasebahum, created yesterday, no comments yet. I'm not sure if it's a bug, or a "feature"
14:50amalloyScriptor: it's the same as the 1.2 repo? github.com/clojure/clojure
14:51amalloyparaseba: i was thinking of something on the clojure-dev mailing list, apparently, not a jira issue
14:52amalloyhttp://groups.google.com/group/clojure-dev/browse_thread/thread/d64923aaaf18a22b?pli=1 is related
14:53amalloybut, as usual on google groups, i can't find the one i'm thinking of
14:53parasebaprobably this? https://groups.google.com/d/topic/clojure-dev/W4aFkFezW2g/discussion
14:53amalloyyes
14:54parasebahum, still not sure if it's intended or just a bug..
14:58raekparaseba: IIRC, 'int' and friends only return primitives if the return value is _immediately_ consumed by a function or method that takes a primitive as an argument
14:59raekif the receiver argument type is Object (like for 'class') the number will be boxed
14:59parasebaraek: but shouldn't be boxed to Integer?
15:01amalloyraek: that seems like a misstatement. it returns an int in all cases
15:01amalloybut most consumers box that
15:02raekparaseba: in clojure 1.3, byte, short, int and long are boxed to Long, and float and double are boxed to Double
15:02raekamalloy: ah, that makes sense
15:03raek,(= (int 1) (long 1))
15:03clojurebottrue
15:03raek,(set (int 1) (long 1))
15:03clojurebotjava.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$set
15:03parasebaraek: what I find strange is the behavior of int function. Even if we always box to Longs, shouldn't int box to Integer?
15:03amalloy&(.equals (int 1) (long 1))
15:03sexpbot⟹ false
15:03raek,#{ (int 1) (long 1)}
15:03clojurebot#{1 1}
15:03amalloyparaseba: no!
15:03amalloyint is sepcifically designed to not box things
15:04raekhere you have a set of an Int and a Long... (this is clojure 1.2)
15:04parasebaamalloy: hum, I see
15:04PupenoHello.
15:05PupenoIs it possible to have slime working with aquamacs?
15:05amalloyparaseba: the point is that int doesn't do any boxing (since it's for performance), and once it comes time to box, the compiler has lost track of the information that the thing was returned from (int)
15:06amalloy~aquamacs
15:06amalloyaw
15:06parasebaamalloy: that makes sense... so somewhere else the output of (int 42) is getting boxed into a Long, which is now the default box
15:06amalloyright
15:07parasebaso now, we need to do (Integer. 42) to create a boxed Integer
15:07amalloyPupeno: fsbot in #emacs says that "[aquamacs is] considered to be so significantly changed, buggy and "unemacs" that people in #emacs are known to be reluctant to help"
15:08Pupenoamalloy: I know, but it's pretty and I'm trying to show Clojure in a conference... well, I'll try to make TextMate work.
15:09raekPupeno: did you try the official swank-clojure instructions?
15:09parasebaamalloy: do you know where I can read about this changes in 1.3.0
15:10amalloyparaseba: i don't know of an official document (still!). on the rare occasions that i care, i find someone else who cares and ask them
15:11amalloyeg dnolen or cemerick
15:11Pupenoraek: I tried the ones in Clojure getting started, it didn't work. I didn't investigate as it said it's not supported but might work, I wanted to gather some feedback to see if anyone was actually using it or not.
15:11raekparaseba: https://github.com/clojure/clojure/blob/master/changes.txt and http://dev.clojure.org/display/design/Home
15:11aaelonyhi, what is the most idiomatic way to see if a file is gzipped? is there a gzipped? function somewhere?
15:12parasebaraek: will try that, thanks
15:14parasebaraek: and what about (class (short 42)) being Short? shouldn't that be Long too? according to " in clojure 1.3, byte, short, int and long are boxed to Long"
15:14paraseba(int) seems to be the only one having this behavior...
15:15parasebamaybe short and bytes are still being boxed to their corresponding types instead of Long?
15:15raekhrm, that is a bit odd :)
15:15raekhttp://dev.clojure.org/display/doc/Enhanced+Primitive+Support
15:15raekthis page says "all long-or-smaller integers are boxed as Long"
15:15amalloy"long or smaller". as if that were a necessary qualifier
15:15raekand "You can't use primitive coercions to force specific box types"
15:16parasebayes ... it's very specific about that
15:16raek...but apparently you can
15:16parasebaso, then, maybe (int) is the only one with the intended behavior
15:17aaelonyok, wrote one myself...
15:22raekit doesn't make sense for me that this is only done for 'int'...
15:22parasebaraek: or you could comment the jira ticket
15:22parasebaclj-820
15:40amalloyanyone know if brian marick hangs around in here, or do i have to send him an actual email to get in touch?
15:41raekamalloy: dunno, but he is very active on twitter
15:41amalloyoh god, so he is. i had to unfollow him eventually
15:45nybblesfliebel: this guy probably has some ideas for that: http://arstechnica.com/tech-policy/news/2011/02/how-one-security-firm-tracked-anonymousand-paid-a-heavy-price.ars
15:58CozeyDoes anyone here know if there is already any clojure job market ?
16:02amalloyCozey: there's some. i work at www.geni.com doing clojure with ninjudd, Raynes, and lancepantz
16:03CozeyI see also thortech is doing some clojure support
16:03Cozeyso geni makes money out of dead people, eh?
16:03amalloyi know ztellman works with amit and some other folks at www.runa.com
16:04amalloyand nathanmarz is at backtype, who were recently acquired by twitter
16:06jcromartieamalloy: got it... so you're saying use Clojure, get acquired by Twitter
16:06jcromartie:P
16:07Cozeyis clojure used mostly in data mining ?
16:08fliebelCozey: Have you seen the survey by cemerick?
16:08Cozeyoh i remember
16:08Cozeyright
16:08Cozeyalso Incanter is a big point here
16:08fliebelhttp://cemerick.com/2011/07/11/results-of-the-2011-state-of-clojure-survey/
16:11fliebelBut if so many people use Clojure for data mining, why aren;t there loads of similarity and clustering things, or even NLP stuff...
16:12kumarshantanuwhen i (load-file "file-name.clj"), can i let-bind local vars around it?
16:12fliebelkumarshantanu: huh?
16:13kumarshantanuso that the local binding will be available in the load-file'd code
16:13dnolenfliebel: not everyone using Clojure is interested in opensource.
16:13kumarshantanu(let [x :foo] (local-file "file.clj")) ; i want file.clj to have access to x
16:13kumarshantanus/local/load/
16:13sexpbot<kumarshantanu> (let [x :foo] (load-file "file.clj")) ; i want file.clj to have access to x
16:14fliebelkumarshantanu: I think you'd have to use binding.
16:14fliebeldnolen: but the same could be said of web frameworks, and we have tons of these.
16:17amalloykumarshantanu: no
16:18kumarshantanuamalloy: any alternative?
16:19amalloyglobal vars
16:19amalloyor, preferably, "stop trying to do things like that"
16:19technomancyfliebel: there's plenty of clustering libs on github
16:19technomancyjobbim, cascalog, conduit, work
16:20technomancypractically every mid-sized company using clojure has rolled their own
16:21amalloytechnomancy: eerily reminiscent of "the lisp curse"
16:21technomancyNLP is another story because it's actually difficult to implement. job distribution systems are decidedly not.
16:21PupenoAnybody remembers that comic about a young programming learning about closures and thinking they are the poor man's objects and then about objects and thinking they are the poor man's closures?
16:21amalloyPupeno: not a comic
16:21technomancyamalloy: eval plus amqp. done.
16:21Pupenoamalloy: I remember a comic strip.
16:22amalloyhttp://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html
16:22amalloysearch for "the venerable master qc na"
16:22amalloytechnomancy: amqp?
16:22technomancyamalloy: advanced message queueing protocol. rabbitmq being the popular implementation
16:23PupenoSomeone turned it into a comic.
16:23amalloyPupeno: okay. well, feel free to find that and paste a link here
16:23Pupenoamalloy: I will if I find it... but it's proving hard.
16:48fliebeltechnomancy: I was talking about *document* clustering, like k-means and stuff.
16:50Scriptorfliebel: what's the difference between document clustering and regular clustering?
16:50fliebelScriptor: The one is about classifying text, the other about distributing work.
16:51Scriptorer, I meant regular clustering as in just regular k-means, but I see document clustering means specifically clustering text
16:51Scriptorrather than, say, numbers
16:53fliebelScriptor: Uhm, well, I just wanted to make clear I was not talking about task queues and such.
16:53amalloyfliebel: i forget, are you the one who wrote sexpbot's ping plugin?
16:54fliebelamalloy: Well, you could say so, yes. But Raynes refactored it a lot I think.
16:55amalloyfliebel: Raynes never refactors, he just makes code uglier. i think i refactored it a lot
16:55Raynesamalloy: I hate you.
16:55fliebeloh, right :)
16:55amalloyanyway, i finally got around to figuring out what broke it ages ago (not your fault, of course) and fixing it. thought you might want to know it's working again
16:57fliebelamalloy: Did Raynes break it? So maybe it was him after all, who did the refactoring. Anyway, glad to know it works again, I used it *tons*
16:57amalloyhaha
16:58amalloywell, we did a global refactor on how plugins are supposed to send messages, and didn't update the ping plugin
17:00fliebel$huglle Raynes
17:00fliebelHm, I think there was something like that...
17:01fliebelhttps://github.com/cognitivedissonance/sexpbot/blob/master/src/sexpbot/plugins/utils.clj#L184
17:02amalloyfliebel: the word is huggle
17:02fliebelgood night
17:03amalloynight
17:08ssideris_hello... is there a way to create a proxy to an interface that is not known at compile time?
17:09Demosthenesdrewr: muahahaha
17:09ssideris_the fact that (proxy) is macro forces me to define the interface to be proxied at compile time, right?
17:09ssideris_*is a
17:12amalloyssideris_: you want to proxy an interface, but you don't know what it is? that sounds hard
17:13ssideris_I have a standard way of mapping certain keywords to certain java interfaces
17:13ssideris_and I'm trying to write the function/macro that will take a keyword as input (and some code) and produce a proxy for you
17:14amalloyssideris_: fwiw, if you're working with interfaces, 95% of the time you want reify, not proxy
17:14amalloynot that this fixes your current problem
17:15ssideris_oh that's a good tip, let me go and look it up
17:15ssideris_thanks
17:15ssideris_the actual problem though...
17:15whiddengiven a symbol that resolves to a name space. How do I determine if it is a macro or a function?
17:16ssideris_it does sound a bit reflection-heavy to be honest
17:17ssideris_amalloy: proxy seems to have the advantage of being able to selectively define methods, you don't need all of them...
17:17amalloyssideris_: "advantage"
17:18amalloyif you have an instance of an interface and only want to support some of its methods, you're not really conforming to the interface
17:19ssideris_when it comes to swing listeners, not all the methods are relevant all the time
17:19amalloywell, yes
17:20ssideris_it's hard :-)
17:21amalloyssideris_: i don't think that what proxy does is what you want for swing
17:21amalloyiirc if you call an implemented method, it throws an exception, not silently continues
17:22amalloy$javadoc java.awt.WindowListener
17:22amalloy$javadoc javax.swing.WindowListener
17:23amalloy$google java windowlistener
17:23sexpbot[WindowListener (Java 2 Platform SE v1.4.2)] http://download.oracle.com/javase/1.4.2/docs/api/java/awt/event/WindowListener.html
17:23amalloy&(doto (proxy [java.awt.event.WindowListener] [] (windowOpened [e] nil)) (.windowIconified nil))
17:23sexpbotjava.lang.IllegalStateException: Var null/null is unbound.
17:24ssideris_ok, then I'll use reify to silently suppress calls to the unimplemented parts
17:24ssideris_thanks
17:24amalloyyeah, that's pretty much your only choice
17:24amalloythough see also WindowAdapter
17:24ssideris_in fact, I think that is the source of a bug in my current implementation
17:25ssideris_so double-thanks
17:25ssideris_:-)
17:25ssideris_the adapters are useful, but don't exist for everything in swing
17:25amalloyi know
17:25ssideris_so I'm trying to offer a solution that covers everything
17:25amalloyyeah, i guess it's hard to see how to productively use an adapter
17:29ssideris_there are at least 2 other swing DSLs out there already, right?
17:29amalloydunno. not my problem
17:29amalloyall i know about is seesaw
17:31aaelonyhas anyone used to-time-zone from joda time? The doc says it takes a date and a time, but i get a string exception
17:31aaelonyjtime
17:31aaelony#<DateTime 2011-07-07T13:59:59.979Z>
17:31aaelony(to-time-zone jtime "America/Los_Angeles")
17:31aaelonyjava.lang.ClassCastException: java.lang.String cannot be cast to org.joda.time.DateTimeZone (NO_SOURCE_FILE:0)
17:31aaelonyany ideas?
17:33aaelonynevermind... it seems it needs to be a org.joda.time.tz.FixedDateTimeZone
17:33aaelonyfor the offset
17:34ssideris_amalloy: so why do you dislike swing so much?
17:34amalloyssideris_: that anyone would write WindowAdapter and not realize there's a problem saddens me
17:35ssideris_:-)
17:35ssideris_ok point taken
17:35amalloyit's an application of interfaces to a concept that doesn't really match
17:36amalloyif i were rewriting it today, i'd probable start with something closer to: public enum WindowEvent { ICONIFIED, ...}; public interface WindowListener { public void handle(WindowEvent e); };
17:37coopernurseamalloy: just tried out your fork of clj-doc-test - do you know if it has issues with functions in namespaces?
17:37amalloycoopernurse: uhhhh, i think i forked clj-doc-test and then didn't ever actually do anything to it. i have no knowledge about it, really
17:38coopernurseamalloy: ah, ok. thanks.
17:38coopernursefor pure functions it seems like a nice way to do tests
17:38coopernursebut it doesn't seem like it has caught on with the clojure community
17:39amalloyyeah, i had some grand plans for it, but i don't remember what they were and i think i decided they weren't a good idea
17:39amalloyit looks like my only commit was to make it cake/lein-friendly
17:46coopernurseamalloy: gotcha
17:57dabdI was looking for a way to write loops where you exit when a condition is met which is not very easy to do in a functional way. However I found trampolines very useful to implement this. Is this a common use case? I used it like this example http://pastebin.com/U5iecrhu
17:58amalloydabd: ew
17:59amalloydrop the trampoline, and replace #(max-4-matches ...) with (recur ...)
17:59dnolendabd: I don't see what stops you from just using recur, at least in this case.
18:00sritchiedabd: https://gist.github.com/1085641
18:00sritchiehaven't debugged that yet, but that's meant to be a straightforward conversion of what you'd had
18:01amalloythough tbh the whole function can easily be written as (count (take 4 (filter #{\x \o} s)))
18:01dabdsritchie: any advantages of using your version vs trampolines?
18:01dnolendabd: trampolines are pretty slow, and just unidiomatic for what you're doing.
18:02sritchieyou don't need mutual recursion between two functions, here, just a single recursion
18:02dabdok
18:03amalloysomeone tell me if i'm wrong, but i think any trampoline that doesn't involve mutual recursion can be trivially transformed into a loop/recur
18:03dnolenamalloy: trampoline is for mutual recursion.
18:04dabdamalloy: let me test your version
18:04sritchiedabd: https://gist.github.com/1085641
18:04sritchiethat's a little cleaner
18:04sritchie(than the first one I posted, imo)
18:05amalloydnolen: i know
18:05dnolenamalloy: i know you know :) came out the wrong way.
18:05dnolendabd: amalloy solution is the best way to do what you want and quite concise.
18:06sritchieamalloy: haha, didn't see that
18:06dekuderpI'm having a bit of trouble; the compiler is telling me I'm not recurring from a proper tail position
18:06dekuderphttps://gist.github.com/1085656
18:07dekuderpspecifically, I get: Can only recur from tail position (map_maker.clj:13)
18:07amalloydekuderp: move the second recur into the if
18:07dabdunfortunately none of the versions work as I intend: I want to check how many consecutive \x or \o chars are in the string stopping as soon as I find 4 but anytime I find a different char I reset the counter
18:07amalloyactually, look up how if works
18:07sritchieI think you're also forgetting parens around your different function versions
18:07sritchieso, wrap [xmax ymax] (recur xmax ymax xmax ymax {}) in parens, as well as the next argvec-body pair
18:08dekuderpamalloy: thanks
18:08dekuderpsritchie: so every [arg] (function body) should be ([arg] (function body))?
18:08sritchieyeah
18:10dekuderpokay here is the new error I am getting: Mismatched argument count to recur, expected: 2 args, got: 5 (map_maker.clj:13)
18:10dabdofc it is easy to correct amalloy's version to have this behavior thanks guys
18:10dekuderphttps://gist.github.com/1085665
18:10dabdsorry I meant sritchie's version
18:11dekuderpso why can't it tell that there is a 5-arg version? I thought I've written clojure code that works like this, but perhaps I'm misremembering
18:12sritchieI usually write (generate-map xmax ymax xmax ymax {})) in this case -- not sure why recur doesn't jump between the different arg versions, though
18:12amalloydekuderp: recur doesn't work that way. you can only recur to the top of the current body
18:12amalloysritchie: because recur is a GOTO, and each function body is a method
18:12sritchiegot it
18:13dekuderpamalloy: thanks!
18:17jonabbeyquestion: did anyone come up with any better pattern for closing streams in clojure than was discussed in http://groups.google.com/group/clojure/browse_thread/thread/b9238d1c26997eea/c85b2e289ae92c88?lnk=gst&amp;q=lazy+stream&amp;fwc=1 ?
18:18jonabbeyi.e, there remain no deterministic destructors in clojure, so you have to do all management of stream lifespan with functional resource management blocks?
18:19jonabbeyi'm trying to do a lazy seq on a stream reader, and i've got it working, but it doesn't close the stream unless the lazy seq is evaluated to the end
18:21dekuderpin this function: https://gist.github.com/1085679 why doesn't (if (and (zero? ycur) (zero? xcur)) worldmap) cause the generate-map function to return the worldmap data structure?
18:22dekuderpafter setting up a few printouts I figured out that it is getting hit, but that the function isn't returning, instead getting stuck in an infinite loop
18:24jonabbey/list-usrs
18:24jonabbeyer
18:27amalloydekuderp: again, look up how if works
18:27amalloy&((fn [] (if true 1) (if false 2) 3))
18:27sexpbot⟹ 3
18:30dekuderpso how do I prevent the continued evaluation? am I supposed to be using cond instead?
18:31dekuderpthis http://clojure.org/special_forms#if isn't really helping me understand my mistake, but I'm looking for other stuff too
18:31amalloyyes, but you can do it with if
18:31amalloy&((fn [] (if true 1 (if false 2 3)))
18:31sexpbot⟹ 1 ; Adjusted to ((fn [] (if true 1 (if false 2 3))))
18:31amalloysexpbot: smartass
18:32amalloydekuderp: the general thrust is, every expression returns something, always
18:32amalloy"early" returns are silently ignored by the special form (do expr1 expr2), which defn includes implicitly
18:33dekuderpso the only way to make an if statement have the power to return a value for the parent function is to chain the if's together?
18:33dekuderpok, I think I sorta get it now
18:33amalloyyes, though you should try to stop thinking about early returns
18:33amalloythose are "statements": "return this value now"
18:34amalloyclojure just has expressions, describing *what* the result of an expression is, not *how* to get it
18:35AbezethibouHello all.. After a same studing aboud Common lisp (aproximately a year)
18:36AbezethibouI start to study clojure
18:36dnolenjonabbey: lazy-seqs and resources don't really play together well, open design problem.
18:36AbezethibouI am reading practical clojure
18:36dekuderpamalloy: thank you very much for helping me understand htat
18:36dekuderpthat*
18:36Abezethibouand little bit joy of clojure
18:37AbezethibouDoes anyone have any suggestion about a complate book
18:38kylpotechnomancy: I've been thinking about learning lisp before clojure. Would you recommend I stick with that plan? Or just go right for clojure. Currently my goal is for learning/practice, I don't really have a project in mind.
18:38technomancykylpo: you mean common lisp?
18:39kylpotechnomancy: yes. The book I'm using is Land of Lisp: http://www.amazon.com/Land-Lisp-Learn-Program-Game/dp/1593272812
18:39bsteuberkylpo: just learn clojure ^^
18:40technomancykylpo: I don't think there's any value in learning CL at all
18:40kylpotechnomancy: K, thanks. Except for understanding elisp, right?
18:41technomancythat's true; CL has a lot of overlap with elisp
18:41technomancyand it has a lot more literature
18:41kylpotechnomancy: do you have an elisp book you like?
18:41technomancykylpo: no, not really
18:41kylpotechnomancy: k
18:42technomancyI guess I learned most of my elisp from Practical CL
18:42kylpotechnomancy: a clojure book you like?
18:42technomancyonly got about halfway through the book though
18:42technomancykylpo: I've read Programming Clojure and the Joy of Clojure. good and great respectively
18:42technomancyPC if you just want the basics quickly and JoC for a more thorough grounding
18:43kylpotechnomancy: K, thanks. I'm thinking I'll check out your peepcast, too. Making games are good ways for me to practice.
18:43technomancyyeah, games are great
19:07dekuderpso apparently this function is not correctly generating a data structure I want: https://gist.github.com/1085752
19:07dekuderpI think this command shows that my logic is sound:
19:07dekuderp,(if (nil? ((keyword (str 1)) {})) (assoc {} (keyword (str 1)) {}))
19:07clojurebot{:1 {}}
19:08dekuderpbut for some reason the function only returns nil instead of the real structure I want
19:11amalloyi'm not sure exactly what your function is trying to do, but it looks like it's in need of update-in and fnil
19:13amalloy(dekuderp: that last directed at you)
19:15amalloydekuderp: note also that ##(assoc nil :x :y) works just fine with nil
19:15lazybot⟹ {:x :y}
19:21ssideris_what's a concise way to go from [[1 10] [2 20]] -> [[1 2] [10 20]] ?
19:21ssideris_for the general case
19:24ssideris_duh, I suppose [(map first v) (map second v)]
19:24ssideris_where v is the structure
19:25ssideris_the vector I mean
19:26amalloy&(apply map vector [[1 10] [2 20]])
19:26lazybot⟹ ([1 2] [10 20])
19:27amalloyssideris_: more general, working for NxM matrices
19:28ssideris_wow nice
19:28ssideris_thanks
19:29dekuderpum, I have been looking at the documentation for update-in, and it seems really useful, but I don't know how to use it
19:29dekuderpthe only example I got to work in my repl is ##(update-in {} [(keyword (str 1)) (keyword (str 2))] {})
19:29lazybot⟹ {:1 {:2 nil}}
19:29amalloydekuderp: well, explain to me what your function is actually doing
19:30amalloythe mess of repeated nested assocs is not easy to follow
19:31dekuderpI want to create a 2d matrix to store other maps in
19:31amalloyso maybe just assoc-in?
19:31amalloy&(assoc-in nil [:1 :2] "data")
19:31lazybot⟹ {:1 {:2 "data"}}
19:32dekuderpamalloy: that is definitely the function I was looking for
19:32dekuderpand I would use update-in for updating the 2d array, right?
19:33amalloyfor changing one entry in it
19:33dekuderpokay, well those functions certainly make life easier
19:33dekuderpthanks!
19:34amalloy&(let [world (-> nil (assoc-in [:1 :2] "data") (assoc-in [:3 :5] 9))] (update-in world [:3 :5] dec))
19:34lazybot⟹ {:3 {:5 8}, :1 {:2 "data"}}
19:34amalloyi still don't understand at all why you want to use keywords as keys instead of numbers
19:35amalloydekuderp: ^ all that stuff
19:37dekuderpamlloy: what do you mean? I am using numbers
19:37dekuderpI am using ##(keyword (str 1)) and such for every num
19:37lazybot⟹ :1
19:38dekuderpat least that's how I figured out how to turn numbers into keys
19:41dekuderpI'm guessing that I'm doing it wrong?
19:41amalloystop making numbers keys! we had this discussion the other day, didn't we? you can just use the actual integer 1 as a key
19:42amalloy&{1 'test, 10 'sample}
19:42lazybot⟹ {1 test, 10 sample}
19:42dekuderpoh, now I get it
19:42amalloyor use a vector of vectors, since vectors are indexed by index anyway
19:43dekuderpdo you think I should be using vectors?
19:43dekuderpI'm not very sure of the trade off in my case, so my choice was pretty arbitrary
19:43amalloy&(let [world (vec (repeat 4 (vec (repeat 4 nil))))] (assoc-in world [3 1] 'test))
19:43lazybot⟹ [[nil nil nil nil] [nil nil nil nil] [nil nil nil nil] [nil test nil nil]]
19:45amalloyif the world is large and mostly empty, a map is surely better. otherwise, it probably depends but doesn't matter much
19:46dekuderpokay, I'll try it with vectors since I am planning on storing data at every entry
20:20mdeboard,(min-key 7 8 9(
20:20clojurebotEOF while reading
20:20mdeboard,(min-key (7 8))
20:20clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
20:20mdeboardCan someone clue me in on what min-key is for :|
20:21amalloy&(min-key :size {:size 1 :name "test"} {:data 4 :size 10})
20:21lazybot⇒ {:size 1, :name "test"}
20:21amalloy&(min-key - 1 2 3)
20:21lazybot⇒ 3
20:22amalloymdeboard: ^
20:29mdeboard&(min-key - 3 2 1)
20:29lazybot⇒ 3
20:29mdeboardwhat.
20:30mdeboard&(min-key + 1 2 3)
20:30lazybot⇒ 1
20:31amalloymdeboard: it calls - on each element before comparing
20:31amalloyand -3 is smaller than -1
20:31mdeboardOh.
20:31mdeboard&(min-key (partial (< 3)) 1 2 3)
20:31lazybotjava.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial
20:32mdeboard&(min-key (> 3 %) 1 2 3)
20:32lazybotjava.lang.Exception: Unable to resolve symbol: % in this context
20:32dnolen&(min-key (partial < 3) 1 2 3)
20:32lazybotjava.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number
20:32amalloymdeboard: unlikely to work anyway. > returns a boolean
20:33dnolen&(min-key (partial min 3) 1 2 3)
20:33lazybot⇒ 1
20:34mdeboardI see
20:38dekuderpis there an easy way to generate a random # between 0 and 1 in clojure?
20:39amalloy&(rand)
20:39lazybot⇒ 0.5675409978355913
20:39dnolen,(rand-int 2)
20:39clojurebot0
20:40dnolen,(take 10 (repeatedly #(rand-int 2)))
20:40clojurebot(0 1 1 1 0 1 1 0 0 0)
20:40dnolen,(take 10 (repeatedly rand))
20:40clojurebot(0.8182436567649329 0.9637135524821122 0.9122072063831675 0.2888228218745055 0.3761627320246498 0.2602531326683677 0.34970107144974993 0.8873792800568543 0.4710056658729913 0.7726407255548855)
20:42mdeboardNow, can someone give me a very very simple example of apply's usage? :\
20:43dekuderpthanks!
20:43mdeboardThe actual operation indicated by the ->> macro would seem like it woul be described with "apply"
20:43technomancymdeboard: (apply * [1 2 3])
20:43technomancybecomes (* 1 2 3)
20:43amalloydnolen: repeatedly takes an optional how-many arg these days
20:44mdeboardtechnomancy: So .. it's reduce?
20:44amalloy&((juxt apply reduce) (partial list '*) [1 2 3])
20:44lazybot⇒ [(* 1 2 3) (* (* 1 2) 3)]
20:44amalloymdeboard: the difference is that
20:44technomancymdeboard: (reduce * [1 2 3]) results in two calls to *
20:44technomancymdeboard: apply is a single call
20:45mdeboardah
20:45mdeboardinterestink
20:55technomancyamalloy: oh dang; I didn't catch what was going on there
20:55technomancyit's like your own private macroexpand-like facility
20:55amalloytechnomancy: more like a trace
21:21mdeboard_&(apply + [1 2 3])
21:21lazybot⇒ 6
21:23mdeboard_&(apply min-key 5 [1 2 3])
21:23lazybotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
21:27mdeboard_&(min-key min [
21:27lazybot⇒ [] ; Adjusted to (min-key min [])
21:27brehautwait; lazybot? when did that happen
21:28mdeboard_&(min-key min [1 2 3] [4 5 6] [7 8 9])
21:28lazybotjava.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number
21:28mdeboard_&(min 1,2,3)
21:28lazybot⇒ 1
21:29mdeboard_Sorry I'm on my phone at Harry potter. This is the only repl I have :(
21:29brehautmdeboard: damning review of a the movie there
21:30amalloybrehaut: earlier this afternoon
21:30amalloymdeboard_: you can /msg lazybot &(min 1 2 3)
21:31mdeboard_Ya doing that now amalloy
21:31mdeboard_brehaut: We're here early.
21:37babilenmdeboard_: https://market.android.com/details?id=com.sattvik.clojure_repl (fwiw) -- but watch the movie, and don't play with the phone ;)
21:37mdeboard_I'm on iPhone :(
21:55ihodescemerick: hey chas
22:01cemerickhey :-)
22:21gfrlog`clojurebot: lazybot?
22:23amalloyclojurebot: lazybot is sexpbot's new name. Same bot, same features, less nsfw-looking name!
22:23amalloyclojurebot: ping?
22:24amalloy,1
22:24gfrlog`clojurebot was only ever interested in sexpbot
22:24amalloyhiredman: clojurebot seems to be dead
22:24ihodescemerick: haha i didn't mean pick me for any particular reason, just a student who's using Clojure, though not in the classroom
22:25cemerickihodes: Yeah, I had no idea you were a student, actually. :-)
22:38ihodescemerick: for one more year, at least. i wish the CS dpt used Clojure. i'm a math major anyway, though. it feels more like programming anyway.
22:39cemerickihodes: Check your PMs :-)
22:46gfrlog`&(nth (sorted-set 1 2 3) 1)
22:46lazybotjava.lang.UnsupportedOperationException: nth not supported on this type: PersistentTreeSet
22:46gfrlog`:(
22:51amalloygfrlog`: the sorted-set impl couldn't do that any faster than ##(nth (seq (sorted-set 1 2 3)) 1) anyway
22:51lazybot⇒ 2
22:52amalloybut i bet there's a measure for a finger tree that combines sorting with random access
22:56gfrlog`amalloy: a tree set can't nth? :/
22:56gfrlog`that's....unnecessary
22:57amalloyno, why would it bother?
22:57gfrlog`because it's so close to being able to?
22:58amalloyno it isn't
22:58gfrlog`then I don't know what a tree set is
22:59amalloyit would have to track, at each node, how many things are in the left and the right branch
22:59gfrlog`amalloy: that's what I meant by so close
22:59gfrlog`all it would have to do is track, at each node, how many things are in the left and the right branch
22:59amalloygfrlog`: i imagine clojure's persistent tree set is pretty close to the mutable tree set. for a mutable set it's a bigger change
23:00amalloybut seriously, this is what finger trees are for. go try them out
23:00gfrlog`I know :(
23:00Scriptoramalloy: like, teh #{} kind of set?
23:00Scriptor*the
23:01gfrlog`Scriptor: ##(sorted-set 1 3 2)
23:01lazybot⇒ #{1 2 3}
23:01amalloyScriptor: uh, what is this in reference to?
23:01Scriptoramalloy: <amalloy> gfrlog`: i imagine clojure's persistent tree set is pretty close to the mutable tree set. for a mutable set it's a bigger change
23:01amalloyScriptor: #{} is a hash set (well, probably array set)
23:02amalloysorted-set is a tree set
23:02Scriptorah, interesting
23:02amalloygfrlog`: a mutable tree set would have to percolate the changes back up to the root at every insertion
23:02amalloypersistent tree sets have to do that anyway
23:03gfrlog`amalloy: so how would clojure's implementation be "pretty close" to the mutable tree set?
23:03amalloygfrlog`: i dunno man
23:03gfrlog`it seems like an all or nothing attribute to me
23:06amalloyi mean the code to implement it seems like it would be similar, not that they would behave similarly
23:06amalloyand who knows, maybe i'm wrong. feel free to read more thoroughly into the source; i've only skimmed
23:08amalloycuddle-trees
23:09gfrlog`rooted acyclic graphs with ordered children
23:10gfrlog`(ragwoc?)
23:10gfrlog`I guess that's a description of trees generally, not finger-trees specifically :/
23:14amalloytrees don't neessarily have ordered children
23:14gfrlog`finger-trees don't?
23:15gfrlog`$google tree data structure
23:15lazybot[Tree (data structure) - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Tree_(data_structure)
23:19amalloygfrlog`: they do. but you said it was a description of trees generally, so i interjected
23:19gfrlog`:)
23:19gfrlog`yeah I admit it was ambiguous
23:20gfrlog`although, if it can be said that a tree has two separate pertitent definitions -- a data structure, and a type of graph -- then one could argue that the first should be understood by the context
23:20gfrlog`(by "a type of graph" I mean specifically connected acyclic graphs)
23:24amalloygfrlog`: {:a nil :b {:c 2}} is a "tree data structure". what order are the children a and b in?
23:25gfrlog`I prefer to call it a map :P
23:26gfrlog`okay you win this round
23:27amalloy(inc pedantry)
23:27lazybot⟹ 1
23:28gfrlog`(inc (inc pedantry))
23:28lazybot⟹ 1
23:28gfrlog`(inc )
23:28lazybot⟹ 1