#clojure log - May 23 2015

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

0:02 justin_smith: also, if you need more rationale about top level state / side effects, consider what happens if you compile your code to a jar for deployment

0:03 or if you want to edit your code and not need to restart your whole vm

0:04 WickedShell: yeah I'm having the restart vm problem like crazy, not sure if theres a workaround for that though if it requires seesaw/java GUI/tie in. If thats not the case please stop me now :/

0:05 justin_smith: WickedShell: stuartsierra's component lib can fix the restart issue if you design your namespaces well and use it as intended. At the very least you'll need to stop and start your vm much less often.

0:05 WickedShell: hmmm sounds promising, watching his talk atm (still unsure how that happens yet with the java side of it but looking forward to finding out)

0:07 justin_smith: the talk is good. Big picture answer is that anything stateful should be provided by a component that knows how to initialize it, and then you can explicitly declare which components use which others internally.

0:07 this allows reliable cycling of component state without having to restart the vm

0:08 WickedShell: I guess the part that I'm tripping up on that is, that the java GUI builds a lot of links which need to be maintained to avoid a nullpointer on layout/repaint so I think it would have to rebuild all of it? (which is still probably faster then a full VM restart)

0:08 justin_smith: Yes, much faster. Clojure loads its compiler pretty slowly.

0:09 so the GUI component would have a stop (the cleans up and destroys the window) and a start (which creates and initializes a window) and anything that needs to access or manipulate GUI state would then declare its usage of that component

0:10 and you would access the GUI and its constituant parts as needed, not via vars in a namespace, but via args supplied at component start time

0:10 WickedShell: yeah, the problem is right now I have the components spread out and controlled in their own sub region, which I suspect is not a good plan/practice

0:10 ie some gui parts are built in one namespace and others in another namespace, which seems werid

0:10 justin_smith: and there are two different kinds of things here called "components"

0:10 heh

0:11 WickedShell: I could see a sane variant of that. One system component that builds the window at init, another that builds the document display, another that builds the toolbar, etc. If they had a strong separation / independence of concerns that could totally work.

0:12 WickedShell: so the goal was to do that, it depends on how much you mean by strong seperation though as some of those areas have to share information periodically

0:12 justin_smith: the key things is ensuring that you have a clear way to make sure things get initialized in the right order, get access to the state they need to build on, without everything being a ball of mud. the component system makes that pretty straightforward once you get used to it.

0:13 WickedShell: and I admit each sub part *seems* to be clean, its just the top level that combines them that is a horror, and the part where they need to share information that is a horror

0:13 justin_smith: right

0:13 WickedShell: which maybe the component part will help with

0:13 justin_smith: the component enforces the restriction that the dependencies are a one way tree without cycles

0:13 which helps a lot

0:14 WickedShell: yeah I made it here without any cycles but I seem to need one at the moment :/

0:14 justin_smith: also it gives a straightforward way to specify who needs what, then it figures out hte initialization order for you, based on that.

0:14 most cycles can be solved by creating a third entity containing the subset of state used by the two others

0:15 whether it loads and controls the other two, or the other two load and control it, is up to your design

0:15 WickedShell: sounds like the kind of OO hell of creating classes as data carriers to be passed around

0:15 justin_smith: well, we don't have classes as anything other than data carriers in normal clojure

0:15 our functions are first class, not methods owned by some class

0:16 this is explicitly about designing your data dependencies

3:22 [mad]: hi

4:35 entity: I have the -main to go into a REPL, but it starts in the wrong namespace. Any way to change this?

4:35 i.e. (defn -main [& args]

4:35 (while true (println (eval (read-string (read-line))))))

4:36 when launched from the uberjar, this gets me into clojure.core, rather than the namespace at the top of the file where -main is defined

