#clojure log - Dec 28 2014

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:04 andyf: Here it is: https://github.com/technomancy/leiningen/issues/1750

0:58 kenrestivo: alter-var-root is the monkeypatcher's dream

3:11 suppi: this triangle is killing me :(

4:11 tucker: hey, can someone please explain to me how

4:11 the lazy seq in

4:11 (defn- coll-or-scalar [x & _] (if (coll? x) :collection :scalar)) (defmulti replace-symbol coll-or-scalar) ; <label id="code.replace-symbol.multi"/> (defmethod replace-symbol :collection [coll oldsym newsym] (lazy-seq ; <label id="code.replace-symbol.lazy-seq"/> (when (seq coll) (cons (replace-symbol (first coll) oldsym newsym) (replace-symbol (rest coll) oldsym newsym))))) (defmethod replace-symbol :scalar [obj oldsym ne

4:11 better yet: https://github.com/stuarthalloway/programming-clojure/blob/e10099afa98f342647ab6ec89e826b360272c8c7/src/examples/replace_symbol.clj

4:11 breks the recursion

4:11 better yet, how does lazy-seq work here?

4:12 i don't understand how it can prevent the stack being blown

4:12 there is still recursion

4:14 Dynasty: is there an order in which macros are expanded? ie, are outer macros expanded first when there is a nesting situation?

4:28 nuwanda_: tucker: (seq col)

4:28 is an idiomatic way of saying not-empty? col

4:39 Manaphy91: Why if I have a namespace like a.b-c and in `b_c.clj` I have a typed named `Foo` I need to use it like a.b_c.Foo in my REPL?

4:39 *type

4:50 SagiCZ1: nuwanda_: yes, u should prefer (seq coll) to ((complement empty?) coll)

5:25 visof: ,(do (println "Hello") (println "world"))

5:25 clojurebot: Hello\nworld\n

5:25 visof: is this the best way to group the statements ?

5:28 Bronsa: visof: that's what do is for, yes

5:28 visof: Bronsa, Good, Thanks

5:33 borkdude: do a lot of people here still use lib-noir?

5:33 SagiCZ1: i find myself doing a lot of (map #(hash-map :a %) coll) i there a shorter way?

5:34 Bronsa: visof: obviously inside other macros that have implicit `do`s, you won't need it

5:34 SagiCZ1: visof: let, fn, when and others have implicit do's .. note that if does not

5:35 visof: 'let', 'fn', 'when' and others have implicit 'do's .. note that 'if' does not

6:06 cfleming: SagiCZ1: Your only other option is to use an fn: (map (fn [i] {:a i}) coll)

6:06 SagiCZ1: Which is not much shorter, but arguably clearer and also uses more efficient small maps

6:08 SagiCZ1: cfleming: oh.. so {} are different than hash-map?

6:09 cfleming: SagiCZ1: Yes, I believe it uses PersistentArrayMap for up to 8 items - larger maps will use a hash map.

6:10 SagiCZ1: See http://blog.factual.com/using-clojure-to-generate-java-to-reimplement-clojure for a very interesting discussion of the technique, and a patch that will hopefully be in Clojure 1.8

6:11 SagiCZ1: That will extend that technique to other data types too

6:13 SagiCZ1: I'm not sure how much difference it will make in practice in your case though.

6:14 SagiCZ1: I often have a similar need with vectors when using into with maps: (into {} (map (fn [i] [(name i) i]) coll))

6:17 SagiCZ1: cfleming: very good to know, thank you.. i wonder if changing the all the hash-map calls in my project will speed things up.. all of these are usually one key maps

6:18 (inc cfleming)

6:18 lazybot: ⇒ 6

6:19 cfleming: SagiCZ1: I'm not sure, you'd have to test it - if you use them a lot in tight loops it might help

6:19 SagiCZ1: mostly I just think the code is a little clearer since I think most people don't use hash-map much

6:20 whysoserious-: Hi, I have a probably noob question but I 've already been stuck for >15 minutes:

6:20 When trying to compile my project I see this error:

6:21 SagiCZ1: yeah.. i was too keen on using the #(..) construct everywhere.. but (fn [.] .. ) is not much worse

6:21 whysoserious-: ption: reduce already refers to: #'clojure.core.async/reduce in namespace: caniche.server, compiling:(/Users/jan/Dev/caniche/src/caniche/server.clj:1:1)

6:21 uh, once again:


6:21 CompilerException java.lang.IllegalStateException: reduce already refers to: #'clojure.core.async/reduce in namespace: caniche.server, compiling:(/Users/jan/Dev/caniche/src/caniche/server.clj:1:1)

6:21 and my ns sexp looks like this:

6:21 (ns caniche.server

6:21 (require [clojure.java.io :as io]

6:21 [compojure.core :refer :all]

6:21 [compojure.core :as route]

6:21 [clojure.core.async :as async :refer :all]

6:21 [ring.adapter.jetty :as ring]

6:21 [ring.util.codec :as c]

6:21 [ring.middleware.multipart-params :as multipart-params])

6:21 (import [org.apache.commons.io IOUtils]))

6:22 SagiCZ1: easy fix would be choosing an alias for core.async

6:22 instead of :refer :all

6:22 oh

6:22 just delete the :refer :all

6:22 whysoserious-: but

6:22 SagiCZ1: because you already have an alias there

6:22 whysoserious-: I don't use reduce anywhere

6:22 SagiCZ1: that doesnt matter

6:23 cfleming: Or explicitly referring the symbols you use, which most core.async code I've seen does

6:23 whysoserious-: I see

6:23 So, as I understand, there is another reduce function defined elsewhere

6:23 SagiCZ1: yes

6:23 whysoserious-: probably in clojure.core ;)

6:23 SagiCZ1: in clojure.core

6:23 ,(reduce + (range 10))

6:24 clojurebot: 45

6:24 cfleming: whysoserious-: :refer :all pulls in c.c.async/reduce, which overwrites clojure.core/reduce

6:24 whysoserious-: , (prn "Lol nice!")

6:24 clojurebot: "Lol nice!"\n

6:24 cfleming: whysoserious-: Whether you use it or not

6:24 whysoserious-: I see

6:25 So, most reasonable solution would be to import only a few functions right?

6:25 weavejester: Yes, you typically :refer only the minimum number of functions.

6:26 I usually have something like [clojure.core.async :as a :refer [go <! >!]]

6:27 whysoserious-: Hmm, let me check it..

6:28 cfleming: Awesome, works!

6:35 SagiCZ1: does anybody have an experience with plotting in incanter or jfreechart for that matter? i have a hard time configuring the colors and such

7:01 augustl: in liberator, I want to implement :processable? to handle JSON parsing and custom validation. What's the best way to ensure that it only does this validation on post and put?

7:01 manually check the ctx?

7:27 tom39291: { :name "Anakin Skywalker" :children [ { :name "Luke Skywalker" :children [] } ] }

7:27 vs

7:27 { :name "Anakin Skywalker" :children [ { :name "Luke Skywalker" } ] }

7:27 Which is most idiomatic? (The difference is whether lack of children should be represented as an empty list or as absense of that key)

7:28 cfleming: tom39291: Either is fine, it's a matter of taste really

7:29 tom39291: Most collection operations treat nil like an empty collection, so generally they're mostly equivalent.

7:34 tom39291: cfleming: Thanks

7:52 frankie_: Hi everyone

7:52 Happy holidays

7:54 I'm looking for somebody who knows his/her way around the Clojure class loader

7:54 I'm facing this issue with generated Java classes and I'm stuck https://groups.google.com/forum/#!topic/clojure/dwrJy5ZmcE4

7:54 tom39291: cfleming: What bit me is http://clojurepastebin.appspot.com/11589001

7:55 I just wondered whether my "fix" (use "seq" as I have done on line 15) was the right fix. Perhaps the right fix is for me to not use represent lack of children as an empty list.

7:56 augustl: how would you map /, /users and /users/:user-id with bidi?

7:57 Bronsa: tomjack: do you have a minimal reproducible case?

7:57 err, frankie_ ^

8:00 frankie_: @Bronsa any :gen-class that :extends javax.annotation.processing.AbstractProcessor and then is loaded at compile time

8:01 When the service loader is trying to create that class using Meta-INF/services you get ExceptionInInitializerError

8:02 Bronsa: frankie_: I don't have time to try and reproduce it myself but do you mind trying a patched version of clojure to see if that fixes your issue?

8:02 luxbock: does anyone here have experience with memory-mapping files with Clojure? I'm building a web app that allows one to explore the results of a computation that results in a large tree like structure, and I'm afraid that I might run into issues with limited memory if I load the entire file into memory every time the service needs to access a portion of it

8:02 I found this library: https://github.com/thebusby/clj-mmap

8:02 frankie_: @Bronsa I'll be happy to

8:03 I can also build a minimal project that reproduces the issue

8:03 Bronsa: frankie_: then try http://dev.clojure.org/jira/secure/attachment/13631/CLJ-979-v7.patch

8:04 frankie_: removing the lein dependency from the steps required to reproduce the issue would be the best incredibbly helpful

8:04 luxbock: right now my plan is to have files contain a header which contains rules for the structure of the tree structure stored, which I could then use to calculate the proper index to read from the file

8:05 frankie_: Sorry, what do you mean by removing the lein dependency?

8:05 Bronsa: frankie_: not requiring `lein uberjar` to reproduce

8:06 luxbock: so in this case the nodes of the tree would be stored as an array where the index matches up with the depth-first search order of the tree

8:06 but if I could somehow use memory-mapping with a Clojure map-like abstraction on top of it then that'd be very nice

8:12 tom39291: My problem is that zipper's children fn needs to return a seq, but in my "broken" implementation, I am not returning a seq. I am returning a list, which is not a seq.

8:13 luxbock: ##(seq? (list 1 2 3))

8:13 lazybot: ⇒ true

8:13 machty: from http://clojure.org/special_forms#recur: "Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged. recur is functional and its use in tail-position is verified by the compiler."

8:14 i'm reading Joy of Clojure and they show how you can convert a mundane-recursive implementation of pow to tail-recursive using a clojure and an accumulator

8:15 tom39291: luxbock: Okay. Oops. [1,2,3] is a vector, not a list. It's time I read up on collections in clojure, rather than winging it, as I've been doing so far.

8:16 luxbock: tom39291: you can call (seq x) on most (all?) Clojure data structures to convert them

8:17 machty: so is there tail-recursive optimizaiton or not? the docs on recur seem to imply there's not...

8:17 ohhh nevermind, sorry, didn't realize the inner helper closure used `recur`... disregar

8:18 luxbock: machty: the point of recur is that wherever you can use, the compiler can optimize the call

8:18 so when defining a recursive function, you can make sure you are getting the optimization by using recur instead of calling itself

8:18 machty: luxbock: confirm, and (current versions of) clojure won't tail-optimize otherwise

8:23 jonathanj: how does one correctly reverse a string in Clojure? ie. (correct-reverse "noël") => "lëon"

8:23 Bronsa: ,(clojure.string/reverse "noël")

8:23 clojurebot: "lëon"

8:24 jonathanj: clj-codetip.handler=> (string/reverse "noël")

8:24 "l̈eon"

8:24 Bronsa: jonathanj: that looks like an issue in the encoding of your repl

8:25 jonathanj: ah, right you are, i guess this shell is old (i recently switched shells and didn't resource all of my terminal tabs)

8:31 Bronsa: actually the issue seems to be using a precomposed version versus the combining character version

8:32 ,(vec "noël")

8:32 clojurebot: [\n \o \e \̈ \l]

8:32 Bronsa: jonathanj: that makes sense then

8:32 jonathanj: ,(vec "noël")

8:32 clojurebot: [\n \o \ë \l]

8:39 dysfun: no, the behaviour is predictable perhaps, but it does not make sense

9:26 augustl: does Prismatic/schema have functions for returning data about the error instead of throwing an exception?

9:31 Kristien: FTR you can easily construct a wrapper yourself: https://gist.github.com/rightfold/66b0397e1b1ad3e265e6

9:38 augustl: Kristien: yeah, but I was hoping my users would get something more, not just a string :)

9:40 Kristien: oof

9:52 luxbock: augustl: Clojure or CLJS?

9:53 vivekramaswamy: Hello all a quick question, this does not work (take 10 (repeatedly #((rand-int 10))) but this works (take 10 (repeatedly (fn [] (rand-int 10)))) why?

9:55 luxbock: ##(macroexpand-1 '#((rand-int 10)))

9:55 lazybot: ⇒ (fn* [] ((rand-int 10)))

9:55 luxbock: vivekramaswamy: think of #(...) as the body of a (fn [] ...)

9:57 vivekramaswamy: ok, but isn't #(...) a shortcut for a function itself

9:58 luxbock: vivekramaswamy: yes but the way you are using it expands to (fn [x] ((rand-int 10)), so you end up trying to call a random integer as though it was a function

9:58 if you swap it with #(random-int 10) it will work

9:58 err, #(rand-int 10)

9:59 vivekramaswamy: Thanks a lot for the explanation, I think I get it.

10:02 akkad: how do you resolve an ip in dns in clj?

10:03 davorb: what is the preferred way to install clojure on ubuntu/debian? apt seems to have a rather old version (1.4, or does that not matter?)

10:04 and wtf is cider? what advantages does that have over slime?

10:04 akkad: davorb: lein

10:05 expez: davorb: are you sure that's the most recent? clojure 1.4 is from like 2012.

10:05 akkad: http://www.emacswiki.org/emacs/nREPL.el

10:05 davorb: expez, yeah, i just did apt-cache search clojure and got 1.4 as the latest

10:05 expez: davorb: slime is for common lisp, cider is for clojure.

10:06 vivekramaswamy: here is link that explains cider quite well https://www.youtube.com/watch?v=4X-1fJm25Ww

10:06 expez: you could use a clojure backend for slime, swank-clojure IIRC, but you don't get much clojure specific functionality doing that

10:06 akkad: if anyone ever complains about clojure being difficult to learn, have them implement what they are doing in CL for a couple of weeks.

10:07 davorb: don't know much about clojure, but i like cl. except some stuff... like loop and how it handles files. and threads support isn't anything to write home about either.

10:07 expez: davorb: if you don't give a shit about tooling and just want a repl then you can use this instead of cider: https://github.com/clojure-emacs/inf-clojure

10:08 davorb: expez, i just want to know what the most popular choice is. cl-folks use slime. what do clojure-men use?

10:08 expez: davorb: cider is the most popular option for emacs users

10:09 davorb: guess i'll use that then

10:10 vivekramaswamy: :davorb many of the people I know are using cider also cursive that runs as a plugin in intellij seems to be getting quite popular

10:11 mi6x3m: hey clojure, I have a protocol implemented for a java interface Foo

10:11 davorb: vivekramaswamy, i'll be staying away from intellij.

10:11 mi6x3m: but somehow it's not resolved for a class implementing Foo

10:11 could this bee?

10:11 -e

10:12 never mind

11:05 hellofunk: davorb: what's wrong with intellij? i've been thinking about switching to Cursive

11:05 davorb: most of what i've seen has been positive, so i'm curious to know about gotchas

11:21 profil: How do I connect to the same repl as my ring application runs in? I start it by running `lein ring server-headless`.

11:31 justin_smith: expez: actually slime-swank has a lot of clojure specific functionality, it has better debugging than cider has ever had. slime-swank was discontinued because the upstream slime protocol kept breaking in incompatible ways and it was a pain in the ass to develop against. But it is still usable at its last released state.

11:33 expez: justin_smith: yeah, nobody is interested in working on clojure debugging. Personally I think that's a shame, but tools.trace / spyscope usually get the job done.

11:33 borkdude: I'm looking for a library that can help me optimize/compress uploaded jpeg files in clojure, any tips?

11:33 justin_smith: the ironic thing is that we dropped slime-swank because breaking changes happened too often, then lo and behold we replace it with cider, which has *even more frequently breaking changes*

11:33 expez: not nobody. cursive has good clojure debugging.

11:33 and slime-swank clojure debugging still works

11:34 expez: justin_smith: cider is lacking integration tests. It's getting so large nobody is using the entire feature set so breakage sometimes goes unnoticed for some time heh

11:34 justin_smith: that's a small part of the issue

11:34 it's also that apis are changed frequently, and due to elisp's compilation model, this requires full cleans and recompiles of elc code

11:35 but the upgrade of versions does not do this automatically

11:35 expez: anyway, some breakage is to be expected prior to version 1.0 imo

11:35 when I upgrade the old cider is always deleted and the new one recompiled

11:35 I have no idea how people end up in situations with outdated .elc files lying around

11:35 justin_smith: expez: I use a lot of pre-1.0 stuff, I have never seen anything else that unstable

11:36 expez: it's easy

11:36 for example, update cider but don't upgrade clojure-mode

11:36 boom, you have stale broken elc files

11:36 the auto-updater doesn't catch that

11:37 expez: cider requires clojure-mode 3.0 according to its package info

11:37 justin_smith: expez: right - but the next cider will *also* require clojure-mode 3.0

11:38 and clojure-mode will break if you replace cider and don't also recompile clojure-mode

11:38 elisp is weird

11:38 Bronsa: clojurebot: elisp is weird

11:38 clojurebot: Roger.

11:38 expez: justin_smith: that sounds unbelievable

11:39 justin_smith: expez: it happens to a lot of us, just check out the cider bug tracker

11:39 happened to me more than once

11:39 expez: clojure-mode as no deps, how can it possibly require a recompile just because cider changed? Oo

11:39 justin_smith: I've used emacs for over a decade, never had anything break as much and as badly as cider

11:41 samebchase: Hi Everyone, I'm trying to remotely run a function using https://github.com/clojure/java.jmx . Basically a function that does some cleanup before the jar can be shutdown. In the documentation there, it looks like the `:gc` operation is invoked. How do I invoke an arbitary function using JMX? Thanks.

11:42 justin_smith: expez: I'm perfectly willing to accept I am wrong about what caused / fixed my issue. Point remains that weird things broke in weird ways that were only fixable by nuking it all from orbit.

11:42 expez: :D

11:43 justin_smith: expez: and the critical difference was going from nuking cider, to nuking cider+clojure-mode

11:43 expez: writing integration tests for cider is actually a hard problem, because it depends on cider-nrepl for much of what it does

11:43 we're not writing any integration tests for clj-refator for the same reason. We just couldn't manage to talk to the refactor-nrepl middleware using ecukes

11:43 clojurebot: I don't understand.

11:44 expez: so we only have integration tests for the elisp bits, but we have to mock out the replies from the middleware

11:45 justin_smith: expez: I have developed elisp that integrates with an external process forming a unified "app", I feel your pain

11:46 borkdude: Here I see a library called imagez at version 0.3.2 https://github.com/mikera/imagez/blob/master/project.clj - yet on clojars I see a library imagez with version 0.5.0, but the group id is a bit different. Cant' seem to find the source code of the newer one.

11:46 justin_smith: borkdude: are the clj files not inside the jar itself?

11:47 borkdude: hmm, yeah, good one

11:47 but still I would like to see the repo somewhere

11:47 justin_smith: many editors can open a jar directly, and browse files inside it

11:47 borkdude: yeah, good luck on that part...

11:47 borkdude: http://crossclj.info/ns/net.mikera/imagez/0.5.0/project.clj.html no link here either, I could ask the author

11:48 justin_smith: borkdude: I think he is on twitter with the same handle?

11:48 borkdude: justin_smith yes

12:30 kl: https://github.com/clojure/core.match I'm a little confused - as core, shouldn't I just be able to require it, without specifying dependencies to maven/lein ?

12:30 Empperi: kl: core.* is different than core

12:31 so no, you need to require those

12:32 kl: Empperi: by "require those", do you mean put dependency info into maven/lein too, or just (require) ?

12:32 Empperi: dependency too

12:32 kl: so, what's "core" about it?

12:32 Empperi: they are considered to be part of core in the future

12:33 and if I'm not mistaken they need the Clojure contributor agreement to allow contribution

12:34 justin_smith: if they are ever to be included in clojure.core that would be a prerequisite, yes

12:34 Empperi: so one can think them as "part of official Clojure project but not part of Clojure the language"

12:38 kl: Thanks, that fits my mental model now :)

12:57 [org.clojure/core.match "0.3.0-alpha4"] shouldn't pasting this into the repl work, for getting the dependency?

12:58 It's listed under "Leiningen dependency information:" for clojure/core.match's readme

12:58 I'm getting: CompilerException java.lang.ClassNotFoundException: org.clojure, compiling:(NO_SOURCE_PATH:0:0)

13:00 zinfandel: Hi. What's the right way to define tests which would use data from a sequence? Let's say I want to test function f and I have a sequence [{:in x, :out (f x)}...{:in x20, :out (f x20)}] and based on these data I want to define 20 tests. So basically, I want to expand that sequence into the body. I guess it's possible with macros but isn't there a simpler way, which I can't find?

13:00 ambrosebs: kl: that goes in the :dependencies vector in your project.clj

13:00 zinfandel: Let's say I am using clojure.test or midje it doesn't really matter

13:01 andyf: zinfandel: With clojure.test you can call the is macro inside of functions, or the body of a doseq. Not sure if that will do what you want, but it is one way to invoke is 20 times without writing it 20 times.

13:04 dnolen_: kl: you need to put that in your project.clj or if you're using Maven directly your pom.xml

13:05 justin_smith: zinfandel: it does kind of matter because clojure.test is very flexible in comparison to midje

13:06 you can do all kinds of fancy things with clojure.test just by using function composition / first class function passing. midje is much more restrictive about how you use it, and you'll usually need to write a macro in that case.

13:06 zinfandel: andyf: Tried it before. The problem was that it was running the tests each time I did :reload. Tried again now and that problem disappeared. Thanks.

13:08 justin_smith: Good to know. I was got such assumption when I saw => macro. I was like, "Eh, how does it work, and how do I manipulate with this thingy"

13:08 s/was got/got/

13:09 kl: Thanks guys

13:12 zarkone: hello all. May be somebody knows about isomorphic Om + Nashorn apps? is it possible nowdays?

13:13 zinfandel: andyf: (doseq [test tests] (is (= :out (f :in))) does work, but is it possible to deftest inside doseq?

13:14 The first problem is that deftest wants Symbol

13:14 andyf: I don't know. You want that to get extra messages when a test fails?

13:14 justin_smith: zinfandel: why would you need to deftest?

13:14 andyf: If so, is takes a last arg that is a string containing whatever you want, e.g. return value of a format call.

13:15 justin_smith: zinfandel: you can put that whole doseq inside a deftest

13:16 zinfandel: Yes I realize that. But it would be messy when I have a lot of tests. In fact each element in the collection is a map with tests of different type.

13:17 So I want to define a specific test with specific name for each element of top collection.

13:17 justin_smith: then you want a macro that creates a deftest form, inside doseq

13:17 but why do you need those names? there is also test/testing

13:17 or as andyf mentions, the third arg to is

13:18 zinfandel: justin_smith: I want to see on which input data it failed.

13:19 Yeah, I guess third arg to 'is would do the job.

13:19 justin_smith: zinfandel: test/testing, and the third arg to is, are both capable of providing that context

13:20 err, second arg actually?

13:20 zinfandel: Actually my use case goes even deeper, I have a sequence of maps that contain maps of sequences of tests for different types of data. :)

13:21 justin_smith: so a combo of testing / extra if args would help

13:21 zinfandel: justin_smith: Yes, but well, it's the third element in the form

13:21 justin_smith: you'll get a) test that failed b) testing clause message c) is extra arg d) actual failed expression for each failure

13:22 a won't be worth much, because you are bundling a loop like that, but b-d should all provide useful info

13:24 zinfandel: Yes, that should do the job, however they wouldn't be logically grouped, of course I can put strings like "test1.subtest1.subsubtest1" but they still wouldn't be grouped at the data-structure level.

13:25 Thanks

13:26 justin_smith: they could be logically grouped though

13:26 (doseq [group test-groups] (testing (:message group) (doseq [test (:tests group)] ...)))

13:27 then you don't need to do that silly string construction at all

13:27 zinfandel: Oh, I see.

13:27 I thought that I can group them only with deftest.

13:28 justin_smith: well that whole thing would be inside a deftest form

13:28 but yes, the point of testing is that it is for grouping

13:29 zinfandel: Yes, and I thought that I have to use deftest inside a doseq

13:31 munderwo: Hi all. I’m getting a wierd error in this code.

13:31 https://www.refheap.com/95493

13:31 its saying that “<! used not in (go …) block ..

13:32 Bronsa: munderwo: for expands its body in a (fn [] ..), go blocks cant cross fn boundaries

13:32 munderwo: I dont understand as it IS in a go block. is there something im missing? does a for loop not remove the go block for some reason?

13:32 ahhhH! bugger.

13:32 Bronsa: munderwo: aka you can't <! & co inside a for statement in a go block

13:33 munderwo: macro expansion… dammit

13:33 any suggestions to work around this?

13:33 justin_smith: munderwo: the glib answer would be "don't use for"

13:34 AimHere: Could it be that the for block is lazy

13:34 So it's resolved only after you left the go block

13:34 justin_smith: AimHere: it is lazy, but that's not the issue here

13:34 Bronsa: AimHere: no, read my first answer

13:34 justin_smith: AimHere: the merge-with forces it

13:34 AimHere: Fair enough

13:34 munderwo: right. which I guess I could do…. its the nested for loop that I want. Is there a nicer way to do the nested iteration?

13:34 AimHere: I just had a similar problem just yesterday

13:34 munderwo: nicer/other

13:35 Bronsa: munderwo: I believe you're stuck with using loop/recur or refactoring the go block

13:35 justin_smith: munderwo: another thing to look out for is (keyword sha) is likely to make keywords that are technically illegal

13:35 not that they keyword function cares

13:35 ,(keyword " this is a ...... keyword.///////")

13:35 clojurebot: : this is a ...... keyword.///////

13:36 munderwo: right. So loop/recur doesnt expand to a (fn [])

13:36 yeah, I’ve got to sort out my keyword stuff. but im putting that off for a bit right now

13:36 justin_smith: munderwo: not that this is likely to break anything as is

13:37 but it could come up if you try to serialize to edn

13:37 or if you try to use hypothetical stricter future clojure version

13:37 munderwo: yeah. its fine at the moment. ok. i’ll keep that in mind for edn. I have worse keywords :)

13:37 :/foo/bar/file.clj springs to mind :)

13:38 justin_smith: munderwo: also, you could avoid some complexity by just not turning the keys into keywords

13:38 (bbloom has a few nice rants on this topic)

13:38 munderwo: it would be nice if keyword didnt create invalid keywords. but I can see why they might.

13:38 I thought the idiomatic way of creating map keys in clojure WAS to use keys ?

13:38 *keywords

13:39 justin_smith: munderwo: for literal keys, sure

13:39 but these are constructed keys that do not exist as literals anywhere in your code

13:39 so making it a keyword gains you little to nothing

13:39 munderwo: ahh I see the distinction… that makes sense.

13:40 justin_smith: strings are interned, so you get similar fast lookup iirc

13:40 munderwo: ok so suggestions on doing a nested loop not using for? some kind of loop recur?

13:41 dysfun: am i misunderstanding :repl-options :init for leiningen? i can't seem to make it automatically call a function because it complains the var doesn't exist. i've even tried injecting a require into there, but it still complains. any ideas? https://www.refheap.com/95494

13:44 justin_smith: &(loop [i 3 a []] (if (zero? i) a (recur (dec i) (conj a (loop [j 3 b []] (if (zero? j) b (recur (dec j) (conj b [i j]))))))))

13:44 lazybot: ⇒ [[[3 3] [3 2] [3 1]] [[2 3] [2 2] [2 1]] [[1 3] [1 2] [1 1]]]

13:44 justin_smith: munderwo: ^^ something like that

13:44 ugly, I'll admit, but it works

13:45 munderwo: cool. I’ll give it a try. I also just realised that I can probably macro-expand the function as it exists now and I might get some idea of how its structured to see how I can implement it .

13:45 justin_smith: munderwo: the best way to macro-expand for is to take mushrooms first and wait until you are peaking

13:46 it won't make any more sense

13:46 but the lack of sense will be more entertaining

13:46 munderwo: ha! it probably makes even less sense in clojurescript :)

13:46 dysfun: justin_smith: some of the code i've seen might better be explained by heroin

13:47 justin_smith: dysfun: no man, look at ##(macroexpand '(for [i (range 10)] (dec i)))

13:47 lazybot: ⇒ (let* [iter__4760__auto__ (clojure.core/fn iter__17887 [s__17888] (clojure.core/lazy-seq (clojure.core/loop [s__17888 s__17888] (clojure.core/when-let [s__17888 (clojure.core/seq s__17888)] (if (clojure.core/chunked-seq? s__17888) (clojure.core/let [c__4758__auto__ (... https://www.refheap.com/95495

13:47 dysfun: cool

13:47 justin_smith: dysfun: that is only explainable by wizardry or hallucinagens

13:48 (be sure to follow that refheap link)

13:48 * dysfun personally just avoids for because i can never remember how it works

13:48 justin_smith: dysfun: munderwo: look at that refheap link, and consider the fact that all that was iterating on was (range 10)

13:48 dysfun: uhuh

13:48 andyf: for and doseq have a lot of options like :when and :let that make them more useful, and more complex in their implementation

13:49 justin_smith: andyf: looking at that expansion (which uses none of those features), the chunking optimizations seem to be the biggest obfuscator

13:49 andyf: but the main thing adding extra code there is optimizing for chunked sequences.

13:49 munderwo: yeah… the for form was super nice.

13:50 andyf: pprint, man, pprint!

13:50 still not pretty, to be sure, but less of a wall.

13:50 TEttinger: &(mapv #(mapv (partial vector %) (range 3)) (range 3))

13:50 lazybot: ⇒ [[[0 0] [0 1] [0 2]] [[1 0] [1 1] [1 2]] [[2 0] [2 1] [2 2]]]

13:51 justin_smith: TEttinger: that leads back to the original problem - the main logic is inside an fn

13:51 TEttinger: he needs a way for the body of the expression not to be in an fn

13:51 TEttinger: ah

13:51 munderwo: because of the core.async infection :(

13:51 and the fact that everything is async….

13:52 TEttinger: I'm not familiar with core.async right now

13:52 munderwo: once you go core.async…. everything is core.async ....

13:53 TEttinger: core.a-sunk

13:53 munderwo: well not everything.. but you find your-self adding go blocks all over the place… well thats what I’ve found anyway

13:53 justin_smith: munderwo: ztellman's talk at the last conj is on that topic btw

13:53 munderwo: ooh… I was there for the conj, but I think I missed that talk. I’ll have to watch it.

13:53 justin_smith: munderwo: he contrasts core.async, his manifold lib, and prismatic/plumbing - each does a very similar thing, with varying levels of contagion / generality

13:54 plumbing being super general and not at all infectious, and async being the opposite extreme

13:54 dysfun: is it online? i'm using manifold with core.async because aleph

13:54 munderwo: the reason I have all this core.async stuff is using nodejs libs… which are all async… so I need a way to deal with all the callback stuff.

13:54 justin_smith: yeah, it's on the clojure conj youtube account

13:55 $google clojure ztellman manifold conj video youtube

13:55 lazybot: [Clojure/conj 2014 Notes - Forays into simplicity] http://eigenhombre.com/clojure/2014/11/27/conj-notes/

13:55 justin_smith: oops, wrong link!

13:55 munderwo: close though

13:55 justin_smith: https://www.youtube.com/watch?v=3oQTSP4FngY&index=17&list=PLZdCLR02grLoc322bYirANEso3mmzvCiI this is the one

13:55 munderwo: $google clojuretv ztellman minifold conj youtube

13:56 justin_smith: their api limits kind of suck lately :(

13:56 need to get that duckduckgo plugin in

13:57 munderwo: as a relative newcomer to IRC im always amazed by all the little tools that people have.

13:58 justin_smith: munderwo: it's fun working on the channel bot, because you get to see people use it (unlike working on other software, where theoretically you know it gets used but you don't get the direct gratification)

13:58 (I did a pretty major lazybot update not long ago)

14:00 benmoss: is there a better idiom for doing things like `(map #(if (foo? %) (modify %) %) coll)` ?

14:00 justin_smith: benmoss: it would be nice to have an "update-if"

14:01 macro

14:01 CodeWar: [Question about implementing a language on top of JVM] Do you just compile the source to ByteCode and classes and give it to the VM and wash your hands off or is there an interpreter that is written by the language designer

14:01 justin_smith: maybe it exists in useful, or one of those other util libs

14:01 benmoss: yeah i suppose it would have to be a macro

14:01 justin_smith: CodeWar: clojure has no interpreter

14:02 AimHere: That doesn't necessarily mean you can't write one for your own purposes, mindyou

14:02 CodeWar: justin_smith: so its straight source to bytecode and let JVM interpret and JIT on its own

14:02 justin_smith: CodeWar: clojure emits bytecode and has the vm run it directly (and hotspot likely improves said bytecode depending on host settings)

14:02 well, the jvm doesn't quite interpret per-se, but yeah

14:03 CodeWar: AimHere: care to elaborate how? Meaning how do I load a class let JVM transfer control over to me until I can interpret profile and then occasionally for parts of the program transfer control back to the VM

14:03 justin_smith: CodeWar: the vm is the only thing that is ever doing anything

14:03 CodeWar: I am aware of Graal but curious if there is something that already exists that languge designers make use of

14:03 justin_smith: clojure uses the asm lib

14:04 mi6x3m: hey clojure, what would you rather call an event listener function?

14:04 on-xyz or xyz-handler?

14:04 clojurebot: No entiendo

14:04 justin_smith: CodeWar: in fact, clojure embeds a copy of the asm lib inside its own source

14:08 CodeWar: justin_smith: what libraries/frameworks do you use for Source to AST generation

14:09 justin_smith: CodeWar: Clojure is that library, and the AST transformation is trivial, Clojure code is very close to being an AST already

14:09 but Bronsa or arrdem could tell you more detail

14:12 CodeWar: big picture, a reader expands certain forms, then macros are expanded, and finally the resulting tree is turned into an AST by some relatively straightforward tree operations

14:12 CodeWar: justin_smith: got it. I forget this is a dialect of LISP so its likely easier than other languages

14:49 augustl: any liberator peeps around? Looking for advice on composing decision functions

14:49 I could just copy `(if (vector? decision) (first decision) decision)` but that seems a bit lame

14:51 AimHere: You could multimethod it

14:54 TEttinger: there really should be a general "if seqable? then the first item, else the item" idiom, but it gets weird with strings and maps

14:54 ,(sequential? {})

14:54 clojurebot: false

14:54 TEttinger: ,(sequential? {:a :b})

14:54 clojurebot: false

14:54 TEttinger: ,(seq {:a :b})

14:54 clojurebot: ([:a :b])

14:54 augustl: seems like most libraries has landed on [true result] and [false error] for returning values that signify either success or error

14:55 dysfun: yeah, it's sort of reminiscent of the 'Either' datatype in haskell

14:57 augustl: hmm, in the case of liberator, I also have to actually manually merge the truthy values as well

14:58 mi6x3m: is there some version of case which returns nil on default?

15:06 Frozenlock: mi6x3m: this? (case "allo" "not-allo" true nil)

15:06 TEttinger: hm ##(case 2 0 "zero" 1 "one")

15:06 lazybot: java.lang.IllegalArgumentException: No matching clause: 2

15:06 andyf: case takes an optional last arg which is an expression returning a default value

15:06 TEttinger: ##(case 2 0 "zero" 1 "one" nil)

15:06 lazybot: ⇒ nil

15:07 TEttinger: neat andyf

15:08 (inc andyf)

15:08 lazybot: ⇒ 18

15:08 andyf: Doc strings can be informative sometimes :)

15:09 Frozenlock: I rest my case.

15:09 *badum tss*

15:10 justin_smith: case is definitely underappreciated

15:10 (or maybe it's just that cond is overused - one of these)

15:20 augustl: decision composition for liberator https://gist.github.com/augustl/518abd83173444747cd2

15:20 need to familiarize myself with the stdlib, I use loop way too often..

15:24 justin_smith: augustl: I think you'll find things get simpler if you always have cur-fn return a vector (even if it is a vector of only one item)

15:25 never mind, now I see what happens there

15:26 dnolen_: cfleming: found out the source of the unresolved issue - was reverting my IntelliJ file

15:27 justin_smith: augustl: why can't (if (= truthy (if result true false)) ...) just be (if result ...)?

15:30 augustl: justin_smith: I need to make termination on truthy or falsy pluggable, since liberator has :processable? (truthy) and :malformed? (falsy)

15:30 justin_smith: so the "if" returns true or false depending on the truthyness of result, and then I compare with the "truthy" argument passed in

15:30 not sure if there are better ways of doing that

15:30 s/the "if"/the inner "if"/

15:31 justin_smith: (if ({:malformed false} result result) ...)

15:31 that will be false for :malformed and otherwise just be the input

15:31 oops, I missed the ?

15:32 augustl: so it'll be called like `:processable? (comp-decision true foo bar)` or `:malformed? (comp-decision false baz maz)`

15:32 justin_smith: ahh

15:32 augustl: the liberator state machine needs false or true to continue depending on the hook :)

15:32 justin_smith: in that case just replace (if result true false) with (boolean result)

15:33 augustl: ah, that's much better

15:33 justin_smith: ,(map boolean [nil false 1 0 true []])

15:33 clojurebot: (false false true true true ...)

15:33 justin_smith: clearly I didn't get the subtlety of what you were doing with liberator there though

15:33 augustl: this is pretty "low level" stuff so perhaps a manual "loop" makes sense

15:34 justin_smith: looks like it could easily be a reduce to me

15:34 augustl: justin_smith: normally, you'd have something like :processable? (fn [ctx] (if whatever true [false {:add-this "to the context"}]))

15:34 justin_smith: you always go through the list in order, you have an accumulator that is updated at each step

15:34 augustl: the vector is so that liberator can add stuff to the context while returning what liberator considers a "falsy" value

15:35 hmm, will try to rewrite as a reduce

15:35 liberators definition of "falsy" is documented under "decision functions" here FYI http://clojure-liberator.github.io/liberator/doc/execution-model.html

15:37 justin_smith: (reduce (fn [acc cur-fn] (let [decision (cur-fn ctx) [result context-update] (if (vector? decision) decision [decision decision]] (if (= truthy (boolean result)) (liberator.core/update-context ctx context-update) (reduced decision))) initial-ctx fns)

15:37 something like that

15:38 my parens are likely off

15:38 clearly acc should be ctx or visa versa

15:38 but that's the gist of it

15:39 notice the destructuring cleverness with decision (too clever?)

15:40 augustl: destructuring is neat :)

15:40 who says Clojure doesn't have "weird syntax" :)

15:41 justin_smith: haha

15:41 kl: Is it possible to exit early from a reduce? Or is there some alternative that would permit such?

15:41 justin_smith: kl: reduced

15:41 (doc reduced)

15:41 clojurebot: "([x]); Wraps x in a way such that a reduce will terminate with the value x"

15:42 kl: justin_smith: I'm not sure how that relates to folding/reduceing?

15:42 justin_smith: ,(reduce (fn [acc x] (if (> x 10) (reduced (+ acc x)) (+ acc x))) (range))

15:42 clojurebot: 66

15:42 justin_smith: kl: it says "such that reduce will terminate with the value x"

15:43 that is precisely and only about reducing

15:43 note above I passed an infinite sequence to reduce, but it only used the values up to 10

15:43 kl: Ahh, so it's used *inside* a reduce, I see

15:44 justin_smith: well values up to 11 or whatever but hopefully you get the point

15:48 kl: justin_smith: thank you mate. This is really useful

15:50 ordnungswidrig: justin_smith: it's an interesting proposal to use a reduce to execute the decision graph

15:51 justin_smith: ordnungswidrig: the logic of augustl 's loop maps perfectly to reduce

15:51 hehe, maybe I should have said "projects perfectly", map is a bit overloaded around here as a term :)

15:51 ordnungswidrig: yes, it would even reduce the stack :-)

15:52 But you're missing that the fns are not know a priori. But a loop recur would work.

15:53 Or a reduction over an infinite sequence that it ignored, *cough* *cough*

15:53 justin_smith: ordnungswidrig: in his case they are, they are a sequence and he repeatedly gets the next item

15:53 ordnungswidrig: Oh, sorry, I skipped that par.

15:53 justin_smith: and having some case that hits reduced will deal with the infinite sequence as nicely as the loop version did

15:54 like I said, reduce is a perfect projection of the logic of his loop :)

15:54 ordnungswidrig: yes, absolutely

15:54 I toyed around with decision function composition à la ring middleware the other day but I did not find some expressive and clear way yet.

15:55 justin_smith: ordnungswidrig: have you looked at prismatic/graph?

15:55 it's an interesting and elegant data driven approach to the domain

15:55 I mean function composition can also be pretty elegant, but I like the declarative style of graph

15:57 graph is part of the "plumbing" lib https://github.com/Prismatic/plumbing

15:57 ordnungswidrig: justin_smith: yes, it's very promising. However I'm not sure how it would fit liberator. I see that there's need to factor out common functionality that might span multiple of liberator decision functions and thus raises the question of how to compose them.

15:58 But I'm currently thinking that is something you can build on top of liberators decision map abstraction, not something to be provided by liberator

15:58 justin_smith: ordnungswidrig: the graph examples show quite complex interactions between values in a graph block

15:59 ie. the map providing the count, mean, mean-square, variance built on top of each other

15:59 ordnungswidrig: you could for sure build something like liberator on top of plumbing.

16:00 justin_smith: yeah, I don't know the specifics of how liberator uses stuff yet (I have planned to look into it), so I can't comment on that side of it

16:00 augustl: justin_smith: makes sense with a recur, that's conceptually what I'm doing

16:01 building a return value for a collection

16:01 s/recur/redue/

16:02 justin_smith: one of my a-ha moments in clojure was when I learned to recognize the signs that something could be expressed as reduce

16:02 (because often if it can be, that is the best representation of the algorithm)

16:03 augustl: was not aware of "reduced" though, that helps

16:03 I some times miss my "break" :)

16:03 justin_smith: yeah, reduced is a total game-changer

16:03 along with reducers and transducers if you want to get advanced

16:03 augustl: does it actually terminate the reduction though? In the example it just returns a static value

16:03 for me it's important that I actually return the value being reduced at that specific point, and doesn't go further

16:04 justin_smith: augustl: if you add a print to the function body you will see nothing else is calculated after it hits reduced

16:04 and yes, definitely returns the precise value you pass to reduced, that's kind of the whole point :)

16:11 TMA: ,(doc reduce)

16:11 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i...

16:11 TMA: ,(doc range)

16:11 clojurebot: "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity. When step is equal to 0, returns an infinite sequence of start. When start is equal to end, returns empty list."

16:12 TMA: ,(reduce + (range 12))

16:12 clojurebot: 66

16:15 TMA: is there a common lisp's (reduce f seq :from-end t) equivalent? or shall I just reverse the sequence manually?

16:17 augustl: updated the liberator decision composition gist fyi https://gist.github.com/augustl/518abd83173444747cd2

16:17 justin_smith: TMA: reverse manually, but use rseq if the input is a vector

16:17 rseq is basically free because of how vectors are implemented

16:18 augustl: opted against the destructuring magic I see

16:19 augustl: justin_smith: how sloppy of me :) forgot all about it

16:21 TMA: ,(map (fn [x] (apply (fn ([] :a) ([x] :b) ([x y] :c) ([& r] :d)) x)) [[] [1] [1 2] [1 2 3]])

16:21 clojurebot: #<CompilerException java.lang.RuntimeException: Can't have fixed arity function with more params than variadic function, compiling:(NO_SOURCE_PATH:0:0)>

16:21 TMA: ,(map (fn [x] (apply (fn ([] :a) ([x] :b) ([x y] :c) ([x y & r] :d)) x)) [[] [1] [1 2] [1 2 3]])

16:21 clojurebot: (:a :b :c :d)

16:22 TMA: oh, nifty

16:22 justin_smith: haha, an arity counter

16:36 kl: is there an idiomatic way to format s-expressions, as far as indentation goes?

16:38 mearnsh: kl: https://github.com/bbatsov/clojure-style-guide#body-indentation

16:43 kl: mearnsh: how about where the closing parens go?

16:43 Whoops: " Place all trailing parentheses on a single line instead of distinct lines."

16:43 expez: ^

16:43 kl: Why is that a good thing? It harms readability for me

16:44 expez: That's just habit

16:45 andyf: kl: takes unnecessary vertical whitespace. People who program a Lisp for a while tend to not look at the parens very often, but expect it to be indented well, usually automatically by their text editor/IDE, and use that.

16:46 kl: If you want to show Lisp/Clojure/Scheme code to someone else and ask for comments or review, and you have trailing parens each on a line on their own, they will cringe.

16:47 expez: in 99% of the cases indentation makes it clear what goes with what. In the other rare case your editor probably has facilities for highlighting pairs of parens which you can rely on.

16:47 Nobody ever argues that Python code is unreadable due to missing { } pairs :) It's just habit.

16:49 tolstoy: To be honest, when using a {} language, I now wish it was okay to condense lines of "}" onto a single line.

16:49 ... else { return finish(); }}}}}

16:49 justin_smith: kl: it's natural for good style to be dependent on that language. In fact it's helpful to me that lisps do not use trailing brackets, because then I can transition from reading a lisp to reading an algol (like c, c++, java, js) more easily.

16:50 dnolen_: cfleming: hrm, actually no, still happening, I've got a screenshot for you.

17:38 cfleming: dnolen_: Cool, can you send it to cursive@cursiveclojure.com?

17:39 dnolen_: cfleming: done

17:39 cfleming: dnolen_: There's actually something else you could try. It's very strange to get a symbol resolution problem that's sporadic - normally it always works, or it doesn't. I'm wondering if your indexes might have been corrupted. Try File->Invalidate Caches and Restart, that will force an index rebuild.

17:40 dnolen_: cfleming: will try that next time - there's no rhyme or reason to the bug as far as I can tell

17:41 cfleming: it usually happens when I switch to a file/tab

17:41 cfleming: dnolen_: So it will suddenly happen in a file you already have open in a tab when you switch to it?

17:42 dnolen_: cfleming: I believe so but I will have to verify

17:43 cfleming: dnolen_: Ok - don't spend much time on it, I suspect it's actually your indexes, especially since no-one else has reported it. You don't have to wait for the problem to rebuild your indexes, if you do it now with any luck the problem won't come back.

17:43 dnolen_: cfleming: ok invalidated / restarted, will let you know if I see it again

17:44 cfleming: dnolen_: Great, thanks.

17:44 SagiCZ1: most of the time when Cursive bugs out or does something weird, restarting and invalidating caches helps

17:45 cfleming: Yeah, they still have some bugs in their indexing framework, although it seems to happen more with Clojure than with Java - it might be bugs in my code, or I'm just using their framework in different ways

17:45 which I almost certainly am.

17:45 SagiCZ1: i dont even know what the indexes are for

17:46 cfleming: Basically any information that has to be visible globally is indexed - in Cursive that's things like metadata about vars, information about all the namespaces and so forth.

17:47 That's why when that gets screwed up the first thing to go is the symbol resolution.

17:47 SagiCZ1: i see.. by the way are way any closer to being able to slurp into quoted strings?

17:49 gfredericks: SagiCZ1: do what?

17:49 SagiCZ1: i think there is no reason why paredit slurping cant work on strings

17:50 "hello |" world --- slurp --> "hello world"

17:50 cfleming: SagiCZ1: No, no reason other than that I haven't got around to it yet. I have a backlog of paredit related issues, I'm going to do a paredit focused release soon.

17:51 SagiCZ1: cfleming: alright, sweet

18:08 michaniskin: tolstoy: re }}} https://github.com/boot-clj/boot/blob/master/boot/base/src/main/java/boot/App.java#L230

18:09 haha i do it all the time now

18:09 it rules

18:10 dnolen_: cfleming: didn't solve the issue

18:11 Bronsa: michaniskin: my eyes

18:12 michaniskin: i think it's artistic

18:12 Bronsa: I guess that's a way to put it :)

18:12 michaniskin: you should see how i do php

18:14 Bronsa: michaniskin: thanks, I'm good

18:14 michaniskin: to late though, you can't un-imagine it

18:15 Bronsa: michaniskin: as humans we have developed selective amnesia exactly for cases like this

18:15 michaniskin: it will haunt you

18:15 you'll see

18:15 single curlies on a line by themselves don't have to be tolerated anymore

18:16 the seed is planted

18:22 justin_smith: to me that says "I would rather be writing lisp code write now"

18:23 visof: hi

18:23 how can i convert this java to clojure ODatabaseRecordThreadLocal.INSTANCE.set( database1 ); ?

18:23 (.get (ODatabaseRecordThreadLocal/INSTANCE) database1) ?

18:25 justin_smith: what is the relationship between ODatabaseRecordThreadLocal and INSTANCE?

18:26 static member of a class?

18:26 visof: http://www.orientdb.org/releases/latest/javadoc/com/orientechnologies/orient/core/db/ODatabaseRecordThreadLocal.html

18:26 justin_smith: oh, I guessed right

18:27 (.set ODatabaseRecordThreadLocal/INSTANCE database1)

18:27 since it's a static field, no invocation is needed on it

18:27 Bronsa: but it would have worket either way :P

18:27 ,(Integer/MAX_VALUE)

18:28 clojurebot: 2147483647

18:28 justin_smith: Bronsa: but not with .get :)

