2012-07-07
| 00:00 | duck1123 | I'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:00 | mthvedt | by deferring looking up symbols, rules can be immutable and you don't have any forward-declaring |
| 00:01 | duck1123 | the one just calls the other, so I don't see what could be going on. |
| 00:01 | mthvedt | if you want recursive rules |
| 00:01 | mthvedt | i 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:02 | mthvedt | grabbing the *ns* is also unclojure-ish, but IMO a lesser evil |
| 00:02 | ToxicFrog | Fair enough |
| 00:03 | ToxicFrog | Hmm. |
| 00:03 | ToxicFrog | The NPE is not limited to redefing 'name |
| 00:03 | mthvedt | yes, looks like redefining any clojure.core fn does it? |
| 00:04 | ToxicFrog | >.< |
| 00:04 | ToxicFrog | I 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:06 | mthvedt | Is the clojure team aware of this issue? It seems to be known in the google groups threads |
| 00:07 | mthvedt | is there a clojure JIRA or something to search? |
| 00:07 | mthvedt | it's known to happen in both lein and maven compilation |
| 00:08 | ToxicFrog | It does, in fact: http://dev.clojure.org/jira/secure/Dashboard.jspa |
| 00:09 | mthvedt | it does not happen except in precompiled code, so that and it being discouraged usage make it low on the radar probably |
| 00:09 | ToxicFrog | Back to Clearly for a moment - |
| 00:09 | mthvedt | ok |
| 00:10 | ToxicFrog | I'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:10 | ToxicFrog | In something like scala.util.parsing or flex+yacc, I'd just use regexes here. |
| 00:10 | ToxicFrog | In Clearly, I have this: https://gist.github.com/fb903793baa2e918aae0 |
| 00:10 | ToxicFrog | Is there a better way to do this? Because this seems super awkward. |
| 00:12 | mthvedt | yup, clearley only eats one item of input at a time |
| 00:12 | ToxicFrog | (also, it would be really nice to be able to construct rules from regexes, specifically for this sort of thing) |
| 00:12 | ToxicFrog | So is it expected to be paired with a lexer? |
| 00:12 | mthvedt | doesn't need to be, though you can if you want to |
| 00:13 | ToxicFrog | Well, yes, it doesn't need to be, but it looks like it would make stuff like this a lot simpler |
| 00:13 | mthvedt | the earley algorithm can be modified to scan multiple items in one low-level rule… it's fairly easy, but it's nontrivial |
| 00:13 | ToxicFrog | There's a lot of code in the json parser as well working around this |
| 00:13 | mthvedt | it's on my "todo" list |
| 00:14 | mthvedt | try |
| 00:14 | mthvedt | i |
| 00:14 | mthvedt | instead of having 9 lines |
| 00:14 | mthvedt | scanner and one-or-more both return rules |
| 00:14 | mthvedt | so i think you can do (def x (one-or-more y (scanner z))) |
| 00:15 | mthvedt | once the rule API is cleaned up, you could just write a clearly regex parser that emits a clearly rule :) |
| 00:15 | mthvedt | and by you, i mean me |
| 00:15 | ToxicFrog | What is y meant to be there? I'm still a bit shaky on "rule heads". |
| 00:16 | ToxicFrog | Well, yes, I was contemplating how hard it would be for me to do, given the current state of Clearley :P |
| 00:16 | mthvedt | oh sorry |
| 00:16 | mthvedt | (def x (one-or-more (scanner y z))) is what i meant to type |
| 00:16 | mthvedt | (def sfs-type (one-or-more (scanner #(…) identity))) |
| 00:17 | mthvedt | try that |
| 00:17 | ToxicFrog | That works fine, thanks |
| 00:17 | ToxicFrog | And is easily macroized too. |
| 00:18 | ToxicFrog | And now that the parser compiles, my super major #1 feature request: useful error reporting when a parse fails. |
| 00:18 | ToxicFrog | This is my #1 reason for using a parsing library rather than just rolling my own recursive descent parser: error reporting. |
| 00:20 | mthvedt | yeah, about that... |
| 00:21 | mthvedt | i hope you don't have to throw your work away… clearly has almost no error reporting at this time |
| 00:22 | mthvedt | or when you say that's a feature request, you just mean, would be very nice to have? |
| 00:23 | ToxicFrog | For 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:24 | mthvedt | ok, cool |
| 00:24 | ToxicFrog | Also 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:24 | ToxicFrog | For projects where this is not the case, yeah, it would be a serious issue. |
| 00:25 | mthvedt | yup |
| 00:25 | mthvedt | one attractive thing about bottom-up parsers is error reporting is a lot more natural... |
| 00:28 | ToxicFrog | For reference, errors from scala.util.parsing - which are, so far, the best I've seen - take the form: |
| 00:28 | ToxicFrog | [29.1] failure: string matching regex `= *[^\n]*' expected but `a' found |
| 00:28 | ToxicFrog | Followed by the offending line, and a carat pointing out the exact location in the line. |
| 00:28 | ToxicFrog | (this is generated by a method on the error object; all of this information can be extracted by the program easily as well) |
| 00:29 | mthvedt | i've never used scale's parsing library, but it looks very nice |
| 00:29 | mthvedt | isn't it top-down, though? i wonder how they make sense of errors |
| 00:30 | ToxicFrog | To be honest, I have no idea |
| 00:30 | ToxicFrog | The 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:32 | ToxicFrog | Of 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:32 | ToxicFrog | Scala's standard library is not exactly lightweight. |
| 00:33 | mthvedt | working with top-down parsers is what drove me to bottom-up parsers in the first place :P |
| 00:33 | mthvedt | we had a use case at work that involved a complex, highly mutually recursive grammar |
| 00:33 | mthvedt | existing grammars, even those that advertised the ability to handle left recursion, just all blew up |
| 00:34 | ToxicFrog | I haven't observed such issues with Scala's parsers, but I've never tried parsing anything super complex with them |
| 00:34 | mthvedt | anyway, i really gotta get some rest soon... |
| 00:35 | ToxicFrog | Ok. Now to actually fix this so that it works |
| 00:35 | ToxicFrog | Since what prompted me to mention error messages was that my parse is failing (because it does no whitespace handling at present) |
| 00:35 | ToxicFrog | Hmm. Maybe I should give it a lexer. |
| 00:37 | mthvedt | if you're too lazy to handle whitespace… s/\s+/ /g :P |
| 00:37 | ToxicFrog | mthvedt: problem with that is, note the rule for sfs-value |
| 00:37 | ToxicFrog | It's everything from the = to the end of line preserving whitespace |
| 00:38 | mthvedt | there's some whitespace rules in the json example |
| 00:39 | ToxicFrog | Yeah; it gets kind of messy. |
| 00:40 | ToxicFrog | This'll be good practice; it's been ages since I wrote a divided lexer/parser |
| 00:58 | ToxicFrog | Huh |
| 00:59 | ToxicFrog | I can do this: #(Character/isLetterOrDigit %) |
| 00:59 | ToxicFrog | But I can't do this: (partial Character/isLetterOrDigit) |
| 01:03 | mthvedt | toxicfrog: because java methods are not clojure fns |
| 01:04 | mthvedt | they are actually clojure special forms |
| 01:05 | ToxicFrog | Oh :( |
| 01:05 | ToxicFrog | Am I pretty much limited to #() and equivalents for that, then? |
| 01:06 | mthvedt | pretty much |
| 02:51 | aperiodic | i 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:53 | aperiodic | on 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:53 | amalloy | as well it should |
| 02:55 | amalloy | &(let [andf (comp (partial every? identity) list)] (andf true false)) |
| 02:55 | lazybot | ⇒ false |
| 02:55 | amalloy | &(let [andf (comp (partial every? identity) list)] (andf true true)) |
| 02:55 | lazybot | ⇒ true |
| 02:55 | aperiodic | man, whenever i do some thing weird with HOFs i should just come here and bug you |
| 02:56 | amalloy | my 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:02 | aperiodic | the reason i ended up writing them was to construct the predicate i wanted to pass to things like every? and some |
| 03:03 | aperiodic | andf and orf are functions on predicates, not booleans |
| 03:04 | amalloy | so you're saying they're some-fn and every-pred? |
| 03:05 | aperiodic | yeah, that's what i'm saying |
| 03:05 | amalloy | &(doc some-fn) |
| 03:05 | lazybot | ⇒ "([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:05 | amalloy | &(doc every-pred?) |
| 03:05 | lazybot | java.lang.RuntimeException: Unable to resolve var: every-pred? in this context |
| 03:05 | amalloy | &(doc every-pred) |
| 03:05 | lazybot | ⇒ "([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:50 | wubino | any good reads on creating a pastebin like service? |
| 04:05 | borkdude | wubino check out https://github.com/Raynes/refheap and www.refheap.com |
| 04:27 | ro_st | are there any compelling reasons NOT to use immutant? |
| 04:27 | ro_st | put another way, what's the catch? |
| 04:28 | hiredman | I wonder how well it would work in a heterogeneous environment |
| 04:29 | ro_st | ok, so one thing is you couldn't do is host on something like heroku |
| 04:29 | hiredman | in 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:31 | ro_st | it's still pretty new |
| 04:31 | hiredman | yeah, but interest is building, and it is gaining features, someone will give it a trial by fire |
| 04:32 | ro_st | not having to build out all the stuff it provides is quite compelling |
| 04:32 | hiredman | yes, but at work we've already built all that stuff :) |
| 04:32 | clojurebot | http://haacked.com/images/haacked_com/WindowsLiveWriter/IConfigMapPathIsInaccessibleDueToItsProt_1446B/works-on-my-machine-starburst.png |
| 04:33 | hiredman | a lot of features seemed to be sort of aimed at webapps instead of backend data processing apps |
| 04:33 | ro_st | perfect for us |
| 04:33 | ro_st | i'm in the process of writing a json api, and shortly will be needing to port ruby/resque based stuff for messaging over |
| 04:38 | hiredman | the custering stuff would be really cool, but I would prefer to be able to swap out discovery mechanisms (just use zookeeper) |
| 04:39 | hiredman | I don't trust the jgroups stuff |
| 04:39 | ro_st | i reckon it's worth playing with |
| 04:40 | ro_st | gotta run! |
| 05:22 | _ulises | morning 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:38 | AWizzArd | Protocol 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:39 | AWizzArd | (defprotocol Bar (foos [x])) and then (extend-protocol Bar clojure.lang.IFn (foos [x] (println :fn)) java.util.Map (foos [x] (println :map))) |
| 08:40 | AWizzArd | Now I want that (foos {}) prints :map. |
| 09:22 | daniel___ | im looking for the most concise way of checking if all the values in a list equal something? |
| 09:22 | daniel___ | ,(map #(= % 1) '(1 2 3 4 5)) |
| 09:22 | clojurebot | (true false false false false) |
| 09:22 | daniel___ | ,(contains? false (map #(= % 1) '(1 2 3 4 5))) |
| 09:22 | clojurebot | false |
| 09:23 | daniel___ | ,(apply #(= true %) (map #(= % 1) '(1 2 3 4 5))) |
| 09:23 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: sandbox$eval87$fn> |
| 09:23 | madsy | daniel___: Maybe every? |
| 09:23 | daniel___ | madsy maybe |
| 09:24 | daniel___ | ,(every? true (map #(= % 1) '(1 2 3 4 5))) |
| 09:24 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn> |
| 09:24 | daniel___ | ,(every? #(= true %) (map #(= % 1) '(1 2 3 4 5))) |
| 09:24 | clojurebot | false |
| 09:24 | daniel___ | :) |
| 09:37 | inklesspen | daniel___: 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:40 | clojurebot | #<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:41 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0)> |
| 09:44 | _ulises | shame that and is a macro, otherwise it'd be great to reduce your checks using and |
| 09:45 | inklesspen | ,(apply (partial = 1) '(1 1 1 1)) |
| 09:45 | clojurebot | true |
| 09:46 | inklesspen | ,(apply (partial = 1) '(1 2 3 4)) |
| 09:46 | clojurebot | false |
| 09:46 | _ulises | lovely |
| 09:48 | AWizzArd | Well, inklesspen already showed the ideomatic solution, which is: (every? #(= 1 %) [1 2 3 4 5]) |
| 09:48 | AWizzArd | _ulises: the function equivalent to `and` is `every?`. |
| 09:49 | inklesspen | AWizzArd: is the anonymous function version any more ideomatic than the partial version? |
| 09:49 | inklesspen | i guess it's shorter |
| 09:49 | AWizzArd | inklesspen: both are okay, but partial is evaluated each time. |
| 09:49 | inklesspen | ah |
| 09:49 | inklesspen | makes sense |
| 09:49 | AWizzArd | While (fn [n] (= n 1)) is directly compiled, and thus a bit more efficient. |
| 09:50 | AWizzArd | Plus: I personally find it more readable. |
| 09:50 | AWizzArd | For this specific case one could do some trickery, such as (= #{1} (set [1 2 3 4 5])) |
| 09:50 | AWizzArd | But this would just check if every element in the seq is =1 |
| 09:51 | AWizzArd | The solution with every? is more generic, and could be used as well for (every? odd? some-numbers) |
| 10:11 | ToxicFrog | Hmm. I wish I could ^Tag strings. |
| 10:14 | mthvedt | toxicfrog: good morning |
| 10:14 | ToxicFrog | 'morning |
| 10:15 | mthvedt | has the parser been working out ok? |
| 10:16 | ToxicFrog | I went to bed at about the same time as you last night; I'm just starting on the lexer now |
| 10:16 | ToxicFrog | Although I did think of a lexer-related question |
| 10:16 | mthvedt | shoot |
| 10:16 | ToxicFrog | When 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:17 | ToxicFrog | Eg, [\{ keyvalues \}] |
| 10:17 | ToxicFrog | How 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:17 | ToxicFrog | I think that using a scanner that checks :tag would work, so you do something like: |
| 10:18 | ToxicFrog | (def open-brace (scanner #(= (:tag %) :open-brace) identity)) |
| 10:18 | ToxicFrog | And then use [open-brace keyvalues close-brace] |
| 10:18 | mthvedt | matched with = |
| 10:18 | ToxicFrog | But is there a better way? |
| 10:19 | mthvedt | there's support for what i'm currently calling "tokenizers" |
| 10:19 | mthvedt | i |
| 10:19 | mthvedt | i'm not sure if they're a good idea, and might change/remove them |
| 10:19 | mthvedt | but basically, to test for a terminal symbol x |
| 10:19 | mthvedt | t |
| 10:20 | mthvedt | the parser runs (= x (tokenizer input)) |
| 10:20 | mthvedt | where the default tokenizer is identity |
| 10:21 | mthvedt | that's still a little cumbersome, because each parse action needs to have :text in it anyway |
| 10:22 | mthvedt | you pass the tokenizer fn to build-parser |
| 10:23 | mthvedt | (build-parser goal-rule tokenizer) |
| 10:23 | ToxicFrog | Hmm |
| 10:23 | ToxicFrog | The 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:24 | ToxicFrog | { :tag :number :text "12.34" :line 5 :col 8 } |
| 10:24 | ToxicFrog | And 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:25 | mthvedt | you could pass :tag as your tokenizer |
| 10:25 | mthvedt | if your input symbols are maps you want to parse the :tags of |
| 10:27 | ToxicFrog | Ok, but in that case, is the return value of the rule just the :tag, or the entire map originally passed to tokenizer? |
| 10:28 | mthvedt | the return value will be the entire map |
| 10:29 | ToxicFrog | Awesome |
| 10:36 | augustl | is it possible to access the persistent data structures from ClojureScript in a Node.js app, without converting my app to ClojureScript? |
| 10:36 | nDuff | augustl: it'll be easier to have your ClojureScript code export to native structures. |
| 10:37 | augustl | I don't have any ClojureScript code :) |
| 10:37 | augustl | I could use persistent data structures though |
| 10:37 | augustl | ah, I see |
| 10:37 | nDuff | augustl: ...oh, you mean you want to _create_ them from native JS code, not just leverage them? |
| 10:38 | augustl | yes |
| 10:38 | augustl | similar to how you can create PersistentVector etc from java (right?) |
| 10:38 | nDuff | Hmm. Well, there's nothing stopping you from calling cljs.core.PersistentVector.fromArray() from native JavaScript |
| 10:39 | augustl | is cljs.core etc. available as one JavaScript file somewhere? |
| 10:39 | nDuff | augustl: ...run a compilation pass, and the output is one JavaScript file. |
| 10:40 | augustl | cool, thanks |
| 10:40 | nDuff | (when compiling with lein-cljsbuild, anyhow) |
| 10:41 | augustl | writing some code where my client for a server needs to get all state, even when it goes down |
| 10:41 | augustl | datomic-esque time semantics with persistent data would make sense for that I think |
| 10:42 | augustl | a 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:44 | ToxicFrog | What's idiomatic for "find the first value in a coll satisfying p"? |
| 11:45 | ToxicFrog | (first (filter p coll)) ? |
| 11:47 | hyPiRion | ToxicFrog: Yeah. |
| 11:54 | ToxicFrog | I keep wanting to call it "first" or "find", but clojure already uses both of those @.@ |
| 11:58 | Sorella | ToxicFrog, find-first? |
| 12:00 | ToxicFrog | Sorella: yeah, that's what I went with. |
| 12:01 | ToxicFrog | (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:01 | TimMc | ToxicFrog: While you're at it, you could add an optional not-found argument. |
| 12:05 | daniel___ | ((a b c) (d e f) (g h i)) is there an ingenius way of testing if a = e = i? |
| 12:05 | daniel___ | ingenious* |
| 12:06 | daniel___ | or c = e = g |
| 12:07 | daniel___ | with pattern matching perhaps |
| 12:07 | TimMc | core.match is still extremely alpha (buggy), unfortunately. |
| 12:08 | daniel___ | ,(let [((a _ _) (_ b _) (_ _ c)) ((1 2 3)(1 2 3)(1 2 3))] (println a b c)) |
| 12:08 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: ((a _ _) (_ b _) (_ _ c))> |
| 12:08 | hyPiRion | both a = e = i or c = e = g? |
| 12:08 | daniel___ | yeah |
| 12:08 | hyPiRion | use vectors instead |
| 12:08 | TimMc | &(#(let [[[a] [_ b] [_ _ c]] %] [a b c]) '((1 2 3)(4 1 6)(7 8 1))) |
| 12:08 | hyPiRion | ,(let [((a _ _) (_ b _) (_ _ c)) ((1 2 3)(1 2 3)(1 2 3))] (println a b c)) |
| 12:08 | lazybot | ⇒ [1 1 1] |
| 12:08 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: ((a _ _) (_ b _) (_ _ c))> |
| 12:08 | daniel___ | hyPiRion: if i had a vector of length 9? |
| 12:09 | hyPiRion | What TimMc wrote. |
| 12:09 | daniel___ | cool |
| 12:09 | daniel___ | pattern matching only works with vectors? |
| 12:09 | TimMc | daniel___: map, nth, apply |
| 12:09 | TimMc | map-indexed, really |
| 12:10 | TimMc | daniel___: destructuring syntax uses vectors, but can be applied to any collection |
| 12:10 | daniel___ | i c |
| 12:10 | daniel___ | ,(let [[[a _ _] [_ b _] [_ _ c]] ((1 2 3)(1 2 3)(1 2 3))] (println a b c)) |
| 12:10 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 12:10 | daniel___ | ,(let [[[a _ _] [_ b _] [_ _ c]] '((1 2 3)(1 2 3)(1 2 3))] (println a b c)) |
| 12:10 | clojurebot | 1 2 3 |
| 12:10 | daniel___ | cool |
| 12:11 | TimMc | &(#(map-indexed (fn [i el] (nth el i)) %) '((1 2 3)(4 5 6)(7 8 9))) |
| 12:11 | lazybot | ⇒ (1 5 9) |
| 12:12 | TimMc | &(#(map-indexed (fn [i el] (nth el (- (count %) i 1))) %) '((1 2 3)(4 5 6)(7 8 9))) |
| 12:12 | lazybot | ⇒ (3 5 7) |
| 12:13 | daniel___ | neat |
| 12:13 | TimMc | &(apply = '(3 5 7)) |
| 12:13 | lazybot | ⇒ false |
| 12:14 | daniel___ | any advantage over the destructuring approach? |
| 12:14 | TimMc | Extensible. |
| 12:15 | TimMc | This gets you diagonals of any length. |
| 12:15 | daniel___ | 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:15 | TimMc | That's why you (defn diagonal ...) and use that. |
| 12:43 | daniel___ | 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:44 | daniel___ | Perhaps there is already a function to achieve something like this, or with partition-by and map-indexed somehow? |
| 12:44 | metellus | ,(partition 3 [a b c d e f g h i]) |
| 12:44 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(NO_SOURCE_PATH:0)> |
| 12:44 | metellus | ,(partition 3 [1 2 3 4 5 6 7 8 9]) |
| 12:44 | clojurebot | ((1 2 3) (4 5 6) (7 8 9)) |
| 12:45 | daniel___ | yeah, im looking at the padding |
| 12:45 | AWizzArd | alternatively (partition-all 3 your-list) |
| 12:45 | daniel___ | (partition 3 3 [1 2 3 4 5 6 7 8 9]) |
| 12:45 | daniel___ | ,(partition 3 3 [1 2 3 4 5 6 7 8 9]) |
| 12:45 | clojurebot | ((1 2 3) (4 5 6) (7 8 9)) |
| 12:45 | daniel___ | thats not what i need |
| 12:45 | AWizzArd | ,(partition-all 3 (range 10)) |
| 12:45 | clojurebot | ((0 1 2) (3 4 5) (6 7 8) (9)) |
| 12:45 | daniel___ | i need ((1 4 7) (2 5 8) .. |
| 12:46 | AWizzArd | ,(apply map first (partition-all 3 (range 10))) |
| 12:46 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: clojure.lang.ArityException: Wrong number of args (4) passed to: core$first> |
| 12:46 | daniel___ | ,(partition 3 3 3 [1 2 3 4 5 6 7 8 9]) |
| 12:46 | clojurebot | ((1 2 3) (4 5 6) (7 8 9)) |
| 12:46 | daniel___ | ,(partition 3 3 3 3 [1 2 3 4 5 6 7 8 9]) |
| 12:46 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (5) passed to: core$partition> |
| 12:47 | daniel___ | ,(partition 3 1 3 [1 2 3 4 5 6 7 8 9]) |
| 12:47 | clojurebot | ((1 2 3) (2 3 4) (3 4 5) (4 5 6) (5 6 7) ...) |
| 12:47 | dustingetz | o 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:47 | dustingetz | *"does anyone know how to map over a tree" |
| 12:47 | AWizzArd | Maybe this: |
| 12:47 | AWizzArd | (apply map list (partition 3 (range 1 10))) |
| 12:47 | dustingetz | i think this is an example in haskell: http://okmij.org/ftp/continuations/Searches.hs - but i don't understand this |
| 12:47 | AWizzArd | ,(apply map list (partition 3 (range 1 10))) |
| 12:47 | clojurebot | ((1 4 7) (2 5 8) (3 6 9)) |
| 12:47 | daniel___ | there we go |
| 12:47 | daniel___ | :D |
| 12:47 | daniel___ | thanks |
| 12:48 | dustingetz | yeah but i want to define functions like 'bfs' 'dfs' which control the order in which i map |
| 12:48 | metellus | ,(zipmap (partition 3 [1 2 3 4 5 6 7 8 9])) |
| 12:48 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$zipmap> |
| 12:48 | metellus | ,(apply zipmap (partition 3 [1 2 3 4 5 6 7 8 9])) |
| 12:48 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$zipmap> |
| 12:48 | AWizzArd | metellus: partition 2 |
| 12:49 | AWizzArd | No, nonsense. I mean: zipmap needs two args. |
| 12:50 | metellus | too bad |
| 12:51 | wingy | you think this is still valid for learning clj 1.4: https://peepcode.com/products/functional-programming-with-clojure |
| 12:51 | wingy | from 2009 |
| 12:51 | wingy | hm probably not |
| 12:51 | wingy | 3 years old afterall |
| 12:53 | wingy | do we have any from Stockholm here? |
| 13:01 | ohpauleez | dustingetz: Take a look at the kibit code |
| 13:01 | ohpauleez | We use clojure.walk |
| 13:01 | ohpauleez | and you can post and pre walk a tree |
| 13:01 | ohpauleez | we also have a function for seq'ing the tree |
| 13:04 | dustingetz | thanks paul |
| 13:04 | ohpauleez | &(doc tree-seq) |
| 13:04 | lazybot | ⇒ "([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:05 | ohpauleez | np |
| 13:19 | weavejester | technomancy: I'm glad you pointed out "lein deploy" to me! Thanks! |
| 13:20 | ToxicFrog | I wish 'lein deploy' could deploy to github |
| 13:21 | ToxicFrog | (using the github upload-file thingy, I mean, not 'git push') |
| 13:23 | ohpauleez | ToxicFrog: There's documentation on how to host a maven repo on github, so technically ... |
| 13:24 | ToxicFrog | ohpauleez: 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:39 | ToxicFrog | Count number of items in xs satisfying p: (count (filter p xs)) ? |
| 13:54 | AWizzArd | ToxicFrog: yes. |
| 14:20 | wingy | why no def- like defn- |
| 14:20 | wingy | but for vars |
| 14:21 | amalloy | defn- only exists because, long ago, it was inconvenient to put :private metadata on your functions |
| 14:21 | wingy | amalloy: is it still inconventient? |
| 14:22 | amalloy | defining 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:22 | amalloy | not at all. just (defn ^:private foo []) |
| 14:23 | wingy | true |
| 14:23 | wingy | but isn't it better to just use that line then? |
| 14:23 | wingy | and remove defn- to keep things consistent? |
| 14:24 | amalloy | it's unlikely to ever get removed, for compatibility |
| 14:24 | wingy | ok |
| 14:24 | wingy | i guess convenience is good as well |
| 14:24 | amalloy | but 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:25 | wingy | just like you can put a doc string with def instead of having to assign a meta doc each time |
| 14:25 | wingy | but i do think if you really want to remove something bad you can do it by deprecating it |
| 14:26 | wingy | and have it there for 1-2 more versions .. better to progress forward in the longer run |
| 14:34 | Chouser1 | Anyone know why the light table sandbox might be failing for me? |
| 14:35 | Chouser1 | The browser console says "Firefox can't establish a connection to the server at ws://localhost:8833/socket." |
| 14:35 | TimMc | Chouser1: Try chrome. |
| 14:35 | TimMc | It seems to work on only some (random) versions of recent Firefoxen. |
| 14:36 | Chouser1 | this is firefox 15.0a2 |
| 14:42 | Chouser1 | TimMc: Thanks, chrome is working. |
| 15:23 | ssutch | what is the recommended way to provide configuration values to a compojure app? |
| 15:23 | ssutch | eg, database URIs and whatnot |
| 15:25 | arohner | ssutch: you have a lot of options. Depends on the app, mainly |
| 15:25 | ssutch | my main deployment target is a uber war deployed on elastic beanstalk |
| 15:25 | ssutch | that's where i want to run it |
| 15:26 | ssutch | i need to provide it with db uri(s) and private keys and such |
| 15:26 | arohner | I like a bash file full of export FOO=bar |
| 15:26 | arohner | then source it before running |
| 15:27 | arohner | if 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:28 | ssutch | ok |
| 15:28 | ssutch | i'm fine with providing it to the command line |
| 15:28 | ssutch | i guess my only concern is things like a private key |
| 15:29 | arohner | so just export the path to the key |
| 15:30 | piotr | ssutch: hi. Env variable is the recommended way to do on Heroku. See https://devcenter.heroku.com/articles/config-vars |
| 15:32 | kmicu | ssutch: also check this out https://github.com/drakerlabs/milieu |
| 15:33 | ssutch | interesting |
| 15:54 | antares_ | Spyglass now has a doc website: http://clojurememcached.info |
| 15:55 | antares_ | and clojurewerkz.org has a new About page (retweets are greatly appreciated): https://twitter.com/ClojureWerkz/status/221681163641688065 |
| 16:00 | daniel___ | https://gist.github.com/3067920 play is my main entry point, i keep getting nullpointerexception with 'lein run' |
| 16:00 | daniel___ | something to do with the read-line |
| 16:01 | daniel___ | can anyone enlighten me? |
| 16:02 | antares_ | daniel___: read-line can return nil |
| 16:02 | daniel___ | yes, but its not prompting |
| 16:03 | antares_ | actually, disregard, I think it returns empty strings |
| 16:03 | antares_ | daniel___: do you have an example stack trace? |
| 16:04 | daniel___ | added to the gist |
| 16:06 | dnolen | ,(dec nil) |
| 16:06 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 16:06 | dnolen | daniel___: your read-int can nil |
| 16:06 | raek | how can I run a ghci repl in a cabal project? |
| 16:07 | dnolen | raek: wrong channel ;) |
| 16:07 | dnolen | daniel___: I mean your read-int can return nil |
| 16:08 | daniel___ | dnolen: if i take away the dec, i get an argument error |
| 16:08 | amalloy | console input doesn't work in lein run |
| 16:08 | daniel___ | for some reason it isnt prompting |
| 16:08 | daniel___ | oh |
| 16:08 | amalloy | try lein trampoline run |
| 16:08 | daniel___ | amalloy: works |
| 16:08 | daniel___ | :) |
| 16:09 | daniel___ | whats trampoline? |
| 16:11 | daniel___ | nvm, i see it runs it after leiningens jvm has closed |
| 16:11 | daniel___ | rather than in a subprocess |
| 16:27 | technomancy | antares_: we used neocons at seajure the other night; it was great |
| 16:28 | antares_ | technomancy: oh, nice! |
| 16:28 | technomancy | we loaded up the clojuresphere data set into it |
| 16:29 | antares_ | technomancy: big people are using clojurewerkz libraries! :) |
| 16:29 | technomancy | yeah, like me. I'm 202cm. |
| 17:05 | mjewkes | Hey 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:05 | mjewkes | Has anyone bumped into this before? |
| 17:07 | amalloy | sounds like an old clojure-mode? |
| 17:08 | mjewkes | possibly - I just installed it using package-install. |
| 17:08 | amalloy | try getting it fresh from technomancy's github |
| 17:08 | mjewkes | Interestingly - slime-connect seems to be missing to. |
| 17:09 | mjewkes | Should that be present - amalloy: will do. |
| 17:09 | amalloy | i dunno. i think jack-in provides its own copies of the slime libs |
| 17:25 | antares_ | yes, swank-clojure bundles its own copy of slime |
| 17:26 | Pupeno_W | From 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:27 | Pupeno_W | What does your profile mean here? |
| 17:27 | mjewkes | ~/.lein/profiles.clj |
| 17:27 | clojurebot | /.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:28 | Pupeno_W | Thanks. |
| 17:34 | ToxicFrog | Oh bollocks |
| 17:34 | ToxicFrog | (drop n s) where s is a string returns a LazySeq |
| 17:34 | ToxicFrog | With tragic results when you're doing something like (re-match pattern (drop header-length buf)) |
| 17:37 | metellus | use subs |
| 17:37 | ToxicFrog | Yeah, I was reflexively trying to make this sequence-type-agnostic |
| 17:37 | ToxicFrog | Despite the fact that, on reflection, it makes sense only for strings |
| 18:04 | overstood | I have what is hopefully a basic syntax question about Clojure, is this the right place for that? |
| 18:05 | ohpauleez | overstood: sure, totally |
| 18:06 | overstood | Great :) |
| 18:10 | overstood | So 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:10 | overstood | is there a better/more elegant way to do this than chaining if statements together? |
| 18:10 | ohpauleez | cond |
| 18:11 | ohpauleez | or condp |
| 18:11 | ohpauleez | &(doc cond) |
| 18:11 | lazybot | ⇒ "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:11 | ohpauleez | http://clojuredocs.org/clojure_core/clojure.core/cond |
| 18:12 | ohpauleez | You might also want to consider `case` |
| 18:12 | ohpauleez | http://clojuredocs.org/clojure_core/clojure.core/case |
| 18:12 | ohpauleez | http://clojuredocs.org/clojure_core/clojure.core/condp |
| 18:12 | ohpauleez | there's condp |
| 18:13 | overstood | That looks like what I was looking for. |
| 18:13 | overstood | Thanks a lot! |
| 18:14 | amalloy | case would work, or you could just use a map |
| 18:15 | amalloy | (let [defaults {1 "one" 2 "two"}] (defn compute [x] (or (defaults x) (do-real-work x)))) |
| 18:16 | overstood | that's neat too |
| 18:16 | ohpauleez | using a dispatch table like that is a pretty typical pattern overstood |
| 18:18 | mcohen | hi there #clojure. trying to get started programming Clojure and am getting stuck trying to compile, test, or repl with lein |
| 18:19 | mcohen | DEBUG output shows Classpath: /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar |
| 18:19 | mcohen | and everyone of those lein commands i listed above yields Exception in thread "main" java.lang.NoClassDefFoundError: |
| 18:19 | mcohen | and a stacktrace |
| 18:19 | mcohen | Caused by: java.lang.ClassNotFoundException: |
| 18:19 | mcohen | at java.net.URLClassLoader$1.run(URLClassLoader.java:202) |
| 18:19 | mcohen | at java.security.AccessController.doPrivileged(Native Method) |
| 18:19 | mcohen | at java.net.URLClassLoader.findClass(URLClassLoader.java:190) |
| 18:19 | mcohen | at java.lang.ClassLoader.loadClass(ClassLoader.java:306) |
| 18:19 | mcohen | at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) |
| 18:19 | mcohen | at java.lang.ClassLoader.loadClass(ClassLoader.java:247) |
| 18:19 | mcohen | Compilation failed. |
| 18:20 | mcohen | i know i must be missing something simple and stupid |
| 18:20 | mcohen | can anyone help please? |
| 18:21 | ohpauleez | cd to a different directly, like you $HOME |
| 18:21 | ohpauleez | then try lein2 repl |
| 18:21 | ohpauleez | do you still get the error? |
| 18:21 | overstood | I'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:22 | overstood | Why would one use cond vs a dispatch table? |
| 18:22 | mcohen | thanks ohpauleez. nope, the repl comes up just fine if i'm not in the project dir |
| 18:22 | ohpauleez | overstood: If you needed different functions to test for different things |
| 18:23 | ohpauleez | overstood: If you're looking for equality, dispatching via maps is usually used |
| 18:23 | ohpauleez | (a dispatch table) |
| 18:23 | ohpauleez | mcohen: There's an error in the source files you've written |
| 18:23 | ohpauleez | try creating a new project with lein2 new, cd into it, and try `lein repl` |
| 18:23 | mcohen | ok, but all i did was "lein new appname" |
| 18:24 | mcohen | and then lein test |
| 18:24 | mcohen | i didn't edit anything |
| 18:24 | ohpauleez | there are no tests to run |
| 18:25 | overstood | so the map is basically just a bit more concise and faster than cond/case? |
| 18:25 | mcohen | test/<project_name>/core_test.clj |
| 18:25 | mcohen | is created when i did lein new app |
| 18:25 | ohpauleez | more concise and preferred in that case (if you're just checking for equality). I'm not sure about performance |
| 18:26 | ohpauleez | mcohen: And what's in that file? |
| 18:26 | overstood | ohpauleez: got it, thanks |
| 18:26 | mcohen | (ns congo.core-test |
| 18:26 | mcohen | (:use clojure.test |
| 18:26 | mcohen | congo.core)) |
| 18:26 | ohpauleez | overstood: No problem! |
| 18:26 | mcohen | (deftest a-test |
| 18:26 | mcohen | (testing "FIXME, I fail." |
| 18:26 | mcohen | (is (= 0 1)))) |
| 18:26 | ohpauleez | mcohen: try creating a new project and see if the errors happen in the new project |
| 18:27 | mcohen | yeah, i tried that already actually. |
| 18:27 | mcohen | when i run with the DEBUG flag on it prints Classpath: /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar |
| 18:27 | mcohen | but if i run lein classpath, i get |
| 18:28 | overstood | one 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:29 | dnolen | overstood: Clojure's design assumes GC, it's pretty hard to avoid |
| 18:30 | overstood | Even more specifically, when I'm using Clojure functions that don't have side effects. What is allocated and when is it released? |
| 18:32 | amalloy | overstood: consider a simple case where x is the list (1 2 3) |
| 18:32 | amalloy | if 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:33 | amalloy | so 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:35 | stain | anyone played with the framebuffer (/dev/fb0) from Clojure? |
| 18:35 | mcohen | so if you run lein <command> in the root of your clojure project with DEBUG=1 what will be shown as the Classpath variable? |
| 18:36 | mcohen | or, what should be shown? |
| 18:36 | mcohen | all i see is /Users/mcohen/.lein/self-installs/leiningen-2.0.0-preview7-standalone.jar |
| 18:36 | mcohen | but if i run lein classpath then it does in fact list out the jars i've included as dependencies |
| 18:36 | mcohen | as well as the src, test, resources, dev-resources, and classes dirs |
| 18:37 | mcohen | but the ClassNotFoundException feels like i must have a classpath issue somewhere |
| 18:38 | overstood | amalloy: That makes parfect sense. I'm still trying to get an intuitive grasp of the implications of immutable state. Thanks! |
| 18:52 | casperc | hello |
| 18:52 | casperc | I have this question which is not really clojure specific, but I thought you might be able to help anyway |
| 18:53 | casperc | I 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:53 | casperc | anyone know how to go about this? |
| 18:54 | jeremyheiler | ,(rand-int 100) |
| 18:54 | clojurebot | 24 |
| 18:55 | jeremyheiler | casperc: you can also check out the ring-jetty-adapter to see how it starts a jetty server. |
| 18:55 | jeremyheiler | https://github.com/mmcgrana/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj |
| 18:55 | casperc | I want to do this to be able do some cucumber/soapui tests against the api as part of ci |
| 18:56 | stain | casperc: ring can do that |
| 18:56 | stain | I just type "lein ring server" and it pops up a browser window |
| 18:56 | casperc | jeremyheiler: 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:56 | stain | I think it just tries to bind to port 3000, if it is taken, add 1, etc |
| 18:57 | jeremyheiler | casperc: how are you invoking the process? |
| 18:57 | jeremyheiler | better yet, how do you want to invoke the process? at a repl? |
| 18:58 | casperc | doesn'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:59 | casperc | multiple tests and builds might be running at the same time, so it can't be the same port always |
| 19:01 | casperc | actually, 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:02 | jeremyheiler | something 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:04 | casperc | jeremyheiler: that might work |
| 19:05 | casperc | I 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:05 | jeremyheiler | casperc: no problem. good luck |
| 19:06 | casperc | thank you |
| 19:14 | AWizzArd | Hmm, 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:15 | AWizzArd | Example: 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:16 | nDuff | AWizzArd: Err. Do you want the file to be read at compile time or runtime? |
| 19:16 | nDuff | AWizzArd: ...keeping in mind that macro expansion happens at compile time... |
| 19:17 | AWizzArd | I want to read the file at runtime. |
| 19:17 | nDuff | AWizzArd: ...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:18 | nDuff | AWizzArd: 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:18 | AWizzArd | nDuff: yes |
| 19:18 | AWizzArd | That’s why Clojure offers destructuring. |
| 19:19 | AWizzArd | I want runtime destructuring of files. |
| 19:19 | nDuff | ...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:19 | amalloy | AWizzArd: no, you want destructuring with unknown keys |
| 19:20 | amalloy | ignore 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:20 | AWizzArd | Yes. |
| 19:20 | amalloy | which is totally possible and not even hard, but pretty disastrous as an idea |
| 19:20 | nDuff | ...even though the code may not even _compile_ if the file doesn't contain the keys it needs/expects. |
| 19:21 | AWizzArd | amalloy: not hard… without using eval? |
| 19:21 | nDuff | Actually -- this is silly. Your code knows which keys it needs. |
| 19:21 | amalloy | no, you of course have to use eval |
| 19:21 | AWizzArd | Yes, I agree. |
| 19:21 | nDuff | So, you can just assume that those keys will be present in the file, and use _real_ destructuring. |
| 19:22 | AWizzArd | amalloy: Pretty trivial, just wanted to check if I might have missed something to make this happen without eval. |
| 19:22 | nDuff | ("real", meaning compile-time) |
| 19:22 | amalloy | read 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:23 | nDuff | AWizzArd: Why can't you use real, fixed-key destructuring, with the set of keys that map to what the code uses? |
| 19:23 | nDuff | AWizzArd: After all, you aren't proposing that the code changes, only that the file does. |
| 19:23 | AWizzArd | Well, I have nearly 10 years Lisp experience, and I am aware of the multitude of problems. |
| 19:24 | nDuff | AWizzArd: ...so there's quite literally no point at all to the extra pain you're wanting to create. |
| 19:25 | AWizzArd | nDuff: The whole purpose is to not have to manually extract those keys. |
| 19:25 | AWizzArd | It is a pure convenience importer macro. |
| 19:25 | nDuff | AWizzArd: not to extract them from the code, as opposed to from the file, right? |
| 19:25 | AWizzArd | For FXML files ==> JavaFX |
| 19:25 | nDuff | AWizzArd: So you can just have your macro analyze the code at compile time; done. |
| 19:25 | amalloy | oh god |
| 19:25 | AWizzArd | Yes? |
| 19:25 | clojurebot | yes isn't is |
| 19:25 | amalloy | that's even worse, nDuff |
| 19:26 | Raynes | I 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:26 | Raynes | You don't want this. Stop before it is too late. |
| 19:26 | amalloy | *shrug* we put up the signposts, he disagrees, and the language gives him a way to do it |
| 19:26 | AWizzArd | Plus I think it may turn out useful. |
| 19:27 | amalloy | *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:27 | AWizzArd | Well, I read a fxml file, and get a hashmap. The keys are keywords, and the values are JavaFX components. |
| 19:28 | amalloy | keywords? 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:29 | AWizzArd | I am really saving a (let [username-label (:username-label fxml), password-label (:password-label fxml), username-text (:username-text fxml) …) |
| 19:29 | AWizzArd | A 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:30 | AWizzArd | (with-fxml ["login-ui" "email-ui"] body) |
| 19:31 | AWizzArd | This is actually nicer than a 21 line let. |
| 19:31 | AWizzArd | But yes, if this turns out to be too problematic, I will remove it before a 1.0. |
| 19:33 | AWizzArd | Also 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:41 | AWizzArd | Trivial, thanks to Clojure’s power: (mapcat (fn [[k v]] [(with-meta (symbol (name k)) {:tag (class v)}) v]) my-map) |
| 19:48 | amalloy | uhhhhh, 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:50 | AWizzArd | The values are Buttons, Labels, TextFields, etc. |
| 19:51 | amalloy | i don't think you'll be able to embed those in code |
| 19:51 | AWizzArd | And in the body one wants to do things such as (.setText password ""). |
| 19:52 | amalloy | try it: (defmacro let-button [& body] `(let [~'button ~(make-button-object)] ~@body)) |
| 19:52 | AWizzArd | Useful when we get a (let [^PasswordField password (:password fxml)] …) |
| 19:53 | AWizzArd | instead of ~'button it should probably be something like ~(with-meta 'button {:tag Button}) |
| 19:53 | amalloy | AWizzArd: yes, but that's not relevant to my objection |
| 19:53 | AWizzArd | Then I don’t understand it yet. Could you say it in other words? |
| 19:55 | amalloy | AWizzArd: either v is a Button object, or it's code that you could evaluate to produce a Button |
| 19:55 | amalloy | if the former, then you can't embed it as part of the let statement |
| 19:55 | amalloy | if the latter, you won't have its class yet |
| 19:56 | amalloy | also, you want {:tag `Button}, not {:tag Button}; tags are symbols, not classes |
| 19:57 | AWizzArd | Yes, it was just a sketch. |
| 19:57 | AWizzArd | I will experiment with this now. |
| 20:01 | AWizzArd | amalloy: I can go around this by not taking the (class v) but (class (eval v)). |
| 20:01 | AWizzArd | The interesting thing here is though that the symbols that end up in the body, are different from the ones in the let. |
| 20:02 | amalloy | i don't understand that last |
| 20:03 | AWizzArd | amalloy: 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:04 | AWizzArd | amalloy: then in the repl: (def x (macroexpand '(bar {foo (:lup {:lup "Hi"})} (.length foo)))) |
| 20:05 | AWizzArd | (-> x second first meta) ==> String, but (-> x last last meta) ==> nil |
| 20:05 | amalloy | of course |
| 20:05 | AWizzArd | Although when you try both -> forms without the last meta, you will both times see it is foo. |
| 20:05 | amalloy | just like without a macro |
| 20:05 | AWizzArd | But also that can be solved :-) |
| 20:05 | amalloy | what? don't solve it |
| 20:05 | amalloy | it's not a problem |
| 20:06 | AWizzArd | Why not? I want those type hints. |
| 20:06 | amalloy | no you don't |
| 20:06 | amalloy | (let [^Foo x 1] x) - nobody writes (let [^Foo x 1] ^Foo x), because there's no reason |
| 20:06 | AWizzArd | Turn on reflection warnings, and you will see that (bar {foo (:lup {:lup "Hi"})} (.length foo)) throws a warning. |
| 20:07 | AWizzArd | I want that the vars in the body inherit the type hints from the let. |
| 20:07 | AWizzArd | So I need the identical (hinted) symbols in the body. |
| 20:07 | amalloy | no you don't |
| 20:07 | amalloy | they always inherit |
| 20:07 | amalloy | the problem is still what i said: tags are symbols, not classes, and you're trying to use a class |
| 20:08 | AWizzArd | Ah, right. |
| 20:08 | AWizzArd | Good point. |
| 20:09 | AWizzArd | Yes, works. |
| 20:10 | AWizzArd | Lot’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:11 | amalloy | shit, really? i thought you were dead, mister mccarthy |
| 20:11 | AWizzArd | ;) |
| 20:12 | AWizzArd | In fact, so far my only real usecase for it was my Genetic Programming lib, where it is obviously the right choice. |
| 20:12 | AWizzArd | (as the whole point is the creation of code at runtime, and then run it) |
| 20:40 | dyba | Should I be expecting an OutOfMemoryError when using (range) ? |
| 20:40 | dyba | I understand (range) creates a lazy sequence from 0 to positive infinity |
| 20:40 | AWizzArd | Fortunately range is lazy, as you said. |
| 20:40 | dyba | but I guess I don't quite understand what lazy means |
| 20:40 | AWizzArd | So it will only produce those numbers when they are needed. |
| 20:41 | dyba | so I shouldn't be expecting an out of memory error, correct? |
| 20:41 | AWizzArd | Yes. |
| 20:41 | AWizzArd | Just don’t keep a pointer to the begin of the sequence. |
| 20:41 | dyba | the only string i get explaining the error is Java heap space |
| 20:42 | dyba | my test is currently failing |
| 20:42 | AWizzArd | (doseq [n (range)] (when (= n 9999999999999) (System/exit 0))) will run fine, without killing the RAM. It would run a long time though. |
| 20:43 | dyba | AWizzArd: I was just running a simple test to make sure I understand what to expect from using range |
| 20:43 | dyba | inside a test I wrote: |
| 20:43 | dyba | (is (= 0 (range))) |
| 20:44 | dyba | but that's not quite correct, it should fail |
| 20:44 | dyba | but i got a failure for a different reason, i.e. OutOfMemory |
| 20:44 | dyba | AWizzArd: so would your approach be a better way to test what I had in mind? |
| 20:47 | AWizzArd | Well, (range) is a sequence of numbers. |
| 20:47 | AWizzArd | The 0 is one of them. |
| 20:47 | AWizzArd | But “a sequence of numbers” is not equal to the number zero. |
| 20:48 | AWizzArd | But (is (= 0 (first (range)))) should succeed. |
| 20:48 | dyba | right |
| 20:49 | ToxicFrog | <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:50 | AWizzArd | amalloy: 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:50 | AWizzArd | That 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:50 | dyba | ToxicFrog: so (range) shouldn't return anything because I haven't carried out any operations on it? |
| 20:50 | ToxicFrog | Depends on what you do with it |
| 20:51 | ToxicFrog | (= 0 (range)) might actually evaluate the entire sequence as it tries to do the compare. |
| 20:51 | dyba | ah I see, hence the OutOfMemory error |
| 20:52 | aamar | dyba: it also might be the clojure.test framework creating the error, as it tries to inform you why the equality comparison failed. |
| 20:53 | ToxicFrog | Yeah, in that case it might try to evaluate the seq so that it can print it or something. |
| 20:53 | ToxicFrog | And then boom. |
| 20:53 | dyba | aamar: I believe you are right, I would have to see what = is doing under the covers |
| 20:53 | aamar | I suspect it's that, because (if (= 0 (range)) 1 2) works fine for me |
| 20:53 | ToxicFrog | Alright then |
| 20:54 | AWizzArd | ,(= 0 (range)) ; = does not traverse the whole range |
| 20:54 | clojurebot | false |
| 20:55 | dyba | thanks <ToxicFrog>, <aamar>, <AWizzArd>! |
| 20:56 | dyba | oh so it's probably the 'is' in the testing clojure.test framework |
| 20:57 | AWizzArd | That may be it. |
| 20:58 | AWizzArd | Though I would find that a bit surprising. |
| 21:08 | dyba | range doesn't look like it's capable of handling floats correctly, am I correct? |
| 21:08 | AWizzArd | What means “handling floats”? |
| 21:08 | dyba | I just tried (range 1.0 2.0 0.2) and it didn't quit get to 1.6 |
| 21:08 | dyba | it gave me 1.5999999 |
| 21:09 | dyba | it gave me (1.0 1.2 1.4 1.59999... 1.79999... 1.99999...) |
| 21:09 | AWizzArd | dyba: You would like to read http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html |
| 21:10 | AWizzArd | “What Every Computer Scientist Should Know About Floating-Point Arithmetic” |
| 21:10 | dyba | AWizzArd: will do, I'll check it out right now |
| 21:10 | AWizzArd | It is a pretty long read, but important stuff in there. |
| 21:11 | AWizzArd | ,(range 1 2 1/5) |
| 21:11 | clojurebot | (1 6/5 7/5 8/5 9/5) |
| 21:11 | dyba | AWizzArd: Ah ha! you used a rational |
| 21:11 | dyba | I forgot about those in Clojure |
| 21:12 | AWizzArd | Although 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:13 | AWizzArd | You have only 2^32 numbers available (4 billion), as floats have to encode those numbers in 32 bits. |
| 21:17 | Frozenlock | Is there some mechanism to install and auto-run a clojure app at each reboot? (Or is this more of a java question?) |
| 21:18 | AWizzArd | dyba: 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:18 | AWizzArd | Frozenlock: more a question of your operating system. |
| 21:19 | Frozenlock | True. Let's say a windows machine. I already use launch4j to wrap my jars, but I would like a proper installation. |
| 21:19 | AWizzArd | dyba: 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:20 | AWizzArd | dyba: in Clojure there is even a reader syntax for such numbers. Just append an uppercase “M”: |
| 21:20 | AWizzArd | ,(range 1.0M 2.0M 0.2M) |
| 21:20 | clojurebot | (1.0M 1.2M 1.4M 1.6M 1.8M) |
| 21:22 | AWizzArd | Frozenlock: 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:22 | AWizzArd | Frozenlock: it will probably take you 3-15 hours to get this working. |
| 21:22 | Frozenlock | Hmmmm so adding the Frozenlock effect, I should count 48 hours :P |
| 21:23 | Frozenlock | Thanks, I'll take a look! |
| 21:23 | AWizzArd | But 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:24 | AWizzArd | That’s a fast and nice way for small admin UIs and such. But professional server software should really run as a Service. |
| 21:24 | Frozenlock | Yeah it does sound hacky- but for a proof of concept it might be enough. Thank you very much! |
| 21:27 | dyba | AWizzArd: I'll look into that, thanks! |
| 21:32 | ToxicFrog | God, I hate deploying on windows. |
| 21:38 | dyba | ToxicFrog: are you doing that for work? |
| 21:40 | ToxicFrog | dyba: no, but one of my current projects is designed to integrate with a game released on windows and OSX |
| 21:40 | ToxicFrog | So it needs to work on windows |
| 21:49 | dyba | AWizzard: yup, the BigDecimal instance works better for the use case I had brought up |
| 22:01 | evildaemon | I'm not quite sure I understand the "lists" model of data processing. |
| 22:01 | evildaemon | I know all the data structures are immutable. But I'm not sure how to build new lists out of the old ones. |
| 22:04 | evildaemon | As 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:04 | evildaemon | Cons does the same thing. |
| 22:04 | ToxicFrog | How are you using them? |
| 22:04 | ToxicFrog | ,(cons 1 '(2 3 4)) |
| 22:04 | clojurebot | (1 2 3 4) |
| 22:05 | evildaemon | ToxicFrog: Thank you. |
| 22:05 | ToxicFrog | ,(cons '(2 3 4) 1) |
| 22:05 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> |
| 22:05 | ToxicFrog | Whups |
| 22:05 | ToxicFrog | ,(cons '(2 3 4) '(1)) |
| 22:05 | clojurebot | ((2 3 4) 1) |
| 22:05 | evildaemon | lol. |
| 22:06 | evildaemon | Wait, isn't it kind of dangerous to have a clojure interpreter just sitting in the IRC channel? |
| 22:07 | ToxicFrog | Pretty sure it's sandboxed so that you can't actually damage anything |
| 22:07 | ToxicFrog | ,(println (range)) |
| 22:07 | clojurebot | (0 1 2 3 4 ...) |
| 22:07 | ToxicFrog | ,(dorun (map println (range))) |
| 22:07 | clojurebot | Execution Timed Out |
| 22:08 | evildaemon | ToxicFrog: I suspected as much, couldn't see how the channel wouldn't be spammed to death by recursive functions otherwise. |
| 22:09 | ToxicFrog | ,(dorun (map println (range 1 100))) |
| 22:09 | clojurebot | 1 |
| 22:09 | clojurebot | 2 |
| 22:09 | clojurebot | 3 |
| 22:09 | clojurebot | 4 |
| 22:09 | clojurebot | 5 |
| 22:09 | ToxicFrog | Oh god |
| 22:09 | clojurebot | 6 |
| 22:10 | clojurebot | 7 |
| 22:10 | clojurebot | 8 |
| 22:10 | clojurebot | 9 |
| 22:10 | clojurebot | 10 |
| 22:10 | ToxicFrog | I'm so sorry |
| 22:10 | clojurebot | 11 |
| 22:10 | clojurebot | 12 |
| 22:10 | clojurebot | 13 |
| 22:10 | clojurebot | 14 |
| 22:10 | clojurebot | 15 |
| 22:10 | clojurebot | 16 |
| 22:10 | clojurebot | 17 |
| 22:10 | clojurebot | 18 |
| 22:10 | clojurebot | 19 |
| 22:10 | clojurebot | 20 |
| 22:10 | clojurebot | 21 |
| 22:10 | ToxicFrog | I should have PMd that |
| 22:10 | clojurebot | 22 |
| 22:10 | clojurebot | 23 |
| 22:10 | clojurebot | 24 |
| 22:10 | clojurebot | 25 |
| 22:10 | clojurebot | 26 |
| 22:10 | clojurebot | 27 |
| 22:10 | clojurebot | 28 |
| 22:10 | clojurebot | 29 |
| 22:10 | clojurebot | 30 |
| 22:10 | clojurebot | 31 |
| 22:10 | clojurebot | 32 |
| 22:10 | clojurebot | 33 |
| 22:10 | TheBusby | nice, like times of old |
| 22:10 | clojurebot | 34 |
| 22:10 | clojurebot | 35 |
| 22:10 | clojurebot | 36 |
| 22:10 | clojurebot | 37 |
| 22:10 | clojurebot | 38 |
| 22:10 | clojurebot | 39 |
| 22:10 | clojurebot | 40 |
| 22:10 | ToxicFrog | evildaemon: it's not nearly as well sandboxed as I thought :/ |
| 22:10 | clojurebot | 41 |
| 22:10 | clojurebot | 42 |
| 22:10 | clojurebot | 43 |
| 22:10 | clojurebot | 44 |
| 22:10 | clojurebot | 45 |
| 22:10 | clojurebot | 46 |
| 22:10 | clojurebot | 47 |
| 22:10 | clojurebot | 48 |
| 22:10 | clojurebot | 49 |
| 22:10 | clojurebot | 50 |
| 22:10 | clojurebot | 51 |
| 22:10 | clojurebot | 52 |
| 22:10 | clojurebot | 53 |
| 22:10 | clojurebot | 54 |
| 22:10 | clojurebot | 55 |
| 22:10 | clojurebot | 56 |
| 22:10 | clojurebot | 57 |
| 22:10 | ToxicFrog | Also, I should have tested with (range 1 5) |
| 22:10 | clojurebot | 58 |
| 22:10 | evildaemon | Goddamit. |
| 22:10 | clojurebot | 59 |
| 22:10 | clojurebot | 60 |
| 22:10 | clojurebot | 61 |
| 22:10 | clojurebot | 62 |
| 22:10 | clojurebot | 63 |
| 22:10 | clojurebot | 64 |
| 22:10 | clojurebot | 65 |
| 22:10 | clojurebot | 66 |
| 22:11 | clojurebot | 67 |
| 22:11 | Frozenlock | That's funny |
| 22:11 | clojurebot | 68 |
| 22:11 | clojurebot | 69 |
| 22:11 | clojurebot | 70 |
| 22:11 | clojurebot | 71 |
| 22:11 | clojurebot | 72 |
| 22:11 | clojurebot | 73 |
| 22:11 | clojurebot | 74 |
| 22:11 | clojurebot | 75 |
| 22:11 | clojurebot | 76 |
| 22:11 | Frozenlock | Isn't there a time limit for clojurebot? |
| 22:11 | clojurebot | 77 |
| 22:11 | clojurebot | 78 |
| 22:11 | evildaemon | I'm sorry I said anything. |
| 22:11 | clojurebot | 79 |
| 22:11 | clojurebot | 80 |
| 22:11 | clojurebot | 81 |
| 22:11 | clojurebot | 82 |
| 22:11 | clojurebot | 83 |
| 22:11 | clojurebot | 84 |
| 22:11 | clojurebot | 85 |
| 22:11 | clojurebot | 86 |
| 22:11 | clojurebot | 87 |
| 22:11 | clojurebot | 88 |
| 22:11 | clojurebot | 89 |
| 22:11 | clojurebot | 90 |
| 22:11 | clojurebot | 91 |
| 22:11 | clojurebot | 92 |
| 22:11 | clojurebot | 93 |
| 22:11 | clojurebot | 94 |
| 22:11 | clojurebot | 95 |
| 22:11 | clojurebot | 96 |
| 22:11 | clojurebot | 97 |
| 22:11 | clojurebot | 98 |
| 22:11 | clojurebot | 99 |
| 22:11 | ToxicFrog | Feature request for clojurebot: combine multiple lines of output into single IRC message; restrict the number of messages a single command can emit. |
| 22:11 | evildaemon | Yes. |
| 22:12 | Frozenlock | At least now we know. |
| 22:12 | evildaemon | What? No one ever tried that before? |
| 22:12 | TheBusby | an knowing is half the battle? |
| 22:13 | Frozenlock | Yup, now we know who the enemy is :) |
| 22:13 | Frozenlock | ,flame ToxicFrog |
| 22:13 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: flame in this context, compiling:(NO_SOURCE_PATH:0)> |
| 22:13 | Frozenlock | What, no flame bot? |
| 22:14 | ToxicFrog | Frozenlock: there is a time limit, but apparently that didn't hit it! |
| 22:14 | evildaemon | (defn 787 (print 5)) |
| 22:14 | evildaemon | ,(defn 787 (print 5)) |
| 22:14 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Parameter declaration print should be a vector> |
| 22:15 | evildaemon | Oh right, arguments. |
| 22:15 | Frozenlock | I think defn is forbidden as a protection |
| 22:15 | Frozenlock | Isn't it? |
| 22:15 | evildaemon | (defn 787 [] (print 5)) |
| 22:15 | evildaemon | ,(defn 787 [] (print 5)) |
| 22:15 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IObj> |
| 22:15 | ToxicFrog | ,(defn foo [x] (println x)) (foo 1) |
| 22:15 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 22:15 | ToxicFrog | Yep. |
| 22:15 | evildaemon | Ah. |
| 22:15 | ToxicFrog | SANBOX. |
| 22:15 | evildaemon | Interesting. |
| 22:16 | evildaemon | So I would assume that def and fn are blocked as well? |
| 22:16 | Frozenlock | Hopefully |
| 22:20 | evildaemon | ,(def test556 9) |
| 22:20 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 22:20 | Frozenlock | , (map (fn [a] (print a)) [1 2 3 4]) |
| 22:20 | clojurebot | (1234nil nil nil nil) |
| 22:20 | Frozenlock | wut |
| 22:21 | evildaemon | lol. |
| 22:21 | Frozenlock | It does the same thing on my repl.... |
| 22:21 | Frozenlock | What am I missing here |
| 22:21 | evildaemon | Oh dear. |
| 22:22 | Frozenlock | , (map (fn [a] a) [1 2 3 4]) |
| 22:22 | clojurebot | (1 2 3 4) |
| 22:23 | Frozenlock | Oh I see... Print send them to *out* (which is the repl), the return nil for everyone of them. |
| 22:23 | Frozenlock | *then |
| 22:24 | evildaemon | I love how the last github commit is entitled: "Should have thought this through." |
| 22:24 | arohner | is there a library like trammel that can be used to provide "inheritance" for fn contracts? |
| 22:25 | Frozenlock | evildaemon: Funny, but kinda lack precision |
| 22:25 | arohner | I'd really like to define a contract for a class of fns, and then define new fns, that match the same contract |
| 22:26 | arohner | and it'd be amazing if at least part of it was verified at compile time |
| 22:41 | evildaemon | ,(print "(+ 2 2)") |
| 22:41 | clojurebot | (+ 2 2) |
| 22:42 | evildaemon | ,(print ",(+ 2 2)") |
| 22:42 | clojurebot | ,(+ 2 2) |
| 22:47 | Frozenlock | Ok I'm doing it, jumping to lein 2 and clojure 1.4, wish me luck! |
| 22:48 | evildaemon | ToxicFrog: How do I do that with named lists? |
| 22:49 | ToxicFrog | evhan: "named lists"? |
| 22:50 | evildaemon | ToxicFrog: You know, lists that have symbols attached with def or let.) |
| 22:50 | ToxicFrog | Er |
| 22:50 | tos9 | evildaemon: I checked that :) |
| 22:50 | tos9 | evildaemon: It's amazing how many bots are vulnerable to that sort of exploit. |
| 22:51 | ToxicFrog | evildaemon: you're going to have to explain in more detail what you're trying to ask |
| 22:52 | evildaemon | tos9: 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:53 | evildaemon | ToxicFrog: (def r (list 7 7 6 5 0)) |
| 22:53 | evildaemon | Not sure what it's actually called. |
| 22:53 | ToxicFrog | Ok, in that case, what is the "that" that you want to do? |
| 22:57 | evildaemon | ToxicFrog: This could take while. |
| 22:58 | ToxicFrog | evildaemon: 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:58 | ToxicFrog | So you must be asking something else |
| 22:59 | evildaemon | ToxicFrog: How do I combine two lists? |
| 23:00 | mindbender | anyone using counterclockwise here? |
| 23:01 | ToxicFrog | evildaemon: depends on what you mean by "combine", but probably (concat xs ys) |
| 23:01 | ToxicFrog | ,(concat '(1 2 3) '(4 5 6)) |
| 23:01 | clojurebot | (1 2 3 4 5 ...) |
| 23:01 | ToxicFrog | evildaemon: also, it sounds like you need this: http://clojure.org/cheatsheet |
| 23:01 | ToxicFrog | It is damn useful. |
| 23:02 | evildaemon | ToxicFrog: Yes. |
| 23:37 | mindbender | with counterclockwise I'm having trouble importing a github project, need I install git for eclipse |
| 23:37 | mindbender | ? |
| 23:41 | acristin | mindbender: 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:44 | mindbender | acristin: 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:53 | ssutch | is it possible to def a function that can respond differently to different keyword arguments, eg |
| 23:54 | ssutch | ,(defn a ([{a1 :a1}] ("something")) ([{a2 :a2}] ("something else")) |
| 23:54 | clojurebot | #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading> |
| 23:54 | ssutch | ,(defn a ([{a1 :a1}] ("something")) ([{a2 :a2}] ("something else"))) |
| 23:54 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 23:54 | ssutch | bajh |
| 23:55 | ssutch | "cant have 2 overloads with the same arity" is what it should print |