#clojure log - Dec 08 2015

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

0:00 justin_smith: ,(,,,,+,,,,,,,,2,,,,,,,,,,2,,,,,,,),,,,,,,,,,,,,,,,,,,,,

0:00 clojurebot: 4

0:00 dongcarl: justin_smith: oh, so it was just for aesthetic purposes?

0:00 justin_smith: right, they don't do anything

0:00 dongcarl: justin_smith: thanks!

0:00 justin_smith: well, they don't do anything a space or newline wouldn't do (of course)

0:22 dongcarl: Hi guys, is there anywhere that can explain clojure's loop and recur structure to me? I'm a scheme user and I don't think I've seen this elsewhere...

0:29 help anyone?

0:32 spieden: dongcarl: have you seen this page? https://clojuredocs.org/clojure.core/loop

0:34 dongcarl: spieden: yes... I think I get it now... so recur just binds the same variables that loop already bound, but to the new values passed to it?

0:51 owlbird: how do you guys test your code?

0:53 mlb-: dongcarl: sounds right to me

1:08 spieden: dongcarl: yeah exactly. like a tail optimized recursive call

1:09 dongcarl: compiles down to similar bytecode to a java loop i think

1:16 dongcarl: spieden: because the JVM isn't optimized for tail-recursion?

1:16 sara: Hi, how to call methods from db.clj in core.cljs,i have core.cljs file with login ui and i want to call a method from db.clj when i click a button

1:16 please help me if anyone know this..

1:54 ridcully_: sara: you need to `require` your db ns. e.g. in your (ns ... (:require [my-ns.db :as db])) and then (db/dosomething ...)

1:57 jonathanj: i have some code that calls a function `fetch-contents` which does an HTTP GET and returns some contents, now to test this i'd rather that function returned some predefined data and made no network requests, i think this is called dependency injection? is there a convenient way to achieve this with Clojure?

1:58 i could of course pass the function as a parameter, but then the implementations get a bit longer and uglier

2:01 ooh, `with-redefs` looks like the winner

2:01 tolstoy: jonathanj You could also define the client with defprotocol, then have a "mock" implementation locally.

2:02 (defprotocol WebClient (get-data [_ params]))

2:02 jonathanj: you still have to pass the implementation to the fn, which is more or less the same as just passing my stubbed version

2:03 so i'm not quite sure what the point would be for a simple piece of code like this

2:03 tolstoy: For your test, you'd just do: (defrecord FakeClient [] protocol/WebClient (get-data [_ params] {:fake "data"})).

2:03 jonathanj: tolstoy: yeah, but you have to pass an instance of that to the fn trying to use it, not so?

2:03 tolstoy: jonathanj Yeah, what I was mentioning is better if you've got a bit of complication.

2:03 jonathanj: agreed

2:04 tolstoy: No, I don't think so.

2:04 There are two defrecords, the "real" one, and the fake one. You're writing tests to the protocol.

2:04 So, (get-data (FakeService.) "x" "y") or whatever.

2:05 jonathanj: okay, except that the tests aren't calling get-data directly

2:05 it's a higher level function

2:05 tolstoy: Ah.

2:05 That's where something like Component helps out.

2:05 jonathanj: like: (defn foo [uri] (do-stuff (http/get uri)))

2:05 tolstoy: with-redefs definately works.

2:05 jonathanj: i'm using system, which is built on component

2:06 how does component help me?

2:06 tolstoy: For tests, you create a new System with the mock deps you want, then start that up rather than the real one.

2:06 jonathanj: the deps still have to get somewhere somehow

2:07 tolstoy: Using component (or system)?

2:07 jonathanj: how does my mock dep get from my system to the foo function above?

2:08 tolstoy: How does the real dep get there? Just use the same way?

2:08 jonathanj: it's required?

2:08 Trioxin: is there anything wrong with creating things like maps and vectors with def to work with them later? So far in my tutorial I haven't seen it done but tried it and it seems to word as in (get vec1 :b)

2:09 jonathanj: tr.

2:09 Trioxin: (def) defines a value global to the namespace you call it in, so you probably don't want to use it for anything that isn't supposed to be global, or for simple examples/repl work