18:28 Bronsa: ,Integer/MAX_VALUE

18:28 clojurebot: 2147483647

18:28 Bronsa: justin_smith: uuuh really?

18:28 justin_smith: Bronsa: I mean, yes, parens or no, both work (but no parens is better)

18:28 Bronsa: ah, ok

18:28 justin_smith: but he should definitely switch his .get to .set

18:29 Bronsa: ah! didn't notice that. you're right

18:30 justin_smith: :)

18:43 dnolen_: just pushed some big changes to ClojureScript that considerably improve the REPL experience. Rhino REPL can start ~1 second. added real support for in-ns and require. doc is loaded into REPLs by default. things feel considerably less wonky now.

18:44 ambrosebs: dnolen_: sounds awesome

18:47 justin_smith: dnolen_: is that ~1s from jvm startup to rhino repl, or ~1s for startup inside an existing vm?>

18:48 dnolen_: justin_smith: jvm startup is 86ms on my machine, this meme has to end

18:48 justin_smith: dnolen_: no, I'

18:48 m not trying to pick on the jvm

18:48 dnolen_: JVM startup is ridiculously fast

18:48 justin_smith: just asking a clarifying question

18:48 I know the JVM can start fast

18:48 dnolen_: everything that is slow in the Clojure ecosystem is of our own doing

