#clojure log - Apr 05 2016

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

0:01 tolstoy: Not (str (System/getenv "HOME") java.io.File/separator ".stuff.edn"))? ;)

0:01 (str (System/getProperty "user.home") java.io.File/separator ".stuff.edn"))

0:02 cwgem|mac: If there's a Java way (like what appears to show up there) to get home I'd probably use that versus trying to work with raw environment variables

0:04 sdegutis: bbl

0:52 user__: man

0:52 everytime

0:52 nil, nil, nil

0:52 args

0:53 TEttinger, I'm havinga brain fart

0:53 tolstoy: Mapping println over values?

0:56 TEttinger: eh?

0:57 yeah tolstoy likely has it

0:57 print returns nil

0:57 same with println, prn, pr, pprint

0:57 there's pr-str

0:57 which returns a string version of what pr would print, but doesn't print on its own

0:57 tolstoy: The other one is some version of (map (when test :val) ...).

0:57 TEttinger: ,(pr-str (map inc [1 2 3]))

0:58 clojurebot: "(2 3 4)"

0:59 user__: TEttinger, tolstoy could be a print

0:59 TEttinger: cwgem|mac: I think clojure may still have trouble with so-called "astral plane" values outside the Basic Multilingual Plane

0:59 like emoji chars, cwgem|mac

0:59 user__: but my printing is also print nil

0:59 I feel like I'm so close to getting Clojure

0:59 i'm very new to lisp

0:59 but learning fast

1:00 cwgem|mac: TEttinger: Not too worried about emoji yet. Just need it to be able to handle CJK

1:00 user__: ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (count (:paths(nth listInput 1)))))

1:00 clojurebot: 2

1:00 TEttinger: it seems like you're getting there. you understand that there's no "void" returns in Clojure, right user__?

1:00 user__: oh

1:00 thats not it

1:00 TEttinger: something like Java's

1:00 user__: TEttinger, i guess

1:00 TEttinger, what if an empty function is used

1:01 TEttinger: ,(.println System/out "yay")

1:01 clojurebot: nil

1:01 TEttinger: print is wrapped specially in clojurebot

1:01 System.out in Java isn't normally used to print in clojure, so clojurebot just shows what it returns

1:01 user__: ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (nth (:paths(nth listInput 1)))0))

1:01 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: core/nth"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: core/nth"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [sandbox$eval97 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval97 invo...

1:01 TEttinger: ah, that's dense

1:02 ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (nth (:paths(nth listInput 1))0)))

1:02 clojurebot: [:node 2 :cost 1]

1:02 user__: ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (nth (:paths(nth listInput 1))0)))

1:02 clojurebot: [:node 2 :cost 1]

1:02 TEttinger: heh

1:02 user__: beat me to it

1:02 ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (:node(nth (:paths(nth listInput 1))0))))

1:02 clojurebot: nil

1:02 user__: there

1:02 nil

1:02 that freaking nil

1:02 ugh

1:03 TEttinger: oh!

1:03 user__: ,clojurebot, what is this wizardry?

1:03 clojurebot: #error {\n :cause "Unable to resolve symbol: clojurebot in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: clojurebot in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: clo...

1:03 user__: ok thanks

1:03 TEttinger: ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (nth (:paths(nth listInput 1))0))

1:03 clojurebot: [:node 2 :cost 1]

1:03 TEttinger: so that's what you are trying to call :node on

1:03 user__: yes

1:04 TEttinger: but that isn't a map, it's a vector

1:04 maps use {}

1:04 vectors use numbers for keys

1:04 like arrays, but resizable

1:04 I suspect you had that as a map at some point

1:05 user__: oh

1:05 TEttinger: ,(let [listInput [{:paths [[:node 1, :cost 1], [:node 2, :cost 2]]},{:paths [[:node 2, :cost 1], [:node 3, :cost 2]]},{:paths [[:node 0 :cost 1], [:node 1, :cost 2]]}] ] (print (:node(apply hash-map (nth (:paths(nth listInput 1))0)))))

1:05 clojurebot: 2

1:05 user__: wow

1:06 that was cool

1:06 TEttinger: thankfully, maps are really easy to make in clojure compared to Java

1:06 user__: you got the :node in there

1:06 TEttinger: yep!

1:06 user__: Yes, java maps are terrible

1:06 way too messy

1:06 java should possibly stick with linked list or arrays lol

1:07 TEttinger: Clojure makes them a lot better, so even though they extend Java's Map interface and that means they aren't considered Collections (which is silly), Clojure lets you call seq on a hash-map or other map as a special case

1:07 and since seq works, map works (operating on key-value pairs)

1:08 and a lot of other stuff Just Works because of seq