4:37 ah okay, doing (eval (use 'my-namespace)) before entering the REPL seems to do the trick :)

4:39 by the way, isn't there some better way to launch a repl? this has trouble with cursor movement keys and crashes the whole app when you make a typo

4:57 hm, okay, I'm trying to launch the cider repl, but the compilation is failing:

4:57 Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure/tools/nrepl/server__init.class or clojure/tools/nrepl/server.clj on classpath: , compiling:(core.clj:1:1)

5:50 mmeix: Short question: if I have a predicate with two arguments, for example: (defn twice? [a b] (= b (* 2 a))) - and I want to use it in negated form, I have to do: #(not (twice % %2)) ... isn't there a more concise way to say this?

5:52 oddcully: ,(doc complement)

5:52 clojurebot: "([f]); Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and returns the opposite truth value."

5:52 mmeix: ah, thanks!

5:52 so it gets (complement twice?)

6:13 entity: I'm trying to itegrate REPL into my app, but the uberjar build is failing: http://pastie.org/10203453

6:14 could anyone please take a look? I have no idea what I'm missing; I followed the readme from https://github.com/clojure-emacs/cider-nrepl

7:59 smokeink: why is Scalar constructor called with two zero parameters? (Scalar. 0 0) the corresponding java code has only one zero parameter http://docs.opencv.org/2.4/doc/tutorials/introduction/clojure_dev_intro/clojure_dev_intro.html#mimic-the-opencv-java-tutorial-sample-in-the-repl

8:15 crocket: Is Incanter the best machine learning library on clojure?

8:35 noncom: crocket: afaik incanter is not really a machine learning thing at all.. it is more about maths?

8:35 and statistic

8:40 crocket: All right...

8:41 Clojure seems to be the best platform for machine learning algorithms.

8:41 Screw R and python.

8:42 wasamasa: lol

8:43 crocket: Clojure screws R and python for math and machine learning.

8:44 mmeix: https://www.refheap.com/101515 - the three functions at the top: did I reinvent the wheel? Did I oversee something in core to do this?

8:46 I only found coll splitting with one-arg predicates

8:50 noncom: mmeix: ummmmm so, your aim is to first break the sequence in pairs and then split the new sequence in places where pairs satisfy a pred?

8:51 mmeix: no, I want to split, if a condition is met between two consecutive list elements

8:51 say the list would be [1 3 4 6 8]

8:51 and I want to split if and only if the difference between two elements is 1

8:52 [1 3 4 6 8] --> [ [1 3] [4 6 8] ]

8:52 so my pred takes two numbers

8:53 noncom: ah, i see

8:53 mmeix: and would be (= (inc a) b), in this case

8:53 but this pred should be a var

8:54 my solution works fine, but I thought, there is a ready made function for this maybe, on core or another lib

8:54 (in core)

8:55 not reinventing things is the motivation (of course reinventing is fun :-))

8:56 noncom: mmeix: well, aside from the fact that i'd rewrite this with a single reduce, i cannot recall any other ways of doing this :)

8:57 mmeix: a single reduce: you wouldn't write the helper function, you mean?

8:58 (I mimicked David Nolen's solution in http://stackoverflow.com/questions/2720958/clojure-finding-sequential-items-from-a-sequence)

8:58 noncom: mmeix: yeah, but that is highly opinionated and depends on a usecase i think

8:59 aha, that's perfectly fine i think

8:59 there are no such functions in the core that i aware of

8:59 mmeix: so this would depend on use case and possible modularity

8:59 ok, thanks!

10:07 entity: I made a siple REPL in my -main, but it annoys me that I have to (eval (use .. .. )) multiple namespaces if I want them to be available at startup

10:07 http://pastie.org/pastes/10203661/text

10:07 notice, how I use the .genetic namespace at the top of the .core namespace

10:08 but then, when trying to bring all the clojure-robby.* namespaces into space in the REPL, I have to iterate through all of them

10:08 I'd have thought that if NS1 uses NS2, then using NS1 also uses NS2

10:20 justin_smith: entity: have you checked out the vinyasa lib?

10:21 entity: namespaces don't work that way

10:21 use only creates references in the namespace where use is called

10:22 entity: ah okay, I see

10:23 justin_smith: there is no global namespace for things like this to be inserted into - it might almost seem like there is one because everything refers clojure.core automatically

10:33 shafire: hi

10:33 mmeix: hi from rainy Austria :-)

10:33 shafire: What was the name of the other clojure ide plugin for eclipse? (I know only ccw)

10:34 justin_smith: shafire: is there another one? the most advanced clojure plugin right now is probably cursive for intellij

10:34 mmeix: there is Cursive for IntelliJ

10:34 shafire: there was another one for eclipse, if I rember correctly

10:35 TEttinger: yep, cursive is pretty excellent.

10:35 shafire: oh, I think it was cursive :)

10:35 and remembered eclipse wrong

10:35 justin_smith: haha - shafire says "what's the other plugin for eclipse" 3 people respond "dunno, use cursive"

10:38 TEttinger: I like CCW, I actually contributed a tiny bit to it back in the day

10:38 mmeix: if anybody could have a short look on https://www.refheap.com/101515 - the first three functions ... any improvements I could do to them?

10:38 TEttinger: Cursive just uh, has debugging

10:39 http://clojuredocs.org/clojure.core/partition-by

10:40 mmeix: yes, but partition-by only looks at one value

10:40 what I need is comparison from one value to the next, and partitioning based on this comparison

10:42 example: "split [1 3 4 7 8 11] everywhere, where the delta between two numbers is exactly 1", so [1 3 4 7 8 11] ==> [ [1 3] [4 7] [8 11] ]

10:42 and so on

10:43 anything I'm overlooking?

10:43 dnolen: mmeix: mapcat first + partition-by + partition could probably work.

10:44 mmeix: but I want the pred configurable

10:44 dnolen: ,(doc partition-by)

10:44 clojurebot: "([f] [f coll]); Applies f to each value in coll, splitting it each time f returns a new value. Returns a lazy seq of partitions. Returns a stateful transducer when no collection is provided."

10:45 dnolen: mmeix: ah you want predictate

10:45 mmeix: yes

10:45 in order to have it configurable

10:46 dnolen: mmeix: well technically partition-by could work, since splits happen on true and false

10:46 mmeix: I took inspiration from your example in http://stackoverflow.com/questions/2720958/clojure-finding-sequential-items-from-a-sequence

10:47 and liked the way, it can be made general

10:47 would anything involving partition-by get me more performance?

10:48 TEttinger: ,(let [chord [1 3 4 7 8 11] paired (mapv vec chord (rest (conj chord nil)))] (partition-by (fn [[a b]] (= (- b a) 1)) paired))

10:48 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: core/vec"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/vec"\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" 36]\n [clojure.core$map$fn__4554 invoke "core.clj" 2627]\n [clojure.lang.Lazy...

10:48 TEttinger: ,(let [chord [1 3 4 7 8 11] paired (mapv vector chord (rest (conj chord nil)))] (partition-by (fn [[a b]] (= (- b a) 1)) paired))