2:10 tolstoy: jonathanj : I can't speak to your system cause I can't see it, but I have stuff like (system-map {:web-svc (mk-web-svc) :data-svc (component/using ... {:web :web-svc})) etc.

2:11 Trioxin: jonathanj, I had put it in a defn to be used within it. so how would I work with a map or vector later? I keep seeing examples of both creating and searching them in the same line but never assigning a name to them.

2:11 tolstoy: So, in tests, I just make one of those, and instead of (mk-web-svc) I use (mk-fake-web-svc). The data-svc then uses that one. Since they both implement the same interface, it works.

2:11 jonathanj: Trioxin: what do you mean by "later"?

2:12 tolstoy: so say you had a function "foo" defined more-or less like i did above, how does it get access to the system map? do you have to pass it to it?

2:12 Trioxin: jonathanj, create a map and then get a value out of it later in a function

2:12 jonathanj: Trioxin: within the same function?

2:12 Trioxin: sure

2:12 jonathanj: Trioxin: perhaps you're looking for `let`?

2:12 ,(doc let)

2:12 clojurebot: "([bindings & body]); binding => binding-form init-expr Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

2:13 jonathanj: that's not actually that useful

2:13 https://clojuredocs.org/clojure.core/let

2:13 tolstoy: jonathanj Yes, or I'm assuming that "foo" is invoked in the context of an existing component, so has access to that components config. But I guess an example is better. Alas, I don't have one visible.

2:14 dongcarl: does clojure do `let' sequentially or in parallel?

2:14 jonathanj: sequentially

2:14 ridcully_: sequentially

2:14 dongcarl: jonathanj: so similar to let* in lisp?

2:14 jonathanj: dunno, the only lisp i know is Clojure

2:14 ridcully_: ,(let [a 1 b (inc a)] b)

2:14 clojurebot: 2

2:15 dongcarl: jonathanj: ridcully_: thanks

2:15 jonathanj: tolstoy: sorry if i'm being stupid here, but i don't understand how "foo" actually gets a reference to the component in order to peel things out of it

2:17 tolstoy: jonathanj: https://gist.github.com/zentrope/ff6fee94f39927d1046f

2:18 Trioxin: jonathanj, I just read let. I am seeing in this tutorial though using defn to create functions that work with sets of data as maps and vectors. This is the accepted way of working with such datasets?

2:18 tolstoy: jonathanj: In that example, I'd make a new map for "testing" and use, say (make-fake-mail-svc) instead of the real one.

2:18 jonathanj: Then, when I call a function (do-something-that-results-in-mail (:biz-svc system)), my fake version would be invoked.

2:20 ridcully_: Trioxin: top level def's (consider ^:const) are fine

2:30 tolstoy: jonathanj I guess in my apps, maybe nothing ever happens except it's inside one of the components. Perhaps you're doing something different? Crossed assumption in there somewhere. ;)

2:43 Trioxin: intellij is annoying me. It never lets me backspace a ( or ) or add one when I'm trying to correct a mistake in my program

2:43 i have to cut and paste them

2:46 TEttinger: Trioxin: sounds like you have paredit on?

2:46 it's on by default in cursive

2:46 Trioxin: thx

2:46 TEttinger: it's either a setting or a button to enable/disable it

2:59 ridcully_: Trioxin: it's called structural editing. it can be toggled with a small button on the lower/right corner or in the settings

3:02 slaterr: sdf

3:03 luma: Trioxin: also, it's actually quite helpful, since it doesn't let you create uneven parentheses

3:03 qsys: clojure and desktop applications: is seesaw still the best option? or are there any other/newer/still maintained projects?

3:03 TEttinger: seesaw doesn't need changes really does it? I mean swing isn't changing

3:03 Trioxin: oic it. just need to turn it off every now and then

3:04 TEttinger: seesaw is really nice IMO

3:04 qsys: allright, never did much in seesaw so far... so well, it's nice and stable

3:05 good enough for me than

3:05 *then

3:05 TEttinger: it helps to check the source of the examples -- docs are good not great

3:06 qsys: ok, thanks.

3:07 Trioxin: For GUI of my clojure programs I'll be using nw.js for desktop

3:08 qsys: nw.js, so clojurescript?

3:09 reasons to use nw.js instead of seesaw?

3:10 Trioxin: HTML5, node, clojurescript, and I should be able to embed jars that can talk in the dom

3:11 as in an applet or you could just communicate on the backend of the app via node since node code in nw.js interops with the dom code

3:12 so very easy to make a GUI

3:12 qsys: yes, I can imagine that

3:13 but easier than, e.g. seesaw? (which looks really simple as well)

3:13 Trioxin: easy as making a webpage. styling with some jquery dropins

3:15 qsys: hmmm, maybe I should try both

3:17 if jars can be embedded in nw.js - that may be a bit of double resources useage: nw.js running on a javascript engine and starting a jvm for some logic

3:17 Trioxin: you could even do both and embed your app at 100% the window if you wanted the extra scripting and node

3:18 you can strip nwjs down to be pretty small getting rid of what you don't need

3:19 qsys: and have just plain access to filesystem and such - I'm talking about a rather small application for desktops only (yes, I have someone asking for that!?)

3:20 Trioxin: jvm will run as separate process i believe and still you have the interop

3:23 qsys: well, maybe time to compare seesaw and nw.js :p

3:24 Trioxin: in my experience, using html5 for desktop GUI comes out looking very nice very fast and then much of that code is then portable to cordova/phonegap

3:26 qsys: sound nice, so here I go... seesaw vs nw.js

3:26 might be fun.

3:26 Trioxin: http://jqueryui.com/

3:41 I'm looking for the last jquery theme I used that was really nice but for some reason I'm missing a file. must be on my external drive

3:42 qsys: :) don't worry, I'll find out.

3:42 theming is not my biggest concern right now :)

3:43 Trioxin: http://www.jquery2dotnet.com/2013/05/jquery-ui-themes-collection.html

4:06 alexyakushev: Hello everyone

4:07 What is the correct way to fully clojure.edn/read a stream until EOF?

4:08 muhuk: alexyakushev: does it stop reading halfway through?

4:09 alexyakushev: No, I just have a file with individual EDN objects, and I want to read them all one-by-one until the file ends

4:09 Like `slurp`, but use clojure.edn/read instead

4:11 Scratch the one-by-one part, I'm being incomprehensible. I just want to read all of them, without catching EOF exception manually

4:11 muhuk: alexyakushev: so you don't want an exception to be thrown on EOF?

4:13 alexyakushev: I thought there might be some utility reading function like `slurp` that just stops reading at the end of file, and returns the result

4:15 noncom: alexyakushev: why don't you slurp and then read-string?

4:15 alexyakushev: actually it sounds like you'd better wrap the individual edn objects into a edn []

4:16 alexyakushev: Because the file is very big, and I reading it as a string first effectively doubles the memory required to process it. Even if it will be GCed shortly after

4:16 noncom: or maybe something like (read-string (str "[" (slurp file) "]"))

4:16 ah i see

4:17 alexyakushev: noncom: No, wrapping it in a top-level sequence is exactly what I don't want to do. EDN is not some filthy JSON, its meant to be streamed :)

4:17 *it's

4:18 noncom: alexyakushev: afaik there's no such functionality readily available

4:18 alexyakushev: I want to have both the ability to read it object by object when I need that, and to read it all without extra hassle

4:19 noncom: Yeah, I suspected that, just asked to be sure

4:20 noncom: alexyakushev: a bit contradictory to the term "edn is meant to be streamed".. but really, there are such holes in functionality - one of them i met when it turned out that clojures ns system is coupled with filesystem, and it is not possible to easily fetch namepsaces from, say, a database or network

4:21 alexyakushev: Yes, there is that

4:22 I just recollect that in one of his talks rhickey said that being able to stream EDN or Transit objects is one of their advantages over JSON where you must have one top-level object

4:23 muhuk: streaming is streaming, EDN or JSON doesn't make a difference.

4:24 what does `read` return? Multiple values or a single seq?

4:25 alexyakushev: muhuk: They do, in fact. Is "foobar" a valid JSON?

4:26 *do differ

4:26 muhuk: alexyakushev: how do you connect having a top-level object with streamability?

4:27 alexyakushev: muhuk: How do you put three JSON objects — "foo", "bar", "baz" — on a stream?

4:28 muhuk: alexyakushev: how does `read` delimit EDN values of `foo` and `bar` (without ticks)?

4:29 alexyakushev: ,(read-string "foo bar")

4:29 clojurebot: foo

4:29 muhuk: alexyakushev: there's your top-level object, it's just not EDN

4:30 alexyakushev: There - where? There is no top level object in that string. There are two objects.

4:31 muhuk: :)

4:31 owlbird: how to add a list of data like ({:math 80} {:math 70} and output {:math 150 :count 2}

4:31 muhuk: alexyakushev: you can write a function that reads a stream of valid JSON, separated with whitespace. It would be no different than the streaming EDN.

4:32 owlbird: there is no core function, if you are asking that

4:32 alexyakushev: owlbird: I don't think there is a single function that does exactly that. But you can construct it from parts

4:32 ,(merge-with + {:math 80} {:math 70})

4:32 clojurebot: {:math 150}

4:33 alexyakushev: Then you can `assoc` the number of maps to it

4:33 owlbird: awesome!

4:34 alexyakushev: muhuk: OK, now you have a stream of JSON objects separated by whitespace. Is that stream valid by JSON spec? How do you read a single value from it?

4:35 muhuk: alexyakushev: is `foo bar` valid EDN?

4:35 alexyakushev: Yes

4:35 muhuk: read-string said no above

4:35 alexyakushev: read-string said yes, it correctly read the first value

4:36 muhuk: alexyakushev: observe:

4:36 ,(read-string "##")

4:36 clojurebot: #error {\n :cause "EOF while reading character"\n :via\n [{:type java.lang.RuntimeException\n :message "EOF while reading character"\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]\n :trace\n [[clojure.lang.Util runtimeException "Util.java" 221]\n [clojure.lang.LispReader$DispatchReader invoke "LispReader.java" 677]\n [clojure.lang.LispReader read "LispReader.java" 263]\n [cloj...

4:36 muhuk: ,(read-string "foo ##")

4:36 clojurebot: foo

4:37 muhuk: alexyakushev: by your logic `foo ##` is also valid EDN

4:37 alexyakushev: `##` is not a valid EDN object

4:38 But the reader stops before it

4:39 muhuk: alexyakushev: did you think why?

4:39 if `foo bar` is valid EDN, why does read-string just read the first bit?

4:40 alexyakushev: Because `foo` is a valid EDN object. `read` reads the first object from the string and returns it.

4:40 s/string/stream/ but the idea is the same

4:41 muhuk: no it's not. `foo bar` not valid EDN, `[foo bar]` is, also `(foo bar)` etc.

4:41 `foo bar` is two valid EDN parts, joined with a space

4:43 in spec it says "There is no enclosing element at the top level. Thus edn is suitable for streaming and interactive applications."

4:43 I guess it's time I eat my words. :(

4:45 alexyakushev: muhuk: No shame as long as the knowledge increases after the discussion

4:45 And you were right that by separating json elements on a stream with whitespace it might be enough to imitate this behaviour

4:46 But since JSON spec says nothing about that, it is entirely on the shoulders of the implementor to either support that or not

4:46 muhuk: yeah, that bit I would still defend. JSON is as streamable as any encoding.

4:47 the spec says there's no enclosing element at the top level, but there is actually an enclosing list/seq, implicitly

4:47 alexyakushev: There's no such thing as "JSON stream" officially

4:47 https://en.wikipedia.org/wiki/JSON_Streaming

4:48 muhuk: yeah I know

4:48 but in practise people do stream JSON

4:48 alexyakushev: Sure

4:48 muhuk: and it works just fine

4:48 alexyakushev: But if I say to me "I will send you a JSON stream", how should I treat that?

4:49 muhuk: you're right. I would ask how you delimit.

4:49 "\r\n" is what's used mostly (prints well)

4:49 alexyakushev: Indeed. So it's not really JSON at this point, but our custom format on top of JSON

4:50 muhuk: alexyakushev: aren't you at least a bit curious why read-string doesn't support this behavior?

4:50 I mean reads just the first thing, ignoring the rest.

4:50 alexyakushev: I think that's the behavior most people expect, or have learned to expect

4:51 read-string is no different from read, except that it turns a string into a stream

4:51 And I wouldn't want `read` to consume the whole stream if I need just one element

4:51 muhuk: but since I now know `foo bar` is valid EDN, I would expect to get a '(foo bar) and not just 'foo

4:52 alexyakushev: Imagine you have a 50GB file of EDN objects, and you want just the top 10 of them

4:52 muhuk: my point is, definition of valid EDN seems to differ, when you're expecting a stream and when you are not.

4:53 alexyakushev: also did you try setting :eof param in options to something like ::this-is-the-end?

4:56 alexyakushev: Damn it, that's where they moved it! I'm so dumb

4:56 Thanks, now that was really helpful:)