1:10 ,(map (fn [[k v]] (+ k v)) {1 10, 2 20, 3 30}) ;; the extra square brackets inside the fn arg vector mean it's "destructuring" the argument it gets, turning the two elements of a seq-like thing it's passed into two named values, k and v (corresponding to the key and value)

1:10 clojurebot: (11 22 33)

1:11 TEttinger: destructuring also makes maps much easier to work with

1:11 in addition to other collections!

1:13 user__: interesting

1:13 TEttinger: user__: next time you're stuck in a deeply nested piece of code like that, try removing the parts that are related to any errors you get. if you don't know, try removing outer calls that do things first (so not let, since you usually need the let in examples like you gave, but I removed the "(print (:node" part and the parens on the other side

1:14 so you can try removing layers like peeling an onion, seeing if you need them first

1:14 user__: TEttinger, Yes, i love this about Lisp

1:14 TEttinger, Makes function tracing easy

1:15 TEttinger, but i still need to get my head around sequences, vectors, maps, coll, and the rest

1:15 i get vectors and maps now which is great

1:16 I'm considering takingmy vector I had upon and changing the multiple vectors into a map

1:17 or sorry, changing the key values inside to use a map, but i don't want it cluttered either.

1:21 TEttinger: sure! that's a good idea

1:35 user__: ,(let [listInput [{:paths [{:node 1}, {:cost 1}], [{:node 2}, {:cost 2}]]},{:paths [{:node 2}, {:cost 1}], [{:node 3}, {:cost 2}]},{:paths [{:node 0} {:cost 1}], [{:node 1} {:cost 2}]]}]] (print (:node(nth (:paths(nth listInput 1))0))))

1:35 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

1:36 user__: ,(let [listInput [{:paths [[{:node 1}, {:cost 1}], [{:node 2}, {:cost 2}]]},{:paths [[{:node 2}, {:cost 1}], [{:node 3}, {:cost 2}]]},{:paths [[{:node 0} {:cost 1}], [{:node 1} {:cost 2}]]}]] (print (:node(nth (:paths(nth listInput 1))0))))

1:36 clojurebot: nil

1:36 user__: TEttinger,

1:38 TEttinger: oh!

1:38 user__: nil is happening again :9