18:48 justin_smith: I know, I know

18:49 I've timed the startup of java hello world

18:49 that wasn't what I was getting at at all

18:49 dnolen_: ~1s is about 800ms of Clojure 1.6.0 boot time - the rest is is loading AOTed ClojureScript and reading some EDN files off disk

18:49 clojurebot: Ack. Ack.

18:50 justin_smith: dnolen_: that's pretty great actually

18:50 thanks for clarifying

19:02 cfleming: dnolen_: Well damn

19:03 dnolen_: Can you zip your project directory up and mail it to me, and I'll take a look to see if there's anything funky about it?

19:04 dnolen_: cfleming: I could put it wouldn't be any different from the ClojureScript repo, I've been committing ClojureScript.iml changes

19:04 s/put/but

19:04 cfleming: dnolen_: Ok, I'll download that and check it out.

20:18 kenrestivo: heh, on the embedded ARM platform i'm using, jvm and clojure is 10 minutes to start up.

20:18 justin_smith: kenrestivo: what about jvm for java helloworld?

20:19 kenrestivo: a uberjar loads faster, a couple minutes. but lein trampoline repl :headless is ~10 minutes.

20:19 of 99% CPU usage

20:20 justin_smith: kenrestivo: I was amazed by how much of the "lein repl" startup time is due to nrepl

