2010-11-02
| 00:08 | _seanc_ | I see that add-classpath is deprecated, what is the correct way to add things to the classpath? I need to add the Sqlite driver :X |
| 00:12 | amalloy | _seanc_: i don't actually know about classpath management in clojure. i'd either add it to my CLASSPATH env variable or figure out how to get the jar from maven |
| 00:13 | amalloy | if you're using lein or cake, you should be able to specify a dependency on sqlite in project.clj, and they'll download it, put it on the classpath, and make it Just Work |
| 00:14 | _seanc_ | I didn't know lein would do that, I'll look into it |
| 00:14 | amalloy | it looks like you just have to add [org.xerial/sqlite-jdbc "3.7.2"] to project.clj |
| 00:14 | amalloy | as a dependency |
| 00:16 | amalloy | _seanc_: yeah, just tried it in one of my projects, and it goes and gets it for me |
| 00:16 | _seanc_ | How did you figure that out? |
| 00:16 | amalloy | well, i searched on google for "sqlite maven" |
| 00:16 | _seanc_ | I was thinking I needed to use clojars, which is 0.5.6 |
| 00:16 | _seanc_ | ah |
| 00:17 | amalloy | found the artifact ID and a list of version numbers; picked the newest |
| 00:17 | amalloy | obviously if you need a different version you should specify that instead |
| 00:19 | _seanc_ | I forget that lein is mavenish |
| 00:20 | amalloy | oh by the way, you have to run lein deps to actually *get* the jars |
| 00:23 | _seanc_ | got that part! :D |
| 00:23 | _seanc_ | You're awesome, thanks |
| 00:25 | amalloy | welcome, _seanc_ |
| 00:42 | jcromartie | does lein use a local maven repo to store jars of the same version? |
| 00:42 | amalloy | jcromartie: ~/.m2 |
| 00:42 | jcromartie | ok so it doesn't always fetch |
| 00:43 | amalloy | no |
| 00:43 | jcromartie | I like my build tools to work offline at least at some point |
| 00:43 | amalloy | though you can force it to, if you tell it to get a snapshot |
| 01:58 | LauJensen | Good morning team :) |
| 02:02 | amalloy | mornin' LauJensen |
| 02:08 | sthubner | good morning! |
| 02:11 | rata_ | good morning LauJensen |
| 02:12 | rata_ | how do you get the previous versions of a ref/atom? is it possible? |
| 02:14 | amalloy | rata_: you have to track them yourself. you might find add-watch useful |
| 02:14 | amalloy | &(doc add-watch) |
| 02:14 | sexpbot | ⟹ "([reference key fn]); Alpha - subject to change. Adds a watch function to an agent/atom/var/ref reference. The watch fn must be a fn of 4 args: a key, the reference, its old-state, its new-state. Whenever the reference's state might have been changed, any registered watches will have their function... http://gist.github.com/659310 |
| 02:16 | rata_ | which files installs lein self-install? |
| 02:17 | amalloy | rata_: http://github.com/technomancy/leiningen/raw/master/bin/lein |
| 02:18 | rata_ | no... I mean... once you run "lein self-install", does it install other files besides "lein"? |
| 02:19 | amalloy | rata_: i think it gets a copy of maven, and uses that to get clojure and clojure-contrib, and then the real leiningen jars |
| 02:19 | rata_ | ok |
| 02:21 | amalloy | why do you ask? |
| 02:23 | rata_ | because the archlinux AUR package installs just /usr/bin/lein and I was suspicious about that |
| 02:23 | amalloy | ah |
| 02:24 | rata_ | ok... a "locate lein" says it installed everything inside ~/.m2 :) |
| 02:24 | rata_ | amalloy: did you solve the problem you had with the value of an atom being changed? |
| 02:25 | amalloy | rata_: sorta. i ended up using another atom |
| 02:25 | rata_ | amalloy: why not use add-watch + set-validator? |
| 02:27 | amalloy | rata_: those introduce asynchronicity and/or exception-handling problems that have to be handled with every swap! |
| 02:29 | rata_ | amalloy: I didn't know that... why is it so? add-watch says the fn is called synchronously |
| 02:30 | amalloy | rata_: sure, synchronously, but then your watcher function has to do something that causes the original caller/swapper to abort the swap, or notice it hasn't applied cleanly. that seems even less clean to me |
| 02:32 | amalloy | and even if it's technically synchronous, you have to do basically the same thing as if it were asynchronous. try using it yourself |
| 02:33 | rata_ | and why don't you compare the old value with the new value in the caller/swapper? |
| 02:34 | amalloy | rata_: then i can't tell whether it stayed the same because (f old-val) == old-val, or because (pred (f old-val)) was false |
| 02:35 | rata_ | do you need to make that difference? |
| 02:35 | rata_ | and the value is an integer, right? |
| 02:35 | amalloy | in my particular case...maybe, i'm not sure. but i wanted to generalize this to be useful for every instance of this problem |
| 02:36 | rata_ | what are you working on? |
| 02:36 | amalloy | sexpbot, at the moment |
| 02:36 | amalloy | it wants to make sure only N threads can be servicing requests at a time |
| 02:37 | amalloy | so i could do it by comparing the old-val and new-val, since it's just an integer and i know it's incrementing |
| 02:37 | amalloy | but i was hoping to solve the problem in a more general way |
| 02:38 | hiredman | uh |
| 02:39 | hiredman | amalloy: http://download.oracle.com/javase/tutorial/essential/concurrency/pools.html |
| 02:42 | amalloy | hiredman: good point, and maybe the right long-term answer. but what if, eg, someone sends sexpbot a million long-running requests via /msg? the current implementation sends them back a million error messages; a thread pool would queue them all up, locking up sexpbot until they were done |
| 02:49 | rata_ | amalloy: and set-validator! + try-catch?... if the validator fn returns false, it throws an exception and you know it failed... and you don't need the extra atom |
| 02:50 | amalloy | rata_: no, but i need a try/catch. i don't think either is much better than the other |
| 02:52 | amalloy | rata_: my current implementation is at http://bit.ly/aw8GIW if you want to tell me how it could be better |
| 02:52 | rata_ | a macro could hide the try-catch thing in a beautiful thing... maybe (changed? (swap! an-atom inc) :some-kwd)... if it doesn't change :some-kwd will be returned... it's the same logic as (get ...) |
| 02:52 | amalloy | rata_: you don't really need a macro; you can do it in a function that hides the same logic |
| 02:53 | rata_ | can you do it? the exception would be thrown on the swapper function and not in "changed?" |
| 02:54 | amalloy | rata_: see the commit i linked. i used an atom, but the function could use try/catch similarly |
| 02:57 | rata_ | which commit? |
| 02:58 | amalloy | http://bit.ly/aw8GIW |
| 03:02 | rata_ | amalloy: yes, it's the same idea |
| 03:07 | rata_ | but maybe the try-catch thing will be a little faster, as it doesn't need to create an atom (which I suppose isn't cheaper than throwing an exception, but don't know really) |
| 03:08 | amalloy | rata_: i don't know either, but i had the opposite intuition - i know exceptions are slow, and the STM seemed like it had to be faster |
| 03:09 | rata_ | oh ok |
| 03:17 | rata_ | amalloy: I was away when you said it, but congratulations for being in the contributors list =) |
| 03:17 | amalloy | heh, thanks |
| 04:50 | rata_ | good night :) |
| 04:59 | esj | Morning all |
| 05:02 | LauJensen | Morning esj |
| 06:15 | Kenjin | hello |
| 06:30 | Kenjin | Could someone take a look please? https://gist.github.com/ffaea21e7de730165da6 thanks |
| 06:44 | esj | Kenjin: I get a "connection refused" but I have zero idea about java.rmi |
| 06:45 | Kenjin | esj: the java bit has to be running |
| 06:46 | Kenjin | basically "r.rebind("rmi://localhost/rmiconnect", rc);" creates an object rmiconnect in the rmi-registry |
| 06:46 | esj | ox |
| 06:46 | esj | sorry to be no help |
| 06:47 | Kenjin | esj: no problem. thanks for taking look :) |
| 07:32 | neotyk | &(loop [s '(1 2 3)] ((fn [] (if-let [r (next s)] (recur (rest s)))))) |
| 07:32 | neotyk | ,(loop [s '(1 2 3)] ((fn [] (if-let [r (next s)] (recur (rest s)))))) |
| 07:32 | clojurebot | java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 0 args, got: 1 |
| 07:33 | neotyk | can someone explain why (fn [] takes precedence over (loop [..] ? |
| 07:34 | LauJensen | neotyk: It looks up the tree and grabs the first match IIRC |
| 07:35 | neotyk | Hi LauJensen, yes, that is for sure what happens |
| 07:35 | neotyk | any ideas how do I make sure that loop is used? |
| 07:35 | neotyk | I have no option to get rid of this fn [] |
| 07:36 | neotyk | this is generated by macro of with-connection from sql |
| 07:41 | neotyk | ok, local let FTW |
| 08:16 | LauJensen | clojurebot: clojureql? |
| 08:16 | clojurebot | clojureql is http://gitorious.org/clojureql and tracked @ http://clojureql.lighthouseapp.com/ |
| 08:16 | LauJensen | clojurebot: forget clojureql |
| 08:16 | clojurebot | clojureql is http://gitorious.org/clojureql and tracked @ http://clojureql.lighthouseapp.com/ |
| 08:16 | LauJensen | clojurebot: clojureql is http://github.com/LauJensen/clojureql |
| 08:16 | clojurebot | Roger. |
| 08:32 | _na_ka_na_ | how to do byte operations in Clojure? For example how to do 76 & 0xFF |
| 08:35 | cemerick | -> (bit-and 76 0xFF) |
| 08:35 | cemerick | ,(bit-and 76 0xFF) |
| 08:35 | clojurebot | 76 |
| 08:36 | cemerick | huh, no sexpbot |
| 08:36 | cemerick | _na_ka_na_: ^^ |
| 08:36 | _na_ka_na_ | thanks |
| 09:17 | tonyl | morning |
| 09:17 | neotyk | afternoon |
| 09:23 | fliebel | morning |
| 09:24 | raek | fliebel: did you manage to see this? http://pastebin.com/9CUeiq3W |
| 09:24 | raek | 5 mins after you left... |
| 09:24 | fliebel | raek: No, I didn't |
| 09:26 | fliebel | raek: Great! Only I just posted it to the mailinglist :( |
| 09:26 | tonyl | fliebel: it's happened to me before |
| 09:27 | fliebel | raek: Trying it right away. |
| 09:29 | raek | as jarpiain said, reduce builds up a nested lazy sequence of map calls |
| 09:31 | fliebel | raek: Right. I was hoping someone would say something like that. My firt thought was a mistake, then I thought of a lazy gotcha, but hten I started to belive it was a real bug. |
| 09:35 | fliebel | raek: Works! Next step is to figure out why it is so slow and make it use all my cores. |
| 10:03 | jaley | hello! can anyone clarify the ! naming convention for me? is it supposed to indicate side-effects only? or something else? |
| 10:04 | raek | jaley: side-effects that are not safe to do in a transaction or a transition function (or anything that might be executed more than one time) |
| 10:05 | drewr | I generally use it to also mean there's no interesting return value from the function (though that's not necessarily clojure's position) |
| 10:05 | jaley | ok.. so it'd be sensible to use it for operations that send things over a network? as in... i don't want to resend requests in transactions being retried |
| 10:05 | raek | yes |
| 10:05 | jaley | cool - thanks guys! |
| 10:10 | fliebel | How can I do type hinting inside of ->? |
| 10:11 | bsteuber | I like the quote "Java is the new COBOL" from clojure in action |
| 10:12 | chouser | heh. I thought that was VB |
| 10:12 | bsteuber | might be nice on a T-Shirt :) |
| 10:12 | chouser | or PHP, or ... |
| 10:12 | bsteuber | true, there are more candidates |
| 10:12 | tonyl | fliebel: do you mean data type hinting or fn parameters type hinting |
| 10:14 | fliebel | tonyl: I think the data thing. I get reflection warnings for a few method calls without parameters. |
| 10:14 | chouser | fliebel: you should be able to hint the previous expression. |
| 10:15 | fliebel | tonyl: I'm doing something like (-> file .method1 .method2) |
| 10:16 | fliebel | chouser: I hinted the starting value, but I don't understand where the type gets lost and how to add it back. |
| 10:17 | fliebel | http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L20 |
| 10:18 | chouser | fliebel: these are just guesses since I don't have the required jars to test it, but it's probably just the (get ...) forms that Clojure can't figure out the return type of |
| 10:19 | chouser | so try hinting those, like ^LevelObject (get "Level") |
| 10:19 | fliebel | chouser: I turned them into .get calls, which didn't help. Will try the hint there. |
| 10:25 | chouser | oh, you should hint file too |
| 10:27 | fliebel | chouser: I hinted nearly every single line in that macro :( |
| 10:30 | fliebel | chouser: All these methods are now java, so they should have a set return type. But I keep getting 2 of these: Reflection warning, clomian.clj:25 - call to get can't be resolved. |
| 10:30 | fliebel | Reflection warning, clomian.clj:27 - reference to field getValue can't be resolved |
| 10:32 | AWizzArd | interesting: I was running (time (dotimes [i 10000000] (XYZ "12345"))) and got those timings (in msecs) for XYZ replaced with: empty? 560, not-empty 560, (not (empty? )) 650 (why is this so much slower?), seq 480, .isEmpty 3 (winner), (not (.isEmpty )) 42 |
| 10:32 | AWizzArd | (time (dotimes [i 10000000] (not true))) ==> 41 msecs |
| 10:33 | AWizzArd | Is timing (not true) mostly measuring how long looking up 'not' takes? |
| 10:38 | AWizzArd | $(let [*14-days* 14] 10) |
| 10:38 | AWizzArd | ,(let [*14-days* 14] 10) |
| 10:38 | clojurebot | 10 |
| 10:38 | AWizzArd | ,(let [+14-days+ 14] 10) |
| 10:38 | clojurebot | Invalid number: +14-days+ |
| 10:39 | AWizzArd | Bug or feature? ;) |
| 10:49 | jcromartie | AWizzArd: what |
| 10:49 | jcromartie | AWizzArd: I'm confused |
| 10:50 | jcromartie | ,'+1 |
| 10:50 | clojurebot | 1 |
| 10:50 | jcromartie | ,'+1- |
| 10:50 | clojurebot | Invalid number: +1- |
| 10:51 | tonyl | so +1 is a number |
| 10:52 | tonyl | ,+1 |
| 10:52 | clojurebot | 1 |
| 10:52 | tonyl | ,-1 |
| 10:52 | clojurebot | -1 |
| 10:52 | tonyl | pos and neg |
| 10:53 | tonyl | fliebel: get you give a snippet of the blocks fn, to see how the type hinting of java calling is going. |
| 10:54 | fliebel | tonyl: "get you give"? |
| 10:55 | tonyl | *can you give or post a snippet |
| 10:55 | tonyl | :P mybad |
| 10:56 | fliebel | tonyl: I have this with ^java.io.File at the top and get > .get http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L20 |
| 10:57 | tonyl | alright, i'll test it |
| 10:59 | fliebel | awesome |
| 11:00 | tonyl | does the input file has some special markup or it can be a file with any content? |
| 11:01 | fliebel | tonyl: It's a nbt file. I don't think you can test it without installing jnbt and getting some sample file. |
| 11:02 | fliebel | tonyl: I think I'm better of finding a profiler and utilizing my other core than nitpicking about reflection. |
| 11:04 | tonyl | yeah... I haven't mess with nbt files |
| 11:14 | jcromartie | wow can we have an official Clojure version of this http://docs.python.org/faq/programming |
| 11:19 | chouser | AWizzArd: for me, all the seq/empty calls (with or without not) come in at essentially identical times, and .isEmpty (with or without not) is indeed about 100x faster |
| 11:20 | chouser | oops, sorry, was scrolled way up. |
| 11:36 | AWizzArd | chouser: are you on 1.3α2 ? |
| 11:36 | chouser | yeah |
| 11:37 | AWizzArd | and is (not (.isEmpty )) as fast as .isEmpty alone, or takes 10x as much runtime? |
| 11:38 | mrijk | Hi all... I am looking for the tree picture (hires) from the presentation "The Roots of Clojure" |
| 11:39 | AWizzArd | My timings were .isEmpty < (not (.isEmpty )) < seq < empty? < not-empty < (not (empty? )) |
| 11:42 | chouser | AWizzArd: same speed |
| 11:42 | chouser | .isEmpty == (not (.isEmpty )) < seq == empty? == not-empty == (not (empty? )) |
| 11:42 | chouser | AWizzArd: you're letting hotspot have a chance to inline everything? |
| 11:51 | fliebel | tonyl: I don't understand half of what I'm doing in this profiling app, but it seems it's spending quite a lot of time reflecting, and runs on one core at the moment. |
| 11:53 | tonyl | is it reflecting all the methods? |
| 11:54 | tonyl | for sure it is not reflecting anything clojure, that is the weird part |
| 11:54 | fliebel | tonyl: I'm not sure. I think only 2-4 of them. |
| 11:57 | chouser | fliebel: if you care about performance, it's absolutely worth getting rid of reflection |
| 11:57 | chouser | fliebel: what version of Clojure are you using? |
| 11:57 | fliebel | chouser: I figured… 1.2 |
| 11:58 | chouser | and it's complaining about .get and .getValue? |
| 11:58 | fliebel | yea |
| 11:59 | chouser | care to paste or push what you've currently got? |
| 12:00 | fliebel | okay, but currently… it stopped "working" i.e. giving reflection warnings. So I'll get those back fisrt. |
| 12:00 | chouser | hm |
| 12:01 | chouser | actually, wait a sec |
| 12:02 | fliebel | okay, it "works" again |
| 12:02 | fliebel | http://github.com/pepijndevos/Clomian/blob/master/src/clomian.clj#L23 |
| 12:03 | fliebel | Check this for the return values: http://jnbt.sourceforge.net/doc/ |
| 12:03 | chouser | .getValue only claims to return an Object. What type is it actually going to return? |
| 12:03 | fliebel | all but the last one return CompoundTag the last bye[] |
| 12:05 | fliebel | and get returns some sort of map, does it matter which one? |
| 12:05 | chouser | a Clojure map? |
| 12:05 | fliebel | no, java.util.map |
| 12:05 | chouser | ok |
| 12:09 | chouser | CompoundTag doesn't have a 'get' method |
| 12:09 | fliebel | chouser: ^org.jnbt.CompoundTag (.get "Level") for both gets leaves me with only this one: Reflection warning, clomian.clj:28 - call to get can't be resolved. |
| 12:10 | chouser | oh, .get is returning a CompoundTag |
| 12:10 | chouser | ok, I'm caught up |
| 12:10 | Kenjin | hi |
| 12:10 | fliebel | yea, I'm confused as wel.. |
| 12:11 | Kenjin | Anyone done some rmi with clojure? https://gist.github.com/ffaea21e7de730165da6 |
| 12:11 | chouser | try ^java.util.Map (.getValue) instead of the first .getValue |
| 12:11 | fliebel | getValue returns a map of tags, and those tags return another map. |
| 12:12 | fliebel | briljant! Works so far :) |
| 12:12 | chouser | :-) |
| 12:15 | fliebel | Now I only need to figure out how to use my other core. Agents, future, pmap… I don't know. Does Joy of Clojure have a chapter on this? |
| 12:17 | chouser | hm, what you want is parallelism, I think, not concurrency |
| 12:18 | chouser | which is currently better covered outside clojure's core features than within them. |
| 12:18 | fliebel | chouser: You mean in Java? |
| 12:18 | chouser | I mean Clojure has these innovative features to address concurrency, but little of its own to address parallelism |
| 12:19 | chouser | but perhaps pmap or the forkjoin lib would help. |
| 12:19 | tonyl | futures? |
| 12:20 | chouser | either way, you're going to need to figure out what chunks of work are expensive enough to be worth farming out to other threads |
| 12:20 | chouser | there's some interesting stuff coming to integrate forkjoin with Clojure vectors, but I'm not sure if it's available anywhere yet. |
| 12:20 | fliebel | chouser: IO? I'm reading 2000 files ;) |
| 12:20 | chouser | Liebke gave a talk on it at Clojure Conj. |
| 12:21 | fliebel | chouser: I saw the slides. |
| 12:21 | AWizzArd | chouser: did the Conj gave any insights about what opportunities Clojure will have in future versions to tackle parallelism? |
| 12:21 | chouser | fliebel: if you're IO-bound, you may not be able to keep all your cores busy |
| 12:22 | fliebel | chouser: I'm not sure I am… I'm just doing a lot of it. |
| 12:23 | chouser | AWizzArd: just what I mentioned. |
| 12:24 | angerman | are there any enty level clojure presentation slides up online somewhere I might take a look at for inspiration? |
| 12:24 | chouser | angerman: rhickey's videos are still the gold standard (and widely mimicked) I believe |
| 12:24 | chouser | angerman: -for-lisp-programmers and -for-java-programmers |
| 12:25 | AWizzArd | chouser: yes, saw it after hitting Enter. |
| 12:25 | chouser | AWizzArd: :-) ok |
| 12:25 | chouser | angerman: you're giving an intro talk? |
| 12:25 | angerman | chouser: yep, tomorrow. |
| 12:25 | chouser | heh |
| 12:26 | angerman | it's at the chair at my university where I'm writing my final thesis. |
| 12:26 | chouser | well, I've given a couple of those now, and next time I think I'm going to try keep the number of "clojure syntax" slides to 1 or 0 |
| 12:27 | fogus_ | chouser: 1 is more ffective |
| 12:27 | chouser | I liked how my expression-problem talk went in that regard -- present an interesting problem and some code in a familiar language that sets up or solves the problem |
| 12:27 | fogus_ | with a single bullet ;-) |
| 12:27 | chouser | fogus_: * none ? |
| 12:28 | chouser | then once they've got the data structures/problem space in their head, re-present with clojure syntax. |
| 12:28 | chouser | and *hopefully* they can just ease into it without concentrating on the details too much |
| 12:28 | angerman | nah, they do know java fairly well. We had a talk on python a few weeks ago and they were interested and at the same time scared that you could probably poke any object with lots of crap. |
| 12:28 | chouser | heh |
| 12:29 | chouser | "you could, but you don't" :-) |
| 12:29 | angerman | though I'd say they are very likely familiar with functional approaches. |
| 12:29 | angerman | so it's more a "so we got the JVM we like, and here's a language that put's the fun back into programming. |
| 12:31 | fliebel | chouser: Some high-tech profiling with Activity monitor and println shows that I'm doing 100% of one core and not so much IO, though the number of files being read is huge(I estimate 5 per second). |
| 12:31 | clojurebot | Ok. |
| 12:35 | chouser | fliebel: freqs takes the bulk of youre time? |
| 12:36 | chouser | fliebel: btw, you can (repeat 128 {}) |
| 12:37 | fliebel | chouser: I think so, but I haven't tried very hard to profile. |
| 12:40 | fliebel | chouser: There are a few copies of pvreduce floating around on github. That sounds like the thing I need. |
| 12:54 | lpetit | Hi, in the github "clojure" organization, the sub project names are not prepended with "clojure.". While I can see this makes sense because they already are in the "clojure" organization, there's still the problem that this "organization" metadata is github specific, not git. So by default when people will start to "fork" clojure organization's project, not having this "clojure." prefix may be a problem. At least I know that for my |
| 12:59 | lpetit | Wouldn't it make sense to add a "clojure." prefix to the project names ? |
| 13:10 | amalloy | lpetit: like change the clojure repository from "clojure" to "clojure.clojure"? |
| 13:11 | lpetit | Oh please |
| 13:12 | lpetit | amalloy: like clojure.data.finger-tree instead of data.finger-tree, (or maybe clojure-data.finger-tree to follow the "contrib" convention ?) |
| 13:16 | lpetit | must leave, have posted the question on IRC? cu |
| 13:16 | lpetit | s/IRC/ml/ |
| 13:30 | amalloy | &(class #"") |
| 13:30 | amalloy | ,(class #"") |
| 13:30 | clojurebot | java.util.regex.Pattern |
| 13:31 | amalloy | ,(class java.util.regex.Pattern) |
| 13:31 | clojurebot | java.lang.Class |
| 13:31 | fliebel | amalloy: The mysterious Class object :) |
| 13:32 | amalloy | fliebel: i always forget and try to use Pattern/class |
| 13:37 | amalloy | being able to just use Pattern will be very convenient if i ever remember it |
| 13:48 | alpheus | I need help understanding when function names are bound to the function object. I tried to write a trace utility (using robert.hooke) to trace a recursive function, and, of course, the call inside the function was to a function *before* the hook was installed, so only the outer function call was traced. |
| 13:49 | alpheus | In Lisp, I might try to bind later, using something like funcall through a name to designate the function. |
| 13:51 | amalloy | alpheus: (declare) is for forward declarations |
| 13:51 | chouser | alpheus: this is changing between 1.2 and 1.3. which version would you like to discuss? :-) |
| 13:52 | alpheus | 1.2, I guess. I'm hoping to have some working code before 1.3 is released ;) |
| 13:56 | chouser | hm |
| 13:56 | chouser | I thought I knew, but I'm seeing behavior I wasn't expeting |
| 13:56 | alpheus | We can pretend I'm debugging fib: (defn fib [n] (if (= n 1) 1 (* n (fib (- n 1))))) ;; not the production version, of course |
| 13:57 | chouser | duh, I'm on 1.3 |
| 13:58 | chouser | hm, same on 1.2 |
| 13:58 | ubii | trying to find some recent Clojure podcasts or videos, can anyone point me to a few? |
| 13:58 | ubii | most of the ones that I have found so far, are from 2008 |
| 13:58 | ubii | also, any word on when the Clojure Conj videos will be available? |
| 13:58 | chouser | alpheus: you can delay var resolution for you recursive call by using (#'fib (- n 1)) instead |
| 13:59 | alpheus | indeed? |
| 14:00 | alpheus | Thank you. It does just what I needed. |
| 14:00 | chouser | alpheus: that'll work the same going forward |
| 14:01 | ubii | chouser: when do you expect JoC to be completed? |
| 14:01 | chouser | note there's some runtime cost because it derefs #'fib each time its called |
| 14:01 | ubii | going through the MEAP now and am really enjoying it |
| 14:01 | kryft | ubii: December, I think. |
| 14:02 | chouser | ubii: thanks! the chapters are essentially complete. hoping for tree pulp version in December |
| 14:02 | alpheus | It's funny. I tried the same thing with Stuart Sierra's trace and when it didn't show the inner function calls, I decided to write my own using robert.hooke. |
| 14:02 | alpheus | Now I know the real answer. |
| 14:02 | chouser | ohhhh |
| 14:03 | alpheus | I'm lucky my employers are tolerant of my learning clojure on their dime! |
| 14:03 | ubii | chouser: when do you plan to go back and address some of the minor spelling/grammar and formatting issues in the MEAP, which folks have brought up on the MEAP forum? |
| 14:04 | chouser | ubii: the copyeditors are hard at work, presumably as we speak. |
| 14:04 | ubii | chouser: cool, thx |
| 14:05 | kryft | chouser: Hehe, glad to hear that, although I love the content. :) |
| 14:05 | clojurebot | amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it |
| 14:06 | chouser | ,(macroexpand-1 '(defn f [] (f))) |
| 14:06 | clojurebot | DENIED |
| 14:07 | chouser | hmph |
| 14:07 | chouser | alpheus: anyway, look at the macroexpansion carefully |
| 14:07 | chouser | alpheus: and tell me what defines f at the point of the recursive call |
| 14:09 | ubii | chouser: I have to say that I really like the approach you guys took, where you start off by explaining the philosophy of Clojure and providing an overview of the core concepts, as compared to other books, which simply jump right in to basic syntax |
| 14:09 | kryft | Agreed. |
| 14:09 | kryft | It really is a joy to read in that respect. |
| 14:10 | chouser | well, that's good to hear. those two chapters got shuffled repeatedly through the process before finally landing with philosophy first. |
| 14:10 | kryft | I also like how you actually explain a bit about what's going on under the hood (eg. how to implement persistent data structures efficiently) |
| 14:11 | chouser | kryft: I was going to go with "it's magic", which is just one more reason why it's good to have fogus_ as a co-author. |
| 14:11 | ubii | :) |
| 14:12 | amalloy | chouser: well, neither of you is wrong |
| 14:13 | kryft | chouser: :) |
| 14:17 | arohner | when using paredit, how do you split a string into two strings? i.e. "foo | bar" -> "foo " "bar" |
| 14:18 | amalloy | arohner: M-shift-s, as i recall |
| 14:18 | maravillas | M-S perhaps? |
| 14:19 | arohner | amalloy, maravillas: yes, thank you |
| 14:19 | arohner | paredit-split-sexp |
| 14:20 | fliebel | Are there any gotchas for using transients? I have a seq of transient maps, but when I do (map persistent!) on them, I get "Transient used after persistent! call" |
| 14:23 | AWizzArd | fliebel: do you have a doall around your map? |
| 14:23 | AWizzArd | You better should use doseq here. |
| 14:23 | amalloy | hm, not that i know of. |
| 14:23 | amalloy | &(map persistent! (map transient! (map range (range 4)))) |
| 14:23 | sexpbot | java.lang.Exception: Unable to resolve symbol: transient! in this context |
| 14:23 | amalloy | &(map persistent! (map transient (map range (range 4)))) |
| 14:23 | sexpbot | java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IEditableCollection |
| 14:24 | amalloy | oh well :P |
| 14:27 | fliebel | still nothing. |
| 14:29 | chouser | fliebel: transients are not mutable collections in the classic sense. you have to leave your code structured as for persistent collections |
| 14:29 | chouser | ...and just do a transient up front and a persistent! afterwards |
| 14:30 | LauJensen | &(-> [1 2 3] transient (conj! 4) persistent!) |
| 14:30 | sexpbot | ⟹ [1 2 3 4] |
| 14:31 | fliebel | chouser: I do that… I think. I have a seq of transients, and when I do persistent! on one item, it works. When I do it to all in a map I get an error. |
| 14:31 | AWizzArd | fliebel: do you have a 'doall' around your map? |
| 14:32 | chouser | hmmm |
| 14:32 | fliebel | AWizzArd: I'm on the repl, so they're going to get realized anyway. |
| 14:32 | chouser | actually, it might have to be around inner map's |
| 14:34 | chouser | ,(last (map persistent! (map-indexed #(conj! %2 %1) (map transient (repeat 100 []))))) |
| 14:34 | clojurebot | [99] |
| 14:34 | chouser | hm, or maybe not |
| 14:34 | chouser | ,(last (map persistent! (map-indexed #(conj! %2 %1) (repeat 100 (transient []))))) |
| 14:34 | clojurebot | java.lang.IllegalAccessError: Transient used after persistent! call |
| 14:35 | fliebel | chouser: This works: (persistent! (first t)) This doesnt: (doseq [t t] (println (persistent! t))) |
| 14:35 | chouser | fliebel: are you sure they're different transients? |
| 14:36 | fliebel | chouser: Different? t and t is the same thing. |
| 14:36 | chouser | ,(let [t (repeat 2 (transient []))] (= (first t) (second t))) |
| 14:36 | clojurebot | true |
| 14:37 | chouser | ,(let [t (map transient (repeat 2 []))] (= (first t) (second t))) |
| 14:37 | clojurebot | false |
| 14:38 | Raynes | chouser: One of these days I'm going to replace your comma and ampersand keys while you're in the shower. |
| 14:38 | fliebel | chouser: wait… you are onto something there. If I would add an item to one of those transients, would the other get updated as well? |
| 14:39 | chouser | fliebel: sometimes, yes. |
| 14:39 | jarpiain | ,(persistent! (second (reductions conj! (transient []) [1 2 3 4])) |
| 14:39 | clojurebot | EOF while reading |
| 14:39 | jarpiain | ,(persistent! (second (reductions conj! (transient []) [1 2 3 4]))) |
| 14:39 | clojurebot | [1] |
| 14:39 | jarpiain | ,(map persistent! (reductions conj! (transient []) [1 2 3 4])) |
| 14:39 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalAccessError: Transient used after persistent! call> |
| 14:40 | chouser | Raynes: , is clojure whitespace -- I find this a convenient coincidence |
| 14:40 | chouser | not to mention a hard habit to break. :-) |
| 14:40 | fugue | Is there any way to pass system properties while using lein swank ? |
| 14:40 | fliebel | chouser: Woo, changing (repeat 128 (transient {})) into (repeatedly 128 #(transient {})) solved the problem :P |
| 14:41 | chouser | fliebel: :-) there you go |
| 14:41 | Raynes | chouser: Understandable. Fortunately, outside of #clojure, sexpbot responds to ,. |
| 14:41 | chouser | Raynes: have you considered ,, ? |
| 14:41 | chouser | hm, nm |
| 14:41 | Raynes | Everybody hates two character prefixes. |
| 14:41 | chouser | ,,:already-taken |
| 14:41 | clojurebot | :already-taken |
| 14:42 | Raynes | Good prefixes are hard to find these days. ;) |
| 14:42 | chouser | what else has sexpbot used? -> and now & ? |
| 14:43 | Raynes | -> "still works" |
| 14:43 | sexpbot | ⟹ "still works" |
| 14:43 | chouser | ah, cool. |
| 14:44 | Raynes | I added & because, as I mentioned before, everybody hates two character prefixes. |
| 14:45 | fliebel | woot, using transients cut my map-hammer-time in half :) |
| 14:47 | fliebel | but I'm still limited by the speed the one core I'm using :( |
| 14:49 | ubii | fliebel: one core, why? |
| 14:50 | fliebel | ubii: because I haven't figured out how to use the other one yet. |
| 14:51 | ubii | fliebel: dumb question, is that due to how you coded things or due to your OS? |
| 14:51 | ariejan | Hello. I'm new. My name is Ariejan. Any one worked with aleph here? How can I print the user-agent string? |
| 14:52 | fliebel | ubii: because of how I coded things. |
| 14:53 | fliebel | ariejan: I don't know, but I think you'll find the answer in Ring. |
| 14:53 | alpheus | chouser: Not sure if I'm getting what you're showing me, but in (defn f [] (f)) the call to f is ultimately an arg to fn* |
| 14:54 | chouser | alpheus: yes. and f is defined by (fn f ...), which is shadowing the outer (def f ...) |
| 14:54 | ubii | fliebel: ah, ok |
| 14:54 | alpheus | ok, that makes sense |
| 14:55 | jarpiain | hmm isn't the recursive call in (def f (fn [] (f))) also compiled to this.invoke() ? |
| 14:55 | chouser | alpheus: so, could do (declare f) (def f (fn [...] ... (f ...))) |
| 14:55 | jarpiain | with or without previous declare |
| 14:56 | chouser | forcing that inner f to refer to a var instead of a local |
| 14:58 | alpheus | I see. I'll have to think about that for a while. |
| 14:59 | chouser | ah, and formulated that way still works fine in 1.3 |
| 15:01 | alpheus | Naturally, I'm starting to wonder what's really going on with recur. |
| 15:02 | chouser | recur compiles to a goto, I believe |
| 15:03 | kotarak | alpheus: are you the "hanging defmethod" guy? |
| 15:03 | chouser | jarpiain: I don't think the compiler knows f is this in (def f (fn [] ...)) |
| 15:03 | alpheus | kotarak: No, I don't think so. |
| 15:03 | kotarak | alpheus: ah. ok. never mind. |
| 15:05 | alpheus | This is a pretty great channel. But I guess you all knew that already. |
| 15:05 | jarpiain | chouser: right, just checked. The 'f is used to name the generated class but not as a this-label |
| 15:05 | chouser | jarpiain: huh! I didn't realize the name was propogated in at all. interesting. |
| 15:06 | kotarak | (def f (fn f ...))? |
| 15:06 | jarpiain | that's the only thing the third argument of analyze() is used for |
| 15:06 | chouser | kotarak: no, without the inner name |
| 15:07 | chouser | (class @(def my-name-is-here (fn []))) ;=> user$eval267$my_name_is_here__268 |
| 15:07 | kotarak | chouser: I meant with (fn f ...) the function knows itself as f. |
| 15:08 | chouser | kotarak: yes, but even without that the outer def passes the name in such that the generated class includes it. jarpiain knew this, but I'm just learning. |
| 15:15 | rata_ | hi all |
| 15:16 | fliebel | hi |
| 15:16 | kotarak | chouser: you didn't know? |
| 15:16 | kotarak | o.O |
| 15:17 | rata_ | which profiler do you guys use? |
| 15:17 | hiredman_ | it's wasn't always the case that defn propagated the name like that |
| 15:17 | kotarak | I was wondering what happens if I have something like (defn foo ...) + somehwere else (let [f (fn foo [] ...) ...) Do I get a clash in class names? |
| 15:18 | hiredman_ | no |
| 15:18 | fliebel | rata_: I just toyed with visualVM, but I don't *use* it. |
| 15:19 | rata_ | fliebel: ok.. how was it? |
| 15:20 | fliebel | rata_: Like stacktraces. |
| 15:33 | fliebel | In Python there is glob to mach certain files. What is the best way I can do this in Clojure? file-seq coms closest I think. Should I just do regexes on that and filter? |
| 15:35 | amalloy | fliebel: i haven't looked for a clojure-specific way, but java.io.File has a list(FilenameFilter) method |
| 15:36 | fliebel | amalloy: But that doesn't do recursion I think. that is more like ls | grep |
| 15:37 | amalloy | yeah, and it's kinda gross anyway, i guess |
| 15:41 | amalloy | fliebel: i don't see any better way than file-seq/regex, unless you want to use the shell's globbing |
| 15:43 | amalloy | though it's still going to recurse into directories whose children you know you won't want |
| 15:44 | amalloy | implementing filtered-file-seq yourself would be a trivial modification of http://bit.ly/bHsvOu |
| 15:44 | fliebel | amalloy: I already figured out the regex. |
| 15:46 | amalloy | you understand what i meant about recursing into uninteresting subdirs though, right? you can't fix that with just a regex |
| 15:47 | amalloy | if that doesn't matter to you, and it might well not, then go for it |
| 15:47 | fliebel | amalloy: I realize that. I'll think about it. |
| 15:47 | fliebel | amalloy: There are some 2000 files in a sub dir I'd like to avoid. |
| 15:49 | amalloy | well then, time to implement filtered-file-seq :) |
| 15:50 | fliebel | amalloy: Yea… You're right. |
| 15:53 | chouser | (tree-seq #(and (.isDirectory %) (not (re-find ... (.getName %)))) #(.listFiles %) (File. ...)) |
| 15:54 | amalloy | chouser: no cigar. you need to filter the children, not the branches |
| 15:55 | chouser | hm, I suppose you're right |
| 15:55 | fliebel | but, how does this work? listFile only returns the files, not the directories, if I'm corect. |
| 15:56 | amalloy | fliebel: you're not correct, though :) |
| 15:57 | fliebel | amalloy: Which part of my assumtion is wrong? |
| 15:57 | amalloy | it returns all the File objects, and directories are Files |
| 15:57 | fliebel | amalloy: java.io is strange... |
| 15:57 | amalloy | http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28%29 |
| 15:58 | amalloy | yes, it's a dreadful mess |
| 15:59 | ubii | I still can't get use to seeing oracle associated with java, instead of sun |
| 16:01 | amalloy | fliebel: http://download.oracle.com/javase/1.4.2/docs/api/java/io/File.html#listFiles%28java.io.FileFilter%29 could be used to return just the files or just the directories |
| 16:02 | fliebel | amalloy: Hav you seen how I am to create a FileFilter? |
| 16:03 | amalloy | fliebel: well, if you were going to do it i'd use reify. but FileFilter is a hack around java's lack of HOFs like (filter) |
| 16:03 | fliebel | amalloy: I was also thinking reify. |
| 16:06 | chouser | amalloy: one of many |
| 16:06 | amalloy | fliebel: (seq (-> (java.io.File. ".") (.listFiles (reify java.io.FileFilter (accept [this f] (.isDirectory f)))))) is how you could do it with reify |
| 16:06 | ohpauleez | ubii: me too |
| 16:06 | ohpauleez | every time I see the docs, I freak out a little |
| 16:07 | fliebel | amalloy: I know :) (thanks to chouser) |
| 16:08 | clojurebot | Why are you asking *him* |
| 16:08 | ubii | having been a Sun sysadmin, in my previous life, I find it painful to now see Oracle pasted on everything :( |
| 16:09 | technomancy | it would be good to make it easier to navigate between the wiki on dev.clojure.org and the ticket tracker |
| 16:09 | technomancy | I only found http://dev.clojure.org/jira by some random poking around |
| 16:18 | fliebel | which of all those 508 functions does the opposite of filter? I can do use not of course but I know it's there. |
| 16:19 | chouser | rmove |
| 16:19 | chouser | remove |
| 16:19 | fliebel | yay! |
| 16:19 | chouser | fliebel: http://clojuredocs.org/clojure_core/clojure.core/filter |
| 16:20 | kotarak | (filter (complement your-predicate) ...) for another road to Rome |
| 16:20 | fliebel | ooh |
| 16:22 | ubii | wait, clojuredocs is written using Rails, what happened to eating our own dog food? :) |
| 16:23 | technomancy | ubii: at least it's not closed-source anymore =\ |
| 16:23 | ubii | technomancy: what was it before? |
| 16:23 | ubii | meant to say, what was it using before? |
| 16:23 | technomancy | I guess they had "unique scalability requirements". |
| 16:23 | technomancy | no, I mean it's always been rails, but at least now it's open to community improvement |
| 16:23 | ubii | ah |
| 16:24 | ubii | wait, rails can scale, when did that happen? :) |
| 16:25 | chouser | I'm so happy to have a site like that -- if having it written with rails is what it took, so be it. |
| 16:25 | ubii | sorry, being a ruby guy, I have to bash a bit on rails |
| 16:26 | ubii | of course, even though I do ruby, I haven't touched rails in years |
| 16:26 | ubii | chouser: I agree, the tools used to build it are much less import than the fact that it exists |
| 16:27 | ubii | I was just being a smarta$$, since I knew technomancy was a fellow ruby convert |
| 16:28 | chouser | I've done a fair amount with ruby myself, though only one (attempted) rails projects. |
| 16:28 | ubii | I will shut up now and get back to reading JoC :) |
| 16:29 | technomancy | I was just a little put off by the way they brushed off compojure as "not ready" without providing constructive criticism. I think it's good that the site exists. |
| 16:30 | chouser | If I had the time to contribute to a such a project, their choice of tools would matter to me more, I'm sure. |
| 16:35 | ubii | I really should be working on implementing the necessary reporting capabilities for the Sinatra app that I wrote last week, which does email campaign monitoring |
| 16:38 | LauJensen | ubii: Only slightly more difficult than doing the same using ring and Moustache |
| 16:38 | LauJensen | At least for me :) |
| 16:38 | bobo_ | im starting to prefer moustache aswell |
| 16:38 | mabes | ubii: yeah, it wouldn't be too hard unless you are relying on a lot of gems (e.g. for openauth) |
| 16:38 | bobo_ | noticed that compojure 0.5.x was released recently though, dont know what changed |
| 16:39 | ubii | LauJensen: actually, someone else suggested that combo, so I will look at that as well |
| 16:40 | bobo_ | and dont forget to look at enlive if you want templating! |
| 16:41 | LauJensen | Yea, Moustache/Enlive is a winning combo |
| 16:42 | ubii | thx, I will check them both out |
| 16:43 | ubii | unfortunately, due to time constraints, I will need to finish up the reporting capability, using Sinatra |
| 16:43 | ubii | then I can go back and look at porting it |
| 16:43 | Raynes | The only thing keeping me from really liking Compojure is the furious lack of documentation. |
| 16:43 | ubii | still learning Clojure, so it is probably premature to try and port it right now |
| 16:44 | apgwoz | isn't compojure more or less just a url mapping framework at this point? ring handles pretty much everything else as far as i can tell. |
| 16:44 | raek | it seems so |
| 16:44 | ubii | then again, I never touched Sinatra before I wrote this app, but at least I knew Ruby |
| 16:44 | danlarkin | I've never heard a lack of something be called furious |
| 16:44 | apgwoz | (well, compojure + hiccup (or something like it) + ring) |
| 16:46 | drewr | you can read compojure's src quicker than an equivalent how-to |
| 16:46 | rlb | Can you create a class instance when the class is stored in a variable, i.e. (def x Integer) (??? x 5)? |
| 16:46 | rlb | new won't work |
| 16:47 | rlb | I can easily work around it -- mostly just curious. |
| 16:48 | pjstadig | ~suddenly |
| 16:48 | clojurebot | CLABANGO! |
| 16:49 | cemerick | danlarkin: along the lines of "violent agreement", perhaps :-) |
| 16:49 | cemerick | danlarkin: welcome back to irc ;-) |
| 16:50 | alpheus | vehement apathy |
| 16:50 | lrenn | rlb: |
| 16:50 | mabes | rlb: you can use .newInstance.. However, that doesn't seem to work on Integer.. Here is an example: |
| 16:50 | mabes | ,(let [x java.util.Date] (.newInstance x)) |
| 16:50 | clojurebot | #<Date Tue Nov 02 13:51:49 PDT 2010> |
| 16:50 | lrenn | ->(let [c java.lang.String] (.newInstance c)) |
| 16:50 | sexpbot | java.lang.IllegalArgumentException: No matching method found: newInstance |
| 16:50 | danlarkin | cemerick: ahoyhoy |
| 16:50 | _seanc_ | What is the best way to iterate over a seq and create a new collection with the values from the first? (Does that make sense?) |
| 16:50 | lrenn | oddly, that works in my repl. |
| 16:50 | hiredman | _seanc_: you mean map? |
| 16:50 | cemerick | outlandish asceticism |
| 16:51 | _seanc_ | hiredman: I tried map, it gave me an error |
| 16:51 | kotarak | "an error" means....? |
| 16:51 | _seanc_ | I cleared the terminal :X |
| 16:51 | _seanc_ | let me get it ahain |
| 16:51 | hiredman | _seanc_: well you did it wrong |
| 16:51 | duncanm | why is ^int not allowed as a type hint? is it useless to hint that? |
| 16:51 | _seanc_ | again* |
| 16:51 | _seanc_ | hiredman: that much I've come to expect :D |
| 16:51 | clojurebot | hiredman is lazy |
| 16:52 | kotarak | ,(map identity [1 2 3]) |
| 16:52 | hiredman | clojurebot: I'll replace you with a very small shell script |
| 16:52 | clojurebot | (1 2 3) |
| 16:52 | clojurebot | clojurescript is Chouser's baby |
| 16:53 | tonyl | what's up with clojurebot and its random quips? somebody logged in like it? |
| 16:53 | tonyl | they are funny though lol |
| 16:53 | rata_ | has anybody used profiler4j? |
| 16:53 | danlarkin | tonyl: it's NLP |
| 16:53 | amalloy | clojurebot: clojurescript? |
| 16:53 | clojurebot | clojurescript is Chouser's baby |
| 16:54 | amalloy | tonyl: ^^ he just overeagerly matches "regular" chatter as a question directed at his info database |
| 16:54 | tonyl | foo hahaha |
| 16:54 | tonyl | i thought it was just for an instant repl in the chat |
| 16:54 | hiredman | overeagerly? |
| 16:55 | kotarak | rata_: I used jvisualvm with success. But YMMV. |
| 16:56 | amalloy | hiredman: well he piped up with a quote about clojurescript just because your message to him ended with "script" |
| 16:56 | amalloy | clojurebot: script |
| 16:56 | _seanc_ | hiredman: where did I go wrong http://pastie.org/1267706 |
| 16:56 | hiredman | amalloy: saw your link to the horrible code you wrote to limit the number of threads running a task, I still don't see why you just don't use a threadpool |
| 16:57 | hiredman | _seanc_: doseq returns nil |
| 16:57 | hiredman | map is lazy |
| 16:57 | amalloy | hiredman: yes, i agree it's pretty horrible |
| 16:57 | hiredman | so do it right |
| 16:57 | hiredman | I pasted you a link to the pool docs |
| 16:57 | _seanc_ | I guess that's where I'm lost. The tutorial on SQL (wikibooks) has them using doseq |
| 16:58 | amalloy | hiredman: i'm trying to improve thread-safety in the current code without changing its semantics |
| 16:59 | hiredman | if the semantics are garbage they should be changed |
| 17:00 | amalloy | hiredman: fixedthreadpool queues up pending requests; currently sexpbot discards them. i don't see any particular reason to prefer queueing them instead of discarding them |
| 17:01 | hiredman | you can easily write a custom threadpool |
| 17:02 | hiredman | you wouldn't even need a custom threadpool |
| 17:02 | amalloy | hm, okay, i'm looking at ThreadPoolExecutor |
| 17:03 | _seanc_ | hiredman: since map iterates over the coll, how do you access the current value within the function? |
| 17:03 | _seanc_ | Ah ha! I figured it out |
| 17:03 | tonyl | _seanc_ is the parameter passed to the fn |
| 17:03 | _seanc_ | it's the combination of #(%) - right? |
| 17:03 | tonyl | or (fn [parameter] parameter) |
| 17:04 | _seanc_ | granted, while it works, I still don't fully understand # |
| 17:04 | _seanc_ | tonyl: cool! That's awesome thanks for the tip |
| 17:04 | amalloy | _seanc_: then i suggest not using #(...) yet. it's really shorthand for (fn [...] ...) |
| 17:05 | _seanc_ | amalloy: oh, well that's a really straightforward explanation. You need to write a blog so I can read it :D |
| 17:05 | bobo_ | you can also just use defn and create a function if you want to name it. |
| 17:05 | amalloy | haha, maybe i'll start collaborating with Raynes, since I Don't Blog either :P |
| 17:06 | _seanc_ | I try to look all of this stuff up ClojureDocs, but for instance they don't have # on there |
| 17:06 | amalloy | _seanc_: # isn't limited to this usage - it's not a function, so to speak |
| 17:07 | amalloy | # is a trigger character that the reader treats specially depending on what character is next |
| 17:08 | amalloy | for example: |
| 17:08 | amalloy | &(map class [#(inc %) #{1} #".*"]) |
| 17:08 | sexpbot | ⟹ (net.licenser.sandbox.box5691$eval5848$fn__5849 clojure.lang.PersistentHashSet java.util.regex.Pattern) |
| 17:09 | _seanc_ | Ah, very cool |
| 17:11 | bobo_ | http://clojure.org/reader has more info on it |
| 17:11 | _seanc_ | Just arrived there! |
| 17:11 | _seanc_ | thanks bobo_ |
| 17:11 | bobo_ | :-) |
| 17:13 | amalloy | ah right, #' and #_. i knew i'd forgotten a couple |
| 17:14 | Raynes | amalloy: I really don't. Now that the conj is over, I doubt I'll find things worthy to blog about. I don't make many interesting discoveries on my own. |
| 17:14 | amalloy | Raynes: i know. i don't either. but i found your blog title very amusing |
| 17:15 | ubii | damn, I will be happy when the elections will be over tonight, as my phone has been ringing non-stop for days, with automated campaign messages from various candidates and election pollers calling |
| 17:16 | ubii | that is the disadvantage of working from home |
| 17:18 | technomancy | ubii: disadvantage of having a land-line more like =) |
| 17:18 | ubii | true, the only reason I have it is associated with my DSL |
| 17:19 | pjstadig | i just never answer my phone when the caller-id is an 800 number |
| 17:19 | pjstadig | or "Unavailable" |
| 17:19 | ubii | it is supposed to be a freaking business line, but somehow it is still listed as a residential line, which is why everyone and the brother calls it |
| 17:20 | ubii | yet, I can't get it added to the do not call list, because it is a business line |
| 17:20 | ubii | go figure |
| 17:20 | ubii | damn, catch 22 |
| 17:20 | ubii | sorry, didn't mean to vent, just tired of hearing that damn phone ring |
| 17:21 | amalloy | ubii: get a call-screening device? or google voice? |
| 17:21 | bobo_ | or just mute the phone |
| 17:22 | ubii | I should, but that would make too much sense :) |
| 17:22 | bobo_ | or move to sweden and get a dsl connection without a phone! |
| 17:24 | pjstadig | or vote for people who will change campaign laws |
| 17:24 | Nafai | I'm so glad I don't have a landline |
| 17:29 | LauJensen | Good night to everybody in #landline |
| 17:42 | fliebel | Dang! The Python version of my parser does in seconds what takes my Clojure version minutes… |
| 17:44 | Raynes | Make it faster. |
| 17:44 | fliebel | Raynes: I've been doing that all day :( |
| 17:44 | apgwoz | what does the parser do? |
| 17:44 | apgwoz | err, what does it parse |
| 17:45 | fliebel | apgwoz: Read a bunch of NBT files and plot frequencies. |
| 17:46 | Raynes | Stop. Hammock time. |
| 17:46 | fliebel | ? |
| 17:47 | Raynes | I keep forgetting that not everybody was at the Conj. |
| 17:47 | Raynes | Rich talked about 'hammock' time in his second talk at the Conj. It's become a bit of a meme. |
| 17:48 | danlarkin | http://p.hagelb.org/hammock.jpg |
| 17:48 | fliebel | danlarkin: Oh, well, that explains it all... |
| 17:49 | raek | is it only in my language a hammock is one of these? http://randomfunnypicture.com/wp2/wp-content/uploads/2010/04/meanwhile-in-finland.jpg |
| 17:49 | raek | (modulo the snow and the finnish guy) |
| 17:49 | fliebel | I guess (not= Hammock Hammer)? |
| 17:50 | fliebel | Raynes: But what did you mean to say? |
| 17:51 | Raynes | It was actually completely random and entirely unrelated to what you were saying before it. |
| 17:51 | Raynes | Like a clojurebot message. |
| 17:52 | fliebel | Raynes: Okay :( I was hoping you had some smart insight on how Python can outperform Clojure. |
| 17:53 | apgwoz | Raynes: in all actuality, i took your comment to mean, "fliebel should stop and think about the problem for the night. the solution will come to him" |
| 17:53 | apgwoz | which relates back to rich's talk |
| 17:53 | apgwoz | :) |
| 17:53 | Raynes | apgwoz: Right. We'll go with that. fliebel: ^ That's what I meant to say. |
| 17:53 | apgwoz | haha |
| 17:54 | fliebel | okay, good night all ;) |
| 17:54 | Raynes | Good night. May the Rich be with you. |
| 17:55 | fliebel | Maybe tomorrow someone can explain me how to profile and improve my code. |
| 17:56 | amalloy | raek: i think we'd call that a swing bench or something silly like that, but it's close to a hammock. hammocks are tradionally more like http://www.hammocks.com/hammocks/fabric-hammocks/textalinehammocknavystripe.cfm |
| 17:56 | raek | ah, a "hängmatta" |
| 17:59 | apgwoz | Raynes: woah, you have an affect on people :) |
| 17:59 | Raynes | I do? |
| 17:59 | apgwoz | well, fliebel left. |
| 18:00 | apgwoz | presumably to go think about the problem. |
| 18:03 | Raynes | hiredman: ping |
| 18:05 | Raynes | hiredman: I'm terribly sorry that I am not the perfect coder, but I *do* accept patches and advice, but I don't respond well to flat out insults. |
| 18:06 | Raynes | If you'd like to talk about anything, assuming you get these messages, let me know. I'd love to discuss whatever reason you have for despising me so, and I'd certainly like to resolve any issues. |
| 18:12 | danlarkin | he has you on ignore, just fyi |
| 18:12 | Raynes | I figured. |
| 18:12 | Raynes | Any clue as to why? |
| 18:13 | Raynes | I mean, he's welcome rub me in the dirt all he wants, but surely he isn't going to insult everybody with an association to sexpbot now. That would be unfortunate. :\ |
| 18:14 | Raynes | I suppose this isn't the place to discuss such things though. I'll leave it be. |
| 18:18 | angerman | how do i have to understand (.instanceMember Classname args*)? |
| 18:18 | angerman | ahh so that's a constructor. |
| 18:18 | angerman | or not? ... yikes |
| 18:19 | duncanm | hmm, what's an idiomatic way to remove some entries out of a map based on its val? |
| 18:20 | duncanm | (into {} (remove #(pred? (val %)) my-map)) ? |
| 18:20 | angerman | filte? |
| 18:20 | clojurebot | ,(let [testar (fn [x y] (cond (= (reduce + (filter odd? (range 0 x))) y) (str y " is a")) )] (testar 11 25)) |
| 18:20 | angerman | filter? |
| 18:20 | clojurebot | filter is not map |
| 18:20 | gfrlog | ,(deref (future (+ 7 8))) |
| 18:20 | clojurebot | 15 |
| 18:22 | gfrlog | am disappointed that partition can drop elements off the end of your list |
| 18:22 | gfrlog | ,(partition 3 (range 5)) |
| 18:22 | clojurebot | ((0 1 2)) |
| 18:22 | scgilardi | gfrlog, see partition-all |
| 18:22 | gfrlog | awesome, thanks :) |
| 18:22 | scgilardi | angerman: see http://stackoverflow.com/questions/2753874/how-to-filter-a-persistent-map-in-clojure |
| 18:23 | amalloy | &(.length "10") |
| 18:23 | amalloy | &(.add (ArrayList.) 10) |
| 18:23 | sexpbot | ⟹ 2 |
| 18:23 | sexpbot | java.lang.IllegalArgumentException: Unable to resolve classname: ArrayList |
| 18:23 | amalloy | &(.add (java.util.ArrayList.) 10) |
| 18:23 | sexpbot | ⟹ true |
| 18:23 | amalloy | angerman: ^^ |
| 18:23 | raek | angerman: (.method object arg1 arg2) is java object.method(arg1, arg2); |
| 18:24 | raek | angerman: (.method SomeClass arg1 arg2) is java SomeClass.method(arg1, arg2); |
| 18:25 | angerman | raek: so a class can have nonstatic methods. hmm... |
| 18:25 | scgilardi | whoops, http://stackoverflow.com/questions/2753874/how-to-filter-a-persistent-map-in-clojure was for duncanm |
| 18:25 | raek | "(.instanceMember Classname args*)" does not make much sense, since instances (objects) and classes are different things |
| 18:25 | amalloy | angerman: do you have java experience? |
| 18:25 | angerman | scgilardi: wasn't bad for me to review that either :D |
| 18:26 | raek | angerman: static=class, instance=object |
| 18:26 | angerman | raek: but that's precicely how it's on the clojure.org/java_interop page stands |
| 18:26 | angerman | raek: so my thinking was right. But the confidence was too low. |
| 18:26 | amalloy | angerman: poorly written, then |
| 18:27 | angerman | to me the 1st 3rd and 4th line make sense |
| 18:27 | raek | yes, how unfortunate... |
| 18:27 | angerman | the 2nd one doesn't. |
| 18:27 | amalloy | &Boolean/TRUE |
| 18:27 | amalloy | &(. Boolean TRUE) |
| 18:27 | sexpbot | ⟹ true |
| 18:27 | sexpbot | java.lang.IllegalArgumentException: No matching method found: TRUE |
| 18:28 | amalloy | ugh, i can never remember how to get at static fields using . notation |
| 18:29 | raek | angerman: yes, your thinking was right |
| 18:29 | rata_ | amalloy: is it that possible? I thought / was the way |
| 18:29 | raek | the / way expands to the dot form |
| 18:30 | raek | but the / way is considered more ideomatic |
| 18:30 | amalloy | &(macroexpand 'Boolean/TRUE) |
| 18:30 | sexpbot | ⟹ Boolean/TRUE |
| 18:30 | amalloy | &(macroexpand '(. Boolean TRUE)) |
| 18:30 | sexpbot | ⟹ (dot Boolean "TRUE") |
| 18:31 | amalloy | raek: the interup section angerman is talking about seem to suggest that (. Boolean TRUE) should work; do you know what was wrong with my example? |
| 18:32 | gfrlog | (dot toString true) |
| 18:32 | gfrlog | ,(dot toString true) |
| 18:32 | clojurebot | java.lang.Exception: Unable to resolve symbol: dot in this context |
| 18:32 | raek | I think 'dot' is something in the implementation of clj-sandbox |
| 18:33 | amalloy | gfrlog: also, booleans are primitives, which don't have a toString method. use (String/valueOf true) instead |
| 18:33 | gfrlog | silly primitives! |
| 18:33 | gfrlog | ,null |
| 18:33 | clojurebot | java.lang.Exception: Unable to resolve symbol: null in this context |
| 18:33 | amalloy | gfrlog: yeah |
| 18:34 | amalloy | &nil |
| 18:34 | sexpbot | ⟹ nil |
| 18:34 | gfrlog | is nil null, or is it an object? |
| 18:34 | amalloy | it's null |
| 18:34 | amalloy | &(String/valueOf nil) |
| 18:34 | sexpbot | java.lang.NullPointerException |
| 18:34 | amalloy | really? |
| 18:35 | gfrlog | &(println "java.lang.NullPointerException") |
| 18:35 | sexpbot | ⟹ java.lang.NullPointerException nil |
| 18:35 | gfrlog | dang it lets you tell the differenc |
| 18:35 | raek | amalloy: (. Boolean TRUE) works in a normal repl |
| 18:35 | amalloy | raek: thanks |
| 18:36 | Chousuke | or just Boolean/True |
| 18:36 | Chousuke | er |
| 18:36 | Chousuke | TRUE |
| 18:37 | amalloy | Chousuke: sure, of course that's the "right" way; but i was confused that . didn't work |
| 18:38 | Chousuke | ah, right. |
| 18:39 | wsimpson | why is one less right? |
| 18:40 | gfrlog | because it is left |
| 18:41 | gfrlog | or more left at least |
| 18:41 | wsimpson | touche. |
| 18:41 | Chousuke | wsimpson: The sugared form is prettier :P |
| 18:42 | Chousuke | therefore better. |
| 18:44 | kotarak | if rich says that one form is to be prefered over this other, this is enough "right" for me. |
| 18:45 | amalloy | wsimpson: my suspicion is because String/valueOf makes it look like a first-class function, while (. String valueOf) makes it look like something else |
| 18:46 | wsimpson | Ah. That makes sense. |
| 18:46 | Chousuke | String/valueOf also makes it clear that it's a static field/method |
| 18:47 | wsimpson | Duly noted. |
| 18:48 | wsimpson | Thanks. :) |
| 18:50 | zencobras | Just getting starting with clojure and emacs (tough combo, but fun). Anyone willing to answer a couple of questions? I am trying the labrepl exercises, and when I run 'slime-connect', get the following : "Versions differ: nil (slime) vs 20100404 (swank). Continue? (y or n)". The REPL seems to run OK - but how to I resolve this version issue? |
| 18:52 | arohner | zencobras: add (eval-after-load 'slime '(setq slime-protocol-version 'ignore)) to your .emacs |
| 18:52 | zencobras | Package list shows slime 20100404, slime-repl 20100404 and swank-clojure 1.1.0. |
| 18:52 | zencobras | arohner: thanks! |
| 18:54 | zencobras | arohner: worked like a charm |
| 18:59 | rickmode | I keep wanting to know if an object is a single object, or some sort of sequence, but *not* a map. I'm tending to use coll?, and when I control the type of object, I use seq?, but I really want something like c.c/seqable? that doesn't allow nil. Basically I want (at least) non-nil lists, vectors, and ArraySeq's to pass. Perhaps I'm attacking the problem wrong? |
| 18:59 | arohner | ,(doc sequential?) |
| 18:59 | clojurebot | "([coll]); Returns true if coll implements Sequential" |
| 19:00 | arohner | rickmode: does that do it for you? |
| 19:00 | cemerick | rickmode: there's a seqable? in clojure.contrib.core, but it's a fundamentally flawed concept |
| 19:00 | rickmode | cemerick: how so? |
| 19:01 | raek | rickmode: what will you use this function for? |
| 19:01 | raek | a macro? |
| 19:01 | rickmode | arohner: perhaps sequential? is what I want |
| 19:01 | cemerick | rickmode: Because seq is polymorphic beyond what can be representable by the JVM's type system. Protocols will fix this, but there's not yet a Collection protocol or somesuch that would provide a proper seqable? fn that collection implementations could implement. |
| 19:02 | cemerick | s/can be/is |
| 19:03 | rickmode | raek: I'm thinking of things similar to how "The Little Schemer" attacks atoms and lists. Basically I want various functions to all one or more items, and I'd like the caller to pick any sort of sequence. E.g. (foo (list :a :b)), (foo [:a :b]) |
| 19:03 | cemerick | rickmode: until then, we're left with things like clojure.contrib.core/sequable?, which is just a bunch of instance? checks essentially. |
| 19:03 | rickmode | raek: seems wrong somehow to force a particular sort of sequence |
| 19:04 | raek | maybe you could do a cond with the map? test before the coll? test |
| 19:04 | rickmode | raek: I don't usually allow either a map or coll, but ya - that works in those cases. Perhaps sequential? is the right forward-compatible beast? |
| 19:06 | rickmode | cemerick: does sequential? cover all cases where an object can behave list-like? (that is, supports first and rest/next)? |
| 19:06 | cemerick | rickmode: no, sequential? tests for (instance? Sequential x). That only includes seqs, vectors, and lists. |
| 19:07 | rickmode | cemerick: what other listy things are there? |
| 19:07 | cemerick | which leaves out strings, maps, and java.util.Lists, to name some others that work with first/rest/next |
| 19:07 | tonyl | &(supers Sequential) |
| 19:07 | sexpbot | java.lang.Exception: Unable to resolve symbol: Sequential in this context |
| 19:08 | cemerick | &(supers clojure.lang.Sequential) |
| 19:08 | sexpbot | java.lang.NullPointerException |
| 19:08 | cemerick | ,(supers clojure.lang.Sequential) |
| 19:08 | clojurebot | nil |
| 19:08 | cemerick | ach, not supers |
| 19:08 | clojurebot | http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png |
| 19:08 | cemerick | tonyl: you want "descendents", except it doesn't exist ;-) |
| 19:08 | rickmode | cemerick: so it's OK for clojure-only code, but doesn't generalize. Perhaps it's ok for my cases though. - ya I look at Seqeuential... it's a type-marker. |
| 19:09 | rickmode | (empty interface) |
| 19:09 | tonyl | yeah, i was looking in the docs :P |
| 19:09 | clojurebot | Huh? |
| 19:09 | raek | I know I have had the same thought as rickmode about finding something similar to listp and atomp |
| 19:09 | raek | but for some reason, it has not been a problem for me |
| 19:09 | rickmode | raek: ya that's why i was wondering if am attacking the problem wrong |
| 19:10 | raek | maybe I tend to treat one data structure specially in the fn, and leave everything else as-is |
| 19:10 | raek | like in http://gist.github.com/633049 |
| 19:11 | raek | in common lisp, it's mostly black and white. either something is a list or an atom |
| 19:11 | raek | in Clojure, there's lots of data structures |
| 19:11 | rickmode | raek: your gist makes sense... but what if you want to allow single objects too.. then you hit my scenario. |
| 19:11 | raek | one of the aspects that make it non-lispy |
| 19:12 | raek | ,(coll? "foo") |
| 19:12 | clojurebot | false |
| 19:12 | raek | yeah... |
| 19:12 | rickmode | raek: indeed. clojure (correctly) adds sets and maps to the list. It has not (yet) unified all possible sequences though |
| 19:13 | raek | I'm afraid I don't have any good answer |
| 19:13 | rickmode | the list meaning, the list of fundamental data structures |
| 19:13 | hiredman | coll? checks to see if it's an ipcollection |
| 19:14 | hiredman | which a string certainly isn't |
| 19:14 | hiredman | neither are many Collections |
| 19:14 | raek | ah, |
| 19:14 | raek | ,(coll? (java.util.ArrayList.)) |
| 19:14 | clojurebot | false |
| 19:14 | rickmode | I *think* I'm ok with sequential? for these clojure functions (i'm not worried about java interop). I'm hoping callers can do (foo :a) (foo (list :a :b)) (foo [:a :b]) and (fn [& rest] (foo rest)) |
| 19:14 | raek | sounds resonable to me |
| 19:15 | rickmode | but *not* (foo {:a 1, :b 2}) |
| 19:16 | rickmode | makes me think this "one or many" idiom is somehow flawed |
| 19:19 | amalloy | rickmode: why not allow maps? if the caller wants to treat their map as a list of pairs, who are you to stop them? |
| 19:19 | amalloy | if you somehow managed to exclude maps, they could just (foo (seq {:a 1 :b 2})) |
| 19:20 | rickmode | amalloy: in this particular case, the caller is passing in one or more keywords... a map wouldn't make sense, but just about anything else would. (The keywords are parameter names for form validation like, :first-name, :last-name). |
| 19:21 | raek | rickmode: you wouldn't be using ring.middleware.params? |
| 19:21 | rickmode | amalloy: I think I'm still getting over my OO/strong-typing hangover. coll? will do the trick, i think. a map will cause a barf on first usage, so that's good enough |
| 19:22 | amalloy | rickmode: it will barf on (foo [[:a 1] [:b 2]]) too, so coll? isn't really helping |
| 19:22 | rickmode | raek: right. (though I don't feel like using ring.middleware.keyword-params - I'm sticking with (name :first-name) since I have only about 3 usages of name. |
| 19:22 | raek | rickmode: I think it is simpler to let the user pass the single thing in a collection of size 1, unless there is any compelling reason |
| 19:23 | amalloy | you could do like: (and (coll? x) (not-any? coll? x)) |
| 19:23 | raek | I don't like the way wrap-params handles multiple values of the same key |
| 19:24 | raek | I think it should split into two variants: one that always store a single value per key (last one wins) and one that has a vector for each key |
| 19:24 | Raynes | raek: Made any interesting progress on your message parser lately? |
| 19:24 | rickmode | raek: oh... i'm not doing that. I'm rolling (yet another) form validation system. I'm allowing something like (validator [:password :password2] #(= %1 %2) "passwords don't match") |
| 19:25 | hiredman | surely you mean (validator [:password :password2] =) |
| 19:25 | raek | looks very much like something I started to work on once... :) |
| 19:25 | rickmode | raek: as well as (validator :first-name #(not (str/blank? %) "first name required") |
| 19:26 | raek | Raynes: well, I think the vocabulary is starting to crystallize |
| 19:26 | raek | rickmode: http://gist.github.com/586836 |
| 19:26 | amalloy | rickmode: oh. so more like (or (not (coll? x)) (not-any? coll? x)) |
| 19:26 | Raynes | raek: Irclj is attention starved. If it doesn't get new code soon, I fear it'll begin gnawing on sexpbot an any other bot it can get it's parentheses around. |
| 19:27 | Raynes | and* |
| 19:27 | raek | rickmode: also http://github.com/Kaali/pour |
| 19:28 | raek | which that was a remix of |
| 19:29 | raek | Raynes: you will love the abstractions that are in my mind currently |
| 19:30 | Raynes | raek: :D |
| 19:30 | rickmode | raek: heh.. ya it's kinda like that... though I'm reading up on monads and it seems like validation... and perhaps the entire response cycle, can be recast / simplified with compossable m-state.. er .. thingies |
| 19:31 | raek | rickmode: I know very little about monads, but I have a hunch that they might be a good fit |
| 19:38 | rickmode | raek: is your weby stuff in a github project? |
| 19:39 | raek | not yet |
| 19:39 | raek | this will eventually be a lib, but I haven't had much time to work on it, unfortunately |
| 19:40 | Raynes | raek: By the way. We have to change the name of Irclj to (apply str (distinct (str "irc" "clj"))). Only difficult thing will be the namespaces. :P |
| 19:44 | raek | I should get some sleep |
| 19:44 | raek | but I don't wanna |
| 19:44 | raek | Clojure is way too fun |
| 19:44 | raek | gn |
| 20:38 | ymasory | is there a function that makes a seq of n elements by applying the provided function n times and collecting its results? |
| 20:38 | ymasory | i can do this with a comprehension or map but i would need a range too |
| 20:39 | tonyl | ,(range 10) |
| 20:39 | clojurebot | (0 1 2 3 4 5 6 7 8 9) |
| 20:40 | ymasory | tonyl: hm? |
| 20:42 | amalloy | &(doc repeatedly) |
| 20:42 | sexpbot | ⟹ "([f] [n f]); Takes a function of no args, presumably with side effects, and returns an infinite (or length n if supplied) lazy sequence of calls to it" |
| 20:42 | amalloy | ymasory: ^^ |
| 20:42 | amalloy | &(repeatedly 10 rand) |
| 20:42 | sexpbot | ⟹ (0.23348923774335106 0.8732098324061308 0.582779226332408 0.9926034362933805 0.9522604963670783 0.5401583818751448 0.3418314042183209 0.15130219536490885 0.5458508576119281 0.241182907854135) |
| 20:43 | amalloy | that what you were looking for? |
| 20:43 | ymasory | amalloy: thank you yes |
| 21:44 | fbru02 | hey guys ... so Leiningen uses ant to run right ? |
| 21:46 | amalloy | fbru02: maven |
| 21:47 | fbru02 | amalloy: did this change recenly ? from the doc For the actual task execution cycles it uses Ant under the covers via Lancet. ???? |
| 21:49 | fbru02 | brb |
| 21:49 | amalloy | okay. i wouldn't be astonished to find out that that's true, i guess, but i thought it used maven for everything. if technomancy were around i'd say ask him |
| 21:50 | fbru02 | amalloy: thanks ! |
| 21:51 | tonyl | I thought it uses maven for dependencies and for alternative building with a pom file instead of project.clj |
| 21:51 | tonyl | but i've been out of the leiningen for a while |
| 21:52 | amalloy | tonyl: it looks like that's true. lein and cake both use ant for actual compilation |
| 22:24 | gfrlog | ,(apply * (range 500)) |
| 22:24 | clojurebot | 0 |
| 22:25 | amalloy | &(apply * (range 1 500)) |
| 22:25 | tonyl | &(apply * (range 1 500)) |
| 22:25 | sexpbot | ⟹ 244027365198222013740247757084609385250714868560638568438482717677169074630776399521099289500440656372602723295429640716832675744415635440096157041031865857095581514387866120754592171817254085834909576484982545268861134034654153892212560462090528843775757893150955429972698873556207528854806765473079... http://gist.github.com/660719 |
| 22:25 | sexpbot | ⟹ 244027365198222013740247757084609385250714868560638568438482717677169074630776399521099289500440656372602723295429640716832675744415635440096157041031865857095581514387866120754592171817254085834909576484982545268861134034654153892212560462090528843775757893150955429972698873556207528854806765473079... http://gist.github.com/660718 |
| 22:25 | tonyl | lol |
| 22:25 | amalloy | lol |
| 22:25 | tonyl | that was weird |
| 22:25 | gfrlog | that was weird |
| 22:26 | gfrlog | I was remarking to myself how you both came up with the number 500.... |
| 22:26 | amalloy | notice the gists came out of order? |
| 22:27 | tonyl | yeah |
| 22:27 | tonyl | lag |
| 22:27 | amalloy | yeah, presumably latency on github's end |
| 22:29 | gfrlog | presumably the designers of github forgot to include the library that determines what order numbers come in |
| 22:29 | amalloy | #include <reality.h>? |
| 22:30 | gfrlog | import org.apache.integers.comparison.*; |
| 22:30 | tonyl | i think it's built in ruby |
| 22:31 | gfrlog | ,(ruby-eval "660718.is_less_than?(660719)") |
| 22:31 | clojurebot | java.lang.Exception: Unable to resolve symbol: ruby-eval in this context |
| 22:31 | gfrlog | unacceptable |
| 22:31 | ymasory | where does autonomous code go in clojure considering agents don't have a loop? in a java thread? |
| 22:32 | amalloy | ymasory: autonomous? do you mean asynchronous, maybe? |
| 22:33 | ymasory | amalloy: autonomous. as in autonomous threads/actors |
| 22:33 | ymasory | agents you pass functions to from the current thread of control. they don't have an independent thread of control, from what i understand |
| 22:33 | ymasory | or my bad, yes they do, to run the function |
| 22:34 | ymasory | i guess i could just pass the agent the looping function (i.e. the "run" method of a java thread) |
| 22:34 | amalloy | ymasory: every clojure function is a java object that implements Runnable. if you want, you can pass them to a thread |
| 22:34 | amalloy | &(supers (class (fn []))) |
| 22:34 | sexpbot | ⟹ #{java.util.Comparator java.io.Serializable clojure.lang.IObj clojure.lang.IMeta java.util.concurrent.Callable java.lang.Object clojure.lang.AFn clojure.lang.AFunction java.lang.Runnable clojure.lang.Fn clojure.lang.IFn} |
| 22:35 | ymasory | amalloy: pass them to a thread or to an agent? |
| 22:35 | amalloy | either will take them; what you should do depends on your goal |
| 22:36 | ymasory | what is the guarantee i get from an agent over the same code running in a thread? |
| 22:38 | amalloy | agents are basically an object that queues up actions, and passes them to a thread one at a time |
| 22:38 | amalloy | if you create ten threads and start them all, they run in parallel; if you create an agent and send it ten functions, they run in series |
| 22:40 | ymasory | so the main benefit of agents is that they manage the thread pool for me? |
| 22:40 | hiredman | agents provide an identity for a series of values over time |
| 22:40 | amalloy | they also have a value |
| 22:40 | hiredman | just like refs and atoms |
| 22:41 | ymasory | right, i guess this is mind-shock for me trying to integrate threads and value-holders into one useful entity |
| 22:41 | amalloy | right. if you just want threads, use clojure futures, and/or java threadpools |
| 22:42 | tonyl | is there a clojure construct for threadpools? |
| 22:42 | cemerick | tonyl: threadpools are a fundamentally hosty concept |
| 22:42 | amalloy | but to perform a series of actions that are conceptually related and need to share state, agents are perfect |
| 22:42 | tonyl | even for the jvm? |
| 22:42 | cemerick | of course |
| 22:43 | cemerick | see java.util.concurrent |
| 22:43 | hiredman | well the jvm is the host |
| 22:43 | cemerick | .NET/CLR has something equivalent |
| 22:44 | tonyl | ok |
| 22:44 | tonyl | i guess i need to learn more about the parallel concepts than just the summaries |
| 22:44 | tonyl | good, thanks |
| 22:44 | cemerick | and then Clojure hosted on some platform that has no threadpool abstraction (probably javascript, for example) just won't be able to support e.g. futures |
| 22:45 | tonyl | got it |
| 22:46 | ymasory | are agents supposed to fall off like java threads, or is it safe to terminate them directly? |
| 22:46 | amalloy | ymasory: fall off? |
| 22:47 | cemerick | ymasory: agents are lightweight reference types whose values change asynchronously *via* threads |
| 22:47 | cemerick | so talking about "terminating" them doesn't really make sense |
| 22:47 | ymasory | cemerick: well in my case i'm passing them a looping function, like you would the run function in a java thread |
| 22:48 | ymasory | i guess i'm not supposed to do that |
| 22:48 | cemerick | ymasory: you mean a fn that never returns? |
| 22:48 | amalloy | ymasory: yeah, that's covered in Agent Abuse 101 :) |
| 22:49 | ymasory | yeah it's a total abuse of an actor too (coming from a scala background here) |
| 22:49 | amalloy | it sounds like you want a direct analog to java threads |
| 22:49 | amalloy | in clojure that's a future, not an agent |
| 22:49 | cemerick | ymasory: just a future will do fine |
| 22:50 | amalloy | ymasory: the idea with sending agents functions is that they take the function's return value and store it as their new state |
| 22:51 | amalloy | if the function never returns, that is a huge warning signal that you shouldn't use agents; for one thing, all agents share a limited threadpool, and you're monopolizing one of their threads |
| 22:51 | ymasory | oh i see. instead of an actor sending back a reply |
| 22:51 | amalloy | ymasory: maybe. i don't have any real background in scala or erlang |
| 22:53 | hiredman | you can use send or send-off inside an agent to loop |
| 22:54 | ymasory | hiredman: send a message to yourself? |
| 22:54 | hiredman | it's not a message |
| 22:54 | hiredman | it's a function |
| 22:54 | hiredman | but yes |
| 22:54 | ymasory | ah |
| 22:55 | cemerick | ymasory: *agent* is bound to the current agent |
| 22:55 | ymasory | very nice |
| 22:56 | ymasory | so i think the last part of this puzzle is figuring out how i can schedule a function to be sent to an agent in the future |
| 22:56 | ymasory | that what a future is? |
| 22:57 | hiredman | send or send-off is scheduling an action to be run in the future |
| 22:57 | cemerick | A future simply runs some code asynchronously, retaining the result, and blocking on derefs until that value is available. |
| 22:58 | ymasory | hiredman: i meant how can i delay the send call |
| 22:58 | hiredman | why? |
| 22:58 | clojurebot | why not? |
| 22:58 | hiredman | clojurebot: buzz off |
| 22:58 | clojurebot | Titim gan éirí ort. |
| 22:58 | ymasory | hiredman: because it's a modeling project, the model only allows a function every so often |
| 22:59 | cemerick | ,(print "I can't do that, Dave.") |
| 22:59 | clojurebot | I can't do that, Dave. |
| 22:59 | amalloy | ymasory: (future (Thread/sleep 5000) (inc 1)) |
| 22:59 | hiredman | ymasory: use a scheduledthreadpool |
| 23:00 | cemerick | we should be able to get parameterization of threadpools into send, send-off, and future for the 1.3.0 cycle |
| 23:00 | tonyl | what is the meta :once true for? |
| 23:00 | ymasory | &(future (Thread/sleep 5000) (println "hi!")) |
| 23:00 | sexpbot | ⟹ #<core$future_call$reify__5500@f84033: :pending> |
| 23:01 | hiredman | cemerick: has rich indicated interest in that? |
| 23:02 | amalloy | &@(future (Thread/sleep 5000) (inc 1)) |
| 23:02 | sexpbot | ⟹ 2 |
| 23:03 | cemerick | hiredman: yes, indicated that is was a semi-safe bet for "release.next" just prior to the 1.2.0 release IIRC |
| 23:03 | cemerick | s/is/it |
| 23:04 | tonyl | is the future object just a reified object done on the fly? |
| 23:05 | cemerick | future is a macro that creates an anonymous fn that is run on a dedicated threadpool |
| 23:06 | tonyl | i meant on future-call |
| 23:06 | amalloy | &(macroexpand '(future (Thread/sleep 5000) (inc 1))) |
| 23:06 | sexpbot | ⟹ (clojure.core/future-call (fn* [] (dot Thread "sleep" 5000) (inc 1))) |
| 23:07 | cemerick | tonyl: future-call does that dispatch of any fn, returning a java.util.concurrent.Future that also happens to implement IDeref |
| 23:08 | hiredman | I had a patch once that, if I recall, let you pass in something on agent creation (it was something out of Agent.java that you could proxy if you wanted to) with the idea of being able to create agents that would have their actions run on the EDT |
| 23:08 | hiredman | that did not go over well |
| 23:09 | hiredman | maybe I should have just offered the patch without mentioning my envisioned use |
| 23:09 | cemerick | yeah; IIRC, Rich said he'd be looking to parameterize the send itself |
| 23:09 | hiredman | oh |
| 23:09 | hiredman | interesting |
| 23:10 | cemerick | My general impression is that there are deeper rearchitecting that are on the table though…which is why I never offered up a patch. ;-) |
| 23:11 | hiredman | I must say I never use agents though |
| 23:20 | ymasory | hiredman: what do you use? |
| 23:25 | amalloy | ymasory: whatever tool is suitable for the job, i imagine |
| 23:26 | amalloy | agents sound deceptively useful, because they incorporate both mutability and concurrency, which are tricky problems in general |
| 23:26 | amalloy | but most of the time, you want something else |
| 23:26 | hiredman | lots of futures and promises |
| 23:27 | ymasory | i guess i was perfectly happy with actors |
| 23:34 | cemerick | There's no reason to generalize about which construct is better than another; they all have their uses for different types of problems. |
| 23:45 | amalloy | cemerick, ymasory is right: i use a fork to eat everything because it's just the best eating utensil. sometimes soup is a little tricky, and i wish campbells would fix that bug, but otherwise i'm very happy with my fork |
| 23:46 | cemerick | heh |
| 23:46 | ymasory | all i said was that i was happy. but i guess happiness is an offensive idea in a developer's life :) |
| 23:47 | cemerick | ymasory: don't worry, I'm sure amalloy was sending nothing but <3 ;-) |
| 23:47 | ymasory | yeah he's the man |
| 23:49 | Raynes | amalloy has magic in him. Magic, I say. |
| 23:49 | amalloy | Raynes: shhhhh, you'll let all the magic smoke out |