1:38 :(

1:38 TEttinger: I know why

1:40 ,(let [listInput [{:paths [{:node 1, :cost 1}, {:node 2, :cost 2}]},{:paths [{:node 2, :cost 1}, {:node 3, :cost 2}]},{:paths [{:node 0, :cost 1}, {:node 1, :cost 2}]}]] (print (:node(nth (:paths(nth listInput 1))0))))

1:40 clojurebot: 2

1:40 TEttinger: you were converting individual pairs to maps

1:40 ,(apply hash-map [[:a 1] [:b 2]])

1:40 clojurebot: {[:a 1] [:b 2]}

1:40 TEttinger: hm

1:41 ,(into {} [[:a 1] [:b 2]])

1:41 clojurebot: {:a 1, :b 2}

1:41 TEttinger: there we go

1:41 I changed it by hand in the data because it seemed easy enough (it took longer than I thought though!)

1:43 user__: ah

1:43 it makes sense !

1:43 A map carries multiple key value pairs

1:43 aha!

1:43 i got it

1:43 thank you TEttinger

2:15 wombawomba: So I want to run a small, profile-dependent piece of code when any lein task runs, that sets some state in my application. As far as I can tell, I would have to write a custom leiningen plugin to do this. Does anyone know of an easier way?

2:20 tolstoy: One way is to use boot, which is much more scripty and imperative.

2:20 There used to be a way to do hooks (robert hooke library).

2:21 What do you want the code to do?

2:27 wombawomba: Here's something: https://github.com/technomancy/leiningen/blob/master/doc/PLUGINS.md#hooks, but maybe a bash script might work better?

2:50 dysfun: or a makefile

3:01 kwladyka: wombawomba but if you only set state in the app, so i guess for example another date to database you can do it in lein.

3:02 wombawomba: sorry

3:02 kwladyka: ?

3:03 wombawomba: tolstoy: I want the code to set ips/ports for a bunch of hosts my project talks to

3:03 kwladyka: wombawomba maybe you need just that https://github.com/weavejester/environ ?

3:04 wombawomba: kwladyka: sorry, how do you mean about date to database? don't understand

3:04 clojurebot: Huh?

3:04 kwladyka: wombawomba ok i didn't guess your intention

3:04 wombawomba: and yeah, I guess environ could work

3:05 thanks

3:05 although, if I go with environ, I'd still have to make sure the init code is called for every target manually

3:06 eg I'd have to find some way to make my test runner call something like `(my-init-fn (env :profile))` before running any code

3:07 kwladyka: for tests use fixtures

3:07 wombawomba: I also have a bunch of aliases on the form run -m ... (essentially scripts), that would all have to call that code as well

3:08 kwladyka: I want to be able to run the exact same tests against a number of different host/ip configurations

3:08 but only one at a time

3:08 I don't think fixtures are appropriate, really

3:08 renl: hi in manifold is there a way to check if a stream has to take! from?

3:08 kwladyka: maybe you need profiles in the project.clj ?

3:09 wombawomba: kwladyka: yeah, that's what I'd like to do ideally

3:09 kwladyka: wombawomba https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md

3:09 wombawomba: I would like to have a bunch of profile, where each profile calls `(my-init-fn :profile-name)` as a first step for any task

3:10 kwladyka: afaict, there's no way to do that with profiles

3:10 I can do it for the repl, e.g. by setting :repl-options > :welcome

3:10 but I can't make sure it happens for my test runner, or for any of my `run -m ...` aliases

3:12 kwladyka: lein with-profile foo test don't satisfy you? I am not sure what is your problem :)

3:12 wombawomba: kwladyka: how do I get lein with-profile foo to run `(my-ns/my-init-fn :foo)` before the tests are run?

3:13 kwladyka: wombawomba use fixtures

3:13 wombawomba: and how do I get `lein with-profile foo run` to run `(my-ns/my-init-fn :foo)` before it calls main?

3:13 kwladyka: use fixtures how?

3:14 kwladyka: wombawomba something like that http://stackoverflow.com/questions/16350504/clojure-how-to-use-fixtures-in-testing

3:14 wombawomba: right

3:14 kwladyka: but i guess you can find better examples

3:14 wombawomba: but how do I run a fixture depending on which profile is active?

3:15 kwladyka: wombawomba you can use environ BTW and in fixtures read that value and depend on that value set something

3:16 wombawomba: yeah, if I use environ I can make it work

3:16 but I still have to manually make sure the proper code is called for every lein task, which is troublesome

3:17 I'd have to 1. do this in every fixture, 2. do this for the repl, 3. do this in every main- function I have

3:18 I am wondering if there's a way to do it once, in one place, without having to solve the problem in a different way for every lein task

3:18 kwladyka: i believe there is but don't solve everything at once time :)

3:19 you can use high priority functions or other solutions

3:19 to solve 3

3:19 and also 1

3:20 2, i guess in the REPL you want start with clear enviroment

3:20 anyway maybe you solve your solution in bad way

3:21 for example maybe you should load different config files depend on profile, or depend your conf on the variable in the system like MY_VARIABLE_FOR_SETTING in the bash

3:22 many solutions are possible, but i don't know precisely your problem. You have to find your own way :)

3:22 wombawomba: :) okay

3:22 I think I'll try boot

3:24 kwladyka: wombawomba try it, but i believe the problem is in solution design what you try to do.