20:20 kenrestivo: i dunno, helloworld is kind of useless to me. the experiment was to see if doing embedded development with a clojure repl was powerful. it is, in a way, but sllloooowwwwww in other ways.

20:20 justin_smith: kenrestivo: fair enough, just wondering what the vanilla java baseline was

20:21 kenrestivo: huh, maybe it is nrepl then. i remember doing some experiments and noticing it had a tight loop that consumed 90% cpu under normal conditions (i think this was with visualvm). i asked chas about it, and he said something to the effect of, oh yeah, it does that.

20:21 that was a couple years ago, maybe it's all been massively improved since.

20:22 justin_smith: try just running clojure.main next time, for comparison at least

20:22 kenrestivo: all i know is, i've been spending a *lot* of time hanging around in #clojure to kill time while waiting for the repl to start

20:22 for the last month

20:23 dweave: i’m trying to figure out exactly what core.async is and how it relates to futures / promises. Is it built on top of futures?

20:23 justin_smith: dweave: it uses a thread pool

20:24 dweave: it's more about queues between threads, and waking up blocks of code when they have data on their queue

20:24 dweave: is it “probably” a more suitable solution if I’m using futures

20:25 justin_smith: do the futures communicate with anything else? if not, core.async won't gain you anything

20:25 dweave: i see

