2014-10-27
| 01:14 | sm0ke | hello in java.jdbc there is a db/query method to fetch whole result set is there a better way to do this? |
| 01:14 | sm0ke | soemthing like a query-seq? |
| 01:15 | sm0ke | which could be operated upon lazily |
| 01:16 | sm0ke | oops there is a result-set-seq! |
| 01:31 | justin_smith | sm0ke: the lazy stuff breaks if you try to realize it outside the transaction context |
| 01:32 | justin_smith | but it does work |
| 01:33 | sm0ke | justin_smith: i dont understand |
| 01:34 | sm0ke | i just want a seq over result as maps, how do i do that? |
| 01:34 | sm0ke | lazy seq |
| 01:35 | sm0ke | i see that internally query uses result-set-seq so i am more confused now |
| 01:35 | justin_smith | sm0ke: just make sure you realize as much of it as you are going to use before exiting the scope where you acquire the results |
| 01:35 | justin_smith | sm0ke: if you just pass the lazy-seq out and then try to access elements later, you get an error because you aren't in the scope where the connection to the db exists any more |
| 01:36 | sm0ke | yes that is true, but i dont think it is still lazy |
| 01:36 | justin_smith | sm0ke: the advantage is that means you can determine lazily when you have enough data and stop without needing to wait for the rest to transfer - but it can lead to unintuitive errors if you use it wrong |
| 01:36 | sm0ke | by default :result-set-fn is doall |
| 01:36 | justin_smith | sm0ke: ahh yeah, but you can change that to actually be lazy |
| 01:37 | justin_smith | if you actually wanted the lazy part |
| 01:37 | sm0ke | so setting it to identity should be enough? |
| 01:38 | justin_smith | I think so |
| 01:42 | oskarkv | Style sheets are cached in JavaFX, and are not reloaded if I don't restart the repl. Does anyone know of a way to fix this? |
| 01:48 | m00nlight | Does struct save memory than ordinary map structure ? |
| 02:14 | dysfun | m00nlight: don't look at it in those terms. do you want polymorphism? use a record. else use a map |
| 02:14 | dysfun | unless you have funky requirements |
| 02:14 | dysfun | there's a really good diagram of which abstraction to pick, let me find it |
| 02:15 | dysfun | https://github.com/cemerick/clojure-type-selection-flowchart |
| 03:14 | m00nlight | dysfun: thanks very much |
| 03:20 | dysfun | yw |
| 03:24 | dysfun | oskarkv: which bindings are you using? |
| 03:26 | dysfun | if it's just raw JavaFX you can do something like (-> my-pane .getStylesheets (.add "styles.css")) |
| 03:26 | dysfun | er with a .clear in there as well |
| 04:00 | oskarkv | dysfun does not work. And it would be strange if it did: It's a new Pane instance each run. |
| 04:00 | oskarkv | dysfun I'm using plain JavaFx |
| 04:01 | dysfun | hrm, i'm afraid i don't know then |
| 04:01 | dysfun | i stopped using javafx once i realised it couldn't actually do what i wanted it for |
| 04:01 | oskarkv | hehe |
| 04:01 | oskarkv | What was that? |
| 04:01 | dysfun | i wanted to manipulate the dom of a webkit control from clojure code without involving javascript or clojurescript |
| 04:02 | dysfun | well, that was one of the things (and doesn't work because the DOM is made read-only, presumably to simplify implementation) |
| 04:02 | oskarkv | hehe ok |
| 04:03 | dysfun | the other one, i wanted to buiild a web browser. but you can't swap out engines so you'd have to create lots of WebViews, and you can see how quickly that's going to get tedious |
| 04:11 | oskarkv | dysfun :p i'm just making a game. It's pretty handy to just draw javafx to a texture and then use that inside the game, because otherwise i'd have to make my own gui from scratch :p |
| 04:12 | oskarkv | btw i can probably just rename the css file to something random, and then load that, tricking the cache P |
| 04:22 | sm0ke | ok so if i set result-set-fn to something other than doall it causes ResultSetClosed exception |
| 04:22 | sm0ke | is there a way to have lazy seq without realizing it immediately? |
| 04:34 | dysfun | oskarkv: yeah, you can just increment a number in a filename i suppose |
| 06:30 | SagiCZ1 | sm0ke: isnt that the point of lazy-seqs? |
| 06:55 | dysfun | laziness and i/o resources don't play terribly lovely together |
| 06:57 | dysfun | you'll be wanting doseq *somewhere* at least to make sure it doesn't get closed before you've read it all. but at that point, why use laziness at all? |
| 07:02 | borkdude | dysfun I'm not clear on this, but someone mentioned transducers could help here? I would like to hear something about this if it's true |
| 07:03 | dysfun | i haven't gotten around to playing with them yet, so i can't help, sorry |
| 07:03 | dysfun | but if you have a read, i can probably help you through some of it if you're struggling to understand |
| 07:08 | borkdude | dysfun I understand what transducers do, but not how they help working with resources |
| 07:08 | borkdude | dysfun in the lazy case |
| 07:10 | SagiCZ1 | (doc read) |
| 07:10 | clojurebot | "([] [stream] [stream eof-error? eof-value] [stream eof-error? eof-value recursive?]); Reads the next object from stream, which must be an instance of java.io.PushbackReader or some derivee. stream defaults to the current value of *in*. Note that read can execute code (controlled by *read-eval*), and as such should be used only with trusted sources. For data structure interop use clojure.edn/read" |
| 07:11 | SagiCZ1 | if read should be used only with trusted sources, what should i use with untrusted source? |
| 07:13 | SagiCZ1 | io/reader i guess |
| 07:14 | dysfun | borkdude: i'm reading. gosh, they sound like lazy monads |
| 07:15 | clgv | borkdude: when you'd do file processing via transducer you eliminate the need for a lazy-seq |
| 07:15 | jonathanj | anyone familiar with instaparse? |
| 07:15 | jonathanj | i have a tree sgement like [:command "F" "O" "O"] |
| 07:16 | dysfun | damn. i've just realised how this could make some of my code cleaner. so i suppose i'll have to go play |
| 07:16 | jonathanj | if i use (insta/transform {:command str}) then i end up with "FOO" whereas what i'm looking for is [:command "FOO"] |
| 07:17 | borkdude | clgv the data source for a (sequence xform source), what would that be instead of a lazy seq? |
| 07:19 | clgv | borkdude: well a transducer is a stepwise description, so the step could be "read the next thing from file" |
| 07:19 | borkdude | clgv the problem with lazy sequences and file resources is that you can't use them within a with-open-file macro for example right? |
| 07:20 | borkdude | clgv because if use consume elements from outside the macro, the file is closed |
| 07:20 | clgv | borkdude: yes, you have to consume as much of the lazy-seq as you need within the with-open |
| 07:20 | borkdude | clgv ok, so it doesn't really add any benefit in that area |
| 07:21 | clgv | borkdude: a transducer would also have to work in the context where the file is open. though as far as I read, the opening and closening could be done in steps supported by the transducer |
| 07:22 | borkdude | clgv what are you reading. |
| 07:23 | SagiCZ1 | how do i convert string to number? |
| 07:23 | SagiCZ1 | ,(Double/parseDouble "1.64") |
| 07:23 | clojurebot | 1.64 |
| 07:23 | SagiCZ1 | more clojury way? |
| 07:23 | clgv | no |
| 07:23 | clgv | ,(double "1.64") |
| 07:23 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number> |
| 07:23 | clgv | ;) |
| 07:24 | SagiCZ1 | okay :) |
| 07:24 | borkdude | (read-string "1.64") |
| 07:25 | borkdude | ,(read-string "1.64") |
| 07:25 | clojurebot | 1.64 |
| 07:25 | clgv | borkdude: I am not sure where I read the finalizing part either the official blog post or on the mailing list |
| 07:25 | clgv | ha! right :P |
| 07:26 | dysfun | borkdude: potentially dangerous |
| 07:26 | clgv | then read-edn ;) |
| 07:27 | borkdude | dysfun clojure.edn/read-string |
| 07:27 | dysfun | also (binding [*read-eval* false]) if you're going to use read-str |
| 07:27 | dysfun | still gotta check what you get back afterwards |
| 07:27 | borkdude | dysfun I'm assuming everybody knows I mean that one ;) |
| 07:27 | dysfun | i suspect there are lots of people in this channel who don't |
| 07:28 | borkdude | dysfun they'll learn |
| 07:29 | dysfun | yes, but we prefer them not to learn in production :) |
| 07:29 | borkdude | dysfun production is the best teacher ;) |
| 07:29 | dysfun | that's definitely true, but it can go quite badly |
| 07:29 | clojurebot | I don't understand. |
| 07:31 | dysfun | now i think about it, , is presumably reminiscent on 'unquote' in other lisps, but clojure uses ~, so it seems an odd choice, especially considering how often people use commas compared to tildes |
| 07:31 | borkdude | dysfun of course I agree. |
| 07:37 | SagiCZ1 | (doc read-string) |
| 07:37 | clojurebot | "([s]); Reads one object from the string s. Note that read-string can execute code (controlled by *read-eval*), and as such should be used only with trusted sources. For data structure interop use clojure.edn/read-string" |
| 07:38 | SagiCZ1 | ,(read-string "(+ 3 3)") |
| 07:38 | clojurebot | (+ 3 3) |
| 07:43 | clgv | ,(-> "(+ 3 3)" read-string eval print) |
| 07:43 | clojurebot | 6 |
| 07:43 | clgv | repl yay! ;) |
| 07:44 | jonathanj | is there a shorter way to write: (fn [& args] [:foo (apply str args)]) ? |
| 07:44 | borkdude | jonathanj you could use a minifier |
| 07:44 | clgv | jonathanj: probably not |
| 07:45 | clgv | or do you want something like that: #(vector :foo (apply str %&)) |
| 07:45 | jonathanj | hrm |
| 07:46 | borkdude | jonathanj I was kidding btw |
| 07:46 | clgv | ,(#(vector :foo (apply str %&)) [:a 1 :b 2]) |
| 07:46 | clojurebot | [:foo "[:a 1 :b 2]"] |
| 07:46 | jonathanj | (defn apply-and-tag [tag f] (fn [& args] [tag (apply f args)])) |
| 07:46 | jonathanj | might work, i guess |
| 07:47 | jonathanj | i want an instaparse transformer that retains tags instead of consuming them |
| 07:47 | clgv | though that result looks strange |
| 07:47 | clgv | ,(apply str [:a 1 :b 2]) |
| 07:47 | clojurebot | ":a1:b2" |
| 07:47 | clgv | ah lol ;) |
| 07:47 | clgv | ,(#(vector :foo (apply str %&)) :a 1 :b 2) |
| 07:47 | clojurebot | [:foo ":a1:b2"] |
| 07:47 | jonathanj | thanks |
| 07:53 | jonathanj | so instaparse produces trees like [:tag [:another-tag [:foo "FOO"]]] |
| 07:54 | jonathanj | what's the easiest way to get the value of the :foo tag? |
| 07:57 | mbac | jonathanj, ((apply hash-map (second (second x))) :foo) |
| 07:57 | mbac | where x = [:tag [:another-tag [:foo "FOO"]]] |
| 07:58 | mbac | you could also just say (second (second (second x))) |
| 07:58 | mbac | but that's probably not what you had in mind |
| 08:00 | mbac | (reduce (fn [x k] ((apply hash-map x) k)) x [:tag :another-tag :foo]) |
| 08:00 | jonathanj | hrm |
| 08:00 | mbac | :P |
| 08:01 | jonathanj | hrm, this is kind of inconvenient to work with |
| 08:02 | jonathanj | i wonder if i'm missing something |
| 08:03 | hyPiRion | jonathanj: you can hide instaparse nodes with the <>-syntax I think |
| 08:03 | jonathanj | hyPiRion: yeah, but in this case i don't want to hide them because having them tagged seems like a useful way to pick out something specific, not so? |
| 08:04 | hyPiRion | jonathanj: well, it sort of depends on what you're doing I guess. (for me it was useful) |
| 08:05 | jonathanj | hyPiRion: parsing IRC messages |
| 08:05 | hyPiRion | I used it in conjunction with core.match for pattern matching |
| 08:05 | jonathanj | hyPiRion: do you have an example? |
| 08:05 | jonathanj | i'd be interested to see that |
| 08:14 | clgv | criterium question: are the mean durations in the result map always in seconds? |
| 08:16 | hyPiRion | jonathanj: not here unfortunately. but it'd be something like x = [:tag [:another-tag [:foo "FOO"]]], then (match [x] [[:tag [:another-tag [:foo foo]]]] foo :else :not-found) |
| 08:17 | hyPiRion | now, if you know all the different permutations à priori (like you'd do for instaparse), using core.match is very succinct |
| 08:37 | Chaze | Hi. Does Clojure have "arrows" (http://www.haskell.org/arrows/) in the core namespace somewhere? |
| 08:37 | dysfun | not in core |
| 08:38 | Chaze | somewhere that ships with clojure? |
| 08:38 | Chaze | (guess that's what i meant) |
| 08:38 | dysfun | check the 'functional programming' section here http://www.clojure-toolbox.com/ |
| 08:38 | dysfun | no, not in the base distribution. use a third party library |
| 08:38 | dysfun | unless there's one in contrib somewhere |
| 08:38 | dysfun | but those still require installing |
| 08:39 | Chaze | Alright, thanks. Great site |
| 08:40 | dysfun | yeah, it is :) |
| 08:48 | clgv | Chaze: btw. it is not automatically a problem if it is a third party library since leiningen makes it pretty easy for you to use those |
| 09:34 | jonathanj | is there a shorter way to write (apply hash-map (apply concat xs))? |
| 09:34 | zoldar | jonathanj: mapcat ? |
| 09:35 | jonathanj | mmm |
| 09:35 | zoldar | umm no |
| 09:35 | jonathanj | xs is like [[:a 1] [:b 2]] |
| 09:36 | mgaare_ | (into {} xs) should do it |
| 09:36 | jonathanj | oh, awesome |
| 09:44 | jonathanj | mgaare: thanks |
| 09:44 | mgaare | jonathanj: you're welcome |
| 09:46 | jonathanj | what's the convention for naming private variables in a namespace? |
| 09:46 | jonathanj | well, private values, rather |
| 09:47 | mgaare | use the ^:private metadata tag, and name it however you want |
| 09:54 | mavbozo | jonathanj: follow bbatsov's clojure style guide |
| 09:54 | mavbozo | jonathanj: https://github.com/bbatsov/clojure-style-guide#private |
| 09:57 | stompyj | private variables?! |
| 09:57 | stompyj | whats next? interfaces to classes? I thought this was #clojure, not #kingdomofnouns |
| 09:57 | stompyj | jk |
| 10:00 | mavbozo | stompyj: chill down. there will always be someone who doesn't know the proper usage of various terminologies |
| 10:00 | stompyj | mavbozo: haha, no, i was legit just messing around. this IRC channel is devoid of the typical pedantic rage that other chans have |
| 10:11 | mavbozo | stompyj: haha, it seems that I am in a very tense-serious mood |
| 10:12 | stompyj | haha, my bad |
| 10:23 | SagiCZ1 | btw why dont we have def- ? |
| 10:24 | Bronsa | SagiCZ1: because we'd need to have a defmulti-, a defonce-, a defprotocol- etc |
| 10:24 | Bronsa | SagiCZ1: just use ^:private, defn- was a bad idea |
| 10:25 | SagiCZ1 | Bronsa: seriously? |
| 10:25 | Bronsa | yes |
| 10:25 | SagiCZ1 | so should i avoid defn- ? |
| 10:25 | Bronsa | use it if you want |
| 10:25 | SagiCZ1 | ,(def x ^:private 6) |
| 10:25 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas> |
| 10:25 | Bronsa | ,(def ^:private x 6) |
| 10:25 | clojurebot | #'sandbox/x |
| 10:25 | SagiCZ1 | Bronsa: thank you |
| 10:25 | Bronsa | SagiCZ1: np |
| 10:28 | jonathanj | how do i do something like Python's repr() in Clojure? |
| 10:28 | jonathanj | i want to examine a string that may include characters line \r or \n |
| 10:28 | perplexa | yo, i have (map (partial a) x) and i want to exec first 'a' and then 'b' on each x, would i do (map (comp b a) x) ? |
| 10:29 | Bronsa | perplexa: (partial a) is just a |
| 10:29 | justin_smith | perplexa: do you want to run b on the result of a, or do each in parallel? |
| 10:29 | perplexa | also (partial) with a 1 param fn is probably pointless ;P |
| 10:29 | perplexa | Bronsa: yeah just realised :D |
| 10:29 | perplexa | justin_smith: yeah b on a |
| 10:29 | Bronsa | perplexa: then comp is ok |
| 10:29 | Bronsa | (map (comp - inc) [1 2 3]) |
| 10:29 | Bronsa | ,(map (comp - inc) [1 2 3]) |
| 10:29 | clojurebot | (-2 -3 -4) |
| 10:30 | Bronsa | otoh if you want to run them in parallel you'd want to use juxt |
| 10:30 | Bronsa | ,(map (juxt - inc) [1 2 3]) |
| 10:30 | mmeix | in the other case (a, and par. b) there would be juxt, as |
| 10:30 | clojurebot | ([-1 2] [-2 3] [-3 4]) |
| 10:30 | perplexa | yeah i have one of those examples myself and tried but |
| 10:30 | perplexa | i don't know which order it is |
| 10:30 | perplexa | ,map (comp inc (partial + 3)) [1 2 3]) |
| 10:30 | clojurebot | #<core$map clojure.core$map@1cf3511> |
| 10:30 | perplexa | ,(map (comp inc (partial + 3)) [1 2 3])) |
| 10:30 | clojurebot | (5 6 7) |
| 10:30 | perplexa | first inc then +? |
| 10:30 | Bronsa | perplexa: no |
| 10:30 | Bronsa | perplexa: right to left |
| 10:30 | perplexa | ok ty |
| 10:31 | Bronsa | that's why I used a non commutative example |
| 10:31 | perplexa | oh the - inc was obv.. ;P |
| 10:33 | mgaare | jonathanj: what does repr() do exactly? |
| 10:33 | perplexa | (inc Bronsa) |
| 10:33 | perplexa | ,inc Bronsa |
| 10:33 | clojurebot | #<core$inc clojure.core$inc@178fdc3> |
| 10:33 | perplexa | narf |
| 10:33 | perplexa | i'll never remember this |
| 10:33 | hyPiRion | (inc Bronsa) |
| 10:34 | hyPiRion | lazybot is dead, long live lazybot |
| 10:34 | Bronsa | perplexa: it was correct the first time, but lazybot is dead |
| 10:34 | perplexa | oh! |
| 10:34 | perplexa | living up to its name i guess |
| 10:35 | hyPiRion | hard at work |
| 10:35 | Bronsa | Raynes: you owe me an inc |
| 10:36 | daniel__ | (inc Bronsa) |
| 10:36 | daniel__ | ,(inc Bronsa) |
| 10:36 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Bronsa in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 10:37 | Bronsa | I'm undefined |
| 10:38 | mgaare | Bronsa: according to Joseph Heller, we all have to start ignoring you now |
| 10:39 | stompyj | (inc mgaare) |
| 10:40 | jonathanj | mgaare: for a string it produces an escaped string |
| 10:41 | jonathanj | repr("\r") -> "\\r" |
| 10:43 | mavbozo` | jonathanj: that's wrong. should be |
| 10:43 | mavbozo` | repr("\r") -> "'\\r'" |
| 10:44 | jonathanj | err, yes sorry |
| 10:46 | mgaare | jonathanj: not aware of a core clojure function that does that. pprint ignores newlines. you could also do something using clojure.string/replace |
| 10:47 | SagiCZ1 | is there a way to have clojure.pprint required no matter what namespace is currently set in the repl? |
| 10:47 | mgaare | with :inject in lein, perhaps |
| 10:48 | mgaare | er, :injections |
| 10:49 | mgaare | in fact that's the default usage example for it - https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L242 |
| 10:50 | SagiCZ1 | it says "Forms to prepend to every form that is evaluated inside your project." |
| 10:50 | SagiCZ1 | isnt that unecessary? |
| 10:51 | mgaare | it's not something you'd want to do in your production profile, to be sure |
| 10:51 | SagiCZ1 | mgaare: makes sense |
| 10:51 | andyf_ | jonathanj: Maybe clojure.string/re-quote-replacement is something like what you?re looking for? I should go read what Python?s repr() does first, though. |
| 10:52 | mavbozo` | jonathanj: do you want to use the escaped string in a regex expression? |
| 10:52 | perplexa | btw, is aot broken in lein 2.5? |
| 10:53 | andyf_ | jonathanj: Python?s repr() has many options for limiting the length and/or nesting depth of large Python objects. This is similar to (binding [*print-level* 7 *print-length* 10] (clojure.pprint/pprint value)) in Clojure |
| 10:54 | perplexa | coworker said sth like that and reverted to a previous lein version, just curious if anybody has experienced any issues |
| 10:55 | mmeix | playing with music structures in clojure... having the strong feeling, that this: https://www.refheap.com/92362 could be done shorter, but not sure how - anybody have a look? |
| 10:57 | jonathanj | mavbozo`: no, i just want to inspect a string |
| 10:59 | SagiCZ1 | can i simplify (or (= x 5) (= x 10)) so that i wouldnt have to repeat x? |
| 10:59 | andyf_ | jonathanj: I don?t know of any built-in Clojure function that limits the size of printed strings like Python?s repr() does, though. |
| 11:01 | gfredericks | SagiCZ1: in this case (#{5 10} x) would work |
| 11:03 | hyPiRion | SagiCZ1: (not (distinct? 5 10 x)) |
| 11:11 | SagiCZ1 | gfredericks, hyPiRion thanks |
| 11:14 | bostonaholic | mmeix: be careful with that implementation. (map notes (series 15)) will cause infinite recursion |
| 11:16 | mmeix | ah ... |
| 11:17 | mmeix | in the mean time I found (some #{x} coll) to test for repetitions, just a bit shorter than my first try |
| 11:18 | mmeix | bostonaholic thanks |
| 11:19 | bostonaholic | mmeix: but that's a cool idea. you could then do similar randomness of quarter, eighth, etc. to create some pretty interesting improv solos |
| 11:20 | mmeix | of course |
| 11:20 | bostonaholic | just play that through my speakers all day, on a blues scale |
| 11:20 | mmeix | this is just getting to grips with clojure |
| 11:20 | jeffterrell | jonathanj: Try (pr-str) |
| 11:20 | jeffterrell | ,(pr-str "\r") |
| 11:20 | clojurebot | "\"\\r\"" |
| 11:20 | jonathanj | thanks, that's probably sufficient |
| 11:21 | justin_smith | ,(shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"]) mmeix |
| 11:21 | clojurebot | ["g#" "a#" "e" "d" "d#" ...] |
| 11:21 | justin_smith | mmeix: your intention is a random permutation of a fixed set, right? |
| 11:22 | mmeix | not quite |
| 11:22 | patrkris | hi everybody. is there some way to have clojure.java.jdbc always replace undercores with hyphens in the field names of result sets? |
| 11:22 | mmeix | this is just a beginning |
| 11:22 | justin_smith | mmeix: (take n (shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"])) |
| 11:22 | justin_smith | to answer your "can this be done shorter" question |
| 11:23 | SagiCZ1 | im using io/reader to read a huge text file and i would like to skip the first half of lines for example, is that possible? |
| 11:23 | mmeix | there will be many methods to build more structurally anchored things, a random dodecaphonic series is just the most primitive example ... |
| 11:23 | justin_smith | mmeix: sure, just addressing the question in that comment, you are doing shuffle |
| 11:23 | mmeix | of course! I had forgotten about shuffle - thank |
| 11:24 | mmeix | this makes it much shorter :-) |
| 11:25 | mmeix | I'm thinking about a more functional version of something like http://web.mit.edu/music21/ |
| 11:26 | mmeix | which is great somehow, but overflows with classes and supers and subs ... |
| 11:26 | mmeix | this has to be done much more simple, functional |
| 11:26 | mmeix | I think |
| 11:27 | mmeix | [thus learning Clojure like crazy ;)] |
| 11:28 | SagiCZ1 | what is the goto benchmarking tool for clojure? or something that looks for hotspots? like which function is called the most |
| 11:28 | mmeix | justin-smith apologies & thanks! |
| 11:29 | patrkris | SagiCZ1: YourKit and JVisualVM seems to be popular choices |
| 11:29 | patrkris | *seem |
| 11:29 | SagiCZ1 | patrkris: JVisualVM is not clojure related though? its general jvm? |
| 11:29 | patrkris | SagiCZ1: I think you are right, yes |
| 11:30 | patrkris | I don't think there is anything specifically suited for Clojure |
| 11:30 | SagiCZ1 | patrkris: ok i will try to use that |
| 11:30 | stuartsierra | You need a JVM-level tool to get worthwhile performance metrics. |
| 11:30 | mavbozo | patrkris: put your converter function in :identifiers arguments in clojure.java.jdbc/query function, default lower-case |
| 11:30 | stuartsierra | Even then it's like voodoo. |
| 11:30 | mavbozo | patrkris: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/query |
| 11:30 | mavbozo | |
| 11:30 | patrkris | mavbozo: yeah, but I have to do that everywhere I call query, right? |
| 11:31 | mavbozo | patrkris: yeah, but we have macros |
| 11:31 | patrkris | we do :) |
| 11:34 | mavbozo | patrkris: and robert-hooke :p https://github.com/technomancy/robert-hooke/ |
| 11:35 | SagiCZ1 | thats interesting, according to jvisualvm the most called function is clojure.lang.RT.next() |
| 11:39 | justin_smith | SagiCZ1: well, what's more important than most called is which one it spends the most time calling |
| 11:43 | SagiCZ1 | justin_smith: its time as well, but maybe im doing something wrong |
| 11:43 | mavbozo | I often get java.lang.OutOfMemoryError: PermGen space when doing too many (refresh) using org.clojure/tools.namespace |
| 11:44 | mavbozo | is it just me? or is anyone else having this kind problem? |
| 11:44 | stuartsierra | mavbozo: Which JVM? |
| 11:44 | mavbozo | java version "1.7.0_67" |
| 11:44 | mavbozo | Java(TM) SE Runtime Environment (build 1.7.0_67-b01) |
| 11:44 | mavbozo | Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode) |
| 11:45 | SagiCZ1 | mavbozo: i've had this problem in a completely different circumstance (jetty hot deploy) but you could try turning permgen garbage collection on |
| 11:45 | justin_smith | mavbozo: 1.8 doesn't even have segregated permgen any more iirc, if upgrading is an option. Or you can just bump up the alloted space for permgen |
| 11:46 | stuartsierra | SagiCZ1, mavbozo: PermGen is GC'd by default. |
| 11:46 | SagiCZ1 | stuartsierra, mavbozo: see https://stackoverflow.com/questions/7383658/permgen-space-exception?lq=1 |
| 11:46 | stuartsierra | But you can fill up the space if you're recompiling a large project. |
| 11:46 | mavbozo | SagiCZ1: I just increase increase the -XX:MaxPermSize |
| 11:47 | stuartsierra | I've had to increase the PermGen size for large projects (hundreds of Clojure source files) |
| 11:48 | mavbozo | thanks everyone |
| 11:48 | justin_smith | stuartsierra: the top SO answer at that link claims permgen GC is off by default |
| 11:48 | stuartsierra | justin_smith: I take no responsibility for what StackOverflow says. |
| 11:49 | justin_smith | stuartsierra: OK - I wasn't saying you were wrong, just pointing out the discrepency |
| 11:49 | mavbozo | stuartsierra: please add that in Warnings section in https://github.com/clojure/tools.namespace README |
| 11:49 | stuartsierra | Older JDKs had PermGen GC disabled by default, but not 1.7. |
| 11:49 | stuartsierra | mavbozo: I will consider that. |
| 11:49 | justin_smith | stuartsierra: thanks for the clarification. Too bad 1.6 is still such a common deployment target. |
| 11:50 | stuartsierra | I'm not certain if 1.6 has it enabled by default, but I think it does. |
| 11:50 | stuartsierra | May depend on the vendor. |
| 11:50 | justin_smith | stuartsierra: I had production issues with permgen running out that I never saw locally, and had a 1.7 / 1.6 split, but I never proved that was the cause... |
| 12:34 | SagiCZ1 | is both first and next always in constant time? |
| 12:38 | justin_smith | SagiCZ1: they call seq - if seq is always constant time then they are too, but I am not sure if seq is always constant time |
| 12:40 | dopamean_ | justin_smith: the other day you mentioned hat i could install a library locally |
| 12:40 | dopamean_ | and you said something really simple that i have now forgotten |
| 12:40 | justin_smith | oh, and seq can wrap a java iterable, and that iterable could hypothetically in a pathological case have a non-linear Iterator? |
| 12:40 | dopamean_ | originally i wanted to use a library i had written that is not on clojars |
| 12:40 | justin_smith | dopamean_: lein install |
| 12:40 | dopamean_ | doh |
| 12:41 | dopamean_ | thanks |
| 13:00 | SagiCZ1 | ,(time (dotimes [_ 10000000] (first (range 5)))) |
| 13:00 | clojurebot | eval service is offline |
| 13:00 | SagiCZ1 | ,(+ 5 3) |
| 13:00 | clojurebot | 8 |
| 13:01 | SagiCZ1 | anyways first is dependent on the size of the size of the sequence even though its lazy..... what a bummer why wouldnt first be always constant .. this breaks my performance terribly |
| 13:02 | hyPiRion | SagiCZ1: no, it isn't. It's dependent on the 1-32 first elements, but only if the lazy seq is chunked. |
| 13:02 | justin_smith | wat - how would first be dependent on the size of the sequence? |
| 13:03 | hyPiRion | It's a bit weird and strange at first, but things are usually chunked unless you do something like (iterate ...) or lazy-seq yourself |
| 13:03 | SagiCZ1 | i ran two tests.. |
| 13:03 | SagiCZ1 | (time (dotimes [_ 10000000] (first (range 50000000000000)))) took 12 seconds |
| 13:03 | SagiCZ1 | (time (dotimes [_ 10000000] (first (range 5)))) took 4 seconds |
| 13:04 | SagiCZ1 | and it is very consistent on my pc |
| 13:04 | justin_smith | SagiCZ1: (range 50) takes as long as (range 50000000000000) |
| 13:05 | justin_smith | SagiCZ1: it's because of chunking, like hyPiRion said |
| 13:05 | justin_smith | first of range realizes the first 32 or so elements |
| 13:06 | SagiCZ1 | oh.. i see, sorry |
| 13:06 | SagiCZ1 | i didnt get hyPiRion's message at first |
| 13:21 | rooster_rus | is there something like perl's "state" variables in clojure? state variables are basicly kept between function calls. I'm trying to make something like (take-while increases!? coll) where increases!? keeps value of previous call. |
| 13:22 | rooster_rus | also state variables are lexically scoped within function body |
| 13:23 | tropicalmug | Hi all. Does anyone have a library of choice for handling RSS feeds? Handling would mean reading entries, caching state, finding new entries. I've found the Java library ROME, but I'm a little unsure of how that works. |
| 13:28 | SagiCZ1 | rooster_rus: i dont think there are state variables but there is always a way of working around that in clojure, maybe iterate or reduce would help you |
| 13:29 | justin_smith | tropicalmug: I have had good luck with https://github.com/yogthos/clj-rss |
| 13:30 | mmeix | I owe justin_smith some incs |
| 13:30 | justin_smith | rooster_rus: you could close over an atom with your function definition, but there is likely a way to realize whatever algorithm you are doing without a state variable |
| 13:30 | mmeix | (inc justin_smith) |
| 13:31 | justin_smith | mmeix: lazybot is out |
| 13:31 | justin_smith | thanks though :) |
| 13:31 | mmeix | I' keep your (repeatedly 5 (inc justin_smith)) for later :-) |
| 13:32 | justin_smith | SagiCZ1: since he is tracking the last argument to the function, that means he is dealing with state and concurrency in a way that reduce or iterate won't really help with - he needs something that manages concurrent access |
| 13:32 | tropicalmug | justin_smith That looks good for creating feeds, though that isn't my use case |
| 13:32 | justin_smith | rooster_rus: agents are values that manage unsyncronized sequential update, that may help you |
| 13:33 | justin_smith | tropicalmug: oh, you want to consume feeds |
| 13:34 | justin_smith | tropicalmug: I don't know of anything, but given your description I would imagine using clojure.xml to make edn data out of the xml, and an atom to cache and update state |
| 13:34 | tropicalmug | justin_smith I was hopeful there would just be the go-to Clojure wrapper for Rome, but rolling my own library isn't the end of the world. |
| 13:34 | tropicalmug | Thanks! |
| 13:35 | justin_smith | https://github.com/scsibug/feedparser-clj this is a ROME wrapper |
| 13:37 | tropicalmug | justin_smith :-b |
| 13:42 | justin_smith | tropicalmug: it's a pretty thin wrapper, just one namespace |
| 13:49 | tropicalmug | justin_smith might hack it to support the conditional-get parts of the rome fetcher. Beyond that, it's all I need. Thanks again. |
| 13:56 | TimMc | "eduction", really? |
| 13:57 | Bronsa | TimMc: it took me by surprise too |
| 14:01 | justin_smith | eduction? |
| 14:01 | mmeix | a typo for Reducation :-) |
| 14:02 | gfredericks | it took me several seconds not to read "education" |
| 14:04 | mmeix | we could need an "educate" function in clojure, for misbehaved colls... (educate {3.14 :a 1/3 :b}) :-) |
| 14:07 | justin_smith | ,{1.0M 1 1 1 1.0 1} |
| 14:07 | clojurebot | {1.0 1, 1 1, 1.0M 1} |
| 14:09 | mmeix | Is there a better way to extract a number's digits than this: (- (int %) 48) (str 42) - looks like cheating to me... |
| 14:09 | mmeix | sorry: (map #(- (int %) 48) (str n)) |
| 14:11 | Bronsa | justin_smith: it's the new name for `iteration` |
| 14:11 | hashpuppy | can someone explain what this does: (defrecord Click [pos] IFn (-invoke [_ state] (click pos state))) |
| 14:12 | hashpuppy | it's in clojurescript |
| 14:12 | Bronsa | hashpuppy: it makes your record invokable |
| 14:12 | dbasch | mmeix: see this blog post for a number of ways http://diegobasch.com/life-the-universe-and-technical-interviews |
| 14:12 | Bronsa | so you can do ((Click. foo) 1) |
| 14:13 | justin_smith | Bronsa: context? |
| 14:13 | mmeix | dbasch thanks! |
| 14:17 | TimMc | justin_smith: eduction |
| 14:17 | chronno | justin_smith: http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/eduction |
| 14:19 | danneu | In Om, you can use `ref` to expose an arbitrary dom node so that you can, for example, focus it in a callback. But how do you do that in Reagent? |
| 14:21 | Bruce_Wayne | anyone ever see when two strings are the same but don’t pass the = test |
| 14:21 | sg2002 | assault_ninjaD9ULSuSkji9YPmKbA462 |
| 14:21 | Bruce_Wayne | but they do pass the = test after wrapped in a prn |
| 14:21 | danneu | Bruce_Wayne: do they pass the == test |
| 14:22 | Bruce_Wayne | is that a thing |
| 14:22 | Bruce_Wayne | ? |
| 14:22 | danneu | ,(== 1 1.0) |
| 14:22 | clojurebot | true |
| 14:22 | Bruce_Wayne | danneu: no they don’t because they are strings not numbers |
| 14:23 | danneu | oh, it's just for numbers? |
| 14:23 | danneu | i now see "nums" in the docstring, but i recall it being useful in another circumstance |
| 14:24 | SagiCZ1 | is there a way to read only last n lines of a file, skipping the lines before? |
| 14:25 | danneu | nvm |
| 14:25 | justin_smith | Bruce_Wayne: the equal after prn thing is odd, you should take the base64 of their byte-array representation next time |
| 14:25 | danneu | SagiCZ1: line-seq + take-last? |
| 14:26 | justin_smith | ,(String. (clojure.data.codec.base64/encode (.getBytes "hello"))) ; Bruce_Wayne |
| 14:26 | clojurebot | #<CompilerException java.lang.ClassNotFoundException: clojure.data.codec.base64, compiling:(NO_SOURCE_PATH:0:0)> |
| 14:26 | justin_smith | ,(require 'clojure.data.codec.base64) |
| 14:26 | clojurebot | #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec/base64__init.class or clojure/data/codec/base64.clj on classpath: > |
| 14:26 | justin_smith | hrmph |
| 14:26 | justin_smith | ,(require 'clojure.data.codec) |
| 14:26 | clojurebot | #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec__init.class or clojure/data/codec.clj on classpath: > |
| 14:27 | SagiCZ1 | danneu: i think take-last still realizes the elements before |
| 14:27 | justin_smith | SagiCZ1: danneu: it definitely does |
| 14:27 | SagiCZ1 | i was thinking maybe some magic with interop .seek ... but i have never used it |
| 14:28 | danneu | SagiCZ1: how about http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/ReversedLinesFileReader.html |
| 14:28 | justin_smith | SagiCZ1: I think you'll need to use interop to seek on the file stream and move backward past N newlines |
| 14:28 | justin_smith | SagiCZ1: or get the one creating the files to do proper rotation so that file size is more reasonable :) |
| 14:29 | SagiCZ1 | danneu: thats pretty wicked actually.. what i really need is to read last lines of some sort of log, so this class could help me a lot |
| 14:29 | SagiCZ1 | justin_smith: haha.. or i could rotate them myself with some simple script.. would took hours though |
| 14:33 | justin_smith | SagiCZ1: well, many loggers come with rotating options you can turn on |
| 14:36 | justin_smith | I wish there was an easy way to run two branches of the same project ... I mean yeah I can do a clone but I don't need to replicate the whole git apparatus, just have two branches visible and isolated at once... |
| 14:37 | SagiCZ1 | justin_smith: why would you need to clone something if you want to make a branch? |
| 14:37 | justin_smith | SagiCZ1: to have both running at once |
| 14:38 | justin_smith | looks like I can use git-new-workdir http://nuclearsquid.com/writings/git-new-workdir/ |
| 14:38 | TimMc | justin_smith: If you clone a git repo from one place on disk to another, it uses hardlinks so it takes up less space... |
| 14:38 | SagiCZ1 | oh i see.. interesting usage, seems like it would be pretty handy |
| 14:38 | justin_smith | TimMc: oh, great, so it just does the right thing |
| 14:39 | TimMc | It does mess up your remotes, though. :-P |
| 14:39 | justin_smith | TimMc: that was my concern, was getting two copies of everything in the git history |
| 14:39 | justin_smith | TimMc: ugh |
| 14:39 | justin_smith | mess up as in? |
| 14:39 | TimMc | The second's only remote is the first. |
| 14:39 | justin_smith | oh, that's fine for my usage |
| 14:39 | justin_smith | thanks man |
| 14:39 | justin_smith | (inc TimMc) |
| 14:40 | justin_smith | Raynes: can we have lazybot back pretty please? |
| 14:41 | Raynes | justin_smith: One lazybot for you sir. |
| 14:41 | justin_smith | (inc Raynes) |
| 14:41 | Raynes | Well wait a second :P |
| 14:41 | danneu | in the meantime, Raynes is manually reading through the #clojure logs and balancing the inc ledger by hand |
| 14:41 | justin_smith | hehe :) |
| 14:41 | SagiCZ1 | danneu: xD |
| 14:41 | Bronsa | (inc TimMc) |
| 14:41 | SagiCZ1 | he better! |
| 14:41 | lazybot | ⇒ 74 |
| 14:41 | Raynes | Hah, the amount of shits I gave is way too small for that. |
| 14:42 | Raynes | My time would be better spent moving lazybot to latest irclj and getting real reconnection support. |
| 14:42 | Raynes | :P |
| 14:42 | Bronsa | lazybot: <3 |
| 14:42 | Raynes | Or anyone's time, for that matter. Blow off work today and do that for me ^ |
| 14:42 | Raynes | I'll give you one (1) cookie. |
| 14:43 | dbasch | the ledger for the karma currency must be consistent and partition-tolerant |
| 14:43 | justin_smith | dbasch: well there are systems that are not C, A, or P |
| 14:44 | justin_smith | 2/3 is the best case, 0/3 is the worst |
| 14:44 | dbasch | or you can be trivially CAP with /dev/null |
| 14:45 | SagiCZ1 | dbasch: how do you get the ledger number for someone? |
| 14:45 | dbasch | $karma SagiCZ1 |
| 14:45 | lazybot | SagiCZ1 has karma 0. |
| 14:46 | SagiCZ1 | dbasch: awww |
| 14:46 | SagiCZ1 | thats harsh |
| 14:46 | dbasch | karma don’t come easy around these parts |
| 14:46 | mmeix | (inc justin_smith) |
| 14:46 | lazybot | ⇒ 105 |
| 14:47 | justin_smith | (inc stuartsierra) |
| 14:47 | lazybot | ⇒ 13 |
| 14:47 | justin_smith | (inc TimMc) |
| 14:47 | lazybot | ⇒ 75 |
| 14:50 | csd_ | How do I bind *out* to a file object for use with with-open? |
| 14:51 | hfaafb | whats the point of ^:const? |
| 14:52 | sg2002 | assault_ninjaD9ULSuSkji9YPmKbA462 |
| 14:53 | justin_smith | csd_: (with-open [f (java.io.FileWriter. "tmpfile")] (binding [*out* f] (prn {:a 0 :b 1}))) |
| 14:54 | justin_smith | csd_: but for a simple case like that pr-str / spit is easier |
| 14:54 | csd_ | what about binding StringWriter? |
| 14:55 | justin_smith | csd_: so do you want with-out-str? |
| 14:55 | justin_smith | ,(with-out-str (prn {:a 0 :b 1})) |
| 14:55 | clojurebot | "{:b 1, :a 0}\n" |
| 14:56 | csd_ | I want to use clojure.data's write-csv function, but it takes a file object to write to, and I want to work with it in the REPL |
| 14:56 | justin_smith | csd_: it seems odd that there wouldn't be a version that just handed you the string... |
| 14:57 | turbofail | pretty sure you could just use (write-csv *out* ...) |
| 14:57 | justin_smith | csd_: it takes a writer, so you can hand it a StringWriter directly as an arg |
| 14:57 | justin_smith | or that if you just want to print, yeah |
| 14:57 | justin_smith | ,(class *out*) |
| 14:57 | clojurebot | java.io.StringWriter |
| 14:58 | csd_ | what file object would i use if i wanted to pass the transformed object in my code? |
| 14:58 | csd_ | would StringWriter still work |
| 14:59 | justin_smith | none of this requires a file |
| 14:59 | justin_smith | it takes a writer |
| 14:59 | justin_smith | create a StringWriter and pass it in if you want that |
| 15:01 | csd_ | i'll give it a shot, thanks |
| 15:13 | arrdem | so has anyone actually built Philip Lord's [n .. 20] unrolling defn yet? |
| 15:13 | amalloy | arrdem: link? |
| 15:14 | arrdem | amalloy: https://groups.google.com/forum/#!topic/clojure/hnkJb9_il_M |
| 15:15 | amalloy | arrdem: that's been an open problem for years. it turns out to be really hard to write a generic unrollng macro, and if you do then it's actually harder to read code that uses it than it is to read hand-unrolled code |
| 15:17 | arrdem | amalloy: oh I totally believe that. I've been kicking the idea around in my head for a day now and "it's hard" is definitely the conclusion. I'm just wondering whether it'll actually achieve a measurable speedup or not. my intuition is not, unless there is an upper bound on apply argument counts that happens to be N ≤ 20 |
| 15:17 | arrdem | or at least a bound on the common case |
| 15:19 | puredanger | old ticket for this: http://dev.clojure.org/jira/browse/CLJ-731 |
| 15:20 | dbasch | it would be interesting to crawl all clojure from github and see what things people are doing that could be helped by generic, untargeted optimizations |
| 15:20 | amalloy | arrdem: are we sure that building the list is actually the expensive part like puredanger says? i would have guessed it's the looping, and it doesn't look like the timing stuff in the ticket says *why* the variadic call is more expensive |
| 15:20 | arrdem | amalloy: no idea we'd have to actually start looking at JIT'd code |
| 15:20 | puredanger | I don't really know for sure - feel free to do some perf analysis |
| 15:21 | arrdem | amalloy: my gut agrees with you... I'd think that the looping is more expensive than an array which is 1) created, 2) unpacked and then 3) discarded |
| 15:21 | Bronsa | varargs & apply are both slower than fixed args + direct invoke, no idea what % they individually contribute to |
| 15:21 | Bronsa | but usually they go hand in hand |
| 15:21 | Bronsa | eliminating one usually eliminates the other too |
| 15:21 | arrdem | amalloy: just because that array would seem like an ideal candidate for bytecode elision. |
| 15:22 | puredanger | as Rich would say "why guess when you can measure? |
| 15:22 | dpetrovics | anyone in here use kioo? (https://github.com/ckirkendall/kioo) Ran into something odd with the do-> chaining transformation |
| 15:22 | arrdem | puredanger: measuring is hard :P |
| 15:22 | puredanger | can't say I've ever seen him take that as an excuse :) |
| 15:27 | Bronsa | automating unrolling + automating inlining would make reading through core.clj so much easier |
| 15:27 | Bronsa | and probably removing manual chunked-seq handling :P |
| 15:30 | mmeix | as an exercise I built a digits-finder ... wondering, if this could be simplified/ improved: https://www.refheap.com/92381 |
| 15:43 | dbasch | mmeix: (defn digits [x] (when (pos? x) (concat (digits (quot x 10)) [(rem x 10)]))) |
| 15:43 | dbasch | mmeix: although mine returns nil for 0, yours returns the empty sequence |
| 15:44 | mmeix | studying your solution ... |
| 15:44 | dbasch | also mine can be lazyfied trivially |
| 15:44 | Bronsa | dbasch: it's easy to fix it though, just change the when to an if and return () on the else branch |
| 15:44 | mmeix | it has no loop |
| 15:45 | dbasch | Bronsa: yes, it’s trivial |
| 15:45 | dbasch | it should return 0 anyway :) |
| 15:46 | mmeix | amazing how much shorter experienced clojurists get it, every time ... |
| 15:46 | sdegutis | Never mind, figured it out. |
| 15:47 | mmeix | (inc dbasch) |
| 15:47 | lazybot | ⇒ 16 |
| 15:49 | dbasch | (btw, not that I see a reason to lazify getting the digits of a number) |
| 15:49 | arrdem | huh |
| 15:50 | arrdem | amalloy: puredanger: looks like that unrolling is a potentially huge perf win unless my benchmark is crap |
| 15:50 | arrdem | https://www.refheap.com/92383 |
| 15:51 | arrdem | I see the arity unrolled victim with call site unpacking doing a factor of up to 5 better than the apply invocation |
| 15:51 | arrdem | both apply invocations are identical |
| 15:51 | justin_smith | mmeix: it's learning and pattern recognition, you eventually learn to recognize the common tasks, and remember how to express them concisely |
| 15:51 | puredanger | arrdem: also need to cross that with frequency of use |
| 15:52 | mmeix | justin_smith ja, it's getting better (know this from teaching music theory: lots of gestalt recognition...) |
| 15:55 | arrdem | https://www.refheap.com/92385 improved benchmark.. |
| 15:56 | arrdem | the call site arity unpacking (basically static call arity determination) looks like the real win here |
| 15:57 | arrdem | maybe this makes sense to do, but it really comes down to avoiding or rewriting apply with partial evaluation |
| 16:03 | turbofail | that would be a nice thing to have |
| 16:05 | turbofail | i would like to be able to use `apply' in more places without throwing performance out the window |
| 16:07 | turbofail | though i wonder how costly that partial evaluation would be in terms of compile time, in order to do it reliably |
| 16:07 | arrdem | eh you quickly wind up needing a really smart partial evaluator or flat out dependent types in order to do static arity determination of apply :/ |
| 16:08 | arrdem | it's not expensive, it just requires purity/effect analysis and a bunch of other stuff we don't have |
| 16:08 | arrdem | it's easier to do if you have an interpreter lying around as well.. |
| 16:08 | {blake} | I'm using "->" to do a bunch of serial map associations, like "(-> (assoc % :whatever (whatever-func var1)) -> (assoc :next-key (next-func var2))" etc., and trying to figure out how best to handle when the function (whatever-func, next-key-func) returns a nil. Should I just clean the map out after or is there a better way? |
| 16:09 | turbofail | might be better to have a wrapper around assoc that doesn't do the association if the value is nil |
| 16:10 | {blake} | turbofail, Ah...yeah, I like that. Thanks! |
| 16:10 | arrdem | don't we have when-> or something that short circuits at the first nil value? |
| 16:10 | {blake} | arrdem, Maaaybe? =P |
| 16:10 | neatonk | http://clojuredocs.org/clojure.core/some-%3E |
| 16:10 | arrdem | (inc neatonk) |
| 16:10 | lazybot | ⇒ 1 |
| 16:10 | neatonk | some-> |
| 16:10 | arrdem | that's the one |
| 16:11 | {blake} | neatonk, arrdem Cool. |
| 16:11 | turbofail | i dunno how well that would fit into this use case though |
| 16:11 | {blake} | Heh, I don't either. Let me try it. |
| 16:17 | {blake} | Ahhh...No, doesn't work because my code is: |
| 16:17 | SagiCZ1 | is there a reason why should the speed of execution depend on size of the queue in this example? is that loop terrible? https://www.refheap.com/92392 |
| 16:17 | {blake} | (assoc :key (get-val item)) so I've got a ":key nil" map entry. |
| 16:18 | {blake} | If I recode it as (some-> (get-val item)), it'll work of course, but I'm not sure that's an improvement. |
| 16:18 | {blake} | Good to have "some->" in the toolbox, tho'. |
| 16:20 | Chaze | What a strange REPL behaviour. (range 1 6622) yields a list as expected. (range 1 6623) yields () |
| 16:20 | SagiCZ1 | ,(range 1 6623) |
| 16:20 | clojurebot | (1 2 3 4 5 ...) |
| 16:20 | SagiCZ1 | Chaze: try a new repl instance |
| 16:22 | Chaze | SagiCZ1: nope. It works with the latest clojure.jar, but the problem exists in counterclockwise using clojure "1.5.1" |
| 16:22 | Chaze | (in case anyone wants to try to replicate it) |
| 16:23 | Chaze | its not just in the REPL, it also occurs in my code at different cutoffs |
| 16:25 | SagiCZ1 | oh, count is O(n) for lists i guess .. thats the problem then |
| 16:25 | justin_smith | SagiCZ1: yeah, and it breaks laziness too |
| 16:26 | SagiCZ1 | justin_smith: whenever i try to make a minimal working example i always omit the part which causes the issue thinking its irelevant |
| 16:26 | arrdem | SagiCZ1: I note that your "loop" is really just (nth (iterate c foo) (count queue)) |
| 16:26 | SagiCZ1 | arrdem: is it? that sounds strange |
| 16:27 | arrdem | SagiCZ1: you have no data dependency between "c" and e/q |
| 16:27 | SagiCZ1 | arrdem: yeah i deleted it from the example, sorry to make it confusing |
| 16:28 | SagiCZ1 | if i want to just simply loop through a collection i need at least two bindings in the loop form right? the collection and the next element |
| 16:28 | arrdem | sure, but you could write that as (loop [[head & more] col] ...) |
| 16:28 | SagiCZ1 | cool |
| 16:29 | SagiCZ1 | internaly it would use first and next maybe? |
| 16:29 | justin_smith | ,(loop [coll (range 10)] (if (= (count coll) 1) (even? (first coll)) (recur (next coll)))) |
| 16:29 | clojurebot | false |
| 16:29 | justin_smith | a loop with only one binding |
| 16:29 | justin_smith | that iterates to the end of the coll |
| 16:29 | arrdem | SagiCZ1: macroexpand tells no lies :D |
| 16:30 | SagiCZ1 | justin_smith: okay so one binding is enough, but since i dont want to repeat (first coll) in my code i will go with the [[element & more] coll] |
| 16:31 | SagiCZ1 | wait |
| 16:31 | SagiCZ1 | isnt the deconstruing done only in the first pass? |
| 16:31 | justin_smith | it's done on every pass |
| 16:31 | amalloy | SagiCZ1: i generally don't like using [x & xs] to walk over a sequence. there are a few problems with it |
| 16:32 | arrdem | amalloy: do share. I was not aware of any. |
| 16:32 | amalloy | first, you can't even tell when the sequence becomes empty |
| 16:32 | SagiCZ1 | ,(seq []) |
| 16:32 | clojurebot | nil |
| 16:32 | amalloy | neither x nor xs can tell you that the collection is empty. if xs is nil, then you know there is at most one element in the collection |
| 16:33 | amalloy | if x is nil, you know that either the collection is empty or there's a nil in it |
| 16:33 | puredanger | there are a lot of cases where I know the latter |
| 16:33 | SagiCZ1 | [e & more] .. when more is empty, seq returns nil right? |
| 16:33 | puredanger | err, know that there ins't nil I should say |
| 16:34 | arrdem | SagiCZ1: seq is defined to return nil for empty sequences |
| 16:34 | arrdem | lazybot: good you're still here |
| 16:34 | amalloy | additionally, there are laziness concerns: if you destructure into [x & xs] and decide that x is the last element of the sequence that you need to look at, too bad: you've already forced one additional element, by asking for xs |
| 16:34 | arrdem | &(macroexpand '(loop [[x & more] [1 2]] 1)) |
| 16:34 | lazybot | ⇒ (let* [G__11389 [1 2] vec__11390 G__11389 x (clojure.core/nth vec__11390 0 nil) more (clojure.core/nthnext vec__11390 1)] (loop* [G__11389 G__11389] (clojure.core/let [[x & more] G__11389] 1))) |
| 16:36 | arrdem | not especially helpful.. |
| 16:38 | SagiCZ1 | amalloy: could you provide me with a better approach with loop then? i am overthinking this too much.. |
| 16:38 | amalloy | SagiCZ1: just loop over the coll, and call first when you need to, and rest when you need to |
| 16:39 | amalloy | if you want to avoid calling first twice, then let-bind it to save the result |
| 16:39 | SagiCZ1 | rest or next? |
| 16:39 | amalloy | wellllll, that depends what you're doing |
| 16:39 | amalloy | rest is a better default choice |
| 16:40 | dbasch | SagiCZ1: why don’t you take a step back and explain what you’re trying to do? It’s not at all obvious from your code snippet |
| 16:40 | SagiCZ1 | will remember that.. i know the difference is subtle and i cant think of an example where it migh matter |
| 16:40 | arrdem | &(next '()) |
| 16:40 | lazybot | ⇒ nil |
| 16:40 | arrdem | &(rest '()) |
| 16:40 | lazybot | ⇒ () |
| 16:40 | sdegutis | Why is there de-dupe now instead of changing distinct based on its argument type? |
| 16:41 | puredanger | they do different things |
| 16:41 | sdegutis | Oh. |
| 16:41 | puredanger | de-dupe removes duplicates in a row |
| 16:41 | sdegutis | Also why is it not called de-duplicate? |
| 16:41 | puredanger | distinct has to keep track of all "seen" values, which is prob a bad idea on streams |
| 16:41 | puredanger | who has time for names that long? |
| 16:41 | puredanger | ;) |
| 16:41 | dbasch | puredanger: java :) |
| 16:42 | sdegutis | We already have "difference"... |
| 16:42 | amalloy | puredanger: i bet we could find a shorter name for 'first, too |
| 16:42 | sdegutis | And "denominator". |
| 16:42 | puredanger | car? |
| 16:42 | sdegutis | And "descendents". |
| 16:42 | arrdem | lol |
| 16:42 | puredanger | you're right, I'm going to remove as many chars from all those as possible. |
| 16:43 | amalloy | sdegutis: clojure doesn't really have a consistent approach to abbreviations, name styles, whatever |
| 16:43 | technomancy | nrplacd |
| 16:43 | technomancy | dem vowels ain't free y'know |
| 16:44 | amalloy | you just kinda roll with it. it's not like de-dupe is objectively better or worse than de-duplicate, or dedupe for that matter |
| 16:44 | EvanR | people say de-dupe in real life |
| 16:44 | puredanger | it's actually dedupe |
| 16:45 | technomancy | "unstutter" is the name I've seen |
| 16:45 | amalloy | oh good. de-dupe seemed weird to me |
| 16:45 | puredanger | I think I wrote de-dupe somewhere incorrectly and it's propagated |
| 16:45 | technomancy | (emphasizes it only removes consecutive dupes) |
| 16:45 | puredanger | http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/dedupe |
| 16:45 | llasram | technomancy: Ooh, I like that one |
| 16:46 | sdegutis | Thanks. |
| 16:46 | amalloy | (inc unstutter) |
| 16:46 | lazybot | ⇒ 1 |
| 16:46 | sdegutis | Since I'm stuck using Clojure, might as well use transducers. |
| 16:46 | puredanger | that's the spirit |
| 16:46 | SagiCZ1 | sdegutis: stuck using clojure |
| 16:46 | SagiCZ1 | never heard that before |
| 16:48 | arrdem | I suppose unstutter of n probably wouldn't get used that often.. |
| 16:59 | technomancy | http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg01000.html |
| 16:59 | technomancy | ^ in today's tragicomic packaging security news |
| 16:59 | mich | hey |
| 16:59 | mich | what linux distributions are you using here? |
| 17:00 | llasram | Debian 3 eva <3 |
| 17:00 | llasram | Er, "4" even |
| 17:00 | mich | llasram: do you also run X or something in it? |
| 17:02 | TimMc | technomancy: :sad-trombone |
| 17:03 | technomancy | TimMC: I don't even |
| 17:03 | arrdem | technomancy: can you sneak .elcs into an elpa package? |
| 17:03 | technomancy | it makes a non-tls request on 443 ._. |
| 17:03 | technomancy | arrdem: anything you can imagine is possible at zombomacs |
| 17:04 | arrdem | technomancy: good. so we can MITM ELPA serving .elc viri :D |
| 17:04 | arrdem | over "https" |
| 17:08 | mgaare | seems like there a lot of libs around (new ones even) that still use (ns ... (:use ...)) |
| 17:08 | sdegutis | Because it's just so fun. |
| 17:09 | arrdem | more importantly we have a bunch of tutorials with high Google PageRank scores that use (:use) |
| 17:09 | sdegutis | If :use works then it's perfectly fine. |
| 17:09 | amalloy | ~blogs |
| 17:09 | justin_smith | also, it's how other languages usually import libs |
| 17:09 | clojurebot | blogs are never to be trusted |
| 17:09 | sdegutis | If it isn't fine then it should be removed. |
| 17:10 | sdegutis | This blog is actually quite trustworthy: http://blog.8thlight.com/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html |
| 17:10 | sdegutis | Despite being quite aged. |
| 17:10 | amalloy | sdegutis: it is trustworthy and *four years old* |
| 17:10 | sdegutis | Hence my disclaimer, O slow poke. |
| 17:10 | amalloy | it recommends some stuff that is just Not Done anymore |
| 17:11 | sdegutis | Well I haven't actually read it. |
| 17:11 | mgaare | Isn't (use) "deprecated"? |
| 17:11 | sdegutis | I just know that Colin is trustworthy. I mean, he wrote a book. |
| 17:11 | technomancy | it's good advice if you need 1.3 compatibility |
| 17:11 | technomancy | protip: you don't need 1.3 compatibility |
| 17:11 | mgaare | or just informally no-longer-idiomatic |
| 17:12 | mdrogalis | technomancy: core.async is still alpha. You never know. |
| 17:12 | arrdem | Eastwood will complain about (:use), right? |
| 17:12 | Bronsa | it should |
| 17:12 | amalloy | hey, two years ago a sentence was added to that article saying "don't use :use anymore, use :require/refer" |
| 17:13 | technomancy | is add-watch still alpha? |
| 17:13 | amalloy | but it's just stuck in the middle of some text about how to use :use; i certainly didn't notice it last time i was reading it |
| 17:13 | sdegutis | In either case, it was a trustworthy blog. |
| 17:13 | puredanger | technomancy: no |
| 17:13 | technomancy | cool |
| 17:13 | amalloy | sdegutis: that's the problem with blogs. they are accurate at the time they are written |
| 17:13 | sdegutis | Personally I think my (ns) lines are way more cluttered than they ought to be. |
| 17:13 | sdegutis | amalloy: Only the accurate ones. |
| 17:13 | puredanger | technomancy: I removed the alpha tag from almost everything in 1.6 (reducers is one notable exception) |
| 17:14 | mdrogalis | puredanger: :) |
| 17:14 | arrdem | Bronsa: huh looks like it warns against unlimited use not against the (:use) form |
| 17:14 | sdegutis | Is 1.7 almost out? |
| 17:14 | sdegutis | We're still on 1.5.1 and I'm afraid to upgrade. |
| 17:14 | puredanger | sdegutis: getting there |
| 17:14 | sdegutis | But at least we upgraded from 1.3 successfully in early 2013. |
| 17:14 | justin_smith | sdegutis: amalloy: you guys are clearly unfamiliar with nostradamus' blog |
| 17:14 | Bronsa | arrdem: that's good enough for me |
| 17:14 | puredanger | sdegutis: http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&requestId=10519 is the list of remaining items |
| 17:14 | sdegutis | justin_smith: I don't know what you're talking about. |
| 17:15 | sdegutis | puredanger: are you Alex Miller? |
| 17:15 | puredanger | yes |
| 17:15 | sdegutis | Oh. Hi. |
| 17:15 | puredanger | Hi :) |
| 17:15 | sdegutis | I saw you on the Clojure mailing list. |
| 17:15 | sdegutis | You were saying stuff about Clojure 1.7. |
| 17:15 | justin_smith | sdegutis: he said that blogs are only true when they are written, nostradamus is famous for his "predictions" |
| 17:15 | arrdem | puredanger: ^:deprecated is a thing, right? |
| 17:15 | justin_smith | bad joke, sorry |
| 17:15 | puredanger | arrdem: sure? |
| 17:15 | sdegutis | justin_smith: Oh. I get the joke now. |
| 17:15 | sdegutis | justin_smith: It is funny. |
| 17:15 | amalloy | justin_smith: it's okay. it was a comprehensible joke |
| 17:16 | sdegutis | justin_smith: You did well. |
| 17:16 | Bronsa | puredanger: arrdem some functions in c.c have :deprecated metadata but there's no automatic warning for that |
| 17:16 | puredanger | sdegutis: we will cut a beta when we believe 1.7 is feature complete (I think feature expressions being the major question mark there) |
| 17:16 | sdegutis | I will go read about transducers again. Last time, I got halfway through the page and it looked incredibly un-huge. |
| 17:16 | arrdem | Bronsa: yeah was thinking about a eastwood ticket for reaching a ^:depricated var |
| 17:17 | sdegutis | Oh no! |
| 17:17 | arrdem | I'm pretty sure that core.async is using it as well in addition to warnings |
| 17:17 | sdegutis | puredanger: But I thought everyone hated that proposal from years ago? |
| 17:18 | arrdem | Yep. it's {:deprecated <DEPRECATED_VERSION} |
| 17:18 | sdegutis | It's just #ifdef ugh! |
| 17:18 | puredanger | sdegutis: most people I've talked to already doing effectively feature expressions but with the preprocessor from cljx |
| 17:18 | arrdem | core.async has no usages of deprecated metadata |
| 17:18 | sdegutis | Feature expressions should be #+js and #+jvm if anything. |
| 17:19 | sdegutis | Because, supposedly "it's all Clojure" anyway. |
| 17:19 | puredanger | sdegutis: the current proposal (and issues) are at http://dev.clojure.org/display/design/Feature+Expressions |
| 17:19 | puredanger | which use #+clj and #+cljs (same as cljx) |
| 17:19 | sdegutis | Right, and I'm suggesting it use #+js and #+jvm instead. |
| 17:20 | puredanger | sdegutis: well, it's going to be clj and cljs |
| 17:20 | puredanger | the biggest question remaining is about creating a new file extension for portable clojure files (.cljc) |
| 17:20 | sdegutis | Right, that's why I didn't waste my time suggesting that in any official way. |
| 17:20 | sdegutis | Because "NOPE" is always the answer to my suggestions. |
| 17:21 | puredanger | well, I know the feeling |
| 17:21 | noonian | seems like at this point clj and cljs make sense since there is a lot of code out there that uses cljx already |
| 17:22 | puredanger | yes, that certainly is a factor |
| 17:24 | arrdem | "common Clojure" |
| 17:25 | joshhead | If there is no cljc extension, what would we use? just .clj? |
| 17:25 | technomancy | arrdem: but then what will we call clojure-on-CL-runtime? |
| 17:26 | arrdem | technomancy: no that's still "common Clojure" because cljs is "Clojure on JS" and "Clojure" is "Common Clojure on the JVM" |
| 17:26 | technomancy | venn diagram pl |
| 17:26 | technomancy | plz |
| 17:26 | arrdem | which means that Oxlang can die and just be Common Clojure in Common Clojure :P |
| 17:27 | Bronsa | arrdem: are you still working on oxlang/oxcart? |
| 17:27 | arrdem | technomancy: if "Common Clojure" (.cljc) is the subset of Clojure common to .cljs and .clj, that means it's a *jure without host interop |
| 17:27 | joshhead | "ClojureCL, not to be confused with ClojureCLR" |
| 17:27 | puredanger | joshhead: yes, that was the path we were going down |
| 17:28 | arrdem | technomancy: thus if you port *jure/Common Clojure thing to another platform, you still have Common Clojure (.cljc) |
| 17:28 | puredanger | joshhead: getting CLJS to do the right thing with .clj source in the presence of .clj macro files is an issue |
| 17:28 | arrdem | Bronsa: oxcart is pretty much dead, I'm still fooling with Oxlang which may or may not die itself |
| 17:29 | joshhead | puredanger: would this mean .cljs file extension could go away eventually too? |
| 17:29 | puredanger | no |
| 17:29 | arrdem | Bronsa: depending on whether or not I decide I've really just reinvented Haskell or Ocaml worse |
| 17:29 | Bronsa | arrdem: gotcha |
| 17:30 | arrdem | Bronsa: I think that a "platform abstract static *jure" is an interesting value proposition, but Clojure itself isn't a sufficiently static lang so I'm not convinced that working on Oxcart is useful at least until lib-clojure clearly makes it or breaks it. |
| 17:30 | joshhead | handling macro files does sound tricky |
| 17:31 | TEttinger | arrdem: was oxcart the "massive speedup for clojure" thing? |
| 17:31 | arrdem | TEttinger: yeah it was/is my GSoC static Clojure compiler |
| 17:32 | arrdem | "ClojureScript on the JVM" I think is what tbaldridge was calling it.. |
| 17:32 | arrdem | and that's pretty apt. |
| 17:32 | joshhead | arrdem: is there another static clojure compilation gsoc project? |
| 17:33 | arrdem | joshhead: there is skummet (I may have gotten the spelling wrong) |
| 17:34 | arrdem | can't actually find it googling wtf |
| 17:34 | joshhead | arrdem: just came up for me, you spelled it right |
| 17:35 | Bronsa | joshhead: I don't think the dev is working on skummet anymore btw |
| 17:35 | arrdem | joshhead: so my ultimate issue with both skummet and oxcart is that they require a fork of Clojure, or changes which I project Core will not take thus making them both relatively expensive to maintain. |
| 17:36 | joshhead | bummer, they claimed a 40% reduction in startup time on android, sounded promising |
| 17:38 | joshhead | ah yeah that does sound expensive to maintain |
| 17:38 | arrdem | joshhead: https://groups.google.com/forum/#!topic/clojure-dev/dSPUNKSaV94 |
| 17:39 | arrdem | I should fix my Clojure forks to actually work... maybe after 1.7 :P |
| 18:15 | gazarsgo | stupid noob question, i have a project.clj and a file core.clj, do they need to be in a particular folder structure for 'lein run' to work ? |
| 18:16 | gazarsgo | guess i should use `lein new` huh |
| 18:16 | gfredericks | yeah that's easiest |
| 18:17 | gazarsgo | trying to pick up some clojure code from a gist someone pasted |
| 18:17 | dbasch | gazarsgo: what error do you get? |
| 18:17 | gazarsgo | i have a new error now that i used lein new :D |
| 18:17 | dbasch | you need at least a :main namespace and a -main [& args] function in that namespace |
| 18:18 | gazarsgo | well, i am pretty sure their code works... i had to put core.clj in the right spot for their namespace, i think it is working now |
| 18:21 | gazarsgo | ok, that worked, sorry for rubber ducking |
| 19:00 | nextstep | new to clojure, starting a new project with some documentation where i'm expected to cite a few papers |
| 19:01 | nextstep | does marginalia have facilities for this? |
| 19:02 | wei | I’m looking for a function that I can use with merge-with to combine all the values in a given key into a vector |
| 19:03 | wei | e.g. (_ 1 2) => [1 2], (_ [1 2] 3) [1 2 3] |
| 19:05 | wei | (merge-with f {:a 1} {:a 2}) => {:a [1 2]} |
| 19:05 | justin_smith | nextstep: margenalia is nice for formatting where comments go in one column and the code goes in another, I don't know if it has any facilities for footnotes though |
| 19:06 | metellus | ,(merge-with vector {:a 1 :b 2 :d 6} {:a 2 :c 4 :d 5}) ;; wei |
| 19:06 | clojurebot | {:c 4, :b 2, :d [6 5], :a [1 2]} |
| 19:07 | amalloy_ | metellus: disastrous! |
| 19:07 | metellus | oh? |
| 19:07 | wei | what about (comp flatten vector) |
| 19:07 | amalloy_ | ,(merge-with vector {:a 1} {:a 2} {:a 3}) |
| 19:07 | clojurebot | {:a [[1 2] 3]} |
| 19:07 | metellus | ~flatten |
| 19:07 | clojurebot | flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with. |
| 19:07 | amalloy | wei: the whole thing is a lot easier if you start off with {:a [1]} instead of {:a 1}, because then you're clear about whether things are going to be collections or ints or what |
| 19:07 | wei | that’s why I’m asking here :) |
| 19:08 | wei | ah, then I can use concat |
| 19:08 | amalloy | wei: s/concat/into |
| 19:09 | nextstep | justin_smith: well, i was just wandering about any facility to cite papers |
| 19:09 | nextstep | not necessarily as footnotes |
| 19:10 | nextstep | in javadoc you can find many citations too |
| 19:10 | justin_smith | nextstep: what margenalia does is make a nice readable html page out of your code, I don't know that it has any facility to treat anything as a footnote |
| 19:10 | nextstep | i think they format them by hand, which is quit tedious |
| 19:10 | justin_smith | nextstep: wait, what do you mean by citations? |
| 19:11 | justin_smith | also, s/footnote/citation above, sorry |
| 19:11 | nextstep | justin_smith: i mean fancy references to papers, like what bibtex does |
| 19:11 | nextstep | no worries |
| 19:11 | danneu | Is there a way to set *out* for all printlns? |
| 19:13 | dbasch | danneu: with-out-str, for example |
| 19:14 | dbasch | or bind *out* to whatever |
| 19:16 | jfojtl | hi, what do you use for generating load? |
| 19:16 | danneu | dbasch: guess i can just define println so that, in development, it wraps println with a with-open and a (binding [*out* file-writer] ...) |
| 19:16 | dbasch | danneu: ugh |
| 19:16 | danneu | it's a pretty advanced logging system |
| 19:17 | danneu | feel free to steal some pages from my book guys |
| 19:17 | Bronsa | danneu: I mean, you can alter-var-root *out* but that's probably a bad idea. |
| 19:17 | dbasch | don’t reinvent logging |
| 19:18 | danneu | yeah, i was just hoping for a one-liner that would let me procrastinate replacing my printlns with a logging system for just 1 more week |
| 19:19 | justin_smith | nextstep: I was curious, so I did a quick scan of the margenalia sources, found nothing that looked like code for citations |
| 19:19 | justin_smith | nextstep: but it does have support for directives, seems like that could be extended to make a "citation" directive |
| 19:24 | justin_smith | nextstep: it would be nice to extend margenalia so that you could provide something similar to data_readers.clj with annotations to look for in comments matched up with formatters that render their output |
| 19:25 | danneu | Bronsa: (alter-var-root (var *out*) (fn [_] (io/writer "dev.log"))) doesn't seem to change *out* |
| 19:26 | justin_smith | danneu: (binding [*out* (io/writer "dev.log")] ...) |
| 19:26 | justin_smith | it's a dynamic var |
| 19:27 | danneu | justin_smith: yeah, was looking for a way to just bind it once for all my printlns |
| 19:27 | justin_smith | danneu: dynamic vars don't work that way |
| 19:27 | danneu | guess i will have to use a logging system like an adult |
| 19:27 | justin_smith | danneu: see also the persistent problem of cider output going to the wrong place |
| 19:28 | justin_smith | danneu: it's really not hard, some of them don't even involve making xml or properties files |
| 19:30 | danneu | *drags feet* |
| 19:31 | amalloy | justin_smith: well, dynamic vars do work that way, except when they're overridden by a binding |
| 19:31 | amalloy | *out* is bound all the time in development, because the repl sets it, so alter-var-root doesn't do anything useful |
| 19:31 | justin_smith | amalloy: thanks for the precision, that's what I meant |
| 19:31 | justin_smith | (inc amalloy) |
| 19:31 | lazybot | ⇒ 178 |
| 19:32 | justin_smith | that was a friendly "that's what I meant", not a surly one |
| 19:33 | nextstep | justin_smith: thanks, directives seem interesting |
| 19:35 | danneu | amalloy: ah right thanks |
| 19:36 | wei | amalloy: kind of bringing back an old topic, but why would you prefer (into [1 2] [1]) to (concat [1 2] [1])? they both produce collections and I don’t care that the end result isn’t also a vector |
| 19:36 | amalloy | wei: because (concat (concat (concat ...))) is really bad if you have a lot of things to concat |
| 19:36 | wei | performance? |
| 19:36 | clojurebot | performance is http://meshy.org/2009/12/13/widefinder-2-with-clojure.html |
| 19:37 | amalloy | wei: try: (first (reduce concat (repeat 2000 [1]))) |
| 19:37 | amalloy | and then do the same thing with into |
| 19:37 | danneu | also into uses transients |
| 19:38 | wei | amalloy: surprisingly, concat is faster on my machine for your example. but for 20000, i get a stack overflow :) |
| 19:39 | justin_smith | wei: but do you get the stack overflow faster? that's what's important right? :) |
| 19:40 | amalloy | wei: really? when i pick a value small enough to avoid the stackoverflow, into is like three times faster |
| 19:41 | technomancy | shouldn't the lazy one be faster till it's forced? |
| 19:42 | justin_smith | yeah, if you did a quick benchmark with time / dotimes that would be a pitfall for sure |
| 19:42 | amalloy | technomancy: the lazy one still builds a linked list of thunks |
| 19:43 | amalloy | and you have to traverse them all to get to the first value (which is the same thing that causes the stack overflow, of course) |
| 19:43 | wei | ah, I am using time. |
| 19:44 | amalloy | wei: you remembered to call (first), right? of course concat is absurdly fast if you don't ever ask for any items |
| 19:44 | wei | reduce should force evaluation, right? |
| 19:44 | dbasch | benchmarking with time is usually a waste of time |
| 19:44 | wei | https://gist.github.com/yayitswei/db118466ff8ecb813653 |
| 19:45 | justin_smith | wei: it's not going to force anything if the reducing function is lazy |
| 19:45 | amalloy | yeah, it was just my lazy benchmarking. the into version is slower if i try harder |
| 19:47 | dbasch | hammockmarking |
| 19:48 | amalloy | but anyway, the important point is that layering concats will cause a stack overflow for no reason |
| 19:49 | {blake} | I find myself doing the following in Clojure: Write some code to do something; discover there's a nil/blank condition; wrap the already written code in a "let" var;make the "body" of the function be an if on said var. |
| 19:50 | {blake} | So, "(do-this (do-that (do-the-other (parm)))" becomes ([let x (do-this...)] (if x x "")). |
| 19:51 | {blake} | Just trying to decide if this is "good" or I like it, or it maybe reflects a weakness. |
| 19:51 | wei | amalloy: got it, thanks |
| 19:51 | amalloy | {blake}: (if x x y) => (or x y) |
| 19:52 | danneu | aside the fact that you can use when-let, consider the possibility of guarding against nils at the edges of your code so that your inner code doesnt need to do nil checks |
| 19:52 | amalloy | thus, just (or (do-this ...) "") |
| 19:53 | {blake} | amalloy, danneu Thanks. |
| 19:53 | {blake} | In some cases, it's...well, I guess it's not surprising, it's kind of shaking out how data is going to be passed around. |
| 19:53 | {blake} | Sometimes it's nils, but sometimes it's a map-entry {:key nil}. |
| 19:54 | {blake} | Anyway, "or" and "when-let" will take care of some of the simpler cases. I probably should go through the Clojure cheatsheet again. |
| 19:57 | danneu | {blake}: yeah, it's nice that clojure is lenient with nils. like how (:foo nil) -> nil. but it also makes it easy to remain indecisive about just how far down the chain your program is gonna pass a nil |
| 19:58 | technomancy | ... |
| 19:58 | technomancy | nice isn't the word I would use |
| 19:58 | danneu | technomancy: nice in that my yolo cowboy-code live-deploy hotfix doesn't break because i didn't have to answer the question "what if it's nil?" today |
| 19:59 | danneu | i can let my future self disarm that bomb |
| 20:00 | dbasch | someone set us up the npe |
| 20:00 | technomancy | given the tragic fact that nil exists on the JVM, clojure offers some help for coding around that flaw. |
| 20:00 | danneu | and by disarm i mean fully rwerite my code from scratch |
| 20:00 | dysfun | actually, the dealing with nil seems very DWIM to me |
| 20:00 | talios | MONADS! |
| 20:01 | technomancy | it's pretty good at dealing with nils in place of collections |
| 20:01 | technomancy | pretty rubbish everywhere else |
| 20:01 | dysfun | that i'll agree with |
| 20:01 | amalloy | $timer 24 0 0 why not try using MONADS!? |
| 20:01 | lazybot | Timer added. |
| 20:01 | dysfun | but i'm still not entirely sold that lists not ending in nil is a good thing |
| 20:01 | technomancy | hehe |
| 20:02 | technomancy | eh; it just depends on how you traverse it |
| 20:02 | technomancy | ,(next ()) |
| 20:02 | clojurebot | nil |
| 20:02 | talios | Cons | Nil |
| 20:02 | talios | Cons | EmptyList |
| 20:03 | dysfun | i can't say it keeps me awake at night |
| 20:03 | technomancy | you'll get there some day |
| 20:18 | technomancy | why do people mention monads when talking about options but not when talking about lists? |
| 20:18 | technomancy | I mean, obviously it was a joke, but options are super useful even when you're not working with them monadically. |
| 20:18 | Travisty | what are options? |
| 20:19 | technomancy | Travisty: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/ |
| 20:19 | Travisty | Ah, maybe :) |
| 20:20 | Travisty | thanks technomancy |
| 20:20 | bbloom | technomancy: in the absence of continuations, the list monad + reduce is all you really need anyway :-) |
| 20:27 | technomancy | clojurebot: the option type is a better way of representing nothing: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/ |
| 20:27 | clojurebot | A nod, you know, is as good as a wink to a blind horse. |
| 20:34 | zwer | technomancy what is the advantage of a maybe/option type in a dynamically typed language, where any variable can refer to an object of any type? |
| 20:35 | bbloom | zwer: often, none. however, you may want to explicitly distinguish between None and Some(None) |
| 20:38 | technomancy | zwer: returning an option indicates to the caller every place they should also consider a None |
| 20:38 | amalloy | zwer: a concrete example of bbloom's point: suppose you're writing memoize, and you want a map from function-args to function-result. (get m args) returns nil if the function was uncached or if it was cached and the result was nil |
| 20:39 | amalloy | so you have something like (if-let [[k v] (find m k)] v (f k)), which is an okay workaround but not as easy as just (get m k) |
| 20:39 | technomancy | zwer: in languages with pattern matching, this leads to a style that is far more likely to deal with missing things at the correct point, because you have to match against a call to get the actual value out of the option, which leads you to also handle the None case |
| 20:39 | technomancy | of course the compiler doesn't help you, but a missing clause stands out a lot more |
| 20:40 | technomancy | without pattern matching there's not much benefit though |
| 20:40 | amalloy | technomancy: the compiler doesn't help you with what? |
| 20:40 | technomancy | amalloy: it won't tell you when you're missing the None clause |
| 20:40 | technomancy | because it can't perform exhaustiveness checks |
| 20:41 | amalloy | we're assuming a dynamically-typed language with option, here? i guess that's true then |
| 20:41 | technomancy | yeah |
| 20:41 | technomancy | like Erlang |
| 20:42 | bbloom | when i need something option-like, i usually use find or just nil vs [nil] |
| 20:42 | bbloom | so easy to wrap some extra [] around something |
| 20:44 | technomancy | it's a lot like immutability--nice when you can bring it in on your own terms, but far more useful when it's a convention you can assume everyone is on board with. |
| 20:44 | nathan7 | technomancy: Rust's matching actually does perform exhaustiveness checks |
| 20:44 | nathan7 | technomancy: match some_option { Some(x) => … } won't compile |
| 20:44 | technomancy | nathan7: sure; their type system allows for it |
| 20:44 | nathan7 | technomancy: yep |
| 20:45 | nathan7 | I've kind of lost my appetite for dynamic languages |
| 20:45 | technomancy | meanwhile google go actually implemented nulls. on purpose. M-x tableflip |
| 20:45 | justin_smith | technomancy: I am sure you have seen the articles comparing go to algol |
| 20:45 | nathan7 | I've written some Go, because it's convenient for small programs |
| 20:45 | technomancy | "Actually, not all dynamic languages have nulls." |
| 20:45 | technomancy | #notalldynamic |
| 20:46 | nathan7 | lol |
| 20:46 | technomancy | justin_smith: yeap =) |
| 20:46 | nathan7 | but Go is best described as "unfortunate" |
| 20:46 | seancorfield | I went to an unsession on Go at The Strange Loop and learned it can do a lot of stuff that is best described as bizarre... |
| 20:46 | bbloom | *shrug* i think null pointers are a very natural idea in languages with mutability |
| 20:46 | justin_smith | technomancy: "actually, it's about ethics in generating runtime errors" |
| 20:47 | technomancy | justin_smith: =D |
| 20:47 | amalloy | bbloom: how does mutability make that more or less natural? the two seem unrelated to me |
| 20:47 | bbloom | amalloy: zero-initialized memory on allocation |
| 20:47 | bbloom | vs atomic initialization |
| 20:48 | bbloom | alloc and new are two distinct operations when you have raw memory access |
| 20:48 | bbloom | new encapsulates alloc on the JVM, but constructors are not atomic. the GC can run during initialization, even for types w/ all final fields |
| 20:49 | bbloom | unlike, say ML or Haskell, where all data constructors are atomic for immutable values |
| 20:49 | amalloy | okay, i think i see what you mean. thanks |
| 20:49 | nathan7 | Box<T> in Rust is guaranteed not to be a null pointer, the box type is never constructed until after allocation |
| 20:49 | bbloom | having a pointer to nowhere is perfectly reasonable when you have a pointer datatype |
| 20:50 | nathan7 | there is an unsafe pointer type which may be null, however |
| 20:50 | bbloom | nathan7: yet Rust has raw pointers and null values in unsafe code |
| 20:50 | nathan7 | bbloom: yep |
| 20:50 | nathan7 | bbloom: it's fairly well-contained, in my opinion |
| 20:50 | bbloom | you don't need it often in normal code, but that doesn't mean it isn't useful sometimes |
| 20:50 | nathan7 | bbloom: and I write a lot of unsafe code |
| 20:50 | bbloom | yeah, i've been a big proponent of unsafe code blocks since experiencing it in C# |
| 20:50 | bbloom | very nice design |
| 20:50 | bbloom | and i've written Managed C++ as well :-P |
| 20:50 | bbloom | so i've written LOTS of unsafe CLR code |
| 20:51 | nathan7 | half of my code is FFI, the other half is an experimental kernel I'm working on |
| 20:51 | nathan7 | and especially in the latter, building safe, zero-cost abstractions around stuff before getting to the meat of it is *amazing* |
| 20:51 | bbloom | my biggest complaint with null in java is that java doesn't have raw pointers |
| 20:51 | bbloom | so there's no good fucking reason why null can't be an object |
| 20:51 | bbloom | as in smalltalk or ruby |
| 20:51 | bbloom | luckily, protocols in clojure can be extended to nil |
| 20:52 | bbloom | null in java (and C#) is the worst of both worls |
| 20:52 | bbloom | worlds* |
| 20:52 | bbloom | it's not a useful data type (raw pointer) and it's not a valid object |
| 20:52 | bbloom | i guess zero-initialized memory is still a think on the JVM, but that was a design mistake in my opinion too |
| 20:52 | bbloom | C# is adding scala-style "primary constructors" |
| 20:53 | bbloom | http://odetocode.com/blogs/scott/archive/2014/08/14/c-6-0-features-part-ii-primary-constructors.aspx |
| 21:15 | justin_smith | bbloom: that seems like a natural way to do immutible datatype initialization |
| 21:23 | cfleming | Ugh, sometimes type hinting in Clojure is a total mystery. |
| 21:24 | cfleming | I'm calling a method accepting a CharSequence, Clojure finds it fine if I call it with "", but not if I call it with ^CharSequence (or (:text params) "") |
| 21:25 | amalloy | cfleming: http://dev.clojure.org/jira/browse/CLJ-865 |
| 21:25 | amalloy | (let [^CharSequence chars (or ...)] (.whatever chars)) would work |
| 21:27 | cfleming | Well that sucks - at least there's a good workaround, thanks. |
| 21:27 | cfleming | 15 votes and a patch and it's not moving anywhere? |
| 21:28 | amalloy | cfleming: a three-year-old patch, even |
| 21:28 | cfleming | Correction, 16 votes |
| 21:28 | amalloy | IMO it got bogged down in bikeshedding: the current behavior is terrible, but nobody wants to take an improved behavior because it's not clear what optimal behavior would be |
| 21:29 | cfleming | So if I understand this correctly, you can never type hint the results of a macro call? |
| 21:29 | amalloy | cfleming: you should not rely on the ability to do so. it might, for some macros, turn out to work okay |
| 21:30 | amalloy | additionally, you can write your own macros to carefully preserve the metadata, if you want |
| 21:30 | cfleming | amalloy: Hoo boy. I'll add an inspection to Cursive for that, just for my own sanity. |
| 21:30 | cfleming | amalloy: That going to hurt when I try to emulate Clojure's type inference though. |
| 21:31 | amalloy | cfleming: for example, it looks like -> does carry the metadata for you |
| 21:32 | amalloy | ,(meta (macroexpand ' ^String (-> x (identity)))) |
| 21:32 | clojurebot | nil |
| 21:32 | cfleming | Or not |
| 21:32 | amalloy | well, i didn't write it very well |
| 21:33 | amalloy | hm, i guess it doesn't. interesting. it saves the metadata on x, but not on the form |
| 21:33 | amalloy | (binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity))))) |
| 21:33 | amalloy | ,(binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity))))) |
| 21:33 | clojurebot | (identity ^Foo x)\n |
| 21:33 | cfleming | ,(meta (macroexpand ^String '(-> x (identity)))) |
| 21:33 | clojurebot | nil |
| 21:34 | cfleming | Interestingly, that does something different in my REPL here: I get {:line 1, :column 35} |
| 21:34 | amalloy | sure sure, because you've got a different reader. but that's immaterial |
| 21:35 | cfleming | Which reader is clojurebot using? |
| 21:36 | amalloy | who knows. some stringreader probably |
| 21:36 | amalloy | that is, it's using the clojure reader, but a different java.io.Reader |
| 21:36 | justin_smith | ,(class *in*) |
| 21:36 | clojurebot | clojure.lang.LineNumberingPushbackReader |
| 21:36 | cfleming | Got it |
| 21:37 | cfleming | Interesting, I get the same here |
| 21:37 | amalloy | justin_smith: that doesn't tell you what it's using for its own input |
| 21:37 | justin_smith | ahh, yeah |
| 21:37 | amalloy | only what *in* is bound to once you start running code |
| 21:37 | cfleming | Devious indeed |
| 21:39 | cfleming | Anyway, thanks amalloy, that saved my sanity |
| 21:39 | cfleming | (inc amalloy) |
| 21:39 | lazybot | ⇒ 179 |
| 21:39 | justin_smith | OK, I hate multimethods so much right now |
| 21:40 | amalloy | justin_smith: def it to nil, and then call it out of spite |
| 21:40 | justin_smith | I replaced a big case statement with multimethods, in code that gets run multiple times in every page load... and they are so fucking slow |
| 21:40 | justin_smith | so now I have to make a protocol, or put it all back into a case statement again |
| 21:40 | justin_smith | which sucks |
| 21:40 | amalloy | did hiredman's patch to reduce locking in multimethods ever get applied? |
| 21:41 | amalloy | it looks like something like it did; they use rwlocks as of 2012. so take heart: it could be much slower |
| 21:42 | justin_smith | still not fast enough :( |
| 21:42 | the_danko | evening fellows |
| 21:42 | the_danko | and ladies |
| 21:43 | justin_smith | hello |
| 21:48 | the_danko | doing some 4clojure |
| 22:14 | justin_smith | cool, it's a great way to level up your clojure fluency |
| 22:14 | justin_smith | (inc amalloy) ; for 4clojure |
| 22:14 | lazybot | ⇒ 180 |
| 22:29 | fairuz | hey guys |
| 22:30 | havenwood | fairuz: hi |
| 22:31 | fairuz | I don't know if I can post Titanium (titandb client) related question here. Their channel seems dead |
| 22:31 | justin_smith | you can go ahead, no guarantees you'll find an expert |
| 22:40 | fairuz | Ok cool. Let me play with it a bit first before asking stupid question :) |
| 22:40 | fairuz | It's nice to know it's alive in here |
| 22:40 | Blizzy | lol. |
| 22:40 | bbloom | fairuz: i don't think he was confirming it was alive. i think he was confirming that we're nice people who may or may answer a question if we're capable of doing so |
| 22:40 | bbloom | may or may not* |
| 22:40 | fairuz | bbloom: True |
| 22:41 | fairuz | I'm referring to at least some people did reply in here :) |
| 22:41 | havenwood | fairuz: we're all bots written in Clojure |
| 22:42 | havenwood | but agreed we're pleasant! |
| 22:45 | wei | what’s the best way to handle exceptions in a go block so that an exception doesn’t close the channel? https://gist.github.com/yayitswei/d80d51ee29dc5e2c1117 |
| 22:46 | bbloom | wei: if some unfortunate API forces exceptions on you for error handling, catch them immediately and return sensible error codes |
| 22:46 | bbloom | wei: in that particular example, you can move the try down inside the let |
| 22:47 | bbloom | wei: <! won't throw, so there's no need for it to be part of the try block. that should work correctly, but better still would be to take the exception handling out of the go all together and push it in to the process! method |
| 22:47 | bbloom | or some helper that calls process! |
| 22:47 | bbloom | make sense? |
| 22:51 | wei | bbloom: the channel seems to still get closed when I move the try block inside the let |
| 22:51 | wei | i expect the second >! to trigger a “processing: true”, but that doesn’t happen |
| 22:52 | bbloom | wei: take a closer look at your compiler warnings |
| 22:52 | bbloom | queue is undefined |
| 22:53 | bbloom | wei: the code that you have should work as is with the correct variable name, but still: 1) move the try inside the let or 2) further move the try inside another call |
| 22:54 | wei | oops, i’ve updated the gist. still not working for me in its current form |
| 22:56 | wei | if you comment out the (>! q false), it works as expected |
| 22:58 | bbloom | wei: so (go (>! ... is the same as (put! ... only the go/>! pair is slower |
| 22:58 | bbloom | those are async sends |
| 22:58 | wei | aha, i was wondering what put! was for |
| 22:58 | bbloom | so there's actually no promise that the false send will occur before teh true send |
| 22:59 | wei | i’m not too particular, but i do want the true to process correctly |
| 23:02 | bbloom | i'm experimenting with it locally b/c i've never actually used a try catch in a core.async go block (and i've written quite a bit of core async) |
| 23:03 | wei | thanks for taking a look |
| 23:06 | bbloom | wei: this is certainly strange |
| 23:08 | wei | yeah, it’s the first time channels haven’t worked like i’ve expected them to in almost a year that i’ve been using them |
| 23:08 | wei | updated the gist to explain the issue: https://gist.github.com/yayitswei/d80d51ee29dc5e2c1117 |
| 23:10 | wei | bbloom: unfortunately I have to take off for a bit. if you discover anything would you mind commenting on the gist? |
| 23:11 | bbloom | wei: *shrug* i've explored it |
| 23:11 | bbloom | not gonna dig any deeper, sorry |
| 23:11 | bbloom | just don't put a try/catch in a go |
| 23:11 | bbloom | it's probably broken |
| 23:11 | bbloom | there's lots of threats around about it being broken elsewhere |
| 23:11 | bbloom | it's also just a questionable idea in the first place |
| 23:12 | bbloom | i'll @ mention tim |
| 23:12 | bbloom | good luck |
| 23:12 | wei | thanks anyways! sounds good |
| 23:54 | fairuz | Hi guys. Using LightTable, in the live mode, if I add something to the DB, it will be really be added to teh DB as I type it? |
| 23:54 | fairuz | *the |