4:56 muhuk: alexyakushev: yw

4:57 alexyakushev: And back to `read-string` question

4:57 Like I've said, `read-string` is just a wrapper around `read`

4:58 So it shouldn't really know if somewhere later in the string there is invalid EDN

4:59 A stream can't know that, a string can, but we'll have to parse the whole string first to ensure that all EDN is valid, and then return only the first element. Which is weird

5:07 sara_: how to use web-server to handle the requests from clojurescript

5:08 muhuk: alexyakushev: that's what I'm saying: it is weird and confusing

5:08 alexyakushev: I'm not really arguing though, if spec says it is, it is

5:09 alexyakushev: muhuk: It might be confusing at first, but at least it is consistent. Which is much more valuable for me

5:09 muhuk: but if I was designing it, I would make "streaming EDN" as an extension to EDN

5:09 I don't think it's consistent

5:10 for the same input; you get a seq from `read`, but `read-string` reads the first thing

5:10 ridcully_: sara_: are you asking the same questions on stack-overflow? then see the comments there

5:11 muhuk: and paste the link to SO so we don't have to fish the details out

5:11 ridcully_: sorry, i was just guessing

5:12 alexyakushev: muhuk: What is an example where you get different things from read and read-string?

5:14 muhuk: alexyakushev: take "foo bar", make a reader out of it. Essentially they are the same input right?

5:15 alexyakushev: Absolutely

5:15 ,(read (java.io.PushbackReader. (java.io.StringReader. "foo bar")))

5:15 clojurebot: foo

5:16 alexyakushev: ,(read-string "foo bar")

5:16 clojurebot: foo

5:16 muhuk: damn you alexyakushev, you made a fool of me again :D

5:17 I thought read was returning a lazy-seq of some sort

5:17 alexyakushev: Oh

5:18 Well, now you know:) It's all for the best

5:18 And thanks again for pointing me at the correct edn/read option! I gonna do so some actual work now

5:18 Cheers

5:18 muhuk: alexyakushev: OK, it's not confusing or inconsistent etc. anymore. Just need to RTFM

5:19 byw

5:19 bye

7:36 clgv: I tried to test direct linking with clojure 1.8-RC3 but it didn't seem to work. I used the following profiles {:uberjar {:aot :all}, :1.8-DL {:dependencies [[org.clojure/clojure "1.8.0-RC3"]], :jvm-opts ^:replace ["-Dclojure.compiler.direct-linking=true"]}} and assumed that direct linking should be used in "lein with-profile 1.8-DL do clean, uberjar" then

7:38 but functions are still resolved via .getRawRoot on call sites

7:41 Bronsa: clgv: I just tried and it's definitely direct linking my vars

7:41 with that same setup

7:42 clgv: Bronsa: ok, that's weird then

7:43 Bronsa: does direct linking have fallback code generated and I confused that?

7:45 I looked up the invoke function of my.ns$my_fn.class with a java decompiler

7:46 Bronsa: clgv: DL generates an invokeStatic method

7:46 clgv: Bronsa: in the same class?

7:46 Bronsa: yes

7:46 clgv: ok that's definitely missing

7:46 Bronsa: clgv: what functions are you trying to compile?

7:46 if you try (defn foo [x] x) (defn bar [x] (foo x))

7:47 clgv: that's the layout, yes

7:47 Bronsa: bar should be compiled into invokestatic Foo.invokeStatic