20:25 justin_smith is that kinda like actors without their own state?

20:25 justin_smith: if they need to do extensive coordination, then yeah, core.async has nice ways of coordinating between threads of execution

20:26 dweave: they also have state, it's a more flexible setup than actors though

20:27 dweave: core.async implements something called CSP, concurrent sequential processes, there are papers on the model if you look for them

20:27 sorry s/concurrent/communicating

20:27 http://en.wikipedia.org/wiki/Communicating_sequential_processes

20:27 dweave: k

20:28 dnolen_: kenrestivo: there a recent post on the ClojureScript mailing list on using using ClojureScript+Node.js / C++ for Raspberry Pi dev - probably more realistic route

20:28 kenrestivo: hmm... yeah i heard there's some new node goodness for cljs. too late on this project, but maybe in the future

20:29 exciting stuff though, i saw your blog post on it.

20:30 dweave: justin_smith: might this be a good use case for core.async: Multiple async http requests all of which need to report back to the main thread which will do some data crunching on each result?

20:33 justin_smith: dweave: yeah, I could easily see a primary go block that reads each http result of a channel and processes it, and then a bunch of others that each put an http result onto that channel

20:34 dweave: justin_smith what state do channels have? They just seem like queues

20:34 justin_smith: but for something that simple, you could just use one of the queues from java.util.concurrent too (reading from the queueu in a loop in the main thread, writing to it from each http request in a future), but if you need more back and forth, that's when core.async makes more and more sense

