2011-07-15
| 01:46 | Demosthenes | so 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:43 | ihodes | Demosthenes: maybe I don't understand you, but can't you send off a jar? |
| 03:36 | dans_ | can you clever folks give me some book recommendations? |
| 03:40 | Dranik | Practical Clojure and then The Joy of Clojure |
| 03:43 | dans_ | reading practical clojure :) |
| 03:43 | dans_ | but i didnt mean just clojure or programming....just in general |
| 03:46 | Dranik | have a look at rich hickey clojure bookshelf |
| 03:47 | Dranik | http://www.amazon.com/Clojure-Bookshelf/lm/R3LG3ZBZS4GCTH |
| 03:49 | dans_ | thanks |
| 03:50 | dans_ | ah nice |
| 05:54 | tsdh | Does (:foo {:foo "bla"}) work because maps implement clojure.lang.ILookup? |
| 06:04 | bsteuber | yes |
| 06:04 | terom | tsdh: I think so, yes, at least based on skimming clojure.lang.Keyword source |
| 06:04 | bsteuber | if(obj instanceof ILookup) |
| 06:04 | bsteuber | return ((ILookup)obj).valAt(this); |
| 06:04 | bsteuber | return RT.get(obj, this); |
| 06:05 | tsdh | Hm, would it be possible to make that interface a protocol, so that you could extend other types to support keyword lookup? |
| 06:06 | tsdh | For example, I'd love to write (:name myNode) instead of (value myNode :name). |
| 06:08 | bsteuber | tsdh: how about using a record? |
| 06:08 | bsteuber | or is it a java type you don't own? |
| 06:19 | Pupeno_ | Hello. |
| 06:21 | Pupeno_ | Anyone using Clojure+Slime on Aquamacs? |
| 06:25 | tsdh | bsteuber: It's a java type I do know. |
| 06:32 | bsteuber | tsdh: then you're screwed basially |
| 06:33 | bsteuber | you could subclass it oO |
| 06:33 | bsteuber | but probably you just want to use your own ILookup replacement without the syntactic sugar |
| 06:34 | tsdh | bsteuber: 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:42 | tibbe | anyone know why PersistentHashMap uses hash collision leaves instead of extended hashing? |
| 07:06 | Dranik | hi all! |
| 07:06 | bendlas | hi |
| 07:07 | Dranik | I'm still struggling with utf8 |
| 07:07 | Dranik | this is what I'm doing |
| 07:07 | Dranik | https://gist.github.com/1084495 |
| 07:07 | Dranik | the encoding is still broken. |
| 07:08 | Dranik | how to fix the encoding? |
| 07:13 | cemerick | Dranik: Seems like that should be [:headers "Content-Type"] |
| 07:13 | Dranik | let me try... |
| 07:15 | Dranik | cemerick: didn't work :-( |
| 07:17 | cemerick | Dranik: Clojure will load your source file as UTF8; is it saved in some other encoding? |
| 07:18 | Dranik | it shouldn't be bcs I use linux with LANG="ru_RU.UTF-8" |
| 07:18 | cemerick | (BTW, you can use the ring.util.response/content-type fn instead of rolling your own assoc-in) |
| 07:19 | cemerick | I'd double check in any case :-) |
| 07:19 | Dranik | cemerick: can you show how? |
| 07:19 | cemerick | how what? Check the file encoding? |
| 07:20 | Dranik | ok, wait, I'll try the content-type fn |
| 07:21 | cemerick | That shouldn't do anything different than what you have, it's just better to use a standard fn instead of rolling your own. |
| 07:21 | Dranik | agree |
| 07:22 | Dranik | though I still can't understend why it doesn't work |
| 07:22 | cemerick | Anyway, `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:23 | Dranik | routes.clj: text/html; charset=utf-8 |
| 07:23 | cemerick | next, I'd curl -v the URL to see exactly what is being sent |
| 07:23 | Dranik | moment... |
| 07:25 | Dranik | Content-Type: text/html; charset=iso-8859-1 |
| 07:25 | Dranik | and question marks in conent instead of unicode letters |
| 07:27 | cemerick | ah, progress |
| 07:27 | bendlas | Dranik: that's because most user agents send smth like "Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3" |
| 07:27 | bendlas | notice that ISO-8859-1 is preferred over utf-8 |
| 07:28 | cemerick | oh, hah |
| 07:28 | bendlas | and web servers oblige |
| 07:28 | cemerick | You're setting the content type on the *request*, not the response. |
| 07:28 | Dranik | ok, how to set it on the response? |
| 07:29 | bendlas | the charset is subject to content negotiation |
| 07:29 | bendlas | AFAIR the served variant is chosen by the highest score |
| 07:29 | Dranik | btw, how to get the user's input in utf-8 if he posts a form? |
| 07:30 | cemerick | bendlas: 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:31 | bendlas | cemerick: for the mime type that's true |
| 07:31 | cemerick | Dranik: 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:31 | bendlas | but I always supposed, that the accept-charset stuff is handled by jetty, ... |
| 07:32 | cemerick | Good point, I'm not sure. |
| 07:32 | cemerick | However, if you're setting Content-Type as a ring header, I really doubt that jetty will quash it down to ISO-XXXX. |
| 07:32 | bendlas | because that happens between Reader/Writer land and IOStream land |
| 07:32 | bendlas | let me check tough |
| 07:33 | Dranik | cemerick! yeah! that works! |
| 07:33 | Dranik | thanks! |
| 07:34 | Dranik | and how about the users input? will it be utf-8 out of the box? |
| 07:34 | bendlas | https://github.com/mmcgrana/ring/blob/master/ring-servlet/src/ring/util/servlet.clj#L71 |
| 07:34 | bendlas | Dranik: java Strings are always unicode |
| 07:35 | bendlas | UTF-16 though (which doesn't have to bother you) |
| 07:35 | Fossi | exept for the boms ;) |
| 07:35 | Dranik | great! |
| 07:36 | Dranik | bendlas: thanks |
| 07:36 | bendlas | you only need to be careful when reading from an InputStream |
| 07:36 | Dranik | is there anywhere an architecture description of Ring? |
| 07:36 | bendlas | i.e. slurp |
| 07:36 | Fossi | Dranik: yes, should be first or second hit on google |
| 07:39 | bendlas | Dranik: hmm actually, you do get user input as an InputStream |
| 07:39 | bendlas | the :body key on the request |
| 07:40 | bendlas | fortunately the request has a :character-encoding key to |
| 07:40 | Dranik | bendlas: so how to set it correctly? |
| 07:40 | bendlas | so you can do (InputStreamReader. (:body req) (:character-encoding req)) |
| 07:41 | bendlas | to get a Reader Object from which you get properly decoded character data |
| 07:41 | Dranik | OMG, isn't there a simplier way? |
| 07:42 | bendlas | you need to read the inputstream anyway |
| 07:43 | bendlas | because you can't do anything with a plain inputstream |
| 07:43 | Dranik | why? if the user has just supplied his text in, for instance, in cyrillic encoding, I can access the form's fields |
| 07:44 | Dranik | the question is: whether it will work the same way for utf8 |
| 07:44 | bendlas | you're talking about form data? |
| 07:44 | Dranik | yep |
| 07:45 | bendlas | that is handled by ring.middleware.params |
| 07:45 | bendlas | which does the decoding at https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/params.clj#L50 |
| 07:46 | bendlas | so yeah, it should work |
| 07:46 | Dranik | but who does set the utf8 encoding there? |
| 07:47 | bendlas | the utf8 _decoding_ is done by slurp |
| 07:47 | Dranik | ok, great! |
| 07:47 | bendlas | which is aproximately (read-into-string (InputStreamReader. %)) |
| 07:47 | Dranik | thanks! |
| 07:47 | bendlas | np |
| 08:42 | bsteuber | what parsing libraries exist for clojure now? |
| 08:42 | bsteuber | last time I checked there was only fnparse |
| 08:43 | bsteuber | but I guess there's more now |
| 08:45 | bendlas | bsteuber: last I've heard, CCW switched to cgrand's parsley |
| 08:46 | bendlas | https://github.com/cgrand/parsley |
| 08:47 | bsteuber | bendlas: thanks, looks interesting |
| 08:48 | bendlas | yw |
| 09:03 | jcromartie | interesting... 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:04 | jcromartie | one small step out of the tarpit, actually :) |
| 09:07 | jcromartie | now if you add invariants you've got something |
| 09:31 | jcromartie | Is there any sense in maintaining my own `clj' script or /Library/Clojure or any of the other nonsense I've cobbled together? |
| 09:31 | jcromartie | it seems to confuse lein |
| 09:37 | wjlroe | I'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:40 | chrissbx | Is it better style to write [a b] instead of (vector a b) to return multiple values? |
| 09:41 | Chousuke | yes |
| 09:41 | Chousuke | use literals |
| 09:42 | Chousuke | vector literals are a popular alternative for (list a b) as well |
| 09:44 | chrissbx | Ok. BTW to my understanding "literal" means "constant", I find it a tad strange to say that vector syntax is a literal. |
| 09:45 | chrissbx | (The way you say it makes me guess that Clojure people are using the term this way freely, though.) |
| 09:49 | Chousuke | chrissbx: if it were a constant I'd say constant :P |
| 09:50 | Chousuke | though in a way, it is a constant. as code, it's a vector of two symbols |
| 09:51 | Chousuke | the resulf of evaluating such a form is context-dependent though :) |
| 09:51 | Chousuke | result* |
| 09:53 | chrissbx | Well, with this reasoning many expressions would be constant. |
| 09:53 | chrissbx | When 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:54 | Chousuke | [a b] is literally a vector of two symbols. it just evaluates to something else. |
| 09:54 | chrissbx | If there would be some way to capture the expression before the symbols are replaced, then calling it a literal would have some validity. |
| 09:55 | Chousuke | that's (quote [a b]). but that's literally a list of a symbol and a vector :P |
| 09:55 | chrissbx | So, you're saying that just a is a literal, too? |
| 09:56 | Scriptor | ,(class (quote [a b])) |
| 09:56 | clojurebot | clojure.lang.PersistentVector |
| 09:56 | Chousuke | I'm not so sure about that. |
| 09:56 | chrissbx | Nah, quote really makes it a constant. |
| 09:56 | Chousuke | the value of [a b] is constant after evaluating it though |
| 09:57 | Chousuke | so it's kind of difficult |
| 09:57 | chrissbx | Well, any value from an expression is constant after evaluating the expression. |
| 09:57 | Chousuke | I'm not sure what you would call a vector form if not a literal |
| 09:57 | chrissbx | As long as the language is functional. |
| 09:57 | chrissbx | Just vector *syntax*. |
| 09:57 | chrissbx | But maybe this is just me. |
| 09:58 | Scriptor | what's this discussion about? |
| 09:58 | Chousuke | the syntax is irrelevant to it actually being a vector though. |
| 09:58 | Chousuke | [a b] is not equivalent to (vector a b) |
| 09:58 | Scriptor | huh, depends on the context, doesn't it? |
| 09:58 | Chousuke | (though they evaluate to the same thing) |
| 09:59 | Scriptor | if you're using a function, both will be evalauted to the same thing before you can do anything |
| 09:59 | Chousuke | in the end I guess it doesn't matter too much but it's interesting to think about |
| 09:59 | Scriptor | but if you use a macro they will be different lists |
| 09:59 | Scriptor | well, not lists per se |
| 09:59 | Chousuke | Scriptor: (vector a b) actually calls a function though. [a b] might do something else |
| 10:00 | Scriptor | Chousuke: ah, right |
| 10:01 | joegallo | i 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:01 | joegallo | but yeah, it's just syntax |
| 10:01 | Scriptor | looks like when you pass [a b] to a macro it will pass an actual vector data structure |
| 10:02 | Chousuke | of course |
| 10:02 | Scriptor | but 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:02 | Chousuke | because [a b] *is* a vector :) |
| 10:02 | Scriptor | yep |
| 10:02 | Scriptor | hmm, this discussion is kind of like determinging whether |
| 10:02 | Chousuke | similarly if you give #{:foo :bar} to a macro you will get an actual set |
| 10:03 | Scriptor | 5 is equivalent to (+ 2 3) |
| 10:03 | chrissbx | More like whether (infix 2 + 3) is equivalent to (+ 2 3) |
| 10:03 | chrissbx | (assuming that there's an infix form that translates to the latter) |
| 10:03 | Chousuke | Scriptor: the evaluated results of both forms are identical |
| 10:04 | Scriptor | Chousuke: right |
| 10:04 | Scriptor | but passed to a macro they're different data structures |
| 10:04 | Scriptor | the literal equals the result of the latter's evaluation |
| 10:04 | Chousuke | in other languages this probably is a non-issue but lisps are funny like that :P it actually matters what your code is |
| 10:05 | mdeboard | homoiconicity |
| 10:05 | Scriptor | I think it's a difference in how programmers read the code |
| 10:05 | chrissbx | Well, Clojure is probably the only lisp that has the vector syntax. |
| 10:05 | Chousuke | common lisp has too |
| 10:05 | Scriptor | someone might see (vector 2 3) and thinks "the vector of 2 and 3" |
| 10:05 | chrissbx | At least as source code (i.e. "literals" ;) |
| 10:06 | Chousuke | #(foo bar)... the difference is, they don't have evaluation semantics |
| 10:06 | Chousuke | or rather, it's just "return object as is" |
| 10:06 | Scriptor | whereas we would see "the vectorization of 2 and 3" if we're passing it to a macro |
| 10:06 | Chousuke | whereas in clojure the evaluation strategy for a vector is to return the vector you get from evaluating all elements in the vector. |
| 10:08 | Demosthenes | so 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:08 | chrissbx | I 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:08 | Chousuke | Demosthenes: I think the most common way is to just do it the Java way. ie. jars |
| 10:09 | Chousuke | Demosthenes: it's not quite the same as native packages, but it works |
| 10:09 | mdeboard | unless you're compiling to javascript |
| 10:09 | mdeboard | right? |
| 10:09 | mdeboard | or how does that work for clj on other platforms |
| 10:10 | Scriptor | with CLI you can probably use one of the installer-builders that visual studio has |
| 10:10 | Demosthenes | my issue is i commonly use scripting languages, and i need to distribute a stand alone binary to customers for a project |
| 10:11 | Demosthenes | and racket might fit the bill because it can make exe's |
| 10:11 | Demosthenes | but libraries are an issue |
| 10:11 | Scriptor | you can use jars to pack all the libraries into it |
| 10:11 | Chousuke | leiningen can make uberjars for you |
| 10:11 | Scriptor | ^ |
| 10:11 | mdeboard | (inc Chousuke) |
| 10:11 | sexpbot | ⟹ 1 |
| 10:12 | Demosthenes | didn't someone just say they weren't like native packages? |
| 10:12 | Scriptor | quick question, how does the jvm know what code to start with in a jar/uberjar? |
| 10:12 | Scriptor | there aren't any main methods as far I see |
| 10:12 | Demosthenes | and can a windows user just doubleclick a jar to launch? |
| 10:13 | pjstadig | it writes the main method to call to the jar manifest or something |
| 10:16 | cemerick | Demosthenes: If they have the Sun/Oracle JRE installed, yes, a double-click should run it. |
| 10:18 | Chousuke | Demosthenes: they are, in that they don't integrate with native package management |
| 10:18 | Demosthenes | ah |
| 10:19 | Chousuke | though I'm pretty sure there are tools to put the jars in an MSI and creating launcher executables |
| 10:19 | Chousuke | after all, java is pretty popular in the enterprise :P |
| 10:19 | Chousuke | +for |
| 10:21 | Demosthenes | hrm, that could be a selling point |
| 10:21 | Chousuke | I don't know much about such tools but you will probably find something if you search |
| 10:21 | mdeboard | Yeah I'm 100% certain jars in MSIs is pretty standard |
| 10:21 | Demosthenes | i've had great luck with scripting languages for my projects, but i can't expect an end user to install all the runtimes |
| 10:22 | Chousuke | Clojure'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:22 | jcromartie | there are good examples of native-ish Java apps out there... like Minecraft |
| 10:23 | Chousuke | also 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:24 | Chousuke | most clojure-based libraries tend to use the EPL too |
| 10:28 | cemerick | Demosthenes: I've shipped the JRE wholesale to customers plenty in the past. |
| 10:29 | Demosthenes | interesting ;] |
| 10:29 | Demosthenes | that's an ability i've lacked with scripting languages |
| 10:52 | Demosthenes | i guess i oughtt o install a clojure environment and try out a few jars |
| 11:02 | jcromartie | y'all might find this useful: https://gist.github.com/1084860 |
| 11:15 | cemerick | technomancy: I had to do this to get javac running after AOT: https://gist.github.com/225e07be131eb8635d84 |
| 11:15 | cemerick | Does that seem idiomatic to you? |
| 11:17 | cemerick | Demosthenes: 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:22 | chrissbx | I need to translate this Scheme code to Clojure, how would you do it?: (call-with-input-file foo read-all) |
| 11:23 | joegallo | http://launch4j.sourceforge.net/ |
| 11:23 | chrissbx | i.e. give a list of all s-exprs that are in the file named in foo |
| 11:35 | joegallo | (read-string (slurp foo))? |
| 11:35 | chrissbx | I 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:35 | chrissbx | slurp, aha |
| 11:36 | joegallo | read-string only reads the first object though |
| 11:36 | chrissbx | That's a problem, yeah. |
| 11:36 | chrissbx | I've found with-in-str, but same problem |
| 11:36 | joegallo | then you would need to look at with-open, binding *in*, and read. |
| 11:36 | chrissbx | I mean, I've only found read, no read-all |
| 11:37 | joegallo | keep calling read repeatedly |
| 11:37 | chrissbx | well can wrap this |
| 11:37 | chrissbx | yep |
| 11:41 | chrissbx | How do you take optional arguments in a function? |
| 11:41 | chrissbx | other than "mis-using" & |
| 11:42 | chrissbx | something like (fn [a b &optional (c 1) (d 2)] ...) |
| 11:42 | jcromartie | chrissbx: you can use (fn ([arg list one] body one) ([arg list number two] body two)) to overload arity |
| 11:42 | chrissbx | where 1 and 2 are the default values for c and d if no argument is passed for those. |
| 11:43 | chrissbx | Yes, 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:43 | chrissbx | is this how you're doing things in Clojure? |
| 11:45 | chrissbx | (Also, that means to duplicate part of the argument lists, which can be a bit tedious in some cases) |
| 11:46 | jcromartie | chrissbx: there are some other defn varieities |
| 11:46 | jcromartie | I'm not sure if there's anything as extensive as CL's |
| 11:47 | jcromartie | but you can user write your own :) |
| 11:47 | jcromartie | s/user/sure/ |
| 11:47 | sexpbot | <jcromartie> but you can sure write your own :) |
| 11:47 | chrissbx | I could, but then I'd be alone. |
| 11:47 | jcromartie | or you could contribute it back |
| 11:47 | chrissbx | Where are those other defn varieties? |
| 11:48 | jcromartie | there's defnk in clojure.contrib.def |
| 11:48 | jcromartie | that's a keyword argument defn |
| 11:49 | jcromartie | what kind of argument bindings do you want? |
| 11:49 | chrissbx | Just an optional argument or two. |
| 11:50 | jcromartie | ok so as an example |
| 11:51 | jcromartie | like what would your fn be |
| 11:51 | jcromartie | (paste it somewhere) |
| 11:51 | jcromartie | sorry |
| 11:51 | jcromartie | chrissbx: something like (fn [a b &optional (c 1) (d 2)] ...) |
| 11:52 | chrissbx | ok, will do in a couple moments |
| 12:00 | chrissbx | jcromartie: http://paste.lisp.org/display/123288 |
| 12:00 | chrissbx | Well, current-input-port is Scheme, dunno how to translate this. |
| 12:00 | chrissbx | Also, I guess read in Clojure doesn't take a port argument? |
| 12:00 | chrissbx | Also, I know I should use the loop macro instead of fn rec. |
| 12:01 | jcromartie | port? no... input stream yes |
| 12:01 | chrissbx | Well, that's the same thing I guess. |
| 12:01 | chrissbx | aka filehandle |
| 12:02 | jcromartie | ,(doc read) |
| 12:02 | clojurebot | "([] [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:02 | chrissbx | ok |
| 12:03 | chrissbx | So I guess (aside these errors) what I wrote is how you'd do it? |
| 12:03 | jcromartie | something like that |
| 12:03 | jcromartie | well hold on |
| 12:04 | jcromartie | you might as well put the body of read-all-1 in the body of your 1-ary read-all |
| 12:04 | chrissbx | hm, that's true. Recurse to read-all. |
| 12:06 | jcromartie | here's an idea |
| 12:06 | jcromartie | (take-while identity (repeatedly read)) |
| 12:08 | amalloy | jcromartie: not very good. input forms could be nil or false |
| 12:08 | jcromartie | true |
| 12:10 | amalloy | you need something more like (let [in (PushbackReader. (reader filename)), sentinel (Object.)] (take-while (complement #{sentinel} (repeatedly #(read in false sentinel))))) |
| 12:10 | amalloy | or, 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:11 | technomancy | cemerick: you're leaving :java-source-path out of defproject explicitly in order to avoid pre-aot javac? |
| 12:12 | technomancy | cemerick: 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:12 | technomancy | this is only the second time I've heard of it. |
| 12:14 | technomancy | cemerick: there is an open issue for this actually: https://github.com/technomancy/leiningen/issues/180 fwiw |
| 12:14 | amalloy | looks like my parens in the sample code above don't balance properly. adjust as necessary |
| 12:15 | technomancy | amalloy: what, you don't have paredit in irc? |
| 12:15 | amalloy | technomancy: well, i got the right number of each kind |
| 12:15 | amalloy | but i nested them wrong |
| 12:15 | technomancy | oic |
| 12:16 | amalloy | i 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:19 | mdeboard | Anyone know if there's a clojure wrapper lib for github api? |
| 12:19 | mdeboard | I asked before searching github obv |
| 12:20 | amalloy | $google clj-github |
| 12:20 | sexpbot | [alienscience/form-dot-clj - GitHub] https://github.com/alienscience/form-dot-clj |
| 12:20 | amalloy | hm |
| 12:20 | amalloy | well, yes, there is |
| 12:20 | amalloy | but it's for v2, maybe even v1 |
| 12:20 | cemerick | technomancy: 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:20 | Scriptor | nothing clojure-y on here: http://develop.github.com/p/libraries.html |
| 12:21 | Scriptor | though there's the java api |
| 12:21 | technomancy | cemerick: yeah, especially if you're looking to demo hooks then that's spot-on. |
| 12:21 | cemerick | I'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:22 | cemerick | We'll have a bit dedicated to hooke in a different chapter unrelated to lein, FWIW. |
| 12:22 | technomancy | cool |
| 12:22 | minou | hello, 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:22 | cemerick | part of the "translating specialized design patterns into regular ol' clojure code" chapter |
| 12:23 | technomancy | "in which the gang of four are overthrown" |
| 12:23 | cemerick | heh, yeah, something like that |
| 12:23 | cemerick | The chapter is currently called "Design patterns in Clojure" |
| 12:23 | cemerick | after reading it, one could reasonably play the "It's a trap!" clip. :-D |
| 12:24 | technomancy | heh. |
| 12:24 | cemerick | Sort of emblematic of the book as a whole, really. |
| 12:25 | cemerick | technomancy: anyway, thanks for the help and pointers to fill in my lein coverage. :-) |
| 12:27 | technomancy | no problem; looking forward to seeing it completed |
| 12:28 | cemerick | as am I! |
| 12:34 | Dranik | I can't wait when "Clojure Programming" is ready!.. |
| 12:40 | mdeboard | Dranik: Why |
| 12:40 | mdeboard | What about it makes you anticipate it |
| 12:41 | Dranik | it is focused on practical ways and tools for everyday programming |
| 12:42 | Dranik | in contrast, all the other published clojure books are mostly about the language itself |
| 12:42 | mdeboard | I see, that makes sense. |
| 12:42 | mdeboard | And web resources for practical programming in clojure are very slim |
| 12:43 | Dranik | clojuredocs.org is the best one for me |
| 12:47 | chrissbx | Is it bad to use the slash in symbols for anything other than namespaces? (I guess so?) |
| 12:47 | amalloy | chrissbx: it's worse than bad: it's undefined behavior |
| 12:47 | chrissbx | Like, I often use names like foo/2 for a function foo that takes 2 arguments. |
| 12:48 | chrissbx | So, do I have to replace this with foo:2 or something, I guess. |
| 12:48 | amalloy | *2 sounds a little clearer to me than :2, personally |
| 12:49 | amalloy | but 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:50 | chrissbx | I'm mainly using it in argument names to library functions, to indicate how many arguments are expected by a higher-order function. |
| 12:50 | amalloy | ah. sensible |
| 12:50 | amalloy | &(class /) |
| 12:50 | sexpbot | ⟹ clojure.core$_SLASH_ |
| 12:51 | chrissbx | i.e. (defn myspecialfold [fn/3 & lists] ...) |
| 12:51 | amalloy | right |
| 12:52 | chrissbx | so I'm going to use * instead |
| 12:57 | chrissbx | How do you append symbol names? i.e. (symbol-append 'a 'b) -> ab |
| 12:58 | Cozey | Hello. Is (set (map ... )) lazy ? |
| 12:58 | amalloy | &(symbol (str 'a 'b)) |
| 12:58 | sexpbot | ⟹ ab |
| 12:58 | amalloy | Cozey: no. sets can't be lazy |
| 12:59 | amalloy | chrissbx: so, i guess, (def symbol-append (comp symbol str)) |
| 12:59 | Cozey | it seems so, but i wanted to be sure :) |
| 13:00 | bsteuber | but cats can be lazy! |
| 13:00 | amalloy | &(doc lazy-cat) |
| 13:00 | sexpbot | ⟹ "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:01 | ssideris_ | hello. in clojure 1.3, the (doc) function seems to be missing... anyone know what the new way is? |
| 13:04 | joly | I'm curious about this too. When I start a new REPL, (doc map) works fine. If I switch namespaces, it doesn't work |
| 13:05 | joly | "Unable to resolve symbol: doc in this context..." |
| 13:05 | ssideris_ | oh I didn't realize that it works initially |
| 13:05 | ssideris_ | maybe it's a bug |
| 13:06 | ssideris_ | https://github.com/technomancy/swank-clojure/issues/45 |
| 13:06 | amalloy | joly: a number of namespaces are automatically use'd in the <user> namespace, as a special convenience for you |
| 13:07 | amalloy | is what i recall |
| 13:07 | amalloy | but doc is in clojure.repl, so if you want it somewhere else, you should be able to (use 'clojure.repl) |
| 13:07 | joly | amalloy: I thought core functions were imported into new namespaces, at least before 1.3 |
| 13:07 | amalloy | joly: it's not in core |
| 13:07 | amalloy | is it? |
| 13:07 | amalloy | &#'doc |
| 13:07 | sexpbot | ⟹ #'clojure.core/doc |
| 13:07 | amalloy | oh, i lied |
| 13:08 | ssideris_ | (use 'clojure.repl) worked for me |
| 13:08 | ssideris_ | thanks! |
| 13:08 | amalloy | maybe it moved to repl in 1.3 then |
| 13:09 | joly | oh, maybe that's it. (use 'clojure.repl) works for me too |
| 13:09 | joly | thanks |
| 13:13 | bendlasMble | Hey folks |
| 13:16 | bendlasMble_ | I wonder: has the issue been raised, that one can't develop clojure applications under the GPL? |
| 13:21 | jweiss | is 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:25 | hugod | Anyone have opinions on how to control which exceptions break into the debugger in ritz? https://github.com/pallet/ritz/issues/14 |
| 13:33 | joegallo | bendlasMble_, what makes you think you can't? |
| 13:41 | bendlasMble | joegallo, because clojure is epl |
| 13:42 | chouser | bendlasMble: yes. The party line is that that's the GPL's fault, not EPL's. |
| 13:42 | bendlasMble | You can't rerelease epl code under gpl |
| 13:42 | joegallo | can'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:43 | bendlasMble | Maybe. That's the reason i think i can't, anyway |
| 13:44 | bendlasMble | Hmm, interesting thought |
| 13:44 | joegallo | http://en.wikipedia.org/wiki/GPL_linking_exception |
| 13:44 | scgilardi | looks relevant: http://stackoverflow.com/questions/168254/can-you-write-gpl-software-using-cpl-libraries |
| 13:45 | joegallo | the highest rated comment there seems to be about copying and pasting cpl code into your gpl program, though |
| 13:45 | joegallo | which is missing the point of the question |
| 13:46 | scgilardi | cpl faq reference may help. |
| 13:46 | scgilardi | if it weren't dead... |
| 13:46 | joegallo | heh |
| 13:47 | joegallo | http://www.eclipse.org/legal/eplfaq.php#USEINANOTHER |
| 13:47 | joegallo | seems to be the same stuff at a different place |
| 13:49 | joegallo | fwiw 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:51 | bendlas` | IMHO the only real solution would be to dual licence clojure |
| 13:52 | hv | Is there an automatic way of generating clojure-api style docs for open source java libraries? |
| 13:53 | joegallo | http://tomfaulhaber.github.com/autodoc/ |
| 13:55 | bendlas` | I'm thinking about this, because I'm doing a project for which I'd really like strong copyleft |
| 13:56 | bendlas` | i.e. an end user program in an educational area |
| 13:59 | pjstadig | joegallo: ? |
| 13:59 | joegallo | hmmm??? |
| 13:59 | pjstadig | the epl is a weak copyleft license... changes to the original code must be released under EPL |
| 14:00 | joegallo | right, so if create a sweet new version of clojure, then that needs to be epl |
| 14:00 | pjstadig | you can combine it with whatever code you want, distribute it as a binary, and use whatever license you want |
| 14:00 | joegallo | exactly |
| 14:00 | pjstadig | you can also combine it at a source code level |
| 14:00 | pjstadig | but any modifications to the files from the original project must be released under the EPL |
| 14:01 | joegallo | right, 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:01 | joegallo | so i don't see the problem |
| 14:01 | pjstadig | and of course the original code must stay under the EPL, so you can't re-license it as GPL |
| 14:01 | pjstadig | joegallo: yeah that was my thought, use gpl+exception |
| 14:01 | joegallo | now, 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:02 | pjstadig | but i think you can only do gpl+exception in binary form |
| 14:03 | joegallo | the other way to do this is to just do what you want and wait for the letters from lawyers :) |
| 14:03 | pjstadig | hehe |
| 14:03 | bendlas` | :) |
| 14:03 | joegallo | it'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:04 | joegallo | in the end, the epl for clojure means whatever people are willing to sue over |
| 14:04 | joegallo | if the core is too busy to sue you, then i guess you escape |
| 14:04 | joegallo | but that's not really being a good citizen, and we all want to play fair |
| 14:05 | hv | joegallo: thanks. Does autodoc generate APIs for java libraries, too? |
| 14:05 | joegallo | i dunno |
| 14:05 | pjstadig | hv: doubt it |
| 14:06 | hv | joegallo: thanks. I couldn't find anything related to java in it, so I asked to be sure. |
| 14:06 | amalloy | $javadoc |
| 14:06 | hv | pjstadig: thanks. |
| 14:06 | amalloy | $javadoc Integer |
| 14:06 | sexpbot | http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html |
| 14:06 | amalloy | (that is: you can use the built-in javadoc tool for that) |
| 14:08 | hv | amalloy: I want the API in a clojure-friendly format, not the ordinary javadoc. |
| 14:08 | amalloy | what is "clojure-friendly"? if you're looking up java APIs for use with clojure, you better not be allergic to javadoc |
| 14:11 | bendlas` | I think the clojure autodoc format reflects the fact, that a clojure API prett much consists of functions in namespaces |
| 14:12 | bendlas` | where as in java you have packages, classes, methods in any combination of static, non-static, public, protected |
| 14:12 | hv | I 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:12 | bendlas` | then the occasional member |
| 14:12 | bendlas` | not to mention types |
| 14:13 | pjstadig | maybe 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:13 | hv | currently people are encouraged to learn some java and only then start learning clojure. That cannot go on forever. |
| 14:14 | Scriptor | they are? |
| 14:14 | Scriptor | this explains some confusion... |
| 14:14 | amalloy | i don't think that's true |
| 14:14 | Scriptor | honestly though, as long as someone reads up on java pckaging and namespaces they should be more than fine |
| 14:15 | amalloy | learn clojure, and then when you run into some bits that need java, learn that |
| 14:16 | hv | amalloy: 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:17 | amalloy | hv: so? that's no reason to impose a strict "first java, then clojure" order |
| 14:17 | amalloy | if you do that, you'll never know which bits of java "matter" |
| 14:19 | hv | I would say first some java intro (hopefully written by someone who knows clojure) and then you can go on and learn clojure. |
| 14:19 | Scriptor | amalloy: to be honest, enough to know from looking at some java code what's what |
| 14:20 | Scriptor | most java code has plenty in common |
| 14:20 | bendlas` | i suggest, we have that talk about host platform doc, as soon as we have every java bit in clojure.lang behind protocols |
| 14:20 | bendlas` | and an impl of those protocols, that compiles to machine code |
| 14:21 | bendlas` | :D |
| 14:24 | hv | amalloy: 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:25 | amalloy | *shrug* you may well be right. i came from java, so i'm not the target audience |
| 14:26 | joegallo | start with ejbs, that's what i always say |
| 14:30 | Demosthenes | you 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:31 | chouser | Demosthenes: that is not a coincidence. That's a core Clojure goal. |
| 14:32 | Demosthenes | i'm not opposed to buying one, but as a small dev i can't outlay $1500-2500 bucks just to publish an app |
| 14:32 | joegallo | http://www.gnu.org/licenses/gpl-faq.html#InterpreterIncompat |
| 14:32 | joegallo | http://www.gnu.org/licenses/gpl-faq.html#GPLPluginsInNF |
| 14:32 | Demosthenes | i'd drop $500 in a heartbeat |
| 14:32 | joegallo | i was trying to find those earlier, but my google-fu was weak |
| 14:33 | hv | Demosthenes: you are not alone! I think more people have avoided java apps than people who liked them. |
| 14:33 | Demosthenes | hv: well, all the "enterprise" apps i see in java (1.4!) are HORRIBLE |
| 14:33 | Demosthenes | memory leaking, cpu sucking pigs. |
| 14:33 | Demosthenes | and the native java syntax makes my skin crawl. |
| 14:34 | Demosthenes | but.... a lisp on jvm? i'm open to that |
| 14:34 | pjstadig | joegallo: the FSF has a very precise and nuanced worldview |
| 14:34 | joegallo | itym gnu/worldview, but yes :) |
| 14:35 | pjstadig | damn! |
| 14:35 | hodapp | the biggest problem with RMS is that he's ever right about anything. |
| 14:44 | paraseba | is (class (int 42)) supposed to be a Long in clj 1.3.0? |
| 14:45 | amalloy | probably |
| 14:46 | paraseba | amalloy: it's a little surprising |
| 14:46 | paraseba | I'd be ok with (class 42) being Long, but (int 42) too? |
| 14:47 | amalloy | paraseba: there's a related ticket on jira somewhere. something about aset-int breaking with the change to make ints autobox to Long |
| 14:47 | amalloy | $google clojure jira aset-int box long |
| 14:47 | sexpbot | [Overview - Clojure v1.2 API documentation] http://clojure.github.com/clojure/ |
| 14:47 | paraseba | it probably brings a lot of interop problems (I know I'm having them) |
| 14:48 | Scriptor | where's the clojure 1.3.0 repo? |
| 14:49 | paraseba | amalloy: maybe this? http://dev.clojure.org/jira/browse/CLJ-820 |
| 14:50 | paraseba | hum, created yesterday, no comments yet. I'm not sure if it's a bug, or a "feature" |
| 14:50 | amalloy | Scriptor: it's the same as the 1.2 repo? github.com/clojure/clojure |
| 14:51 | amalloy | paraseba: i was thinking of something on the clojure-dev mailing list, apparently, not a jira issue |
| 14:52 | amalloy | http://groups.google.com/group/clojure-dev/browse_thread/thread/d64923aaaf18a22b?pli=1 is related |
| 14:53 | amalloy | but, as usual on google groups, i can't find the one i'm thinking of |
| 14:53 | paraseba | probably this? https://groups.google.com/d/topic/clojure-dev/W4aFkFezW2g/discussion |
| 14:53 | amalloy | yes |
| 14:54 | paraseba | hum, still not sure if it's intended or just a bug.. |
| 14:58 | raek | paraseba: 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:59 | raek | if the receiver argument type is Object (like for 'class') the number will be boxed |
| 14:59 | paraseba | raek: but shouldn't be boxed to Integer? |
| 15:01 | amalloy | raek: that seems like a misstatement. it returns an int in all cases |
| 15:01 | amalloy | but most consumers box that |
| 15:02 | raek | paraseba: in clojure 1.3, byte, short, int and long are boxed to Long, and float and double are boxed to Double |
| 15:02 | raek | amalloy: ah, that makes sense |
| 15:03 | raek | ,(= (int 1) (long 1)) |
| 15:03 | clojurebot | true |
| 15:03 | raek | ,(set (int 1) (long 1)) |
| 15:03 | clojurebot | java.lang.IllegalArgumentException: Wrong number of args (2) passed to: core$set |
| 15:03 | paraseba | raek: what I find strange is the behavior of int function. Even if we always box to Longs, shouldn't int box to Integer? |
| 15:03 | amalloy | &(.equals (int 1) (long 1)) |
| 15:03 | sexpbot | ⟹ false |
| 15:03 | raek | ,#{ (int 1) (long 1)} |
| 15:03 | clojurebot | #{1 1} |
| 15:03 | amalloy | paraseba: no! |
| 15:03 | amalloy | int is sepcifically designed to not box things |
| 15:04 | raek | here you have a set of an Int and a Long... (this is clojure 1.2) |
| 15:04 | paraseba | amalloy: hum, I see |
| 15:04 | Pupeno | Hello. |
| 15:05 | Pupeno | Is it possible to have slime working with aquamacs? |
| 15:05 | amalloy | paraseba: 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:06 | amalloy | ~aquamacs |
| 15:06 | amalloy | aw |
| 15:06 | paraseba | amalloy: that makes sense... so somewhere else the output of (int 42) is getting boxed into a Long, which is now the default box |
| 15:06 | amalloy | right |
| 15:07 | paraseba | so now, we need to do (Integer. 42) to create a boxed Integer |
| 15:07 | amalloy | Pupeno: 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:08 | Pupeno | amalloy: 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:09 | raek | Pupeno: did you try the official swank-clojure instructions? |
| 15:09 | paraseba | amalloy: do you know where I can read about this changes in 1.3.0 |
| 15:10 | amalloy | paraseba: 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:11 | amalloy | eg dnolen or cemerick |
| 15:11 | Pupeno | raek: 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:11 | raek | paraseba: https://github.com/clojure/clojure/blob/master/changes.txt and http://dev.clojure.org/display/design/Home |
| 15:11 | aaelony | hi, what is the most idiomatic way to see if a file is gzipped? is there a gzipped? function somewhere? |
| 15:12 | paraseba | raek: will try that, thanks |
| 15:14 | paraseba | raek: 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:14 | paraseba | (int) seems to be the only one having this behavior... |
| 15:15 | paraseba | maybe short and bytes are still being boxed to their corresponding types instead of Long? |
| 15:15 | raek | hrm, that is a bit odd :) |
| 15:15 | raek | http://dev.clojure.org/display/doc/Enhanced+Primitive+Support |
| 15:15 | raek | this page says "all long-or-smaller integers are boxed as Long" |
| 15:15 | amalloy | "long or smaller". as if that were a necessary qualifier |
| 15:15 | raek | and "You can't use primitive coercions to force specific box types" |
| 15:16 | paraseba | yes ... it's very specific about that |
| 15:16 | raek | ...but apparently you can |
| 15:16 | paraseba | so, then, maybe (int) is the only one with the intended behavior |
| 15:17 | aaelony | ok, wrote one myself... |
| 15:22 | raek | it doesn't make sense for me that this is only done for 'int'... |
| 15:22 | paraseba | raek: or you could comment the jira ticket |
| 15:22 | paraseba | clj-820 |
| 15:40 | amalloy | anyone know if brian marick hangs around in here, or do i have to send him an actual email to get in touch? |
| 15:41 | raek | amalloy: dunno, but he is very active on twitter |
| 15:41 | amalloy | oh god, so he is. i had to unfollow him eventually |
| 15:45 | nybbles | fliebel: 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:58 | Cozey | Does anyone here know if there is already any clojure job market ? |
| 16:02 | amalloy | Cozey: there's some. i work at www.geni.com doing clojure with ninjudd, Raynes, and lancepantz |
| 16:03 | Cozey | I see also thortech is doing some clojure support |
| 16:03 | Cozey | so geni makes money out of dead people, eh? |
| 16:03 | amalloy | i know ztellman works with amit and some other folks at www.runa.com |
| 16:04 | amalloy | and nathanmarz is at backtype, who were recently acquired by twitter |
| 16:06 | jcromartie | amalloy: got it... so you're saying use Clojure, get acquired by Twitter |
| 16:06 | jcromartie | :P |
| 16:07 | Cozey | is clojure used mostly in data mining ? |
| 16:08 | fliebel | Cozey: Have you seen the survey by cemerick? |
| 16:08 | Cozey | oh i remember |
| 16:08 | Cozey | right |
| 16:08 | Cozey | also Incanter is a big point here |
| 16:08 | fliebel | http://cemerick.com/2011/07/11/results-of-the-2011-state-of-clojure-survey/ |
| 16:11 | fliebel | But if so many people use Clojure for data mining, why aren;t there loads of similarity and clustering things, or even NLP stuff... |
| 16:12 | kumarshantanu | when i (load-file "file-name.clj"), can i let-bind local vars around it? |
| 16:12 | fliebel | kumarshantanu: huh? |
| 16:13 | kumarshantanu | so that the local binding will be available in the load-file'd code |
| 16:13 | dnolen | fliebel: not everyone using Clojure is interested in opensource. |
| 16:13 | kumarshantanu | (let [x :foo] (local-file "file.clj")) ; i want file.clj to have access to x |
| 16:13 | kumarshantanu | s/local/load/ |
| 16:13 | sexpbot | <kumarshantanu> (let [x :foo] (load-file "file.clj")) ; i want file.clj to have access to x |
| 16:14 | fliebel | kumarshantanu: I think you'd have to use binding. |
| 16:14 | fliebel | dnolen: but the same could be said of web frameworks, and we have tons of these. |
| 16:17 | amalloy | kumarshantanu: no |
| 16:18 | kumarshantanu | amalloy: any alternative? |
| 16:19 | amalloy | global vars |
| 16:19 | amalloy | or, preferably, "stop trying to do things like that" |
| 16:19 | technomancy | fliebel: there's plenty of clustering libs on github |
| 16:19 | technomancy | jobbim, cascalog, conduit, work |
| 16:20 | technomancy | practically every mid-sized company using clojure has rolled their own |
| 16:21 | amalloy | technomancy: eerily reminiscent of "the lisp curse" |
| 16:21 | technomancy | NLP is another story because it's actually difficult to implement. job distribution systems are decidedly not. |
| 16:21 | Pupeno | Anybody 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:21 | amalloy | Pupeno: not a comic |
| 16:21 | technomancy | amalloy: eval plus amqp. done. |
| 16:21 | Pupeno | amalloy: I remember a comic strip. |
| 16:22 | amalloy | http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html |
| 16:22 | amalloy | search for "the venerable master qc na" |
| 16:22 | amalloy | technomancy: amqp? |
| 16:22 | technomancy | amalloy: advanced message queueing protocol. rabbitmq being the popular implementation |
| 16:23 | Pupeno | Someone turned it into a comic. |
| 16:23 | amalloy | Pupeno: okay. well, feel free to find that and paste a link here |
| 16:23 | Pupeno | amalloy: I will if I find it... but it's proving hard. |
| 16:48 | fliebel | technomancy: I was talking about *document* clustering, like k-means and stuff. |
| 16:50 | Scriptor | fliebel: what's the difference between document clustering and regular clustering? |
| 16:50 | fliebel | Scriptor: The one is about classifying text, the other about distributing work. |
| 16:51 | Scriptor | er, I meant regular clustering as in just regular k-means, but I see document clustering means specifically clustering text |
| 16:51 | Scriptor | rather than, say, numbers |
| 16:53 | fliebel | Scriptor: Uhm, well, I just wanted to make clear I was not talking about task queues and such. |
| 16:53 | amalloy | fliebel: i forget, are you the one who wrote sexpbot's ping plugin? |
| 16:54 | fliebel | amalloy: Well, you could say so, yes. But Raynes refactored it a lot I think. |
| 16:55 | amalloy | fliebel: Raynes never refactors, he just makes code uglier. i think i refactored it a lot |
| 16:55 | Raynes | amalloy: I hate you. |
| 16:55 | fliebel | oh, right :) |
| 16:55 | amalloy | anyway, 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:57 | fliebel | amalloy: 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:57 | amalloy | haha |
| 16:58 | amalloy | well, we did a global refactor on how plugins are supposed to send messages, and didn't update the ping plugin |
| 17:00 | fliebel | $huglle Raynes |
| 17:00 | fliebel | Hm, I think there was something like that... |
| 17:01 | fliebel | https://github.com/cognitivedissonance/sexpbot/blob/master/src/sexpbot/plugins/utils.clj#L184 |
| 17:02 | amalloy | fliebel: the word is huggle |
| 17:02 | fliebel | good night |
| 17:03 | amalloy | night |
| 17:08 | ssideris_ | hello... is there a way to create a proxy to an interface that is not known at compile time? |
| 17:09 | Demosthenes | drewr: muahahaha |
| 17:09 | ssideris_ | the fact that (proxy) is macro forces me to define the interface to be proxied at compile time, right? |
| 17:09 | ssideris_ | *is a |
| 17:12 | amalloy | ssideris_: you want to proxy an interface, but you don't know what it is? that sounds hard |
| 17:13 | ssideris_ | I have a standard way of mapping certain keywords to certain java interfaces |
| 17:13 | ssideris_ | 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:14 | amalloy | ssideris_: fwiw, if you're working with interfaces, 95% of the time you want reify, not proxy |
| 17:14 | amalloy | not that this fixes your current problem |
| 17:15 | ssideris_ | oh that's a good tip, let me go and look it up |
| 17:15 | ssideris_ | thanks |
| 17:15 | ssideris_ | the actual problem though... |
| 17:15 | whidden | given a symbol that resolves to a name space. How do I determine if it is a macro or a function? |
| 17:16 | ssideris_ | it does sound a bit reflection-heavy to be honest |
| 17:17 | ssideris_ | amalloy: proxy seems to have the advantage of being able to selectively define methods, you don't need all of them... |
| 17:17 | amalloy | ssideris_: "advantage" |
| 17:18 | amalloy | if 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:19 | ssideris_ | when it comes to swing listeners, not all the methods are relevant all the time |
| 17:19 | amalloy | well, yes |
| 17:20 | ssideris_ | it's hard :-) |
| 17:21 | amalloy | ssideris_: i don't think that what proxy does is what you want for swing |
| 17:21 | amalloy | iirc if you call an implemented method, it throws an exception, not silently continues |
| 17:22 | amalloy | $javadoc java.awt.WindowListener |
| 17:22 | amalloy | $javadoc javax.swing.WindowListener |
| 17:23 | amalloy | $google java windowlistener |
| 17:23 | sexpbot | [WindowListener (Java 2 Platform SE v1.4.2)] http://download.oracle.com/javase/1.4.2/docs/api/java/awt/event/WindowListener.html |
| 17:23 | amalloy | &(doto (proxy [java.awt.event.WindowListener] [] (windowOpened [e] nil)) (.windowIconified nil)) |
| 17:23 | sexpbot | java.lang.IllegalStateException: Var null/null is unbound. |
| 17:24 | ssideris_ | ok, then I'll use reify to silently suppress calls to the unimplemented parts |
| 17:24 | ssideris_ | thanks |
| 17:24 | amalloy | yeah, that's pretty much your only choice |
| 17:24 | amalloy | though see also WindowAdapter |
| 17:24 | ssideris_ | in fact, I think that is the source of a bug in my current implementation |
| 17:25 | ssideris_ | so double-thanks |
| 17:25 | ssideris_ | :-) |
| 17:25 | ssideris_ | the adapters are useful, but don't exist for everything in swing |
| 17:25 | amalloy | i know |
| 17:25 | ssideris_ | so I'm trying to offer a solution that covers everything |
| 17:25 | amalloy | yeah, i guess it's hard to see how to productively use an adapter |
| 17:29 | ssideris_ | there are at least 2 other swing DSLs out there already, right? |
| 17:29 | amalloy | dunno. not my problem |
| 17:29 | amalloy | all i know about is seesaw |
| 17:31 | aaelony | has 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:31 | aaelony | jtime |
| 17:31 | aaelony | #<DateTime 2011-07-07T13:59:59.979Z> |
| 17:31 | aaelony | (to-time-zone jtime "America/Los_Angeles") |
| 17:31 | aaelony | java.lang.ClassCastException: java.lang.String cannot be cast to org.joda.time.DateTimeZone (NO_SOURCE_FILE:0) |
| 17:31 | aaelony | any ideas? |
| 17:33 | aaelony | nevermind... it seems it needs to be a org.joda.time.tz.FixedDateTimeZone |
| 17:33 | aaelony | for the offset |
| 17:34 | ssideris_ | amalloy: so why do you dislike swing so much? |
| 17:34 | amalloy | ssideris_: that anyone would write WindowAdapter and not realize there's a problem saddens me |
| 17:35 | ssideris_ | :-) |
| 17:35 | ssideris_ | ok point taken |
| 17:35 | amalloy | it's an application of interfaces to a concept that doesn't really match |
| 17:36 | amalloy | if 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:37 | coopernurse | amalloy: just tried out your fork of clj-doc-test - do you know if it has issues with functions in namespaces? |
| 17:37 | amalloy | coopernurse: 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:38 | coopernurse | amalloy: ah, ok. thanks. |
| 17:38 | coopernurse | for pure functions it seems like a nice way to do tests |
| 17:38 | coopernurse | but it doesn't seem like it has caught on with the clojure community |
| 17:39 | amalloy | yeah, 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:39 | amalloy | it looks like my only commit was to make it cake/lein-friendly |
| 17:46 | coopernurse | amalloy: gotcha |
| 17:57 | dabd | I 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:58 | amalloy | dabd: ew |
| 17:59 | amalloy | drop the trampoline, and replace #(max-4-matches ...) with (recur ...) |
| 17:59 | dnolen | dabd: I don't see what stops you from just using recur, at least in this case. |
| 18:00 | sritchie | dabd: https://gist.github.com/1085641 |
| 18:00 | sritchie | haven't debugged that yet, but that's meant to be a straightforward conversion of what you'd had |
| 18:01 | amalloy | though tbh the whole function can easily be written as (count (take 4 (filter #{\x \o} s))) |
| 18:01 | dabd | sritchie: any advantages of using your version vs trampolines? |
| 18:01 | dnolen | dabd: trampolines are pretty slow, and just unidiomatic for what you're doing. |
| 18:02 | sritchie | you don't need mutual recursion between two functions, here, just a single recursion |
| 18:02 | dabd | ok |
| 18:03 | amalloy | someone 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:03 | dnolen | amalloy: trampoline is for mutual recursion. |
| 18:04 | dabd | amalloy: let me test your version |
| 18:04 | sritchie | dabd: https://gist.github.com/1085641 |
| 18:04 | sritchie | that's a little cleaner |
| 18:04 | sritchie | (than the first one I posted, imo) |
| 18:05 | amalloy | dnolen: i know |
| 18:05 | dnolen | amalloy: i know you know :) came out the wrong way. |
| 18:05 | dnolen | dabd: amalloy solution is the best way to do what you want and quite concise. |
| 18:06 | sritchie | amalloy: haha, didn't see that |
| 18:06 | dekuderp | I'm having a bit of trouble; the compiler is telling me I'm not recurring from a proper tail position |
| 18:06 | dekuderp | https://gist.github.com/1085656 |
| 18:07 | dekuderp | specifically, I get: Can only recur from tail position (map_maker.clj:13) |
| 18:07 | amalloy | dekuderp: move the second recur into the if |
| 18:07 | dabd | unfortunately 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:07 | amalloy | actually, look up how if works |
| 18:07 | sritchie | I think you're also forgetting parens around your different function versions |
| 18:07 | sritchie | so, wrap [xmax ymax] (recur xmax ymax xmax ymax {}) in parens, as well as the next argvec-body pair |
| 18:08 | dekuderp | amalloy: thanks |
| 18:08 | dekuderp | sritchie: so every [arg] (function body) should be ([arg] (function body))? |
| 18:08 | sritchie | yeah |
| 18:10 | dekuderp | okay here is the new error I am getting: Mismatched argument count to recur, expected: 2 args, got: 5 (map_maker.clj:13) |
| 18:10 | dabd | ofc it is easy to correct amalloy's version to have this behavior thanks guys |
| 18:10 | dekuderp | https://gist.github.com/1085665 |
| 18:10 | dabd | sorry I meant sritchie's version |
| 18:11 | dekuderp | so 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:12 | sritchie | I 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:12 | amalloy | dekuderp: recur doesn't work that way. you can only recur to the top of the current body |
| 18:12 | amalloy | sritchie: because recur is a GOTO, and each function body is a method |
| 18:12 | sritchie | got it |
| 18:13 | dekuderp | amalloy: thanks! |
| 18:17 | jonabbey | question: 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&q=lazy+stream&fwc=1 ? |
| 18:18 | jonabbey | i.e, there remain no deterministic destructors in clojure, so you have to do all management of stream lifespan with functional resource management blocks? |
| 18:19 | jonabbey | i'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:21 | dekuderp | in 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:22 | dekuderp | after 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:24 | jonabbey | /list-usrs |
| 18:24 | jonabbey | er |
| 18:27 | amalloy | dekuderp: again, look up how if works |
| 18:27 | amalloy | &((fn [] (if true 1) (if false 2) 3)) |
| 18:27 | sexpbot | ⟹ 3 |
| 18:30 | dekuderp | so how do I prevent the continued evaluation? am I supposed to be using cond instead? |
| 18:31 | dekuderp | this http://clojure.org/special_forms#if isn't really helping me understand my mistake, but I'm looking for other stuff too |
| 18:31 | amalloy | yes, but you can do it with if |
| 18:31 | amalloy | &((fn [] (if true 1 (if false 2 3))) |
| 18:31 | sexpbot | ⟹ 1 ; Adjusted to ((fn [] (if true 1 (if false 2 3)))) |
| 18:31 | amalloy | sexpbot: smartass |
| 18:32 | amalloy | dekuderp: the general thrust is, every expression returns something, always |
| 18:32 | amalloy | "early" returns are silently ignored by the special form (do expr1 expr2), which defn includes implicitly |
| 18:33 | dekuderp | so 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:33 | dekuderp | ok, I think I sorta get it now |
| 18:33 | amalloy | yes, though you should try to stop thinking about early returns |
| 18:33 | amalloy | those are "statements": "return this value now" |
| 18:34 | amalloy | clojure just has expressions, describing *what* the result of an expression is, not *how* to get it |
| 18:35 | Abezethibou | Hello all.. After a same studing aboud Common lisp (aproximately a year) |
| 18:36 | Abezethibou | I start to study clojure |
| 18:36 | dnolen | jonabbey: lazy-seqs and resources don't really play together well, open design problem. |
| 18:36 | Abezethibou | I am reading practical clojure |
| 18:36 | dekuderp | amalloy: thank you very much for helping me understand htat |
| 18:36 | dekuderp | that* |
| 18:36 | Abezethibou | and little bit joy of clojure |
| 18:37 | Abezethibou | Does anyone have any suggestion about a complate book |
| 18:38 | kylpo | technomancy: 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:38 | technomancy | kylpo: you mean common lisp? |
| 18:39 | kylpo | technomancy: yes. The book I'm using is Land of Lisp: http://www.amazon.com/Land-Lisp-Learn-Program-Game/dp/1593272812 |
| 18:39 | bsteuber | kylpo: just learn clojure ^^ |
| 18:40 | technomancy | kylpo: I don't think there's any value in learning CL at all |
| 18:40 | kylpo | technomancy: K, thanks. Except for understanding elisp, right? |
| 18:41 | technomancy | that's true; CL has a lot of overlap with elisp |
| 18:41 | technomancy | and it has a lot more literature |
| 18:41 | kylpo | technomancy: do you have an elisp book you like? |
| 18:41 | technomancy | kylpo: no, not really |
| 18:41 | kylpo | technomancy: k |
| 18:42 | technomancy | I guess I learned most of my elisp from Practical CL |
| 18:42 | kylpo | technomancy: a clojure book you like? |
| 18:42 | technomancy | only got about halfway through the book though |
| 18:42 | technomancy | kylpo: I've read Programming Clojure and the Joy of Clojure. good and great respectively |
| 18:42 | technomancy | PC if you just want the basics quickly and JoC for a more thorough grounding |
| 18:43 | kylpo | technomancy: K, thanks. I'm thinking I'll check out your peepcast, too. Making games are good ways for me to practice. |
| 18:43 | technomancy | yeah, games are great |
| 19:07 | dekuderp | so apparently this function is not correctly generating a data structure I want: https://gist.github.com/1085752 |
| 19:07 | dekuderp | I think this command shows that my logic is sound: |
| 19:07 | dekuderp | ,(if (nil? ((keyword (str 1)) {})) (assoc {} (keyword (str 1)) {})) |
| 19:07 | clojurebot | {:1 {}} |
| 19:08 | dekuderp | but for some reason the function only returns nil instead of the real structure I want |
| 19:11 | amalloy | i'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:13 | amalloy | (dekuderp: that last directed at you) |
| 19:15 | amalloy | dekuderp: note also that ##(assoc nil :x :y) works just fine with nil |
| 19:15 | lazybot | ⟹ {:x :y} |
| 19:21 | ssideris_ | what's a concise way to go from [[1 10] [2 20]] -> [[1 2] [10 20]] ? |
| 19:21 | ssideris_ | for the general case |
| 19:24 | ssideris_ | duh, I suppose [(map first v) (map second v)] |
| 19:24 | ssideris_ | where v is the structure |
| 19:25 | ssideris_ | the vector I mean |
| 19:26 | amalloy | &(apply map vector [[1 10] [2 20]]) |
| 19:26 | lazybot | ⟹ ([1 2] [10 20]) |
| 19:27 | amalloy | ssideris_: more general, working for NxM matrices |
| 19:28 | ssideris_ | wow nice |
| 19:28 | ssideris_ | thanks |
| 19:29 | dekuderp | um, 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:29 | dekuderp | the only example I got to work in my repl is ##(update-in {} [(keyword (str 1)) (keyword (str 2))] {}) |
| 19:29 | lazybot | ⟹ {:1 {:2 nil}} |
| 19:29 | amalloy | dekuderp: well, explain to me what your function is actually doing |
| 19:30 | amalloy | the mess of repeated nested assocs is not easy to follow |
| 19:31 | dekuderp | I want to create a 2d matrix to store other maps in |
| 19:31 | amalloy | so maybe just assoc-in? |
| 19:31 | amalloy | &(assoc-in nil [:1 :2] "data") |
| 19:31 | lazybot | ⟹ {:1 {:2 "data"}} |
| 19:32 | dekuderp | amalloy: that is definitely the function I was looking for |
| 19:32 | dekuderp | and I would use update-in for updating the 2d array, right? |
| 19:33 | amalloy | for changing one entry in it |
| 19:33 | dekuderp | okay, well those functions certainly make life easier |
| 19:33 | dekuderp | thanks! |
| 19:34 | amalloy | &(let [world (-> nil (assoc-in [:1 :2] "data") (assoc-in [:3 :5] 9))] (update-in world [:3 :5] dec)) |
| 19:34 | lazybot | ⟹ {:3 {:5 8}, :1 {:2 "data"}} |
| 19:34 | amalloy | i still don't understand at all why you want to use keywords as keys instead of numbers |
| 19:35 | amalloy | dekuderp: ^ all that stuff |
| 19:37 | dekuderp | amlloy: what do you mean? I am using numbers |
| 19:37 | dekuderp | I am using ##(keyword (str 1)) and such for every num |
| 19:37 | lazybot | ⟹ :1 |
| 19:38 | dekuderp | at least that's how I figured out how to turn numbers into keys |
| 19:41 | dekuderp | I'm guessing that I'm doing it wrong? |
| 19:41 | amalloy | stop 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:42 | amalloy | &{1 'test, 10 'sample} |
| 19:42 | lazybot | ⟹ {1 test, 10 sample} |
| 19:42 | dekuderp | oh, now I get it |
| 19:42 | amalloy | or use a vector of vectors, since vectors are indexed by index anyway |
| 19:43 | dekuderp | do you think I should be using vectors? |
| 19:43 | dekuderp | I'm not very sure of the trade off in my case, so my choice was pretty arbitrary |
| 19:43 | amalloy | &(let [world (vec (repeat 4 (vec (repeat 4 nil))))] (assoc-in world [3 1] 'test)) |
| 19:43 | lazybot | ⟹ [[nil nil nil nil] [nil nil nil nil] [nil nil nil nil] [nil test nil nil]] |
| 19:45 | amalloy | if the world is large and mostly empty, a map is surely better. otherwise, it probably depends but doesn't matter much |
| 19:46 | dekuderp | okay, I'll try it with vectors since I am planning on storing data at every entry |
| 20:20 | mdeboard | ,(min-key 7 8 9( |
| 20:20 | clojurebot | EOF while reading |
| 20:20 | mdeboard | ,(min-key (7 8)) |
| 20:20 | clojurebot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 20:20 | mdeboard | Can someone clue me in on what min-key is for :| |
| 20:21 | amalloy | &(min-key :size {:size 1 :name "test"} {:data 4 :size 10}) |
| 20:21 | lazybot | ⇒ {:size 1, :name "test"} |
| 20:21 | amalloy | &(min-key - 1 2 3) |
| 20:21 | lazybot | ⇒ 3 |
| 20:22 | amalloy | mdeboard: ^ |
| 20:29 | mdeboard | &(min-key - 3 2 1) |
| 20:29 | lazybot | ⇒ 3 |
| 20:29 | mdeboard | what. |
| 20:30 | mdeboard | &(min-key + 1 2 3) |
| 20:30 | lazybot | ⇒ 1 |
| 20:31 | amalloy | mdeboard: it calls - on each element before comparing |
| 20:31 | amalloy | and -3 is smaller than -1 |
| 20:31 | mdeboard | Oh. |
| 20:31 | mdeboard | &(min-key (partial (< 3)) 1 2 3) |
| 20:31 | lazybot | java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial |
| 20:32 | mdeboard | &(min-key (> 3 %) 1 2 3) |
| 20:32 | lazybot | java.lang.Exception: Unable to resolve symbol: % in this context |
| 20:32 | dnolen | &(min-key (partial < 3) 1 2 3) |
| 20:32 | lazybot | java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number |
| 20:32 | amalloy | mdeboard: unlikely to work anyway. > returns a boolean |
| 20:33 | dnolen | &(min-key (partial min 3) 1 2 3) |
| 20:33 | lazybot | ⇒ 1 |
| 20:34 | mdeboard | I see |
| 20:38 | dekuderp | is there an easy way to generate a random # between 0 and 1 in clojure? |
| 20:39 | amalloy | &(rand) |
| 20:39 | lazybot | ⇒ 0.5675409978355913 |
| 20:39 | dnolen | ,(rand-int 2) |
| 20:39 | clojurebot | 0 |
| 20:40 | dnolen | ,(take 10 (repeatedly #(rand-int 2))) |
| 20:40 | clojurebot | (0 1 1 1 0 1 1 0 0 0) |
| 20:40 | dnolen | ,(take 10 (repeatedly rand)) |
| 20:40 | clojurebot | (0.8182436567649329 0.9637135524821122 0.9122072063831675 0.2888228218745055 0.3761627320246498 0.2602531326683677 0.34970107144974993 0.8873792800568543 0.4710056658729913 0.7726407255548855) |
| 20:42 | mdeboard | Now, can someone give me a very very simple example of apply's usage? :\ |
| 20:43 | dekuderp | thanks! |
| 20:43 | mdeboard | The actual operation indicated by the ->> macro would seem like it woul be described with "apply" |
| 20:43 | technomancy | mdeboard: (apply * [1 2 3]) |
| 20:43 | technomancy | becomes (* 1 2 3) |
| 20:43 | amalloy | dnolen: repeatedly takes an optional how-many arg these days |
| 20:44 | mdeboard | technomancy: So .. it's reduce? |
| 20:44 | amalloy | &((juxt apply reduce) (partial list '*) [1 2 3]) |
| 20:44 | lazybot | ⇒ [(* 1 2 3) (* (* 1 2) 3)] |
| 20:44 | amalloy | mdeboard: the difference is that |
| 20:44 | technomancy | mdeboard: (reduce * [1 2 3]) results in two calls to * |
| 20:44 | technomancy | mdeboard: apply is a single call |
| 20:45 | mdeboard | ah |
| 20:45 | mdeboard | interestink |
| 20:55 | technomancy | amalloy: oh dang; I didn't catch what was going on there |
| 20:55 | technomancy | it's like your own private macroexpand-like facility |
| 20:55 | amalloy | technomancy: more like a trace |
| 21:21 | mdeboard_ | &(apply + [1 2 3]) |
| 21:21 | lazybot | ⇒ 6 |
| 21:23 | mdeboard_ | &(apply min-key 5 [1 2 3]) |
| 21:23 | lazybot | java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn |
| 21:27 | mdeboard_ | &(min-key min [ |
| 21:27 | lazybot | ⇒ [] ; Adjusted to (min-key min []) |
| 21:27 | brehaut | wait; lazybot? when did that happen |
| 21:28 | mdeboard_ | &(min-key min [1 2 3] [4 5 6] [7 8 9]) |
| 21:28 | lazybot | java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number |
| 21:28 | mdeboard_ | &(min 1,2,3) |
| 21:28 | lazybot | ⇒ 1 |
| 21:29 | mdeboard_ | Sorry I'm on my phone at Harry potter. This is the only repl I have :( |
| 21:29 | brehaut | mdeboard: damning review of a the movie there |
| 21:30 | amalloy | brehaut: earlier this afternoon |
| 21:30 | amalloy | mdeboard_: you can /msg lazybot &(min 1 2 3) |
| 21:31 | mdeboard_ | Ya doing that now amalloy |
| 21:31 | mdeboard_ | brehaut: We're here early. |
| 21:37 | babilen | mdeboard_: https://market.android.com/details?id=com.sattvik.clojure_repl (fwiw) -- but watch the movie, and don't play with the phone ;) |
| 21:37 | mdeboard_ | I'm on iPhone :( |
| 21:55 | ihodes | cemerick: hey chas |
| 22:01 | cemerick | hey :-) |
| 22:21 | gfrlog` | clojurebot: lazybot? |
| 22:23 | amalloy | clojurebot: lazybot is sexpbot's new name. Same bot, same features, less nsfw-looking name! |
| 22:23 | amalloy | clojurebot: ping? |
| 22:24 | amalloy | ,1 |
| 22:24 | gfrlog` | clojurebot was only ever interested in sexpbot |
| 22:24 | amalloy | hiredman: clojurebot seems to be dead |
| 22:24 | ihodes | cemerick: haha i didn't mean pick me for any particular reason, just a student who's using Clojure, though not in the classroom |
| 22:25 | cemerick | ihodes: Yeah, I had no idea you were a student, actually. :-) |
| 22:38 | ihodes | cemerick: 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:39 | cemerick | ihodes: Check your PMs :-) |
| 22:46 | gfrlog` | &(nth (sorted-set 1 2 3) 1) |
| 22:46 | lazybot | java.lang.UnsupportedOperationException: nth not supported on this type: PersistentTreeSet |
| 22:46 | gfrlog` | :( |
| 22:51 | amalloy | gfrlog`: the sorted-set impl couldn't do that any faster than ##(nth (seq (sorted-set 1 2 3)) 1) anyway |
| 22:51 | lazybot | ⇒ 2 |
| 22:52 | amalloy | but i bet there's a measure for a finger tree that combines sorting with random access |
| 22:56 | gfrlog` | amalloy: a tree set can't nth? :/ |
| 22:56 | gfrlog` | that's....unnecessary |
| 22:57 | amalloy | no, why would it bother? |
| 22:57 | gfrlog` | because it's so close to being able to? |
| 22:58 | amalloy | no it isn't |
| 22:58 | gfrlog` | then I don't know what a tree set is |
| 22:59 | amalloy | it would have to track, at each node, how many things are in the left and the right branch |
| 22:59 | gfrlog` | amalloy: that's what I meant by so close |
| 22:59 | gfrlog` | all it would have to do is track, at each node, how many things are in the left and the right branch |
| 22:59 | 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:00 | amalloy | but seriously, this is what finger trees are for. go try them out |
| 23:00 | gfrlog` | I know :( |
| 23:00 | Scriptor | amalloy: like, teh #{} kind of set? |
| 23:00 | Scriptor | *the |
| 23:01 | gfrlog` | Scriptor: ##(sorted-set 1 3 2) |
| 23:01 | lazybot | ⇒ #{1 2 3} |
| 23:01 | amalloy | Scriptor: uh, what is this in reference to? |
| 23:01 | Scriptor | amalloy: <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:01 | amalloy | Scriptor: #{} is a hash set (well, probably array set) |
| 23:02 | amalloy | sorted-set is a tree set |
| 23:02 | Scriptor | ah, interesting |
| 23:02 | amalloy | gfrlog`: a mutable tree set would have to percolate the changes back up to the root at every insertion |
| 23:02 | amalloy | persistent tree sets have to do that anyway |
| 23:03 | gfrlog` | amalloy: so how would clojure's implementation be "pretty close" to the mutable tree set? |
| 23:03 | amalloy | gfrlog`: i dunno man |
| 23:03 | gfrlog` | it seems like an all or nothing attribute to me |
| 23:06 | amalloy | i mean the code to implement it seems like it would be similar, not that they would behave similarly |
| 23:06 | amalloy | and who knows, maybe i'm wrong. feel free to read more thoroughly into the source; i've only skimmed |
| 23:08 | amalloy | cuddle-trees |
| 23:09 | gfrlog` | rooted acyclic graphs with ordered children |
| 23:10 | gfrlog` | (ragwoc?) |
| 23:10 | gfrlog` | I guess that's a description of trees generally, not finger-trees specifically :/ |
| 23:14 | amalloy | trees don't neessarily have ordered children |
| 23:14 | gfrlog` | finger-trees don't? |
| 23:15 | gfrlog` | $google tree data structure |
| 23:15 | lazybot | [Tree (data structure) - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Tree_(data_structure) |
| 23:19 | amalloy | gfrlog`: they do. but you said it was a description of trees generally, so i interjected |
| 23:19 | gfrlog` | :) |
| 23:19 | gfrlog` | yeah I admit it was ambiguous |
| 23:20 | gfrlog` | 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:20 | gfrlog` | (by "a type of graph" I mean specifically connected acyclic graphs) |
| 23:24 | amalloy | gfrlog`: {:a nil :b {:c 2}} is a "tree data structure". what order are the children a and b in? |
| 23:25 | gfrlog` | I prefer to call it a map :P |
| 23:26 | gfrlog` | okay you win this round |
| 23:27 | amalloy | (inc pedantry) |
| 23:27 | lazybot | ⟹ 1 |
| 23:28 | gfrlog` | (inc (inc pedantry)) |
| 23:28 | lazybot | ⟹ 1 |
| 23:28 | gfrlog` | (inc ) |
| 23:28 | lazybot | ⟹ 1 |