#clojure logs

2015-05-25

00:23bluesnowWhat is a tuple in Clojure? My book Programming Clojure mentions "tuples" but they don't seem to be an actual data structure type
00:47lokebluesnow: a "tyuple" normally is a fixed set of values
00:47lokeI mean tuple
00:48bluesnowah I see. okay, thanks.
00:48amalloywell, a fixed-size collection
00:48lokeYou might want to read this, if you want to gritty details: https://en.wikipedia.org/wiki/Tuple
00:50bluesnowloke: cool. I'll take a look at that page.
00:56jtmarmonis there a way to do an "unquote"/"unquote-splicing" within a regular quoted statement instead of within a backtick? if not, why not?
00:59bbloom~backtick
00:59clojurebotCool story bro.
00:59bbloomjtmarmon: no, but:
01:00bbloomhttps://github.com/brandonbloom/backtick
01:00bbloomyou can use the "template" function
01:00bbloomalthough the use cases are pretty esoteric
01:00bbloomtemplate *macro* i mean
01:01jtmarmonduude nice
01:01jtmarmon(inc bbloom)
01:01lazybot⇒ 55
01:01jtmarmonalso I've noticed the clojure community really likes the word complect
01:02bbloomturns out to be a useful word :-P
01:02jtmarmonif datomic sells to fb rich hickey will buy a league of legends team and name it complecsity
01:02jtmarmon(http://lol.gamepedia.com/CompLexity_Gaming)
01:03bbloomnone of those things seem likely.
01:04jtmarmonfyi @bbloom - use case is for datomic queries. I have a bunch of optional boolean flags to pass as inputs to the query
01:04bbloomhuh?
01:04bbloomsomebody can probably suggest a more straightforward approach if you gist some code
01:05jtmarmonok so example:
01:07jtmarmondating site where you can filter by food preference. i want suiters to be able to only look at potential suitors who like pizza. so the datomic statement might be [?person :person/likesPizza true] but only if that flag is there. otherwise no filtering
01:07jtmarmonlol i used suitors twice and once incorrectly. (inc 2am)
01:07bbloomcan't you just concatenate some clauses?
01:08jtmarmonoh
01:08jtmarmonyeah
01:08bbloomstart with some base query and conj on additional clauses
01:08jtmarmonhow do oyu do that clojurebot thing again
01:08bbloom(let [query ..., query (if (some? pizza) (conj query '[?person :person/likesPizza true) query), ....
01:09bbloom(let [query ..., query (if (some? pizza) (conj query '[?person :person/likesPizza true]) query), .... ; add missing ]
01:09jtmarmonokay yeah you're totally right
01:09bbloomthat's kinda half the damn point for the design of datomic's query syntax :-)
01:09jtmarmoni just didn't consider that because it's quoted. still working on getting into the whole "nothing is special (usually)" style of programming
01:10bbloomalso, rather than making one attribute per food, you should use just make :person/likes a cardinality many attribute
01:10jtmarmonyeah bad example. i swear i'm not starting a food related dating site
01:10jtmarmonalthough not a bad idea...
01:11bbloom(reduce (fn [query thing] (conj query ['?person :person/likes thing])) initial-query likes)
01:11bbloomtada: tag filters!
01:11bbloomdoesn't get simpler than that
01:11jtmarmondang
01:11jtmarmonthat's perty
01:12jtmarmonman i actually went to sql from mongodb and i really hated dealing with strings so it's nice to be back :D
01:12jtmarmoner sorry, mongodb -> sql
01:12bbloommongo's queries have atrocious composition properties
01:12bbloomi mean, better than sql strings, but still pretty awful
01:13jtmarmonyeah well they try to stuff everything into objects. it's all...complected...
01:13jtmarmone.g. {thing: {$qualifier: and {thing: {field
01:14bbloomit's certainly complicated, but you can't say complected unless you specify which two or more things are complected together :-)
01:15bbloombut yes, the distinction between lists and vectors is very useful for separating meta syntax from more general use of sequences
01:15bluesnowWhat does something like (:customer %) or (:total %2) mean in Clojure?
01:16bbloombluesnow: https://yobriefca.se/blog/2014/05/19/the-weird-and-wonderful-characters-of-clojure/
01:16bbloomalso http://clojure.org/reader
01:19bluesnowbbloom: ok, thanks for the references
01:54bluesnowOkay, I have a question about something in my clojure book. It does (def flat-breakup {["Wile Coyote" "Anvil"] 900, ["Elmer Fudd" "Anvil"] 300})
01:54bluesnowThen it does (reduce #(apply assoc-in %1 %2) {} flat-breakup)
01:54bluesnowIt says that this will result in assoc-in being called thus - (assoc-in {} ["Wile Coyote" "Anvil"] 900)
01:55bluesnowI'm wondering why the above happens instead of (assoc-in {} [["Wile Coyote" "Anvil"] 900])
01:55bluesnowWhy are the [k v] for a map entry being separated out into k v when assoc-in is called?
02:10noidibluesnow, it's the apply
02:11noidi(apply f [a b c]) = (apply f a b c)
02:11noidisorry
02:11noidi(apply f [a b c]) = (f a b c)
02:16bluesnownoidi: Ah okay, thanks.
02:22bluesnowAlso quick question about the documentation for apply
02:23bluesnowIt says that the arguments for apply could look like [f a b c d & args]
02:23bluesnowWhat does the & symbol mean?
02:23bluesnow(It says that the options for calling apply are [f args], [f x args], [f x y args], [f a b c d & args]
02:24bluesnowI'm not sure how the & symbol makes the last option different from [f x y args]
02:34noidithe & symbol means that the function can take extra arguments in addition to the required ones named before the &
02:35noidithe sequence of extra arguments is assigned the name after the & (in this case "args")
02:35noidi,((fn [x y & args] [x y args]) 'a 'b 'c 'd 'e 'f)
02:35clojurebot[a b (c d e f)]
02:36bluesnownoidi: Uh hmm. Okay, I'm not sure I see why this is a separate option in the case of apply
02:37bluesnowI thought apply took [f x y z .. (as many single args as desired) args (where args is a vector of args)]
02:38Empperiapply takes a list of arguments
02:38Empperi,(doc apply)
02:38clojurebot"([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."
02:39Empperithere is only a limited amount of function declarations for apply where it takes arguments all by themselves
02:39Empperithe last one is a vararg version, which works nice due to that
02:40bluesnowEmpperi: Still confused unfortunately. In the first option, [f args], isn't args a vector?
02:41Empperiyes, let me give you an example
02:41Empperi,(apply + [1 2 3])
02:41clojurebot6
02:42Empperi,(apply + 1 [1 2 3])
02:42clojurebot7
02:42Empperi,(apply + 1 2 [1 2 3])
02:42clojurebot9
02:42Empperiand so forth
02:42bluesnowright
02:42bluesnowI understand that
02:42Empperithe way apply works is that the last argument has to always be a seq
02:42bluesnowyeah
02:42Empperiand that's what it's documentation says: "Applies fn f to the argument list formed by prepending intervening arguments to args."
02:42bluesnowright, I understand that part of the doc
02:43Empperiok, so your confusion was about?
02:43bluesnowWait so is [f a b c d & args] saying that we can have as many single args as we want, and then we can put all the rest of the args into the vector?
02:44bluesnowI was confused about what the & in [f a b c d & args] meant
02:45bluesnowSo the & in [f a b c d & args] says that we can put as many remaning arguments into the vector args as we want?
02:46Empperiit means there can be any number of intervening arguments before the last argument which has to be a seq
02:46bluesnowoh okay, that makes sense. Someone else explained it differently above.
02:47Empperiwell, he was right in what he said
02:47Empperibut that's how apply works under the hood
02:47Empperithe way & works is that it means "0-n arguments in here"
02:48bluesnowright
02:48Empperiapply just digs the last argument out of that, uses that as a seq and ensures that all the intervening arguments are prepended to that seq
02:49Empperiif you look at the source code of apply you see what I mean
02:49Empperihttps://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L623
02:49bluesnowYeah, the part he said that confused me was "the sequence of extra arguments is assigned the name after the & (in this case "args")"
02:49Empperinotice the call to "spread"
02:49Empperiyeah, well he was right :)
02:49bluesnowI didn't see why the sequence of arguments would be assigned the name "args"
02:49Empperibut it's just the starting point for the internal logic of apply
02:50Empperiit's because it's named as 'args'
02:50Empperisee the source code
02:53bluesnowEmpperi: Oh I see. I'm pretty new to Clojure, but from what I can tell, the rest of the arguments after a b c d are added by spread to the args vector
02:53bluesnowI'm having trouble reading some of this code. Just started learning Clojure
02:53Empperino problem dude, happy to help :)
02:54Empperithe way apply works and why it exists in core, is that it allows you to call functions dynamically with variable amount of arguments
02:54Empperiif you didn't have apply you'd have to always know the amount of arguments when calling your function
02:55Empperiwhich would force you to require people to pass in seqs
02:55Empperiso apply is very often used with functions which have variable arguments
02:55Empperi+ is a great example
02:55Empperi,(+ 1 2 3 4 5)
02:55clojurebot15
02:55Empperiworks
02:55Empperibut so does this
02:55Empperi,(apply + [1 2 3 4 5])
02:55clojurebot15
02:55Empperiand this
02:56Empperi,(apply + (range 1 6))
02:56clojurebot15
02:56bluesnowEmpperi: Right. I have one more question about something in the docs. The docs say that the argument list for assoc-in is ([m [k & ks] v])
02:56Empperiyou'd have to have a separate version of + which would accept seqs or add additional logic into it which would check if the argument is a seq to make that last example work
02:56Empperiwithout apply
02:56bluesnowwhere ks is a sequence of keys
02:57Empperiyeah, lol. assoc-in is a confusing one
02:57Empperiupdate-in is even more so lol
02:57Empperibut yeah, assoc-in uses a lisp functionality called destructuring in it's function declaration
02:57Empperiassoc-in is called like this:
02:58bluesnowso based on that doc, I thought that when I did (assoc-in {} [:a :b (seq [:c :d])] 5) I would get {a: {b: {c: {d: 5}}}}
02:58Empperi,(assoc-in {} [:foo :bar] 1)
02:58clojurebot{:foo {:bar 1}}
02:58bluesnowright
02:58Empperiwhat it does is that it'll receive the second argument and destructures that
02:58Empperiby the destructuring rules, which in this case is [k & ks]
02:58bluesnowEmpperi: But based on the docs, I thought it could be (assoc-in {} [:foo :bar (seq [:foo_again :bar_again])] val)
02:59Empperiyou're confusing this with apply
02:59Empperiapply works exactly the same but with the difference it does it's own magic inside the function
02:59bluesnowyeah, the way the docs are written, is [k & ks] supposed to be a vector?
02:59Empperiwhen your call to apply is done, it's exactly the same in the beginning
02:59Empperiit can be any seq
02:59bluesnowright
03:00Empperi(assoc-in {} '(:a :b) 1)
03:00Empperi,(assoc-in {} '(:a :b) 1)
03:00clojurebot{:a {:b 1}}
03:00bluesnowbut based on the docs, it seems like ks could be another seq nested inside that seq
03:00bluesnowsince the docs say it's [k & ks], so it looks like a variable number of individual keys followed by another nested sequence ks
03:00Empperinot really, nesting is something actually why assoc-in exists :)
03:00Empperiyou have assoc for non-nested cases
03:00Empperi,(assoc {} :foo 1)
03:00clojurebot{:foo 1}
03:01bluesnowhmm okay. I'm just trying to figure out why the docs are written that way so I can read the docs correctly
03:01EmpperiI think you should read about clojure destructuring
03:01bluesnowWhy do they write it as [k & ks] if they don't mean that the ks can be a nested seq?
03:01Empperiit is it's own little mini language
03:01bluesnowEmpperi: I've read a bit about clojure destructuring
03:02Empperi[k & ks] means, you'll have to provide at least one key but you can provide as many as you wish
03:02Empperi[& ks] would mean 0-n
03:02bluesnowright
03:02bluesnowBut why not write it as [k & last_key], to make it clear that the last argument should be an individual key, not a nested seq?
03:03bluesnowThey say that "ks" is a sequence of keys, so that seems like it would be a seq nested inside the first seq
03:03Empperiwell, ks/last_key can contain multiple keys
03:03Empperiso 'last-key' would be a bit misleading, don't you think?
03:03bluesnowWhy would it be misleading? since we have the & in between k and last_key, then it seems clear that we could have 1-n keys
03:03Empperibut you don't see the & inside the function
03:04Empperinot unless you look at the function parameter declaration
03:04Empperieg. (doseq [k last-key] (println k)) would look totally wierd naming wise
03:04Empperiweird
03:05bluesnowEmpperi: Oh hmm, ok. I think it might look weird to me since I'm only looking at the docs
03:05Empperiit's one of the naming conventions in clojure which is all over the place
03:05bluesnowIe, I'm entirely reading the docs without looking at the source code, which might be why the docs seem written in an odd way
03:05bluesnowokay, sounds good
03:05Empperiyou usually don't have to look at the source code
03:06EmpperiI like to read them though to give me a better understanding of how stuff works under the hood
03:06bluesnowEmpperi: Right, got it. So, if the doc writers had actually meant for ks to be a nested seq inside the first seq, how would they have written that?
03:07Empperiyeah, see eg. https://clojuredocs.org/clojure.walk/postwalk
03:07Empperithat function works with nested data structures
03:08bluesnowI see
03:09bluesnowhmm okay, thanks
03:10Empperinp
03:10Empperihappy to help
05:22justin_smithit's called ks because & only creates seqs
05:22justin_smith[k & [next-key]] would also make sense
05:22justin_smithbut there is not destructuring that would give you last-key
05:25currento_
05:39ConfusionThis seems a bit weird: ArityException: Wrong number of args (-2) passed to: Symbol
05:39ConfusionIs this a bug in the error message?
05:39justin_smithConfusion: iirc this is a bug in error messages for macros
05:39justin_smith,(or)
05:39clojurebotnil
05:39Confusionack
05:39justin_smith,(and)
05:39clojurebottrue
05:39justin_smithhmm
05:40justin_smith,(for [i (range)])
05:40clojurebot#error {\n :cause "Wrong number of args (1) passed to: core/for"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/for"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6636]}]\n :trace\n [[clojure.lang.Compiler macroexpand1 "Compiler.java" 6636]\n [clojure.lang.Compiler macroexpand "Compiler.java" 6702]\n [clojure.lang.Compiler eval "...
05:41justin_smith,(#'for [i (range)])
05:41clojurebot#error {\n :cause "Unable to resolve symbol: i in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: i in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: i in this context"\n ...
05:41justin_smith,(#'for [])
05:41clojurebot#error {\n :cause "Wrong number of args (1) passed to: core/for"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/for"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.lang.Var invoke "Var.java" 379]\n [sandbox$eval114 invoke "NO_...
05:41justin_smithnever mind, I thought I remembered how to make that happen, clearly I don't
05:42ConfusionIf I figure out what causes it without rewriting the lot, I'll let you know :)
06:04crocketClojure, the king.
06:25ionthas_is there a elegant way to generate a vector like this? [1 0 1 0 1 0 1]. Right now I'm using loop recur.
06:26ronh-ionthas_ take + cycle?
06:26kaiyin,(interpose 0 (repeat 1))
06:26clojurebot(1 0 1 0 1 ...)
06:27kaiyinionthas_: ^
06:27ionthas_wow, that's a neat way to do it kiyin
06:27ionthas_kaiyin, thanks
06:27ronh-,(cycle '(1 0))
06:27clojurebot(1 0 1 0 1 ...)
06:28crocket,(doc interpose)
06:28clojurebot"([sep] [sep coll]); Returns a lazy seq of the elements of coll separated by sep. Returns a stateful transducer when no collection is provided."
06:28crocket(take 5 (interpose 0 (repeat 1)))
06:28crocket,(take 5 (interpose 0 (repeat 1)))
06:28clojurebot(1 0 1 0 1)
06:33crocketWhy does (commute) execute once in a transaction and once after the transaction?
06:33crocketdoesn't make sense.
06:40crocketAh, I get it
06:57crocketWhat does '#' do in #'+?
06:57crocketVery mysterious.
07:00TMA,#'+
07:01clojurebot#'clojure.core/+
07:01TMA,'+
07:01clojurebot+
07:01TMA,+
07:01clojurebot#object[clojure.core$_PLUS_ 0x55e37a06 "clojure.core$_PLUS_@55e37a06"]
07:14amalloy,(quote #'+)
07:14clojurebot(var +)
07:38ConfusionI have a macro (defmacro run [expr] `(inc ~expr)). This works fine: (run (+ 1 1)) returns 3. But the arguments I actually have are already unevaluated lists. I can't seem to figure out how to make the macro that makes (run (list + 1 1)) return 3. Is this indeed tricky or am I overlooking something simple?
07:39bendlasConfusion: that's the reason you let-bind input expressions in a macro, to ensure single-evaluation: (defmacro run [expr] `(let [expr# ~expr] (inc expr#)))
07:40bendlasConfusion: oh sorry, misread the question
07:41bendlaswhat you want in this case is actually to call eval from the macro
07:41bendlas(defmacro run [expr] `(inc ~(eval expr)))
07:42bendlasjust beware, that the expression will be evaluated at compile time
07:42bendlasof course, you could also expand to a call to eval, to evaluate it at run time
07:43bendlas(defmacro run [expr] `(inc (eval ~expr)))
07:43bendlasdepending on your needs
07:44Confusionbendlas, OK, thanks, it seems there is then no way around eval for my use case.
07:44wlr#haskell
07:45bendlasConfusion: no, there isn't. The only thing you could do is to implement a subset of eval tailored to your needs.
07:45bendlasbut to eval at compile time isn't all that bad
07:46Confusionbendlas, true, but it's going to have to be at runtime. Fortunately the input already conforms to an instaparse grammar, so it's probably safe
07:47bendlasConfusion: ok, the go-to idiom for runtime eval is (defmacro make-runner [expr] `(fn [] ~expr))
07:48bendlasthus you can still take proper advantage of the JIT and such
07:48ConfusionAh, that's interesting!
07:49bendlaserm, sorry: (defn make-runner [expr] (eval `(fn [] ~expr)))
09:03Empperifuck yeah, it looks like I'm getting to Euroclojure
09:13zalatovoIs there a way to pass the name for a let binding into a macro?
09:13zalatovoright now I'm using something like `(let [~var ...] ...)
09:14bendlaszalatovo: that's the usual way, what would you like to do that you can't do with that?
09:14zalatovobendlas: it doesn't seem to work, I get a "no such var" RuntimeException
09:15zalatovobendlas: it probably has something to do with namespaces
09:15zalatovoI'm trying to write a (with-connection db (open ...) ...body...) macro which automatically closes db
09:16zalatovodb is the name that should be bound by the let in the body
09:16chouserzalatovo: Have you looked at the source code for the with-open macro?
09:17zalatovochouser: I haven't but I'll take a look
09:17chouserHm, as usual there's a bit more there than you might hope: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L3677
09:18zalatovothe strange thing is that the macro works just fine if I expand it manually and then run it
09:18chouserzalatovo: anyway, you may be able to use with-open itself. If not, you must be close.
09:18zalatovochouser: it does look a lot like what I'm trying to do but this is more of a macro exercise for me than something I really need
09:19bendlaszalatovo: sounds strange, care to pastebin?
09:19chouserzalatovo: sure. Maybe post the whole macro someplace?
09:19zalatovoI'll do that
09:20zalatovohttps://gist.github.com/anonymous/34897ea9039a2bce427d
09:20zalatovothink that's all of it
09:21chouserah! what's that 's' about? :-)
09:21bendlaschouser yep
09:22zalatovochouser: what do you mean?
09:22bendlasline 8
09:22zalatovoahhh I see it now haha
09:22zalatovorookie mistake
09:22chouser:-)
09:22zalatovothanks for the help anyway
09:24chouserso, the clue in the error message is the fully-qualified symbol. Your message was something like "No such var: test-project.foo/s" right?
09:24zalatovoyep
09:25chouserBut your 's' was never meant to be a "var" but rather a local
09:26zalatovoI'm not entirely sure of the difference
09:26chouserSo that suggests that something was fully-qualifying 's' when you didn't want it to. And syntax-quote (that is, the backtick `) fully-qualifies any symbol it can't resolve.
09:26zalatovolocals are bound by let whereas a Var is created using def?
09:27bendlaszalatovo: that's the primary difference
09:27chouserzalatovo: essentially, yes. Vars made via def live in a namespace and have a full name, like test-project.foo/with-string-stream
09:27chouser(there are also anonymous vars but seriously nobody uses those)
09:28zalatovo(let [x 10] test-project.foo/x) here the x would refer to a var instead of the local x?
09:28bendlasvars can also be thread-local (via ^:dynamic and binding), can hold macros, compiler macros
09:28bendlasyes
09:28zalatovothat makes sense
09:31chouserWhoa, I take it back. People use with-local-vars to an insane degree! https://github.com/search?l=clojure&q=with-local-vars&ref=searchresults&type=Code
09:31bendlasalso, not to forget, vars are mutable (volatile), contrary to immutable let bindings
09:32zalatovoaha
09:32zalatovoalso during macro expansion do symbols like print get resolved to clojure.core/print etc?
09:32chouser...though mutating even vars much is not encouraged.
09:32zalatovothat's what I understand from the reader docs
09:33chouserzalatovo: not during macro expansion, but during syntax-quote reading
09:33zalatovoaha
09:33chouser, `(list foo)
09:33clojurebot(clojure.core/list sandbox/foo)
09:34chouserno macros expanded there, but syntax-quote read each symbol as fully-qualified.
09:34chouser'list' was resolved to the real var clojure.core/list, whereas 'foo' wasn't found as a var anywhere, so the current namespace (sandbox) was assumed
09:35bendlaschouser: that step has always been kind of lost to me (if not explicit by `). It must also implicit as the first step to eval, right?
09:36chouserbendlas: right, syntax-quote resolves vars during read, but eval also resolves vars if necessary.
09:37bendlasso, the analyzer resolves them in the namespace context, if not in the lexical context ...
09:37zalatovoso something like (let [var 'foo] `(list ~var)) causes syntax-quote to use the fully qualified name for list and simply splice in the foo symbol without resolving it
09:38noncomis anyone here familiar with lein uberjar and handling of native libraries ?
09:38chouserzalatovo: exactly!
09:38chouserI think this is a difference between Clojure's sorta-hygenic syntax quote compared to Common Lisp's not-at-all-hygenic backquote
09:38zalatovochouser: then I understand why I got that particular error message :0
09:39chouserzalatovo: excellent!
09:40chouserbendlas: yep, if I understand you.
09:40chousernoncom: *shudder* a bit
09:42chouserbendlas: Actual analyzer actually analyzing a symbol: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6906
09:42noncomchouser: umm, i'm having a very strange problem. i include lwjgl libraries in my project.clj. and then in my source, I call "(org.lwjgl.opengl.Display/setLocation screen-x screen-y)"
09:43noncomchouser: that works ok from the IDE (Eclipse + CCW), but fails with no class found exception in jar made by lein uberjar. it cannot find the Display class
09:43TMA,(let [var 'foo] `(list ~var '~var ~'var ~'foo 'foo))
09:43clojurebot(clojure.core/list foo (quote foo) var foo ...)
09:44chouserbendlas: so: local, unqualified class name, qualified static Java field, var, actual class object, and finally "unresolved"
09:44bendlaschouser: right, even #'foo gets passed to the analyzer as (var foo)
09:44chouser,(read-string "#'foo")
09:44clojurebot(var foo)
09:45noncomchouser: what's more strange, the app that itself uses opengl starts fine if i just remove the call
09:45chouserbendlas: yep.
09:46chousernoncom: hm. It's complaining about not finding the Java class? nothing about a native lib or an unresolved function?
09:46noncomchouser: yes. the fact is that the class is there in the jar. my guess about the natives trouble is that it cannot load the class because it cannot load the natives that it requires
09:47bendlasnoncom: are the natives (*.so) in the jar?
09:47noncomchouser: what is really odd, the app *is* starting ok with all that stuff, and the app internally uses that very opengl...
09:48bendlasuberjar is not great at reproducing behavior of the regular packaging, in corner cases
09:48noncombendlas: awit, checking for the *.so files... why isn't it so great? does not it fullfill its duty?
09:49bendlasi'd say it does, as good as can be done for the general case. but there is just to much weirdness in the combination of java's classpath and maven
09:51bendlase.g. when having duplicate files on your class path, uberjar can include a different one than you would get for a regular run (even though duplicate files on CP might be called undefined behavior)
09:51noncombendlas: well, i am on windows and those are dll files and yes, they're there in the jar
09:52noncombendlas: strange thing is - the application *does* create the display and run inside it...
09:52chousernative libs don't follow the same classloader and classpath rules that class files do.
09:52chousernoncom: you're not getting any other errors or warnings before the class-not-found error?
09:52noncomlet me check again...
09:54bendlasIIRC, .so files (or dll files, if you will), need to be unpacked to a temp dir, before being loaded by the JVM, though I don't know what code does that
09:55chouserI think that's right, and it's up to each Java lib to do that itself.
09:57bendlasnoncom: also double check, if you don't have that issue with duplicate files on your class path. if your .class files get switched to a version that doesn't fit with its .so, it might just result in a class not found error
10:00noncomwell, it gives this, actually: http://joxi.ru/5mdkdLzuQw6Pr1
10:00noncomsorry, that's a bit different error
10:03chouserah, yeah, that's a native lib error.
10:03noncomdamn.. it worked a week ago
10:03chouserso java.library.path is usually set at jvm startup (though I'm sure IDEs will mess around with it)
10:04chouseranyway, the .dll (or .so) needs to be in one of the directories listed in java.library.path
10:04profilEmpperi: through opportunity grant or what? :)
10:04noncomsomehow, everything just works in Eclipse. when i try to publicsh a clojrue app, i usually get a bunch of errors... i am so tired of being bound to eclipse for clojure apps to just work...
10:05chouserThere may be some Java code in jgl or Eclipse somewhere to unpack the .dll from some .jar file and put it in some java.library.path directory
10:06chouserI have some vague recollection of lein also having such code. Hm...
10:06noncomactually, there was time, i had to write such a plugin for lein by myself: https://bitbucket.org/noncom/nativot
10:07noncombut i avoid using it if i can..
10:07chouserhttps://github.com/technomancy/leiningen/blob/master/sample.project.clj#L290
10:07noncomchouser: that's for compile-timne i think
10:08noncommy problem is that the already compiled jar does not start ok
10:08chouseroh! You may be right.
10:11Empperiprofil: my company sends me there
10:13noncomchouser: why can't they just make it so that the tool just works as it should...
10:13bendlasnoncom: I don't know what eclipse's equinox does automagically, but why not use something along the lines of https://github.com/scijava/native-lib-loader
10:14bendlasalso, relevant SO: http://stackoverflow.com/questions/2937406/how-to-bundle-a-native-library-and-a-jni-library-inside-a-jar
10:16noncombendlas: wow, thank you for the links!
10:16noncomnow i just have to tie it together with leiningen..
10:18bendlasnoncom: yw, let us know how it went :-)
10:19noncomhaha, if i get some result.. :) i am so blind tired of all this things, including classloading... you know, since i am creating a software for internal use, i just ship it with Eclipse...
10:19noncomthat's a shame, but i spent literary days on figuring similar kind of problems and solutions for them with clojure...
10:21noncombendlas: like, this one my message: https://groups.google.com/forum/#!topic/clojure/dY4AmXCDnxw none of the official did not even say a thing. only 2 ppl proposed some complex workarounds.. and just 1 irrelevant question "what version of clojure are you using" from someone, who's expected to really answer the question...
10:21noncomsad, that's just sad..
10:28bendlasnoncom: well, there is always a bit of luck involved, in your message getting read by a person who is able to help along. all in all, I think most members of the community share your disgust in java's classloading model
10:32bendlasalso, for me, the chance of fully comprehending a message on the mailing list and thus being able to match it with my own experience, increases exponentially with every minute effort to strip it down to it minimized form (in terms of introduced concept, not nessecarily words)
10:36jtmarmonis there a simple way to do a conditional kv within an object? I usually do (merge (if thing {:t thing} {}) {:rest :of :object :here}) but is there a way I can just do {:rest :of :object :here (some-magical-splicing-conditional)}
10:39bendlasjtmarmon: such splicing is only available at read time, via the new reader conditionals
10:39chouser(conj {:rest :here} (when thing [:t thing]))
10:39chouser(-> {:rest :here} (cond-> thing (assoc :t thing)))
10:40bendlas^ this
10:40jtmarmonah great, thank you!
10:41chouseror with synthread: (-> {:rest :here} (->/if thing (assoc :t thing)))
10:42profilEmpperi: oh, you lucky. Are you working with clojure?
10:57noncombendlas: yeah, i know.. but what can i do.. if the topic is like that :)
11:00bendlasnoncom: keep focussing on the core of the problem, until you have a kernel that's almost trivial to convey.
11:01bendlasthen you only need to convince people that it is actually the root of something relevant ;-)
11:02noncom:) well, maybe i made my google groups quesion explanation too broad... indeed, it could be fit within 1-2 lines of text maybe..
11:03bendlasI think clojure, in the large, sets a great precedence of building something more simple on top of something as baroquely complex as the jvm. which is in equal parts miraculous when viewed from the OOP side, as well as easy to underestimate when used to it
11:06bendlas... but i guess that goes for every useful abstraction
11:08bendlas... and same as most useful abstractions, it has its corner cases where leaks spring as soon as you put the pressure on
11:23stainhi, is it possible to do some magic to add Clojure methods to an existing Java class or interface? E.g. make a third-party org.apache.commons.Foo also be Seqable and IPersistentMap?
11:23stainor should I better make a bunch of wrappers
11:24stainwhich then have to wrap their constituent fields etc
11:26chouserstain: alas, no such magic. If Seqable and IPersistentMap were protocols (like they are in ClojureScript), you could use extend-type. But alas they are Java interfaces, so you have only the normal Java options.
11:27chouserSo, yes, wrappers.
11:28chouserstain: or, if you don't really need Clojure's existing interfaces to work, you can make your own protocols or multimethods and extend them to 3rd party classes as well as Clojure's own.
11:28stainyeah, that might be easier
11:32stainI'm thinking of the best way to make a Clojure bridge for the Commons RDF API (Java interfaces) http://commonsrdf.incubator.apache.org/apidocs/org/apache/commons/rdf/api/package-summary.html - which naively and natively could just be like this in clojure: https://github.com/stain/commons-rdf-clj/blob/master/src/commons_rdf_clj/graph.clj
11:33stainbut my problem is I have not decided which direction I would want to bridge.. :)
11:36rpaulo]]]]]]]]]]]]]]]]]]]]]]]]]]
11:36rpaulooops, cat
12:15studentrobHi, I'm new to Clojure. I have a function that, given two arguments, returns a number. I want to make a priority-map using the second argument as the key and the returned result as the value ... http://pastebin.com/zrtNVkyt
12:17studentrobThis is part of a kata, and I probably haven't read as much of "Clojure Programming" as I should have so far
12:19_1_Melvin2hello
12:21chouserstudentrob: clojure doesn't come with a priority-map. There is a sorted map, but beware your comparison fn must describe a full stable order (no returning of 0 unless the two keys are *actually* equal)
12:31studentrobHi Chouser, thanks for your reply. (Had to look it up online in the logs as I was disconnected.) .... I'm using an external library for priority map which I guess makes this hard for other people to run, doh.. I'll try sorted-map
12:32studentrobI have the same issue with sorted-map .... I'm not sure how to set up the map function properly to get key-value pairs .... I can make a vector of keys, and a vector of values separately but am not sure how to match them up
12:33studentrobmaybe rather than using map I should loop
12:42justin_smithstudentrob: any reasonable hash-map implementation should give you a sequence of entries if you call map on it
12:42justin_smith,(map identity {:a 0 :b 1 :c 2 :d 3})
12:42clojurebot([:a 0] [:b 1] [:c 2] [:d 3])
12:53studentrobThanks Justin . I figured it out via a loop. My problem was constructing the "innards", :a 0 :b 1 :c 2 :d 3 , properly .. I ended up with this : http://pastebin.com/9dtPYpr7 .. If that can be accomplished using the map function, I'd love to know how, but it was beyond my brain capacity as I've just started learning this language
12:54justin_smithstudentrob: that's not a map, that's a reduce
12:55justin_smithand it's reducing on cand, not the priority-map
12:55justin_smiththe priority-map is the accumulator for reduce
12:55studentrobokay, cool, I haven't read about reduce yet
12:55studentrobI'll take note of your comments and read up on that
12:56justin_smith(reduce (fn [pm w1] (assoc p1 w1 (dist w1 goal))) (priority-map) (filter #(= (count %) (count goal)) words))
12:56justin_smiththat should work in the place of your loop ^
12:56cap10morganIs there a simple rule for when to use put! vs. >!! in core.async?
12:59justin_smithcap10morgan: does the next line of code break if the value was not consumed yet?
12:59justin_smithif yes, use >!!, if no, use put!
12:59cap10morganah, b/c >!! blocks but put! does not?
12:59justin_smithright
13:00cap10morganjustin_smith: OK, thanks. that makes sense.
13:04studentrobThanks, I understand reduce now!
13:04justin_smithstudentrob: awesome, it's a very useful and flexible function
13:04justin_smithstudentrob: once I figured out reduce, I realized it could replace almost every usage of loop I had been using
13:05jtmarmonok im very confused - is there something that can make a function exit early in clojure other than an exception? for some reason this function exits early and i can't figure out why. https://gist.github.com/jtmarmon/9e7491b8ebcff3d4d8f6
13:05studentrobYeah. Seems like a very common operation, pretty handy
13:07justin_smithjtmarmon: I can't reproduce
13:07jtmarmonso weird o_O
13:07justin_smithjtmarmon: if I call (wtf {:a 0}) I see both "hi1" and "hi2"
13:08justin_smithjtmarmon: are you giving postwalk something that's lazily generated and potentially infinite?
13:09jtmarmonit's a datomic entity map...maybe?
13:18jtmarmonjustin_smith: ok converting the entity map to a hash-map and calling wtf still prints "hi1" only
13:18jtmarmonwat
13:20jtmarmonit must be something with the runtime. i'm running this via "lein ring server". it works fine in my repl, just not in the server logs
13:25jtmarmoni'm so confused T_T
13:27justin_smithjtmarmon: one thing I like to use is a: make sure I have a repl in the ring process (starting the server from a repl, or running clojure.tools.nrepl will work) then using an atom to store the args to the problematic function
13:27justin_smithwhich lets me come back and interactively use the data, and figure out what went wrong
13:27justin_smithit's one of the nice side effects of using immutable data
13:28jtmarmonvery helpful, thanks. i'll see if i can figure it out that way
13:28justin_smitheg. (defonce debug (atom [])) and then inside your function arg (swap! debug conj problem-input)
13:28justin_smith*inside your function
13:42gfredericksI like the quick-and-dirty method of just throwing a (def arg arg) inside a function
13:42justin_smithhaha, there's that too
13:43gfredericksalthough this makes me want to write some utils for my . namespace that can as-easily-as-possible start capturing args & return values
13:43justin_smithlike a tools.trace that stores the values and lets you look them up
13:43justin_smithbonus if it also stores timestamps so you can go find the arg that was supplied an hour ago etc.
13:44jtmarmonso it seems i'm getting an abstractmethoderror on the "conj" step of postwalk but it's not being thrown for some reason... https://gist.github.com/jtmarmon/9e3e6826460b51b8f616
13:45jtmarmon nor do i know why it's happening in the first place
13:45gfredericksjustin_smith: well there's lots of leak issues there
13:45justin_smithoh, yeah, it's by definition a huge space leak
13:46gfredericksjtmarmon: how do you find out about it if it doesn't get thrown?
13:46jtmarmoni stored it in an atom and re-called the function myself
13:46justin_smithjtmarmon: my guess is that into is trying to populate the empty version of some data structure from datomic, and it's failing
13:46justin_smithbecause that data structure is weird or something I guess?
13:46jtmarmonoh wtf it works now
13:46jtmarmon-_-
13:46justin_smithhaha
13:47jtmarmonnot the whole thing, just when i call it manually
13:54jtmarmonokay, so if i select certain keys from the object it works fine...meaning there's just some k-v pairs in the map angering rich
13:56gfredericks,(defrecord Foo [a b])
13:56clojurebotsandbox.Foo
13:56gfredericks,(select-keys (->Foo 1 2) [:a :c])
13:56clojurebot{:a 1}
13:56gfredericks,(type (select-keys (->Foo 1 2) [:a :c]))
13:56clojurebotclojure.lang.PersistentArrayMap
13:57gfredericksjtmarmon: select-keys can take a special kind of map and turn it into a generic map
13:57puredangerAre you missing the id?
13:57gfredericks,(type (select-keys (sorted-map :a 3) [:a :c]))
13:57clojurebotclojure.lang.PersistentArrayMap
13:58jtmarmonpuredanger: what do you mean?
13:58puredangerNever mind, didn't read enough of the back chat
14:00jtmarmongfredericks: into {} converts the datomic result into a persistenthashmap. how can I get it to use a persistentarraymap instead
14:00gfredericksjtmarmon: normally those two are functionally equivalent; I'd expect them to be w.r.t. clojure.walk at least
14:01gfredericks,(type (into {} {:hey :ya}))
14:01clojurebotclojure.lang.PersistentArrayMap
14:01jtmarmono_O wat
14:01jtmarmonoh i see
14:01gfredericksjtmarmon: looks like it uses an arraymap for small maps probably
14:03jtmarmonso to recap i'm threading the datomic result set through (map #(into {})) and then through (postwalk #(if (keyword? %) (keyword (name %)) %)). if I comment out postwalk, I get a response. if I don't comment it out, i get nothing
14:03gfrederickswhat does "get nothing" mean?
14:04gfredericksis this a ring server?
14:05jtmarmonyes
14:05jtmarmonyeah okay, exception is being eaten i'm sure of it
14:05gfredericksit's probably worth putting some effort into figuring out how to get exception details with your setup
14:05gfrederickswhat's the http response exactly? 500 with empty body?
14:06gfredericksthis is probably the most appropriate thing: https://ring-clojure.github.io/ring/ring.middleware.stacktrace.html
14:06SeyleriusWhat's the best way to push something through a stack of functions that alternately need it at the start and finish?
14:07SeyleriusReally, it's one that needs it at the start, and the rest can use it at the finish, actually...
14:07gfredericksI'm having trouble parsing that
14:07SeyleriusI figured it out.
14:08gfredericksthat was easy
14:08SeyleriusYep
14:08SagiCZhey guys.. i am trying to get some information from a server using SOAP request.. the response is this https://www.refheap.com/101650 .. it should contain a xml file with the configuration but all i see is some huge random string.. how would i obtain the xml?
14:08gfredericksglad I could help
14:08Seyleriusgfredericks: Basically, I need to use ->>. The first function takes the value at the start, but the rest are all mapv
14:08SagiCZim very new to SOAP
14:09SeyleriusSo, something like (->> (select board :foo) (mapv func))
14:09SeyleriusWith as many mapvs as I'm going to need.
14:09Seyleriusboard is the value pushed in.
14:10gfredericksSeylerius: a bunch of mapvs can be squashed into one
14:11gfredericksSagiCZ: looks like it's base64 with some more xml in it
14:11justin_smithtransduce that junk yo!
14:11SagiCZgfredericks: base64 is some kind of hashing? bear with me i am a total noob.. it is supposed to contain xml indeed
14:12justin_smithSagiCZ: base64 is a safe way to encode arbitrary data in a subset of ascii
14:12Seyleriusgfredericks: Actually, this is where I'll need to talk with y'all. I need to nest deeper with each pass. Basically, I've got a GUI structure that contains text boxes nested 3 layers in, and I need to preserve the shape while extracting the data.
14:12justin_smithso it's used for things like email attachments
14:12justin_smithSeylerius: sounds like a job for postwalk
14:13gfredericksSeylerius: you might want to show some examples
14:13SagiCZgfredericks, justin_smith thank you both guys.. it really is just encoded.. very simple but i didnt know what to google so you saved me!
14:13SeyleriusSo board is a grid-panel containing 9 grid-panels, containing 9 grid-panels, containing 9 text boxes.
14:13arav93clojure.xml/parse expects a URI as input
14:13SeyleriusEach grid-panel needs to turn into a vector, and the text boxes need to be numbers.
14:14arav93BUt it seems to show an exception when I pass one
14:15Seylerius(This makes my brain feel like a matryoshka doll)
14:17gfredericksSeylerius: yeah clojure.walk sounds plausible
14:17Seyleriusgfredericks: prewalk might be better than postwalk, because they won't really become seqs until processed.
14:18gfredericksyeah
14:18justin_smithSeylerius: the generic "walk" that does both might be an option here
14:18SeyleriusI suppose the function would just have to detect whether it got fed a grid-panel or a textbox, and then do the Right Thing™ from there
14:18gfredericks,(clojure.walk/prewalk #(repeat (rand-int 3) %) 42)
14:18justin_smithyeah, that's what walking code usually looks like
14:18clojurebot#error {\n :cause "clojure.walk"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.walk"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n [java.net.U...
14:19gfredericks,(require 'clojure.walk)
14:19clojurebotnil
14:19gfredericks,(clojure.walk/prewalk #(repeat (rand-int 3) %) 42)
14:19clojurebot((() (((((()) (() (((# #)))))) (() (() (((() (#))))))))) ())
14:19gfredericks^ protip
14:19justin_smithhaha
14:19SeyleriusHeh.
14:19gfredericksI wonder how to measure the expected size based on the arg to rand-int
14:20gfredericksit reminds me of random-walks and trying to describe the probability that a walk returns to the origin
14:20justin_smithgfredericks: it would be an unbounded lazy seq no matter what, wouldn't it?
14:20arav93could someone show an example where clojure.xml/parse works?
14:20arav93:/
14:20gfredericks,(clojure.walk/prewalk #(repeat (rand-int 3) %) 42)
14:20clojurebot((((()) ((((() ()))) (()))) (((() (()))))))
14:21gfredericksjustin_smith: ^ no
14:21justin_smithgfredericks: ahh
14:21arav93I don't seem to get it to work
14:21justin_smithgfredericks: but in the pathological case it could hypothetically be unlimited
14:22gfredericksjustin_smith: right -- but there's a specific probability of it being unlimited
14:22gfrederickssomething in the range [0,1)
14:22justin_smithahh, so expected size isn't a number, it's more of a curve
14:22gfredericksI assume it's positive for large enough n but don't know for sure
14:23gfredericksjustin_smith: well expected size is infinity if there's a positive probability of infinite size
14:23gfrederickscould be infinity even without that
14:24jtmarmonahah http://comments.gmane.org/gmane.comp.db.datomic.user/4773
14:24justin_smithjtmarmon: there you have it
14:25jtmarmonany idea what "clojure data" entails here? i'm already mapping it to a hash-map which i thought would be enough
14:25justin_smithjtmarmon: at every level?
14:25jtmarmonah i suppose not
14:25justin_smithit could have been a nested data issue
14:33jtmarmonjustin_smith: any idea what i'm missing here? error is still hanging around https://gist.github.com/jtmarmon/229e07936d19f53d7d60
14:34arav93So, I tried this '(clojure.xm/parse "http://www.cnn.com")
14:35arav93I got "SAXParseException The entity name must immediately follow the '&' in the entity reference. com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException (ErrorHandlerWrapper.java:198)"
14:50SeyleriusWhen prewalk descends, does it descend into the transformed result, or the original?
14:51Seyleriusie, can prewalk work with a function that turns non-seqs into seqs, and descend into those?
15:00andyfSeylerius: I am pretty sure the whole distinction between pre walk and post walk is whether the supplied function is applied before descending deeper (pre walk) or after returning from descending (post walk). Have you tried pre walk on a toy example?
15:01Gue______Seylerius: > (clojure.walk/prewalk #(if (= 1 %) [0 0] %) [1 0 1 0 1])
15:01Gue______[[0 0] 0 [0 0] 0 [0 0]]
15:01Gue______> (clojure.walk/prewalk #(if (= 1 %) [0 1 0] %) [1 0 1 0 1])
15:01Gue______java.lang.StackOverflowError
15:02Seyleriusandyf: nah, postwalk starts at the bottom and works up.
15:02SeyleriusLook at prewalk-demo and postwalk-demo
15:03SeyleriusBut looking closer at postwalk reveals that prewalk (if it behaves like postwalk in all respects except going top-down) will operate on the result of the function.
15:04andyfSeylerius: To get to the bottom, post walk must start at the top :)
15:05Seyleriusandyf: Look at the demo functions.
15:05crash_epSeylerius: not sure if my paste went through…
15:05crash_ep> (clojure.walk/prewalk #(if (= 1 %) [0 0] %) [1 0 1 0 1])
15:05crash_ep[[0 0] 0 [0 0] 0 [0 0]]
15:05crash_ep> (clojure.walk/prewalk #(if (= 1 %) [0 1 0] %) [1 0 1 0 1])
15:05crash_epjava.lang.StackOverflowError
15:06andyfI did. They show when the supplied functions are applied. They don't show how post walk gets to the bottom in the first place.
15:06crash_epshows that the walk does descend into the value returned from the function if it returns a seq.
15:06Seyleriuscrash_ep: Ah.
15:08Seyleriuscrash_ep: Yeah, that proves it.
15:08Seyleriusprewalk is what I need.
15:08SeyleriusThanks.
15:08crash_epnp
15:08Seylerius(inc crash_ep)
15:08lazybot⇒ 1
15:25SeyleriusThere a function to tell if a vector contains vectors or just numbers?
15:27Seylerius'Cause I need to build a walk function that prewalk can call that will simply return the argument if there are more vectors, and do shit if the argument only contains numbers
15:27SeyleriusActually, wait, I can skip that step.
15:28bendlas,(every? number? [1 2 3 4])
15:28clojurebottrue
15:28bendlas,(every? number? [1 2 [3 4] 5])
15:28clojurebotfalse
15:30mmeixI'm trying to write a cond-clause which evaluates to true if and only if the number 1 appears only once in a coll ... I have now: (= 1 (count (filter #{1} c)))
15:30mmeixCould this be done simpler?
15:32bendlas,(some #{1} [1 2 3 4])
15:32clojurebot1
15:32bendlas,(some #{1} [2 3 4])
15:32clojurebotnil
15:32ToxicFrogbendlas: "appears only once" is the key.
15:32ToxicFrogIt should pass for [1 2 3 4] but fail for [1 1 1 1].
15:33mmeixexactly
15:33bendlasOIC, in that case, no
15:33ToxicFrogmmeix: that said, #{1} can probably be replaced with (partial = 1). Not sure if that's clearer to you, though.
15:33mmeixclearer - yes
15:34ToxicFrogOh hey
15:34SeyleriusMaking an int from a string?
15:34ToxicFrogI think you want frequencies
15:34SeyleriusJust int?
15:34mmeixah!
15:34mmeixfrquencies I forgot about
15:34ToxicFrog,(-> [1 2 3 4] frequencies 1 (= 1))
15:34clojurebot#error {\n :cause "java.lang.Long cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval121 invoke "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval121 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [clojure.lang.Compiler eval "Compiler.java" 6755]\n ...
15:34ToxicFrogright whoops
15:35ToxicFrog,(-> [1 2 3 4] frequencies (get 1) (= 1))
15:35clojurebottrue
15:35ToxicFrog,(-> [1 2 3 4 1] frequencies (get 1) (= 1))
15:35clojurebotfalse
15:35bendlasonly, frequencies does more work, which might or might not be relevant
15:35Seylerius,(int "4")
15:35clojurebot#error {\n :cause "java.lang.String cannot be cast to java.lang.Character"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to java.lang.Character"\n :at [clojure.lang.RT intCast "RT.java" 1163]}]\n :trace\n [[clojure.lang.RT intCast "RT.java" 1163]\n [sandbox$eval193 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792]\n [c...
15:36bendlas,(Long/valueOf "4")
15:36clojurebot4
15:37mmeixin this case performance might matter, because this is in the dispatch function of a multimethod
15:38mmeixI'm dealing with an awful collection of rules to solve a graphic problem (music setting), and just trying to tame the beast with intelligent dispatch
15:42mmeixthe frequencies-method seems to run about 10 times longer, trying with (time ...)
15:42mmeix,(time (-> [1 2 3 4 1] frequencies (get 1) (= 1)))
15:43clojurebot"Elapsed time: 0.538152 msecs"\nfalse
15:43mmeix,(time (= 1 (count (filter #{1} [1 2 3 4 1]))))
15:43clojurebot"Elapsed time: 0.12773 msecs"\nfalse
15:43Deraencount will have to realize the whole filter, you could use first and second instead of it:
15:43Deraen,(time (let [x (filter #{1} [1 1 2 3 4])] (and (first x) (not (second x)))))
15:43clojurebot"Elapsed time: 0.223119 msecs"\nfalse
15:44mmeixif that matters: count is seldom more than 20 in my case
15:44DeraenThough that will only matter with collections larger than seq chunk-size or something
15:44mmeixunderstood
15:45mmeixso filtering and counting in such small vectors is not that bad
15:52mmeixa strategic question as follow- up: is a lookup of ready-made solutions in form of a map a feasable way, timingwise? I have to deal with a domain with a lot of small special rules, so in some cases the needed calculations for a single case are a lot. I thought about creating a map with, say 30-50 of the most frequent cases, and using the functional machinery only for the few remaining ... not a pure solution, but maybe practical.
15:57TEttingermmeix: most efficient would probably be an array with the indices exactly as you want them
15:57TEttingerassuming you are giving and returning primitives
15:58mmeixmy input would be something like [0 1 0], and it's solution [1 0 -1]
15:58mmeixa vector of offsets to add to the input
15:59TEttingerso... your numbers are always 1, 0, or -1?
15:59mmeixno
15:59TEttingeror are there a lot of possible entries?
16:00mmeix[0 0 1], [0 1 1], [0 1 2], [0 2 2], [0 2 3], etc, up to 7 for each place
16:00TEttingerfriggin' sweet. I get to use bit twiddling
16:01mmeixoh ...
16:01TEttingerdepends how crazy you need speed
16:01mmeixit's clojurescript project, music notation in a browser
16:02TEttingeroh then none of my advice applies
16:02mmeixI'm not sure about needed speed yet
16:02TEttingerarrays make the most sense for JVM opts, probably don't exist in JS (they're not like Java arrays, at least)
16:03mmeixso maybe simple maps might be the way to go
16:03TEttingeryes
16:03mmeixit's about untangling the many possible cases
16:03mmeixinto simple lookup
16:03TEttingerJS objects are pretty much everywhere in JS code, so I'd bet they are optimized by JS engines extremely heavily
16:03mmeixI thought this might be just simpler
16:04TEttingerobjects should be best
16:04mmeixok, something to think about - great & thanks!
16:06TEttingerwhere an object corresponds to a map, I mean, mmeix
16:07TEttingerthey are probably extremely similar at runtime
16:07mmeixin JS every object is similar to a clojure(script) map, I think
16:08mmeixwill think & try
16:09mmeixthanks! & bye ...
17:30turtilAside from the Changelog, is there anywhere I can find a list of substantial changes from Clojure 1.4 to the Current Release? Basically im re-reading Clojure Programming (O'Reilly) and Programming Clojure (Prag Bookshelf) and im wondering how current these books will be for the most part
17:36bbloomturtil: clojure is very stable & backwards compatible. you'll miss out on some new stuff, but nothing you learn will be wrong
17:36bbloomthe only stuff that i can think of that's meaningfully deprecated occurred before clojure 1.4, so don't worry about it
17:37kaiyinCan I set *out* to something similar to /dev/null on unix machines?
17:39andyfkaiyin: I'm not aware of anything specific for that in Clojure. Here is a StackOverflow question for Java: http://stackoverflow.com/questions/691813/is-there-a-null-outputstream-in-java
17:39andyfkaiyin: I'd recommend trying (clojure.java.io/writer "/dev/null") on a unix-like machine and see if it works as expected, but that would probably not be portable to non-unixes.
17:40bbloom,(clojure.java.io/writer "/dev/null")
17:40clojurebot#error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__881 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__881 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkWrite nil -1]\n [java.io.FileOutputStream <init> "FileO...
17:40bbloomaw
17:40kaiyinok
17:40andyfbbloom: Can't have people breaking security by making the bots discard data :)
18:05turtilbbloom: thanks for that, i will continue as per normal then :)
18:36TimMcfile:///dev/null I think
18:37bbloom,(clojure.java.io/writer "file:///dev/null")
18:37clojurebot#error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__881 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__881 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkWrite nil -1]\n [java.io.FileOutputStream <init> "FileO...
18:37TimMcbut really you'd just want to make an OutputStream that threw away all writes
18:39TimMcThe second answer on that SO link is good.
18:51arohnerwhat's the name of that clojure.test replacement library that has almost the same API?
18:53bbloom.... if it has almost the same api, what's the point?
19:06auxcharAnyone know a good example project for clj-ssh?
19:24turbofailauxchar: pallet, presumably
19:42auxcharThanks, turbofail.
20:10elvis4526Is there a way to combine multiple regexp together in a single pattern ?
20:11elvis4526Is there a way to combine multiple regexp together in a single regexp?
20:11elvis4526I tried with (re-pattern) but its annoying to be forced to escape each backslash you enter
20:18Shayanjmis there a structural difference between conventional 'arrays' in other languages and vectors in clojure? Or is it just semantics?
20:19andyfelvis4526: Should be able to write a function that combines multiple together, with some assumptions or limitations of what each regex contains.
20:19andyfelvis4526: Nothing existing in Clojure's library, but someone has probably written something for themselves.
20:19andyfShayanjm: Arrays in most languages are mutable, and O(1) access time to any element.
20:20Shayanjmandyf: do clojure vectors not have O(1) access time to elements?
20:20andyfShayanjm: Clojure vectors are immutable, and to get immutability the best known implementation require O(log n) access time and update time, with memory allocation required for each update. The base of the log is 32 in the implementation, which helps keep # of memory references low.
20:20Shayanjmahhhh
20:20Shayanjmthanks andyf
20:20Shayanjmmuch appreciated
20:21andyfThere are blog posts explaining the details of how the implementation works, but I don't have a link ready and waiting for it.
20:22andyfShayanjm: Most notably, Clojure's immutable vectors are *not* binary trees, which in practice are quite a bit slower than 32-way branching trees for reads.
20:22Shayanjmgotcha
21:17arohnerbbloom: re: clojure.test earlier. it cleans up a few things regarding e.g. fixtures
21:18arohnerI implemented basically the same thing in Circle's codebase, but I monkeypatched clojure.test directly
21:20arohneriirc, in raw clojure.test, calling a test fn directly doesn't call its fixture
21:24gfredericksarohner: sounds right
21:24arohnergfredericks: do you remember the name of the clojure.test replacement library? almost exactly the same API
21:24gfredericksarohner: do you think there's an obviously correct behavior for calling a test directly w.r.t. :once fixtures?
21:24gfredericksarohner: no
21:25arohnerI don't think there's an obviously correct way w/ :once fixtures, and I don't use them
21:25arohnerIMO, they're a sign your tests are too stateful
21:25arohnerimplicit global state ,etc etc
21:34gfredericksarohner: that's an interesting point
21:34arohnergfredericks: I'm a full-blown convert to stuartsierra/component. It cleaned up my tests a lot
21:39gfredericksarohner: yeah I definitely use it; I should check what my :once fixtures were about
21:40justin_smithugh, I feel so lazy. I was going to make all the tests on my cljc port of component pass this weekend
21:40justin_smithinstead I took naps
21:40andyfjustin_smith: Forgive yourself
21:41justin_smith I'll have to :)
21:41gfredericksarohner: looks like the only one was for resetting the database
21:41justin_smithI still want to make those tests pass though, maybe I'll do it on the clock
21:41gfredericksI had a couple others but they were fast enough that they could be switched to :each with no noticeable slowdown
21:41arohnergfredericks: why not reset before every test?
21:41TEttingergfredericks, I watched part of that random talk, been meaning to watch the rest
21:42gfredericksarohner: I think I had something else for that, that made it not as slow
21:42TEttingerit's making me wonder about clojure's language-level rand-int and rand-nth but no srand
21:42gfredericksarohner: I can't remember it's kind of complicated :/
21:43gfredericksTEttinger: yeah I think that's somewhat of an orthogonal problem
21:43gfredericksunless you wanted to get ambitious and make it splittable while you were at it
21:43TEttingerheh
21:43gfredericksTEttinger: but I have a ticket for that
21:43TEttingernice
21:43gfredericksTEttinger: http://dev.clojure.org/jira/browse/CLJ-1452
21:44TEttingerI've been wondering about language-level state, function-level state, etc.
21:45gfredericksyeah when I started developing that talk I was at least going to mention that clojure's builtin rng api is about the least useful possible
21:45gfredericksbut that turned out to not really fit
21:46TEttingerlike, would it be good to be able to set fields in a function. (set rand .state 12345)
21:47TEttinger(this is for my language, which is clojure-inspired but not really a lisp)
21:48gfredericksTEttinger: I think clojure-style is to use dynamic vars for this kind of situation
21:49gfrederickswhich is strictly more useful than C's global srand
21:49gfredericksclojure < C < clojure+*rand*
21:50gfredericksI suppose you could argue that srand in C being global means you just shouldn't use it at all and therefore it's not more useful than clojure
21:50gfredericksdunno
21:51TEttingeralso, what do you think about the claims made by PCG-random ?
21:51TEttinger$google pcg random
21:51lazybot[PCG, A Family of Better Random Number Generators | PCG, A ...] http://www.pcg-random.org/
21:52gfredericksI'm not the best for comparing algorithms
21:52gfredericksI've read through that page a couple times and I don't think they're aiming for a general splittable RNG
21:53gfredericksunless "multiple streams" means something different than what it sounds like
21:54TEttingerhttp://www.pcg-random.org/useful-features.html#id3
21:54TEttingerapparently it is splittable
21:57gfredericksTEttinger: what part of that page suggests that?
21:59TEttingerI may misunderstand the splittable part. the same seed can be used to construct 2^63 different RNGs, since it uses 63 bits to determine how it permutes the LCG generator result
21:59gfredericks2^63 isn't enough :)
22:00TEttingerhow many is enough?
22:01TEttinger,(Math/expt 2 63)
22:01gfrederickswell that was misleading
22:01clojurebot#error {\n :cause "No matching method: expt"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: No matching method: expt, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6740]}\n {:type java.lang.IllegalArgumentException\n :message "No matching method: expt"\n :at [clojure.lang.Compiler$StaticMet...
22:01TEttinger,(Math/pow 2 63)
22:01clojurebot9.223372036854776E18
22:01gfredericksit's more that that kind of algo structure doesn't really lend itself to splittability
22:01TEttingerah
22:01gfredericksin a general splittable RNG you don't know a priori how many rngs you'll need to split into
22:02TEttingerbut you will encounter a limit at some point
22:02gfredericksso the API for a splittable rng is more or less:
22:03gfredericks(create seed) => rng; (rand-long rng) => long; (split rng) => [rng rng]
22:03gfrederickshow would you implement such an api on top of the PCG generator?
22:04gfredericksin particular what do create and split do w.r.t. those 2^63 possible ways to initialize the PCG?
22:04gfredericksthe difficulty is not knowing what is the structure of splitting the user will perform
22:25danielcomptonping cfleming
22:26cflemingdanielcompton: pong
22:26danielcomptonI've started getting super weird cljsbuild error messages from a Cursive REPL that I don't get from a Lein REPL, does that ring any bells?
22:27cflemingdanielcompton: There is a cljsbuild bug that affects Cursive because Cursive uses trampoline - one sec
22:28cflemingdanielcompton: https://github.com/cursiveclojure/cursive/issues/369 and https://github.com/cursiveclojure/cursive/issues/386
22:28cflemingdanielcompton: Does that look like your issue?
22:29danielcomptoncfleming: yep thats it. I'm a bit puzzled though because it's only just started showing up for me...
22:29cflemingdanielcompton: Dunno - it's an upstream cljsbuild bug
22:29cflemingdanielcompton: No-one ever got to the bottom of it, and Chas closed it as "no patch provided"
22:30cflemingdanielcompton: https://github.com/emezeske/lein-cljsbuild/issues/204
22:30cflemingdanielcompton: If you feel like debugging and fixing it, many people including me will be very happy :-)
22:31danielcomptoncfleming: I have enough trouble keeping my cljs projects building successfully, but maybe if I get frustrated enough I'll dig in
22:31cflemingdanielcompton: How much value is cljsbuild actually providing you with recent versions of cljs?
22:32cflemingdanielcompton: It seems like cljs itself handles most of the building itself these days
22:32danielcomptoncfleming: I've really been enjoying dnolen's mies templates with just scripts, but I wanted something to give me an autoloading clojure frontend and backend for a quick project so chestnut was *was* a good option
22:35cflemingdanielcompton: Here's a description of how to get figwheel working with just scripts - this is thanks to jackjames, I haven't had a chance to write it up properly yet. https://www.refheap.com/101322
22:35danielcomptoncfleming: ta
22:35cflemingdanielcompton: That gives you figwheel + REPL.
22:35danielcomptoncfleming: now I want to get to the bottom of it just for the glory
22:36cflemingdanielcompton: I like a masochist
22:48cflemingDoes anyone have any experiences to report using cloverage? Does it work well?
22:49danielcomptoncfleming: yep
22:49danielcomptoncfleming: well
22:49danielcomptoncfleming: it needs to be interpreted in my experience.
22:49cflemingdanielcompton: Nice, thanks. No problems with subtle differences after the code instrumentation?
22:50danielcomptoncfleming: what do you mean about differences?
22:50cflemingdanielcompton: You mean the output needs to be interpreted?
22:50danielcomptoncfleming: yeah, I'm going to pull up a recent one I did to explain what I mean
22:51cflemingdanielcompton: Well, it instruments your code, which involves macroexpanding it all using riddley. That sounds like it might introduce subtle differences in how the code works.
23:02danielcomptoncfleming: brb
23:02cflemingdanielcompton: np
23:28ddellacostacfleming: re: cloverage, I recall it took a bit of fiddling to get it working but that may have more to do with the messy state of our codebase as anything
23:28danielcomptoncfleming: https://dl.dropboxusercontent.com/u/5803867/Random/Screenshot%20of%20Safari%20%2826-05-15%203%3A26%3A58%20pm%29.png
23:29danielcomptoncfleming: so some bits are correctly identified, and some aren't
23:29cflemingddellacosta: Once you got it going, did it seem reliable?
23:29danielcomptoncfleming: It's a good visual tool to use to go through your own code and spot bits you've missed, but I wouldn't break the build on less than 100% test coverage
23:29cflemingdanielcompton: Thanks, that's interesting.
23:29ddellacostaI mean, I think so? I just use it off and on to get a sense of where we're at w/testing
23:29ddellacostaI should probably be using it more often really
23:30cflemingdanielcompton: I wonder why it misses some parts
23:30ddellacostayeah, and what danielcompton sez ^
23:30cflemingI'm wondering if a Java bytecode coverage tool might not work better/more reliabley
23:30cfleming*reliably
23:31cflemingDoes cloverage identify coverage of individual exprs on a single line?
23:45danielcomptoncfleming: restarting my computer made the cljsbuild errors go away for now
23:46cflemingdanielcompton: That's really weird.
23:51danielcomptoncfleming: is Cursive's REPL an nREPL or something else?
23:52cflemingdanielcompton: Well, there are two now - an nREPL one and a clojure.main one. But you're probably using the nREPL one.
23:53justin_smithhaha, sorenmacbeth's new twitter name is Mad.MAX_VALUE
23:53justin_smithMad/MAX_VALUE would have been more clojureish, but I'll accept it