20:34 dweave: they are queues with some limitations

20:35 for example you can't check if they have data for you - your options is to read or not

20:36 dweave: starting to make sense

20:36 so asyn channels are more about like 2 way communication

20:36 justin_smith: each channel is one way

20:36 but you can of course have a channel to go each direction, of course

20:36 dnolen_: dweave: core.async is really just that, a fantastic DSL over queues - concurrent or not

20:37 dweave: ok

20:54 gfredericks: hey look I made a regex to match JSON with bounded nesting: https://www.refheap.com/95500

20:55 warz: hi all, im aiming for a basic clojure environment in emacs. im new to emacs, so i was hoping for something that works out of the box. i was trying cider, and i followed the install directions, but my emacs does not look like the screenshot on cider's github repo: https://raw.githubusercontent.com/clojure-emacs/cider/master/screenshots/cider-overview.png

20:55 should my emacs look like this screenshot, after installing?

20:55 andyf: please tell me you didn't type that regex in by hand

20:55 gfredericks: andyf: I didn't type that regex in by hand

20:56 it seems like a natural example of a situation where you could add a feature to regexes to make them dramatically more succinct but no more powerful

20:56 a let-like feature

20:56 andyf: Yeah, I think they call them context-free grammars :)

20:56 gfredericks: "no more powerful" <-- trying to distinguish from CFGs