7:47 clgv: Bronsa: I'll enter this simple example in the same namespace and check again

7:50 Bronsa: might be a build tool problem - the code is in a non-aot dependency library

7:50 though it is compiled just fine

8:01 Bronsa: is there a known issue with leiningen 2.5.0 wrt dynamic linking or jvm options?

8:01 Bronsa: no idea

8:05 clgv: there's not a single invokeStatic in the whole target/classes folder :(

8:14 Bronsa: clgv: I'm using lein 2.5.3 and it works fine

8:14 I really don't see why lein would affect DL though

8:15 clgv: me neither, I should just set the JVM options and then it is supposed to work

8:16 Bronsa: are you sure you're using 1.8?

8:17 clgv: yes, according to lein with-profile 1.8-DL deps :tree

8:25 Bronsa: a simple dummy project without profiles worked

8:27 ok, the :jvm-opts in the profile seem to be the problem

8:36 noncom: did anyone use Pallet for shell scripting in Clojure? http://palletops.com/pallet/doc/reference/script/

8:39 clgv: noncom: yes some small remote startup scripts

8:39 noncom: clgv: did you find it really useful?

8:40 i mean, it does not look like it allows using {}s easily..

8:40 just does some very rough and primitive clj->bash translation?

8:41 clgv: I just needed bash scripts so it was good for that job

8:41 I am not sure what you mean with "allows using {}s easily."

8:42 noncom: clgv: well, if i would like to use the capabilities of {}s for data manipulation, that won't work since there are no analogous bash concepts

8:43 clgv: "{}s" = shortcut for clojure maps?

8:45 ARM9: {} is an empty map

8:45 clgv: ARM9: sure, I was trying to find out what it meant for noncom in his description of bash tasks

8:46 noncom: clgv: oh, yes, sorry, i meant exactly maps, right

8:46 i just find that in clojurespeak, typing {}, [] or () or {:kw [] ..} is a good way to describe data structs

8:47 clgv: noncom: yeah, in bash you get just streams that you can pipe through different programs

8:49 "^doubles" is not resolved anymore in Clojure 1.8?

8:49 previously it could be used to tag arrays to avoid reflection

8:53 What is the correct way to type hint double arrays now?

8:53 ,(type (double-array 0))

