#clojure logs

2012-07-07

00:00duck1123I've hit an odd issue in monger. If I insert, then find-map-by-id I get my document back. If I replace the insert with insert-and-return, I get nil. Anyone know what's up?
00:00mthvedtby deferring looking up symbols, rules can be immutable and you don't have any forward-declaring
00:01duck1123the one just calls the other, so I don't see what could be going on.
00:01mthvedtif you want recursive rules
00:01mthvedti tried it the 'normal' way, and having to forward declare rules then go back and mutate the old ones, to get mutually recursive rules, just seemed… un-clojureish
00:02mthvedtgrabbing the *ns* is also unclojure-ish, but IMO a lesser evil
00:02ToxicFrogFair enough
00:03ToxicFrogHmm.
00:03ToxicFrogThe NPE is not limited to redefing 'name
00:03mthvedtyes, looks like redefining any clojure.core fn does it?
00:04ToxicFrog>.<
00:04ToxicFrogI would have thought that redefing any of those would just shadow the definition in clojure.core, since I'm in my own namespace here
00:06mthvedtIs the clojure team aware of this issue? It seems to be known in the google groups threads
00:07mthvedtis there a clojure JIRA or something to search?
00:07mthvedtit's known to happen in both lein and maven compilation
00:08ToxicFrogIt does, in fact: http://dev.clojure.org/jira/secure/Dashboard.jspa
00:09mthvedtit does not happen except in precompiled code, so that and it being discouraged usage make it low on the radar probably
00:09ToxicFrogBack to Clearly for a moment -
00:09mthvedtok
00:10ToxicFrogI'm trying to create rules for three token types. A typename is a sequence of uppercase letters; a key is any sequence of letters and numbers; and a value is any string at all not containing a newline.
00:10ToxicFrogIn something like scala.util.parsing or flex+yacc, I'd just use regexes here.
00:10ToxicFrogIn Clearly, I have this: https://gist.github.com/fb903793baa2e918aae0
00:10ToxicFrogIs there a better way to do this? Because this seems super awkward.
00:12mthvedtyup, clearley only eats one item of input at a time
00:12ToxicFrog(also, it would be really nice to be able to construct rules from regexes, specifically for this sort of thing)
00:12ToxicFrogSo is it expected to be paired with a lexer?
00:12mthvedtdoesn't need to be, though you can if you want to
00:13ToxicFrogWell, yes, it doesn't need to be, but it looks like it would make stuff like this a lot simpler
00:13mthvedtthe earley algorithm can be modified to scan multiple items in one low-level rule… it's fairly easy, but it's nontrivial
00:13ToxicFrogThere's a lot of code in the json parser as well working around this
00:13mthvedtit's on my "todo" list
00:14mthvedttry
00:14mthvedti
00:14mthvedtinstead of having 9 lines
00:14mthvedtscanner and one-or-more both return rules
00:14mthvedtso i think you can do (def x (one-or-more y (scanner z)))
00:15mthvedtonce the rule API is cleaned up, you could just write a clearly regex parser that emits a clearly rule :)
00:15mthvedtand by you, i mean me
00:15ToxicFrogWhat is y meant to be there? I'm still a bit shaky on "rule heads".
00:16ToxicFrogWell, yes, I was contemplating how hard it would be for me to do, given the current state of Clearley :P
00:16mthvedtoh sorry
00:16mthvedt(def x (one-or-more (scanner y z))) is what i meant to type
00:16mthvedt(def sfs-type (one-or-more (scanner #(…) identity)))
00:17mthvedttry that
00:17ToxicFrogThat works fine, thanks
00:17ToxicFrogAnd is easily macroized too.
00:18ToxicFrogAnd now that the parser compiles, my super major #1 feature request: useful error reporting when a parse fails.
00:18ToxicFrogThis is my #1 reason for using a parsing library rather than just rolling my own recursive descent parser: error reporting.
00:20mthvedtyeah, about that...
00:21mthvedti hope you don't have to throw your work away… clearly has almost no error reporting at this time
00:22mthvedtor when you say that's a feature request, you just mean, would be very nice to have?
00:23ToxicFrogFor this project, it's not a priority, since this project is actually a rewrite of an existing codebase with no real urgency. So if I have to wait for error reporting to be added, or even add it myself, it's not a big deal.
00:24mthvedtok, cool
00:24ToxicFrogAlso because I'm the only user of this program who actually cares about parse errors, since the stuff it's processing is all machine-generated and all the end users need to do is report parse errors as a bug to me if they occur.
00:24ToxicFrogFor projects where this is not the case, yeah, it would be a serious issue.
00:25mthvedtyup
00:25mthvedtone attractive thing about bottom-up parsers is error reporting is a lot more natural...
00:28ToxicFrogFor reference, errors from scala.util.parsing - which are, so far, the best I've seen - take the form:
00:28ToxicFrog[29.1] failure: string matching regex `= *[^\n]*' expected but `a' found
00:28ToxicFrogFollowed by the offending line, and a carat pointing out the exact location in the line.
00:28ToxicFrog(this is generated by a method on the error object; all of this information can be extracted by the program easily as well)
00:29mthvedti've never used scale's parsing library, but it looks very nice
00:29mthvedtisn't it top-down, though? i wonder how they make sense of errors
00:30ToxicFrogTo be honest, I have no idea
00:30ToxicFrogThe source is available from http://www.scala-lang.org/api/current/scala/util/parsing/combinator/Parsers.html if you feel like crowbarring it open and looking inside, although I doubt much if any of it will be relevant to an Earley parser.
00:32ToxicFrogOf course, it's also worth noting that the top-level Parser.scala - not even any of the concrete implements like RegexParser - is almost as large as all of Clearley including the tests
00:32ToxicFrogScala's standard library is not exactly lightweight.
00:33mthvedtworking with top-down parsers is what drove me to bottom-up parsers in the first place :P
00:33mthvedtwe had a use case at work that involved a complex, highly mutually recursive grammar
00:33mthvedtexisting grammars, even those that advertised the ability to handle left recursion, just all blew up
00:34ToxicFrogI haven't observed such issues with Scala's parsers, but I've never tried parsing anything super complex with them
00:34mthvedtanyway, i really gotta get some rest soon...
00:35ToxicFrogOk. Now to actually fix this so that it works
00:35ToxicFrogSince what prompted me to mention error messages was that my parse is failing (because it does no whitespace handling at present)
00:35ToxicFrogHmm. Maybe I should give it a lexer.
00:37mthvedtif you're too lazy to handle whitespace… s/\s+/ /g :P
00:37ToxicFrogmthvedt: problem with that is, note the rule for sfs-value
00:37ToxicFrogIt's everything from the = to the end of line preserving whitespace
00:38mthvedtthere's some whitespace rules in the json example
00:39ToxicFrogYeah; it gets kind of messy.
00:40ToxicFrogThis'll be good practice; it's been ages since I wrote a divided lexer/parser
00:58ToxicFrogHuh
00:59ToxicFrogI can do this: #(Character/isLetterOrDigit %)
00:59ToxicFrogBut I can't do this: (partial Character/isLetterOrDigit)
01:03mthvedttoxicfrog: because java methods are not clojure fns
01:04mthvedtthey are actually clojure special forms
01:05ToxicFrogOh :(
01:05ToxicFrogAm I pretty much limited to #() and equivalents for that, then?
01:06mthvedtpretty much
02:51aperiodici think that's part of why point-free style is not really used as much in clojure--if you use #(), you don't have to keep 'is this a special form?' in the back of your mind
02:53aperiodicon a related note, i ended up writing andf & orf (the fn versions of and and or) the other day, which felt a bit odd to me
02:53amalloyas well it should
02:55amalloy&(let [andf (comp (partial every? identity) list)] (andf true false))
02:55lazybot⇒ false
02:55amalloy&(let [andf (comp (partial every? identity) list)] (andf true true))
02:55lazybot⇒ true
02:55aperiodicman, whenever i do some thing weird with HOFs i should just come here and bug you
02:56amalloymy point isn't really the allegedly-clever definition of andf using comp/partial, it's that you should just use every? and some instead of andf and orf
03:02aperiodicthe reason i ended up writing them was to construct the predicate i wanted to pass to things like every? and some
03:03aperiodicandf and orf are functions on predicates, not booleans
03:04amalloyso you're saying they're some-fn and every-pred?
03:05aperiodicyeah, that's what i'm saying
03:05amalloy&(doc some-fn)
03:05lazybot⇒ "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns the first logical true value returned by one of its composing predicates against any of its arguments, else it returns logical false. Note that f is short-... https://www.refheap.com/paste/3505
03:05amalloy&(doc every-pred?)
03:05lazybotjava.lang.RuntimeException: Unable to resolve var: every-pred? in this context
03:05amalloy&(doc every-pred)
03:05lazybot⇒ "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns true if all of its composing predicates return a logical true value against all of its arguments, else it returns false. Note that f is short-circuiting in... https://www.refheap.com/paste/3506
03:50wubinoany good reads on creating a pastebin like service?
04:05borkdudewubino check out https://github.com/Raynes/refheap and www.refheap.com
04:27ro_stare there any compelling reasons NOT to use immutant?
04:27ro_stput another way, what's the catch?
04:28hiredmanI wonder how well it would work in a heterogeneous environment
04:29ro_stok, so one thing is you couldn't do is host on something like heroku
04:29hiredmanin some sense it is waiting for some one to take a chance on it, I haven't heard of anyone using it "in production" yet
04:31ro_stit's still pretty new
04:31hiredmanyeah, but interest is building, and it is gaining features, someone will give it a trial by fire
04:32ro_stnot having to build out all the stuff it provides is quite compelling
04:32hiredmanyes, but at work we've already built all that stuff :)
04:32clojurebothttp://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png
04:33hiredmana lot of features seemed to be sort of aimed at webapps instead of backend data processing apps
04:33ro_stperfect for us
04:33ro_sti'm in the process of writing a json api, and shortly will be needing to port ruby/resque based stuff for messaging over
04:38hiredmanthe custering stuff would be really cool, but I would prefer to be able to swap out discovery mechanisms (just use zookeeper)
04:39hiredmanI don't trust the jgroups stuff
04:39ro_sti reckon it's worth playing with
04:40ro_stgotta run!
05:22_ulisesmorning all, I have a question about midje background; basically, if I define (against-background :facts (some-fn)...) and then have (fact (f) => 1 (g) => 2), then (some-fn) is executed twice. Maybe I'm not properly understanding (fact ...) vs (facts ...)? My objective is to start a web server before running tests and to bring it down once I'm done testing. I managed to do this with (against-background :contents ...)
08:38AWizzArdProtocol experts wanted: I have a Protocol which I want to implement for IFns and Maps. Now, a Clojure map is at the same time an IFn. When I now call (my-proto-fn {}) I end up in the body specified for IFns. But I want to call the my-proto-fn for java.util.Maps. Ideas?
08:39AWizzArd(defprotocol Bar (foos [x])) and then (extend-protocol Bar clojure.lang.IFn (foos [x] (println :fn)) java.util.Map (foos [x] (println :map)))
08:40AWizzArdNow I want that (foos {}) prints :map.
09:22daniel___im looking for the most concise way of checking if all the values in a list equal something?
09:22daniel___,(map #(= % 1) '(1 2 3 4 5))
09:22clojurebot(true false false false false)
09:22daniel___,(contains? false (map #(= % 1) '(1 2 3 4 5)))
09:22clojurebotfalse
09:23daniel___,(apply #(= true %) (map #(= % 1) '(1 2 3 4 5)))
09:23clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: sandbox$eval87$fn>
09:23madsydaniel___: Maybe every?
09:23daniel___madsy maybe
09:24daniel___,(every? true (map #(= % 1) '(1 2 3 4 5)))
09:24clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn>
09:24daniel___,(every? #(= true %) (map #(= % 1) '(1 2 3 4 5)))
09:24clojurebotfalse
09:24daniel___:)
09:37inklesspendaniel___: you can just do (every? #(= % 1) '(1 2 3 4 5)) looks like. or (every? (partial = 1) '(1 2 3 4 5))
09:40_ulises,(apply and (map #(= 1 %) [1 2 3]))
09:40clojurebot#<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0)>
09:41_ulises,(reduce and (map #(= 1 %) [1 2 3]))
09:41clojurebot#<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0)>
09:44_ulisesshame that and is a macro, otherwise it'd be great to reduce your checks using and
09:45inklesspen,(apply (partial = 1) '(1 1 1 1))
09:45clojurebottrue
09:46inklesspen,(apply (partial = 1) '(1 2 3 4))
09:46clojurebotfalse
09:46_uliseslovely
09:48AWizzArdWell, inklesspen already showed the ideomatic solution, which is: (every? #(= 1 %) [1 2 3 4 5])
09:48AWizzArd_ulises: the function equivalent to `and` is `every?`.
09:49inklesspenAWizzArd: is the anonymous function version any more ideomatic than the partial version?
09:49inklesspeni guess it's shorter
09:49AWizzArdinklesspen: both are okay, but partial is evaluated each time.
09:49inklesspenah
09:49inklesspenmakes sense
09:49AWizzArdWhile (fn [n] (= n 1)) is directly compiled, and thus a bit more efficient.
09:50AWizzArdPlus: I personally find it more readable.
09:50AWizzArdFor this specific case one could do some trickery, such as (= #{1} (set [1 2 3 4 5]))
09:50AWizzArdBut this would just check if every element in the seq is =1
09:51AWizzArdThe solution with every? is more generic, and could be used as well for (every? odd? some-numbers)
10:11ToxicFrogHmm. I wish I could ^Tag strings.
10:14mthvedttoxicfrog: good morning
10:14ToxicFrog'morning
10:15mthvedthas the parser been working out ok?
10:16ToxicFrogI went to bed at about the same time as you last night; I'm just starting on the lexer now
10:16ToxicFrogAlthough I did think of a lexer-related question
10:16mthvedtshoot
10:16ToxicFrogWhen using defrule, a rule is of the form [terminal-or-nonterminal+], where a nonterminal is another rule, and a terminal is - when parsing a string - a single character
10:17ToxicFrogEg, [\{ keyvalues \}]
10:17ToxicFrogHow is that single character matched, and what does it need to be replaced with when parsing a stream of { :tag :foo :text "bar" } tokens?
10:17ToxicFrogI think that using a scanner that checks :tag would work, so you do something like:
10:18ToxicFrog(def open-brace (scanner #(= (:tag %) :open-brace) identity))
10:18ToxicFrogAnd then use [open-brace keyvalues close-brace]
10:18mthvedtmatched with =
10:18ToxicFrogBut is there a better way?
10:19mthvedtthere's support for what i'm currently calling "tokenizers"
10:19mthvedti
10:19mthvedti'm not sure if they're a good idea, and might change/remove them
10:19mthvedtbut basically, to test for a terminal symbol x
10:19mthvedtt
10:20mthvedtthe parser runs (= x (tokenizer input))
10:20mthvedtwhere the default tokenizer is identity
10:21mthvedtthat's still a little cumbersome, because each parse action needs to have :text in it anyway
10:22mthvedtyou pass the tokenizer fn to build-parser
10:23mthvedt(build-parser goal-rule tokenizer)
10:23ToxicFrogHmm
10:23ToxicFrogThe issue I see there is that the tokenizer would (at least, I would expect) return not just the name of the input symbol but a whole bunch of information
10:24ToxicFrog{ :tag :number :text "12.34" :line 5 :col 8 }
10:24ToxicFrogAnd for matching, you only actually care about :tag; :line and :col are for the error reporter and :text is for whatever processes the AST.
10:25mthvedtyou could pass :tag as your tokenizer
10:25mthvedtif your input symbols are maps you want to parse the :tags of
10:27ToxicFrogOk, but in that case, is the return value of the rule just the :tag, or the entire map originally passed to tokenizer?
10:28mthvedtthe return value will be the entire map
10:29ToxicFrogAwesome
10:36augustlis it possible to access the persistent data structures from ClojureScript in a Node.js app, without converting my app to ClojureScript?
10:36nDuffaugustl: it'll be easier to have your ClojureScript code export to native structures.
10:37augustlI don't have any ClojureScript code :)
10:37augustlI could use persistent data structures though
10:37augustlah, I see
10:37nDuffaugustl: ...oh, you mean you want to _create_ them from native JS code, not just leverage them?
10:38augustlyes
10:38augustlsimilar to how you can create PersistentVector etc from java (right?)
10:38nDuffHmm. Well, there's nothing stopping you from calling cljs.core.PersistentVector.fromArray() from native JavaScript
10:39augustlis cljs.core etc. available as one JavaScript file somewhere?
10:39nDuffaugustl: ...run a compilation pass, and the output is one JavaScript file.
10:40augustlcool, thanks
10:40nDuff(when compiling with lein-cljsbuild, anyhow)
10:41augustlwriting some code where my client for a server needs to get all state, even when it goes down
10:41augustldatomic-esque time semantics with persistent data would make sense for that I think
10:42augustla client having to be present at all times to track state as it flows is pretty horrible. Would be much better if a client gets a ping, and then requests the state changes from time at last fetch to now
11:44ToxicFrogWhat's idiomatic for "find the first value in a coll satisfying p"?
11:45ToxicFrog(first (filter p coll)) ?
11:47hyPiRionToxicFrog: Yeah.
11:54ToxicFrogI keep wanting to call it "first" or "find", but clojure already uses both of those @.@
11:58SorellaToxicFrog, find-first?
12:00ToxicFrogSorella: yeah, that's what I went with.
12:01ToxicFrog(I'm coming from a collections library which uses head/tail rather than first/rest, and (find p xs) finds the first x in xs satisfying p)
12:01TimMcToxicFrog: While you're at it, you could add an optional not-found argument.
12:05daniel___((a b c) (d e f) (g h i)) is there an ingenius way of testing if a = e = i?
12:05daniel___ingenious*
12:06daniel___or c = e = g
12:07daniel___with pattern matching perhaps
12:07TimMccore.match is still extremely alpha (buggy), unfortunately.
12:08daniel___,(let [((a _ _) (_ b _) (_ _ c)) ((1 2 3)(1 2 3)(1 2 3))] (println a b c))
12:08clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: ((a _ _) (_ b _) (_ _ c))>
12:08hyPiRionboth a = e = i or c = e = g?
12:08daniel___yeah
12:08hyPiRionuse vectors instead
12:08TimMc&(#(let [[[a] [_ b] [_ _ c]] %] [a b c]) '((1 2 3)(4 1 6)(7 8 1)))
12:08hyPiRion,(let [((a _ _) (_ b _) (_ _ c)) ((1 2 3)(1 2 3)(1 2 3))] (println a b c))
12:08lazybot⇒ [1 1 1]
12:08clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: ((a _ _) (_ b _) (_ _ c))>
12:08daniel___hyPiRion: if i had a vector of length 9?
12:09hyPiRionWhat TimMc wrote.
12:09daniel___cool
12:09daniel___pattern matching only works with vectors?
12:09TimMcdaniel___: map, nth, apply
12:09TimMcmap-indexed, really
12:10TimMcdaniel___: destructuring syntax uses vectors, but can be applied to any collection
12:10daniel___i c
12:10daniel___,(let [[[a _ _] [_ b _] [_ _ c]] ((1 2 3)(1 2 3)(1 2 3))] (println a b c))
12:10clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>
12:10daniel___,(let [[[a _ _] [_ b _] [_ _ c]] '((1 2 3)(1 2 3)(1 2 3))] (println a b c))
12:10clojurebot1 2 3
12:10daniel___cool
12:11TimMc&(#(map-indexed (fn [i el] (nth el i)) %) '((1 2 3)(4 5 6)(7 8 9)))
12:11lazybot⇒ (1 5 9)
12:12TimMc&(#(map-indexed (fn [i el] (nth el (- (count %) i 1))) %) '((1 2 3)(4 5 6)(7 8 9)))
12:12lazybot⇒ (3 5 7)
12:13daniel___neat
12:13TimMc&(apply = '(3 5 7))
12:13lazybot⇒ false
12:14daniel___any advantage over the destructuring approach?
12:14TimMcExtensible.
12:15TimMcThis gets you diagonals of any length.
12:15daniel___the disadvantage i can see is that it is less explicit, i mean it takes a few moments longer to work out what its doing
12:15TimMcThat's why you (defn diagonal ...) and use that.
12:43daniel___Can anyone create a neat way of doing this, in a similarly extensible way as before? [a b c d e f g h i] -> ((a d g) (b e h) (c f i))
12:44daniel___Perhaps there is already a function to achieve something like this, or with partition-by and map-indexed somehow?
12:44metellus,(partition 3 [a b c d e f g h i])
12:44clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)>
12:44metellus,(partition 3 [1 2 3 4 5 6 7 8 9])
12:44clojurebot((1 2 3) (4 5 6) (7 8 9))
12:45daniel___yeah, im looking at the padding
12:45AWizzArdalternatively (partition-all 3 your-list)
12:45daniel___(partition 3 3 [1 2 3 4 5 6 7 8 9])
12:45daniel___,(partition 3 3 [1 2 3 4 5 6 7 8 9])
12:45clojurebot((1 2 3) (4 5 6) (7 8 9))
12:45daniel___thats not what i need
12:45AWizzArd,(partition-all 3 (range 10))
12:45clojurebot((0 1 2) (3 4 5) (6 7 8) (9))
12:45daniel___i need ((1 4 7) (2 5 8) ..
12:46AWizzArd,(apply map first (partition-all 3 (range 10)))
12:46clojurebot#<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (4) passed to: core$first>
12:46daniel___,(partition 3 3 3 [1 2 3 4 5 6 7 8 9])
12:46clojurebot((1 2 3) (4 5 6) (7 8 9))
12:46daniel___,(partition 3 3 3 3 [1 2 3 4 5 6 7 8 9])
12:46clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: core$partition>
12:47daniel___,(partition 3 1 3 [1 2 3 4 5 6 7 8 9])
12:47clojurebot((1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) ...)
12:47dustingetzo you know how to map over a tree? i want to define functions like "bfs" "dfs" "iterative deepening search" that turn a tree into a lazy seq i can map over
12:47dustingetz*"does anyone know how to map over a tree"
12:47AWizzArdMaybe this:
12:47AWizzArd(apply map list (partition 3 (range 1 10)))
12:47dustingetzi think this is an example in haskell: http://okmij.org/ftp/continuations/Searches.hs - but i don't understand this
12:47AWizzArd,(apply map list (partition 3 (range 1 10)))
12:47clojurebot((1 4 7) (2 5 8) (3 6 9))
12:47daniel___there we go
12:47daniel___:D
12:47daniel___thanks
12:48dustingetzyeah but i want to define functions like 'bfs' 'dfs' which control the order in which i map
12:48metellus,(zipmap (partition 3 [1 2 3 4 5 6 7 8 9]))
12:48clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$zipmap>
12:48metellus,(apply zipmap (partition 3 [1 2 3 4 5 6 7 8 9]))
12:48clojurebot#<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$zipmap>
12:48AWizzArdmetellus: partition 2
12:49AWizzArdNo, nonsense. I mean: zipmap needs two args.
12:50metellustoo bad
12:51wingyyou think this is still valid for learning clj 1.4: https://peepcode.com/products/functional-programming-with-clojure
12:51wingyfrom 2009
12:51wingyhm probably not
12:51wingy3 years old afterall
12:53wingydo we have any from Stockholm here?
13:01ohpauleezdustingetz: Take a look at the kibit code
13:01ohpauleezWe use clojure.walk
13:01ohpauleezand you can post and pre walk a tree
13:01ohpauleezwe also have a function for seq'ing the tree
13:04dustingetzthanks paul
13:04ohpauleez&(doc tree-seq)
13:04lazybot⇒ "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence ... https://www.refheap.com/paste/3508
13:05ohpauleeznp
13:19weavejestertechnomancy: I'm glad you pointed out "lein deploy" to me! Thanks!
13:20ToxicFrogI wish 'lein deploy' could deploy to github
13:21ToxicFrog(using the github upload-file thingy, I mean, not 'git push')
13:23ohpauleezToxicFrog: There's documentation on how to host a maven repo on github, so technically ...
13:24ToxicFrogohpauleez: yeah, but I don't want to host a maven repo, I just want to be able to upload release packages from the command line :P
13:39ToxicFrogCount number of items in xs satisfying p: (count (filter p xs)) ?
13:54AWizzArdToxicFrog: yes.
14:20wingywhy no def- like defn-
14:20wingybut for vars
14:21amalloydefn- only exists because, long ago, it was inconvenient to put :private metadata on your functions
14:21wingyamalloy: is it still inconventient?
14:22amalloydefining a new top-level name for every little thing you want to change leads to an explosion of new names: what about defmacro-? and defn-*, if we decide * should be for :dynamic?
14:22amalloynot at all. just (defn ^:private foo [])
14:23wingytrue
14:23wingybut isn't it better to just use that line then?
14:23wingyand remove defn- to keep things consistent?
14:24amalloyit's unlikely to ever get removed, for compatibility
14:24wingyok
14:24wingyi guess convenience is good as well
14:24amalloybut every few months someone asks on the mailing list if they can please have def-, and the response is primarily "no, defn- is bad enough"
14:25wingyjust like you can put a doc string with def instead of having to assign a meta doc each time
14:25wingybut i do think if you really want to remove something bad you can do it by deprecating it
14:26wingyand have it there for 1-2 more versions .. better to progress forward in the longer run
14:34Chouser1Anyone know why the light table sandbox might be failing for me?
14:35Chouser1The browser console says "Firefox can't establish a connection to the server at ws://localhost:8833/socket."
14:35TimMcChouser1: Try chrome.
14:35TimMcIt seems to work on only some (random) versions of recent Firefoxen.
14:36Chouser1this is firefox 15.0a2
14:42Chouser1TimMc: Thanks, chrome is working.
15:23ssutchwhat is the recommended way to provide configuration values to a compojure app?
15:23ssutcheg, database URIs and whatnot
15:25arohnerssutch: you have a lot of options. Depends on the app, mainly
15:25ssutchmy main deployment target is a uber war deployed on elastic beanstalk
15:25ssutchthat's where i want to run it
15:26ssutchi need to provide it with db uri(s) and private keys and such
15:26arohnerI like a bash file full of export FOO=bar
15:26arohnerthen source it before running
15:27arohnerif you don't mind your config being checked in, you can write a clojure file that's just (def config {:foo bar}), and load that
15:28ssutchok
15:28ssutchi'm fine with providing it to the command line
15:28ssutchi guess my only concern is things like a private key
15:29arohnerso just export the path to the key
15:30piotrssutch: hi. Env variable is the recommended way to do on Heroku. See https://devcenter.heroku.com/articles/config-vars
15:32kmicussutch: also check this out https://github.com/drakerlabs/milieu
15:33ssutchinteresting
15:54antares_Spyglass now has a doc website: http://clojurememcached.info
15:55antares_and clojurewerkz.org has a new About page (retweets are greatly appreciated): https://twitter.com/ClojureWerkz/status/221681163641688065
16:00daniel___https://gist.github.com/3067920 play is my main entry point, i keep getting nullpointerexception with 'lein run'
16:00daniel___something to do with the read-line
16:01daniel___can anyone enlighten me?
16:02antares_daniel___: read-line can return nil
16:02daniel___yes, but its not prompting
16:03antares_actually, disregard, I think it returns empty strings
16:03antares_daniel___: do you have an example stack trace?
16:04daniel___added to the gist
16:06dnolen,(dec nil)
16:06clojurebot#<NullPointerException java.lang.NullPointerException>
16:06dnolendaniel___: your read-int can nil
16:06raekhow can I run a ghci repl in a cabal project?
16:07dnolenraek: wrong channel ;)
16:07dnolendaniel___: I mean your read-int can return nil
16:08daniel___dnolen: if i take away the dec, i get an argument error
16:08amalloyconsole input doesn't work in lein run
16:08daniel___for some reason it isnt prompting
16:08daniel___oh
16:08amalloytry lein trampoline run
16:08daniel___amalloy: works
16:08daniel___:)
16:09daniel___whats trampoline?
16:11daniel___nvm, i see it runs it after leiningens jvm has closed
16:11daniel___rather than in a subprocess
16:27technomancyantares_: we used neocons at seajure the other night; it was great
16:28antares_technomancy: oh, nice!
16:28technomancywe loaded up the clojuresphere data set into it
16:29antares_technomancy: big people are using clojurewerkz libraries! :)
16:29technomancyyeah, like me. I'm 202cm.
17:05mjewkesHey Everyone. I'm running OSX with Emacs 24. I've installed lein and added 1.4.4 of lein-swank to the profiles.clj file. I've installed clojure mode in emacs and it is doing syntax highlighting properly. But emacs doesn't seem to have the clojure-jack-in command available.
17:05mjewkesHas anyone bumped into this before?
17:07amalloysounds like an old clojure-mode?
17:08mjewkespossibly - I just installed it using package-install.
17:08amalloytry getting it fresh from technomancy's github
17:08mjewkesInterestingly - slime-connect seems to be missing to.
17:09mjewkesShould that be present - amalloy: will do.
17:09amalloyi dunno. i think jack-in provides its own copies of the slime libs
17:25antares_yes, swank-clojure bundles its own copy of slime
17:26Pupeno_WFrom https://github.com/technomancy/swank-clojure/blob/master/README.md: "Add [lein-swank "1.4.4"] to the :plugins section of either project.clj or your user profile."
17:27Pupeno_WWhat does your profile mean here?
17:27mjewkes~/.lein/profiles.clj
17:27clojurebot/.lein/profiles.clj is nice, but it doesn't allow you to vary the profile for a specific project without checking it in to the repo
17:28Pupeno_WThanks.
17:34ToxicFrogOh bollocks
17:34ToxicFrog(drop n s) where s is a string returns a LazySeq
17:34ToxicFrogWith tragic results when you're doing something like (re-match pattern (drop header-length buf))
17:37metellususe subs
17:37ToxicFrogYeah, I was reflexively trying to make this sequence-type-agnostic
17:37ToxicFrogDespite the fact that, on reflection, it makes sense only for strings
18:04overstoodI have what is hopefully a basic syntax question about Clojure, is this the right place for that?
18:05ohpauleezoverstood: sure, totally
18:06overstoodGreat :)
18:10overstoodSo there is a function that normally it takes a number, does a thing to it and returns a value. There are some edge cases where this function needs to just return a constant because the behavior of that function is not covered by the algorithm that handles most cases. I'm currently using a lot of (if (eq input foo) constant (if (eq input foo2) constant2 (normalAlgorithm input)))
18:10overstoodis there a better/more elegant way to do this than chaining if statements together?
18:10ohpauleezcond
18:11ohpauleezor condp
18:11ohpauleez&(doc cond)
18:11lazybot⇒ "Macro ([& clauses]); Takes a set of test/expr pairs. It evaluates each test one at a time. If a test returns logical true, cond evaluates and returns the value of the corresponding expr and doesn't evaluate any of the other tests or exprs. (cond) returns nil."
18:11ohpauleezhttp://clojuredocs.org/clojure_core/clojure.core/cond
18:12ohpauleezYou might also want to consider `case`
18:12ohpauleezhttp://clojuredocs.org/clojure_core/clojure.core/case
18:12ohpauleezhttp://clojuredocs.org/clojure_core/clojure.core/condp
18:12ohpauleezthere's condp
18:13overstoodThat looks like what I was looking for.
18:13overstoodThanks a lot!
18:14amalloycase would work, or you could just use a map
18:15amalloy(let [defaults {1 "one" 2 "two"}] (defn compute [x] (or (defaults x) (do-real-work x))))
18:16overstoodthat's neat too
18:16ohpauleezusing a dispatch table like that is a pretty typical pattern overstood
18:18mcohenhi there #clojure. trying to get started programming Clojure and am getting stuck trying to compile, test, or repl with lein
18:19mcohenDEBUG output shows Classpath: /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar
18:19mcohenand everyone of those lein commands i listed above yields Exception in thread "main" java.lang.NoClassDefFoundError:
18:19mcohenand a stacktrace
18:19mcohenCaused by: java.lang.ClassNotFoundException:
18:19mcohen at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
18:19mcohen at java.security.AccessController.doPrivileged(Native Method)
18:19mcohen at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
18:19mcohen at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
18:19mcohen at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
18:19mcohen at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
18:19mcohenCompilation failed.
18:20mcoheni know i must be missing something simple and stupid
18:20mcohencan anyone help please?
18:21ohpauleezcd to a different directly, like you $HOME
18:21ohpauleezthen try lein2 repl
18:21ohpauleezdo you still get the error?
18:21overstoodI'm just starting to learn functional programming (I'm coming from a pretty strong OO background). It's definitely an interestint paradigm shift. I feel a bit overwhelmed by the amount of power in relatively terse statements.
18:22overstoodWhy would one use cond vs a dispatch table?
18:22mcohenthanks ohpauleez. nope, the repl comes up just fine if i'm not in the project dir
18:22ohpauleezoverstood: If you needed different functions to test for different things
18:23ohpauleezoverstood: If you're looking for equality, dispatching via maps is usually used
18:23ohpauleez(a dispatch table)
18:23ohpauleezmcohen: There's an error in the source files you've written
18:23ohpauleeztry creating a new project with lein2 new, cd into it, and try `lein repl`
18:23mcohenok, but all i did was "lein new appname"
18:24mcohenand then lein test
18:24mcoheni didn't edit anything
18:24ohpauleezthere are no tests to run
18:25overstoodso the map is basically just a bit more concise and faster than cond/case?
18:25mcohentest/<project_name>/core_test.clj
18:25mcohenis created when i did lein new app
18:25ohpauleezmore concise and preferred in that case (if you're just checking for equality). I'm not sure about performance
18:26ohpauleezmcohen: And what's in that file?
18:26overstoodohpauleez: got it, thanks
18:26mcohen(ns congo.core-test
18:26mcohen (:use clojure.test
18:26mcohen congo.core))
18:26ohpauleezoverstood: No problem!
18:26mcohen(deftest a-test
18:26mcohen (testing "FIXME, I fail."
18:26mcohen (is (= 0 1))))
18:26ohpauleezmcohen: try creating a new project and see if the errors happen in the new project
18:27mcohenyeah, i tried that already actually.
18:27mcohenwhen i run with the DEBUG flag on it prints Classpath: /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar
18:27mcohenbut if i run lein classpath, i get
18:28overstoodone more question, are there any good resources to learn more about performance in clojure. I'm specifically interested in memory allocation. I want to try writing a little game for Android which means I want to try to avoid GC collection if I can.
18:29dnolenoverstood: Clojure's design assumes GC, it's pretty hard to avoid
18:30overstoodEven more specifically, when I'm using Clojure functions that don't have side effects. What is allocated and when is it released?
18:32amalloyoverstood: consider a simple case where x is the list (1 2 3)
18:32amalloyif you compute (cons 4 (rest x)), you get back (4 2 3). that list shares the 2 and 3 elements (and the list pointers linking them together) with the original
18:33amalloyso the head of the x list is no longer needed (assuming you don't have a reference to x anymore), and it's thrown away, GCed whenever the JVM finds it convenient
18:35stainanyone played with the framebuffer (/dev/fb0) from Clojure?
18:35mcohenso if you run lein <command> in the root of your clojure project with DEBUG=1 what will be shown as the Classpath variable?
18:36mcohenor, what should be shown?
18:36mcohenall i see is /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar
18:36mcohenbut if i run lein classpath then it does in fact list out the jars i've included as dependencies
18:36mcohenas well as the src, test, resources, dev-resources, and classes dirs
18:37mcohenbut the ClassNotFoundException feels like i must have a classpath issue somewhere
18:38overstoodamalloy: That makes parfect sense. I'm still trying to get an intuitive grasp of the implications of immutable state. Thanks!
18:52casperchello
18:52caspercI have this question which is not really clojure specific, but I thought you might be able to help anyway
18:53caspercI want to start a clojure process which starts an embedded jetty server at a random port. Then I want to have that port returned to my so I can run som tests against my api
18:53caspercanyone know how to go about this?
18:54jeremyheiler,(rand-int 100)
18:54clojurebot24
18:55jeremyheilercasperc: you can also check out the ring-jetty-adapter to see how it starts a jetty server.
18:55jeremyheilerhttps://github.com/mmcgrana/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj
18:55caspercI want to do this to be able do some cucumber/soapui tests against the api as part of ci
18:56staincasperc: ring can do that
18:56stainI just type "lein ring server" and it pops up a browser window
18:56caspercjeremyheiler: i should clarify, I know how to start the jetty at a random port. What I don't know is how to get that random port returned to the rake script starting the process
18:56stainI think it just tries to bind to port 3000, if it is taken, add 1, etc
18:57jeremyheilercasperc: how are you invoking the process?
18:57jeremyheilerbetter yet, how do you want to invoke the process? at a repl?
18:58caspercdoesn't really matter actually, the imortant bit is that the jetty server is started and the port returned so I can run api tests again it externally
18:59caspercmultiple tests and builds might be running at the same time, so it can't be the same port always
19:01caspercactually, come to think of it, the correct way may by for the invocing process to supply the port, not the clojure process to return it
19:02jeremyheilersomething like this? (let [port (random-port)] (start-jetty-server port) port) which would then return the port number taht you can write to std out or whatever you need to put it.
19:04caspercjeremyheiler: that might work
19:05caspercI think i will try it the other way around though and have the script starting the process supply the port. Thanks for the input :)
19:05jeremyheilercasperc: no problem. good luck
19:06caspercthank you
19:14AWizzArdHmm, interesting: at runtime I load a file. This file contains key/value pairs. I now want to implement a macro (with-file "c:/my.file" body). I want that with-file is like an implicit let, where the bindings represent those key/value pairs, so that I can refer to them in the body.
19:15AWizzArdExample: in the file I have this map: {:a 1, :b 2, :c 3}. Now I want that (with-file "c:/my.map" (= c (+ a b))) expands to code that will eval to “true” at runtime. I think this could be a case for valid use of “eval”. Opinions?
19:16nDuffAWizzArd: Err. Do you want the file to be read at compile time or runtime?
19:16nDuffAWizzArd: ...keeping in mind that macro expansion happens at compile time...
19:17AWizzArdI want to read the file at runtime.
19:17nDuffAWizzArd: ...what you want can't be done without forcing the code within the macro to be recompiled every time it's executed. That's pretty evil.
19:18nDuffAWizzArd: is it really _that_ much harder to put the read contents of the file in a variable and refer to (:a my-var) rather than just "a"?
19:18AWizzArdnDuff: yes
19:18AWizzArdThat’s why Clojure offers destructuring.
19:19AWizzArdI want runtime destructuring of files.
19:19nDuff...sure, but destructuring as it's typically done doesn't impact runtime performance, at least not to the scale you're talking about here; it's a very different tradeoff.
19:19amalloyAWizzArd: no, you want destructuring with unknown keys
19:20amalloyignore the "file" part of this entirely - then you're asking for (with-map m body), where body is evaluated with all the locals in m implicitly bound
19:20AWizzArdYes.
19:20amalloywhich is totally possible and not even hard, but pretty disastrous as an idea
19:20nDuff...even though the code may not even _compile_ if the file doesn't contain the keys it needs/expects.
19:21AWizzArdamalloy: not hard… without using eval?
19:21nDuffActually -- this is silly. Your code knows which keys it needs.
19:21amalloyno, you of course have to use eval
19:21AWizzArdYes, I agree.
19:21nDuffSo, you can just assume that those keys will be present in the file, and use _real_ destructuring.
19:22AWizzArdamalloy: Pretty trivial, just wanted to check if I might have missed something to make this happen without eval.
19:22nDuff("real", meaning compile-time)
19:22amalloyread over http://stackoverflow.com/questions/9345056/in-clojure-how-to-destructure-all-the-keys-of-a-map before you really commit to doing something that i think is a mistake
19:23nDuffAWizzArd: Why can't you use real, fixed-key destructuring, with the set of keys that map to what the code uses?
19:23nDuffAWizzArd: After all, you aren't proposing that the code changes, only that the file does.
19:23AWizzArdWell, I have nearly 10 years Lisp experience, and I am aware of the multitude of problems.
19:24nDuffAWizzArd: ...so there's quite literally no point at all to the extra pain you're wanting to create.
19:25AWizzArdnDuff: The whole purpose is to not have to manually extract those keys.
19:25AWizzArdIt is a pure convenience importer macro.
19:25nDuffAWizzArd: not to extract them from the code, as opposed to from the file, right?
19:25AWizzArdFor FXML files ==> JavaFX
19:25nDuffAWizzArd: So you can just have your macro analyze the code at compile time; done.
19:25amalloyoh god
19:25AWizzArdYes?
19:25clojurebotyes isn't is
19:25amalloythat's even worse, nDuff
19:26RaynesI think the point amalloy is trying to make is that this is a convenience to you and a terrible, terrible inconvenience to anyone who ever reads your code or works with it, including future you.
19:26RaynesYou don't want this. Stop before it is too late.
19:26amalloy*shrug* we put up the signposts, he disagrees, and the language gives him a way to do it
19:26AWizzArdPlus I think it may turn out useful.
19:27amalloy*nod* if you're doing it as a general-purpose macro where you don't know what the code is or what the config file contains, that's interesting. still has problems, but isn't obviously loony
19:27AWizzArdWell, I read a fxml file, and get a hashmap. The keys are keywords, and the values are JavaFX components.
19:28amalloykeywords? if they're supposed to represent symbols, and you're reading the file rather than eval'ing it, it makes more sense to store symbols as keys
19:29AWizzArdI am really saving a (let [username-label (:username-label fxml), password-label (:password-label fxml), username-text (:username-text fxml) …)
19:29AWizzArdA bigger program with several UIs would require always a 20 line let in the setup functions. This can be reduced to a one-liner.
19:30AWizzArd(with-fxml ["login-ui" "email-ui"] body)
19:31AWizzArdThis is actually nicer than a 21 line let.
19:31AWizzArdBut yes, if this turns out to be too problematic, I will remove it before a 1.0.
19:33AWizzArdAlso that macro can type-hint all those symbols, so calling into .methods will do no reflection. Type hints are really required, since the UI thread should not be slowed down from reflection.
19:41AWizzArdTrivial, thanks to Clojure’s power: (mapcat (fn [[k v]] [(with-meta (symbol (name k)) {:tag (class v)}) v]) my-map)
19:48amalloyuhhhhh, is that going to work? it's hard to imagine values for v where the class can be usefully typehinted and the value can be embedded into code
19:50AWizzArdThe values are Buttons, Labels, TextFields, etc.
19:51amalloyi don't think you'll be able to embed those in code
19:51AWizzArdAnd in the body one wants to do things such as (.setText password "").
19:52amalloytry it: (defmacro let-button [& body] `(let [~'button ~(make-button-object)] ~@body))
19:52AWizzArdUseful when we get a (let [^PasswordField password (:password fxml)] …)
19:53AWizzArdinstead of ~'button it should probably be something like ~(with-meta 'button {:tag Button})
19:53amalloyAWizzArd: yes, but that's not relevant to my objection
19:53AWizzArdThen I don’t understand it yet. Could you say it in other words?
19:55amalloyAWizzArd: either v is a Button object, or it's code that you could evaluate to produce a Button
19:55amalloyif the former, then you can't embed it as part of the let statement
19:55amalloyif the latter, you won't have its class yet
19:56amalloyalso, you want {:tag `Button}, not {:tag Button}; tags are symbols, not classes
19:57AWizzArdYes, it was just a sketch.
19:57AWizzArdI will experiment with this now.
20:01AWizzArdamalloy: I can go around this by not taking the (class v) but (class (eval v)).
20:01AWizzArdThe interesting thing here is though that the symbols that end up in the body, are different from the ones in the let.
20:02amalloyi don't understand that last
20:03AWizzArdamalloy: try this: (defmacro bar [m & body] (let [lala (mapcat (fn [[k v]] [(with-meta (symbol (name k)) {:tag (class (eval v))}) v]) m)] `(let [~@lala] ~@body)))
20:04AWizzArdamalloy: then in the repl: (def x (macroexpand '(bar {foo (:lup {:lup "Hi"})} (.length foo))))
20:05AWizzArd(-> x second first meta) ==> String, but (-> x last last meta) ==> nil
20:05amalloyof course
20:05AWizzArdAlthough when you try both -> forms without the last meta, you will both times see it is foo.
20:05amalloyjust like without a macro
20:05AWizzArdBut also that can be solved :-)
20:05amalloywhat? don't solve it
20:05amalloyit's not a problem
20:06AWizzArdWhy not? I want those type hints.
20:06amalloyno you don't
20:06amalloy(let [^Foo x 1] x) - nobody writes (let [^Foo x 1] ^Foo x), because there's no reason
20:06AWizzArdTurn on reflection warnings, and you will see that (bar {foo (:lup {:lup "Hi"})} (.length foo)) throws a warning.
20:07AWizzArdI want that the vars in the body inherit the type hints from the let.
20:07AWizzArdSo I need the identical (hinted) symbols in the body.
20:07amalloyno you don't
20:07amalloythey always inherit
20:07amalloythe problem is still what i said: tags are symbols, not classes, and you're trying to use a class
20:08AWizzArdAh, right.
20:08AWizzArdGood point.
20:09AWizzArdYes, works.
20:10AWizzArdLot’s of evals, but currently I still think this is a valid use case for it. I am thankful for the scepticism to use it, but I want to remind that I am the guy who invented scepticism against the use of eval.
20:11amalloyshit, really? i thought you were dead, mister mccarthy
20:11AWizzArd;)
20:12AWizzArdIn fact, so far my only real usecase for it was my Genetic Programming lib, where it is obviously the right choice.
20:12AWizzArd(as the whole point is the creation of code at runtime, and then run it)
20:40dybaShould I be expecting an OutOfMemoryError when using (range) ?
20:40dybaI understand (range) creates a lazy sequence from 0 to positive infinity
20:40AWizzArdFortunately range is lazy, as you said.
20:40dybabut I guess I don't quite understand what lazy means
20:40AWizzArdSo it will only produce those numbers when they are needed.
20:41dybaso I shouldn't be expecting an out of memory error, correct?
20:41AWizzArdYes.
20:41AWizzArdJust don’t keep a pointer to the begin of the sequence.
20:41dybathe only string i get explaining the error is Java heap space
20:42dybamy test is currently failing
20:42AWizzArd(doseq [n (range)] (when (= n 9999999999999) (System/exit 0))) will run fine, without killing the RAM. It would run a long time though.
20:43dybaAWizzArd: I was just running a simple test to make sure I understand what to expect from using range
20:43dybainside a test I wrote:
20:43dyba(is (= 0 (range)))
20:44dybabut that's not quite correct, it should fail
20:44dybabut i got a failure for a different reason, i.e. OutOfMemory
20:44dybaAWizzArd: so would your approach be a better way to test what I had in mind?
20:47AWizzArdWell, (range) is a sequence of numbers.
20:47AWizzArdThe 0 is one of them.
20:47AWizzArdBut “a sequence of numbers” is not equal to the number zero.
20:48AWizzArdBut (is (= 0 (first (range)))) should succeed.
20:48dybaright
20:49ToxicFrog<dyba> but I guess I don't quite understand what lazy means - lazy seqs evaluate each element only as needed. (take 5 (range)) evaluates only the first five elements in the seq, even though the seq is, in principle, infinite.
20:50AWizzArdamalloy: it is in fact very exciting how easy this is in Clojure. Java developers who want to work with FXML will have to manually extract all their components which they want to refer to in event handlers.
20:50AWizzArdThat option is still available in my lib, and it also has advantages. But being able to automtically import them is a very nice feature.
20:50dybaToxicFrog: so (range) shouldn't return anything because I haven't carried out any operations on it?
20:50ToxicFrogDepends on what you do with it
20:51ToxicFrog(= 0 (range)) might actually evaluate the entire sequence as it tries to do the compare.
20:51dybaah I see, hence the OutOfMemory error
20:52aamardyba: it also might be the clojure.test framework creating the error, as it tries to inform you why the equality comparison failed.
20:53ToxicFrogYeah, in that case it might try to evaluate the seq so that it can print it or something.
20:53ToxicFrogAnd then boom.
20:53dybaaamar: I believe you are right, I would have to see what = is doing under the covers
20:53aamarI suspect it's that, because (if (= 0 (range)) 1 2) works fine for me
20:53ToxicFrogAlright then
20:54AWizzArd,(= 0 (range)) ; = does not traverse the whole range
20:54clojurebotfalse
20:55dybathanks <ToxicFrog>, <aamar>, <AWizzArd>!
20:56dybaoh so it's probably the 'is' in the testing clojure.test framework
20:57AWizzArdThat may be it.
20:58AWizzArdThough I would find that a bit surprising.
21:08dybarange doesn't look like it's capable of handling floats correctly, am I correct?
21:08AWizzArdWhat means “handling floats”?
21:08dybaI just tried (range 1.0 2.0 0.2) and it didn't quit get to 1.6
21:08dybait gave me 1.5999999
21:09dybait gave me (1.0 1.2 1.4 1.59999... 1.79999... 1.99999...)
21:09AWizzArddyba: You would like to read http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
21:10AWizzArd“What Every Computer Scientist Should Know About Floating-Point Arithmetic”
21:10dybaAWizzArd: will do, I'll check it out right now
21:10AWizzArdIt is a pretty long read, but important stuff in there.
21:11AWizzArd,(range 1 2 1/5)
21:11clojurebot(1 6/5 7/5 8/5 9/5)
21:11dybaAWizzArd: Ah ha! you used a rational
21:11dybaI forgot about those in Clojure
21:12AWizzArdAlthough 1.5999999 is as close as you can get to 1.6, when you just can express 4 billion different numbers (i.e. floats).
21:13AWizzArdYou have only 2^32 numbers available (4 billion), as floats have to encode those numbers in 32 bits.
21:17FrozenlockIs there some mechanism to install and auto-run a clojure app at each reboot? (Or is this more of a java question?)
21:18AWizzArddyba: the engineers who implemented this had a pretty hard job. Out of all numbers they had to choose 4 billion that can be expressed with a float. Obviously nearly all numbers had to be excluded. They concentrated on numbers that are typically interesting to scientists.
21:18AWizzArdFrozenlock: more a question of your operating system.
21:19FrozenlockTrue. Let's say a windows machine. I already use launch4j to wrap my jars, but I would like a proper installation.
21:19AWizzArddyba: what you can do though is not using the floating-point unit that ships with your mainboard, but instead use a java.math.BigDecimal, which has a different representation and allows for much more precision.
21:20AWizzArddyba: in Clojure there is even a reader syntax for such numbers. Just append an uppercase “M”:
21:20AWizzArd,(range 1.0M 2.0M 0.2M)
21:20clojurebot(1.0M 1.2M 1.4M 1.6M 1.8M)
21:22AWizzArdFrozenlock: this is a not so trivial issue and has not really to do with Clojure or Java. You should try in #Windows. If you know about Windows Services you might be interested in http://yajsw.sourceforge.net/
21:22AWizzArdFrozenlock: it will probably take you 3-15 hours to get this working.
21:22FrozenlockHmmmm so adding the Frozenlock effect, I should count 48 hours :P
21:23FrozenlockThanks, I'll take a look!
21:23AWizzArdBut a very simple way would be to run a .bat file on reboot. In that file you have a line such as: start java -jar c:/users/frozenlock/Desktop/nice-tool.jar
21:24AWizzArdThat’s a fast and nice way for small admin UIs and such. But professional server software should really run as a Service.
21:24FrozenlockYeah it does sound hacky- but for a proof of concept it might be enough. Thank you very much!
21:27dybaAWizzArd: I'll look into that, thanks!
21:32ToxicFrogGod, I hate deploying on windows.
21:38dybaToxicFrog: are you doing that for work?
21:40ToxicFrogdyba: no, but one of my current projects is designed to integrate with a game released on windows and OSX
21:40ToxicFrogSo it needs to work on windows
21:49dybaAWizzard: yup, the BigDecimal instance works better for the use case I had brought up
22:01evildaemonI'm not quite sure I understand the "lists" model of data processing.
22:01evildaemonI know all the data structures are immutable. But I'm not sure how to build new lists out of the old ones.
22:04evildaemonAs an example, if I try to use conj to build a new list, I get a list bubble and then the contents of the other list.
22:04evildaemonCons does the same thing.
22:04ToxicFrogHow are you using them?
22:04ToxicFrog,(cons 1 '(2 3 4))
22:04clojurebot(1 2 3 4)
22:05evildaemonToxicFrog: Thank you.
22:05ToxicFrog,(cons '(2 3 4) 1)
22:05clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>
22:05ToxicFrogWhups
22:05ToxicFrog,(cons '(2 3 4) '(1))
22:05clojurebot((2 3 4) 1)
22:05evildaemonlol.
22:06evildaemonWait, isn't it kind of dangerous to have a clojure interpreter just sitting in the IRC channel?
22:07ToxicFrogPretty sure it's sandboxed so that you can't actually damage anything
22:07ToxicFrog,(println (range))
22:07clojurebot(0 1 2 3 4 ...)
22:07ToxicFrog,(dorun (map println (range)))
22:07clojurebotExecution Timed Out
22:08evildaemonToxicFrog: I suspected as much, couldn't see how the channel wouldn't be spammed to death by recursive functions otherwise.
22:09ToxicFrog,(dorun (map println (range 1 100)))
22:09clojurebot1
22:09clojurebot2
22:09clojurebot3
22:09clojurebot4
22:09clojurebot5
22:09ToxicFrogOh god
22:09clojurebot6
22:10clojurebot7
22:10clojurebot8
22:10clojurebot9
22:10clojurebot10
22:10ToxicFrogI'm so sorry
22:10clojurebot11
22:10clojurebot12
22:10clojurebot13
22:10clojurebot14
22:10clojurebot15
22:10clojurebot16
22:10clojurebot17
22:10clojurebot18
22:10clojurebot19
22:10clojurebot20
22:10clojurebot21
22:10ToxicFrogI should have PMd that
22:10clojurebot22
22:10clojurebot23
22:10clojurebot24
22:10clojurebot25
22:10clojurebot26
22:10clojurebot27
22:10clojurebot28
22:10clojurebot29
22:10clojurebot30
22:10clojurebot31
22:10clojurebot32
22:10clojurebot33
22:10TheBusbynice, like times of old
22:10clojurebot34
22:10clojurebot35
22:10clojurebot36
22:10clojurebot37
22:10clojurebot38
22:10clojurebot39
22:10clojurebot40
22:10ToxicFrogevildaemon: it's not nearly as well sandboxed as I thought :/
22:10clojurebot41
22:10clojurebot42
22:10clojurebot43
22:10clojurebot44
22:10clojurebot45
22:10clojurebot46
22:10clojurebot47
22:10clojurebot48
22:10clojurebot49
22:10clojurebot50
22:10clojurebot51
22:10clojurebot52
22:10clojurebot53
22:10clojurebot54
22:10clojurebot55
22:10clojurebot56
22:10clojurebot57
22:10ToxicFrogAlso, I should have tested with (range 1 5)
22:10clojurebot58
22:10evildaemonGoddamit.
22:10clojurebot59
22:10clojurebot60
22:10clojurebot61
22:10clojurebot62
22:10clojurebot63
22:10clojurebot64
22:10clojurebot65
22:10clojurebot66
22:11clojurebot67
22:11FrozenlockThat's funny
22:11clojurebot68
22:11clojurebot69
22:11clojurebot70
22:11clojurebot71
22:11clojurebot72
22:11clojurebot73
22:11clojurebot74
22:11clojurebot75
22:11clojurebot76
22:11FrozenlockIsn't there a time limit for clojurebot?
22:11clojurebot77
22:11clojurebot78
22:11evildaemonI'm sorry I said anything.
22:11clojurebot79
22:11clojurebot80
22:11clojurebot81
22:11clojurebot82
22:11clojurebot83
22:11clojurebot84
22:11clojurebot85
22:11clojurebot86
22:11clojurebot87
22:11clojurebot88
22:11clojurebot89
22:11clojurebot90
22:11clojurebot91
22:11clojurebot92
22:11clojurebot93
22:11clojurebot94
22:11clojurebot95
22:11clojurebot96
22:11clojurebot97
22:11clojurebot98
22:11clojurebot99
22:11ToxicFrogFeature request for clojurebot: combine multiple lines of output into single IRC message; restrict the number of messages a single command can emit.
22:11evildaemonYes.
22:12FrozenlockAt least now we know.
22:12evildaemonWhat? No one ever tried that before?
22:12TheBusbyan knowing is half the battle?
22:13FrozenlockYup, now we know who the enemy is :)
22:13Frozenlock,flame ToxicFrog
22:13clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: flame in this context, compiling:(NO_SOURCE_PATH:0)>
22:13FrozenlockWhat, no flame bot?
22:14ToxicFrogFrozenlock: there is a time limit, but apparently that didn't hit it!
22:14evildaemon(defn 787 (print 5))
22:14evildaemon,(defn 787 (print 5))
22:14clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Parameter declaration print should be a vector>
22:15evildaemonOh right, arguments.
22:15FrozenlockI think defn is forbidden as a protection
22:15FrozenlockIsn't it?
22:15evildaemon(defn 787 [] (print 5))
22:15evildaemon,(defn 787 [] (print 5))
22:15clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IObj>
22:15ToxicFrog,(defn foo [x] (println x)) (foo 1)
22:15clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
22:15ToxicFrogYep.
22:15evildaemonAh.
22:15ToxicFrogSANBOX.
22:15evildaemonInteresting.
22:16evildaemonSo I would assume that def and fn are blocked as well?
22:16FrozenlockHopefully
22:20evildaemon,(def test556 9)
22:20clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
22:20Frozenlock, (map (fn [a] (print a)) [1 2 3 4])
22:20clojurebot(1234nil nil nil nil)
22:20Frozenlockwut
22:21evildaemonlol.
22:21FrozenlockIt does the same thing on my repl....
22:21FrozenlockWhat am I missing here
22:21evildaemonOh dear.
22:22Frozenlock, (map (fn [a] a) [1 2 3 4])
22:22clojurebot(1 2 3 4)
22:23FrozenlockOh I see... Print send them to *out* (which is the repl), the return nil for everyone of them.
22:23Frozenlock*then
22:24evildaemonI love how the last github commit is entitled: "Should have thought this through."
22:24arohneris there a library like trammel that can be used to provide "inheritance" for fn contracts?
22:25Frozenlockevildaemon: Funny, but kinda lack precision
22:25arohnerI'd really like to define a contract for a class of fns, and then define new fns, that match the same contract
22:26arohnerand it'd be amazing if at least part of it was verified at compile time
22:41evildaemon,(print "(+ 2 2)")
22:41clojurebot(+ 2 2)
22:42evildaemon ,(print ",(+ 2 2)")
22:42clojurebot,(+ 2 2)
22:47FrozenlockOk I'm doing it, jumping to lein 2 and clojure 1.4, wish me luck!
22:48evildaemonToxicFrog: How do I do that with named lists?
22:49ToxicFrogevhan: "named lists"?
22:50evildaemonToxicFrog: You know, lists that have symbols attached with def or let.)
22:50ToxicFrogEr
22:50tos9evildaemon: I checked that :)
22:50tos9evildaemon: It's amazing how many bots are vulnerable to that sort of exploit.
22:51ToxicFrogevildaemon: you're going to have to explain in more detail what you're trying to ask
22:52evildaemontos9: I didn't feel like pushing it, but I briefly thought: "I wonder if I look at the source I'll discover that trick will work if you append a users name and timestamp before it."
22:53evildaemonToxicFrog: (def r (list 7 7 6 5 0))
22:53evildaemonNot sure what it's actually called.
22:53ToxicFrogOk, in that case, what is the "that" that you want to do?
22:57evildaemonToxicFrog: This could take while.
22:58ToxicFrogevildaemon: I mean, it looks like you're asking "how do I print a list by name" but that's the same as anything else - (def r '(1 2 3 4 5)) (println r)
22:58ToxicFrogSo you must be asking something else
22:59evildaemonToxicFrog: How do I combine two lists?
23:00mindbenderanyone using counterclockwise here?
23:01ToxicFrogevildaemon: depends on what you mean by "combine", but probably (concat xs ys)
23:01ToxicFrog,(concat '(1 2 3) '(4 5 6))
23:01clojurebot(1 2 3 4 5 ...)
23:01ToxicFrogevildaemon: also, it sounds like you need this: http://clojure.org/cheatsheet
23:01ToxicFrogIt is damn useful.
23:02evildaemonToxicFrog: Yes.
23:37mindbenderwith counterclockwise I'm having trouble importing a github project, need I install git for eclipse
23:37mindbender?
23:41acristinmindbender: I haven't installed git for eclipse, and I have been able to import github projects that I had cloned through the git commandline tool, but I think eclipse copied the whole directory into my workspace. I'm not sold on counterclockwise yet, so I didn't really try very hard
23:44mindbenderacristin: ok.. I'm still exploring too and wondering why it won't even recognize my cloned repo in the first place but I'm corresponding with Laurent, a top maintainer of ccw, thanks for sharing your experience!
23:53ssutchis it possible to def a function that can respond differently to different keyword arguments, eg
23:54ssutch,(defn a ([{a1 :a1}] ("something")) ([{a2 :a2}] ("something else"))
23:54clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>
23:54ssutch,(defn a ([{a1 :a1}] ("something")) ([{a2 :a2}] ("something else")))
23:54clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
23:54ssutchbajh
23:55ssutch"cant have 2 overloads with the same arity" is what it should print