20:57 kl: hmm

20:57 gfredericks: CFGs are letrec, I'm talking about regular let

20:57 kl: what is the difference between a transducer and a partially applied function

20:57 andyf: In Perl you can assign regexes to variables, and then use the values of those variables in other regexes. Should work in Clojure, too, via string concatenation.

20:57 kl: andyf: i tried looking at the wiki page for context-free grammars and i just got confused. is there a simple definition?

20:58 andyf: yes

20:58 gfredericks: andyf: well that's where I got mine from; but you're expending a lot of resources with that approach, building strings and parsing the resulting regexes

20:59 andyf: there's probably some sort of recursion-limited grammar that would be more or less what I'm talking about

20:59 justin_smith: kl: you can apply a transducer to another transducer, and you get a transducer that is the composition of their behaviors

20:59 kl: that's not how normal partially-applied functions would behave

20:59 andyf: kl: The examples might be easier to read than the definition.

21:00 gfredericks: andyf: this might be it: http://en.wikipedia.org/wiki/Regular_grammar

21:01 I take it back

21:01 seems like a different kind of limitation

21:01 justin_smith: warz: are you referring specifically to the completion dropdown?

21:01 andyf: Basically you have some 'non-terminal symbols' which are usually capital letters in the examples. You start with one of them, and at each step you take a nonterminal symbol and replace it using one of the rules in the grammar, which look like: S->aSSb, which means to replace an S with aSSb. When you have replaced all non-terminal symbols so no more remain, you have a legal string in the language your grammar defines.