10:48 clojurebot: #<NullPointerException java.lang.NullPointerException>

10:48 TEttinger: haha

10:49 dnolen: mmeix: I don't think so.

10:49 mmeix: then I#ll keep my solution for now :-)

10:50 what I find evrytime: it's not easy to find proper names for functions

10:55 edannenbe: mmeix, there are only two hard things in computer science: cache invalidation and naming things :p

10:56 mmeix: obviously

10:56 :-)

11:05 another ad hoc question: testing if a series of integers is monotonically growing ( [3 4 5 6] )

11:05 (= c (range (apply min c) (inc (apply max c))))

11:05 is there something more concise?

11:05 (c being the series being tested)

11:07 (growing by one, I forgot to mention)

11:11 my other idea was: (every? #(= 1 %) (map - (rest c) c))

11:12 dnolen: mmeix: that one is better since you don't have min max scans

11:12 mmeix: ah, ok...!

11:12 thanks

11:12 dnolen: it's lazier

11:12 mmeix: which is good, I understand

11:13 dnolen: (every? #{1} (map - (rest c) c))

11:13 if you want to make it a bit shorter

11:13 mmeix: ah, of course - thanks!

11:14 TEttinger: ,(let [c [1]] (every? #{1} (map - (rest c) c)))

11:14 mmeix: (in my application, no vector is longer than around 15 elements though, so it's mostly a question of readability, I guess)

11:14 clojurebot: true

11:14 TEttinger: nice

11:14 I'm surprised that worked

11:14 ,(rest [1])

11:14 clojurebot: ()

11:14 TEttinger: ah, because they're map args

11:14 dnolen: (every? true? '())

11:14 ,(every? true? '())

11:14 clojurebot: true

11:15 dnolen: TEttinger: it's because map will work over the shortest seq, which is nil and every? return true

11:15 for empty seq

11:15 justin_smith: ,(every #(= Double/NaN %) ())

11:15 clojurebot: #error {\n :cause "Unable to resolve symbol: every in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: every 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: every in this...

11:15 mmeix: aha, and then I can do tests like (every? #{0 1} (map - (rest c) c))

11:15 justin_smith: ,(every? #(= Double/NaN %) ())

11:15 clojurebot: true

11:16 justin_smith: ,(every? #(= Double/NaN %) '(Double/NaN))

11:16 clojurebot: false

11:17 TEttinger: ,(let [nana Double/NaN] (every? #(= nana %) '(nana)))

11:17 clojurebot: false

11:17 TEttinger: ,(let [nana (/ 0.0 0.0)] (every? #(= nana %) '(nana)))

11:17 clojurebot: false

11:17 TEttinger: hmmm

11:18 mmeix: ,(let [c [1 1 2 3 3 4]] (every? #{0 1} (map - (rest c) c)))

11:18 clojurebot: true

11:18 mmeix: great

11:19 thanks everybody!

11:26 kaiyin: ,(disj [1 2 3] 3)

11:26 clojurebot: #error {\n :cause "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentSet"\n :at [clojure.core$disj invoke "core.clj" 1452]}]\n :trace\n [[clojure.core$disj invoke "core.clj" 1452]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [clojure.l...

11:27 kaiyin: How can i remove an element from a vector?

11:28 ionthas_: Noob question: I want to apply a pop 3 times into a vector to drop the last 3 values. I'm doing de following without success: (dotimes [n 3] (pop [1 2 3 4 5 6 7 8])).

11:28 kaiyin: You can remove the last element with (pop v)

11:29 kaiyin: ionthas_: yeah, but that's a special case, i want to remove by value

11:30 ionthas_: kaiyin: I think there's no way to remove with the vector index. You should use a list instead. (Maybe I'm wrong)

11:32 kaiyin: ok

11:37 justin_smith: kaiyin: you can use remove, but that returns a lazy-seq, even if the input was a vector

11:37 ,(remove #{1 3} [0 1 2 3 4 5 6])

11:37 clojurebot: (0 2 4 5 6)

11:37 kaiyin: cool.

11:38 dnolen: ionthas_: you can't mutate vectors like that

11:39 ionthas_: dnolen: Ok. I supose I will use loop/recur :) thanks!

11:40 dnolen: ,(reduce #(%2 %1) [1 2 3 4 5] (repeat 3 pop))

11:40 clojurebot: [1 2]

11:40 dnolen: ionthas_: ^

11:41 justin_smith: ,(nth (iterate pop [1 2 3 4 5]) 3)

11:41 clojurebot: [1 2]

11:41 ionthas_: that was exactly what I was looking for. Thanks

11:41 dnolen: one day will learn to use iterate :)

11:42 justin_smith: I'm always trying to make things recursive generative systems, so I don't pass up the chance when the problem actually maps to that

11:42 well this is kind of the opposite of generative though

11:43 ionthas_: justin_smit: what do you mean with recursive generative?

11:43 justin_smith: ionthas_: in general, iterate takes an input, and some operation, and gives you all the steps of repeated, recursive, applications of that operation

11:44 ,(iterate inc 1)

11:44 clojurebot: (1 2 3 4 5 ...)

11:44 ionthas_: I see. Interesting. I will play with that function. It seems useful.

11:45 justin_smith: or (iterate markov \a) (where markov is a markov chain function that's been trained on some input)

12:03 kaiyin: how do you update a vector at multiple indices?

12:04 ,(update-in [1 2 3 4] [1] inc)

12:04 clojurebot: [1 3 3 4]

12:04 kaiyin: Imperative code would use a for loop here.

12:07 justin_smith: kaiyin: what kind of updates are being done?

12:07 kaiyin: Replace with another value.

12:08 conditionally.

12:09 justin_smith: ,(reduce #(if (even? (% %2)) (update % %2 inc) %) [1 2 3 4 5 6 7] [1 2])

12:09 clojurebot: [1 3 3 4 5 ...]

12:09 justin_smith: the function does the conditional update, the last arg represents the indexes to check and maybe update

12:33 kaiyin: justin_smith: this looks ineffecient.

12:33 justin_smith: why?

12:34 clojurebot: why is Why

12:34 kaiyin: you have to traverse through all the elements.

12:34 justin_smith: no, you traverse the indexes to update

12:34 not the elements

12:34 kaiyin: ah, i see.

12:34 cool.

12:38 justin_smith: it's a pattern I am fond of - finding a way of encoding each update as data, then walking a sequence representing all the updates

13:06 kaiyin: very nice.

13:07 borkdude: is there a way to check you're running in dev without environment variables or lein environ?

13:08 {:profiles {:dev {:env {:dev true}}}} seems a bit too much

13:08 justin_smith: borkdude: off the top of my head, (.getCanonicalPath (java.io.File. ".")) or something that gets your hostname?

13:09 borkdude: justin_smith possible

13:09 I wonder if they have solved that problem in boot

13:10 justin_smith: borkdude: another things to consider is that ideally on production lein should not be present

13:10 borkdude: justin_smith true... it isn't in my case

13:11 justin_smith well, I cheated. I used lein to install immutant

13:11 I guess lein environ is the best option I've got then

13:11 justin_smith: in production, you end up needing to set a proper environment var

13:12 unless you are just checking for the absence of anything being set of course

13:13 borkdude: you could also set something your code can check at entry point, if immutant and lein repl or lein run have different entry points

13:14 borkdude: justin_smith yeah. I've done that, also with environ. I discovered now that the settings from ~/.lein/profiles.clj, {:user :env {...}} and project.clj {:profiles {:dev {:env ...}}} get merged into .lein-env, which makes it better suited for the problem I had

13:15 justin_smith: ahh

13:20 ,(.getHostName (java.net.InetAddress/getLocalHost))

13:20 clojurebot: "localhost"

13:20 justin_smith: haha

13:20 on my machine that shows my actual hostname

13:44 kaiyin: could anyone help me with this? http://stackoverflow.com/questions/30415771/strange-illegalargumentexception-in-clojure

13:48 bensu: can you tell me which line is 70?

13:49 kaiyin, ^

13:49 kaiyin: bensu: (vec (repeat *world-size* c)))))

13:50 I think this error msg doesn't quite make sense.

13:50 justin_smith: kaiyin: ##([:a :b :c] :a)

13:50 lazybot: java.lang.IllegalArgumentException: Key must be integer

13:50 justin_smith: that's the error

13:51 bensu: kaiyin, a vector needs a number as key

13:51 Bronsa: kaiyin: you're invoking a vector with a non-key, in (min-by f-score openset)

13:51 kaiyin: ah, i see.

13:51 Bronsa: with a non-integer*

13:52 kaiyin: why then does the compiler direct me to line 70?

14:05 entity: how can I get w out of \w? str does not do what I want:

14:05 ,(str \w)

14:05 clojurebot: "w"

14:07 entity: I'm trying to write a vector of characters into a file

14:09 justin_smith: entity: wait, what?

14:10 do you mean ##(apply str [\h \e \l \l \o])

14:10 lazybot: ⇒ "hello"

14:10 entity: I have '[\a \b c\]' and I want to write '[a b c]' into a file

14:10 justin_smith: ,(mapv (comp symbol str) [\a \b \c])

14:10 clojurebot: [a b c]

14:11 entity: awesome, thanks :)

14:29 kaiyin: anyone knows how to solve this? https://github.com/amalloy/ordered/issues/15

14:30 justin_smith: why wouldn't the regular conj work?

14:31 kaiyin: ah, that's the regular conj on the github homepage... sorry.

14:32 justin_smith: yeah, conj is already polymorphic

14:32 so he wouldn't be likely to implement his own namespaced version of conj

15:29 kaiyin: finally got this A* algorithm done: http://codereview.stackexchange.com/questions/91588/a-search-algorithm-in-clojure

15:50 justin_smith: is this related to the one talked about in joc?

15:53 tsunny: Hey room

16:03 arohner: I'm calling Thread/setDefaultUncaughtExceptionHandler, but it doesn't appear to be working when I do (future (throw (Exception. "test"))). Any recommendations on where to look?

16:14 ah, the answer is that j.u.c.FutureTask.run catches the exception, so defaultuncaughtException is never called: http://stackoverflow.com/questions/23177331/concrete-example-of-a-defaultuncaughtexceptionhandler

16:18 Confusion: I want to use 'and' as a value. I solve it by defining (defn- and-fn [& args] (every? identity args)). Is there a different way?

16:19 TEttinger: hm? 'and' is a macro?

16:19 Seylerius: If I need 9 9x9 grids of text boxes in seesaw, and need to get data out of them, and put data into them, would y'all recommend creating them all individually, or making a function that spits out the 9x9 grids with an appropriate title?

16:20 TEttinger: ,(map and [true true false false] [false true false true])

16:20 clojurebot: #error {\n :cause "Can't take value of a macro: #'clojure.core/and"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6543]}\n {:type java.lang.RuntimeException\n :message "Can't take value of a macro: #'clojure....

16:20 TEttinger: ,(map #(and %1 %2) [true true false false] [false true false true])

16:20 clojurebot: (false true false false)

16:21 TEttinger: Seylerius, I'd recommend making a function that spits them out

16:21 it shouldn't actually be that hard

16:22 arohner: ,(:macro (meta #'and))

16:22 clojurebot: true

16:22 arohner: TEttinger: 'and guarantees it only evaluates arguments as necessary, so that necessarily makes it a macro or special form

16:23 TEttinger: ah!

16:23 amalloy: Confusion: that is the way to do it

16:24 TEttinger: and-fn will still evaluate all args though, right?

16:25 kaiyin: ,(let [x 9, y '(- x)] (println `y) (println ``y) (println ``~y) (println ``~~y))

16:25 clojurebot: sandbox/y\n(quote sandbox/y)\nsandbox/y\n(- x)\n

16:26 amalloy: TEttinger: yes, but it takes its args as a seq, so passing in a lazy seq would be fine

16:26 TEttinger: ah!

16:26 arohner: amalloy: but chunking is an issue?

16:26 mullr: Confusion: do you just want to pass it to reduce? That's what I always want to do, and that's what 'every?' is for.

16:26 ,(doc every?)

16:26 clojurebot: "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

16:27 TEttinger: ok, this seems like a good place to ask about macro design.

16:28 I'm working on a programming language, it's pretty much a functional language but shares some similarities with stack languages. I'm trying to implement defmacro

16:29 Confusion: mullr, no, I'm parsing expressions from strings and some operator in the strings is equivalent to 'and'. Short circuiting would be nice, though not strictly necessary.

16:30 TEttinger: the language compiles to Lua, with a Lua standard lib, and currently all the macros I have written have been in Lua, but they are pretty clunky

16:31 mullr: Confusion: ah, wrapping it in an fn is probably your best choice then.

16:32 TEttinger: like I have the macro fn . it can be called like (fn [ a b ] (+ a b)) , equivalently (fn [ a b ] a + b)

16:32 this is implemented in a really awful way though.

16:33 kaiyin: could anyone help me with this? http://stackoverflow.com/questions/30417291/illegalstateexception-in-nested-quote-and-unquote

16:34 TEttinger: when evaluation of a group (everything between parentheses) hits a macro, it puts the macro on top of the eval order, and until that macro has reached its target arity or the group ends, it adds things as arguments to that macro (all functions work like this). macros in my language treat values as values, and identifiers as the quoted names of those identifiers (which can be used to look them up)

16:37 the problem is, in my implementation of fn, given the args: [ a b ] a + 9 , it gets '[ 'a 'b '] 'a '+ 9

16:38 and it only knows what are supposed to be names of arguments to fn by reading from the second arg (always skipping the first because it expects it will be '[ ) until it finds the symbol ']

16:38 Seylerius: TEttinger: I've been thinking that would be the right idea, but wasn't sure how much of a pain referencing back into them would be.

16:40 TEttinger: well the other thing it does is it specifically creates a table of names that can be used in the function when it's generated. when the generated function is called, it makes a new subscope, takes each argument it was given, and a name from the table, and assigns in the subscope the value to the name

16:41 then it evaluates the body and deletes the subscope

16:42 or rather, in the fn implementation, it unquotes all the values in body before it evals them

16:43 so 'a becomes an identifier that will look up the value of a (finding whatever it has in the subscope)

16:43 I understand that macros don't evaluate their arguments

16:43 I'm not sure when defmacro should cause things to be evaluated

16:45 mullr: kaiyin: ~ is a reader macro which turns in to 'unquote', and ` is a reader macro which turns into 'syntax-quote'. I can tell you that it only makes sense to unquote inside syntax quote, but I can't for the life of me find the code that makes it work that way.

16:47 kaiyin: Ah, I think I see it. The reader is knows about syntax-quote, and interprets unquote as a special form in that context only. Outside of that, it looks just like any other function, which is not actually defined.

16:48 kaiyin: mullr: that makes sense.

16:50 ,(println ''y)

16:50 clojurebot: (quote y)\n

16:50 kaiyin: so this means println explicitly unquote once?

16:50 implicitly, sorry.

16:51 TEttinger: ,(println 'y)

16:51 clojurebot: y\n

16:51 TEttinger: ,(class 'y)

16:51 clojurebot: clojure.lang.Symbol

16:51 TEttinger: ,(class ''y)

16:51 clojurebot: clojure.lang.PersistentList

16:53 kaiyin: TEttinger: nice illustration, thanks.

16:53 (inc TEttinger )

16:53 lazybot: ⇒ 5

16:53 TEttinger: ah, thanks

16:53 me with space has more karma now!

16:54 kaiyin: (inc mullr)

16:54 lazybot: ⇒ 1

16:54 TEttinger: multiple quotes are weird but can be handy

16:54 not often

16:54 in macros that generate macros, yes

17:03 kaiyin: TEttinger: could give an example of macro-generated macro?

17:03 justin_smith: TEttinger: now I want to implement def-def-def

17:03 TEttinger: haha justin_smith

17:03 kaiyin, it's rare. I do have one

17:03 justin_smith: which is of course a macro that generates a macro that creates definitions

17:04 TEttinger: ,(defmacro import-alias [new-name imported] `(defmacro ~new-name [f# & body#] `(. ~'~imported ~f# ~@body#)))

17:04 clojurebot: #'sandbox/import-alias

17:05 TEttinger: ,(import-alias J Math)

17:05 clojurebot: #'sandbox/J

17:05 TEttinger: ,(J PI)

17:05 clojurebot: 3.141592653589793

17:05 TEttinger: in the body of the second macro is some really gnarly macro work

17:06 that took a long time to get right, especially since I had never really written a complex macro before

17:07 http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros was VERY helpful

17:09 amalloy: but also like...don't do it. you don't need a macro that produces maros in real life

17:10 TEttinger: i still have trouble with the differene between ~'~ and ~~'

17:11 TEttinger: hehe amalloy. I'm crediting you (and justin_smith and gfredericks and #clojure in general) on the credits page for my programming language, since you fellas have been handy in my understanding of lots of tricky concepts

17:12 kaiyin: what is the differene between ~'~ and ~~'

17:12 ?

17:13 TEttinger: well they both make amalloy's head asplode, so avoid them :)

17:13 Bronsa: does ~~' even make sense?

17:14 only in the context of nexted syntax-quotes, right?

17:14 amalloy: Bronsa: well that's true of ~'~ too

17:14 ,(let [sym 'x] ``[~'~sym ~~'sym]) ;; they both do something, of course

17:14 Bronsa: no, I don't think so

17:14 clojurebot: (clojure.core/apply clojure.core/vector (clojure.core/seq (clojure.core/concat (clojure.core/list (quote x)) (clojure.core/list sym))))

17:14 Bronsa: `~'~a

17:14 ,`~'~a

17:14 clojurebot: (clojure.core/unquote a)

17:14 TEttinger: ,(defmacro [blah] `(inc ~~'blah))

17:14 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(NO_SOURCE_FILE:0:0)"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6644]}\n {:type java.lang.IllegalArgumentException\n :message "Do...

17:14 Bronsa: ,`~~'a

17:14 clojurebot: #error {\n :cause "Attempting to call unbound fn: #'clojure.core/unquote"\n :via\n [{:type java.lang.IllegalStateException\n :message "Attempting to call unbound fn: #'clojure.core/unquote"\n :at [clojure.lang.Var$Unbound throwArity "Var.java" 43]}]\n :trace\n [[clojure.lang.Var$Unbound throwArity "Var.java" 43]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval95 invoke "NO_SOURCE_FI...

17:14 amalloy: yes, if you want to emit an unquote or something, but that is just weird and you shouldn't

17:14 TEttinger: haha

17:15 Bronsa: true

17:15 TEttinger: more symbols than letters in these recent codes

17:15 justin_smith: "emit an unquote" is the weirdest euphamism ever

17:15 Bronsa: unless I'm dynamically generating macro bodies :)

17:15 but yeah, I wouldn't do that

17:17 TEttinger: hey baby I wanna emit an unquote all over your body and get your value

17:17 Bronsa: are nested syntax-quotes actually used in CL? I remember feeling like it was something that would come up often while reading PG's book but I don't think I've ever nested them in CLJ

17:18 or I might have used it once in neurotic, but anyway it's not something I see in code

17:29 kaiyin: TEttinger: you are probably the best person to answer this question: http://stackoverflow.com/questions/30417758/how-does-macro-generating-macro-work-in-clojure :-)

17:31 TEttinger: oh no

17:31 I am not the best person for any question!

17:33 I strongly suspect it has to do with it being a macro within another macro

17:33 that was I think the second macro I ever wrote

17:33 so I can't say I understand it that well

17:34 also, I have to say: I only wrote it because someone said it couldn't be done

17:34 it still can't alias classes that need to be instantiated

17:35 kaiyin: alright, let's just wait for some clojure gods to take care of it.

17:35 TEttinger: haha

17:35 amalloy will scold me :)

17:36 amalloy: kaiyin: (concat (list x) (list y) (list z)) is of course equivalent to (list x y z), but it's just simpler for the compiler to generate stuff if it makes everything a list and then calls concat as necessary

17:37 and since it's all happening at compile time instead of runtime, the performance issues of doing stuff in a simple but silly way don't really matter

17:46 kaiyin: ok.

18:08 entity: if I def something in a namespace, I can later re-def it only from the same namespace?

18:08 I'm getting "java.lang.IllegalStateException: gold-prob already refers to: #'clojure-robby.genetic/gold-prob in namespace: clojure.core"

18:09 justin_smith: why are you adding defs to clojure.core?

18:09 entity: hm, good question

18:10 I def it in clojure-robby.genetic

18:11 although, I then "(eval (use 'clojure-robby.genetic))" and launch a repl

18:11 I want to bundle a REPL in my app, so I wrote a one-line that does that

18:12 it's probably messing up the namespaces

18:15 I'm open to suggestions as to how to properly implement a REPL in my app

18:16 justin_smith: clojure.tools.nrepl.server lets you launch your own nrepl network server

18:16 entity: but I'd need both the server and the client

18:16 it seem excessive

18:17 justin_smith: "lein repl :connect" can connect to a running nrepl

18:17 entity: but requires a dependency - leiningen

18:17 justin_smith: that's true

18:17 entity: I'd like to get a single portable .jar file

18:17 justin_smith: entity: for a regular repl, you can just invoke clojure.main

18:20 entity: okay, that's cool

18:20 is there any way to have it use a couple namespaces at startup?

18:21 justin_smith: entity: the default namespace at startup is user, so you could switch into namespace user, then use whatever namespaces you like from user

18:21 the repl is not a sandbox

18:21 it's the same namespaces and bindings as the rest of clojure

18:21 if you do want a sandbox, you could check out eg. clojail

18:21 ionthas_: Anyone can explain me why this code is only dropping one of the values of the vector? (loop [n 0 lol v1] (if (< n 10) (recur (inc n) (pop v1)) lol)) with (def v1 [[0 [1 0 4 3]] [6 [3 2 1 1]] [3 [3 1 1 1]]]). It only drops the last element of the vector. It doesn't depend of the number in the condition. Anyone has some idea what's going on? Thanks!

18:22 justin_smith: ionthas_: you want (pop lol) not (pop v1)

18:22 because of course v1 never changes

18:23 so you end up with the result of popping it once

18:23 ionthas_: shit XD

18:23 you're right. That's the sign. Not more programming for today.

18:24 entity: justin_smith: thanks, this was very helpful :) I think I'll figure it out now

18:50 justin_smith: I am now in a user namespace by binding *ns* to a newly create namespace

18:51 but I still get shuted at for trying to redefine a var: "java.lang.IllegalStateException: gold-prob already refers to: #'clojure-robby.genetic/gold-prob in namespace: user-ns"

19:02 I do not understand why I'm suddenly not allowed to re-def a var in my namespace

19:03 I can create new bindings and re-def those

19:03 but I can't re-def what I've imported from other namespaces

19:16 sandbags: I've written a small API server using Liberator which has been great. I'm deploying it using Jetty but something that has me stumped is how I can pass configuration data to the app... i guess this may be more of a Java/Jetty question but I'm not turning up anything via Google

19:16 hoping someone can point me in the right direction

19:27 fourq: Hey all, Clojure/Clojurescript book ideas for a noob? (I have 18+ years, background: vb6, c#, js, node, fullstack) I'll be mainly working on web apps for enterprise.

19:28 sandbags: fourq: one of either "Clojure Programming" or "Programming Clojure" as a jumping off point

19:28 PragProg vs O'Reilly

19:30 as to web app stuff there is "Web Development with Clojure" which covers 'classic' server side app development

19:30 the client side stuff in CLJS is probably moving too fast

19:35 fourq: sandbags ty very much

19:37 Is Chas Emerick in here ever? I listened to a podcast a few days ago and he had 2 book suggestions. (I just forget what they are)

19:38 sandbags: Well I found Clojure in Action a good jumping off point

19:39 amalloy: $seen cemerick

19:39 lazybot: cemerick was last seen quittingPing timeout: 264 seconds 4 hours and 24 minutes ago.

19:39 amalloy: so he was here 4 hours ago

19:39 sandbags: it's a bit less heavy than the other two, Joy of Clojure is often cited also

19:39 fourq: amalloy ty

19:40 epichero: Om and dev tools like figwheel are good clientside. (it is moving really fast though that's true)

19:41 fourq: I've been playing with om, and fig along with the unreleased book Clojure for the Brave and True

19:41 great read btw

19:42 Om would be a hell of a learning curve if I didn't have prior React exp

19:44 sandbags: I quite enjoyed Functional Programming for the OO programmer by Brian Marick

19:44 i came to CLJ from Ruby so it was pretty on-point

19:44 fourq: I'll add that to my list. I have a weekend without the kids. Should be good for a few books

19:45 sandbags: if you're writing services rather than apps i can definitely recommend looking at Liberator

19:45 i've found it a breath of fresh air

19:45 fourq: both eventually

19:51 epichero: i haven't tried liberator, i'm wanting to do some websocket stuff myself

19:52 any suggestions on that front?

19:59 edannenbe: fourq, can recommend http://www.braveclojure.com/

20:03 fourq: edannenbe I've read it! ty. I loved it

20:03 edannenbe: yea very entertaining read

20:04 fourq: It really was

20:04 Something pretty rare in the tech book world. Well it's not that rare, but it's rare that it worked out, and wasn't horribly overdone.

20:14 postpunkjustin: Does anyone know a good way to redirect to a URL in ClojureScript?

20:27 justin_smith: postpunkjustin: use js interop to make the browser load the other page?

20:27 postpunkjustin: yeah, I'm having a lot of trouble getting that to work

20:28 justin_smith: (set! (.href (.location js/window)) "http://www.google.com"))

20:28 something like that

20:28 maybe it's set and not set!

20:29 oh, and you likely need (.-href (.-location js/window))

20:30 one minute, I'll load up my app and actually see what works

20:31 postpunkjustin: awesome, thanks

20:31 justin_smith: I've been learning cljs myself the last month or so

20:32 using figwheel, sente, reagent

20:32 ported stuartsierra/component to cljc (once I make all the frontend and backend tests pass I'll make a pr / announcement)

20:33 postpunkjustin: oh sweet, that's really cool

20:33 I'm using a similar stack

20:33 justin_smith: it's been a cool experience so far

20:33 also, I set up a /test route that runs frontend tests in the console, and backend tests show in the browser page

20:33 I might try to make that a plugin

20:34 lein plugin, that is

20:35 epichero: what do you think of sente?

20:36 justin_smith: epichero: so far it is awesome

20:36 postpunkjustin: (set! (.-href (.-location js/window)) "http://www.google.com") verified to work in the figwheel repl

20:37 epichero: I ended up making some wrappers so the api for accessing and sending messages was more uniform on each side

20:37 but overall I like

20:38 epichero: a great addition was using json-web-tokens for session storage. Just make sure that you explicitly state which storage algo you are checking for when unencrypting

20:38 by default there is a "none" encryption method, and the client by default sets the encryption method when sending the data

20:39 so there is a stupid thing where they can forge any data they like, and the server's like "lol, encryption method is none so obviously the data is valid, I'll go ahead and use it now"

20:39 there's an extra arg to declare exactly which encryption method you will allow

20:41 epichero: justin_smith: thats standard fare, sometimes people just get used to things be built-in

20:41 postpunkjustin: justin_smith: ok, cool, that definitely works if I put it at the top level, but now I'm trying to call it from a button :on-click handler and it doesn't work there for some reason

20:41 any ideas why that might be?

20:41 justin_smith: postpunkjustin: weird...

20:42 so to make it an on-click you wrap it in an anonymous function, right?

20:42 postpunkjustin: yeah, the :on-click val is an anonymous function

20:42 justin_smith: oh, is this reagent?

20:42 postpunkjustin: yeah

20:44 justin_smith: postpunkjustin: do you have to override the default button click handler? there's a css trick for that and it's slightly different for different browsers

20:44 postpunkjustin: oh, interesting idea

20:44 I didn't realize that would be necessary

20:44 justin_smith: that's a frequent problem I've seen with button actions

20:46 but I am far from being a frontend expert

20:46 postpunkjustin: yes, I think you're totally right

20:47 it was a form submit button. changing it to a regular button fixed it. thanks!

20:47 justin_smith: ahh!

20:47 yeah, that would do it

20:52 so this is the nifty testing setup I have right now... maybe I'll make it a plugin this weekend http://i.imgur.com/GbPXAJb.png

22:34 Shiro-Ichida: Yes! I got a clojurescript repl running! Probably no big deal for most people here but it's exciting to me and none of my friends use Clojure, so...uh. Yeah, that's it.

22:34 justin_smith: Shiro-Ichida: it's a cool thing!

22:34 Shiro-Ichida: It's very cool.

22:35 blkcat: Shiro-Ichida: congrats :)

22:35 clojurescript looks very very interesting. i need to give it a shot.

22:36 dnolen: Shiro-Ichida: nice!

22:36 justin_smith: it's nice to do a webapp end to end all clojure

23:40 crocket: Does clojure beat C++ when you need to hit GPU?

23:40 justin_smith: beat by what criteria? for performance I'd be surprised if clojure was ever as fast as c++

23:41 crocket: GPU performance would be more important than performance differences among languages.

23:42 Is clojure fast enough for GPU operations? Does clojure make it easy to hit GPUs?

23:44 justin_smith: "fast enough for GPU operations" is a weird quesiton, to use the GPU at all from clojure you'll need a lib like jcuda, and there's some stuff out there, but not very much, and not very mature that I know of

23:44 crocket: If your operations stay on GPUs most of the time, clojure could be good enough.

23:45 Then, it should be simple to hit GPUs on clojure.

23:45 justin_smith: OK, but the tooling really isn't there at the moment

23:45 and making your code run on the GPU isn't a simple thing in most cases

23:45 it requires a different programming style

23:46 crocket: So, does GPU programming suit C++ better?

23:48 epichero: you can do it, but you are misunderstanding how all of this works

23:48 crocket: epichero, I don't understand it at all.

23:49 justin_smith: crocket: gpu programming is easiest from c++, because it is targetted to the types of applications where you would be using c++ for speed reasons already

23:50 crocket: justin_smith, Why not C?

23:50 justin_smith: crocket: clojure is better suited to situations where you want to have less code, and less time developing code, in particular when it comes to doing concurrency correctly.

23:51 crocket: because outside of things like the Linux kernel, c++ has much more mainstream adoption right now

23:51 crocket: Concurrency can be achieved by GPUs.

23:51 justin_smith: if you program in a very specific way, yes

23:52 but not every situation in a typical program can simply be thrown at a GPU to make it concurrent

23:52 crocket: I think haskell and clojure will take over C++ on GPU programming.

23:52 justin_smith: any more than every situation in a typical program can be thrown at threads to make it concurrent

23:52 crocket: first someone needs to build the tooling, it's really not there right now.

23:52 or there, but very immature

23:52 crocket: haskell has accelerate

23:52 justin_smith: OK

23:53 epichero: haskell is pure so there are no conflicts

23:53 crocket: Given the momentum given to haskell and clojure, they'll get tooling supports soon.

23:53 In the next 10 years.

23:53 epichero: theres already proof of concept stuff around, you can do it now if you want to

23:53 finding a niche where it makes sense is a bit more difficult

23:54 justin_smith: crocket: idiomatic clojure (or even full idiomatic haskell) is a bad fit for the GPU because we rely heavily on GC, and use a lot of RAM

23:54 crocket: even with accellerate, it only works if you translate all your data into arrays of numerics

23:55 so at best you get a sub-language where most of the host language is unavailable, but it performs well

23:55 just see how many lines of clojure code you can write that don't allocate or leak heap space

23:56 crocket: justin_smith, Does haskell have chance, then?

23:56 justin_smith: It can use that stuff, but in a limited sublanguage. A chance to what?

23:57 crocket: beat C++

23:57 in GPU programming

23:58 Haskell is getting a lot of momentum.

Logging service provided by n01se.net