2014-06-26
| 02:30 | visof | hi |
| 02:31 | visof | i tried to require (require 'clj-wordnet.similarity.algo.hso :reload) , but i got errors FileNotFoundException Could not locate clj_wordnet/similarity/algo/hso__init.class why it try to loat clj_wordnet not clj-wordnet |
| 02:31 | visof | ? |
| 02:32 | visof | i'm using tutorial here https://github.com/delver/clj-wordnet |
| 02:40 | vpm | willgorman: 25 |
| 02:41 | vpm | oh fracking irssi, sorry :-/ |
| 03:06 | cespare | technomancy: is there a way to change the column width slamhound uses? |
| 03:11 | latk | What does the hash symbol signify in this code: #(= contact %) ? |
| 03:25 | justin_smith | latk: # introduces a reader macro |
| 03:25 | justin_smith | here's a neat trick: |
| 03:26 | justin_smith | ,'#(= contact %) |
| 03:26 | clojurebot | (fn* [p1__25#] (= contact p1__25#)) |
| 03:26 | justin_smith | we can see from the quoted form's expansion that it creates an anonymous function |
| 03:26 | justin_smith | the var name is a bit weird, but it should be clear what it did |
| 03:27 | justin_smith | sometimes you get the # back in the read form |
| 03:27 | justin_smith | ,#{1 2 3} |
| 03:27 | clojurebot | #{1 3 2} |
| 03:27 | justin_smith | ,(class #{1 2 3}) |
| 03:27 | clojurebot | clojure.lang.PersistentHashSet |
| 03:29 | clodeindustrie | hi there, newbie here, can someone explain to me why I can do (= '(1) '(2)) and not (= (1) (2)) |
| 03:31 | cmdrdats | clodeindustrie: '(1) is a list with 1 element, (1) is trying to call 1 as a function |
| 03:35 | clodeindustrie | The problem I was working on had ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5) returning (5 4 3 2 1) |
| 03:36 | clodeindustrie | I guess I can't consider a list ? |
| 03:52 | latk | Is destructuring just the same as tuple unpacking in python ? |
| 04:01 | ddellacosta | latk: seems similar in the case of vectors, although I'm not sure what would be analogous for how hash-map destructuring works in Clojure--is there a way to do destructuring assignment with dictionaries in python? |
| 04:02 | latk | ddellacosta: There wasn't the last time I used Python :p |
| 04:02 | latk | But yes, I suppose I meant similar rather than the same |
| 04:03 | ddellacosta | &(let [[x y] [1 2 3]] (println "x: " x ", y: " y)) |
| 04:03 | lazybot | ⇒ x: 1 , y: 2 nil |
| 04:03 | ddellacosta | latk: & I guess that example is pretty similar to how Python does it, right? |
| 04:03 | ddellacosta | er, ^ |
| 04:03 | ddellacosta | &(let [{:keys [x y]} {:x 1 :y 2}] (println "x: " x ", y: " y)) |
| 04:03 | lazybot | ⇒ x: 1 , y: 2 nil |
| 04:04 | ddellacosta | ,(println "still locked out of clojurebot?") |
| 04:04 | clojurebot | eval service is offline |
| 04:04 | latk | ddellacosta: Pretty similar, yeah |
| 04:21 | latk | I see the function keys returns the keys of a map. What does {:keys [delete]} mean? |
| 04:22 | latk | Is this still using the keys function, or something else ? |
| 04:24 | clgv | latk: that's associative destructuring of maps |
| 04:24 | clgv | latk: it extracts the value bound to keyword ":delete" and binds it to symbol "delete" |
| 04:25 | latk | clgv: Ah, okay. That value can be any other datastructure, presumably ? |
| 04:25 | latk | clgv: Also, why does it get the value bound to :delete? |
| 04:25 | clgv | latk: you mean the value that is finally bound to "delete"? |
| 04:26 | latk | clgv: Yes |
| 04:26 | clgv | yeah thats arbitrary |
| 04:26 | latk | Okay |
| 04:27 | clgv | ,(let [my-map {:a 42 :b (zipmap (range 5) (range 5)}, {:keys [a b]} my-map] (prn a b)) |
| 04:27 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: }> |
| 04:27 | clgv | ,(let [my-map {:a 42 :b (zipmap (range 5) (range 5))}, {:keys [a b]} my-map] (prn a b)) |
| 04:27 | clojurebot | 42 {4 4, 3 3, 2 2, 1 1, 0 0}\n |
| 04:27 | clgv | latk: ^^ |
| 04:27 | latk | clgv: Huh, okay. I would not have guessed that this is what :keys does :P |
| 04:28 | latk | clgv: Incidentally, where is the best place to search for this kind of thing? Is there a clojure-specific search that will understand :keys ? |
| 04:28 | clgv | latk: just search for "clojure destructuring" or "clojure map destructuring" |
| 04:29 | clgv | there are at least two blog post explaining the details |
| 04:29 | latk | clgv: No sure, I meant in general if I found something I didn't understand :p |
| 04:29 | clgv | latk: ask here how it's called so that you can search properly ;) |
| 04:29 | latk | hah, okay :) |
| 04:31 | clgv | latk: or if you are new get one of the recent books and work through it. in my experience thats the fastest way to learn clojure. depending on your speed you can be through a book in 3-5 days fulltime with trying examples |
| 04:33 | latk | clgv: I skimmed through a book, but found some tutorials online that seemed more interesting.. if I get stuck today, I will go back to it |
| 04:51 | clgv | latk: ok, maybe that's the academic in me that wants to read such a book completely to get a solid basic knowledge ;) |
| 04:52 | latk | clgv: I tend to learn best by doing :P |
| 04:58 | clgv | latk: that's tricky with clojure since you have to learn a lot of new concepts (depending on your background) and thus you simply can't do the thing you dont know the concepts of ;) |
| 04:59 | clgv | by working through the book I dont mean just reading but also experimenting with examples ;) |
| 05:22 | latk | clgv: I'm most comfortable programming in Haskell, so I'm relativley comfortable with functional stuff. Admittedly I have no experience with lisps.. |
| 05:27 | clgv | latk: yeah just wanted to share my thoughts ;) |
| 05:27 | latk | clgv: You may well be right - will have to see how it goes ! |
| 05:52 | latk | Could anyone explain the let binding in: http://bpaste.net/show/VeTUgekGw8tdmudTfIqX/ ? |
| 05:53 | latk | It is more complicated than the simple examples I have read, and I don't quite get it. |
| 06:06 | viperscape | latk: http://bpaste.net/show/hyGOYllsePNAKNus2gh3/ |
| 06:07 | viperscape | it's destructuring the string's parts into a vector, called parts |
| 06:09 | viperscape | you could just as well do (second parts) within the let bindings, or simply "last" since it's techinically bound to it through the destructuring |
| 06:11 | viperscape | also, I wouldn't suggest using key terms such as first and last |
| 06:11 | latk | viperscape: Isn't all of the stuff inside the first set of [] in the same let binding ? |
| 06:13 | viperscape | ,(let [[f m l :as parts] (clojure.string/split "first last" #"\s+")] (= m (second parts))) |
| 06:13 | clojurebot | true |
| 06:15 | viperscape | the second line is simply reordering the f m l parts, essentially dropping middle-name if needed |
| 06:15 | viperscape | or last, rather |
| 06:15 | latk | this is what I suspected |
| 06:16 | viperscape | http://blog.jayfields.com/2010/07/clojure-destructuring.html |
| 06:21 | clgv | be carefull with the combination of :or and :as ;) |
| 06:44 | hyPiRion | oh, that one's always "funny" |
| 06:44 | hyPiRion | Also the fact that either :or or :as does its argument in reverse |
| 07:06 | latk | ,(.. "string" (substring 2) (equals "ring")) |
| 07:06 | clojurebot | true |
| 07:07 | latk | ,(-> "string" (substring 2) (equals "ring")) |
| 07:07 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: equals in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 07:08 | ro_st | if i use key destructuring inside a when-let, does the when part look at each of the destructured locals? |
| 07:11 | luxbock | https://gist.github.com/luxbock/425ae5912656b9ff7803 |
| 07:11 | luxbock | what is the right way to translate the (new Date(d)) part to CLJS? |
| 07:13 | hyPiRion | ,(= (subs "string" 2) "ring") |
| 07:13 | clojurebot | true |
| 07:13 | latk | How can I find the documentation on .. and . in clojurescript ? |
| 07:18 | TimMc | latk: It's the same as in Clojure. (doc ..) |
| 07:19 | TimMc | latk: . is a special form, though, and probably doesn't have doc from the REPL. |
| 07:19 | TimMc | http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/. |
| 07:26 | clgv | (doc ..) |
| 07:26 | clojurebot | "([x form] [x form & more]); form => fieldName-symbol or (instanceMethodName-symbol args*) Expands into a member access (.) of the first member on the first argument, followed by the next member on the result, etc. For instance: (.. System (getProperties) (get \"os.name\")) expands to: (. (. System (getProperties)) (get \"os.name\")) but is easier to write, read, and understand." |
| 07:50 | jonathanj | i feel like i'm being silly here |
| 07:51 | jonathanj | i created a new project with lein and do lein repl but i can't access stuff defined in my code as i was expecting: |
| 07:51 | jonathanj | clj-neon.core=> -input-stream |
| 07:51 | jonathanj | CompilerException java.lang.RuntimeException: Unable to resolve symbol: -input-stream in this context, compiling:(/private/var/folders/qj/lb3tbsp97gg74jpcxtcw30zm0000gn/T/form-init698424686803171253.clj:1:941) |
| 07:51 | jonathanj | core.clj:6: (defn -input-stream |
| 08:27 | jcromartie | can any Enlive contributors comment on https://github.com/cgrand/enlive/pull/107 |
| 08:29 | jcromartie | 2 weeks and no comments or nuffin |
| 08:49 | latk | Where can I find the docs for om.dom ? |
| 09:07 | ollivera | how can I access locale value in the array? :pageid "1" :translation [{:locale "ja_JP"},{:locale "zh_CN"}] |
| 09:09 | bbloom | that's a "vector" not an array |
| 09:09 | bbloom | (doc get-in) |
| 09:09 | clojurebot | "([m ks] [m ks not-found]); Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil if the key is not present, or the not-found value if supplied." |
| 09:09 | ollivera | okay, thank you |
| 09:09 | bbloom | (get-in yourmap [:translation 0 :local]) |
| 09:46 | visof | ,(clojure.string/split "helloWorld" #"(?=[A-Z])") |
| 09:46 | clojurebot | ["hello" "World"] |
| 09:46 | visof | ,(clojure.string/split "helloWOrld" #"(?=[A-Z])") |
| 09:46 | clojurebot | ["hello" "W" "Orld"] |
| 09:46 | visof | that's problem for splitting |
| 09:47 | visof | how can i fix this ? |
| 09:50 | TimMc | visof: You haven't explained why you tthink that's wrong. :-) |
| 09:51 | visof | TimMc: i need to split in the first upper letter |
| 09:51 | visof | if i got two or n upper letter consecutive then split at first one |
| 09:52 | visof | ,(clojure.string/split "helloWOrld" #"(?=[A-Z][A-Z])") |
| 09:52 | clojurebot | ["hello" "WOrld"] |
| 09:52 | visof | ,(clojure.string/split "helloWORld" #"(?=[A-Z][A-Z][A-Z])") |
| 09:52 | clojurebot | ["hello" "WORld"] |
| 09:52 | TimMc | ,(clojure.string/split "helloWOrld" #"(?=[A-Z]+)") |
| 09:52 | clojurebot | ["hello" "W" "Orld"] |
| 09:52 | TimMc | Hmm, right. |
| 09:53 | visof | this techinque do what i need, so the solution maybe to check if there is [A-Z]+ pattern |
| 09:53 | visof | if i got [A-Z] pattern then split at [A-Z] |
| 09:53 | TimMc | You could include a negative lookbehind for uppercase. |
| 09:53 | visof | if there is two then split at [A-Z][A-Z] |
| 09:54 | visof | if there are n split at [A-Z]..n |
| 09:54 | visof | is there a good way to do this? |
| 09:55 | TimMc | ,(clojure.string/split "helloWOrld" #"(?<![A-Z])(?=[A-Z])") |
| 09:55 | clojurebot | ["hello" "WOrld"] |
| 09:56 | TimMc | visof: but maybe you actually want the camel-snake-kebab library? |
| 09:57 | Dutch|AFK | quit |
| 09:57 | visof | TimMc: can it handle myAPI ? |
| 09:57 | visof | have you checked it? |
| 09:58 | TimMc | visof: Haven't used it myself, but I think it handles this sort of thing. |
| 09:58 | visof | TimMc: i'm trying it |
| 10:18 | Shayanjm | Is there a way that I can completely replace the values in a ref with totally new values? |
| 10:18 | Shayanjm | update-in seems to modify state with some applied function |
| 10:18 | Shayanjm | but that seems a bit roundabout for what I'm trying to do |
| 10:20 | TimMc | Shayanjm: ref-set |
| 10:20 | Shayanjm | wow. |
| 10:20 | Shayanjm | thanks TimMc |
| 10:20 | Shayanjm | i should probably just generally read the API docs shouldn't I |
| 10:20 | TimMc | Shayanjm: I keep telling myself that one of these days I will skim through clojure.core. |
| 10:20 | Shayanjm | lol |
| 10:20 | TimMc | http://clojure.org/cheatsheet is good though |
| 10:21 | Shayanjm | ah |
| 10:22 | Shayanjm | so if I'm understanding correctly: refs have write guarantees when transacted upon? |
| 10:22 | Shayanjm | so I'm assuming to reap those benefits you would have to be transacting over multiple refs? |
| 10:23 | Shayanjm | (i.e: can't be a ref & an atom?) |
| 10:23 | TimMc | yeah |
| 10:23 | Shayanjm | k cool |
| 10:23 | TimMc | Only refs (and in a certain sense, agents) participate in txs, |
| 10:23 | TimMc | . |
| 10:24 | TimMc | (Txns delay agent sends until they complete.) |
| 10:26 | Shayanjm | gotcha |
| 10:27 | Shayanjm | Yeah basically I'm just getting a bunch of stuff from the NYT API, sticking it in (what used to be an atom) what is now a ref, performing SA on the URLS in the ref, and storing the results to a second ref so they can be 'gotten' easily |
| 10:29 | TimMc | Shayanjm: Make sure you understand what ensure does. |
| 10:31 | TimMc | (Watch out for write skew.) |
| 10:34 | Shayanjm | wait what DOES ensure do? |
| 10:34 | Shayanjm | it says it provides 'more concurrency than ref-set' |
| 10:34 | Shayanjm | looking online, the provided examples aren't really clear either... |
| 10:35 | Shayanjm | My best guess is: if I'm altering ref1 via ref-set or something, i'd need to throw ensure on ref2 to make sure it's not accidentally transacted on in the meanwhile? |
| 10:35 | Shayanjm | but if I'm ref-setting BOTH refs within a single dosync, would using ensure matter? |
| 10:37 | TimMc | You got it. (in *2) |
| 10:38 | TimMc | It prevents ref2 from being written to if you're only reading from it. |
| 10:38 | Shayanjm | I see |
| 10:38 | Shayanjm | but isn't the whole clojure mantra 'no side effects'? |
| 10:38 | Shayanjm | err, i guess lisp mantra? |
| 10:38 | TimMc | but multiple txns can call ensure on the same ref without interfering with each other (more concurrency) |
| 10:38 | Shayanjm | oic |
| 10:39 | Shayanjm | so i could have 3x ensure on a ref without issues? |
| 10:39 | Shayanjm | does ensure just last the lifetime of the txn? |
| 10:40 | TimMc | yeah |
| 10:40 | Shayanjm | cool |
| 10:40 | TimMc | (Theoretically, haven't tested or read the source.) |
| 10:40 | Shayanjm | kk |
| 10:41 | TimMc | Various Lisps use side-effects all over the place. |
| 10:41 | TimMc | (mutablle cons, etc) |
| 10:41 | TimMc | Clojure is focused on reducing *uncontrolled* mutation. |
| 10:42 | Shayanjm | gotcha |
| 10:43 | koreth__ | That's even true of something like Haskell, really -- they're not against side effects per se over in Haskell land, it's just about keeping them well-contained and nailing down the semantics. |
| 10:43 | Shayanjm | gotcha |
| 10:55 | benzap | when destructuring, is there a way to bind a key to a new key name? like (let [{:keys [x :as blah]}]... |
| 10:56 | cbp | (let [{a :c} {:c 1}] c) |
| 10:56 | cbp | er |
| 10:56 | cbp | ,(let [{a :c} {:c 1}] a) |
| 10:56 | clojurebot | 1 |
| 10:57 | benzap | ah ok |
| 11:21 | mocker | Is there a difference between these two things? |
| 11:21 | mocker | ,(merge {:a 1 :b 2} {:b 3 :c 4}) |
| 11:21 | clojurebot | {:c 4, :b 3, :a 1} |
| 11:21 | mocker | ,(conj {:a 1 :b 2} {:b 3 :c 4}) |
| 11:21 | clojurebot | {:c 4, :b 3, :a 1} |
| 11:22 | ndaly | I think merge can take an arbitrary number of arguments and conj only conjoins one |
| 11:22 | ndaly | but I'm a total newb, so I could be wrong |
| 11:22 | mocker | :) |
| 11:22 | mocker | newbs unite! |
| 11:24 | llasram | When everything is a map I believe they have the same result, but `merge` makes that intent more explicit and handles a `nil` initial argument differently |
| 11:24 | llasram | ,(conj {} {:a 1} {:b 1} {:c 1}) |
| 11:24 | clojurebot | {:c 1, :b 1, :a 1} |
| 11:25 | llasram | ,(conj nil {:a 1} {:b 1} {:c 1}) |
| 11:25 | clojurebot | ({:c 1} {:b 1} {:a 1}) |
| 11:25 | llasram | ,(merge nil {:a 1} {:b 1} {:c 1}) |
| 11:25 | clojurebot | {:c 1, :b 1, :a 1} |
| 11:25 | mocker | Nice, thanks. |
| 11:26 | llasram | Hmm, and `merge` can apparently take 0 arguments |
| 11:26 | llasram | ,(merge) |
| 11:26 | clojurebot | nil |
| 11:26 | llasram | ,(merge {}) |
| 11:26 | clojurebot | {} |
| 11:26 | llasram | Fun times |
| 12:04 | jjl` | llasram: quite a few functions 'do the right thing' with zero arguments |
| 12:08 | cbp | (merge) => nil is hardly the right thing |
| 12:08 | ddellacosta | cbp: what would the right thing be? |
| 12:08 | cbp | {} |
| 12:09 | ddellacosta | cbp: but merge doesn't work exclusively on hash-maps |
| 12:09 | ddellacosta | although the docs seem to suggest it does...weird |
| 12:10 | ddellacosta | huh, the implementation is pretty generic. Not sure why the docs say what they do. |
| 12:13 | ndaly | cbp: (seq {}) => nil |
| 12:13 | cbp | ndaly: ? |
| 12:14 | ndaly | cbp: not sure, just thought it might be relevant for the rationale behind (merge) => nil |
| 12:15 | ndaly | something that's merging in a loop will probably need to know when the merge results in an empty map |
| 12:15 | TimMc | jjl`: That's a low bar, though. I mean, base cases are *kind of a big thing* in functional programming. |
| 12:15 | ndaly | and nil let's them use a truth test for that |
| 12:15 | ndaly | anyway, I don't know enough to know what the right thing would be, but that may be part of the rationale |
| 12:15 | TimMc | Nil punning is the worst. |
| 12:16 | cbp | {} would be the identity value of merge |
| 12:16 | cbp | like how 0 is of + |
| 12:16 | ndaly | ,(merge {}) |
| 12:16 | clojurebot | {} |
| 12:16 | TimMc | (Worst reason for a design decision, at least.) |
| 12:16 | ndaly | ,(merge) |
| 12:16 | clojurebot | nil |
| 12:17 | jjl` | TimMc: and there are many ways to solve them. e.g. the little schemer provides simple rules of recursion to catch them |
| 12:18 | TimMc | jjl`: I'm just continually surprised at how many Clojure fns don't support nullary or unary forms. |
| 12:18 | jjl` | TimMc: and there's where it comes down to opinion about what 'the right thing' is |
| 12:20 | TimMc | &(assoc-in {:a :b} [] 5) |
| 12:20 | lazybot | ⇒ {nil 5, :a :b} |
| 12:20 | edw | Do we have a One True Matrix library? Or something resemblng one? I see clatrix… |
| 12:20 | TimMc | It's shit like that. |
| 12:21 | TimMc | Not only is the base case not supported, it clearly wasn't even considered. |
| 12:21 | seangrov` | &(get (assoc-in {:a :b} [] 5) nil) |
| 12:21 | lazybot | ⇒ 5 |
| 12:21 | seangrov` | uhg, wow |
| 12:21 | clgv | TimMc: there is a ticket for that or update-in ... |
| 12:21 | rplaca | thus foiling my PAAS platform arbitrage edw: core.matrix is headed that way - it can wrap Clatrix and others |
| 12:21 | TimMc | ,(assoc-in {:a :b} [] 5) |
| 12:21 | clojurebot | {nil 5, :a :b} |
| 12:21 | rplaca | edw: core.matrix is headed that way - it can wrap Clatrix and others |
| 12:21 | edw | rplaca: Ah, thanks. |
| 12:22 | edw | rplaca: I don't see a clojure/core.matrix repo on GitHub… Is it unofficial yet? |
| 12:24 | rplaca | edw: it's not officially part of Clojure yet, but I think it's on that road |
| 12:24 | edw | rplaca: Ah. I'll widen my search. |
| 12:24 | rplaca | the subject has been discussed and Rich, et al., are open to the idea of adding it when the time is right |
| 12:25 | rplaca | edw: https://github.com/mikera/core.matrix |
| 12:25 | edw | rplaca: Thanks. Addin' it to my project.clj |
| 12:25 | rplaca | edw: cool |
| 12:29 | amalloy | TimMc: for what it's worth, it's not clear what the behavior of (assoc-in {} [] 5) should be, or the equivalent with update-in |
| 12:30 | TimMc | amalloy: The result should be 5. |
| 12:30 | amalloy | that's a result that's reasonable in this peephole focus, but do you really want to be the guy who tells everyone that assoc-in doesn't always return a map? |
| 12:30 | amalloy | {nil 5} is stupid, but there's nothing that's great. {}, 5, throw-an-exception, are all sorta plausible |
| 12:32 | amalloy | useful has versions of assoc-in and update-in that do in fact return 5 in that case, but it's not really the kind of behavior i'd welcome in clojure.core - https://github.com/flatland/useful/blob/develop/src/flatland/useful/map.clj#L95-L118 |
| 12:32 | TimMc | I'm OK with it not always returning a map. |
| 12:32 | amalloy | i'd prefer it throwing an exception, personally |
| 12:32 | TimMc | I'd understand if people were upset, but... *shrug*. |
| 12:32 | amalloy | and if you want a version that returns 5 (which is a fine thing to want), that's easy to write |
| 12:33 | clgv | amalloy: for update-in there is a reasonable default, apply the function to the root map |
| 12:33 | amalloy | clgv: that's exactly the same as for assoc-in |
| 12:33 | amalloy | you want to make update-in not always return a map; that's going to create as many issues as the current behavior |
| 12:33 | TimMc | &(update-in {:a :b} [] (constantly 5)) |
| 12:33 | lazybot | ⇒ {nil 5, :a :b} |
| 12:34 | TimMc | &(assoc-in nil nil nil) |
| 12:34 | lazybot | ⇒ {nil nil} |
| 12:34 | TimMc | phweeee |
| 12:34 | ambroseb_ | clearly that should throw an exception, but clojure.core error handling .. |
| 12:35 | amalloy | ambroseb_: well, as a static-typing enthusiast, of course you want it to never return a non-map! but TimMc thinks it's just as clear that it should return 5 |
| 12:36 | clgv | amalloy: well for update functions that return maps that would be useful. if you use it with a function that does not return a map its your fault. at least the regular use case for empty path works... |
| 12:36 | amalloy | let's have it return a Maybe |
| 12:36 | amalloy | clgv: i find it useful also; that's why i put it in org.flatland/useful |
| 12:36 | jjl` | and how is that going to be any different from using a sentinel value (such as nil) in practice, in a language like clojure? |
| 12:36 | TimMc | ambroseb_: Does core.typed support the notion of "non-empty coll"? |
| 12:37 | amalloy | but it's hardly the only sensible behavior - i'd argue it's not much better as a default than the current nonsense |
| 12:37 | clgv | amalloy: ah ok^^ |
| 12:37 | ambroseb_ | TimMc: yes. |
| 12:37 | amalloy | jjl`: Maybe was not a real suggestion |
| 12:37 | TimMc | So assoc-in could be described as returning a map if given a non-empty keyseq. |
| 12:37 | jjl` | amalloy: you never know. i saw a 2014 java article about a maybe type. and of course they missed the point :) |
| 12:38 | ambroseb_ | assoc-in is special cased in core.typed, but it falls back on basically Any -> Any https://github.com/clojure/core.typed/blob/master/module-check/src/main/clojure/clojure/core/typed/base_env.clj#L1024 |
| 12:38 | amalloy | i'm a big fan of haskell and its types, but you can't just dump them into clojure |
| 12:40 | ambroseb_ | rich declined an enhancement for fixing assoc-in, but I think it's really a job for linters like Dynalint anyway. |
| 12:40 | ambroseb_ | same as the open ticket about `get` throwing on non-Associative |
| 12:40 | amalloy | for linters? how can a static linter fix assoc-in? |
| 12:41 | ndaly | it can't, but it can point out pathological uses |
| 12:42 | ambroseb_ | sorry, Dynalint isn't really a linter, it redefines core vars to include better errors and warnings on undefined behaviour. |
| 12:42 | ndaly | interesting |
| 12:42 | ambroseb_ | I consider assoc-in on empty path & get on non-Associative to be undefined behaviour, so Dynalint would complain if it gets evaluated. |
| 12:43 | amalloy | ambroseb_: couldn't the type be [(U nil (Associative Any Any)) (Seqable Any) Any -> (Associative Any Any)]? assoc-in always returns a map |
| 12:43 | ambroseb_ | amalloy: correct, it's a dumb type either way. |
| 12:43 | cbp | :-P https://github.com/clojure/core.typed/blob/master/module-check/src/main/clojure/clojure/core/typed/base_env.clj#L865 |
| 12:43 | cbp | Just in case comment doesn't work |
| 12:43 | ambroseb_ | amalloy: ideally there'd be fancy dotted types linking the paths to the output map |
| 12:44 | Bronsa | cbp: comment would insert a nil |
| 12:44 | ambroseb_ | grep for "insane" |
| 12:44 | amalloy | cbp: yeah, comment is no good there. the comment is in case #_ doesn't work; exactly the opposite of what you thought |
| 12:45 | cbp | :-( |
| 12:45 | ambroseb_ | cbp: as someone pointed out to me, core.typed uses every kind of comment, and then some |
| 12:46 | amalloy | well, actually comment wouldn't insert a nil after all, Bronsa |
| 12:46 | amalloy | because this is inside another macro |
| 12:46 | amalloy | so comment wouldn't even get macroexpanded, it would confuse the outer macro first |
| 12:47 | amalloy | just like you can't write (defn (comment lol) f [x] x) - not because (comment lol) expands to nil, but because defn is baffled |
| 12:47 | Bronsa | amalloy: oh, sure. I assumed the wrapping expression was a function call |
| 12:49 | ambroseb_ | I hear core.typed is in the new 7 languages book? |
| 12:49 | ambroseb_ | oh core.logic |
| 12:49 | ambroseb_ | haha, finger memory. |
| 12:50 | ambroseb_ | anyway, that's awesome. |
| 12:53 | ambroseb_ | on that note, I hope dnolen isn't still stuck in some airport :) |
| 12:53 | ambroseb_ | heard he had a nightmare travel to EuroClojure |
| 12:54 | TEttinger | I spent 24 hours in transit from australia to california once |
| 12:54 | ambroseb_ | ouch |
| 12:54 | TEttinger | and there were people on my flight who had further to go |
| 12:54 | TEttinger | (when the family got back, the car battery was dead too) |
| 12:55 | ambroseb_ | haha |
| 12:55 | TEttinger | there was everything, mechanical failure on a plane, while waiting for replacement there's a bomb threat.. |
| 12:56 | TEttinger | so I hope dnolen doesn't have to deal with that |
| 12:56 | ambroseb_ | my travel time to the US when everything goes *smoothly* is usually 30 hours. |
| 12:56 | TEttinger | ouch |
| 12:56 | TEttinger | going from asia or europe? |
| 12:56 | ambroseb_ | Perth, Western Australia |
| 12:56 | TEttinger | ah. |
| 12:56 | TEttinger | even further |
| 12:57 | ambroseb_ | yea, I'm sick of it so I'm moving to Indiana. |
| 12:57 | ambroseb_ | ;) |
| 12:57 | TEttinger | perth is IIRC incredibly hot, has unusual weather and extremely poisonous wildlife? |
| 12:57 | ambroseb_ | haha sure! |
| 12:57 | TEttinger | which is why the trip didn't go visit |
| 12:58 | mdeboard | What's wrong with Indiana |
| 12:58 | dbasch | mdeboard: have you been to Indiana? |
| 12:58 | mdeboard | dbasch: I am here right now :) |
| 12:58 | dbasch | mdeboard: is that where you're from? |
| 12:58 | TEttinger | my brother watched a cricket game in melbourne in the summer. the heat was rough |
| 12:59 | TEttinger | tasmania was nice though |
| 12:59 | mdeboard | dbasch: ya, only been back a few years and moving out again next month |
| 12:59 | ambroseb_ | I meant Indiana means I don't need to travel 30 hours to get anywhere :) |
| 12:59 | dbasch | ambroseb_: it depends on where you want to go. If you want a more central location try Denver or Chicago |
| 13:00 | TEttinger | atlanta is where 2 of the airlines have hubs I think |
| 13:00 | dbasch | the Traveling Clojurist Problem, also known as TCP |
| 13:00 | dbasch | Indiana Pacers, also known as IP |
| 13:00 | mdeboard | lol |
| 13:01 | TEttinger | but it's hard to beat SF I imagine for meeting clojurists |
| 13:01 | ambroseb_ | I have conferences in Montreal, St Louis and London, probably a few hours closer than Perth :) |
| 13:01 | mdeboard | Indiana has a really modern airport that is very uncrowded, TSA is best I've ever been through (and I *HATE* the TSA) |
| 13:01 | dbasch | SF rocks in that sense |
| 13:01 | mdeboard | I will miss Indianapolis airport and Indianapolis traffic the most |
| 13:01 | mdeboard | when I move to Austin |
| 13:01 | rplaca | but the only place to find Dan Friedman is in Indiana... |
| 13:02 | rplaca | :) |
| 13:02 | dbasch | SFO is not bad compared to other airports in the US |
| 13:03 | amalloy | wait, is ambroseb_ actually moving to indiana? i can't keep track of the real statements in this conversation |
| 13:03 | ambroseb_ | amalloy: yes, PhD starting at Indiana Bloomington in about a month. |
| 13:04 | amalloy | man, i'll have to start saying nicer things about core.typed |
| 13:04 | TEttinger | dr ambrose b |
| 13:04 | amalloy | now that i'm in striking distance |
| 13:04 | dbasch | ambroseb_: funny, a friend of mine is there right now at the ACM Web Science conf |
| 13:05 | amalloy | web science? i can't believe there's much science about the web, unless this conference is focused on actual spiders |
| 13:05 | dbasch | amalloy: go tell them :P http://websci14.org/ |
| 13:05 | ambroseb_ | amalloy: where are you? |
| 13:05 | amalloy | oh, LA. not actually that close, but closer than australia |
| 13:06 | amalloy | my sister's getting her phd at purdue, though |
| 13:06 | ambroseb_ | certainly |
| 13:06 | dbasch | I'm in LA too, but only for today |
| 13:06 | amalloy | so i've spent two days in indiana |
| 13:06 | amalloy | practically a native |
| 13:07 | dbasch | my friend speaking at websci is now "Head of Query Understanding" at LinkedIn |
| 13:08 | cbp | wat |
| 13:08 | dbasch | cbp: exactly |
| 13:08 | dbasch | better than another old coworker of mine who called himself "Chief Entomologist" |
| 13:08 | clgv | dbasch: you certainly need a head for query understanding :P :D |
| 13:09 | dbasch | clgv: and you want to hold on to it |
| 13:09 | dbasch | one time I collected all the ways in which people had ended up at britneyspears.com through a query |
| 13:10 | dbasch | you wouldn't believe the spelling creativity of the web |
| 13:10 | dbasch | (you can tell this was 10 years ago, when Britney Spears was relevant) |
| 13:11 | dbasch | $google brittny spiers |
| 13:11 | lazybot | [britney spiers 123 remix - YouTube] http://www.youtube.com/watch?v=goeAUbtolEE |
| 13:11 | amalloy | buttery spores |
| 13:11 | dbasch | damn, I get britney spears |
| 13:11 | dbasch | btirnsy spirss works too |
| 13:12 | dbasch | you can find britney spears on google while wearing box gloves |
| 13:12 | amalloy | dbasch: by induction, any google search at all yields britney spears, yes? |
| 13:12 | dbasch | boxing gloves |
| 13:13 | dbasch | amalloy: enough monkeys typing will only create the works of shakespeare if they don't get distracted by britney spears first |
| 13:14 | dbasch | it would be a fun game: guess the google result |
| 13:14 | dbasch | rianah -> rihanna |
| 13:15 | dbasch | google distance is always closer than Levenshtein's |
| 13:21 | aconz2 | quick q on clojure-contrib libs. I'm looking to use clojure.contrib.java-utils, tho it seems like this has moved and/or been dropped from contrib? seems like a lot of libs listed on http://richhickey.github.io/clojure-contrib/java-utils-api.html have been dropped in the move to the clojure repo |
| 13:21 | dbasch | ~contrib |
| 13:21 | clojurebot | Monolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go |
| 13:26 | aconz2 | thanks! @dbasch : could some work be done to update the page I linked? pretty deceiving, tho only as an artifact of googling. I'd be happy to do the work and make a PR if helpful |
| 13:34 | amalloy | aconz2: the work that should be done is to delete richhickey.github.io - no official clojure stuff has been hosted in his repo for years |
| 13:35 | amalloy | it's all just old and decaying versions of stuff long since superseded by clojure.github.io |
| 13:42 | aconz2 | amalloy: has an attempt been made to delete already? I mean the problem of "misinformation" is solved for me, but I imagine it would still be an issue for any other new(ish)comer |
| 13:43 | xeno__ | Given 2 similar web apps written in Rails and Luminus, running on a quad-core i7 with 32GB RAM, would Clojure + jetty be more efficient in resource usage compared with Rails + Unicorn? I will be deploying a single-box app soon and wondered about memory usage and process size. |
| 13:44 | mdeboard | xeno__: Withoutknowing anything abou tyour application that's basically impossible to answer. With the JVM you can set max memory usage |
| 13:44 | dbasch | xeno__: it's kind of hard to answer that question in the abstract. "web app" doesn't say much about memory usage, the question is more about what you're doing in the backend |
| 13:46 | amalloy | xeno__: with rails, memory usage scales pretty quickly with number of processes, right? since you need N different rails processes. whereas the jvm has a high up-front cost just to start a single jvm, but threads are very cheap |
| 13:51 | xeno__ | amalloy: So you give up, say, 200MB RAM for the JVM but can then get each process using a fraction of a comparable Rails process? |
| 13:51 | amalloy | xeno__: it's not close to 200MB |
| 13:51 | xeno__ | amalloy: What, then? |
| 13:51 | amalloy | well, maybe it is. it's hard to say because a lot of it is disk buffers |
| 13:51 | amalloy | mmapped jars, etc |
| 13:51 | xeno__ | amalloy: Typically, I mean. |
| 13:51 | dbasch | xeno__ amalloy it also depends on what you're using to run Rails |
| 13:51 | amalloy | he said unicorn |
| 13:52 | amalloy | not that i'm a rails expert or anything |
| 13:52 | dbasch | I only used Passenger, which I believe lets you play with processes and threads |
| 13:53 | xeno__ | amalloy: Just trying to get some idea of trade-offs for a CRUD app which also does some quick calculations for about 1 in 3 requests. |
| 13:53 | amalloy | xeno__: well, okay, maybe it is close to 200MB. i have some clojure servers running, with the java heap size set small, so most of the overhead is the jvm itself. they have a resident set size of around 150MB |
| 13:53 | amalloy | i've no idea how much of that they'd be willing to "give back" if there were memory pressure |
| 13:53 | xeno__ | Just thinking if I have the basic principle correct, ie. allocate so much for JVM then each process is much cheaper? |
| 13:54 | amalloy | xeno__: well, there's only one process |
| 13:54 | amalloy | threads inside the jvm aren't full OS-level processes, although i confess i'm not sure exactly what they are |
| 13:54 | justin_smith | xeno__: unlike in ruby, in the jvm it is viable to have multiple threads in one vm |
| 13:54 | xeno__ | amalloy: 200/300MB is no big deal for me if there is 32GB in total available. |
| 13:55 | dbasch | 32GB for a web server. I feel old. |
| 13:55 | amalloy | you should have no trouble running just about anything on 32GB |
| 13:55 | amalloy | my linode has 3GB and is running five or six different clojure webservers |
| 13:55 | justin_smith | xeno__: another data point: I have never had to restart a production clojure app because of a memory leak. |
| 13:56 | amalloy | i have! |
| 13:56 | dbasch | my crappy mp3 search engine in 1998 handled a peak of 200k queries in one day with 128 mb |
| 13:56 | amalloy | i spent weeks, maybe a month, on and off trying to track down a memory leak |
| 13:56 | cbp | it certainly didnt use lucene amirite |
| 13:57 | justin_smith | amalloy: yeah, wasn't saying it was impossilbe. But from what I hear from ex ruby users at my old job, constantly restarting ruby tasks that had their memory usage balloon uncontrollably was a routine thing |
| 13:57 | xeno__ | dbasch: Check 'em out at Hetzner. 32GB/quad-core i7 for under 500 quid a year. |
| 13:57 | amalloy | yeah, that seemed to happen all the time when i was at geni, justin_smith |
| 13:57 | xeno__ | justin_smith: Yes, exactly what I'm trying to avoid. |
| 13:57 | amalloy | they had a monit task that hunted for ruby processes whose memory usage was too high and automatically destroyed them |
| 13:59 | justin_smith | xeno__: from what I can tell, in clojure a task that has memory usage blow up isn't routine, it's considered an anomoly. I have clojure servers with very long uptime, only limited by the need restart in order to deploy updates |
| 13:59 | amalloy | yeah, for sure |
| 13:59 | amalloy | my clojure servers have uptime that's the same as the machine itself |
| 14:00 | amalloy | well, except 4clojure. that one restarts itself all the time because its fundamental requirement is to do stupid stuff (ie, evaluate user-supplied code) |
| 14:00 | xeno__ | justin_smith: Yes, I'm attracted to what seems to be easier server management with Clojure/JVM compared with Rails |
| 14:01 | xeno__ | justin_smith: I started writing the app in Rails while learning Clojure and was going to rewrite later in Clojure but now I'm thinking get it done right at the outset. |
| 14:02 | amalloy | xeno__: that sounds like a good approach. it'll give you something concrete to work towards while learning clojure |
| 14:02 | amalloy | avoid the classic problem of "anyone know an OSS project that wants help from someone who doesn't know how to do anything?" |
| 14:03 | justin_smith | xeno__: I think that would be good. And about your above question, I think the only way clojure would use more ram would be a fixed size price you pay at the outset (the size of clojure, size of the jvm), and that size is not enough to flatten a server, and after that it scales much better than ror / unicorn |
| 14:03 | xeno__ | amalloy: Trouble is you get too deeply into the Rails MVC OO mindset. |
| 14:03 | tuft | xeno__: you're probably in a similar situation to me with django. our provisioning is so complex compared to just installing the JVM and deploying fat jars |
| 14:04 | xeno__ | justin_smith: That was my concern. If there's plenty of RAM available it sounds like JVM is more efficient as the app scales. |
| 14:04 | tuft | yeah, real threads always helpful with conserving that shared stuff =) |
| 14:05 | justin_smith | xeno__: at my previous place of employment we had an in house clojure web framework that started as a rails replacement |
| 14:05 | justin_smith | xeno__: this, as you can imagine, was advantageous in some ways, and in others was an impediment |
| 14:06 | justin_smith | it's pretty heavyweight, and in the clojure world we do prefer combining modular libs over big kitchen sink included frameworks, but caribou is out there if you want to try it |
| 14:06 | justin_smith | and it does work |
| 14:07 | latk | could anyone point me to some more complicated examples of om applications? The example code I have found is pretty limited in scope. |
| 14:07 | gtrak | justin_smith: the choice of domain wording can be a little uncomfortable? :-) |
| 14:07 | xeno__ | justin_smith: Had a look at it a while ago briefly. So it's a Rails clone? |
| 14:08 | xeno__ | justin_smith: But not heavier than Rails itself? |
| 14:08 | gtrak | how would you make a rails clone? |
| 14:08 | justin_smith | gtrak: let-caribou.in ? heh, I picked let-caribou since that had kind of a clojure-esque feel to it, and my tech manager decided it should be a .in domain because he was a perv |
| 14:08 | gtrak | justin_smith: hahaha |
| 14:09 | justin_smith | xeno__: not a rails clone, just developed as a smooth upgrade from rails |
| 14:09 | gtrak | well, it doesn't even have to go there, 'let the caribou in to our house? you're crazy?' |
| 14:09 | justin_smith | xeno__: so it was a priority to re-implement workflows and functionality that the workplace had grown fond of |
| 14:09 | gtrak | it'll wreck all the china and scratch the furniture. |
| 14:09 | xeno__ | justin_smith: Could be very useful to me then unless I just drop the Rails prototype approach altogether. |
| 14:10 | xeno__ | justin_smith: Is it being developed actively? |
| 14:11 | justin_smith | xeno__: the company divested from clojure, and laid the clojure team off (both of us!) |
| 14:11 | justin_smith | we still address bug reports on github, and some day I may start up where I left off with some of the features |
| 14:11 | justin_smith | but it is less active after the layoff to be sure |
| 14:12 | justin_smith | mind that it has been used in many production sites, so it's pretty stable and mature (if very large) |
| 14:13 | xeno__ | justin_smith: What's missing at present? |
| 14:14 | xeno__ | justin_smith: I started out with Luminus. |
| 14:23 | Frozenlock | I'll give plenty of love to whoever can solve this https://github.com/dakrone/clj-http/issues/202 |
| 14:26 | gtrak | Frozenlock: does http-kit actually verify the certs? |
| 14:27 | gtrak | I thought at least the server didn't do ssl at all. |
| 14:30 | amalloy | gtrak: it uses java's http library, which does verify certs |
| 14:31 | amalloy | afaict java doesn't yet support SNI |
| 14:31 | gtrak | ugh I hate security |
| 14:32 | justin_smith | gtrak: Frozenlock: I've generally gotten the recommendation to do ssl via an nginx layer |
| 14:32 | justin_smith | nginx should be in front of whatever you have public facing, regardless |
| 14:32 | amalloy | justin_smith: oh, for sure. that's not the problem |
| 14:32 | amalloy | they're talking about client-side |
| 14:32 | justin_smith | oh, that |
| 14:33 | amalloy | if you have one server with nginx serving ssl for two different domains, then java clients get mad |
| 14:34 | amalloy | i had some trouble recently with the 4clojure.com server, which also hosts refheap, and does ssl for both of them. browsers can handle it because they have SNI support, but clojure and python do their ssl negotiation before sending the Host header, so nginx can't know which ssl cert to use |
| 14:36 | gtrak | at least you hide your lein-in-production behind an nginx |
| 14:36 | amalloy | i always thought lein was an abbreviation for leininproduction |
| 14:36 | amalloy | german all sounds the same to me |
| 14:37 | gtrak | did you konw taht a cbaimrgde uvenisitry stduy... |
| 14:38 | arrdem | ow my face |
| 14:38 | gtrak | that could be a really simple clojure app |
| 14:39 | amalloy | gtrak: that story is actually a bit dubious - it's typically presented with "random" rearrangements that are easier to read than most orderings |
| 14:41 | Frozenlock | amalloy: "afaict java doesn't yet support SNI" I hope it's not the case. I've read it's somehow supported since 1.7, but I don't know enough about this particular subject :-( |
| 14:42 | Frozenlock | About 4clojure and refheap, did you find a solution? Different servers? |
| 14:42 | amalloy | user> (munge "gtrak: that story is actually a bit dubious - it's typically presented with \"random\" rearrangements that are easier to read than most orderings") => "gratk: that sorty is atlucaly a bit douibus - it's tailclypy ptersneed with \"rdanom\" rgmaerenenrats that are eseair to raed than most orirnegds" |
| 14:43 | amalloy | basically it works pretty well for short or common words, but things like "ptersneed" or "tailclypy" are pretty tough to figure out |
| 14:43 | gtrak | ptersneed is pretty funny |
| 14:44 | benzap | amalloy: you need to reduce the amount of characters movements from it's point of origin |
| 14:44 | amalloy | Frozenlock: we arranged for refheap's cert to be used in the case of clients that don't support SNI. that works fine because nobody ever uses 4clojure outside of a browser |
| 14:46 | ndaly | re: 4clojure.com: "So wait, I can't buy cheap real estate here?" … rofl |
| 14:49 | Frozenlock | https://github.com/OpenSourceFieldlinguistics/FieldDB/issues/1435 |
| 14:49 | Frozenlock | Damned be my limited brain. I don't understand why it doesn't work for Clojure. |
| 14:50 | DomKM | Are URI fragments not available in ring request maps? I don't see fragment/anchor/hash in the ring spec and ring mock is not parsing them. |
| 14:50 | amalloy | DomKM: they're not sent to the server at all, right? |
| 14:53 | amalloy | a difficult scrambled word: dtcnuesrutirg |
| 14:53 | cbp | destructuring? |
| 14:53 | clojurebot | destructuring is http://clojure.org/special_forms#binding-forms |
| 14:54 | amalloy | well, okay, not *that* difficult. but harder than wehre |
| 14:55 | Frozenlock | ,(take 5 (slurp "https://www.4clojure.com")) |
| 14:55 | clojurebot | #<SecurityException java.lang.SecurityException: denied> |
| 14:55 | Frozenlock | err |
| 14:56 | Frozenlock | Anyhow, how comes slurping works? |
| 14:56 | cbp | Frozenlock: what is the issue? |
| 14:56 | cbp | (doc slurp) |
| 14:56 | clojurebot | "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments." |
| 14:56 | amalloy | hm, good question. not sure; i thought that was broken |
| 14:57 | cbp | (doc clojure.java.io/reader) |
| 14:57 | clojurebot | "([x & opts]); Attempts to coerce its argument into an open java.io.Reader. Default implementations always return a java.io.BufferedReader. Default implementations are provided for Reader, BufferedReader, InputStream, File, URI, URL, Socket, byte arrays, character arrays, and String. If argument is a String, it tries to resolve it first as a URI, then as a local file name. URIs with a 'file' protocol are converted to |
| 14:57 | Frozenlock | cbp: clj-http can't handle SNI (https with multiple certs on the server), but `slurp' can. |
| 14:57 | cbp | oh |
| 14:57 | cbp | sorry i misunderstood :-P |
| 14:57 | TimMc | Frozenlock: What happens if you slurp a site with an invalid cert? |
| 14:57 | Frozenlock | TimMc: Good question... |
| 14:58 | Frozenlock | Anyone has one around? |
| 14:58 | gtrak | *BOOM* goes the JVM |
| 14:58 | TimMc | Maybe slurp just ignores the "cert failure" due to SNI. |
| 14:58 | DomKM | amalloy: I don't know. I guess I should find that out first. |
| 14:58 | TimMc | Frozenlock: https://www.cacert.org/ assuming you dno't have their root cert installed |
| 14:59 | amalloy | $google http spec fragment |
| 14:59 | lazybot | [RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax] http://tools.ietf.org/html/rfc3986 |
| 14:59 | DomKM | amalloy: Looks like you're correct. Thanks :) |
| 15:00 | Frozenlock | BOOM! javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target |
| 15:00 | gtrak | just shell out to curl |
| 15:00 | TimMc | OK, so it doesn't ignore *that* kind of failure. :-) |
| 15:01 | Frozenlock | technology, y u no work? |
| 15:02 | gtrak | security is a pain-fractal |
| 15:02 | tuft | software is hard =( |
| 15:03 | gtrak | normal software at least creates value :-) |
| 15:03 | Frozenlock | security doesn't? |
| 15:03 | gtrak | unless of course it's getting hacked, sigh.. |
| 15:03 | cbp | creates more jobs to maintain it at least |
| 15:04 | TimMc | I guess there can't be a pathod-like service that responds with whatever SSL cert properties you specify in the request. |
| 15:08 | TimMc | (slurp "https://12345.sni.velox.ch/") |
| 15:09 | ndaly | gtrak: "security is a pain-fractal" is now my quote of the day |
| 15:09 | TimMc | Great! Your client [Java/1.7.0_51] sent the following TLS server name indication extension in its ClientHello: 12345.sni.velox.ch |
| 15:10 | Frozenlock | So, java 1.7 indeed supports TLS |
| 15:10 | TimMc | So slurp is doing the right thing. |
| 15:10 | Frozenlock | clj-http ---> javax.net.ssl.SSLException: hostname in certificate didn't match: <12345.sni.velox.ch> != <alice.sni.velox.ch> OR <alice.sni.velox.ch> OR <carol.sni.velox.ch> |
| 15:11 | gtrak | Frozenlock: most definitely httpclient doesn't use the same code paths. |
| 15:12 | gtrak | Frozenlock: https://issues.apache.org/jira/browse/HTTPCLIENT-1119 |
| 15:12 | gtrak | check your version |
| 15:12 | Frozenlock | gtrak: https://github.com/dakrone/clj-http/issues/202 |
| 15:13 | gtrak | oh, heh. |
| 15:13 | Frozenlock | Thanks anyway ;-) |
| 15:14 | gtrak | well, maybe clj-http is using an older version, is what I meant. |
| 15:14 | cbp | i think http-kit client should work? :-P |
| 15:14 | gtrak | nope, I'm wrong. |
| 15:17 | gtrak | pain-fractal can be a black-metal overtone band. |
| 15:57 | benzap | is there a way to do exception handling on (load-string "")? It doens't seem like my try catch statement is catching anything |
| 15:59 | amalloy | there aren't a lot of good reasons to call load-string |
| 16:00 | jcromartie | benzap: how do you mean? (try (load-string …) (catch Throwable t …)) works fine |
| 16:00 | jcromartie | when the code loaded from the string contains errors |
| 16:07 | shaun_ | Om as string cursor question: why does this fail? https://gist.github.com/shaunlebron/bca0fd36f26dee6fc6dd |
| 16:10 | ndaly | I'm trying to understand the statement, "Elegance and familiarity are orthogonal." |
| 16:10 | ndaly | is there any chance someone knows in what context Rich said it? |
| 16:10 | shaun_ | petehunt do you use Om? |
| 16:10 | petehunt | shaun_: no i don’t really know clojure very well |
| 16:10 | petehunt | and i don’t have time to get good right now |
| 16:10 | bbloom | ndaly: you don't really need the context to process that statement |
| 16:10 | nullptr | petehunt: do you have a hammock? |
| 16:11 | bbloom | ndaly: it's simply the easy vs simple distinction rehashed |
| 16:11 | petehunt | nullptr: at work yes, not at home :P |
| 16:11 | shaun_ | petehunt: I can imagine, well, thanks for react |
| 16:11 | bbloom | ndaly: elegant == simple, familiar == easy |
| 16:11 | bbloom | ndaly: assuming you've watched simple made easy |
| 16:11 | ndaly | I haven't watched simple made easy |
| 16:11 | petehunt | shaun_: ;) lots of people over here. we owe the cljs community for a lot as well |
| 16:11 | ndaly | but that does illuminate it some, thank you |
| 16:11 | bbloom | ~simplemadeasy |
| 16:11 | clojurebot | Titim gan éirí ort. |
| 16:11 | bbloom | ~easy |
| 16:12 | clojurebot | Titim gan éirí ort. |
| 16:12 | bbloom | ~simple |
| 16:12 | clojurebot | Gabh mo leithscéal? |
| 16:12 | bbloom | *shrug* |
| 16:12 | bbloom | ndaly: you can find it. it's worth watching for sure |
| 16:12 | ndaly | I'll look for it. Thanks. |
| 16:14 | benzap | I have this, am I doing something wrong with (try? http://pastebin.com/6aEsBs1j |
| 16:14 | ndaly | think this is it, if anyone else is interested: http://www.infoq.com/presentations/Simple-Made-Easy |
| 16:15 | oskarkv | ndaly yes. best video ever |
| 16:15 | Frozenlock | Pff, Rich Hickey is good, but he's no Carl Sagan :-p |
| 16:16 | oskarkv | :p |
| 16:16 | nullptr | "...billions and billions of state changes, but only one identity..." |
| 16:16 | oskarkv | hehe |
| 16:16 | shaun_ | I told my intern simple != easy when teaching her clojurescript |
| 16:16 | gtrak | haha |
| 16:16 | shaun_ | she interpreted that as meaning clojurescript is very difficult even though it's simple |
| 16:16 | Frozenlock | shaun_: clojurescript is neither simple nor easy ... |
| 16:17 | arrdem | Rich also isn't a god sadly :P |
| 16:17 | shaun_ | Frozenlock: I thought that was the whole argument, that cljs is simple |
| 16:17 | arrdem | Frozenlock: simple compared to javascript perhaps |
| 16:18 | Frozenlock | ok, I could accept this comparison |
| 16:18 | gtrak | Frozenlock: the idealized CLJS is simpler than the current state of things. |
| 16:18 | bbloom | it's certainly simpler than javascript... up to, but excluding, javascript interop |
| 16:18 | bbloom | which of course has all the complexity of javascript itself, and then some |
| 16:19 | shaun_ | Frozenlock: if you can learn the syntax in 15 minutes, I would say simple: https://github.com/shaunlebron/ClojureScript-Syntax-in-15-minutes |
| 16:19 | amalloy | benzap: map is lazy |
| 16:19 | arrdem | shaun_: syntax is almost universally easy :P |
| 16:19 | Frozenlock | shaun_: I'm pretty sure this doesn't cover dealing with externs |
| 16:19 | benzap | amalloy: so it's evaluated outside ofthe try? |
| 16:19 | amalloy | your map immediately returns a lazy seq, then you exit the try/catch scope, then you realize the seq at some later date |
| 16:19 | arrdem | benzap: yep |
| 16:19 | Frozenlock | Also, "b isn't defined" is a terrible error message :-p |
| 16:19 | benzap | hmm, how would I ensure it's not lazy? wrap it in (seq? |
| 16:20 | arrdem | benzap: doall |
| 16:20 | gtrak | if clojure didn't already exist, we might not accept the principles, but the principles and the kinds of programs you can write with those abstractions are what's 'simple'. |
| 16:20 | amalloy | well, (try (doall (map ...))) is the smallest change |
| 16:20 | amalloy | or i guess using mapv instead is smaller |
| 16:21 | benzap | ah thank you |
| 16:21 | benzap | mapv did the trick |
| 16:21 | amalloy | i'd recommend using a more explicit side-effecting construct like doseq, since i bet you don't care about the results of load-string at all |
| 16:21 | shaun_ | Frozenlock: true, you mean interop? or externs for advanced mode |
| 16:21 | benzap | hmm |
| 16:21 | benzap | i might care about the side effects, it depends |
| 16:22 | amalloy | not the side effects, the return value |
| 16:22 | Frozenlock | shaun_: advanced compilation |
| 16:22 | amalloy | tbh i'm a little surprised load-string actually returns anything. i would have guessed it returns nil |
| 16:26 | arrdem | amalloy: well load returns the value of the eval of the tail form AFAIK, so that's not surprising.. |
| 16:27 | amalloy | i just would never use load in a context where i want a return value; that's what eval is for. so i imagined that it doesn't give you a return value |
| 16:27 | Bronsa | arrdem: man you have short memory. load returns nil, you even patched t.e.jvm's load to return nil |
| 16:28 | arrdem | Bronsa: why do you think I leave type signatures and verbose docs behind? I can't remember this crap. |
| 16:28 | arrdem | nor should I... |
| 16:29 | Bronsa | wut https://twitter.com/raymcdermott/status/482222051659632640 |
| 16:30 | arrdem | er.... |
| 16:31 | Frozenlock | For speed? |
| 16:33 | arrdem | Bronsa: HAH the reason I patched t.e.jvm is that clojure.core as usually is silly. (eval-string "(+ 1 2)") -> 3 |
| 16:33 | bbloom | Bronsa: odd, i wonder why |
| 16:34 | arrdem | s/eval-string/load-string/g |
| 16:35 | Bronsa | bbloom: given the core.async impl I really cannot figure out what could go into the compiler |
| 16:36 | bbloom | Bronsa: maybe just some of the analysis needed to trigger the state machine rewrite |
| 16:38 | arrdem | bbloom: but what for? Clojure has eschewed TCO and other state machine rewrites for a long time.. |
| 16:39 | arrdem | bbloom: see amalloy's argument for this directed at me in the logs a few days ago, and Rich's old comments on TCO on Scheme lists. |
| 16:40 | bbloom | arrdem: i don't think i have those logs & our various bots seem down... |
| 16:40 | amalloy | a few days ago? i don't remember talking about this recently |
| 16:41 | bbloom | arrdem: anyway, it's not just for TCO |
| 16:41 | bbloom | arrdem: core.async uses the state machine rewrite |
| 16:41 | bbloom | but there dozens of other useful reasons to do state machine or other transforms to avoid stack consumption |
| 16:41 | Bronsa | bbloom: that seems a bit unlikely given that it just moved to t.a.jvm for that |
| 16:41 | bbloom | maybe he had another one in mind and needs some real compiler analysis data |
| 16:42 | Bronsa | bbloom: oh you mean the ssa transformation? |
| 16:42 | bbloom | the ssa transform depends on some ad-hoc analysis |
| 16:42 | bbloom | but yeah, the ssa transform may be useful for other compiler stuff |
| 16:43 | bbloom | maybe there's a particular hot path in datomic or something that needs some optimization that ssa would simplify, that could justify some local transforms in the compiler |
| 16:43 | bbloom | probably not worth speculating, tho |
| 16:43 | arrdem | bottom line: it's Rich's language and he's gonna do as he sees fit. |
| 16:44 | Frozenlock | inb4 clojure fork |
| 16:44 | arrdem | Frozenlock: inb4 inb4 |
| 16:44 | bbloom | i mean, why even bother writing your own language if you're not gonna do as you see fit? :-P |
| 16:45 | hyPiRion | isn't the go block only able to detect visible <! and >! calls? |
| 16:46 | bbloom | hyPiRion: yes, but the compiler wouldn't help much with a dynamic extent transform b/c called functions are already compiled to byte code and need to support hot swapping vars |
| 16:50 | benzap | i'm wodnering, is there any clojure functions that sortof work like a rollback? |
| 16:51 | benzap | I want to try and load-string some scripts, but I want to make sure that I can rollback if anything doesn't evaluate |
| 16:51 | benzap | or does load-string take care of that? |
| 16:51 | hyPiRion | bbloom: Yeah, I wasn't thinking about the compiler analysis part though. Neither Go nor Erlang could do that either. |
| 16:52 | bbloom | huh? i'm 99% sure that go does inter-function analysis optimizations, at least within a single compilation unit |
| 16:52 | amalloy | there's no such thing, benzap. load-string can perform arbitrary side effects, like delete your hard drive, if that's what the code you're loading says to do. how do you roll that back? |
| 16:52 | arrdem | benzap: clojure's namespace and var binding structures are not first class and are not trivial to manipulate or restore. Consequently what you are asking for is very, very hard. |
| 16:53 | amalloy | arrdem: easier, it's impossible |
| 16:53 | m_m | Hi. What i can put at 'x' place for getting true: (= 2400 (reduce (fn [a b] (* a b)) x [1 2 3 4])) |
| 16:53 | amalloy | m_m: do you understand what that code is doing? |
| 16:53 | gtrak | amalloy: arrdem: benzap: you just need an 'inverse' function that takes a function, easy-peasy. |
| 16:53 | Frozenlock | benzap: if you want to deal with atoms you could use https://github.com/Frozenlock/historian, but otherwise I don't see how this could be done. |
| 16:54 | bbloom | Bronsa: https://gist.github.com/philandstuff/299cda371c7e74b03f18#q-other-possible-extensions |
| 16:54 | gtrak | it'll run the bytecode backwards |
| 16:54 | gtrak | or forwards on an anti-jvm |
| 16:54 | benzap | hmm yeah, i'm probably going to be careful how I approach this |
| 16:54 | amalloy | gtrak: inverse :: IO b -> (a -> b) -> a -- this would be awesome |
| 16:54 | bbloom | Bronsa: had a brief chat w/ rich about generators/yield back when i gave a talk in NYC on Fipp |
| 16:54 | m_m | amaloy: I think that I need to add 1000 to vector [1 2 3 4]...but I dont know how. I understend rest of the code. |
| 16:54 | gtrak | it's like a turing machine, you just turn the tape the other way. |
| 16:55 | bbloom | Bronsa: basically i used reducers to emulate generators, but he suggested i try core.async's >! to emulate yield |
| 16:55 | hyPiRion | bbloom: Not generally I think? |
| 16:55 | amalloy | m_m: observe that reduce is being called with three arguments, a function, x, and a vector. you can't change the vector by changing x, of course - do you know what reduce does when it gets three args? |
| 16:55 | hyPiRion | Let me try to come up with an example |
| 16:56 | bbloom | Bronsa: thread here: https://twitter.com/BrandonBloom/status/356873464461791234 |
| 16:56 | m_m | amalloy: So my x will be an in line function which will be conj 1000 to vector [1 2 3 4] ? |
| 16:57 | gtrak | the hard part is making sure that the inverse function halts. |
| 16:57 | amalloy | m_m: what does (reduce f x y) do? |
| 16:57 | bbloom | this is what i was trying to do w/ the CPS transform, where i labeled functions with :cps metadata... never did get it working, but i was operating at the macro level too |
| 16:57 | bbloom | core.async puts locals in to fields on state machine object |
| 16:57 | m_m | amalloy: Use funtion 'f' on x and y ? |
| 16:58 | gtrak | ((inverse +) 3) -> ([1 2] [0 3] [-1 3 1] ...) |
| 16:59 | gtrak | ((inverse delete-my-hard-drive)) -> (for [x universe-of-possible-hard-drives] x) |
| 16:59 | amalloy | here is an example: ##(reduce #(cons %2 %1) () '(a b c d)) |
| 16:59 | lazybot | ⇒ (d c b a) |
| 16:59 | arrdem | "declare a fn as async".... |
| 16:59 | amalloy | that's quite different from ##(#(cons %2 %1) () '(a b c d)), isn't it? |
| 16:59 | lazybot | ⇒ ((a b c d)) |
| 17:01 | m_m | amalloy: Aahhh i see... |
| 17:01 | amalloy | so (reduce f x y) is definitely not the same as (f x y), but rather (f (f (f x (first y)) (second y)) (third y)) ... and so on until ys is empty (and pretending here that third is a function that exists) |
| 17:02 | sveri | Hi, I just found this thread, trying to store an uri: https://groups.google.com/forum/#!msg/datomic/4bZUz2JjlbI/hKB_s3t5nIoJ Is there still no way to store a uri? |
| 17:03 | hiredman | sveri: you can create your own data reader that creates uri objects |
| 17:04 | hiredman | sveri: it looks like according to that exchange you can store uris just fine |
| 17:05 | alandipert | or ye olde read-eval |
| 17:05 | hiredman | sveri: seems likely you are getting tripped up on loading a file but not evaluating it |
| 17:05 | hiredman | alandipert: sure |
| 17:05 | alandipert | ##{:x #=(list java.net.URI. "http://foo.com")} |
| 17:06 | hiredman | alandipert: but that only works if the code is evaulated, in which case, why not just call the constructor? |
| 17:06 | alandipert | +1 tagged literal though |
| 17:06 | hiredman | ,(read-string "{:x #=(list java.net.URI. \"http://foo.com\")}") |
| 17:06 | clojurebot | #<RuntimeException java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.> |
| 17:06 | hiredman | feh |
| 17:06 | hiredman | anyway, you won't get a URL object |
| 17:17 | aaelony | Can a defrecord defined in namespace A be instantiated in namespace B ? I've seen this (http://cyrax.wordpress.com/2013/07/22/clojure-importrequireuse-defrecord-from-another-namespace/) but I still get an "Unable to resolve classname" error. Perhaps due to bad aliasing... any help appreciated. |
| 17:20 | bbloom | aaelony: use the -> factory function that gets generated |
| 17:20 | bbloom | ,(defrecord Point [x y]) |
| 17:20 | clojurebot | sandbox.Point |
| 17:20 | bbloom | ,(->Point 5 10) |
| 17:20 | clojurebot | #sandbox.Point{:x 5, :y 10} |
| 17:20 | bbloom | ,(fn? sandbox/->Point) |
| 17:20 | clojurebot | true |
| 17:21 | aaelony | bbloom: Thanks. I am using (->Point 5 10) and tried (->sandbox/Point) but not (sandbox/->Point) |
| 17:21 | bbloom | aaelony: the -> is just part of the name |
| 17:22 | bbloom | ,`->Point |
| 17:22 | clojurebot | sandbox/->Point |
| 17:22 | bbloom | ,'you-can<-have-#strange->names%like*this+ |
| 17:22 | clojurebot | you-can<-have-#strange->names%like*this+ |
| 17:23 | aaelony | bbloom: that's perfect. Works like a charm, many thanks... |
| 17:23 | bbloom | it's not syntax, see (doc defrecord) |
| 17:23 | noonian | there is also (map->Point {:x 5, :y 10}) |
| 17:26 | aaelony | On a similar note, suppose I have several defrecords defined and I want a way to instantiate an appropriate defrecord based on a keyword. I'm currently doing a cond on the keyword and if it matches then instantiating. But maybe there is a better way...? |
| 17:26 | bbloom | aaelony: any reason you can't just use the function directly? |
| 17:26 | bbloom | ie are you serializing these keywords or anything like that? |
| 17:26 | bbloom | ->Point is a value |
| 17:26 | bbloom | it's just not round-trip serializable |
| 17:27 | bbloom | ,(defrecord Rect [l t r b]) |
| 17:27 | clojurebot | sandbox.Rect |
| 17:28 | bbloom | ,(let [cmd [:rect 5 10 15 20]] (apply ({:rect ->Rect :point ->Point} (first cmd)) (next cmd))) |
| 17:28 | clojurebot | #sandbox.Rect{:l 5, :t 10, :r 15, :b 20} |
| 17:29 | bbloom | just def a lookup table |
| 17:29 | aaelony | bbloom: well, here's what I'm trying to do. I have n file types, each in their own format. Each file type has a corresponding defrecord that knows about the fields expected in each file. Each defrecord also has a function that knows how to extract file datestamp information embedded in the filename (which unfortunately is different for each filetype). I know at runtime which file I'm interested in and I want th |
| 17:29 | aaelony | e dispatch to work to get the right parsing of the datestamp info |
| 17:30 | noonian | aaelony: if you know the set of possible file types then a lookup table as bbloom suggests should work fine |
| 17:30 | noonian | you could also use multimethods for dispatch here |
| 17:31 | aaelony | noonian: I already rely on the defrecords for other things as well. I'd love to be able to have a lookup table from keyword to defrecord that would instantiate the appropriate defrecord. |
| 17:31 | bbloom | aaelony: a map of format to line parser seems like the no brainer way to go |
| 17:32 | aaelony | bbloom: so defrecords are out? |
| 17:32 | bbloom | defrecord is totally orthogonal |
| 17:32 | noonian | ,(defrecord Markdown [content]) |
| 17:32 | clojurebot | sandbox.Markdown |
| 17:32 | noonian | ,(defrecord Org [content]) |
| 17:32 | clojurebot | sandbox.Org |
| 17:32 | aaelony | bbloom: I kinda just want polymorphism |
| 17:33 | bbloom | aaelony: but you want polymorphism per file type, right? |
| 17:33 | noonian | ,(def lookup-table {:md ->Markdown, :org ->Org}) |
| 17:33 | clojurebot | #'sandbox/lookup-table |
| 17:33 | aaelony | yes |
| 17:33 | aaelony | noonian: that looks exactly like what I need |
| 17:33 | bbloom | aaelony: do you have any pressing need for *open* polymorphism? |
| 17:33 | aaelony | thanks |
| 17:33 | bbloom | aaelony: that's exactly what i showed you, go look at my example about :rect |
| 17:33 | bbloom | heh |
| 17:34 | bbloom | but i suspect that this isn't what you want really |
| 17:34 | bbloom | do the different file formats have the same info in them? |
| 17:34 | bbloom | or are they totally unrelated? |
| 17:34 | aaelony | bbloom: maybe I didn't understand initially. Let me try noonian's answer |
| 17:34 | aaelony | the file formats are completely unrelated |
| 17:34 | bbloom | and how many records are in each file type? |
| 17:34 | bbloom | order of magnitude. 10? 10000? |
| 17:35 | noonian | aaelony: my answer is the same idea as bblooms, i was just trying to illustrate a possible implementation |
| 17:35 | aaelony | each file type can have as many records as it needs |
| 17:35 | aaelony | noonian: yes, that is correct. I just didn't understand what was meant without the example implementation. |
| 17:36 | aaelony | bbloom: less than 30 records |
| 17:36 | noonian | but do the files represent the same things? with the format being just the representation |
| 17:36 | bbloom | aaelony: don't bother with defrecord |
| 17:36 | bbloom | just use amap |
| 17:36 | bbloom | it's overkill here |
| 17:36 | noonian | because in that case you might just want a single record with a polymorphic function to instantiate them from different formats |
| 17:36 | aaelony | yes, I like maps a lot. But I wanted to try dispatch with defrecords |
| 17:37 | bbloom | but you want polymorphic construction |
| 17:37 | bbloom | you said the records from different file types are totally unrelated |
| 17:37 | aaelony | correct |
| 17:37 | bbloom | defrecord is for optimizing field storage (totally unecessary for small row counts) and for type dispatch on the record itself |
| 17:37 | bbloom | you're dispatching on the file format... once.... before any records are created |
| 17:38 | noonian | to hook into the record dispatch you need to use protocols and have a record instance in the first place. since you want polymorphic construction you need to use a different method to get the instance in the first place |
| 17:38 | aaelony | there are 2 unrelated concepts, defrecords for the data in each file, and defrecords for data in each file's name |
| 17:38 | bbloom | aaelony: don't bother with defrecords |
| 17:38 | aaelony | unfortunate |
| 17:38 | bbloom | {:format :type1 :path "some/file"} |
| 17:39 | bbloom | put :type1 and :type2 in a map and look up a parse function from that |
| 17:39 | bbloom | no reason to bring complexity like types in to this |
| 17:39 | aaelony | maps are nice |
| 17:39 | aaelony | well this is one area where it would have been nice to have a more OO view |
| 17:40 | bbloom | aaelony: not that i can tell |
| 17:40 | aaelony | suppose there are functions like parse-x where the implementation will differ depending on the file name format |
| 17:41 | aaelony | there are many X's too |
| 17:41 | noonian | you can think of a map as an object whose entries are its fields |
| 17:41 | noonian | there are more ways than records to get polymorphism in clojure |
| 17:41 | bbloom | (def parsers {:format1 some-parser-fn :format2 some-other-fn}) |
| 17:41 | aaelony | yes yes |
| 17:41 | aaelony | of course |
| 17:41 | bbloom | if you need open dispatch: |
| 17:41 | bbloom | (defmulti parser :format) |
| 17:41 | aaelony | bbloom: I'd prefer open dispatch |
| 17:42 | noonian | yeah, multi-methods are the way to go then |
| 17:42 | bbloom | (defmethod parser :format1 [file-map] (fn [line] ...))) |
| 17:42 | aaelony | I have used multi methods in the past, and they were very slow |
| 17:42 | bbloom | you're going to do ONE multimethod dispatch per file |
| 17:42 | bbloom | i promise you, they are fast enough for that |
| 17:42 | sveri | hiredman: I see, I guess, thank you :-) |
| 17:43 | aaelony | anyways, I appreciate the help. I've got the defrecord solution working the way I want it. |
| 17:44 | aaelony | bbloom: I believe you. Thanks again |
| 17:44 | noonian | you could also just take an optional argument which is a parse fn or another lookup table that you merge with the first one |
| 17:45 | aaelony | cool |
| 17:55 | ivan | why does putting code into :repl-options {:init ... without a (do wrapper magically break things with "Wrong number of args (2) passed to [whatever]"? |
| 17:56 | bbloom | ivan: i'm not an expert on this, but i think the init code is merged in to a bigger do in some way when you have plugins or layered protocols |
| 17:56 | bbloom | seems like the rule is just always use do |
| 17:56 | ivan | that's depressing |
| 17:56 | ivan | thanks |
| 17:56 | bbloom | agreed |
| 17:57 | bbloom | seems like it should be straightforward to put it in to a nested do & not have this problem |
| 17:57 | bbloom | *shrug* |
| 17:57 | bbloom | layered procotols => i meant profiles |
| 18:00 | ivan | my new security-hole-free REPL setup is { cat init.clj; cat; } | java -Xmx192M -Dfile.encoding=UTF-8 -cp "$(lein classpath)" reply.ReplyMain |
| 18:00 | ivan | I need that second cat to prevent it from quitting immediately, but unfortunately I need to EOF/ctrl-c a second time to exit or something |
| 18:01 | amalloy | ivan: i don't understand what problem you're talking about. :repl-options {:init (println 'hi)} works fine for me |
| 18:01 | ivan | amalloy: that's probably just println. try a load-file or an eval. |
| 18:01 | amalloy | if you mean :repl-options {:init ((println 'hi) (println 'bye))}, then of course that doesn't work |
| 18:02 | amalloy | :repl-options {:init (eval '(println 'hi))} works fine too, of course. what is a specific thing that doesn't work for you? |
| 18:02 | ivan | :init (load-file "init.clj") |
| 18:03 | bbloom | amalloy: iirc i ran in to an issue where a plugin adds repl-options & lein tries to compose them |
| 18:03 | bbloom | dunno if something has changed |
| 18:04 | amalloy | that load-file works fine too. i'm with bbloom: some middleware is putting stupid stuff in your project |
| 18:04 | ivan | amalloy: apparently it works without (do ...) if you don't have some lein plugins in your ~/.lein/profiles.clj |
| 18:04 | amalloy | try lein pprint |
| 18:04 | amalloy | i have plugins in my profiles. you just have one that breaks things |
| 18:04 | amalloy | probably in the manner bbloom describes |
| 18:05 | ivan | :plugins [[lein-ancient "0.5.4"]] was responsible |
| 18:05 | amalloy | (ie, by concatting together two lists into a list) |
| 18:05 | bbloom | amalloy: i think it's lein that does it |
| 18:05 | bbloom | at least that's what i recall |
| 18:05 | bbloom | it assumes your :init value is a list beginning with do |
| 18:05 | bbloom | calls `next on it, then concats them in to another do |
| 18:06 | ivan | sorry, wrong culprit, lein-ancient is fine |
| 18:06 | ivan | :plugins [[mvxcvi/whidbey "0.2.2"]] |
| 18:07 | amalloy | bbloom: i'd guess that it doesn't assume that, but rather just merges lists by concatting them |
| 18:07 | amalloy | as a generic merge on lists, not specific to repl-init |
| 18:08 | cespare | I'm having trouble with lein checkouts, where occasionally running 'lein jar' puts the .class files for a checkout dependency (say, mylib) into target/classes/. Once those are in there, they shadow any changes to the mylib source, so my project is broken until I run lein clean. |
| 18:08 | cespare | This is with :aot :all in the profile I'm using for lein jar btw. |
| 18:09 | cespare | also I've spent a long time trying to get a reliable repro without luck. I've seen it happen on a fresh pair of lein projects once, but now I can't make it happen again. |
| 18:10 | cespare | (It's an issue for our team because this breaks our projects for us once or twice a day on average) |
| 18:10 | amalloy | AOT compilation is a creeping misery, spreading sadness to all it touches |
| 18:12 | amalloy | right, i think https://github.com/technomancy/leiningen/blob/f73a9998ff2992ab7574448e5884e08417c21526/leiningen-core/src/leiningen/core/project.clj#L512-L518 is all that's responsible for combining your repl-init values |
| 18:13 | amalloy | if you were to lein-pprint, you'd see that your repl-init is set to something bad like ((load this) (print that)) |
| 18:13 | bbloom | amalloy: is metadata "inherited"? |
| 18:13 | bbloom | seems like the base profile could specify a sensible merge policy for repl-init |
| 18:13 | amalloy | bbloom: i dunno, he does all sorts of weird gyrations with metadata |
| 18:13 | amalloy | i don't try to keep up |
| 18:14 | bbloom | nor do i, i do the absolute minimum leinfu to make the couple plugins i use work... frankly, i totally understand rich's preference for CLASSPATH=whatever java -jar |
| 18:14 | amalloy | it does look like the base profile could have :repl-init ^{:reduce (fn [a b] `(do ~a ~b))} () |
| 18:15 | amalloy | but i dunno |
| 18:15 | stephenjudkins | i have asked this question before, but: where does the documentation for `->` live? |
| 18:16 | arrdem | #(clojure.repl/doc ->) |
| 18:16 | hiredman | ,(doc ->) |
| 18:16 | clojurebot | "([x & forms]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc." |
| 18:17 | stephenjudkins | thanks |
| 18:18 | cespare | amalloy: okay, I got a repro with :aot |
| 18:18 | cespare | so it's not actually that. |
| 18:19 | cespare | *without :aot |
| 18:19 | cbp | lol arrdem |
| 18:19 | amalloy | cespare: if you can reproduce it without a :main or :aot i'll be impressed |
| 18:21 | amalloy | (because :main implies AOTing the main namespace, which typically entails AOTing everything under the sun) |
| 18:25 | cespare | amalloy: yeah, you're right about :main. |
| 18:26 | cespare | Any ideas how to fix this? It seems like a bug |
| 18:30 | amalloy | i stay away from AOT as much as i can. what solution you choose will depend on why you have a :main and what tradeoffs you're willing to make |
| 18:31 | cespare | amalloy: all our projects have mains |
| 18:31 | cespare | they are servers |
| 18:31 | cespare | the problem i'm seeing is that it (apparently non-determistically) breaks checkouts |
| 18:32 | cespare | *deterministically |
| 18:33 | cespare | at this point, the main other alternative we're considering is getting rid of checkouts and going back to our old solution of symlinking our shared_lib code into all our projects. |
| 18:33 | cespare | which is pretty nasty, but at least doesn't break unexpectedly. |
| 18:33 | amalloy | you're being too generous - it nondeterministically breaks all kinds of things, checkouts being just one specific case. but i also stay away from checkouts, so i don't have any particularly good advice for you |
| 18:34 | cespare | so to summarize, you're saying that lein is broken? |
| 18:34 | amalloy | s/lein/clojure, really. aot just blows |
| 18:34 | amalloy | cespare: you can put your shared_lib in a maven repo, and release it when there's a new feature, updating dependencies as needed |
| 18:34 | amalloy | it's a hassle, but it's reproducible and works |
| 18:34 | cespare | we change it very rapidly along with our other code |
| 18:34 | cespare | that overhead wouldn't be acceptable. |
| 18:35 | hiredman | you could just not aot anything |
| 18:35 | cespare | but I need a main, yes? |
| 18:35 | cj3kim | Hi. I'm new to clojure. I downloaded a library called gaussian_elimination and I have placed it into my project directory that has a src/core.clj and project.clj file. Gaussian_elimination has the same structure. How do I require gaussian_elimination code in my project src/core.clj code? |
| 18:35 | cespare | our projects are mainly ring servers |
| 18:36 | amalloy | you can have a main which doesn't load anything else at compile time, but compiles it at app startup with a dynamic require |
| 18:36 | hiredman | cespare: there are tons and tons of possibilities |
| 18:36 | amalloy | it'll slow down startup significantly, but that's the price you pay |
| 18:36 | possibilities | but there's only one @possibilities |
| 18:36 | amalloy | ~lein |
| 18:36 | clojurebot | lein is http://github.com/technomancy/leiningen |
| 18:37 | hiredman | cespare: clojure comes with a clojure.main class that has a handy -m option |
| 18:37 | hiredman | cespare: you can write some java stubs |
| 18:39 | hiredman | cespare: you can create war files that run in some container instead of jars that run their own http server (althought the easiest way to do that stupidly aot compiles your code, but fixing that takes an afternoon) |
| 18:41 | hiredman | speaking of which |
| 18:43 | hiredman | amalloy: I think we talked about lein-ring aot breaking stuff at some point, I made some changes to a fork and now it doesn't aot https://github.com/hiredman/lein-ring/commit/aa2f9ad12502e3502af03087f6bb2e72e850a917 |
| 18:43 | cespare | what if I put ^:skip-aot on my main |
| 18:44 | hiredman | cespare: why have a :main then? |
| 18:44 | hiredman | cespare: just leave it out of your project.clj |
| 18:44 | hiredman | use java -cp … clojure.main -m foo.bar to launch |
| 18:45 | cespare | ok, i'll give that a shot. |
| 18:45 | amalloy | hiredman: you must have a keyboard macro for "TODO: delete" |
| 18:45 | hiredman | I should |
| 18:46 | hiredman | it needs lots of clean up for a "release" but I did a lein install and have been using it for all the clojurebot bits that use lein ring |
| 18:48 | cespare | hiredman: where do I get the clojure jar to put on my cp if I'm using lein? |
| 18:49 | amalloy | java -cp `lein classpath` # lol |
| 18:49 | cespare | ah |
| 18:49 | hiredman | cespare: lein uberjar jars up all of a projects deps in to single jar |
| 18:49 | amalloy | well, the # lol is there because this is not really a great idea |
| 18:49 | hiredman | that includes clojure |
| 18:49 | amalloy | really you want the uberjar |
| 18:50 | cespare | separate issue, but yes we normally use uberjar. |
| 18:51 | hiredman | the uberjar includes clojure in it, including the clojure.main class |
| 18:52 | cespare | cool, got that working. |
| 18:52 | cespare | I think we'll be able to purge most of the aot. |
| 18:52 | cespare | thanks guys |
| 18:59 | bra | I'm working on tuning a clj application via visualvm and the sampler is telling me that clojure.lang.Keyword.hasheq is my most CPU-hungry hotspot. |
| 19:00 | bra | This is a bit surprising to me, since IIUC keywords are interned and their hashes are computed at construction time. |
| 19:00 | bra | Is there something I'm missing here? |
| 19:00 | danneu | been stuck with node for a while on client projects. found out about this a couple days ago https://github.com/koajs/koa -- finally made node bearable |
| 19:00 | hiredman | bra: are you processing json? |
| 19:00 | bra | hiredman: Nope. |
| 19:00 | hiredman | ah well |
| 19:00 | turbofail | are you doing anything else that might convert strings to keywords? |
| 19:01 | hiredman | bra: some other kind of deserialization? |
| 19:01 | bra | I don't believe I'm converting strings to keywords anywhere |
| 19:02 | bra | The primary hot loop is taking strings and a vec of [:keyword parser-fun] pairs and generating a map of {:keyword parsed-string-bit} |
| 19:02 | amalloy | hasheq doesn't suggest to me that he's creating keywords, but that he's comparing them |
| 19:02 | amalloy | or using them as keys in a large map, i guess is more like it |
| 19:02 | bra | Yep. |
| 19:03 | bra | Each map has ~36 keys, and I'm generating a few thousand per second in test. |
| 19:03 | hiredman | ah well, that makes sense |
| 19:04 | hiredman | the call to hash eq is a required part of sticking keys in the map |
| 19:04 | hiredman | bra: what version of clojure? |
| 19:04 | bra | hiredman: 1.5 |
| 19:04 | bra | 1.5.0 |
| 19:05 | amalloy | if the main thrust of your work is building large hashmaps, then no matter how fast hashing is, it will take a large part of your computational time |
| 19:05 | hiredman | 1.6 has some hashing changes, but I think those mainly effect the performance of hashing of collections |
| 19:06 | bra | Thanks all. |
| 19:06 | amalloy | you might be able to reduce the amount of rebucketing that goes on by creating the maps all in one go rather than incrementally? i'm not sure |
| 19:06 | hiredman | 1.6 may have a better distribution of hashcodes, but I am not sure, and I forget if that would even matter for keywords, they could just use the identity hashcode I think |
| 19:07 | amalloy | like, (apply hash-map (apply concat vec-of-kvs)) |
| 19:07 | bra | Would replacing my map with a record be a fruitful approach? |
| 19:07 | amalloy | not with 36 keys |
| 19:07 | bra | Ah, I'll test the all-at-once approach. |
| 19:07 | bra | kk |
| 19:08 | bra | Why does the key count affect the performance? |
| 19:08 | amalloy | records perform best for small numbers of keys, because they have no structural sharing |
| 19:08 | Bronsa | hiredman: IIRC in 1.6 keywords use the murmur3 hash of the internal strings rather than their .hashCode |
| 19:08 | hiredman | obviously you should partition the keys up and do the merges in parallel using fold |
| 19:09 | gfredericks | amalloy: neither do array-maps |
| 19:09 | amalloy | uh huh...? |
| 19:09 | bra | amalloy: FWIW these are never mutated after creation. It's all field accesses. |
| 19:10 | gfredericks | amalloy: I thought you were advocating for records over regular maps? |
| 19:10 | gfredericks | oh wait no |
| 19:10 | hiredman | bra: if it is a fixed set of keys, use a vector assign each key to a spot in the vector |
| 19:10 | gfredericks | you just meant records with a whole bunch of keys are bad? |
| 19:10 | amalloy | mhm |
| 19:11 | gfredericks | english! |
| 19:11 | hiredman | (you could even use a transient or array while building up the vector if you need too) |
| 19:12 | hiredman | if you aren't generating keywords it must be a fixed set I guess |
| 19:12 | amalloy | or just use an array as the canonical store. light speed! |
| 19:12 | hiredman | *zoom* |
| 19:13 | amalloy | then of course you'll have to write (case k :foo (aget arr 0) :bar (aget arr 1)) and so on, and you'll probably pay for hasheq in the case dispatch |
| 19:13 | bra | :D |
| 19:13 | hiredman | amalloy: write a macro that translates the keywords to numbers for you |
| 19:13 | bra | Right, I was a bit concerned about the API there. |
| 19:13 | bra | Macro might be useful. Hm. |
| 19:14 | amalloy | hiredman: ztellman/vertigo. go big or go home |
| 19:14 | hiredman | amalloy: sure |
| 19:30 | cj3kim_ | Hi. I've been trying to require code in lein, but I've been having trouble. Here's a gist with the relevant description and files https://gist.github.com/anonymous/39f3a8148eeba430db14 |
| 19:31 | noonian | cj3kim_: there are a few problems, firstly you should only have one require form in a ns form, and you should use the keyword :require instead of the function require |
| 19:31 | hiredman | ~namespaces |
| 19:31 | clojurebot | namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it |
| 19:32 | noonian | i would also guess that the namespace you are trying to require is gaussian.elimination and then you want to refer to the functions gaussian and vector |
| 19:32 | noonian | oh, nvm i didn't see the other files |
| 19:33 | amalloy | noonian: you can have multiple requires in a namespace |
| 19:33 | noonian | yeah, try merging the multiple use and require statements i.e. (:use [gausian.elimination.matrix] [gausian.elimination.vector] ...) |
| 19:33 | amalloy | it's not stylistically popular, but it's equivalent |
| 19:33 | noonian | hmm, i didn't know, but surely it's not idiomatic |
| 19:33 | cj3kim_ | hmmr |
| 19:34 | amalloy | the problem is not in his ns statements, but probably in where he's put the files |
| 19:35 | noonian | yeah, it cant find gaussian, that would also happen if it is failing to compile |
| 19:36 | cj3kim_ | noonian: how do I know if it's failing to compile? And, what can I do to compile it? |
| 19:37 | noonian | if you have a repl open, i would try evaluating (require 'gaussian.elimination.gausian :reload) and see if you get an error or not |
| 19:38 | cj3kim_ | I ran it and it returned a "FileNotFoundException" |
| 19:38 | cj3kim_ | noonian: |
| 19:38 | amalloy | why do you have a file named core.js which contains clojure code? and where is promethix.core? |
| 19:38 | noonian | what is the directory structure and file names of your source tree? |
| 19:39 | cj3kim_ | A moment please. Need to type stuff out in a gist |
| 19:40 | noonian | gaussian.elimination.gaussian should be at path src/gaussian/elimination/gaussian.clj with the leiningen default src paths |
| 19:40 | cj3kim_ | noonian: I am using lighttable, an editor, as well. C |
| 19:40 | noonian | also, which file is the filenotfoundexception for? if it's a different source file of yours then your should try requiring that one |
| 19:41 | cj3kim_ | noonian: Copy/pasting all relevant info to a gist. :) |
| 19:43 | cj3kim_ | noonian: https://gist.github.com/cj3kim/abac1f85ce1b4cb50af8 |
| 19:44 | hiredman | https://github.com/LightTable/LightTable/issues/1520 learning clojure using lighttable seems like it would be hell |
| 19:45 | cj3kim_ | hiredman: what would you recommend in its stead? |
| 19:45 | amalloy | cj3kim_: whatever text editor you're already comfortable with |
| 19:45 | amalloy | and lein repl |
| 19:46 | hiredman | preferably something that has some kind of mode where it will help you match up brackets, but that is not a strict requirement |
| 19:47 | nullptr | yeah, i think show-paren-mode is sufficient when you're starting -- paredit would be a bit much for a newbie |
| 19:50 | amalloy | cj3kim_: everything there seems okay (except you misspelled gaussian in your repl example) |
| 19:50 | amalloy | you'd probably have had an easier time just pushing the whole git repo for someone else to repro with |
| 19:51 | noonian | cj3kim_: (require 'gaussian.elimination.gausian :reload) you mispelled gaussian gausian |
| 19:51 | noonian | i was using light table for a while but using lein repl for the repl |
| 19:54 | amalloy | noonian: that's true, but it's also breaking in his ns clause, where it *is* spelled correctly, so i'd guess his dependencies are not present somehow |
| 19:55 | amalloy | like maybe you haven't restarted your repl since adding the dependency? but i have no idea what light table does automatically for you |
| 19:56 | DomKM | Anyone know why protocols are typically prefixed with `I`? Is this because of their similarity to Java interfaces? |
| 19:57 | amalloy | that is why, DomKM. but it's not a universal convention; you're free to ignore it |
| 19:57 | amalloy | (just like prefixing java interfaces with I isn't universal) |
| 19:58 | DomKM | amalloy: cool, thanks. |
| 19:58 | noonian | amalloy: i agree, i asked him to require it by hand to see if one of that files deps was missing |
| 20:07 | cj3kim_ | noonian: amalloy: Thanks for the help |
| 20:15 | ttasterisco | hm, prefixing java interfaces with I was never the norm. that's from .net |
| 20:15 | ttasterisco | java interfaces were always -able |
| 20:16 | systemfault | List…able? :P |
| 20:16 | ttasterisco | Runnable |
| 20:16 | ttasterisco | Callable |
| 20:16 | ttasterisco | Iterable |
| 20:16 | ttasterisco | etc |
| 20:17 | amalloy | ttasterisco: it leaked in from .net |
| 20:17 | amalloy | it's not used in the jdk itself, but lots of people who write java do it |
| 20:17 | ttasterisco | damn migrants |
| 20:17 | ttasterisco | burn them |
| 20:17 | bbloom | Bronsa: now i'm all self-conscious screwing up and force pushing on public repos :-P |
| 20:17 | amalloy | how dare they force their lambdas on us |
| 20:18 | bbloom | i usually abuse the crap out of my own fork, but now i have observers.... |
| 20:18 | amalloy | bbloom: your nick is confusing to type. double-single-double? i propose you change your last name to Blloom |
| 20:19 | bbloom | amalloy: does bb<tab> not handle it? |
| 20:19 | amalloy | well, i actually do bbl<tab> |
| 20:19 | amalloy | but this time i was doing a google search to see if i could guess what repo you were talking about |
| 20:19 | bbloom | so does some random guy in #ruby, who has never actually talked to me, but mentions me with some regularity |
| 20:20 | cj3kim | amalloy: noonian: pushed to git for help. https://github.com/cj3kim/promethix |
| 20:20 | Bronsa | bbloom: oh just ignore me. if it makes you feel better I screw up a lot on t.a/t.a.j and I cannot even force push because of autodoc |
| 20:20 | cj3kim | noonian: my general feeling is gaussian_elimination isn't compiling |
| 20:21 | bbloom | Bronsa: not just you, but you made me aware of the audience |
| 20:21 | amalloy | cj3kim: version 1.0.0 of gaussian_elimination chooses to call its namespaces gaussian_elimination.gaussian |
| 20:21 | amalloy | rather than what's on github, which is gaussian.elimination.gaussian |
| 20:21 | cj3kim | amalloy: how do you know this? |
| 20:22 | amalloy | i opened up the jar and read it |
| 20:22 | cj3kim | and how can i check in the future? |
| 20:22 | amalloy | are you sure you want to use this library? it looks pretty slapdash |
| 20:22 | Bronsa | bbloom: then I'll pat my back for being successful in screwing you up. pushing will never feel the same |
| 20:22 | bbloom | Bronsa: i'm super careful when specifying what-to-push-where, but when i work on my own tracked branch, i view the server as a backup & push constantly |
| 20:23 | cj3kim | ah, i see. thank you |
| 20:24 | amalloy | cj3kim: it looks like https://github.com/skatenerd/gaussian_elimination/tree/358e9e9cb3c8c6f40b4684550c854874f3860173 is the code you are actually using |
| 20:24 | cj3kim | amalloy: oh my god >_> |
| 20:24 | amalloy | hm? |
| 20:25 | cj3kim | my friend had downloaded an older version of that library which used all dots instead of the underscore |
| 20:25 | cj3kim | i just wasted three hours! |
| 20:25 | amalloy | i don't think your friend's download is relevant? that jar is being fetched from maven |
| 20:26 | amalloy | and dots are actually the "latest" code (ie, two years old), which he hasn't ever released to maven (but it's the latest git) |
| 20:26 | cj3kim | we used this code <-https://github.com/skatenerd/gaussian_elimination/blob/master/src/gaussian/elimination/gaussian.clj |
| 20:27 | cj3kim | thanks for your ehlp |
| 20:27 | amalloy | right. that code is newest, not older |
| 20:27 | amalloy | and he just never released it |
| 20:28 | amalloy | anyway, have fun. it looks like the author probably knows his math but doesn't know his clojure |
| 20:28 | bbloom | i think "meth" is my new favorite symbol |
| 20:29 | amalloy | bbloom: if you've been doing meth i need to tell you it's not just a symbol, it is an addictive and dangerous drug |
| 20:29 | amalloy | see, eg, the AMC documentary Breaking Bad |
| 20:31 | bbloom | amalloy: saw that. stellar investigative journalism. i need to figure out how to get out of the meth business and in to that empire business thing |
| 20:34 | cespare | If i no longer have a :main, is there another way to specify the starting point for my lein repl? |
| 20:34 | cespare | starting namespace I mean |
| 20:34 | hiredman | there is no such thing as a starting namespace |
| 20:35 | noonian | if you have a user namespace on the classpath it will use that though |
| 20:35 | hiredman | noonian: you keep answering a question that is slightly different then the asked one |
| 20:36 | noonian | in this case i don't know the answer |
| 20:36 | cespare | hiredman: seems to me you very likely understand what I'm asking |
| 20:36 | hiredman | cespare: sure, you want lein to require and in-ins in to a given namespaces when you run lein repl |
| 20:37 | cespare | sounds about right, if that's what it does when you do :main myproj.core |
| 20:37 | cespare | is there another way to ask lein repl to do that? |
| 20:37 | ttasterisco | cespare: in there repl, there's no "main". if you mean when doing `lein run`, then you can use the -m |
| 20:37 | hiredman | cespare: I would suggest either you'll be in an editor, and evaluating the file at hand in the editor will in-ns the repl's state to the same namespace |
| 20:38 | ttasterisco | *the |
| 20:38 | cespare | hiredman: Yep, that's true 95% of the time. The other 5% it's convenient for the repl to automatically load the main namespace. |
| 20:38 | hiredman | cespare: why? |
| 20:38 | cespare | it's not a big deal, just wanted to know if there's a workaround, now that I'm removing :main from all my projects. |
| 20:39 | hiredman | cespare: how likely is it that you are going to be using stuff in the main namespace? |
| 20:39 | cespare | quite likely, if i'm just playing around a bit. |
| 20:39 | hiredman | cespare: sure you could use something like the repl-init options |
| 20:39 | cespare | i've been writing clojure for the past 9 months or so, and I know from experience that it's something I occasionally want to do. |
| 20:40 | cespare | hiredman: there we go. |
| 20:40 | cespare | I see :repl-options { :init-ns foo.bar } |
| 20:40 | hiredman | in my experience using lein run means I am doing performance testing of some functionality of one particular namespace on an ec2 node |
| 20:41 | hiredman | so I would have in-ns to the particular namespace anyway to start fiddling with it |
| 20:41 | synkte | What's the best way to seed a database in clojure? |
| 20:41 | amalloy | cespare: try `lein help sample` next time you are looking for some lein feature |
| 20:42 | amalloy | (this is the same as leiningen's sample.project.clj on github, so you can look there instead if you prefer) |
| 20:42 | cespare | hiredman: sure, understood. It's just that starting out in a commonly used namespace of my project is better than not |
| 20:43 | hiredman | cespare: I think lein doing that kind of thing encourages people to form incorrect ideas about namespaces as something that contains in some way the execution of code |
| 20:43 | TimMc | cespare: If you still need a main entrance point but don't want AOT, I wrote lein-otf a while back. |
| 20:44 | tuft_ | cespare: the trick i'm using is creating a user.clj in the project that's just a bunch of requires, if we're talking about the same thing |
| 20:44 | cespare | TimMc: hey, neat! |
| 20:46 | TimMc | cespare: You can do the same trick yourself with less infrastructure (just have a tiny AOT'd main ns that dynamically requires your real entrance point and calls it) but lein-otf is a drop-in. |
| 20:47 | TimMc | I actually don't know if I'd use lein-otf myself these days; it adds a potential complexity cost to the project and an explicit approach + plenty of comments might be better. |
| 20:48 | cespare | I think I'm just gonna go with the clojure.main -m ... approach for now. |
| 20:49 | cespare | Is there some PSA about AOT causing all kinds of problems that I've somehow missed since starting to use clojure? |
| 20:50 | noonian | getting burned by AOT is a clojure right of passage |
| 20:50 | TimMc | No kidding. |
| 20:52 | hiredman | https://groups.google.com/forum/#!topic/clojure/Bs70_PUj-TY is maybe the first anti aot screed, a bit dated by now I am sure |
| 20:53 | hiredman | https://groups.google.com/d/msg/clojure/Bs70_PUj-TY/azR1gNleT_oJ good for a chuckle |
| 20:58 | cgag | i'm using clojurescript and trying to do the equivalent of rangy.createRange() by doing (.createRange js/rangy), but running into undefined is not a function am i doing something obviously wrong? |
| 20:59 | TimMc | hiredman: The C-in-C bit? |
| 21:00 | bbloom | Bronsa: have you found a need to differentiate let and loop bindings at all? |
| 21:01 | bbloom | Bronsa: for eclj i differentiate between locals via let, jvm classnames, and of course vars... i haven't needed to differentiate let & loop at all, but i definitely need to figure something out for object fields |
| 21:02 | bbloom | Bronsa: for that, i'm torn between (symbol-macrolet [x (.-x this#) ... and true fields support |
| 21:02 | ddellacosta | cgag: is rangy getting pulled in properly? |
| 21:02 | bbloom | Bronsa: but seems like loop is just a shorthand for fn really, if you have tail calls like i do |
| 21:03 | Bronsa | bbloom: in ta every local has a :local field that indicates where it comes from |
| 21:03 | Bronsa | bbloom: uhm, there are some differences between loop/fn locals wrt type hints & primitive support |
| 21:03 | bbloom | Bronsa: hm, interesting |
| 21:04 | Bronsa | bbloom: not sure if that is a problem at all but fn args can only be long/double primitives while loop/let locals can be whatever primitive type you want |
| 21:04 | bbloom | i was looking at :local, but noticed loop & let seemed to mostly follow the same code paths |
| 21:05 | Bronsa | bbloom: yeah I think in tej we never need to differenciate between :let/:loop locals |
| 21:05 | bbloom | Bronsa: that's good to know, thanks. doesn't affect my environments, but will affect me when i get to the compiler |
| 21:05 | Bronsa | but I'm not 100% sure, let me check |
| 21:05 | bbloom | (hints, i mean) |
| 21:06 | cgag | ddellacosta, now that I'm trying to use it with just pure js I'm not as confident as I was. The code fails in my test.js file fails even though it runs in the console, don't think it's clojurescript related anymore. |
| 21:06 | ddellacosta | cgag: ah, okay. That happens too. But it sounds to me like rangy wasn't getting pulled in properly, perhaps. |
| 21:10 | bbloom | Bronsa: luckily, i don't have to abide by the rules for eclj, so i'm going to implement symbol-macrolet & use that for fields :-) |
| 21:10 | Bronsa | bbloom: yeah I checked, I never need to differenciate between :loop and :let locals |
| 21:10 | bbloom | Bronsa: cool |
| 21:11 | bbloom | Bronsa: any crazy thing about field symbols i should know? or is (intelligently) replacing foo with (.-foo this#) seem sane? |
| 21:11 | Bronsa | bbloom: I was just thinking about that. |
| 21:11 | Bronsa | oh yeah |
| 21:11 | Bronsa | bbloom: you cannot (set! (.-foo this#) bar) I believe |
| 21:12 | Bronsa | I might be wrong on that one though |
| 21:13 | Bronsa | bbloom: oh you indeed cannot but that's a compiler bug that I submitted a patch for, lol |
| 21:13 | bbloom | heh |
| 21:13 | Bronsa | nothing else comes to mind then |
| 21:14 | bbloom | ,(deftype A [x]) |
| 21:14 | clojurebot | sandbox.A |
| 21:14 | bbloom | ,(.x (A. 1)) |
| 21:14 | clojurebot | 1 |
| 21:14 | bbloom | ,(deftype A [^:unsynchronized-mutable x]) |
| 21:14 | clojurebot | sandbox.A |
| 21:14 | bbloom | ,(.x (A. 1)) |
| 21:14 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: x for class sandbox.A> |
| 21:14 | bbloom | ^^ interesting.... |
| 21:14 | Bronsa | bbloom: yeah mutable fields are private |
| 21:14 | bbloom | makes sense, but i didn't think rich believed in encapsulation :-P |
| 21:15 | Bronsa | bbloom: mh if you use symbol-macrolet I belive shadowing will be problematic? also using the symbol in macros |
| 21:15 | bbloom | Bronsa: that would be an issue if symbol-macrolet was a macro, but i'm going to implement it in the interpreter |
| 21:16 | Bronsa | bbloom: probably a better approach would be replacing the field at macroexpansion time |
| 21:16 | bbloom | Bronsa: there really isn't a "macro expansion time" in eclj |
| 21:16 | bbloom | it's interleaved with evaluation |
| 21:16 | bbloom | the assumption is that macros are pure & terminate |
| 21:17 | Bronsa | I wish I could make the same assumption for clojure macros |
| 21:17 | bbloom | again, i have the benefit of not having to follow the rules :-) |
| 21:17 | Bronsa | I have to do crazy things like rebuilding the entire namespace map every macroexpansion because somebody could intern vars at macroexpansion time |
| 21:17 | Bronsa | and midje actually does it. |
| 21:18 | bbloom | you're trying to match jvm/clj proper, i'm aiming for rough source-level compatability for idiomatic code |
| 21:18 | bbloom | lol fucking midje |
| 21:18 | Bronsa | that's exactly what I thought |
| 21:19 | bbloom | interning happens via an effect in my system, so i can intercept it |
| 21:19 | bbloom | i implement the dynamic nature of namespaces, but via continuations |
| 21:19 | bbloom | another luxury you don't have :-) |
| 21:19 | bbloom | but then again, your stuff is actually useful |
| 21:19 | bbloom | so there's that :-P |
| 21:20 | Bronsa | bbloom: me and ambrose were wishing clj namespaces were IRefs a while ago |
| 21:20 | bbloom | and setting fields with (.-whatever works fine for me. so macrolet it is! |
| 21:20 | bbloom | Bronsa: for watches? |
| 21:20 | Bronsa | yep |
| 21:20 | bbloom | would be nice |
| 22:03 | akurilin | Quick prismatic schema question: is there a way of enforcing values of map keys being not nil outside of using predicates? As in, say I specify {:foo [{:bar "baz}]} as schema, {:foo nil} will validate correctly for some reason |
| 22:17 | bbloom | Bronsa: amusingly, see the "Notes:" here: http://www.lispworks.com/documentation/lw61/CLHS/Body/s_symbol.htm |
| 22:18 | bbloom | "The special form symbol-macrolet is the basic mechanism that is used to implement with-slots." |
| 22:18 | bbloom | with-slots is basically what i want for fields |
| 22:18 | bbloom | everything old is new again :-P |
| 22:18 | trptcolin | the HyperSpec - that’s pretty intense |
| 22:19 | bbloom | if you're going to implement something, you gotta do your homework :-) |
| 22:20 | trptcolin | :) that’s why i went straight to ztellman’s github when i decided to write a little code-walking macro for this book |
| 22:21 | trptcolin | not that this little faux-library is a comparable effort to what you’re undertaking ;) |
| 22:25 | Jaood | trptcolin: are you writing a book about clojure? |
| 22:25 | trptcolin | Jaood: yeah, macros specifically |
| 22:26 | Jaood | oh nice |
| 23:33 | mlakewood | Hi all. I just stumbled across component https://github.com/stuartsierra/component |
| 23:33 | mlakewood | it feels like this might have some overlap with Protocols etc. could somebody explain the differences? |
| 23:44 | trptcolin | mlakewood: component is built on top of a protocol: https://github.com/stuartsierra/component/blob/030fe57eeb2f1ac0d0675d420db9614b78ecc857/src/com/stuartsierra/component.clj#L4-L12 |
| 23:44 | mlakewood | Oh ok. thats good to know. Thanks! |
| 23:47 | Frozenlock | Oh Gooood. Less than one week away from the Canada's Anti-Spam Legislation. |
| 23:48 | Frozenlock | Why can't these lawmakers STOP making new laws? They just screw up anyway. |
| 23:57 | boltR | is there a way to throw an exception using fnil? |
| 23:57 | boltR | (fnil inc (throw (Exception. "foo"))) |
| 23:58 | boltR | or can I only use an if-else for throwing exceptions |
| 23:59 | dbasch | boltR: you can throw exceptions anywhere, but I fail to grasp why you would want to use fnil for that |