21:02 alandipert: gfredericks: epic regex man

21:04 warz: justin_smith, the whole theme and everything, the 3 panes, etc

21:04 justin_smith: warz: I know nothing about the theme, and I wouldn't expect anything about cider to set the color theme or font etc.

21:05 warz: in terms of the panes, managing windows in emacs is very different from other apps

21:05 kl: justin_smith: I see, I think I get that, thanks. It sounds like an idea that wouldn't be peculiar to clojure, do you find them elsewhere, too?

21:05 gfredericks: alandipert: heythanks

21:05 justin_smith: warz: they are more dynamic, and they don't even have the same names they have in newer software

21:07 kl: they do what one might intuitively expect nested calls to map / filter / etc. to do if you had a "smart" compiler. Clojure's compiler isn't super clever like ie. haskell's though.

21:08 kl: functionality wise they don't do anything wrapping one stream transform in another wouldn't, performance wise they are a big change though.

21:10 kl: justin_smith: sorry, I'm probably being dumb, but I'm trying to work out (again) how this differs from partial application. A partially applied map given a partially applied filter, given a value - is pretty much the same thing, is it not?

21:10 justin_smith: kl: no

21:10 because the mapping and filtering (though you would naively expect them to) don't happen in one go

21:11 amalloy: gfredericks: putting honest, hard-working regex craftsmen out of work with your automated regex factories?

21:11 justin_smith: transducers combine them in a way that the function composition doesn't yet, and eliminate some fiddly stuff in the middle

21:12 kl: as I was trying to say, at first you would expect this to be automatic, but Clojure doesn't typically try to be that clever (see also our usage of "recur" instead of automatic tco)

21:12 kl: justin_smith: so isn't what you said effectively what I said, BUT going over a lazy stream?

21:12 (Trying to reconcile a proper mental model)

21:13 justin_smith: kl: a map over a filter is still two lazy streams, a transduced map+filter can be one lazy stream, or feed input to one reduce without creating a lazy stream, or...

21:14 gfredericks: amalloy: hey regex factories create jobs

21:15 kl: justin_smith: thanks, you've been much help :)

21:15 + justin_smith 1

21:15 justin_smith: kl: what's different isn't the behavior, but the implementation (and thus how well it performs, and incedentally, transducers also make it easy to port all of map, filter, reduce, etc. to a new data source / sink)

21:55 uris77: alert: newbie question - How do I render a response as edn in ring?

21:58 verma: uris77: you could return something like: {:status 200 :body (pr-str obj) :headers { "Content-Type" "application/edn"}} from your ring handler

21:58 ,(def res {:status true :values [:hello :world]})

21:58 clojurebot: #'sandbox/res

21:59 verma: ,{:status 200 :body (pr-str res) :headers {"Content-Type" "application/edn"}}

21:59 clojurebot: {:status 200, :body "{:status true, :values [:hello :world]}", :headers {"Content-Type" "application/edn"}}

21:59 verma: pretty sure there's some middleware somewhere

21:59 uris77: https://github.com/tailrecursion/ring-edn

22:05 uris77: verma: thank you

22:05 googling for clojure stuff (other than lang basics) is a little disappointing. I saw some snippets that had response/edn

22:06 tried that and got a compilation error

22:07 verma: I just searched for "clojure ring edn middleware"

22:07 or something similar

22:13 uris77: i searched for clojure ring render edn

22:53 ipaomian_: test

22:53 fairuz: test success ipaomian_

22:54 ipaomian_: thanks fairuz

Logging service provided by n01se.net