3:24 (but i can be in mistake, because i don't know details)

3:25 wombawomba: yeah, it's possible

7:16 Glenjamin: does anyone else find it really hard to read (> x y) vs (< y x) ?

7:17 ridcully: > and < in prefix notation don't work well with my brain

7:18 Glenjamin: i find < works ok, because you then write the arguments in ascending order

7:18 MJB47: i 100% of the time

7:18 get them in the wrong order

7:18 Glenjamin: i just did exactly that

7:18 MJB47: even if i know im going to get them in the wrong order, so purposely flip them around

7:18 they will still be in the wrong order

7:21 dmsnell: Glenjamin: confused me until someone said "it's always the same, just move the operator for infix in between the arguments"

7:21 (< 4 5) => (4 < 5)

7:21 (> 5 4) => (5 > 4)

7:22 ridcully: yeah, that's what i do. but it's basically the only operator i have such trouble with

7:22 mrcnxs: Glenjamin, so if y was greater than x would you write (< x y)? and if it wasnt you'd write (< y x)? and what if you didnt know what x or y was?

7:22 Glenjamin: i still know what i want to do

7:22 dmsnell: I would argue that you should use whichever is closer to indicating what you want to infer in the code

7:23 mrcnxs: dmsnell, yeah thats usually how it works

7:23 dmsnell: (if (> x y) (biggerX) (notBiggerX))

7:27 Glenjamin: i just think that visually `<` looks like it's describing a little funnel

7:27 and `>` looks like it's pointing at some numbers

7:28 mrcnxs: just think of < looks like L for less

7:28 dmsnell: Glenjamin: try (funnel 4 5) and (point-to-> 4 5) XD

7:28 ridcully: maybe time to alias them with gt, lt, gte, ... ;_

7:29 tdammers: idk, I think < and > are bad names for variadic comparison functions, especially in prefix notation

7:29 if you write a < b, it's obvious that you want the thing on the smaller end of the < to be smaller, but (< a b c) requires a mental leap

7:30 Kneiva: What do I need to import to use predicates like 'in' and 'like' in Korma SQL?

7:30 Glenjamin: (def ascending? <)

7:31 tdammers: Glenjamin: yeah, except that (ascending? a b) also requires a mental leap when what you really want to express is "a is less than b"

7:35 Glenjamin: also true

8:16 sdegutis: Good evening.

8:20 Glenjamin: morning

8:20 is there a variant of cond/condp where I can pass a single argument and a series of predicates?

8:22 TimMc: Glenjamin: condp, if your argument is #(% foo bar)

8:22 Glenjamin: oh of course, that'll do it

8:22 TimMc: or hmm, maybe that's not quite it...

8:22 Glenjamin: thanks

8:22 i get the gist

8:22 TimMc: I don't use condp very often.

8:23 luma: (condp #(%1 %2) expr pred-1 result-1 pred-2 result-2 ...)

8:23 Glenjamin: yup, thats the one

8:24 luma: that'll evaluate (pred-1 expr), and if it's truthy, return result-1 etc

8:24 Glenjamin: much nicer: https://www.refheap.com/116924

8:24 TimMc: If all of your predicates are unary that could be annoying.

8:24 sdegutis: Glenjamin: what does your desired code look lik-- oh

8:24 TimMc: ah yeah, that works

8:24 Glenjamin: i was using normal (cond), but i'd forgotten to include the `number` argument with the sets

8:24 so it was always matching the second clause

8:24 sdegutis: Glenjamin: hmm it seems like there really ought to be a pre-made macro for that

8:25 ive wanted that too

8:25 (condf) or something

8:25 TimMc: You forgot :VR, vice-regent

8:25 sdegutis: (condf x, pos? :positive, neg? :negative, zero? nil, :else (throw))

8:26 justin_smith, TimMc, TEttinger3: does something like my conf exist?

8:26 *condf

8:27 ridcully: also you could cheat with your 42 numbered card ;)

8:28 Glenjamin: there's a (card) fn with some preconditions

8:29 I'm prepping a functional version of http://buildingskills.itmaybeahack.com/book/oodesign-3.1/html/blackjack/details.html for a workshop at the local FP group

8:29 hyPiRion: sdegutis: (defmacro condf [& body] `(condp #(%1 %2) ~@body)) ?

8:29 Except you must omit :else

8:30 sdegutis: hyPiRion: hmm sounds right, but it seems like such a useful thing that im surprised it doesnt already exist

8:31 Glenjamin: it would be possible to check for an odd number of arguments and generate :else I think

8:31 hyPiRion: condp #(%1 %2) isn't that much longer than condf

8:31 Glenjamin: https://github.com/glenjamin/defshef-blackjack/blob/master/clojure/src/defshef/blackjack.clj if anyone is interested in the rest

8:31 hyPiRion: Glenjamin: condp already does that

8:31 ,(condp #(%1 %2) 2 odd? :odd :even)

8:31 clojurebot: :even

8:31 Glenjamin: aha

8:32 oh i see what you mean about omitting now

8:32 oh, that also means my :else is wrong

8:32 * Glenjamin adds more tests

8:33 sdegutis: :)

8:35 Glenjamin: oh, heh - it works either way

8:35 because the (throw) evals

8:35 Fender: Hi guys, I'm working with emacs/cider and I currently have the problem that after some changes to the code and C-c C-k my code changes are compiled successfully but they are not seen by the nrepl server. There are no changes to var/ns names and no indirections apart form a #'handler indirection due to being a ring app. Does anyone experience something similar? and is it a cider or a clojure 1.8 problem (-> invokeStatic)

8:36 my workflow now requires often a cider-restart and that's annoying

8:42 sdegutis: Fender: im using clojure 1.8 and cider 11, and dont have that problem

8:42 Fender: i think the reason i dont see the same problem you see is because i dont use vars (e.g. #'handler) but instead i re-build the handler from a function after cider-refresh

8:43 cwgem|mac: Any folks toyed around with Clojure on Java 9 EA out of curiosity?

8:43 Fender: to be honest, I am not entirely sure what cider-refresh does and for what it is useful (other than what the name suggests)

8:44 sdegutis: Fender: it's basically just a wrapper around tools.namespace.repl.refresh or whatever its claled

8:44 Fender: it re-evals all your changed files in dependency-order and then optinoally calls a function you tell it to

8:45 in my case, system-start

8:45 Fender: sounds like something I should be using in these cases

8:47 OK, I think I found something re the how and why: https://github.com/clojure/tools.namespace

8:47 thanks already

8:48 sdegutis: Fender: also read about stuartsierra's Reloadable Workflow

8:48 it inspired me to adjust my code to be more reloadable

8:48 which is hecka aweasome

8:48 Fender: where everything is saved in a context map?

8:48 I know about it but I didn't yet need it

8:49 well, I think I need to catch up on that :)

8:54 sdegutis: Fender: :)

8:54 hi all

8:54 how do you interpolate strings into a regex?

8:54 ,(let[foo"bar"]#"#{foo}")

8:54 clojurebot: #<NoClassDefFoundError java.lang.NoClassDefFoundError: Could not initialize class java.util.regex.PatternSyntaxException>

8:55 sdegutis: oh, re-pattern

8:55 ,(let[foo"bar"]#(re-pattern foo))

8:55 clojurebot: #object[sandbox$eval47$fn__48 0x34af2848 "sandbox$eval47$fn__48@34af2848"]

8:55 sdegutis: ,(let[foo"bar"](re-pattern foo))

8:55 clojurebot: #"bar"

8:55 sdegutis: yay

9:24 hey

10:19 Hello?

10:19 How do you use ring-mock along with sessions?

10:19 I'm having trouble

10:34 Glenjamin: sdegutis: peridot might help there

10:34 it builds a concept of a session over ring-mock

10:34 with a cookie jar

10:34 sdegutis: Glenjamin: I remember using it a few years ago, but it looks since abandoned, and I remember having issues with it

10:35 Glenjamin: i somehow inherited it. it doesn't change much now - only major issues i'm aware of are around multipart uploads

10:35 sdegutis: Git says I removed peridot on April 29, 2013.

10:36 Glenjamin: to get a session in ring-mock, you need to make a cookiejar object, parse set-cookie headers from responses and pass cookie headers into requests

10:37 sdegutis: Glenjamin: which seems also to be what https://github.com/rreas/ring-test does

10:37 Glenjamin: see also https://github.com/rreas/ring-test/blob/master/src/ring_test/core.clj

10:38 Glenjamin: looking at our git history, peridot was very similar to webrat/capybara in its api, for better or worse, whereas ring-test is a lot simpler

10:40 Glenjamin: yeah, peridot is intended to flow between requests, and mostly exists for kerodon

10:47 sdegutis: Glenjamin: never mind yeah i was remembering kerodon mostly

10:56 Glenjamin: slightly off-topic, but does anyone know if there's a simple Haskell testing framework that's as easy to use as the tests in here: https://github.com/glenjamin/defshef-blackjack/blob/master/clojure/src/defshef/blackjack.clj

11:09 jjmalina: anyone recommend some resources for getting around the limitation of tail call recursion? like what if you need two different recursive calls?

11:10 arrdem: jjmalina: if you really need unbounded mutual recursion trampoline is typically what you'll use.

11:10 jjmalina: arrdem what do you mean by "unbounded mutual recursion"?

11:11 arrdem: jjmalina: if you have two fns which you want to mutually recur as if they had been tco rewritten into a goto block, you've got to use trampoline.

11:11 jjmalina: trampoline could work i suppose, just adds more complexity

11:11 in this case i am calling the same function, just with different arguments

11:12 arrdem: If it's a tail call you can just use recur

11:12 Sorry. A tail call of the same arity.

11:12 If you have to cross arities, you have to do a fn invocation.

11:13 jjmalina: basically it's a tree traversal

11:14 one recursive call goes left the other goes right, but then both results have to be handled

11:20 arrdem: Until you know you have to do something more advanced I'd suggest simply let binding the results of simple recursive calls.

11:21 sdegutis: Hi?

11:52 oh right, yeah

11:52 hi

13:20 someone1: hi

13:24 ben_vulpes: hello!

13:25 someone1: is there a rails like web framework for clojure? also with clojurescript support. I want to use datomic

13:26 ben_vulpes: nope.

13:26 someone1: I tried to use jruby mixed with clojure and clojurescript in the rails asset pipeline ... but it is not that good

13:43 Lewix: https://github.com/6ewis/recruitersPickupLines/blob/master/bestLines.md contribute for the laugh

13:48 tolstoy: Is there a way to specific a list as a p/schema type, rather than vector or map?

13:53 I have a DSL-ish thing: (foo bar [:some "data"]) and want to validate that foo == foo and bar is a symbol, but the whole thing is in a list. Hm. Maybe convert to vector before calling validate?

13:55 amalloy: i would be surprised if validate cared about the difference between vectors and lists

13:56 tolstoy: I think you're right. I'm getting some other error I don't understand regardless.

13:57 Like, you know, using defn where I should be using def.

14:51 backnforth: So Eclipses ide works with Clojure? Can I use it to get variables values at a breakpoint?

14:54 ane: I don't think it has debugging

14:54 cursive or cider can do debugging

14:59 backnforth: it does with java

15:12 can i retrieve variable values at a breakpoint with cider?

15:15 bendlas: dnolen: hi, we're here at the vienna om.next meetup. we are working with the todomvc demo and try to complete it

15:16 dnolen: @bendlas: ok might be a slightly tricky, also I haven't really looked at it in a very long time.

15:16 bendlas: dnolen: we were wondering, how we were supposed to trigger rerenders asynchronously in the reconciler

15:17 dnolen: bendlas: I don't really understand that question

15:17 bendlas: dnolen: there seems to be a mismatch with {:value {:keys [:foo]}} vs {:value [:foo]}

15:17 dnolen: what's there does demo basic async calls & render

15:18 bendlas: we're trying to implement creation and it's already working, but the ui doesn't rerender

15:18 dnolen: bendlas: I think this is a typical misunderstanding

15:18 {:values {:keys ...}}

15:18 doesn't have a real meaning - it's just for humans

15:18 the only thing that triggers re-renderings are explicit re-reads

15:18 [(change/it!) :foo :bar]

15:19 bendlas: right, we tried that, but doesn't work

15:19 dnolen: components that depend on :foo and :bar will render when you run this query expression

15:19 bendlas: b/c ui rerenders before server returns

15:19 dnolen: bendlas: well you need to be specific about whether that query is needed both locally and remotely

15:20 that is you can make it run twice

15:20 bendlas: a better place to ask this question is in the Om Slack channel, lots of people there who can help this bit

15:21 bendlas: ok, so to rerun it on the client after the server returns (that was my question about async rerender), we would call merge! ?

15:22 dnolen: bendlas: I dont' think so, all there's a bunch of simple defaults in place to avoid having to customize really basic stuff

15:22 bendlas: sorry I can't say much more at the moment, busy with some other stuff

15:22 bendlas: ya, sorry, don't want to keep you

15:23 om.nnext? ;-)

15:38 kwladyka: hmm agents run function 1 time, atoms can run many times during conflict. Why not just always use agents?

15:44 rhg135: agents use a thread pool

15:49 kwladyka: agent make new thread, atom operate on same shared state in the thread where is called

15:50 ?

15:50 but still not sure why use atoms over agents when generally everybody want run functions 1 time

15:51 amalloy: there are lots of things you generally want

15:51 eg, you generally want functions run at a particular time

15:52 which is not a feature agents offer

15:54 kwladyka: amalloy so it is the choice between run functions many times but immediately and one but don't know when?

15:55 still i can't imagine when atom is over agent? If i have to run something immediately for example to third part software i can just run that without atom. What i want to use with atom with danger of running it many times?

15:58 Even idempotent function, why run they many times if can be run once? Running them many times don't have anything.

16:05 dysfun: because it results in higher throughput on average

16:06 kwladyka: dysfun ok that is the argument

16:09 thx

17:26 Lewis: stupid question

17:26 ,`(1 2 3 4)

17:26 clojurebot: (1 2 3 4)

17:27 Lewis: ,'(1 2 3 4)

17:27 clojurebot: (1 2 3 4)

17:27 Lewis: (= `(1 2 3 4) '(1 2 3 4))

17:27 ,(= `(1 2 3 4) '(1 2 3 4))

17:27 clojurebot: true

17:27 Lewis: ,(class `(1 2 3 4) )

17:27 clojurebot: clojure.lang.Cons

17:28 Lewis: ,(class '(1 2 3 4) )

17:28 clojurebot: clojure.lang.PersistentList

17:28 TimMc: Lewis: Correct. :-)

17:28 Lewis: whats the difference between cons and persistentList?

17:29 TimMc: ,(ancestors (class `(1 2 3 4)))

17:29 clojurebot: #{clojure.lang.IObj clojure.lang.IMeta clojure.lang.Sequential clojure.lang.ASeq java.lang.Iterable ...}

17:29 TimMc: hrmf

17:29 ,(apply println (ancestors (class `(1 2 3 4))))

17:29 clojurebot: clojure.lang.IObj clojure.lang.IMeta clojure.lang.Sequential clojure.lang.ASeq java.lang.Iterable clojure.lang.IHashEq clojure.lang.Obj java.io.Serializable java.util.Collection clojure.lang.Seqable java.util.List clojure.lang.ISeq clojure.lang.IPersistentCollection java.lang.Object\n

17:30 TimMc: ,(apply println (ancestors (class '(1 2 3 4))))

17:30 clojurebot: clojure.lang.IObj clojure.lang.IMeta clojure.lang.Sequential clojure.lang.ASeq clojure.lang.Counted java.lang.Iterable clojure.lang.IHashEq clojure.lang.Obj java.io.Serializable java.util.Collection clojure.lang.Seqable clojure.lang.IReduceInit java.util.List clojure.lang.ISeq clojure.lang.IPersistentCollection clojure.lang.IPersistentList java.lang.Object clojure.lang.IReduce clojure.lang.IPersis...

17:32 TimMc: Lewis: Anyway, to answer your question... not a whole lot. :-)

17:33 They're both sequential, serially accessed data structures.

17:34 Cons is a seq, whereas PersistentList is a list, and the difference is kinda subtle to nonexistent.

17:40 Lewis: TimMc: in other words, you dont know the diff either?

17:41 TimMc: Lewis: I can tell a story about what I think the difference is, but I don't think there's an official explanation.

18:02 wombawomba: what's the best library for doing http requests in cljs these days?

18:05 arrdem: wombawomba: clj-http still works just fine

18:05 wombawomba: if you need async the choice is less obvious

18:05 wombawomba: async would be nice

18:06 arrdem: http-kit is probably more your speed then.

18:06 wombawomba: hmm

18:06 notw I wrote cljs

18:07 bsima: wombawomba: I think cljs-http is the equivalent https://github.com/r0man/cljs-http

18:10 wombawomba: okay

18:31 backnforth: How do I do a hot reload of my Clojure code when using the repl?

18:37 Glenjamin: anyone know how to go from 0x1F0A0 to the character at that unicode code point?

18:38 TEttinger: backnforth: there's a :reload additional argument that can be passed to require

18:38 Glenjamin: that's going to be tricky since that's really two chars

18:38 ,(Character. 0x1F0A0) ; just curious, not sure if this works

18:39 clojurebot: #error {\n :cause "java.lang.Long cannot be cast to java.lang.Character"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.Long cannot be cast to java.lang.Character"\n :at [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox$eval25 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.jav...

18:40 Glenjamin: oh good, the docs for Character have a brief discussion about how terrible a choice UTF-16 was

18:41 with no hint of an alternative

18:41 justin_smith: backnforth: another options is load-file, especially useful when you want to load code from a local copy of a file (eg. if really you loaded from a jar, but want to redefine some of the code from a copy of the file from the jar)

18:42 Glenjamin: hrm, actually in my case the first byte doesn't need to change

18:44 justin_smith: backnforth: also, environments like CIDER or fireplace should have a keystroke to send the current function or file to the repl (and this will use load-file under the hood)

18:46 backnforth: justin_smith, interesting

18:46 justin_smith, I haven't gotten around to installing vim-cider yet

18:46 justin_smith, only vim-fireplace

18:50 Deraen: backnforth: Fireplace includes the functionality to reload namespaces (cpr) and evaluate forms (cpp, cp<motion>).

18:52 Glenjamin: ,(Character/toChars 0x1F0A0)

18:52 clojurebot: #object["[C" 0x9c32307 "[C@9c32307"]

18:52 Glenjamin: now how do I turn a primitive character array into a string?

18:53 oh, duh

18:53 ,(String. (Character/toChars 0x1F0A0))

18:53 clojurebot: "🂠"

18:53 Glenjamin: ,(String. (Character/toChars (inc 0x1F0A0)))

18:53 clojurebot: "🂡"

19:28 backnforth: Is it ok to have a "let" function inside of a loop? I keep getting a NullPointerException because of it. I have done much debugging and the error is coming from the viable value I'm trying to assign with.

19:29 Glenjamin: backnforth: can you post some code? (via a pastebin of some sort)

19:31 backnforth: Glenjamin, certainly

19:36 http://pastebin.com/GA0cf55H

19:36 Glenjamin, The error happens at the first let on the second iteration of the loop

19:37 Glenjamin: you're trying to access some of those vectors as if they were maps

19:40 backnforth: Glenjamin, It accesses work outside of the let

19:41 Glenjamin, And it should work because the vectors hold maps

19:41 Glenjamin: it's hard to follow what's going on, i'd suggest breaking it up into a series of smaller functions so you can check those bits independently

19:42 but for example, you do (:paths tempVector)

19:42 but tempVector is a vector, so that'l always be nil

19:43 backnforth: Glenjamin, Ah. How could I go about simply making it a map?

19:44 Glenjamin, {} yes

19:44 Glenjamin: yes

19:44 it's really hard to follow this function, i think mostly because it's operating at a bunch of different levels of abstraction

19:45 here's more detail on what I mean by that: http://principles-wiki.net/principles:single_level_of_abstraction

19:45 amalloy: regularization of whitespace would help a lot too

19:47 backnforth: interesting, thank you

19:48 Glenjamin, Weird. Now I'm getting an error at my first recur

19:48 Saying I can only recur from tail possition

19:49 I know recur can work with cond, but about if/else inside of a cond?

19:58 Glenjamin, nvm, that was my fault for having a bad brace

20:51 bsima: Does anyone know much about core.match internals?

20:51 I could use some help improving this https://gist.github.com/bsima/f48eeb3d4531be1408287727016beb2a

20:51 see the tests on line 34. I'm pretty stumped about how to fix it

21:36 cespare: Is there a faster way to create an empty transient vector than (transient []) ? The cloning of the empty vector seems to be using a lot of cpu in a profile

21:37 justin_smith: cespare: transient shouldn't by cloning anything - all it needs to do is set a bit

21:37 unless I'm totally misremembering how transients work

21:38 dmac: justin_smith: I'm working on this with cespare; this is the expensive line that's showing up in our profile: https://github.com/clojure/clojure/blob/clojure-1.7.0/src/jvm/clojure/lang/PersistentVector.java#L547

21:38 justin_smith: specifically the .clone()

21:39 cespare: justin_smith: well, if you do (transient foo), then foo needs to remain undisturbed by whatever mutate-y stuff you do with the transient, yes?

21:42 justin_smith: transient calls asTransient https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L3209 which then calls transientvector's constructor https://github.com/clojure/clojure/blob/clojure-1.7.0/src/jvm/clojure/lang/PersistentVector.java#L133 and all that does is flip some bits https://github.com/clojure/clojure/blob/clojure-1.7.0/src/jvm/clojure/lang/PersistentVector.java#L523

21:42 cespare: oh, wait, the editableRoot and editableTail methods do clone an array - not the whole vector, but one node

21:43 which dmac linked while I was source digging, heh

22:51 Lewis: justin_smith: how do you guys think in terms of recursion day in and day out

22:52 https://gist.github.com/6ewis/4e280967cf6f33aed05463f3e4ec41ab this piece of code give me headaches

22:52 justin_smith: Lewis: you should almost always use cond instead of nested if

22:52 and you should use recur instead of that self call

22:52 Lewis: justin_smith: thats not my code

22:53 justin_smith: oh, I had no way of knowing that

22:53 Lewis: justin_smith: my solution is actually a one liner

22:53 #(= (seq %) (reverse %))

22:54 justin_smith: i was looking at somebody else solution and I was flabbergasted by the fact that it made sense to him

22:54 justin_smith: is it me or this code is overly complex and hard to follow

22:54 justin_smith: it's a direct translation of how you would write it in C

22:54 Lewis: i still dont get it but i get the idea

22:55 really

22:55 justin_smith: complete with the annoying trailing braces

22:56 Lewis: justin_smith: ok ill have to study it

22:57 ,(doc butlast)

22:57 clojurebot: "([coll]); Return a seq of all but the last item in coll, in linear time"

22:57 justin_smith: oh, I guess that part isn't like c, heh

23:11 amalloy: well, in C you'd simulate rest/butlast with start/end pointers

23:13 incidentally that function is much simpler with no ifs at all: (defn palindrome? [xs] (or (not (next xs)) (and (= (first xs) (last xs)) (palindrome? (butlast (next xs))))))

23:22 Lewis: amalloy: wow any suggestion on how to make the it easier on the mental load?

23:23 amalloy: practice, like anything

23:23 do exercises if that helps

23:27 Lewis: amalloy: i meant the recursion stuff

23:27 amalloy: yep

23:27 practice

23:27 Lewis: like your example and the gist i gave

23:27 amalloy: uh huh

23:27 practice writing and reading recursive functions

23:27 that's it

23:27 no silver bullets

23:32 Lewis: amalloy: ok im on it

23:48 amalloy: ahhh its pretty easy now

23:48 im black belt in recursion :p

23:53 amalloy: your solution is even more complicated

23:53 sheesh

23:53 amalloy: it is literally less complicated: it replaces (if foo true bar) with (or foo bar)

23:54 and likewise (if foo false bar) => (and foo bar)

23:54 Lewis: ,(doc and)

23:54 clojurebot: "([] [x] [x & next]); Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true."

23:54 Lewis: ,(and 1 2 3 4 5 false 3)

23:54 clojurebot: false

23:55 Lewis: ,(and 1 2 3 4 5 3)

23:55 clojurebot: 3

23:55 Lewis: ,(doc or)

23:55 clojurebot: "([] [x] [x & next]); Evaluates exprs one at a time, from left to right. If a form returns a logical true value, or returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expression. (or) returns nil."

23:56 Lewis: ,(or 1 2 3 4 5 true 4)

23:56 clojurebot: 1

23:56 Lewis: ,(or false nil 3)

23:56 clojurebot: 3

23:57 Lewis: amalloy: that's so misleading, i expect or to be || and and to be AND

23:57 &&

23:58 amalloy: okay, and...it is

23:58 not sure how you are misleading yourself here

Logging service provided by n01se.net