8:53 clojurebot: [D

8:53 clgv: that thing^^?

8:54 justin_smith: clgv: ^"[D" should work, but ^doubles should too

8:56 clgv: I have https://www.refheap.com/112483 which worked <= 1.6, and it had to be a string since there was a compiler error otherwise

8:58 justin_smith: clgv: I had no idea hints on let bindings would be on the symbol rather than the value

9:00 DEA7TH: Is there a function which would transform [1 1 3 1 3 1] into [[1 1] [1] [1]], treating each 3 as a separator like a string split?

9:01 clgv: ,(->> [1 1 3 1 3 1] (split-with #{3}) (remove #{3}))

9:01 clojurebot: (() (1 1 3 1 3 ...))

9:01 clgv: ups

9:02 DEA7TH: ok so no. gotta write that yourself

9:02 justin_smith: clgv: `(let [a# ^doubles ~a] ...) appears to work with reflection warnings turned on I see no warning

9:03 clgv: justin_smith: there were error cases with that one

9:03 jeaye: DEA7TH: You can do that with a single reduce.

9:03 clgv: justin_smith: the metadata might get lost for macros (and inline fns?)

9:03 justin_smith: clgv: I got an error case with [^doubles a# ~a] but not with [a# ^doubles ~a]

9:04 clgv: justin_smith: which?

9:04 justin_smith: CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: clojure.core/doubles, compiling:(/tmp/form-init4469662376927938804.clj:1:1)

9:04 jeaye: DEA7TH: In each call to the reduce fn, conj onto the last vector; when you hit a 3, conj a new vector on

9:04 clgv: that it can not resolve clojure.core/doubles to a type?

9:04 DEA7TH: eh, I used str/split. it was actually a string, but I preferred to use partial rather than a lambda

9:05 clgv: justin_smith: yeah that's pretty strange that it works in functions but not in macros. but it is totally fine to type hint the binding name

9:05 DEA7TH: str/split's middle argument is the data, not sure why.

9:07 ridcully_: ,(remove (partial = '(3)) (partition-by #{3} [1 1 3 1 3 1]))

9:07 justin_smith: clgv: my version works inline and inside macros

9:07 clojurebot: ((1 1) (1) (1))

9:08 clgv: justin_smith: call it with a macro in argument position or an inline fn

9:10 justin_smith: the stupid thing is that I only get that error when AOT compiling

9:10 on repl it just compiles fine

9:17 DEA7TH: is there something like ctrl-o which works in the REPL? I have to retype 10 lines of code and I'd rather not do (uparrow 10 times + enter) 10 times

9:18 ridcully_: DEA7TH: clojure-rlwrap: aliased to rlwrap -m -M .clj

9:19 DEA7TH: CTRL-^ then open your $VISUAL

9:23 * Chitoge slaps ChanServ around a bit with a large fishbot

9:23 * Chitoge slaps 5EXAAAWDW around a bit with a large fishbot

9:23 * Chitoge slaps `backtick` around a bit with a large fishbot

9:23 * Chitoge slaps `brian around a bit with a large fishbot

9:23 * Chitoge slaps a4j around a bit with a large fishbot

9:23 * Chitoge slaps aaron7 around a bit with a large fishbot

9:24 clgv: DEA7TH: better use some sane dev env with editor-repl-integration

10:05 Bronsa: clgv: (fn [a] (let [^doubles x a] (aset x 1 1.0))) works with no reflection warnings for me

10:06 clgv: Bronsa: sure, (defn ^doubles f [...] ...) caused an error when AOT compiling via leiningen, but not in REPL

10:06 Bronsa: clgv: that's wrong

10:06 metadata on var names is evaluated

10:07 doubles is resolved to the clojure.core/doubles function

10:07 clgv: Bronsa: but (defn f ^doubles [...] ...) does not work either

10:07 Bronsa: it should

10:07 I just tried, it works

10:07 clgv: Bronsa: I tried and got reflection warnings anyway. pre 1.8 the var was the place where the metadata was used to avoid reflection

10:08 Bronsa: (defn f ^doubles [] (double-array 10)) (aset (f) 0 1.0)

10:08 works w/ no refelction warnings

10:08 clgv: no, that never worked

10:09 clgv: it's always been the case that you can type hint on both the var name and the argvec

10:09 they have different semantics

10:09 type hints on arg name are evaluated, on the argvec are not

10:09 so (defn foo ^doubles [] ..) ~= (defn ^{:tag 'doubles} foo [] ..)

10:09 clgv: Bronsa: ok, maybe stale definition then... I tried all possibilities there..

10:10 Bronsa: so is it now possible to only tag types on the arg vec?

10:10 Bronsa: no, you can do both, depending on the type hint

10:10 clgv: THat did only work for primitives up to clojure 1.6

10:11 Bronsa: it always worked for every type hint, with some caveats

10:11 clgv: Bronsa: yeah, the caveats were what made me say it didnt work

10:11 Bronsa: so now I can establish the convention of only tagging the argvec in my projects?

10:11 Bronsa: yeah, those have been fixed in 1.8

10:11 clgv: yes

10:11 clgv: great :)

10:11 Bronsa: I would suggest that

10:13 it has the additional benefit of throwing an exception when you use invalid type hints aswell (some are calling that a bug :( http://dev.clojure.org/jira/browse/CLJ-1863)

10:14 rhg135: A npe...

10:15 clgv: Bronsa: well, let's switch that to a more informative exception ;)

10:16 so let's see whether there is an improvement through direct linking

10:21 Bronsa: rhg135: clgv: you try to convince clojure/core that type-hinting validation is reasonable and I'll be more than willing to fix that :) I've been starting that same discussion multiple times for over 3 years now and they just seem not to care

10:22 so a NPE at compile time to me is still an improvement over silently ignoring type hints & maybe throwing at callsite

10:25 rhg135: The worrying part is that it could throw at runtime

10:25 clgv: Bronsa: read at least one of the discussions on the ML ;)

10:26 rhg135: But then again if you need the type hint to not blow up, then you need more help

10:34 jonathanj: hrm, how can i turn an Enumeration<String> into a Clojure object that is readable using (println)?

10:49 rhg135: seq

10:49 Maybe

10:54 jonathanj: (enumeration-seq) appears to have worked

11:07 class "org.bouncycastle.asn1.ASN1Object"'s signer information does not match signer information of other classes in the same package

11:07 how on earth do i resolve this type of error?

11:21 nevermind, figured it out with the help of `lein deps :tree`

11:22 is there something like (for) that would produce a map instead?

11:22 i could do (into {} (for ...)) but i was wondering if there was something more direct

11:25 j-pb: (into {} is the idiomatic way to create maps from pairs :)

11:26 if you have a keysequence and a value sequence you can combine them into a map with zipmap

11:26 clgv: hmm no real difference between 1.8 and 1.8 with direct-linking on this benchmark

11:27 approx 5% improvement from 1.7

11:27 rhg135: Hey, that means non direct is pretty fast

11:29 clgv: ok, since I needed that code as fast as possible on 1.6 this likely means that I found all hotspots where inline functions were worth it ;)

11:29 rhg135: Indeed

11:30 clgv: so this results is probably not that representative

11:30 rhg135: Maybe it's meant for less hand optimized code

11:30 clgv: definitely

11:30 since the JVM can inline if it detects that as beneficial

11:32 rhg135: The clojure compiler doesn't optimize much I think

11:32 But the jvm is good at it

14:39 Stalkr_: Hi, I wish to explore some Clojure as I have heard a lot of good stuff about it. I am wondering though, I am just creating a very simple "Hello, World" server using Compojure, how come it eats over 100mb of RAM just for that? Is that just how it is with Clojure?

14:44 justin_smith: Stalkr_: yes, you can't run clojure code without loading the whole language and compiler into your runtime

14:45 Stalkr_: which is bad if you are worried about RAM usage, but in practice we tend to use it for things that start up once, stay running for months at a time, and we just live with the inflated memory usage.

14:47 Stalkr_: justin_smith: I see, I'm only worried about having 512mb RAM on a cheap DigitalOcean host but I assume that means it takes more to reach 200mb or more RAM usage then

14:53 justin_smith: yeah, most of that usage is just from loading clojure itself - unlike most languages there is no way to run clojure without loading the full language (though there are experiments to do otherwise)

14:54 Stalkr_: if heap usage is a big concern, you could also check out clojurescript under node.js

14:54 Stalkr_: justin_smith: I come from mainly JavaScript, so ClojureScript interests me too

14:54 but I suspect CS will be a pretty big change from JS too

14:54 justin_smith: Stalkr_: one bonus is all of js is accessible very easily from interop

14:55 which can be a crutch, but also eases things

14:56 Stalkr_: justin_smith: I could run Express with ClojureScript through interop if I wanted right? I am not sure if Clojure or ClojureScript seems most appealing to me

15:30 juanjo_: hi, can you help me with luminus?

15:30 i have created a demo app with h2

15:30 jonathanj: is anyone here familiar with <https://github.com/stuartsierra/component>?

15:30 juanjo_: but id like to use postgresql in heroku

15:31 how should I do it?

15:31 jonathanj: i have a question about composing components

15:31 codefinger: juanjo_: when you generate the luminus app use +postgres

15:32 juanjo_: codefinger: that's the problem, the app is aready generated

15:32 how can I add +postgres now?

15:33 codefinger: juanjo_: hmm, not sure. you could generate a new app and see what's different. but i don't think there is much. mainly the jdbc driver

15:33 s/there is/there is not/

15:33 juanjo_: ok

15:34 codefinger: err no. was right first time :)

15:35 juanjo_: i don't have an app in front of my but i think you'll need to add [postgresql "9.4-1201-jdbc4"] to project.clj

15:37 juanjo_: and because yesql/conman use DATABASE_URL, it will just pick up the right driver for the postgres:// protocol

15:39 mavbozo: jonathanj, what is your question?

15:40 jonathanj: mavbozo: i think i've answered it, just testing some code

15:41 schmir: [org.postgresql/postgresql "9.4-1206-jdbc42"]

15:46 codefinger: schmir: +1 juanjo_ ^^

15:46 juanjo_: thanks

15:46 jonathanj: mavbozo: i'm actually using https://github.com/danielsz/system

15:47 anyway, i'm trying to use this component to define a ring handler: https://github.com/danielsz/system/blob/master/src/system/components/app.clj

15:48 but apparently whatever code i'm running doesn't match that

15:49 (component/using (new-app #'some-ns/my-ring-handler) produces clojure.lang.ArityException: Wrong number of args (1) passed to: app/new-app

15:50 oh, there has been a release since i last looked

15:50 thanks for the rubber duck session, mavbozo :|

15:53 mavbozo: jonathanj, :)

15:58 jonathanj: except now it's still not working, apparently some dependency is nil for reasons i'm unable to explain

16:00 ridcully_: i thought the rubber duck was replaced with the plushy cthulu?

16:02 jonathanj: so (component/using (new-app #'some-ns/my-ring-handler) [:foo]) ends up invoking some-ns/my-ring-handler with nil as the only parameter, that makes no sense to me

16:02 in particular because another component is initialized before with the same component dependency and it's not nil there

16:13 mavbozo: jonathanj, i don't see any component/using usages in danielsz/system readme.

16:15 so, now you use stuartsierra's component directly?

16:18 jonathanj: mavbozo: i'm sure it mentions it, it might be kind of indirect

16:18 anyway, i discovered the issue, the new-app component expects the dependent component to be named "db"

16:23 which seems like a stupid requirement

16:23 justin_smith: Stalkr_: yes, you should be able to use Express with cljs

16:24 Stalkr_: sorry for the delay, just got back from lunch

16:24 Stalkr_: a walkthrough I found http://www.mase.io/code/clojure/node/2015/01/25/clojurescript-and-node-part-2-express/

16:26 Stalkr_: justin_smith: No problemo, I will probably give both a try over a few weeks, since I am interested in front-end too cljs with Om/Reagent or some React-wrapper like those seems very interesting. I'll give the article a look later :-) Does it make most sense to have Clojure on back-end + cljs on front-end or in that case keep it all cljs?

16:29 ridcully_: jonathanj: in component the using part would name the things you want to autowire/inject

16:30 jonathanj: ridcully_: yeah, i mean that the "generic ring app" component in system has the thing named "db"

16:32 justin_smith: Stalkr_: I have not tried cljs on the backend but a friend has in production and says it works well

16:32 Stalkr_: but clojure on the backend is definitely the mainstream choice - it's the "official" version and all

16:33 MJB47: cljs + node works well

16:33 but using normal clojure is easier imo

16:34 but depends what you wanna do

16:34 you obviously dont get threads with cljs

16:34 which you may or may not care about

16:34 Stalkr_: justin_smith: I have tried to search for isomorphic (rendering JavaScript HTML server-side) but I could not find much, only a single article, but was thinking that it made more sense that with cljs to have isomorphic sites. Though I guess it should be possible with Java Nashorn

16:34 MJB47: is threads important when you have core.async?

16:34 MJB47: core.async is just an abstraction

16:34 it doesnt replace threads

16:35 like you can do what core.async does with callbacks

16:35 https://www.youtube.com/watch?v=fICC26GGBpg

16:35 also i recommend this

16:35 Stalkr_: I know, not saying it does but I mean it's the best we got for async programming with cljs right?

16:35 MJB47: which goes into some depth about server side rendering

16:35 arguably yes it is

16:36 but if your project would like to have proper concurrency, i would not recommend node

16:36 justin_smith: Stalkr_: yeah, you might find something on pre-rendering reagent or om components via nashorn or node

16:36 Stalkr_: Ahh cool, I'll give it a watch, I have seen some cool stuff with Clojure(Script), like Figwheel but I still feel like it's a very different world from JS

16:37 ridcully_: jonathanj: i don't know system. i just added this, because component injects by the name _you_ give it in your record. so maybe the same with that other thingy

16:37 jonathanj: if this just adds to the confusion... sorry ;P

16:37 Stalkr_: MJB47: I am not sure when I would require that, but in any case, I could have one Node server for rendering, another pure Clojure for heavy tasks that requires proper concurrency right?

16:37 MJB47: you could yes

16:38 Stalkr_: Of course that is more expensive for the machine than a single Clojure + front-end cljs

16:38 MJB47: but you have to think about the complexity that would involve

16:38 ultimately that might be the set up that suits you best

16:38 or it might not

16:38 who knows

16:38 gfredericks: tcrawley: ping

16:39 Stalkr_: Yeah I don't have any particular reasons for using Clojure yet so that's hard to say, that will definitely be something I will have to think about some day when doing a real project

16:39 tcrawley: gfredericks: what up, dog?

16:39 gfredericks: tcrawley: are you familiar with the general idea of how component works?

16:39 Stalkr_: but for now I will explore Clojure(Script) some more, see how it fits with me

16:40 tcrawley: I feel like that's a trick question, but I'll respond with a tentative yes

16:40 gfredericks: tcrawley: okay so I'm using immutant and component at the same time

16:41 which so far has been fine but now I want an http server too

16:41 and don't know enough about how immutant works to be able to tell if that is even possible

16:41 the big question I think is whether I can start/stop the web server myself, or if it has to be registered w/ the deploy somehow such that I don't have control over it

16:42 (this works fine with jetty instead of immutant, since you can just call start-jetty and get a server object that you can later stop)

16:43 tcrawley: gfredericks: see if https://github.com/danielsz/system/commit/1bdc182022bdbd79129d4f75bf770613b60a6499 is helpful

16:44 gfredericks: tcrawley: I bet so; okay thanks man thanks

16:44 tcrawley: you can pass the return value of immutant.web/run to immutant.web/stop, which is what ^ does

16:44 my pleasure!

16:46 gfredericks: tcrawley: wait wait what if I'm using immutant 1.1.4?

16:46 tcrawley: oh dear

16:47 gfredericks: I'm so sorry

16:47 tcrawley: in that case, you're kindof in a pickle

16:47 gfredericks: tcrawley: okay maybe my real question is about upgrading then -- do I have to upgrade other apps deployed to the same server in synchrony?

16:48 tcrawley: wait, you should be able to do something similar in 1.1.4 though, let me look

16:48 gfredericks: immutant.web/start doesn't say what it returns

16:48 tcrawley: if you want to upgrade, then you have to upgrade the container itself to WildFly, or move the apps out to run as uberjars

16:49 you can't run an Immutant 2.x app inside the Immutant 1.x container

16:49 gfredericks: roger

16:50 tcrawley: you can do (immutant.web/start "/" handler) (immutant.web/stop "/")

16:50 or (immutant.web/start handler) (immutant.web/stop), and "/" will be assumed in both casees

16:51 gfredericks: tcrawley: okay I will try that thanks Señor crawley

16:51 tcrawley: my pleasure! I'm always here for you

16:51 gfredericks: you are!

16:52 ~tcrawley is always here for me

16:52 clojurebot: 'Sea, mhuise.

16:53 jcrossley3: gfredericks: one other thing, if it matters: there is an undocumented option, :auto-start, that can be set to false in order to create a server without actually starting it, after which you can (.start s) or (.stop s) it. that may play nicer with component, depending on what you're doing

16:55 gfredericks: jcrossley3: thanks; I think the main thing that feels weird about it is that it's global rather than OOP; but it amounts to the same thing I think so it's not a big deal

16:55 if you call immutant.web/start twice with the same args will the second one throw?

16:55 jcrossley3: gfredericks: er... :auto-start is for the (server ...) function, not (run ...). that was added for pedestal, iirc

16:57 gfredericks: there is no start, only run or server. i don't think run throws if you restart.

16:57 gfredericks: jcrossley3: there's a start because I'm using a 17-year-old version of immutant

16:58 jcrossley3: gfredericks: you probably need to stop doing that

16:58 gfredericks: jcrossley3: it's hard since there's like seven other apps too

16:59 jcrossley3: gfredericks: SIMPLICITY IS HARD!

17:00 gfredericks: that was the punchline of rich's famous talk "Simplicity Is Hard"

17:00 jcrossley3: gfredericks: fwiw, i would be surprised if start tossed if called twice

17:01 gfredericks: jcrossley3: roger roger ack ack

17:01 Morgawr: This is probably a silly question but what's the most elegant way to obtain the index of an element searched in a vector that fits a given condition?

17:02 like I have a vector of maps with an :id property and I want to get the index of a specific map with a given :id within that vector

17:02 gfredericks: (first (keep-indexed (fn [idx el] (when (pred el) idx)) coll))

17:02 Morgawr: gfredericks: thanks, didn't know about keep-indexed :) cheers

17:16 tcrawley: gfredericks: calling start twice with the same context path should replace the former handler

17:16 gfredericks: tcrawley: the component gods are mildly sad about this

17:16 amalloy: Morgawr: also consider storing a map instead of a list, since you are looking stuff up by id often

17:18 Morgawr: amalloy: that's a good point, I'll keep that in mind. I need to check if I look it up more often than I need it ordered or not :) But yeh, I'll consider it

17:18 MJB47: you could always use a sorted map

17:58 WorldsEndless: What's the clojure equivalent of "import namespace.*"?

17:59 tolstoy: Is it use? (use '[some.lib.core])?

17:59 amalloy: uhhh, it kinda depends whether you mean import or namespace or what. like, you import things, but not namespaces

18:00 WorldsEndless: So, java has import java.util.*;

18:00 That one happens to have a nice clojure wrapper, but for those that don't...

18:01 amalloy: there is no way to import all classes from a package

18:01 WorldsEndless: I suppose that's for the best

18:01 amalloy: yes, whenever you do it in java someone tells you not to

18:01 WorldsEndless: Just makes translating this java code a little trickier...

18:02 dang someone

18:02 can :import use :as the same way :require does?

18:03 amalloy: sadly not

18:03 that is a feature that would be cool, unlike import foo.*

18:03 WorldsEndless: shucks

18:09 tolstoy: WorldsEndless: When porting java, I don't use imports at all. Let the compiler tell me what it can't find. Most of the imports aren't needed.

18:23 WorldsEndless: look what I found:

18:23 (:import [cc.mallet.util.*])

18:24 So apparently you can do the bad stuff

18:25 amalloy: that just like...doesn't do anything

18:25 that import is literally a no-op

18:25 WorldsEndless: Hmm... well, it's in the text book

18:25 amalloy: RIP textbook

18:25 unless something new went into 1.8 i guess. i'm not super up to date

18:28 puredanger: Nope

18:29 amalloy: thanks puredanger, i just confirmed it myself by looking at the source too

18:29 WorldsEndless: confirmed. who wrote this cargo-culting textbook?

18:29 WorldsEndless: Let's see... "Mastering Clojure Data Analysis" by Eric Rochester

18:30 cargo-culting?

18:31 amalloy: mmm. i haven't heard of eric rochester, and the book seems to be about data analysis, not about clojure. so like, he's obviously wrong, but that's not totally unexpected given the focus of the book, nor really a huge condemnation of the book either. if it were a book about clojure it'd be a bigger issue

18:31 https://en.wikipedia.org/wiki/Cargo_cult#Metaphorical_uses_of_the_term

18:32 WorldsEndless: That's a great idiom. I'm gonna use it, so I look smart like you guys.

18:33 :|

18:34 Seriously, though, that's a great term.

18:35 justin_smith: somewhere there are polynesian devs that are like "yeah, my grandpa was in a cargo cult, and now I cargo cult in my code, what about it?"

18:39 Pupeno: What’s the best way to have one or more example programs that exercise my library in my library’s project? Should they be full leiningen projects on their own?

18:40 WorldsEndless: Pupeno: I'd try to make them as tests

18:40 Pupeno: WorldsEndless: I don't want tests, this is on top of tests.

18:41 WorldsEndless: In that case, making seperate lein projects is what I often see on Github, with a readme in the primary project that links to them

18:53 Takeiji: ls

19:19 didibus: I've asked this before, but what's the Clojure syntax for destructuring inside nested maps when using :keys ?

19:20 ,{:first "John" :last "Doe" :parents {:mother "Alicia" :father "George"}}

19:20 clojurebot: {:first "John", :last "Doe", :parents {:mother "Alicia", :father "George"}}

19:20 didibus: ,(let [{:keys [parents]}]

19:20 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

19:21 didibus: , (let [{:keys [parents]} {:first "John", :last "Doe", :parents {:mother "Alicia", :father "George"}}] parents)

19:21 clojurebot: {:mother "Alicia", :father "George"}

19:21 didibus: Now say I wanted mother and father too?

19:32 justin_smith: , (let [{:keys [parents] {:keys [mother father]} :parents} {:first "John", :last "Doe", :parents {:mother "Alicia", :father "George"}}] [parents mother father])

19:32 clojurebot: [{:mother "Alicia", :father "George"} "Alicia" "George"]

19:33 justin_smith: also, it might be clearer not to do keys when you have nesting

19:34 , (let [{{:keys [mother father] :as parents} :parents} {:first "John", :last "Doe", :parents {:mother "Alicia", :father "George"}}] [parents mother father])

19:34 clojurebot: [{:mother "Alicia", :father "George"} "Alicia" "George"]

19:34 justin_smith: , (let [{{mother :mother father :father :as parents} :parents} {:first "John", :last "Doe", :parents {:mother "Alicia", :father "George"}}] [parents mother father]) ; there's also doing away with :keys altogether

19:34 clojurebot: [{:mother "Alicia", :father "George"} "Alicia" "George"]

19:35 justin_smith: I think that version is a little easier to puzzle out (though :keys is convienient)

19:54 kenrestivo: what are some sane/reasonable ways to pass settings from a clojure app to a clojurescript app?

19:55 i.e. i have src/foo.clj , i also have src-cljs/foo.cljs. it's not so much state that i want to share, as global settings. i can't use the network to pass the state because it involves setting up the network

19:56 and project.clj is not the place for it, since i don't want these in git. i'm using schema and component to load settings from an edn file

19:56 amalloy: fwiw i think the :keys version is more readable than manual map destructuring

19:57 justin_smith: ^ i have to read the manual map destructuring carefully because it being manual implies it's doing something more sophisticated than :keys

19:58 didibus: Wow, nice, so many different ways.

20:00 kenrestivo: yeah, :keys is fantastic. i'm addicted to it.

20:01 makes it very clear when reading code, what things are passed in as parameters and where they come from

20:02 and speaking of passing parameters...

20:02 the current nasty hack i'm using is a moustache template with "var settings = {{{settings}}}" in the clj ring handler, and then reading that on the cljs side.

20:03 (defonce state (atom {:settings (js->clj js/settings)}) etc. i hate this.

20:19 LuminousMonkey: Hey #clojure, sorry, I've got a question and my google-fu is failing. When it comes to lein deps, and specifying versions, is there a best practice? For example, I write a library that can be used with Clojure 1.6 or 1.7, etc. In the project deps do I specify a range, or just the latest version?

20:22 rhg135: I'd just go for the latest. If people want to use old versions, they can read the readme

20:26 LuminousMonkey: I thought so, I've never noticed any problems, but I have had lein deps :tree give exculsion suggestions. I thought it might just a suggested way to stop my libraries causing that, even though I have noticed problems. Ta.

20:26 *haven't

20:31 amalloy: ranges cause more problems than you can possibly imagine, despite seeming like good ideas on the surface

20:36 LuminousMonkey: So, basically just the highest version for all your deps at the time?

20:36 TEttinger: highest version you've tested with

20:37 LuminousMonkey: Cool.

20:37 Ta.

20:56 didibus: Is there a function that sorts a nested map structure recursively in alphabetical order?

20:57 xeqi: is there a function that turns a channel into a lazyseq?

21:01 kenrestivo: a transducer might

21:01 TimMc: didibus: Not a single function, no, but there are tree walk fns + sorted-map-by

21:04 didibus: Ok, I'll look into the walk functions

21:21 TimMc: didibus: clojure.walk/postwalk seems to be the thing to use

21:39 dongcarl: Hi guys, can anyone explain to me what #(or %2 %1) does in (merge-with #(or %2 %1) state new-data)?

21:39 justin_smith: it's the same as (merge state new-data)

21:40 ,'#(or %2 %1)

21:40 clojurebot: (fn* [p1__26# p2__25#] (or p2__25# p1__26#))

21:40 justin_smith: wait, not the same because the new-data could have false or nil

21:40 right,

21:41 dongcarl: so... #(or %2 %1) is like syntactic sugar for a lambda?

21:42 justin_smith: ,'#()

21:42 clojurebot: (fn* [] ())

21:42 justin_smith: in general #(...) is syntactic sugar for a lambda, yeah

21:42 dongcarl: justin_smith: thanks!

21:43 justin_smith: one gotcha with #() is that it doesn't nest - because it would be impossible to specify the args

21:43 TEttinger: or will short-circuit evaluate in that case and, if the second argument given to the lambda is true, will return that without ever evaluating the first arg (I think)

21:43 pretty sure that's the reason for %2 and then %1 after it

21:44 ,(merge-with #(or %2 %1) {:a 1 :c 3} {:a 10 :b 20})

21:44 justin_smith: TEttinger: the second item is already fully realized before the or sees it

21:44 clojurebot: {:a 10, :c 3, :b 20}

21:45 TEttinger: ah, so it's just to prefer the second arg then

21:45 justin_smith: right, which is the normal merge behavior

21:45 except special case for nil or false

21:45 ,(merge-with #(or %2 %1) {:a 0 :b 1} {:a nil :b 2})

21:45 clojurebot: {:a 0, :b 2}

21:45 TEttinger: (I mean why %2 is before %1, which is normally a little odd)

21:45 dongcarl: justin_smith: what happens in those cases? how is it different?

21:45 justin_smith: ,(merge {:a 0 :b 1} {:a nil :b 2})

21:46 clojurebot: {:a nil, :b 2}

21:46 dongcarl: justin_smith: ah!

21:46 justin_smith: in the merge case, the nil is newer, so it replaces the original

21:46 TEttinger: interesting

21:46 where's you see this code, dongcarl?

21:46 *where did

21:47 I'm a bit curious

21:47 dongcarl: TEttinger: one sec

21:48 TEttinger: https://github.com/shaunlebron/parinfer/blob/master/lib/src/parinfer/reader.cljc#L129

21:48 TEttinger: ah ok thanks

21:48 dongcarl: I'm trying to port this to emacs-lisp for an emacs plugin

21:49 justin_smith: oh, cool

21:50 it would make writing lisps just like writing python or haskell I guess

23:42 kenrestivo: does this new 1.8 socket repl break nrepl?

23:43 justin_smith: it's meant to replace it

23:43 kenrestivo: :(

23:43 justin_smith: I would be surprised if it broke nrepl - it's going to be a better alternative though

23:44 kenrestivo: when I compare clojure startup times, nrepl, lein, and clojure itself are about equal in the time each takes to load - even just an improvement on that front would be great

23:46 kenrestivo: i'm sure it'll be better, i just have to budget time for dealing with all my tooling breaking

23:47 justin_smith: I'm actually not using anything that relies on nrepl at the moment - I use lein repl but only because that's easier than starting up clojure.main

23:48 dongcarl: HI guys can you help me understand what's going on here: https://github.com/shaunlebron/parinfer/blob/master/lib/src/parinfer/reader.cljc#L59

23:50 justin_smith: it takes something like {:ch \)} then returns something different based on whether it's opening, closing, or neither

23:50 puredanger: kenrestivo: no, the socket repl does not break nrepl

23:50 justin_smith: or {:ch \a} - that's easier to read

23:50 puredanger: justin_smith: and no it is not intended to replace it

23:50 justin_smith: puredanger: oh!

23:50 puredanger: they are alternatives

23:50 justin_smith: puredanger: wishful thinking on my part

23:51 dongcarl: justin_smith: so I know that it takes in a state map which has a key :ch, would that work as well?

23:51 justin_smith: dongcarl: the other keys don't matter, it just looks at the :ch key

23:51 and that should have a char

23:51 TEttinger: \a is the syntax for char literal lowercase a

23:51 puredanger: justin_smith: the socket repl is really a socket server + a repl that runs over it. you could also run something that did nrepl framing over the socket server afaik if you wanted to

23:51 TEttinger: what would be 'a' in C or Java

23:52 justin_smith: ,(int \a)

23:52 dongcarl: justin_smith: if it's opening, it calls "

23:52 clojurebot: 97

23:52 dongcarl: (defmethod push-char* :open ...)"?

23:52 justin_smith: it would be 97 in emacs

23:52 puredanger: the provided socket repl is stream-oriented, whereas nrepl is more message-oriented, as far as I understand it

23:53 justin_smith: dongcarl: defmulti defines the dispatch, the defmethods define what it does for different dispatch values

23:57 dongcarl: justin_smith: okay. So let me get this straight. It grabs ch from the :ch key in the input, checks if it's opening, if it is, it'd call (defmethod push-char* :open ...), then check if it's closing, if it is, it'd call (defmethod push-char* :close ...), otherwise, it calls a (defmethod push-char* ch ...), and if there are no defmethods with ch, then it calls (defmethod push-char* :default ...)?

23:57 justin_smith: dongcarl: no, it can only call one of the dispatch values

23:58 it either calls the method for :open, :close, or the char itself - though it's clearly poorly named, because looking at the methods defined, it is dispatching on string not char

23:58 dongcarl: justin_smith: okay so it's what I said but if one of the defmethods are called, the other ones aren't called? like an ifelse?

23:59 owlbird: how to write a fun just return its arguments? I tried eval like this (if (nil? style) #(eval %) #(:node %)), which seems very slow.

23:59 justin_smith: dongcarl: right, first the dispatch in the defmulti is called, and based on that, one of the dispatch values is called

Logging service provided by n01se.net