#clojure logs

2009-11-24

00:00KirinDave1I'm trying to, as a way to get a handle on compojure
00:00KirinDave1write a little program to track our foosball scores.
00:01KirinDave1I'm writing things like make-player, make-game, add-player, add-game.
00:02KirinDave1https://gist.github.com/3d800d9dfc8c437e548d
00:02KirinDave1Is there a more elegant way to do this stuff?
00:02KirinDave1Am I doing something that is already being done for me?
00:04carkwell, using struct directly does the job, or better yet struct-map
00:04carkthough in the long run it's good to have functions abstracting this
00:04KirinDave1It seems like that'd be tedious is client code
00:04KirinDave1Yeah
00:04technomancystructs are generally used as perf operations when you've profiled to find out that just plain maps aren't fast enough.
00:04technomancys/operations/optimizations/
00:05KirinDave1technomancy: I'm mostly using them as a way of documenting the keys I expect.
00:05carkthe one thing i don't like in your code : instead of having that many refs, you need a single one
00:05carkmake a single *database* ref
00:05carkthis will also be better for you to learn clojure
00:05KirinDave1cark: I've thought about that, but wouldn't I also want the internal refs?
00:05KirinDave1For the player history?
00:06technomancyKirinDave1: that works, but it generally ends up being more verbose.
00:06KirinDave1There seems to be no reason to lock the entire DB if I want to update a single player.
00:06carknope
00:06_atocark: if you're going to have a single database ref, it may as well be an atom
00:06KirinDave1Right.
00:06technomancyKirinDave1: also: if you're not doing anything in a dosync except commuting, consider atoms
00:06carkKirinDave : you will mostly be reading, writing only happens once a game is played
00:06technomancysince you're not really taking advantage of the ACI properties of transactions
00:06KirinDave1technomancy: I will be doing alters for other stuff.
00:06technomancyKirinDave1: I mean if you're only doing a single write per transaction
00:07_atopresumably there will cases later on where you want to atomically change team's wins as well the games or history together
00:07KirinDave1Yeah
00:07cark_ato : right, but what if you add more stuff later and need to coordinate ?
00:07KirinDave1The stuff that involves adding a game and then updating the history, and the ladder, will involve multiple changes in a single transation
00:08technomancythat's true; I guess you are planning ahead for stuff that isn't there yet
00:08KirinDave1Yes
00:08arohnerwhy do you guys advocate a single ref? I've always thought of using a ref for each thing with identity that can change
00:08carkthat's a trade-off, this database is small, it doesn't need such granualirty
00:08arohnerand IMO smaller refs are easier to manipulate than reaching N levels into a tree structure to alter one node
00:08carkgranularity
00:09carknot at all, using clojure it's easy to reach deep
00:09arohnerit's still more work than not reaching deep
00:10carkallright, what if you suddenly need to keep track of some other games, say fifa for instance
00:10KirinDave1Well I'd probably abstract a top level databse.
00:10KirinDave1But I wouldn't make that a ref, i don't think.
00:10KirinDave1That structure would be immutable, it'd have keys
00:10carkso you need to go back in your code and change it all
00:10KirinDave1Its key's values would be mutable.
00:10arohnernot at all
00:11KirinDave1I suppose. I was thinking maybe a database binding.
00:11arohnertake this current code, add another ref on top of it, for the "league"
00:11arohnerthe league ref points at a set of games
00:12KirinDave1Well I'd have to refactor those direct refs. :)
00:12KirinDave1players, teams, games, etc
00:12technomancyKirinDave1: the only other thing I'd note is that when you have multiple arg lists, it's more common to have the fewer-arg versions call the more-arg versions, filling in the missing args.
00:12_atocark: there's no point in Clojure's STM if you're just using a single top-level database ref. You're not taking advantage of concurrency. While it's true this is a simple app so it doesn't need concurrency I think KirinDave1 is using it as an excercise to learn about Clojure's features
00:12technomancyminor point, but it ends up being a little more dry
00:13KirinDave1technomancy: Good point.
00:13carkato : in a real life program you'll have more than this single database
00:13KirinDave1cark: wouldn't I just make the database anargument in the functions?
00:13carkeach time you use a ref, you loose the nice characteristics of purely functional programing
00:13KirinDave1instead of a top ref?
00:14carkKirinDave : yes, that's even better
00:14carkbut at some point you need a ref or an atom to hold the identity of your state
00:14KirinDave1cark: Right, well I may go back to that.
00:14KirinDave1That should be in client code tho.
00:14KirinDave1Not this lib.
00:14KirinDave1I should ahve a make-league function that drops a league out that you could keep.
00:15carkwell you must stop at some point
00:15KirinDave1I will in my compojure client code
00:15carkwhat about adding planet mars leagues ?
00:15KirinDave1probably an atom
00:15KirinDave1I was considering using a binding-able variable instead of a calling argument
00:15KirinDave1Is that a shitty idea?
00:15KirinDave1I see people use bindable vars all the time in contrib, but I hear a lot of grumbling about it here.
00:16carkwell no it's not a bad idea, arguments are more readily readable tho
00:16hiredman*grumble* *grumble*
00:16carkthis var binding stuff is good when there are many arguments that almost never change
00:16technomancyKirinDave1: you run into trouble when you create a lazy seq within binding that gets consumed outside the binding form
00:17carklike the *print-blahblah* vars for instance
00:17_atothe other problem with bindables is if you want to deal with two leagues in the same function you end up having to (with-league l1 ...) (with-legaue l2 ...) around every call anyway
00:17carkahyes and one last recommendation : those toplevel vars should be named like this : *player* *teams*
00:18carkthat's a convention people use
00:21KirinDave1cark: I though that was a convention for things that would be bound, but sure.
00:24carkyou'll run into another problem
00:25carkyou have players in teams and in players
00:25KirinDave1?
00:25KirinDave1What's the problem with that?
00:25KirinDave1The players are a set and I intend to only use players from the players set
00:25carkso if you change a player, you need to update both its team and the players database
00:26carkso that's where you might want to make refs of those players
00:26KirinDave1Does identity propagate through refs?
00:26KirinDave1Seems like sets would get very irritated at that. :)
00:27_ato,#{(ref 1) (ref 1)}
00:27clojurebot#{#<Ref@d41010: 1>}
00:27KirinDave1Wow, that's neat.
00:27_atothat's... weird
00:27KirinDave1I mean, the thing is.
00:27_atoI wonder what happens then if you change one of them
00:27KirinDave1Yeah
00:27carkwell when you populate a player struct, you get a _value_
00:27KirinDave1that's just what I was wondering
00:27carkwhen you put this value in a ref, you get identity
00:28carkato : yes that's very weird =/
00:28carkand i wouldn't rely on that
00:29arohnerthat seems like a bug
00:29arohner,(ref 1)
00:29clojurebot#<Ref@e4bf0e: 1>
00:29arohner,(ref 1)
00:29clojurebot#<Ref@b2d6bd: 1>
00:30_ato,(let [s #{(ref 1) (ref 2)}] (dosync (ref-set (first s) 2)) s)
00:30clojurebot#{#<Ref@86c645: 2> #<Ref@e9ff86: 1>}
00:30_ato,(let [s #{(ref 1) (ref 2)}] (dosync (ref-set (first s) 1)) s)
00:30clojurebot#{#<Ref@596d65: 1> #<Ref@11d1bb6: 2>}
00:30carkKirinDave : or you could make your player database a map, and store the key in other places
00:31KirinDave1So players mapped by name, you suggest?
00:31_ato,(let [s #{(ref 1) (ref 2)}] (dosync (doseq [r s] (ref-set r 1))) s)
00:31clojurebot#{#<Ref@ed4107: 1> #<Ref@39e50f: 1>}
00:31carkif you're sure these are unique =)
00:31KirinDave1I suppose.
00:31_ato,(set (let [s #{(ref 1) (ref 2)}] (dosync (doseq [r s] (ref-set r 1))) s))
00:31clojurebot#{#<Ref@e32bd0: 1> #<Ref@516c52: 1>}
00:31KirinDave1The only part of a player that can change is its history, tho
00:31KirinDave1And that's what's ref'd and shared throughout all the databases.
00:31_ato,[(ref 1) (ref 1)]
00:31clojurebot[#<Ref@1bda30a: 1> #<Ref@11b0d65: 1>]
00:31KirinDave1So long as I make sure to populate teams with entries from *players*
00:31_ato:\
00:32arohner_ato: that's weird
00:32KirinDave1Yeah I'm not sure that's so awesome
00:33carkwell try it, you'll see a bug where you have the old value still in team once you updated the player in players
00:33_ato,(apply hash-set (let [s #{(ref 1) (ref 2)}] (dosync (doseq [r s] (ref-set r 1))) s))
00:33clojurebot#{#<Ref@759e62: 1> #<Ref@1f16253: 1>}
00:33_ato,#{(ref 1) (ref 1)}
00:33clojurebot#{#<Ref@1436fa7: 1>}
00:33_ato,(hash-set (ref 1) (ref 1))
00:33clojurebot#{#<Ref@5b4583: 1> #<Ref@30ac0d: 1>}
00:33_atoeh...
00:33_ato,(array-set (ref 1) (ref 1))
00:33clojurebotjava.lang.Exception: Unable to resolve symbol: array-set in this context
00:34arohnerI would model this so every player is a ref, every game is a ref
00:34arohnereverything that wants to talk about players or games will point at that ref
00:34arohnerso there's no possibility of having two copies of a player, and things won't get inconsistent
00:35KirinDave1Um, but players are immutable except for thier history.
00:35KirinDave1So what could change?
00:35carkright tradeoffs again, it makes sense here
00:35arohnerso?
00:35arohnertheir histories change
00:36carkif their history change, their value change, so that's a completely new player
00:36arohnerthat's a new player *struct*
00:36arohnerconceptually, the ref is the player
00:37carkthat's a new player value =) conceptually his identity is the ref =)
00:37KirinDave1Well, conceptually his history is the ref
00:37KirinDave1I mean I could do away with history alltogether and just calculate it on the fly with games
00:38KirinDave1I was just going to keep it caches
00:38KirinDave1err, cached.
00:39KirinDave1But I'll consider changing it.
00:40carkanyways you have 2 options to give your players an identity, either you give them a unique key or you put them in a ref, and i'm off to bed !
00:40carkgnight
01:04radsis there a concise way to turn something like [["a" 1] ["b" 2] ["c" 2] ["a" 2] ["b" 3]] into {"a" 3, "b" 5, "c" 2}? (find the sums)
01:06_ato,(apply merge-with + (map hash-map [["a" 1] ["b" 2] ["c" 2] ["a" 2] ["b" 3]]))
01:06clojurebotjava.lang.RuntimeException: java.lang.IllegalArgumentException: No value supplied for key: ["a" 1]
01:06_ato,(apply merge-with + (map #(apply hash-map %) [["a" 1] ["b" 2] ["c" 2] ["a" 2] ["b" 3]]))
01:06clojurebot{"a" 3, "b" 5, "c" 2}
01:07_atorads: ^
01:07rads_ato: thank you. the flexibility of clojure's sequence library never ceases to impress me
01:36radshow would I double each value in a hash map?
01:52tomoj,(into {} (for [[k v] {:foo 3 :bar 6 :baz 9}] [k (* 2 v)]))
01:52clojurebot{:foo 6, :bar 12, :baz 18}
01:52tomojrads: ^
02:04radstomoj: thanks
02:08_ato,(use 'clojure.contrib.generic.functor)
02:08clojurebotnil
02:08_ato,(fmap #(* % 2) {:foo 3 :bar 6 :baz 9})
02:08clojurebot{:foo 6, :bar 12, :baz 18}
02:09_ato,(fmap #(* % 2) [3 6 9])
02:09clojurebot[6 12 18]
02:09tomojcool
02:10tomojis that any faster? or just prettier?
02:10_atojust prettier, it's implemented in terms of (into {} ...) IIRC
02:13_ato~def fmap
02:14_atoheh, yeah: (into (empty m) (for [[k v] m] [k (f v)])))
02:14_ato~def into
02:15_atodoing a reduce might be slightly faster as it avoids the lazyseq but probably not enough to be worth the trouble
02:18tomojI wonder if a transient map could do it faster?
02:18_ato"into" uses a transient map
02:18tomojwell, I meant take the original map, make it transient, and then replace the keys
02:19tomojer, values
02:19_atooh right
02:19tomojto avoid building up the structure again, dunno if that'd help or is possible
02:20_atohmm, not sure. it'd have to copy all keys and values anyway, so perhaps not, but there might some weird cache locality benefits or something
02:28tomojhmm
02:28tomojI think it might actually be a bit faster
02:28tomojbut not much
02:28tomojcomparing (defn trans-map [f m] (let [t (transient m)] (doseq [k (keys m)] (assoc! t k (f (get t k)))) (persistent! t)))
02:28tomojand (defn trans-map2 [f m] (into {} (for [[k v] m] [k (f v)])))
02:29tomojI wish the 'time' macro returned the time instead of printing it :/
02:30_atoyeah, you should be seeing at least a slight advantage from the lack of the lazyseq that 'for' returns
02:30_atooh hang on..
02:30_atoerr... you can't use a transient that
02:31_atoway
02:31_atoit'll break
02:31_atoat least it's not guaranteed to work anyway
02:31_atoI wouldn't rely on it
02:34tomojhuh?
02:35tomojhow would it break?
02:35hiredmantomoj: you read http://clojure.org/transients ?
02:36hiredman"Don't bash in place"
02:36hiredmanthe flow is just like with the persistent versions, you have to pass around the result of operations
02:36tomojoh yes
02:36tomojso I should be reducing I guess
02:37_atoyeah
02:39_atosomething like (persistent (reduce (fn [m [k v]] (assoc! m k (f v))) (transient! m) m))
02:39_atothough I suspect (persistent (reduce (fn [m [k v]] (assoc! m k (f v))) (transient! {}) m)) would be just as fast
02:39tomojwell that's what my initial wonder was, really
02:39tomojI always feel bad starting from {} and rebuilding
02:40tomojthe hash structure stays the same since the keys aren't changing, so it seems like it would be faster to just swap out all the values
02:45_atohmm, looks like you might be right, but the effect is only worth 5 or 10% at least on my PC
02:45tomojnot worth the bother then
02:49tomojyeah I just got a 5% speedup too
04:47kzarIs there a way to pass extra parameters to the JPanel repaint function? I want to pass the information needed to render the game's state.
04:50scottj_I haven't used Swing much but from the java docs it doesn't look like that's what repaint is for
04:50liwpkzar: huh? repain() sends an event to the Swing event handler asking for a repaint of that component. It has nothing to do with your game state
04:52kzarliwp: Yea, my game's running from a loop and when I call repaint it ends up calling the function I wrote to render the game. I wanted to pass details of the state through repaint, so it reached my render function. That way the code would be more functional then having a variable set outside the game loop
04:54kzarI'm not sure that's possible or if there's an alternative way to acheive a similar result.
04:54liwpkzar: your functions has to be a method of a class for it to work with swing, so I think your only option is to embed the game state in your instance of that class
04:55tomojisn't repaint called when the user moves the window around?
04:55tomojor resizes, etc?
04:55liwpkzar: fundamentally swing is an OO framework, so I think you'll just run into a lot of trouble if you try to shoehorn it into FP thinking
04:55liwptomoj: yes, but you can also call it yourself to force a redraw
04:55tomojwhatever's calling repaint when the window is resized shouldn't have to know the gamestate, though
04:55liwpagreed
04:56kzaroh that's a good point
04:56tomojwouldn't you just have a proxy that uses paint to access the gamestate and draw it?
04:56tomojand then if someone wants to repaint it they just ask? I still don't really understand swing very well :/
04:57liwpkzar: what you can do it write another function that is purely functional and returns the new game state based on the old game state, and call this function from your implementation of the function that swing calls
04:57liwpthat way you do have a nice purely functional game state updater
04:57kzarliwp: But where does it get the old game state from?
04:58liwpkzar: you must implement a class that inherits one of the swing base classes, right?
04:58liwp(it's been a while since I've done any swing)
04:58liwpso your game state would be a field of that class
04:58tomojseems strange to me to update the gamestate based on what swing wants
04:59kzartomoj: Yea that's not what I want
04:59tomojI want my gamestate in a ref/atom and the gui component will just deref this and paint whatever's there
05:00liwpsure, so your function would be something like (defn my-fun [#^Graphics g] (let [s @state] <paint>))?
05:01liwpI gotta run, but I think tomoj's right, you should use refs
05:01kzarok
06:07krumholt_can i make a collection from a java array?
06:10hoeck1krumholt_: just call seq on it
06:11krumholt_hoeck1 nice thanks
06:16AWizzArdchouser: shell-outs sh is for short running processes yes? (not like a pipe)
07:01djpowellhmm, you know how add-class-path doesn't work well cause it can't append to the system class path? Attach agents, like I use in my liverepl can. Wonder if you could use them to replace the interactive uses of add-class-path? <http://java.sun.com/javase/6/docs/jdk/api/attach/spec/com/sun/tools/attach/VirtualMachine.html#loadAgent(java.lang.String, java.lang.String)>
07:01djpowellprobably not. sounds flakey.
07:23djorkdjpowell: what's your liverepl?
07:28_atodjpowell: it's likely the agent is loaded in a subclassloader, so it would probably have the same problems as add-classpath (namely stuff loaded in higher classloaders can't see stuff in lower classloaders)
07:29_atoadd-classpath should work okay if you load everything into Clojure's classloader (ie you put nothing but the clojure jar on the -cp command-line and add every jar you need with add-classpath)
07:31esjgents, is there a way to send a SIGINT (or equivalent) to a particular agent. shutdown-agents merely prevents new actions being dispatched, while I want to pull-down the running action.
07:33krukowesj: I don't think so, you'd have to program the agent to be interruptible
07:33krukowand check for interrupt status often
07:33krukowand still you'd need to access the thread... so probably not :-(
07:34esjok thanks
07:36_atoyeah, not reliably anyway. Even if you can get a handle on the thread (I guess you could have the agent put it in a ref when it starts the job or something), if it blocks on IO or something catches the interrupt exception it becomes uninterruptible
07:39mrSpecCould you tell me how to change the value of x in let block? I cant find anything :/ like: (let ((x 0)) (setf x 1))
07:40krukowyou cant: let bound locals are not variables
07:40_atomrSpec: clojure locals are immutable
07:40esjhmm... will need to think.
07:41krukowthere was one thing that came up yesterday: you can (let [x 42 x (inc x)] x)
07:41_atoyou can however do: (let [x 0] (let [x 1] ...))
07:41_atoyeah
07:41krukowLOL :-)
07:41krukow,circuitbreak
07:41clojurebotjava.lang.Exception: Unable to resolve symbol: circuitbreak in this context
07:41esjyikes !
07:41_atothat's not changing the value though, it's creating a new binding that "shadows" the outer one
07:41mrSpechehe
07:41krukow,(let [x 42 x (inc x)] x)
07:41clojurebot43
07:41krukowthat is what I mean
07:42mrSpecbut can I do it in other way? to change value?
07:42MaddasWhy?
07:42mrSpecI dont want 2nd "x"
07:42MaddasWhat is the problem you're trying to solve? You can't mutate an immutable, that's kinda the point :-)
07:42krukowwhy do you want to change it: can you give an example?
07:43mrSpecok, I'm rewriting C++ code
07:43mrSpecI'll paste it sec
07:43djpowelldjork: http://github.com/djpowell/liverepl - lets you repl in to running clojure/java processes with no special pre-configuration
07:43krukowheh - ok here we go
07:43djorkoh cool
07:44mrSpec,paste
07:44clojurebotjava.lang.Exception: Unable to resolve symbol: paste in this context
07:44mrSpechmm
07:44mrSpecwhat was the url?
07:44djorkclojurebot: paste
07:44clojurebotlisppaste8, url
07:44lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
07:44mrSpecthanks
07:44krukowclojurebot: help
07:44clojurebothttp://www.khanacademy.org/
07:44djorkmrSpec: to "change" the value of a binding in a block you would recur
07:45djorkeither recur on the fn itself or use the loop construct
07:45lisppaste8mrSpec pasted "Mandelbrot " at http://paste.lisp.org/display/91009
07:46djork,(loop [x 1] (if (< x 10) (recur (inc x)) x)
07:46clojurebotEOF while reading
07:46djorkoops
07:46djork,(loop [x 1] (if (< x 10) (recur (inc x)) x))
07:46clojurebot10
07:46krukowC for usually maps to loop-recur
07:46krukowor higher order functions
07:47djorkmrSpec: you wouldn't "change" isInside, you would return it
07:47mrSpecso if it so complicated, I'm doing something wrong?
07:47mrSpecdjork: ah
07:47esjyeah, i think recrusion
07:48djorkyour innermost for loop should be translated into one expression that evaluates to the value of is-inside
07:49krukowmrSpec: it is not really more complicated, just different
07:49mrSpecdjork: ok, I'll try with loop
07:49krukowbut don't measure performance and then come back saying that clojure is slow :-)
07:49djorkheh
07:51mrSpechah about speed... I have some memory problem. It takes a lot of memory, but first I'll make it work, then I will think about memory ;)
07:51krukow;-) btw. I think that algorithm will be awkward to translate
07:52krukowparticularly the part that sets isInside to false and then checks it later to sideeffect putpixel
07:55mrSpeckrukow: so I should find other algorithm? ;)
07:57krukowI think it would be easier to rethink the algorithm than to try and port that imperative algorithm to a functional style, but just my two cents :-)
07:59_atohttp://gist.github.com/241856
08:00_atothe isInside loop might look something like that I guess
08:00_atoI don't know what the alrogithm is doing so I've just called it "step"
08:01djorkI'd make the algo return a seq of coords
08:04mrSpec_ato: thanks, I'll try it :D
08:05_atoI guess you'd probably need to use letfn instead of defn for step and inside? as you need to close over c-im and c-re values from the outer loops
08:06mrSpeci will have to read about letfn to see the difference.
08:06_atooh actually inside? is okay
08:06_atoit's just step that uses c-im and c-re
08:10_atoyeah.. so actually maybe the whole thing would look something more like this: http://gist.github.com/241856 (updated)
08:10mrSpecok, thanks for help, I have to go to Uni BBL
08:11krukowheh - uni exercise :-)
08:14AWizzArdrhickey: when I (send my-agent) in two threads T1 and T2, will then an await or await-for in T1 always wait for the answer it sent?
08:16the-kennyAWizzArd: I think t1 will wait for *all* actions in the agent to complete
08:17AWizzArdSo then I would need to keep my current strategy to provide a (promise) and read that, ok.
08:56rhickeyso I've just applied a contributed patch with git am, and tests fail, what's the easiest way to back it out?
08:57chouseryou haven't pushed it?
08:57rhickeyno
08:57chousergit reset --hard HEAD^ # that'll back you up one commit
08:57chouserthe --hard means you might lose data, but of course that's what you want.
08:57chouserjust be careful you don't have any uncommitted changes you want to keep
08:58rhickeyI thought so, what an ugly command for such an ordinary thing
08:58chouserwell, it's what I do. I don't know if it's "right" or best
08:58rhickeysince git am applications are always speculative, you are not committing something you wrote yourself and understand to be correct
09:02chouseryes. I think another option might be to do all such commits in a local branch made for just such activity
09:03chouserbut it's not clear to me that whole set of commands you'd end up using would be any less wordy
09:03rhickeychouser: I do that, but there were prior patches I wanted to keep
09:04rhickeyok, next release punch list is down to three items
09:06chouserooh
09:06rhickeyagent errors needs tidying
09:07rhickeysorted-set-by patch is broken, but I'd like to get the fix in
09:07chouserembedded constants is just about the tests.
09:07chouserneed to make sure they're actually testing what they claim to be
09:08rhickeyI'm unclear about embedded constants, don't we have that already?
09:08chouseryeah, the main patch is in but there's been some confusion about the tests.
09:09chouserat least in part because my experience reading tests is thin
09:11rhickeyI've looked t every patch, and determined it's either not yet a good idea or not ready (in backlog), a good idea for next time (approved backlog), applied it, or those 3 left in Next Release
09:14chouserthank you. Does this feel like a sane system to repeat for future releases?
09:15rhickeyI think so, we'll see how people do with the latest code and release candidate downloads
09:17chouseralmost 30% so far say they're using 1.0. I'm losing my bet.
09:17rhickeywe are going to need docs for a lot of things
09:17chouseryeah, I thought of that. :-/
09:17rhickeywhere are the results?
09:17chouserno good result charts yet
09:18chouserI was just using this: http://tinyurl.com/yefmz8e
09:19rhickeythanks
09:19chouseralmost 10% on 'new'
09:20rhickeycrazy people
09:20rhickey:)
09:20chouser:-)
09:20fogus_chouser: Hey! I resemble that remark.
09:21rhickeyso new is very new today - the direct linking stuff is in for the craz... er intrepid
09:21the-kennyHow can I take the survey? I can't find a link in the Spreadsheet..
09:21fogus_I don't know what that word means, but it sounds great!
09:22chouser53% don't know what chunked seqs are
09:22chouserthe-kenny: survey: http://tinyurl.com/yeejwok
09:23chouser1% say chunked seqs hurt
09:26devlinsf,(str "Test")
09:26clojurebot"Test"
09:51cemerickrhickey: been absent for a bit -- is this 'direct linking' written up anywhere, or are the irc logs the best spot?
10:08jweissquestion - is it idiomatic or overkill to use a multimethod like a switch statement? I am not sure that's an intended use for multimethods
10:08krumholt_can i "clear" a namespace of all symbols? i am trying to compile my code and i have renamed a bunch of functions. the "old" version are still around and i need to get rid of them
10:09chouserjweiss: if there's a possibility someone else might want to extend your switch statement, multimethods are definitely a good option
10:09jweisschouser: probably not going to need extending
10:09chouserjweiss: if not then I guess it's up to you whether you think it would be clearer using cond or condp, or if multimethods would be clearer.
10:11jweisschouser: i'll try the multimethod and see if it looks readable. thanks
10:11chouserjweiss: of course anytime the cond wouldn't be at the top level of a fn, a multimethod is likely to be a poor fit.
10:12chouserkrumholt_: you can combind ns-interns with ns-unmap to clear everything
10:13jweisschouser: i'm trying to "switch" on a test result (pass/fail/skip/exception) and call a set of "listeners" which do user-defined stuff based on the results of the test
10:13jweissthis is not any of the build in test stuff btw
10:13jweissbuilt
10:14jweissi think multimethod will work
10:14krumholt_chouser, thanks
10:28scottj_Is there a general pattern for converting (for [a (foo) b (bar a) c (baz b)] [a b c]) into a series of maps? I'm trying to generalize p27 from ninety-nine prolog probs, here is the specific solution I came up with http://paste.lisp.org/display/91015 any suggestions? thanks
10:31chouserwhat's wrong with using 'for'?
10:34scottj_in part I'm curious how to do it w/ map, since I could use pmap. in part bc I thought map might be easier to write a general solution for w/o macros.
10:34chouserhm, maybe we need pfor. :-)
10:35jweissif i'm using a multimethod that takes 3 args, and the dispatch only cares about the first arg, what do i put for the 2nd and 3rd args in the defmethods?
10:37jweissjust use nil?
10:40chouserscottj_: http://paste.lisp.org/display/91015#1
10:41chouserscottj_: when you have :when or :while things get trickier.
10:42scottj_Chousuke: thanks!
10:42scottj_(sorry about the default autocorrect)
10:42scottj_or maybe that was tab
10:42chousernp
10:43chouserhappens all the time
10:43chouserbut we're each too stubborn to change our nicks, so there you go. :-)
10:44rhickeycemerick: IRC logs re: direct linking - new last weekend
10:47cemerickOK, thanks :-)
10:48cemerick+1 on the idea of pfor
10:48rhickeycemerick: short story - more speed, via dynamicity tradeoff - nothing new under the sun
10:49cemerickrhickey: yeah, I caught a brief bit of the conversation yesterday, w.r.t. issues with contrib ns' rebinding core fns
10:49rhickeybut open questions about how to best expose/control, so please chime in once up to speed
10:49chouserapparently I have an unconcious urge to make 'for' as complex as possible. chunk support helped a lot. pfor would take it a significant step further.
10:50cemerickI actually do rebind the root of a couple of core vars, though I presume that wouldn't be impacted by dynamic linking.
10:50cemerickor, static linking, that is.
10:51cemerickchouser: for is the new LOOP? :O
10:51rhickeycemerick: meaning you replace the core fn?
10:51chousercemerick: if you don't call it, it won't be staticly linked
10:51rhickeyI'd like to call it direct linking
10:51chousercemerick: if you don't call it, it won't be direct linked
10:52cemerickrhickey: yeah -- the memoization of classes, or bases (forget which)
10:52chouserah
10:52cemerickah, supers and bases
10:52rhickeybut yes, replacing roots would be effected since code direct linked prior to the replacement won't see the new version
10:52rhickeyaffected
10:53cemerickrhickey: I make sure I do my monkey-patching very, very early :-)
10:54rhickeyI'm interested in any early experience reports on the latest new with direct linking
10:54cemerickI'm bundling a release this week -- will hopefully pull in HEAD over the weekend.
10:54cemerickrhickey: you're expecting some pretty crazy perf improvements eh?
10:55rhickeycemerick: it seems like 20-25% across the board is easy, but in specific cases it can be much. much faster, like 10x +
10:56rhickeyright now it is limited to clojure*, so you won't get direct links for your own code
10:56cemerickis there more going on here than simply avoiding the indirection of the vars?
10:57rhickeycemerick: it's not actually the indirection, its the volatility
10:57rhickeycan't inline through volatile
10:57cemerickyou mean all the stuff associated with binding...
10:57cemerickoh, you mean java-volatile
10:57rhickeycemerick: no, dynamic binding is another layer, I'm just talking about replaceable roots
10:58chouserrhickey: re agent errors, you want some kind of guard to prevent any thread from doing clear-agent-errors while a error handler is running?
10:58chouserrhickey: or just guard the error handler thread itself while the handler is running?
10:59rhickeychouser: if easy, which it could be since you could compare *agent* to passed agent
10:59rhickeybut most important is to doc that it is not ok
11:00rhickeyuntil we figure out that it is :)
11:00chouserso other threads clearing while handler is running is ok
11:00cemerickso, without looking at HEAD (:-P ), I'm guessing there's now two Var classes, one with a volatile root another without -- and a direct-linked call site gets the latter, everyone else gets the former...
11:00chouser:-) right
11:00rhickeycemerick: no, direct linking is a property of the caller, not the var
11:00cemerickswing-and-a-miss
11:00rhickeyso different callers might have different linkage
11:01rhickeythe only thing that *is* on the var currently is a :dynamic true metadata tag that indicates it should never be direct-linked as it is due to be rebound by design
11:01rhickeycurrently pr is marked thusly for pprint
11:02rhickeyand test/report
11:03chousersorry, I'm still not clear on what you want for clear-agent-errors. (send a (fn [_] (clear-agent-errors *agent*))) is ok, right?
11:04rhickeychouser: why would one do that?
11:05cemericknuclear-level error clearing "I want a usable agent back, dammit!"
11:05rhickeycemerick: but the send part?
11:06cemerick*shrug*
11:06chouseractually that won't work because you can't send to an agent with errors
11:06cemerickI've taken to simply wrapping everything sent to agents with a (try (catch Throwable ...)), just to avoid having to deal with agent errors. :-(
11:06rhickeycemerick: you want to ignore the errors?
11:06chousereither ignore or ...dum da dum... provide a callback.
11:06chousercemerick: right?
11:07cemerickrhickey: well, that (catch Throwable) is in a quickie macro. The "real" code being sent has proper error handling. I just wanted a safety in the event of a stack overflow, OOME, etc.
11:08cemerickI'm only using agents in one spot, so it's entirely possible that I'm Doing It Wrong.
11:09cemerickThe client code only really cares about two states, :error and everything else. When the former happens, it gets logged to be pondered later, very little that can be done in-place.
11:09cemerickExceptions hanging around in the agent just muck up the other 99% of the work that goes off without a hitch.
11:10rhickeycemerick: so that ties into the auto-clear concept - send to callback and don't log internally
11:10rhickeyI'm not opposed
11:11cemerickrhickey: I'm afraid I'm not at all versed in the various proposals wafting around for agent errors. Learn from me at your peril. ;-)
11:11rhickeyI guess we had talked about the return value of the callback controlling that and the next agent state
11:11rhickeycemerick: these are things we already talked about
11:11chouserok, so queued actions will proceed even if there's an error in the list. That's not a behavior I've taken advantage of.
11:13chouserso perhaps you might send several actions, some of which you know might fail and queue up a clear at the end of them so that future sends will be allowed.
11:13rhickeychouser: that's somewhat broken
11:13chousersounds like a risky design, I suppose
11:13chouseryeah
11:21tmountainI was playing around with writing a squeeze function this morning to replace redundant runs of a given character in a string with a single instance of that character
11:21tmountainhttp://travis-whitton.blogspot.com/2009/11/squeezing-string.html
11:22tmountainfor some reason, the version I wrote which uses reduce has terrible performance compared to using re-gsub from str-utils
11:22tmountainI'm wondering if it's something in my code or if I should avoid using reduce if I'm concerned about performance?
11:23rhickeytmountain: building strings by successive concatenation is a bad idea in every programming language, here too
11:24leafwtmountain: use str, which uses an StringBuilder.
11:24rhickeysetting aside that regex will build a little machine for you, you'll need something with efficient append - streams, transient vector etc
11:25rhickeyleafw: calling str over and over is no different than concat
11:25leafwtrue, still lots of new String being created.
11:25tmountainrhickey: so in the real world, I'd be better off with the regex or using something like a transient?
11:26rhickeytmountain: you can try a vector instead with little change to your existing code, and transient will little change to that
11:26leafwtmountain: no, rhickey meant you'd use a vector to accumulate strings, then apply str to it
11:26tmountainleafw: ok, gotcha
11:28rhickeymake x a [] and (conj x y)
11:29rhickeystr when done
11:29rhickeyit still won't compete with a regex
11:30rhickeyalso, last is dangerous
11:30rhickey,(doc last)
11:30clojurebot"([coll]); Return the last item in coll, in linear time"
11:30rhickeylinear time == do not use for not known small
11:31tmountainrhickey: good to know. thanks for the tips.
11:37replaca_p
11:41replaca_oops
11:46Chousukehm, there's a ninja commit in the git repo :P
11:46Chousuke"Author: unknown <Ninja@.(none)>"
11:46chouseryikes
11:47Chousukeprobably someone with misconfigured tortoisegit :)
11:47magnetthat's what he wants you to believe
11:48chouserah, pretty to see whose it actually is.
11:52chouserseems to me that most of the time if you provide an error-fn for an agent you don't want the error queued for you or the value of the agent to change, so simply providing an error-fn could do that
11:53chouseryou can always have your error-fn queue the error somewhere else if that's what you want, otherwise just don't provide an error-fn and let it be queued in the agent
11:54SergeyDidenkoHi! Can anyone help me to simplify the following code: (def mymap {:vec [1 2 3]})
11:54SergeyDidenko(assoc-in mymap [:vec] (conj (:vec mymap) 5))
11:54SergeyDidenkoI mean the second line
11:54SergeyDidenko:)
11:54chouserso that really just leaves the (I think unusual) case where you want the error-fn to adjust the value of the agent, perhaps based on the fn, args, or old state of the agent. Could use the return value of error-fn to communicate that, but doing so complicates the "normal" case of just leaving it alone.
11:55chouserSergeyDidenko: (update-in mymap [:vec] conj 5)
11:56SergeyDidenkoThanks, chouser. Somehow missed that.
11:56chouserrhickey: how does a set-agent-value that only works inside error-fn strike you?
11:57chouserSergeyDidenko: np
12:03chouserhaving an error cause a change to the agent value isn't even an option today, so maybe that feature's just not needed.
12:09chouserso that would mean agents with an error-fn would never be in an 'error' state. If all the useful data (exception, agent, fn, args) get passed to error-fn as a map, you could do something as simple as (agent state :error-fn prn) to get an agent that never gets "stuck" and prints errors to stdout
12:09chouserI think I like that
12:09chouserrhickey: I'm not going to touch this without some sense I'm headed in the right direction. Do you want me to write this up better and maybe post to clojure-dev?
12:15tmountainI re-wrote the squeeze function, built up the data, and then applied str at the end, and it runs 27X faster ;-) http://travis-whitton.blogspot.com/2009/11/squeezing-string.html
12:23chouser(agent init :error-fn #(.printStackTrace (:error %))) if you want to get fancy
12:26cemerickchouser: nice :-)
12:31djorktmountain: nice
12:31djorktmountain: good call on leaving str to the last step
12:43esjanybody here interacted with COM in clojure ?
12:45duncanmesj: via Java, or via .NET?
12:45devlinsfesj: No, but there is the JaCOB library
12:45esjJava
12:45devlinsfesj: http://danadler.com/jacob/
12:46esjyeah, i've seen JaCOB, com4j and ez jcom
12:46esjwas wondering if anybody had opinions
12:47duncanmheh, i wonder if you can run Clojure on the MS JVM
12:47duncanmdoes clojure require java 5+?
12:49devlinsfduncanm: Yes, I believe java 5 is required
12:50jweisscan I use isa? with an interface? ie, how do i call isa? to check that Exception is a Throwable.
12:51jweisssorry that (Exception.) is a Throwable.
12:51devlinsf,(isa? (class {}) clojure.lang.IFn)
12:51clojurebottrue
12:52jweiss,(isa? (Exception.) java.lang.Throwable)
12:52clojurebotfalse
12:52devlinsf,(isa? java.lang.Exception java.lang.Throwable)
12:52clojurebottrue
12:52jweissdevlinsf: that's because they are both classes
12:52devlinsfjweiss: Try this
12:52hiredman,(doc instance?)
12:52clojurebot"([c x]); Evaluates x and tests if it is an instance of the class c. Returns true or false"
12:53Chousuketmountain: I wrote a quick version of that using a transient vector and it's about 30% faster it seems :)
12:53devlinsf,(isa? (class (Exception.)) java.lang.Throwable)
12:53clojurebottrue
12:53hiredman,(instance? Callable #())
12:53clojurebottrue
12:53hiredman,(instance? clojure.lang.IFn #())
12:53clojurebottrue
12:53jweisshiredman: i ask about isa? because i'm using multimethods, which calls isa?
12:53devlinsfjweiss: Use the class fn
12:54Chousuketmountain: http://gist.github.com/242063
12:54jweissso if i want to dispatch on a Throwable, how do i do that.
12:56ChousukeI like how few changes I had to make to use transients :P
12:56jweissmaybe i'm confused about what isa does. if i pass it two class objects, does it actually look at the hierarchy of their inheritance, or does it just say "yep, they're both class objects"
12:56hiredmanit looks at the hierarchy
12:56krumholt__can someone explain to me why (map (fn [a b c] (a b c)) '(list list) [1 1] [2 2]) => (2 2) i would expect ((1 2)(1 2))
12:56jweisshiredman: ok thanks
12:57hiredmanyou can even pass your own hierarchy to isa?
12:57jweisshiredman: yeah i know, but i don't want to make my own in this case
12:57Chousukekrumholt__: you're using the symbol list as a function instead of the function list
12:57Chousuke,('list 1 2)
12:57clojurebot2
12:57krumholt__Chousuke, oh thanks
12:58Chousukein general, it's ('sym coll not-found)
12:58krumholt__what does a symbol used as a function do?
12:58Chousukelooks itself up in whatever
12:58Chousukeor returns the second argument if it fails.
12:58krumholt__ok thanks
12:58Chousukeie. same as a keyword.
12:59Chousukeyou'd get the result you wanted if you used a vector instead of a quoted list :)
13:00krumholt__very nice :)
13:04devlinsfkrumholt__: to empasize chosuke's point
13:04devlinsf,(map (fn [a b c d] (a b c d)) '(list list) [1 1] [2 2] [3 3])
13:04clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: Symbol
13:04devlinsf,(map (fn [a b c d] (a b c d)) [list list] [1 1] [2 2] [3 3])
13:04clojurebot((1 2 3) (1 2 3))
13:05tmountainChousuke: very cool
13:06hiredman,(map (fn [a b c d] (a b c d)) (list list list) [1 1] [2 2] [3 3])
13:06clojurebot((1 2 3) (1 2 3))
13:06Chousukehiredman: very clever :P
13:06hiredmanbuffalo buffalo buffalo buffalo
13:06defnbuffalo
13:06duncanmhmm
13:06duncanmhow does that work?
13:06Chousukeduncanm: (list list list) creates a list of two functions, list and list
13:07hiredman,(list list list)
13:07clojurebot(#< clojure.lang.PersistentList$1@bd11b1> #< clojure.lang.PersistentList$1@bd11b1>)
13:07duncanmohh
13:07defn,(list list list list)
13:07clojurebot(#< clojure.lang.PersistentList$1@bd11b1> #< clojure.lang.PersistentList$1@bd11b1> #< clojure.lang.PersistentList$1@bd11b1>)
13:08defn,(list (list (list list list)))
13:08clojurebot(((#< clojure.lang.PersistentList$1@bd11b1> #< clojure.lang.PersistentList$1@bd11b1>)))
13:08ChousukeHm
13:08ChousukeI think Lisps problem wasn't that there were too many parentheses
13:09Chousukeit was that there were too many lists.
13:09Chousuke:P
13:09defnheh
13:09Chousukealso, Lisp's
13:10duncanmheadius: the talks from JRubyConf will be posted, right? do you have an estimate?
13:11defni wish they'd hurry up and post the RubyConf S. Halloway talk
13:12headiusduncanm: I do not know, but it will hopefully come quickly
13:12headiusclojure came up several times...seems like a lot of people like the idea of jruby front-end with clojure for concurrent services in the back-end
13:12headiusjruby's becoming a pretty nice web gluey front-end for other jvm langs
13:17ambientwhy can't there be one lang uber alles? :(
13:18ambientsql, java, xml, http, html, orm, templates, blah, it all gives me a headache.
13:18headiusambient: there will never be one lang
13:18ambienti see no reason why everything could not be done with lisp
13:18ambientor a language without any syntax
13:18annealeri see no reason why i'd want to program in a world like that
13:18rhickeychouser: I think you can't pass fn + args, since fn isn't a great identity, so if you just pass error plus current state, it would be easy to return that state or some reset value. Setting a handler can replace putting in internal error log afaic
13:18annealervariety is fun. there is no one language to rule them all
13:19headiusbecause not everyone will want to use lisp, and so everyone using lisp will have to duplicate effort others have already put in
13:19ambientvariety distorts focus, focus is good for getting things done
13:19headiusbetter to reuse than reimplement again and again
13:20annealervariety breeds innovation. there's more to life than just getting things done
13:21ambienti guess it's a good thing, we wouldn't want computing to be too simple so that there are more jobs available
13:21cemerickheadius: I had an old RoR hand chat me up over the weekend about how we should use JRoR as our eventual front end. He made a compelling case.
13:21headiuswho was that?
13:21headiuscemerick: ^^
13:22headiusRails 3 is also going to be even more compelling, since it will make it easier for us to swap bits out for existing java libs
13:22cemerickjust a friend of mine who was deep into rails for some years, until he got yanked out into php land a few months ago
13:22headiusthere's several folks doing exactly that
13:22headiusJRoR front plus Clojure in the back
13:22headiusit's like a reverse mullet
13:23ambientdoes jruby hide the classpath awkwardness?
13:23headiusgenerally, yes
13:23headiusrequire 'java'; $CLASSPATH << 'whatever.jar'
13:23cemerickinsofar as the web stuff is fundamentally "just a cost" for us (modulo the whole notion of quality UX), using something that designers and other like-minded folk are super-comfortable with makes sense.
13:23headiusit's not flawless, but it works for most people just fine
13:23defnhttp://disclojure.org/
13:24chouserI have exactly one rails project. It makes me unhappy.
13:24ambientthe fact that you have only one or the fact that you have a rails project?
13:24chouserIt's not ruby's fault either.
13:25headiuswe need to get a clojure-inline added to the inlining gem
13:25cemerickJust about any front-end I've ever had to build has been a miserable experience.
13:25headiussomeone added scala over the weekend
13:25chouserambient: heh. I've used the project to learn rails, and I haven't been fond of what I've learned.
13:25ambientchouser: not meant as a joke, i was just wanting to know your opinion and your statement was ambiguous ;)
13:25cemerickchouser: I think the objective in general is, bang it out, it's all going to get replaced in 6 weeks. ;-)
13:26defnso true
13:26cemerickThat was the general approach in the django world when I passed through there a while back, too.
13:26chouserI knew ruby already -- still my favorite pre-clojure language.
13:26ambienti've done some django, never touched rails
13:26headiusrails 3 cleans up a lot of the yuck in rails
13:26defnI haven't tried rails 3
13:27chouserI thought that since I hadn't done much standard server-side web app design that I should use a project that had made a bunch of design decicions already
13:27bitbcktdefn: it's still "edge"
13:27headiusthere's at least one place going live with jruby + rails 3 soon
13:27cemerickheadius: what's your pitch, then? Why should I use JRoR instead of something like compojure + enlive?
13:27defni tried doing a HAML + SASS + RoR project with 2.x, but I do NOT recommend it
13:27headiusthey're kind of crazy though
13:27headiuscemerick: no other web framework does as much for you as ror
13:27defn^
13:27defnthere's a reason compojure is modeled after rails
13:28ambientmost web frameworks give me headaches. I did Java Server Faces when it was barely version 1.0
13:28cemerickheadius: but aren't I risking a significant skills/attention dilution by having yet another language floating around?
13:28headiusambient: I think that's a feature of JSF, actually
13:28ambientheadius: not just headaches, but uncontrolled bursts of blind rage
13:28headiuscemerick: well, given that there's lots of folks building rails apps without really knowing ruby, I'd say the watering-down potential is low
13:28KirinDavecemerick: For the libraries. :) For the language, it's a lot like human language. Your total capacity grows with your total inventory.
13:29headiusrails is really just a nice internal DSL for web apps
13:29headiusthe fact that it's in ruby is peripheral
13:29defncemerick: i don't think so. You have CSS, XHTML, why not throw a couple more in for other specific aspects of your application?
13:29chouserI would argue with "nice", esp. around activerecord
13:29KirinDaveAlso, find something that is more suitable for rapidly developing a web app with a small team.
13:29defnchouser: no one is forcing you to use activerecord
13:29KirinDaveMost people don't understand the tradeoffs Rails decided to make.
13:30cemerickdefn: yeah -- I'm, uh, promiscuous w.r.t. programming languages already. Just trying to draw headius out a bit :-)
13:30defnhehe :)
13:30headiusI'm not a great person to advocate rails over X though
13:30headiusI don't do apps much these days
13:30cemerickchouser: I'd agree, but when one isn't using an RDBMS, then activerecord ceases to be a problem :-)
13:30cemerickheh, I should head over to #ruby and see what I can stir up.
13:30iceytwitter has turned into a really good irc warning system. when you start seeing the OHs you know it's time to login :D
13:30bitbcktcemerick: #ruby-lang
13:31bitbcktBut if you go too far toward Rails, you risk getting punted into #ror, from there.
13:31cemerickhuh, and there's a #jruby too
13:31KirinDaveWhich is totally worthless.
13:31bitbcktRightly so, imho.
13:31KirinDavejruby is much better.
13:32KirinDaveThis is an example of #ruby-lang
13:32KirinDavehttp://kirindave.tumblr.com/post/24570389/incredibly-stupid-people-on-freenode-ruby
13:32KirinDaveI would avoid them.
13:32cemerickheadius: is glassfish still the preferred container for JRoR?
13:32bitbckt+1 on glassfish
13:32technomancybitbckt: did I meet you at JRubyConf?
13:32headiuscemerick: it's very nice
13:32bitbckttechnomancy: Yessir, you did.
13:32headiusas app server or as gem
13:32defnOooOooo! http://orgmode.org/worg/org-contrib/babel/org-babel.php There is no clojure support for org-babel
13:32bitbckttechnomancy: I'm the awkward idiot that bugged you before your talk. :-)
13:32defnerr rather org-babel support for clojure
13:32defnnow*
13:32headiusbitbckt: who are you irl?
13:33bitbcktheadius: Brandon Mitchell
13:33cemerickheadius: is GF the only viable option, though?
13:33headiusahh ok, one more connection made then
13:33technomancybitbckt: heh; yeah I was just kind of heads-down since I decided to to the lightning talk on short notice.
13:33bitbcktheadius: We had dinner together a RubyConf 2 years ago.
13:33headiuscemerick: nah, jror can deploy as a war file to lots of stuff
13:33headiusGF just has some other nice non-WAR options
13:34bitbckttechnomancy: I understand. I appreciated your advocacy.
13:34bitbcktAnd Halloway, of course.
13:34technomancyhe sure knows how to pitch
13:35bitbcktYes, he does. Despite Susser.
13:35bitbckt>_>
13:36headiusis phil hagelberg on irc?
13:37headiushe did a lightning talk at jrubyconf about using refs+stm from jruby
13:37bitbcktheadius: technomancy
13:37headiusoh, great :) hi, technomancy
13:37bitbckthehe
13:37headiustechnomancy: I was thinking of ways to make that more seamless
13:37bitbcktHuzzah for Rubyists in #clojure...
13:37KirinDaveheadius: I am surprised you two haven't met.
13:37KirinDaveSeems like you're on a collision course.
13:37headiusI just didn't know nickname
13:38headiustechnomancy: I've also had a handful of people that want to implement a "clojure mode" in Duby that uses clojure refs
13:38headiusperhaps for object fields or something
13:38technomancythat would be slick
13:39bitbcktOoh.
13:39technomancyright now the problem with jruby integration is exception wrapping; retry exceptions inside ruby blocks get wrapped with ruby exceptions
13:39chousericey: what do you meant?
13:39technomancyI was trying to patch Clojure to catch them at the appropriate place and retry, but I wasn't sure how to do that without making Clojure depend on JRuby
13:39headiusyeah there's a backward-compat issue that's hard to deal with
13:40jweisstechnomancy: i'm following step3 of swank-clojure install ( 3.
13:40jweiss if you want to use a newer version of Clojure than 1.0 you will need to build it yourself and symlink the compiled jar to ~/.swank-clojure/clojure-$VERSION.jar after removing the old version.) i am getting classnotfound on clojure.main. did i need to make the link names exactly the same as the old filenames, even though it's a different ver of clojure?
13:40headiusi.e. previous jruby folks decided to wrap all incoming java exceptions in our NativeException, rather than just make Java exceptions get JI-wrapped and use that
13:40duncanmheadius: i had a similar thought the other day - duby syntax + clojure semantics might be useful for those afraid of the lisp syntax
13:40technomancyjweiss: it should just use all the .jar files in ~/.swank-clojure if you don't set the classpath yourself.
13:40headiusduncanm: to be sure, and probably not hard to wire in
13:40headiuscould spike a "clojure_compiler" for duby that does it without much effort
13:41jweisstechnomancy: hm. do i need to recompile swank-clojure or anything like that?
13:41technomancyheadius: yeah, tom was telling me that was the Way of the Future.
13:41headiustechnomancy: I think I just had an idea how to get real exceptions to propagate without breaking anything
13:41headiuswe'll just have NativeException#=== return true for Java exceptions
13:41KirinDavetechnomancy: I have a question for you.
13:41the-kennytechnomancy: Would it be possible to bring swank-clojure-project to use the var swank-clojure-extra-classpaths in addition to the classpaths from the project?
13:41jweissi just renamed the old jar files, appending ".old" and symlinked the new ones (freshly built from master git branch)
13:41headiusthen existing rescue blocks will still work
13:41headiushmmm
13:41KirinDavetechnomancy: I'm really curious about hacking on your build project now that i've spent so much time with it. But... I was curious...
13:42KirinDavetechnomancy: Would you be opposed to more direct interaction with clojars during the project invocation?
13:42technomancyheadius: wow, if that would work, that'd be much cleaner.
13:42KirinDavetechnomancy: E.g., "I think it was... compjure or something. Let's search."
13:43technomancythe-kenny: there's an alias set up that is supposed to do that already
13:43iceychouser: sometimes I'll see someone mention a quote on twitter (invariably it's someone quoting headius) and it lets me know there's probably an interesting irc conversation going on ;)
13:43headiustechnomancy: yeah, definitely...then we'd just propagate the actual exception throughout
13:43the-kennytechnomancy: Huh? my repl depends somehow on swank-clojure-extra-classpaths, and it doesn't work if I use swank-clojure-project
13:44chousericey: ah, I see. thanks!
13:44technomancythe-kenny: nm; misread you. the idea of swank-clojure-project is that everything is self-contained; if you want to use jars outside the project dir use symlinks
13:44the-kennytechnomancy: hm.. ok.
13:45iceychouser: are you chouser on twitter?
13:45chousericey: no, chrishouser
13:45technomancyKirinDave: not sure quite what you mean... which leiningen task(s) would get hooked up to clojars?
13:45KirinDavetechnomancy: Well, a more fancy "new" would be pretty awesome, in my opinion.
13:46headiusanother possible reason to use ror for the front-end is that webapps are messy, stateful, mutable affairs; better to just let rails handle all that mess
13:46technomancyKirinDave: oh, so something that can pick from a number of new project templates?
13:46technomancythat'd be nice
13:46KirinDavetechnomancy: Yes. And also maybe even integration with the clojars metadata.
13:47the-kennytechnomancy: Another question: When do I have to (require 'swank-clojure-autoload) in my .emacs? I couldn't get it to work without copying some from the file to my .emacs.
13:47KirinDaveLike let's say the project page is tied to a github, you could envision git enabled tasks to pull out submodles as necessary and properly configure the project to build them.
13:47defnWhat are chunked sequences?
13:48KirinDavedefn: It's an optimisation
13:48technomancythe-kenny: that should be handled for you by an elpa install... if you're not using elpa it's more complicated.
13:49KirinDavedefn: They basically compute the sequence in chunks to amortise the advancement cost over time.
13:49defnooo cljdb!
13:49defnKirinDave: ah-ha -- thanks
13:49the-kennytechnomancy: I don't want to use elpa... I like to have control about such things.
13:49rhickeychouser: did you see above: I think you can't pass fn + args, since fn isn't a great identity, so if you just pass error plus current state, it would be easy to return that state or some reset value. Setting a handler can replace putting in internal error log afaic
13:49KirinDavedefn: rhickey tweeted the link yesterday: http://bit.ly/7pmDgE
13:49defnahhh, thanks again
13:50defnback to work...
13:50technomancyKirinDave: right now projects can have dev dependencies on leiningen plugins, which would work for tighter integration for everything except new (since new runs without a project in place)
13:50chouserrhickey: yes I did thanks.
13:50technomancybut we're thinking about adding a user-level config file, so you could have leiningen plugins loaded across the board
13:50chouserrhickey: you think it's important to allow the error-fn to change the state of the agent?
13:50headiusI wish we all had a common set of function interfaces across langs
13:50technomancythe-kenny: ok, but if you don't use the supported installer then you're on your own, sorry.
13:50headiussigh
13:50the-kennytechnomancy: hm ok, no problem.
13:50headiustechnomancy: is there a bare "clojure" gem?
13:50bitbcktheadius: That would ruin all the fun.
13:50KirinDavetechnomancy: Which is why the task would have to be built in.
13:50the-kennyIt's working fine now.
13:51KirinDavetechnomancy: But after that, things like git assists would be easy to add.
13:51rhickeychouser: yes, but if handed the current state, should be no problem to simply return it
13:51technomancyheadius: not without my wrapper afaik
13:51cemerickbitbckt: "bozo bit company" :-D
13:51bitbcktcemerick: *sigh*
13:51chouserrhickey: ok
13:52bitbcktcemerick: I can't express how true that is.
13:52headiustechnomancy: we should release one, so there's a basline gem people can depend on
13:52cemerickbitbckt: don't worry, the times, they are a'changin.
13:52headiusor I need to get off my ass and wire maven support directly into rubygems
13:52bitbcktcemerick: I hope so.
13:52headiusor just clean this up and make it handle dependencies well: http://github.com/jruby/maven_gem
13:53headiusthen you'd just gem install clojure-1.0 and it would fetch from maven
13:58iceyDoes anyone know if anybody is working on a Clojure web framework that uses templates instead of representing HTML in Clojure?
13:59KirinDaveicey: You can easily use a template agency with compojure.
13:59chouserrhickey: changing state means running validators which may in turn cause errors. I guess errors thrown by error-fn directly or from validators can be put in the errors list?
14:00iceyKirinDave: pardon my ignorance, but what is a template agency?
14:00KirinDaveicey: I dunno why I wrote agency. I must have had a serious brainfart there.
14:00KirinDave... I am worried now.
14:00KirinDaveI meant library but I typed agency. :(
14:01iceyKirinDave: haha okay thanks :D I hit google thinking I had been looking for the wrong thing. Any idea what sort of engines people are using w/ compojure?
14:02KirinDaveThere was one really cool one I saw in here yesterday but I seem to have lost the think.
14:02KirinDaveFuck
14:02KirinDaveWhat the hell is wrong with me. I'm typing every word but the word I mean. Am I grandpa gummy now?
14:03cemerickicey: enlive is great concept, haven't used it in anything significant myself, though.
14:03KirinDaveicey: I was meaning to try http://clj-me.blogspot.com/2009/01/enlive-yet-another-html-templating.html
14:03cemerickjust about anything can be wired in, though
14:03KirinDavehttp://github.com/cgrand/enlive/blob/2a15c466048f7e0311243b3d7a669705bbcbe072/src/net/cgrand/enlive_html/example.html
14:04iceyHmmm, enlive looks interesting; I might check that out, thanks :D
14:05KirinDaveYeah, it looks like a really good way to interact with pages that have very rich javascript.
14:05iceyKirinDave: You can blame your mental state on the upcoming holidays; that seems to work for me
14:05KirinDaveYou can put in "stock" crap that simply provides sample data for your scripts.
14:05KirinDaveicey: I wish. I did just get married. I hear that once you get married you get dumber. Something about settling down to have kids.
14:05iceyKirinDave: that matches my experience with getting married ;)
14:06iceyI need HTML templates because I will often get completed sites sent to me that just need code added for the functionality, and I don't want to translate everything into Clojure to make it work
14:06KirinDaveyeah
14:06KirinDaveWell that whole sexpr-html is a very misguided idea when you're building whole pages.
14:06KirinDaveIt's nice for things like list items.
14:06cemerickI still don't understand the urge to use sexprs instead of HTML.
14:07KirinDavecemerick: It's because people hate and/or look down upon HTML.
14:07cemerickI'm hoping it's deeper than that -- trying to leverage the power of macros, etc.
14:07iceycemerick: I really like them when I'm doing one-off small applications and I just need a couple of forms, for example. I can see everything at once, and use functions for my patterns
14:07cemerickSeems like one's looking for a nail in that case, tho.
14:08chousermy co-workers were very happy when I provided a way to use JavaScript syntax to build DOM tree for subsequent insertion on the page.
14:08KirinDaveRight
14:08KirinDaveFor snippets it makes total sense.
14:08KirinDaveLike, I have strings and a list of strings could easily be a list in html.
14:08KirinDaveGreat.
14:09KirinDaveBut the minute you start trying to make more complex tags it falls apart
14:09KirinDaveAnd is less readable and less robust than HTML
14:09chouserhmmm
14:09cemerickIt might be because I used them so much, but I still like JSPs -- super-simple, gets out of your way, gets the job done.
14:09cemerickAvoid putting "real" code in there, of course.
14:09iceysexprs are also really nice if your application is composed, depending on prior user actions; I have a survey application that completely changes depending on what's been answered previously
14:09chouserSeems to me HTML was designed for marking up text. s-expr's (and json) are lousy for that.
14:10cemerickchouser: what do you think of the sexpr js templating lib that popped up a bit ago?
14:10chouserbut if you're creating a dense tree of small nodes, html/xml gets annoying fast, while s-exprs, json, yaml, etc. do nicely
14:12chouserhm, seems I wrote about this once.
14:12chouserheh. old. http://n01se.net/chouser/blog/#blogsd
14:14chousercemerick: link?
14:17cemerickchouser: yeah, not that I can find it again now. :-/
14:18cemerickchouser: http://github.com/arohner/scriptjure/
14:18cemerickOK, not *so* recent, but new to me. :-P
14:18djorkis it just me or is the list of announced features for JVM 7 a bit... underwhelming
14:19cemerickhuh, by our own arohner, even. I didn't even notice at first blush.
14:20djorkwow, scriptjure sure highlights the similarities between JS/clojure
14:20djorkit would be interesting to see a return-less version
14:20djorki.e. just automatically insert return in tail position
14:21KirinDaveI wonder if Clojure is ever going to switch from its CL-style macro system to a more scheme-like MBE system.
14:21KirinDaveIt seems like MBE is more in line with the way clojure does method definitions.
14:21the-kennyMBE?
14:21KirinDaveMacro By Example
14:21KirinDaveHave you see the way PLT-Scheme does macros?
14:22KirinDaveVery beautiful.
14:22djorkhmm, I just got used to Clojure's macros
14:22the-kennyNo I haven't, sorry.
14:22djorkI never got my head around PLT's
14:22KirinDavehttp://docs.plt-scheme.org/guide/pattern-macros.html
14:22djorkmostly because the docs are quite dense
14:22KirinDavedjork: I dunno, PLT Scheme has some of the most approachable documentation anyone has ever had for a lisp.
14:22djorkoh wow, that' snot bad
14:22KirinDavedjork: Just read the guide, not the reference.
14:22the-kennyMaybe you can implement MBEs with clojure macros :D
14:22djorkfor some reason I remember struggling with it a while back
14:22djorkah yes
14:22djorkit was the reference
14:23KirinDaveWhat's so cool about it is that it automagically handles masking.
14:23KirinDaveSo you can just write macros without consideration for variable capture.
14:24the-kennyKirinDave: Clojure has auto-gensyms.
14:24KirinDavethe-kenny: They're still explicit.
14:24KirinDaveor so the docs suggested?
14:25the-kennyYes, but it's easier than in CL :)
14:25KirinDaveYou need to decide when you want them
14:25KirinDaveOh sure.
14:25KirinDaveAnd sometimes you need the raw dawg macro
14:25KirinDaveI wonder if I could write an MBE library for clojure...
14:25KirinDaveFor 95% of all macros, MBE is superior, safer, and almost always clearer.
14:25djorkgo for it
14:26the-kennyKirinDave: Just try it :)
14:26djorkI'm happy with defmacro so far
14:26djorkbut I'm new to macros in general
14:26the-kennyIf it isn't possible with macros (which i doubt), you can also implement it right in the reader ;)
14:27KirinDavethe-kenny: It's possible with macros. Although it's best to be integrated into the reader to handle the namespacing issues.
14:27djorkthe-kenny: I think the trick with implementing MBE as a macro is the scope consideration
14:27technomancydid #^bytes get added as a type hint specifier, or is that still being worked on?
14:33cemericktechnomancy: I think it's in there, yeah
14:33jweissanyone here used c.c.logging ? getting it to work at the repl seems to be nontrivial
14:33chousercemerick: ah, for generating js from clojure, I misunderstood you. I haven't used it yet, but do have a project where it might fit. So no real opinion other than it seems like to be filling a real need.
14:33cemerickjweiss: it needs a little work -- it binds at compile time
14:33twbray,*command-line-args*
14:33clojurebotnil
14:37cgrandtechnomancy: #^bytes exists
14:37technomancycool
14:38technomancyit looks like you can type hint with classes that don't actually exist; that seems pretty strange
14:38technomancyno warnings or anything
14:38chouseralso with strings!
14:44twbrayPardon my extreme stupidity... been working in the REPL for a while, trying to run a script through main, failing. If I say (ns clojure.main) (defn main [args] ... ) in my script, then say java yadda yadda clojure.main my-script.clj, shouldn't that do it?
14:44twbrayLooking at http://clojure.org/repl_and_main
14:46chousertwbray: when called from the command line like that, it's just executing everything at the top level. you could add your own (apply main *command-line-args*) to the bottom of the file if you want.
14:47chouserI think there's another way to get a fn named 'main' called, but I don't remember how.
14:47twbrayAll I really want is to get access to cmd-line args, having trouble getting *command-line-args* to have any values
14:47technomancy-main is for building an executable jar
14:48twbrayThere has got to be a way to get a command-line arg into my clojure script :(
14:50lisppaste8Chouser pasted "command-line-args, simplest example" at http://paste.lisp.org/display/91038
14:52twbraychouser: Thanks. That was my first attempt, must have had some subtle typo.
14:59drewrwill clojure automatically benefit from Java 7's number underscores?
15:00cemerickisn't that just compiler sugar?
15:01chouserdrewr: I doubt it. cemerick: probably
15:01chouserthere have been proposals for spacers in numbers for Clojure
15:01drewrI remember those discussions
15:01fogus_What was the final verdict?
15:01cemerickI don't see the appeal, but whatever
15:01drewrmaybe this will help make a decision
15:02devlinsfJava 7 is dead. Isn't that why we're here?
15:02chouser:-(
15:02drewrI think (range 10_000_000) is much nicer than (range 10000000)
15:02chouserI like (range 1e7)
15:02drewryeah, I forget about that
15:03chouserbut of course that doesn't help with 121121521111 or whatever
15:03chouserof which there are so many in my code
15:03the-kennyI think 10_000_000 is very ugly
15:03the-kenny,(identity 10,00)
15:03clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$identity
15:03chousercomma is whitespace!
15:03drewrcomma is whitespace, not null space
15:03chouser~comma
15:03clojurebotIt's greek to me.
15:03fogus_I like (range 046113200)
15:04the-kennyokay
15:04chouserfogus_: noooo...
15:04duncanmtechnomancy: is your site down? i'm having trouble installing SLIME from ELPA
15:04drewrfogus_: :-)
15:05fogus_chouser: You made the point though... it's not often that you'll see those huge constants except in toy code
15:05devlinsffogus_: I don't get it
15:05fogus_,(count (range 046113200))
15:05clojurebot10000000
15:06fogus_devlinsf: ^^^^^
15:06devlinsffogus_: Huh? Is it an overflow?
15:06chouseroctal :-P
15:06drewrdevlinsf: not base 10
15:07devlinsfOh, okay
15:07devlinsf,(range 08000)
15:07clojurebotInvalid number: 08000
15:07chouserread support for octal should look more like #octal:2342
15:07devlinsfGot it
15:07drewr,0xfff
15:07clojurebot4095
15:08drewr,0777
15:08clojurebot511
15:08fogus_,(range 010)
15:08clojurebot(0 1 2 3 4 5 6 7)
15:09chouser,(+ 1 36rHello)
15:09clojurebot29234653
15:09fogus_This is like modern day calculator curse words
15:09chouserheh
15:10devlinsfchouser: is there a shortcut for 2r1111
15:10chousershorter that "2r"? I don't think so
15:10devlinsfWell, something that implied binary
15:11devlinsfSo it looks special
15:11chouseryeah, I don't think so.
15:11devlinsfHmm, okay
15:11devlinsfJust the EE in me
15:12chouserLooking at the code now. The answer is "no"
15:14chouserbut you can use a capital instead or r or x
15:16fogus_Where does the zero-prefix for octal come from anyway? C? Fortran?
15:16devlinsfI'd guess C
15:16chouserC at least, if not before
15:17fogus_I guess my question is what's the rationale?
15:18chouserrm, 8r377 is smalltalk
15:18chouserhrm
15:18chouserpython3 uses 0o377 ...doesn't seem like a good idea to use ohs in numbers
15:18alexykhi guys -- anyone used congomongo?
15:19devlinsffogus: Wikipedia doesn't have anything :(
15:19devlinsffogus_: Wikipedia doesn't have anything :(
15:19fogus_Yeah, depending on your font, 0O010 could be a headache to look at in Python
15:20fogus_devlinsf: Yeah, that's where I tried first
15:20jasappalexyk: I use it a bit
15:20devlinsfMaybe the 0x is an seembly holdout?
15:20devlinsf*Maybe the 0x is an assembly holdout?
15:21defn`Easiest, simplest way to get a basic blog set up with clojure syntax highlighting?
15:21defn`Preferably something that I can just use out of the box without extra config.
15:21fogus_defn`: Github?
15:22defn`fogus_: ?
15:22the-kennydefn`: gist.github.com
15:22fogus_defn`: Like this http://github.com/raganwald/homoiconic
15:22defn`oh duh, i didn't think of that!
15:22defn`i was hoping to put it on my domain
15:23defn`but i could just redirect i guess
15:23alexykjasapp: I'm saying (:use somnium.congomongo) and it can't find it, although the jar is on the path.
15:23the-kennydefn`: You can use github-pages :) If you're a premium member, you can set CNAME-Values too.
15:23chouserI think I've seen github gists embedded in blog pages
15:24chouserclojure.org uses a javascript thingy
15:24fogus_I embed gists in my blog
15:24technomancydefn`: M-x htmlize-region is awesome if you blog from Emacs
15:24chouserfogus_: probably where I saw it then. :-)
15:25duncanmwhat's the difference between :use and :require again?
15:25the-kennyfogus_, chouser: http://github.com/blog/122-embedded-gists
15:25fogus_defn`: I use this cool WP plugin that lets me wrap the code in a tag and if a gist doesn't already exist it creates one and links to that
15:25Chousukeembedded gists are not so nice. they require javascript and just *disappear* if you don't have it enabled :P
15:26Chousukeit's pretty confusing to read blog posts stating "here's the code" when there's nothing.
15:26devlinsfduncanm: use mixes all of the functions into the namespace. require imports them and lets you alias them
15:27devlinsfduncanm: require helps avoid collisions. see str-utils2 for an example of a lib that is better reuire'd than use'd
15:27jasappalexyk: is that in the ns macro?
15:27fogus_Chousuke: The plugin I use takes care of that... I wish I could remember the name without having to log into my blog admin :(
15:27alexykyeah
15:27alexykI'm using it outside the macro, can I?
15:29jasappI'm not sure I understand exactly, but if it's outside the ns macro, you want use the function, not use the keyword.
15:29defn`fogus_: that is cool
15:30fogus_defn`: I use this http://blog.kno.at/tools/highlight-source-pro/
15:30alexykjasapp: ah ok, am very new to clojure :) in ns works
15:30jasappalexyk: and you'll also want somnium.congomongo to be quoted
15:31alexykjasapp: single quote in front, right?
15:31fogus_defn`: Whoops, that's not right. I use http://pomoti.com/gist-it
15:32alexykfogus_: "Basically, that problem usually happens with those who ‘programming-bloggers’ are the main activity when not sleeping." :)
15:35alexykwhat do people use for SQL? anything prettier than raw jdbc?
15:36drewralexyk: for simple cases, c.c.sql suffices
15:37chouserI continue to be intruiged by http://www.gitorious.org/clojureql/
15:37chouserhaven't actually used it thought
15:37chouserthough
15:37chouserI'm in nosql land now
15:37drewrchouser: +1
15:37drewrcql is really good, I just haven't had time to write a mssql backend
15:38alexykdrewr: who cares about MS :) postgres is all I need
15:39alexykchouser: I have an abstract system where I try different backends. Tried BDB and Mongo, but Postgres will do too.
15:40chouserif you're not writing sql-like queries in your app code, clojureql is probably the wrong level
15:40fogus_chouser: Which nosql?
15:40chouserwriting our own :-)
15:40drewrnice
15:41fogus_NIH! ;-)
15:41chouserI was skeptical, but came around. I think we have sufficiently compelling reasons for not building on anything that's out there right now.
15:41fogus_chouser: In clojure?
15:42drewrall the nosql tech is so young
15:42drewrI've been impressed with cassandra but it's not quite there yet for our needs
15:42chouserfogus_: clojure, C++, Java plus some jruby for testing, a custom query language, and no doubt eventually php bindings.
15:45somniumalexyk: I've used it :)
15:46alexyksomnium: works nicely! :)
15:46alexyknone of the ORM headaches from Scala... since not much types enforcement in here :)
15:47rhickeychouser: sorry, away for a bit - yes, if value returned by error-handler fails validation just put in normal error list
15:47somniumalexyk: yes, json format fits clojure's structures well. unfortunately I can't use it for my current project :( but I'm glad its useful to some people
15:49alexyksomnium: there's a competing project on github, by gilbertl, did you see that?
15:49somniumI'm not sure that we're competing :) We both use an open source language to wrap an open source driver for an open source database
15:50alexyksomnium: you are competing for users! :)
15:50chouseramazing amount of complexity packed in here. :-/ when to skip releasePendingSends()?
15:51alexykok, alternative... any idea of the differences?
15:53chouserskip releasePendingSends() even if the error was handled by an error-fn, right?
15:54rhickeyhmmm
15:54somniumalexyk: I did look at it, I suspect its a bit slow, since it traverses maps with clojure.walk to handle keywords. Though I kind of cheated and wrote a little java class to do that.
15:54duncanmtechnomancy: i keep on seeing 'failed to download clojure jars' when i run M-x slime on a fresh machine
15:54alexyksomnium: you have a better readme, so I picked yours. :)
15:54somnium:)
15:55chouserif the action throws something, you'd be surprised to find some 'sends' go out but not others, wouldn't you?
15:55alexyksomnium: I have a 70 GB database with 100M twits, let's see how you can handle *that* :)
15:56rhickeychouser: which went out?
15:56chouserthough if a watcher fails, you might be surprised if any sends are held back.
15:56somniumalexyk: it can create IPersistentMaps quickly, but I guess you'll run out of ram pretty quickly with that load :)
15:56alexyksomnium: is there any tuning I must/can do? I have a 64 GB RAM box for this job
15:57chouserif your action does: send 1, throw, send 2 ...1 will go out if released, but 2 would never have been queued
15:57somniumalexyk: mongo doesn't support concurrent reads until 1.4, + deftype and defprotocol make it even faster, so I'm kind of waiting for the next release
15:57alexyk35 GB are data, 35 GB indexes
15:57alexyksomnium: you mean 1.1.4?
15:57somniumalexyk: yes 1.1.4
15:57alexykwhat are deftype and defprotocol?
15:58somniumalexyk: new performance enhancing clojure features, as for mongo, I guess you'll want to shard it, but the driver won't help with concurrency right now :(
15:58kotarak_ato: you are the clojars guy, right?
15:59alexyksomnium: java driver or clojure wrapper?
16:00rhickeychouser: ah, ok, so, never queued, not really missed. It seems there could be no correct default policy there, but currently we eat on error, so let's keep that. I guess a composite return could tell us what to do...
16:01somniumalexyk: well, the clojure wrapper is very threadsafe, but to get a performance boost from concurrency you'll need a connection pool to n databases
16:01somniumI would check the java driver to see if it offers any support for that
16:01chousera composite return could also allow nil to mean no change to agent value, which would be handy for many minimal examples.
16:01alexyksomnium: ok
16:02rhickeychouser: how so? nil could be the new value
16:03rhickeyI'm not sure I follow the problem with returning what you are handed
16:03rhickeydo you want to avoid the validation etc?
16:04chouserNo, it's not a big problem, but I expect a lot of simple cases to end up with error fns like #(do (prn %2) %1) instead of just prn
16:04chouserreal-world code will have more complex handlers and returning an explicit new value won't feel awkward there
16:05technomancykotarak: _ato is on aussie time IIRC, but I'm working on the project with him
16:05chouserbut I thought you were suggesting error-fn return {:pending-sends :release, :new-value foo} or something, in which case nil could mean no change.
16:05rhickeyyeah, I wouldn't worry, people will write one handler they like and reuse
16:06chouserok
16:06defn`poor s_e_t_h and his failed clojure blog post
16:06kotaraktechnomancy: ah. Ok. Are there special requirements on the filenames copied? specifically: does the pom need to be called "pom.xml" or could it also by "foobar-1.2.0.pom.xml"?
16:06rhickeychouser: nil for the entire return? would that relase sends?
16:07chouserI ... uh, I dunno. I guess I would think not.
16:07technomancykotarak: I don't see "pom.xml" hardcoded in, so I suspect your longer version would work. give it a try.
16:08ordnungswidrigclojure compiler error message is driving me nuts. the file with the namespace a.b must go in /a/b.clj right?
16:08chouserreleasing sends seems like something you want only when things are working "normally"
16:08kotaraktechnomancy: ok, will try.
16:08chouseran action can always try/catch itself if it's expecting errors
16:09ordnungswidrighmm, are dashes allowed in ns names? a-b.c-d ??
16:09chouserordnungswidrig: yes, but are _ in file and directory names
16:09rhickeychouser: yeah, until you think about the exception conveying enough info for the handler to fabricate a valid work step. The biggest problem is not knowing how far through any sends you've gotten, as you mentioned before
16:09ordnungswidrigchouser: thanks!
16:10rhickeyreally, any action that sends needs to have its own handler, even if it ends up rethrowing
16:10chouserhow do erlang and scala do this?
16:10rhickeyso, let's just not release, and have a single return of new state - you can do an identity test to avoid validation/watchers
16:11rhickeychouser: erlang is fail == die
16:11chouseroh
16:11chouserI assume neither hold "sends" at all?
16:11rhickeywith death notification and restarts
16:12chouserwe do notifyWatches on an action, even with the value is unchanged. You want to withhold notification if the error-fn makes no change?
16:12rhickeyso you just have this chain of death notification links
16:12ordnungswidrigAnybody seen this with slime/swank: error in process filter: Symbol's function definition is void: swank-clojure-slime-mode-hook
16:13chouseralso, is it really worth it to you to have me write this when all I do is pester you with every little decision. ;-)
16:13rhickeythat has toggled back and forth a few times, note the boolean return on setState
16:13ordnungswidrigI'm using slime from elpa and maven swank-clojure 1.0-SNAPSHOT
16:14chouserrhickey: yeah, I noticed.
16:14rhickeyI think it was your use case that swapped it last time :)
16:15chouser:-)
16:15rhickeya countdown watcher or something
16:15technomancyordnungswidrig: did you install swank-clojure or just slime?
16:16technomancy(in elpa)
16:16ordnungswidrigboth
16:16rhickeyin some sense, a watcher is like a permanent pendingSend, so they should have the same policy
16:16ordnungswidrigI suppose elpa takes precedence on debians slime
16:16chouserexcept they happen synchronously. But yeah, I definitely see your point.
16:17technomancynever used debian's slime; they could be conflicting
16:17hiredmanwoa
16:17hiredmantechnomancy: you've seen javagems?
16:17rhickeyso, no watchers on identical state
16:17chouserit seems a bit odd that an error-fn could change the state of an agent because a watcher threw something
16:17ordnungswidrigtechnomancy: I think it an outdated swank-clojure that maven is using. I try starting the repl by slime
16:18rhickeyI'm happy having watcher errors go into the normal list
16:18rhickeyreally, a watcher that can throw is bogus
16:18chousermy main complaint about the normal list is how it poisons the agent
16:18chouseryes
16:18rhickeybut, I'm sure people want to route all problems to a single place
16:19chouserbut routing errors seems a bit different than fixing up an agent state
16:19rhickeyor there could be a watcher-error-handler
16:20ordnungswidrigtechnomancy: strange. slime starts a clojure repl but swank-clojure-project fails on missing clojure libs
16:21chouserwather-error-handler return values would be ignored instead of updating the agent
16:21rhickeythat's probably easier architecturally for us, and makes more sense = would be passed exception ony, ignored return
16:21chouserbut could default to be the same as the normal error-fn?
16:21rhickeyno
16:21rhickeydifferent args
16:22chouserno state
16:22rhickeyright
16:23rhickeyin fact, if no watcher error handler provided - I'd prefer to ignore them
16:23chouserok!
16:23rhickeycouldn't ignore before because there would be no way to find out about the failures
16:23ordnungswidrigtechnomancy: got it. had to run mvn dependency:copy-dependencies first :-)
16:24rhickeynow user choice
16:24chouserright
16:24chouserwe can consider changing the default for action errors to match at some later point. :-)
16:25rhickeychouser: well, there might be user code already using agent-errors
16:25chouserright
16:25chouserbreaking change. not for now.
16:25rhickeyright
16:25chouser:error-handler is better than :error-callback
16:25rhickeyyes
16:25kotaraktechnomancy: it works! the name is not interesting. clojuresque 1.1.0 pushed to clojars. :) (formerly known as clj-gradle)
16:26duncanmtechnomancy: sigh, am i doing something stupid? M-x slime isn't workign for me ;-P
16:27chousersetWatcherErrorHandler in ARef instead of Agent?
16:27ordnungswidrigduncanm: what's your error?
16:27duncanmordnungswidrig: failed to download clojure jars
16:28duncanmoh doh
16:28duncanmnow it's working
16:28ordnungswidrigduncanm: *g*
16:28rhickeychouser: yes, and IRef
16:28rhickeyactually, no
16:29rhickeythis is just an async problem
16:29rhickeyall sync things can just let exceptions flow out
16:29rhickeyso, on Agent only
16:30chouseryes, ok.
16:32technomancyhiredman: yeah... the authors emailed me. it's an interesting project, but I don't think it's that relevant to clojure.
16:32chouservalidator throws: error-fn is called, pending sends are dropped.
16:33rhickeychouser: sounds right
16:33chouserbut ... watchers are still triggered if error-fn changes the state.
16:33krumholt__why does (eval (fn [] "test")) not yield "test" as a result? instead it returns what i would expect from (eval '(fn [] "test")). could someone explain that to me?
16:35chouserand sends queued by error-fns and by watchers triggered by error-fns are ... released? disallowed!? this all feels a bit wrong.
16:35somniumkrumholt__: eval != invoke, try ((eval '(fn [] :foo)))
16:36chouserkrumholt__: (fn ...) returns a value, a function. Eval'ing a value just returns the value.
16:37chouserkrumholt__: or: (eval '((fn [] :foo)))
16:37krumholt__oh ok thanks. a function is a value eval returns that value makes sense thanks
16:37rhickeychouser: let's break it down
16:38rhickeythe reason to allow the handler to 'fix' the state is because re-queueing a new action will change the (possibly important) order
16:38chousernot sure what that means, but error-fn inserting a state change feels like the source of complexity to me
16:38chouserheh
16:39rhickeypending sends may be an incomplete set, there's no way to know, so if your action sends and might throw, you should have your own internal handling
16:39chouserok, yes. There's no better way to indicate which sends you want to do than your own appropriately grouped try/catches
16:40chouserin the action
16:40rhickeyso pending sends have to be chucked, but the one case you couldn't self-handle is validation failure
16:41chouservalidators can't send because they're supposed to be pure
16:41chouserso no pending issue there
16:41somniumquestion to vimclojure users: is there a recommended way to manage the classpath for standard ./src ./lib ./build project structure?
16:42kotaraksomnium: the launcher adheres to CLASSPATH env var, the new one also reads a .clojure file in the current directory.
16:42chouserdoes the same apply then to error-fn? can be a pure fn of the state and exception but shouldn't throw or send?
16:43rhickeyvalidation failure is a programming error, so finding out about about it is most important
16:43kotaraksomnium: you can also set CLOJURE_EXT to load jars in that directory
16:43rhickeyerror-fns aren't pure, in that they may frequently do queue I/O
16:44rhickeybut people use agents as queues...
16:44chouseris an error-fixer different than an error-queuer?
16:44rhickeyhandler implies both
16:44chouseryes I know
16:45chouserI'm wondering if that's an bad conflation
16:45ikitatI'm at a loss how to make use of clojure.test/use-fixtures http://paste.pocoo.org/show/152745/ gives me "Unable to resolve symbol: x in this contex"
16:46rhickeyI think if it is clear - "I fixed this" vs "it never happened", then other decisions become easier
16:46hiredmanikitat: I don't know anything about test-is
16:46hiredmanbut that looks like an issue of lexical v. dynamic scope
16:46chouserrhickey: ok, yes.
16:47rhickeyI fixed it - all messages go out, it never happened - none do
16:47chouseryes
16:47somniumkotarak: where can I read on .clojure file in the current dir? I was thinking of writing a alternate bash script similar to swank-clojure-project (locate build.xml/pom.xml and build classpath).
16:47hiredmanbut then again, I don't know what I am talking about
16:47somniumkotarak: btw, mine breaks if I open a random .clj file not already in CLASSPATH, so maybe I have something configured wrong
16:48rhickeyso, state identity is too weak
16:48chouserdo, do you indicate which you're doing by returning an = value, or is that too much magic
16:48chouseryeah
16:48rhickeyor at least unclear
16:48kotaraksomnium: it's not a bug, it's a feature. You can turn it off in the latest bleeding-edge.
16:48chouserif you didn't fix it, you have no new value to provide
16:49ikitathiredman, yeah, I figured that it's a scoping issue, the documentation for test-is isn't clear (to me) how this can be used
16:49somniumkotarak: I'm not qualified to have an opinion on bug/feature status at this point :) I'll try the bleeding edge, does it work with new branch?
16:49chouserI guess a single handler might need to look at the exception to know what it's doing, so providing separate fixer-fn from logger-fn is bad
16:49rhickeybut as your use case indicated, sometimes a valid work step doesn't change the state
16:49kotaraksomnium: yes, but the highlighting is not 100% up-to-date.
16:50hiredman,(doc clojure.test/user-fixtures)
16:50clojurebotGabh mo leithscéal?
16:50kotaraksomnium: this will fix your problem: http://bitbucket.org/kotarak/vimclojure/changeset/f80ecd0532b7/
16:50rhickeyI think return the exception to indicate 'didn't happen', else state and all messages go
16:50hiredman,(doc clojure.test/use-fixtures)
16:50clojurebotNo entiendo
16:50chouserhm!! return the exception.
16:51rhickeyacts as an implicit notFixed flag
16:51chouserjust too unlikely that someone wants to store that particular exception in the agent? better than re-throwing it?
16:51kotaraksomnium: ad parsing poms: I don't see this is as the responsibility of vc. The user has to setup his classpath with the ng-server. This can for example done via some target for maven, ant or gradle.
16:51kotaraksomnium: parsing poms is a nightmare with vim.
16:51rhickeywe don't want rethrow that's for sure, it's still handled
16:51rhickeyjust not fixed
16:52chousertreat that particular exception different from any other exception then?
16:52rhickey?
16:53chouserif the error-fn returns an exception other than the one passed in, that becomes the new value of the agent.
16:53kotaraksomnium: as for the .clojure, I must confess, that I haven't pushed the changeset, yet. sorry. My mistake.
16:53rhickeywe could have a return-this-value-if-not-fixed, but seems a bit much
16:53chouseryes, I can see that.
16:53hiredmanikitat: it looks like a fixture is just a normal function
16:53ikitatthe only usage of use-fixtures in clojure-contrib seems to modify *ns* and that is the one and only case I can find.
16:53somniumkotarak: ah ok, well I threw together an alternative nailgun launcher that just exports command line args to classpath, and that seemed to work
16:53hiredmanso you will need to setup x as a dynamically rebound var
16:53rhickeythe other option is the agent itself
16:53chouserheh
16:54rhickeybut people get so confused already between the agent and its state
16:54hiredmanikitat: http://clojure.org/vars
16:54chouserI'm ok with the exception itself, esp. for an experimental feature
16:54rhickeywhat is getting passed - the agent or its state?
16:55somniumkotarak: oh, my idea wasn't to parse .pom, just find it, and then add ./src ./lib etc to classpath, then launch nailgun, for convenience
16:56chouserseems like if you've got an agent managing exceptions as values *and* your actions throw exceptions *and* you've got an error-fn *and* you want to fix up the error, well, you already used up all your grace.
16:56chouserrhickey: patch in assemble passes agent to error-fn, but I think that's wrong, should be state.
16:57chouserin assembla
16:57rhickeyit's not exceptions as values, its the identical exception that was passed to the handler, not by type at all
16:57chouseryes
16:57kotaraksomnium: ah. Ok. I just have CLASSPATH=src:classes CLOJURE_EXT=lib and I start the ng server from the project root. Universally working for all my projects. :)
16:57rhickeyso unless the agent is going to use that specific exception object as its state...
16:58chouserright
16:58chouserloony
16:58rhickeychouser: this was a simpler idea when it was to be a queue
16:58rhickeyno question about the activity of the handler itself
16:59rhickeyfor instance, we're still not good if the handler wants to send the fix as a new action
16:59chouserok, and watchers aren't fired until after the error-fn, and only if error-fn doesn't return the sentinel
17:00chouserthe handler can either send (if it wants it queue at the end) or do an action directly, can't it?
17:00ikitathiredman: it seems the right thing to do is (def x) (def y) (use-fixtures :each ... (binding [x 2 y 3] ... ) I was hoping to have a way to not bleed x and y into the namespace
17:00rhickeychouser: a reentrant send? where does it go?
17:01somniumkotarak: ok, that is simpler. thanks
17:01Anniepoohmm... ok, beginner question
17:02chouserif error-fn does a send and returns a fixed-up value, all the actions's queued sends and the error-fns sends all get released, don't they?
17:02rhickeyit will be in pending sends, which aren't going out since not fixed
17:02chouseroh, you're saying if error-fn wants to send but not fix
17:02chouserbleh
17:02rhickeyI guess it would have to know to return the existing state
17:03rhickeyalso, handed only the state, to whom does it send?
17:10ordnungswidrigI have lengthy call of ((-> f wrap1 wrap2 wrap3 wrap4) arg) where wrap* are higher order functions that wrap a given function. How can I trace invokations of the wrappers easily?
17:12hiredman(doto prn)
17:12chouserrhickey: *agent* since we're in-thread
17:16ordnungswidrighiredman: say how?
17:17rhickeychouser: it seems like there are more facets - like would people still want to be able to neuter the agent for further actions? what about other things in its queue
17:17hiredmanordnungswidrig: or something like that
17:18ordnungswidrig*g* I'll try
17:18hiredman((fn [x] #(doto (x) prn)))
17:19hiredman,(-> p ((partial partial inc)) ((fn [x] #(doto (x) prn))))
17:19clojurebotjava.lang.Exception: Unable to resolve symbol: p in this context
17:19hiredman,(-> 1 ((partial partial inc)) ((fn [x] #(doto (x) prn))))
17:19clojurebot#<sandbox$eval__5995$fn__5997$fn__5999 sandbox$eval__5995$fn__5997$fn__5999@15fc68a>
17:19hiredman,((-> 1 ((partial partial inc)) ((fn [x] #(doto (x) prn)))))
17:19clojurebot2
17:19clojurebot2
17:20rhickeyalso, if you 'fix' in order to send a true fixing action, other messages and the watchers will go out
17:22michaeljaakahi, how to easily make passing parameters to function by symbols?
17:22michaeljaakaI have looked into core.clj
17:22rhickeyin a queue model, there'd be no immediate fixing, and thus no sends at all, but we'd have to send the agent itself since dequeuing on another thread
17:22ordnungswidrighiredman: thanks.
17:23michaeljaakaand found something like (defn me[ & args] (let [ x (apply hash-map args)] ... and later (:sym x)
17:23michaeljaakais it ok?
17:23michaeljaakaor is there any easier way
17:24michaeljaakabtw. I was activly writing to clojure google group but my last two post didn't appear - am I banned there, spamming there or something?
17:25hiredmanmichaeljaaka: you can use straight up map destructuring
17:25hiredman~destructuring
17:25clojurebotdestructuring is http://clojure.org/special_forms#let
17:27michaeljaakaok, I will try it again, last time when was trying to play with function parameters nothing worked for me ;(
17:34michaeljaaka"Clojure supports abstract structural binding, often called destructuring, in let binding lists, fn parameter lists,"
17:34michaeljaaka(defn testfun[ & a :as e ] (println (:dom a)))
17:35michaeljaakaexpressions given in example doesn't work for fn parameter lists
17:35hiredmanmichaeljaaka: then read the example again
17:36michaeljaakaok :) (note: I understand examples for let binding)
17:36djorkmichaeljaaka: let/fn have the same destructuring rules
17:37hiredmanmichaeljaaka: you are missing en tire set of []
17:38hiredmanso obviously you did not read the example closely enough
17:39michaeljaakahmmm it is obvious that for let
17:39michaeljaakaI have to pass second []
17:39djork,((fn [[a b & c :as d]] (println a b c d)) [:foo :bar: bat :baz])
17:39clojurebotInvalid token: :bar:
17:39michaeljaakawhich initializes left form
17:39djorkoops hah
17:39devlinsfHey, how do I create fields in a gen-class?
17:39djork,((fn [[a b & c :as d]] (println a b c d)) [:foo :bar bat :baz])
17:39clojurebotjava.lang.Exception: Unable to resolve symbol: bat in this context
17:39djorkI fail it
17:39djork,((fn [[a b & c :as d]] (println a b c d)) [:foo :bar :bat :baz])
17:39clojurebot:foo :bar (:bat :baz) [:foo :bar :bat :baz]
17:40alexyksomnium: ping
17:40djorkmichaeljaaka: the rules for let and fn bindings are the same
17:40alexykI get integers back from json as 2.3275269E7, how can I convert them back to ints?
17:41alexykdo we have longs, too?
17:41michaeljaakayes, I have noticed now
17:41michaeljaakathat I was missing double []
17:41michaeljaaka[[ all goes here ]]
17:42somniumalexyk: hi
17:43alexyksomnium: so I'm wondering about getting back ints and longs from json ^^
17:43alexykfrom mongo
17:43alexykalthough it looks like mongo returns floats
17:44alexykhow in clojure do you check the type of x?
17:44devlinsf(class x)
17:44alexykyep
17:44devlinsf,(class {})
17:44clojurebotclojure.lang.PersistentArrayMap
17:44devlinsfOoops
17:45alexykso if I do (def x <very long int>) will it make it long?
17:46alexykI see if I do (def x (long <very long int>)) then it does
17:46the-kenny,(class (bigdec 1e100))
17:46clojurebotjava.math.BigDecimal
17:46hiredman(class 1e100M)
17:46hiredman,(class 1e100M)
17:46clojurebotjava.math.BigDecimal
17:47alexykI just care for long and int for now :)
17:47alexyk(long 2.173617511E9)
17:47alexyk,(long 2.173617511E9)
17:47clojurebot2173617511
17:47alexyk,(int 2.173617511E9)
17:47clojurebot2147483647
17:48alexyksee wha'am sayin'?
17:48alexykI get back floats from JSON and need to make them either int or long again
17:48alexykand I don't want to waste bits
17:48alexykI guess I'll just use longs for the long ones :)
17:49somniumalexyk: I'm not sure, I just tried a test and it came back as expected
17:49alexyksomnium: do you see integrals? I have floats for twit ids and user ids
17:49alexyk:id 2.173617511E9, ...
17:50somnium-> (insert :nums {:x (int 1)})
17:50alexykah, right, you do insert via clojure. I've used mongoimport.
17:50alexykAnd it made all numbers floating-point.
17:50somniumok, so not my fault I hope :)
17:50alexyksomnium: you're fine :)
17:51alexykI just wonder if you tried mongoimport-ed json
17:51hiredman:|
17:51hiredmanbest not to be doing float -> int/long conversions
17:52alexykhiredman: well, it's a cheap way to dodge the question for mongo, I guess. All the digits are there, at least.
17:52hiredman:(
17:52somniumhmm, java.lang.BigDecimals do get converted to doubles though
17:53somniummakes me want to rewrite the encoders in clojure even more
17:53alexyksomnium: what do defprotocol and deftype do which would speed it up?
17:53somniumI've actually taken to using strings and then (read-string) in clojure for sensitive numbers
17:53ordnungswidrigIs there a function to flatten nested lists? Or sth to convert sth to a one-element-list unless it's a list?
17:54somniumalexyk: check assembla and lots of discussion in the logs here and the mailing list
17:54alexyksomnium: ok :)
17:56michaeljaaka,(defn me[ { :keys [ one two ] } m] (println (:one m)))(me :one 2 :two 3 )
17:56clojurebotDENIED
17:56michaeljaaka,(defn me[ { :keys [ one two ] } m] (println (:one m)))
17:56clojurebotDENIED
17:57ordnungswidrigmichaeljaaka: you must not use defn
17:57michaeljaakaok :) I noticed :)
17:57michaeljaaka,(fn[ { :keys [ one two ] } m] (println (:one m)))(me :one 2 :two 3 )
17:57clojurebot#<sandbox$eval__6052$fn__6055 sandbox$eval__6052$fn__6055@1655d7e>
17:58michaeljaaka,((fn[ { :keys [ one two ] } m] (println (:one m)))(me :one 2 :two 3 ))
17:58clojurebotjava.lang.Exception: Unable to resolve symbol: me in this context
17:58michaeljaaka,((fn[ { :keys [ one two ] } m] (println (:one m)))( :one 2 :two 3 ))
17:58clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to keyword: :one
18:00michaeljaakawhy this is wrong?
18:01hiredman(:one 2 :two 3)
18:01ordnungswidrigmichaeljaaka: the form ( :one 2 :two 3)
18:01michaeljaakahow I should def fun so I have use (myfun :one 2 :two 3)
18:01michaeljaakaI don't want to play with clojurebot (ieave him alone)
18:02michaeljaakaI want just to write one stupid function :( I almost done writing cool program and ended with many args
18:02michaeljaakaand wanted to pass them with symbols
18:02michaeljaakato make it more readable
18:04somnium,(-> {:one 1} ((fn [{:keys [one]}] (println "one is" one))))
18:04clojurebotone is 1
18:05spuzHello, all, I've written an article about how I went about optimising my Clojure fractal renderer: http://developmentjungle.wordpress.com/2009/11/24/optimising-mandelbrot/
18:05michaeljaakasomnium: it is cool
18:06spuzIt's most likely that I'm still doing newbie things so any and all feedback is very welcome!
18:06michaeljaakabut how to call it in terms of usage (myfun :one 1 :two 2)
18:06michaeljaakaetc.
18:07somniummichaeljaaka: easiest would be to use defnk in clojure.contrib.def
18:07michaeljaakasomnium: anyways thanks, you explained how to use symboled binding
18:07michaeljaakaoh, so destructuring doesn't help here
18:07michaeljaakajust I wanted to know that
18:07somniumit does, defnk is a macro that destructures for you
18:08hiredmanI wish people would just use map destructuring
18:08somniumyou have to do [arg1 ... argn & kwargs]
18:08hiredmanintead of whatever macros, or apply hash-map
18:08hiredmaninstead
18:09michaeljaakaohh, so by default hash-map is a pure solution
18:09michaeljaakajust wanted to know that
18:09michaeljaakaapply on hash-map
18:09somniumhiredman: people like sugar?
18:09hiredmanmichaeljaaka: no!
18:09hiredmanapply hash-map is horrible
18:10hiredman,((fn [{:keys one}] one) {:one 1})
18:10clojurebotjava.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
18:10hiredman,((fn [{:keys [one]}] one) {:one 1})
18:10clojurebot1
18:10hiredman:P
18:10somniumhiredman: the nicest thing about defnk is the dryness, default args and automatic symbols in ~@
18:10michaeljaakabut is used in core.clj
18:10michaeljaakai like to learn by example
18:11hiredman:|
18:11hiredmanspuz: looks nice
18:11michaeljaaka,( (fn[ { :keys [ one two ] } m] (println one)) [ :one 2 :two 3] )
18:11clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--6103$fn
18:11michaeljaakadoesn't work
18:12hiredmanfor many many reasons
18:12hiredmanmichaeljaaka: I think you should become more familar with more basic things before you start with destructuring
18:13michaeljaakawell for example?
18:13hiredmanfor example, [:one 2 :two 3] is a vector
18:14ordnungswidrigspuz: nice post.
18:14hiredmanthe fn you created there takes two args, but you only passing it a single vector
18:14hiredmaneven if the fn took one arg, you trying to do map destructuring on a vector
18:15spuzhiredman: thanks, I think the main interesting part is digging into Clojure's internals with VisualVM. Of course I'm not an expert but I thought it would be useful to show my findings
18:16hiredmanspuz: yeah, exploring clojure's call tree++
18:17michaeljaakaok
18:19michaeljaakaI will just use
18:19michaeljaaka,((fn[ & a ] (let [ b (apply (hash-map) a) ] :one b )) :one 2)
18:19clojurebot2
18:19ordnungswidriggood night everyone
18:19michaeljaakabye!
18:19hiredmanmichaeljaaka: :|
18:19kzar<h1>I wonder what happens to the logs</h1></body></html>
18:19hiredman(hash-map) is a bug there
18:20michaeljaakaso it is in core.clj :)
18:20hiredmanno
18:20hiredmanthe idiom is (apply hash-map …
18:20hiredmannot (apply (hash-map) …
18:20hiredmanseriously
18:21michaeljaakaah
18:21michaeljaakaok
18:21hiredmanyou need more practice just reading and understanding clojure code
18:21michaeljaakain core.clj is hash-map not (hash-map)
18:21hiredmanI would suggest sitting down with project euler or similar
18:21michaeljaakayeah, practicing :) just writing google map reduce in clojure
18:21michaeljaakaalmost done ;)
18:22hiredmandon't worry about destructuring or keyword args till you can read and write code
18:22hiredmanmichaeljaaka: I can almost guarantee it will be full of bugs if your interactions with clojurebot are a representative sample
18:22michaeljaakawith true distribution between machines
18:23michaeljaakano problem ;) I'm just learning language, often just asking and making stupid questions
18:23michaeljaakabut finally gots alwasy this "oh this is it"
18:24hiredmanjava.lang.IllegalStateException: case already refers to: #'clojure.core/case in namespace: ring.jetty (jetty.clj:1)
18:24hiredmangrrrr
18:26_atomichaeljaaka: btw, something I've noticed with your code is the spacing. Normal Clojure style is to do: (defn [arg1 arg2] ...) rather than (defn[ arg1 arg2 ] ...) which you seem to be doing. Not a huge deal but if you get used to the same style everyone else uses than it will be easier for you to read their code and for them to read your code. :-)
18:27michaeljaakayeah, I must change it, the same is with writing doc for function, I need to learn writing doc before fn binding
18:27michaeljaakafn params
18:27the-kennyAre there some "coding conventions" for clojure like for Common Lisp?
18:31KirinDave1How does one go about converting a set to a list?
18:31_atothe-kenny: not specific clojure ones AFAIK. The conventional style is basically the same as Lisp/Scheme style though: http://mumble.net/~campbell/scheme/style.txt
18:31_ato,(seq #{1 2 3})
18:31clojurebot(1 2 3)
18:32KirinDave1Ah, I see.
18:32the-kenny_ato: Yeah, I know the conventions for Lisp, but I think Clojure needs some improvements (hashmaps, for example)
18:32_atoKirinDave1: ^
18:32the-kennyMaybe I'll start a page in the Wiki
18:32the-kenny:)
18:33_atothe-kenny: good idea. :-) Do you mean either breaking the line or using commas with hashmaps: {:k1 :v1, :k2 :v2} to pair keys and values?
18:35the-kenny_ato: Yeah, and also how to write and indent hashmaps with one element per line.. clojure-mode seems to have problems with "{\n:foo 42\n}" so I'm using "{:foo 42\n:bar 23} currently.
18:35the-kennyI'm interested in what other people think and use
18:36ChousukeI think {:foo 'bar\n :zonk ...} is the most common
18:36Chousukegenerally, you don't separate the opening bracket from the first item
18:37_atoyeah, I tend to treat () [] {} #{} etc all the same way. no whitespace or newlines at the start or end
18:37Chousukesome people seem to like writing function definitions like (defn foo[params] ...) but I think that's just misleading :)
18:37Chousukeit makes foo[bar] look like some kind of special syntax
18:38the-kennyYes, it reminds me of C++ or Java.
18:40KirinDave1,(isa? #"" java.util.regex.Pattern)
18:40clojurebotfalse
18:41KirinDave1(class #"")
18:41KirinDave1,(class #"")
18:41clojurebotjava.util.regex.Pattern
18:41KirinDave1So uh, how do I know if I have a regex?
18:41Chousukeheh, that lisp style guide says to avoid point-free style :P
18:41_ato,(instance? #"" java.util.regex.Pattern)
18:41clojurebotjava.lang.ClassCastException: java.util.regex.Pattern cannot be cast to java.lang.Class
18:42_atodid I get backwards
18:42_ato,(instance? java.util.regex.Pattern #"")
18:42clojurebottrue
18:42KirinDave1Ahh
18:42KirinDave1Yeah I guess that's it then.
18:42KirinDave1Weird, I thought that isa? did that too.
18:42_ato,(isa? java.util.regex.Pattern #"")
18:42clojurebotfalse
18:44_atoI agree with generally avoiding point free style. I don't mind the occasionally partial, or comp with just two functions in it, but if you chain together a whole line of comps and partials it's really hard to understand what's going on
18:45Chousukethe problem is made worse by the fact that point-free style in clojure is just verbose :P
18:51KirinDave1:\
18:51KirinDave1The most awkward part of learning a new language is in those first concrete modules you write and you go ":\ Man I wrote this the wrong way."
18:52tomojis it evil to rely on hashCode for vectors being consistent across JVM executions?
18:53Chousukeyes?
18:54ChousukeIIRC the contract for hashCode specifically states that, but I'm not sure.
18:54tomojyeah the contract specifically states that it doesn't need to be consistent, but it seems that it is for vectors
18:55ChousukeThat seems very likely to break.
18:56tomojguess i can prn and hash that string.. hmm
18:58hiredmanhmmm
18:58hiredmanactually
18:59technomancyclojurebot: style is http://mumble.net/~campbell/scheme/style.txt
18:59clojurebotAck. Ack.
19:00technomancyhiredman: we're coming up on clojurebot's first birthday soon, aren't we?
19:02hiredmanclojurebot: if you where a super hero what would your origin story be?
19:03hiredmanlong sentences like that peg the fuzzer hard
19:03technomancyis it still thinking?
19:03hiredmanyep
19:04somniumis he smart enough for s/where/were?
19:04hiredmanjava's cpu time is falling
19:04hiredmanhuh
19:04hiredmanout of heap space
19:04hiredman:(
19:05the-kenny:(
19:05hiredmanclojurebot: your origin story?
19:05clojurebothttp://clojure-log.n01se.net/date/2008-11-21.html#13:04
19:05hiredmanhuh
19:05technomancyoh, my clojure birthday was last week!
19:06technomancyI thought it was this week. time to cancel the party. =(
19:06the-kennyIf clojurebot gains the ability to modify his own source code, he will surely become skynet
19:06hiredmanclojurebot: clojurebot |has| a lot of features
19:06clojurebotIn Ordnung
19:07somnium~terminator
19:07clojurebotexcusez-moi
19:08the-kennyclojurebot: You |will not| become skynet
19:08clojurebotIn Ordnung
19:08technomancy"so far it's hard to keep a bug alive long enough for a tracker to be useful. They tend to be fixed within a day or two, if not hours or minutes." <= from a year ago. =(
19:09_ato:(
19:10hiredmanclojurebot: you?
19:10clojurebotYou will not become skynet
19:10the-kennyclojurebot: Do you plan to evolve to skynet?
19:10clojurebotYou will not become skynet
19:11danlarkintechnomancy: ha!!
19:15somniumclojurebot: clojurebot |will| become skynet
19:15clojurebotAlles klar
19:17the-kennyOh no :(
19:17somniumits kind of scary he responded with Alles klar
19:20the-kennyJa, das stimmt.
19:20the-kenny;)
20:02carkhiredman: what are the pipes for when talking to clojurebot ?
20:02krumholt__,(((fn [r] ((fn [f] (f f)) (fn [f] (r (fn [x] ((f f) x)))))) (fn [f] (fn [n] (if (= n 0) 1 (* n (f (- n 1))))))) 5)
20:02clojurebot120
20:18hiredmancark: arbitrary predicates
20:18hiredmanclojurebot defaults to X is Y
20:18hiredmanbut with the pipes you can say X | Z | Y
20:18carkoh i see
20:19carkclojurebot: clojurebot?
20:19clojurebotclojurebot has a lot of features
20:19carkallright thanks =)
20:19carkdoes it do the "also" part automatically now ?
20:20carki mean, no overwriting existing definitions ?
20:22chouserrhickey: if we give up on handlers fixing state, whether queue or synchronous model, most of the complexity goes away. error actions always "never happened", no watchers, no sends
20:22hiredmancark: yes
20:23hiredmanyou can remove a definition if you know the exact tripple
20:23hiredmantriple
20:23carkah so i'll need to be sneaky when adding definitions aboutu you !
20:23carkthanks anyways =)
20:29Anniepoo,(set! *ns* "tacos for lunch")
20:29clojurebot"tacos for lunch"
20:30Anniepoo,(+ 1 2)
20:30clojurebot3
20:30Anniepoo8c)
20:32tomojmm tacos
20:32chouserwhat have you done!?
20:32chouser,`foo
20:32clojurebotsandbox/foo
20:32chouserhm
20:33Anniepoojust wondered if that crashed clojurebot
20:33AnniepooI'm using hiredman's sandbox for a thing I'm building
20:33tomoj(set! *ns* "foo") blows up for me
20:34tomojand *ns* is left unchanged
20:34Anniepoothrows a java exception, yet
20:34tomoj,*ns*
20:34clojurebot#<Namespace sandbox>
20:35tomojweird that you still get a return value
20:36AnniepooI'm still trying to find a better way to prevent an evaluation from making global changes than clojurebot uses
20:36Anniepooclojurebot does a macroexpand, then looks for 'bad forms'
20:36Anniepoothis seems iffy to me
20:36hiredman it is
20:36carkwhat's your use case for sandboxing ?
20:37AnniepooI'm trying to make an 'injectable code' server
20:37Anniepooyou send me a form, I evaluate it and send you the result
20:37carkdoes the injected code need to be fast ?
20:38Anniepoohmmm.... why, you know a slow way?
20:38carkyes =)
20:38Anniepoowhat's the slow way?
20:38carkdo your own lisp interpreter, only reuse the clojure reader
20:39carksounds like a lot of work, but it really isn't
20:39Anniepoothat might actually work
20:39Anniepooit's not as elegant as allowing arbitrary clojure
20:39AnniepooI could reverse hiredman's scheme, make a list of everything that's OK
20:40carkbut you have perfect control
20:40hiredmanyou could send the code to appengine to run :P
20:40hiredmanlet google worry about the sandboxing
20:40Anniepoowhat's appengine?
20:40hiredman~google appengine
20:40clojurebotFirst, out of 327000 results is:
20:40clojurebotGoogle App Engine - Google Code
20:40clojurebothttp://code.google.com/appengine/
20:40hiredmangoogles hosting thing
20:41Anniepooah, ok, sorry, didn't get it, yes yes
20:41hiredmanit's free up to a certain point
20:41hiredmanwhich is pretty cool
20:41Anniepoowell, I'm acutally not concerned about the java sandboxing, which, as you know, is pretty trivial
20:41Anniepooit's actually a bigger problem to sandbox the clojure
20:42Anniepooin an ideal world I'd make a new JVM environment for each session
20:42hiredmanyeah, but you can just ship the clojure code to google, and it's their problem
20:42Anniepooso if you ruin your environment it's your problem
20:42Anniepoono, I'm not worried about violating the java sandbox
20:43AnniepooI'm worried about somebody clobbering my clojure server
20:43hiredmanI know, but the clojure code can do whatever it wants on google's jvm in the sky
20:43hiredmangoogle limits execution time to something like 30 seconds
20:43hiredmanand has other limitations as well
20:43Anniepoook, I could do the same thing locally, spawn a jvm
20:43Anniepooand install a security manager, then eval the code
20:43carkmhh you can instanciate a clojure environment from java, so i guess you could do it from clojure as well, so i guess you'd get a new instance of the whole thing ?
20:44Anniepoothat works, but is massively inefficient
20:44hiredmanI bet shipping the code to google would actually be faster than ramping up a new jvm
20:44Anniepoogood point, cark
20:44Anniepooif you can do that
20:44Anniepoobut I haven't figured out how to
20:45Anniepoohow would I make a new environment? That's what I really want
20:45hiredmanmake a new classloader and load clojure.lang.RT
20:45Anniepooreally?
20:45AnniepooHmm....
20:45AnniepooOK
20:45Anniepoosounds like deep doings, but I'm up for it
20:47carkmhh nope =(
20:47carkhttp://markmail.org/message/madkidutwpp2yd44?q=thread:tx23zaxf77b6widh
20:49hiredmanI dunno about that, but clojure runtime is initilized via a static init block in RT
20:49Anniepoook, now gotta find some sorta docs on clojure.lang.RT
20:49hiredmanpffft
20:49hiredmandocs
20:52Anniepoo8cP Somehow reading the source code to RT strikes me as likely to induce paranoid schizophrenia or warts or soemthing
20:52hiredman*shrug*
20:55hiredman(== clojure.lang.RT (-> (ClassLoader/getSystemClassLoader) (.loadClass "clojure.lang.RT")))
20:55hiredmaner
20:55hiredmanuser=> (== clojure.lang.RT (-> (ClassLoader/getSystemClassLoader) (.loadClass "clojure.lang.RT")))
20:55hiredmanfalse
20:55hiredmanuser=>
20:58Anniepooooh, are you saying that if I call RT:load that's all I gotta do here?
20:59hiredmanpossibly
21:01Anniepoohmm... Ah, you're saying make a new classloader and then use it to load RT, which will make a 'new' RT class?
21:01AnniepooI wonder if that makes a memory leak
21:02Anniepooafter I've processed a few thousand of these I've got my memory full of class definitions of RT
21:03hiredmanuser=> (-> (ClassLoader/getSystemClassLoader) (.loadClass "clojure.lang.RT") (wall-hack-method :var [String String] nil "clojure.core" "+") (apply '(1 2 3 4)))
21:03hiredman10
21:03hiredmanuser=>
21:04hiredmanactually
21:06hiredmanyou'll want (proxy [ClassLoader] [(ClassLoader/getSystemClassLoader)])
21:06Anniepoook, I'm getting 10% of this, but will go do my homework. Keep talkin!
21:06hiredmanClasses can be GC'ed, but I forget the provisos
21:07AnniepooI'll find out how
21:07chouserclasses get GCed when their classloader gets GCed
21:07chouserI think
21:08hiredmanok, yeah, that is why you need the proxy
21:08hiredmanso you have an instance of the classloader you can let go of
21:08Anniepooah
21:08hiredmaninstead of the bare system classloader
21:09Anniepoonifty nifty!!!
21:09Anniepoothat's what I've been looking for
21:10hiredmanmaybe not
21:10Anniepoohmm, why not?
21:11hiredmanit looks like altering the metadata on the var named by clojure.core/+ from the new RT alters the meta data on the old one
21:11hiredman(implying they are the same)
21:11hiredman:|
21:12Anniepoo8c( not good
21:12hiredmanoh
21:12hiredmanI wonder if its a result of var interning from compile to runtime
21:12hiredmananyway, *shrug*
21:13hiredmanah!
21:13hiredmanyeah, it must be
21:13_atoare you trying to run two seperate clojure instances in the one JVM?
21:13_atohttp://gist.github.com/240818
21:13_ato^ that's what I was playing with the other day
21:14Anniepoowow, sweet, ato!
21:16Anniepoook, this looks promising.
21:17AnniepooSo, I wonder what the memory overhead will be for each of these instances I have laying around
21:18_atonote that you have to use java interop stuff to "talk" to the "inner" Clojure as they're completely segregated, the data structures in the outer clojure can't be passed directly to the inner one AFAIK. But you could of course write a function that prn's some code to a string then does a read-string and eval on it in the inner Clojure.
21:19Anniepooyes,
21:19AnniepooI'm going to be evaling a string anyway
21:19AnniepooI want to make a sort of 'rmi' for clojure
21:20Anniepooyou send me a string, I eval it (suitably sandboxed) and return the value to you
21:20Anniepoothe hard part is the 'suitably sandboxed'
21:22_atoah yeah, you'd probably to proxy URLClassLoader to setup it's permissions to block access to files and sockets and such
21:22_atoalso note that creating a fresh classloader and loading a fresh copy of clojure in it can take a while, it's about 600ms on my PC
21:22Anniepoooochie. 8cP afraid of that
21:24Anniepoomaybe I can make a custom version of RT
21:26Anniepootake all the static members and swap them out
21:27hiredman:|
21:27hiredmanthe time is not in loading RT, it is loading everything else
21:27hiredmanwhen you load RT you are loading all the classes clojure uses
21:28Anniepooyes, I suppose. And it smells of back to the bad-forms method
21:28hiredmanand for interning stuff like Var you need to have them seperate
21:28Anniepoothe interpreter seems to make more and more sense
21:29Anniepoo8cD What we need is clojure in clojure!
21:29hiredmanyou could pool RTs
21:29Anniepoono, because the point is to have a 'fresh' one
21:29_atoyou could pre-create a pool of them
21:29_atouse one
21:29_atoand throw it away
21:29hiredmanspin up two or three, every time you spin up one
21:29_atocreate a new
21:29_atoetc
21:30Anniepootrue, but that limits my sustained rate, and works the server
21:30AnniepooI'm beginning to think the interpreter way is the right way
21:30_atothere might be a way to put most of the classes in a parent classloader and just the stuff that changes like RT itself in multiple child classloaders
21:30Anniepoomake a toy lisp interpreter in Clojure.
21:31_atoso they share most classes
21:32_atoactually that probably wouldn't work as RT and the collections are pretty tightly coupled, the collections call into RT
21:32kzarKind of a dumb question but I'm writing a simple recursive function and I'm trying to create a lazy sequence of numbers. I tried doing something like (lazy-seq x (recur (+ x 1))) but it doesn't work because x is an integer. What's the right way around that?
21:33_atouse the function name instead of recur
21:33hiredmankzar: it doesn't work because you can't call recur within lazy-seq
21:33_atorecur does tail call optimisation, but a lazy-seq exits the function so it doesn't make sense
21:34Anniepoowell, thanks all, this has been helpful. I'll explore the options
21:34_atooh
21:34_atoand you need: (lazy-seq (cons x (recur (+ x 1)))))
21:34_atokzar: lazy-seq doesn't cons for you
21:35_atoerr, I of course mean: (lazy-seq (cons x (my-fn (+ x 1)))))
21:35hiredman"Elapsed time: 1.846638 msecs"
21:35kzarSweet gotya, thanks
21:36hiredmanRT loads pretty fast here
21:36_atohiredman: ah awesome
21:36_atomaybe it's fast if you use the same version
21:36_atoit can probably used the already loaded classes
21:37_atoI was loading 1.0 inside 1.1
21:38zaphar_psis the clojure documentation available as a downlaod anywhere?
21:38zaphar_psthat would be really useful
21:39Anniepoohiredman, you're probably only having to reload the one class
21:39Anniepoobut since the versions are diff ato's reloading the world?
21:40_atozaphar_ps: try this: http://github.com/ksuzuki/Save-cljsites
21:41_atozaphar_ps: there's also various other suggestions on the google group: http://groups.google.com/group/clojure/search?group=clojure&amp;q=offline+documentation
21:42_atozaphar_ps: if you're using emacs + slime move the cursor over the name of a function and press: C-c C-d C-d (that obviously doesn't let you search though)
21:42zaphar_psahh nifty that's like the wget option I was considering
21:43zaphar_ps_ato: yeah I use vimclojure which has similar
21:43zaphar_psbut like you say it doesn't allow searching or browsing
21:43kzar_ato: That worked but when I took too many from the lazy sequence I got a stack overflow. Your right that recur wouldn't work because it gives me an error so is there an alternative?
21:43_atokzar: strange... you shouldn't get a stackoverflow, can you pastebin your whole function
21:43_ato?
21:45Anniepooanybody know of a lisp interpreter in clojure? I'm beginning to like that tack a lot
21:47lisppaste8kzar pasted "fib" at http://paste.lisp.org/display/91070
21:48_atoah, I get a heap overflow not a stack overflow
21:49kzar_ato: whoops sorry me too
21:50_atotry reduce instead of apply
21:50_atoI suspect apply is holding onto the head of the sequence
21:52kzar_ato: Hmm that's taking ages to run
21:53kzar_ato: hope my macbook doesn't blow a hole in my crappy desk, it's whiring up ominously
21:54_atowell you're asking it to sum 4 million fib numbers
21:54_mstkzar: I don't think you need to sum the first 4,000,000 numbers to solve that problem ;)
21:54_atothe final answer is going to be enormous
21:55kzarI guess so but here's the question: "Find the sum of all the even-valued terms in the sequence which do not exceed four million."
21:55_mstyep, but even fib(100) exceeds four million by loads
21:56kzaroh I read it while the number in the sequence is less than four million but it meant while the sum was less than four million
21:57_atoit does mean the numbers in the sequence are less than four million
21:57_atoit doesn't mean while the *length* of the sequence is less than four million
21:57kzaryea gotya :/ I'm glad this is logged for everyone to see
21:57_atoyou probably want (take-while #(< % 4000000) ...) instead of (take 4000000 ...)
21:58_mstless ambiguously: (reduce + (take-while #(< % 4000000) (filter even? (fib)))) ;)
22:00kzaroh cool, that's pretty powerful
22:00lisppaste8kzar annotated #91070 "better" at http://paste.lisp.org/display/91070#1
22:21alexykhow do you print to stderr?
22:30zaphar_psalexyk: (.println (System/err) "foo")
22:30zaphar_psoff the top of my head that should work
22:30zaphar_psuses javas stderr print stream
22:31alexykthx!
22:32zaphar_pshttp://clojure.org/java_interop
22:32zaphar_psthat would probably be useful
22:32alexykso here .println is called on System/err? is that the syntax?
22:32zaphar_psalexyk: yeah
22:40zaphar_psalexyk: after further reading *err* represents stderr in clojure as well
22:41alexykzaphar_ps: can we use (print ...) with it somehow?
22:41alexykweird: (print *err* "au") gets me a: #<PrintWriter java.io.PrintWriter@2db7ae22> aunil
22:42zaphar_psyou can .println with it
22:42zaphar_psbut print doesn't take a stream it assumes *out*
22:43somniumyou can also do (binding [*out* *err*] ...)
22:43zaphar_pssomnium: yeah
22:45alexykah ok it just printed *err*
22:47zaphar_pscode?
22:50alexykI mean representation of *err* is #<PrintWriter java.io.PrintWriter@2db7ae22>
22:52zaphar_psalexyk: right
23:19kzarhow could you take the last two items in a sequence?
23:20defnnthrest
23:20defnerr not what you were asking i suppose
23:24_mstif you happen to have a vector: (take 2 (rseq [1 2 3 4 5]))
23:25defn(reverse seq), (take 2 seq)
23:25defnoh yeah, rseq
23:25defnyou'll probably wanna reverse the final output from _mst's though
23:26defn,(reverse (take 2 (rseq [1 2 3 4 5 6])))
23:26clojurebot(5 6)
23:29defnyou also could (let [sz (count [1 2 3 4 5 6])] (rest (split-at (- sz 2) [1 2 3 4 5 6])))
23:29defn,(let [sz (count [1 2 3 4 5 6])] (rest (split-at (- sz 2) [1 2 3 4 5 6])))
23:29clojurebot((5 6))
23:29defnor something like that
23:32JAS415you could also do (drop (-(count coll) 2) coll)
23:32zaphar_pswhy do read and readline not accept a java.io.FileReader?
23:34JAS415have you looked at the duck-streams contrib module?
23:34defn^^
23:34zaphar_psJAS415: no I haven't
23:35JAS415it might be useful to you
23:38defn,(let [size (count [1 2 3 4 5 6])] (subvec (- size 2) size [1 2 3 4 5 6]))
23:38clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IPersistentVector
23:38defndoh
23:39JAS415other way round
23:47eno__,(let [v [1 2 3 4 5 6] size (count v)] (subvec v (- size 2)))
23:47clojurebot[5 6]