#clojure log - Sep 10 2015

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

0:12 simon1234: Hi there! I have a problem with using get-method. I defined a multimethod with (defmulti describe (fn [a b] [(foo a) b])) ; and a matching describe: (defmethod describe [:blue :oneline] )

0:13 It works fine, but I can't use get-method. (get-method describe [:blue :oneline]) won't work even if (describe :blue :oneline) will

0:13 (and I can't say: (get-method describe :blue :oneline)

0:13 Any input would be great, thanks!

0:14 justin_smith: simon1234: your multimethod takes two args

0:14 is that intentional?

0:14 simon1234: justin_smith: yes

0:14 justin_smith: to define both the entity to describe and the level of information you want to get out

0:16 I know I could do (defmulti describe (fn [a & args] a) and then have a case in a defmethod. But I decided to go this way for now. I'm just wondering if I can use get-method with this kind of implementation

0:17 justin_smith: simon1234: sorry for being slow, I realize what you are getting at now

0:17 simon1234: justin_smith: ahah, not a problem at all! thanks for the help!

0:17 justin_smith: my approach has been to use a varargs dispatch, yeah, but it is clumsy

0:19 simon1234: clearly get-method should have the semantics of apply (or else accept varargs and use apply to call the dispatch function internally)

0:21 simon1234: justin_smith: oh sorry i'm stupid...

0:22 justin_smith: ?

0:22 devn: (he's not stupid)

0:22 :D

0:22 simon1234: it works in fact, I need to call it this way: (get-method describe [(foo :blue) :oneline])

0:22 not (get-method describe [:blue :oneline])

0:22 (I was thinking that the multimethod function would get applied

0:22 justin_smith: simon1234: oh you call it with the result of your dispatch

0:22 simon1234: before trying to see what function would fit for the dispatch

0:22 justin_smith: not the input to your dispatch?

0:23 now it makes sense

0:23 simon1234: I used to call it with the input, I have to apply the dispatch-fn function to it

0:23 justin_smith: well sorry to have wasted your time and thanks a lot for your help

0:23 justin_smith: oh no, I learned (or at least was reminded of) something

0:24 simon1234: Well, no a complete waste then, cool ;)

0:24 s/no/not

0:26 devn: i know "there be dragons," but anyone have thoughts on the best way to go about exposing the contents of __extmap on a defrecord as if they had been defined on the record in the first place?

0:26 simon1234: You can get the internal dispatch fn using: (.dispatchFn core/describe*)

0:26 devn: (namely, so code you don't control won't need to know anything special)

0:27 simon1234: (.dispatchFn <your multimethod>)

0:28 amalloy: devn: huh? (a) what would it mean to expose it "as if" it had been defined on the record, and (b) what good would it do?

0:30 devn: allow someone interacting with the record to use (.-foo rec) even though foo was not in the definition of the record

0:31 but was instead assoc'd on sometime later

0:31 amalloy: ^

0:32 amalloy: why would you do that? if you're interacting with some unknown record, just use (:foo rec) for all fields, instead of (.-foo rec)

0:32 it would pollute the definition of .- a lot, if it looked up things which aren't java fields

0:33 devn: because code that i do not control currently only accesses fields via `.-foo`

0:33 amalloy: aye, im not saying i'd use it, necessarily, just interested in the problem

0:34 justin_smith: devn: how about using reify to create an object with the fields you want the consumer to see?

0:34 amalloy: you can't make fields with reify

0:34 devn: ^

0:34 amalloy: what code do you imagine someone writing that interacts with the fields of an unknown object?

0:38 (and how could you meaningfully participate in that?)

0:38 they wouldn't write it in java, because that's super hard to do; they wouldn't write it in clojure, because keywords are better and easier anyway

0:47 devn: im either failing to convey the situation, or i'm looking for light at the bottom of a well, but

0:48 but in clara, you use a macro `defrule`, and on the left hand side of the rule, you bind things like `(= ?foo foo)`, where `foo` refers to the field on the record.

0:49 and now that i write that, i realize that i haven't yet tried to use :foo instead of foo yet in one of those definitions

1:09 amalloy_: namely it's this bit:

1:10 ,(defrecord FooBar [a])

1:10 clojurebot: sandbox.FooBar

1:11 devn: ,,(clojure.lang.Reflector/invokeStaticMethod ^Class FooBar "getBasis" ^"[Ljava.lang.Object;" (make-array Object 0))

1:11 clojurebot: [a]

1:11 devn: (i think)

1:59 amalloy: so, that doesn't actually interact with any fields on a record, devn

1:59 it takes a class, and returns a seq of symbols

2:32 devn: amalloy: yeah, thank you, that makes sense

2:32 i can actually destructure just like it's a map

3:23 doctorinserenity: Does anyone know whether I can use lein-oneoff REPLs integrated with Emacs?

3:37 luxbock: doctorinserenity: it should work if you use `cider-connect`, but I haven't tried it

3:40 Olajyd: Hi TEttinger :)

3:41 TEttinger: hello Olajyd!

3:44 doctorinserenity: luxbock: thanks i'll give that a go!

3:44 Olajyd: I was trying out something (reduce #(if (pos? (compare %1 %2)) %1 %2) [["Coke" "16" ""]["Coke" "2" "3"] ["Coke" "" "36"]["Coke" "35" "3"]]) how can we compare based on the second column value

3:47 TEttinger: Olajyd, so this is a string comparison, right?

3:47 ,(> "12" "9")

3:47 Olajyd: can we try this use case: [[“Coke" "16" ""]["Coke" "2" "3"] [“Pepsi” "" "36"]["Coke" "35" "3"]] so instead of ;=> [“Pepsi” "" "36"] we’ll get ;=> ["Coke" "35" "3"]

3:47 clojurebot: #error {\n :cause "java.lang.String cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers gt "Numbers.java" 229]}]\n :trace\n [[clojure.lang.Numbers gt "Numbers.java" 229]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" -1]\n [...

3:47 TEttinger: ,(compare "12" "9")

3:47 clojurebot: -8

3:47 Olajyd: TEttinger, yeaa

3:49 ,(reduce #(if (pos? (compare %1 %2)) %1 %2) [["Coke" "16" ""]["Coke" "2" "3"] ["Coke" "" "36"]["Coke" "35" "3"]])

3:49 clojurebot: ["Coke" "35" "3"]

3:50 TEttinger: I'm not sure why that works. I think comparing vector to vector will be just based on the length of the vector

3:50 ,(compare ["" "" "" ""] ["" "" ""])

3:50 clojurebot: 1

3:51 Olajyd: I think the default is for every first element, then if its the same it moves to the second element..my assumption though

3:51 TEttinger: ,(reduce #(do (print (pos? (compare %1 %2))) %2) [["Coke" "16" ""]["Coke" "2" "3"] ["Coke" "" "36"]["Coke" "35" "3"]])

3:51 clojurebot: falsetruefalse["Coke" "35" "3"]

3:52 TEttinger: it seems like this should be a sorting thing, not sure

3:53 ,(reduce #(if (pos? (compare (second %1) (second %2))) %1 %2) [["Coke" "16" ""]["Coke" "2" "3"] ["Coke" "" "36"]["Coke" "35" "3"]])

3:53 clojurebot: ["Coke" "35" "3"]

3:53 TEttinger: let's try a different collection

3:53 ,(reduce #(if (pos? (compare (second %1) (second %2))) %1 %2) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

3:53 clojurebot: ["Coke" "35" "3"]

3:53 TEttinger: and with the original...

3:54 ,(reduce #(if (pos? (compare %1 %2)) %1 %2) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

3:54 clojurebot: ["Pepsi" "" ""]

3:54 Olajyd: ok

3:55 TEttinger: I think the comparison with vectors is... not predictable unless you have a single item to compare with

3:55 or rather, it is predictable, I just don't know what makes it do what it does

3:56 Olajyd: lol

3:56 TEttinger: there's also sort-by which may be what you want

3:56 (doc sort-by)

3:56 clojurebot: "([keyfn coll] [keyfn comp coll]); Returns a sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item). If no comparator is supplied, uses compare. comparator must implement java.util.Comparator. If coll is a Java array, it will be modified. To avoid this, sort a copy of the array."

3:57 TEttinger: ,(sort-by second [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

3:57 clojurebot: (["Pepsi" "" ""] ["Coke" "" "36"] ["Coke" "16" ""] ["Coke" "2" "3"] ["Coke" "35" "3"])

3:57 TEttinger: yep, sorted character by character in the string

3:58 empty strings are lowest, strings starting with "1" are lower than ones starting with "2"...

3:59 ,(sort-by #(Integer/parseInt (str "0" (second %)) 10) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

3:59 clojurebot: (["Pepsi" "" ""] ["Coke" "" "36"] ["Coke" "2" "3"] ["Coke" "16" ""] ["Coke" "35" "3"])

3:59 TEttinger: that gets the 16 after the 2, which may be desired

4:00 Olajyd: (reduce (fn [x y] (let [a (get x col) b (get y col)] (if (pos? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]]) I also tried this to though

4:00 ,(reduce (fn [x y] (let [a (get x col) b (get y col)] (if (pos? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

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

4:01 Olajyd: ,(reduce (fn [x y] (let [a (get x 1) b (get y1)] (if (pos? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

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

4:01 Olajyd: ,(reduce (fn [x y] (let [a (get x 1) b (get y 1)] (if (pos? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

4:01 clojurebot: ["Coke" "35" "3"]

4:02 TEttinger: yep, that's pretty much the same as mine. (get x 1) and (second x) are very very similar but get would also work for hash-maps and supports an extra arg as a fallback if x has less than 2 elements

4:03 so what's the intended output?

4:03 that looks like the largest thing in the second column

4:04 Olajyd: TEttinger, yep

4:05 How about getting the minimum

4:06 TEttinger: ,(reduce (fn [x y] (let [a (get x 1) b (get y 1)] (if (neg? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]["Pepsi" "" ""]["Coke" "" "36"]])

4:06 clojurebot: ["Coke" "" "36"]

4:06 TEttinger: there's two choices there

4:06 I just changed pos? to neg?

4:06 Olajyd: oh

4:06 nice

4:07 TEttinger: if using sorted stuff, you can get first or last

4:07 Olajyd: ,(reduce (fn [x y] (let [a (get x 1) b (get y 1)] (if (neg? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]])

4:07 clojurebot: ["Coke" "16" ""]

4:08 TEttinger: yep, lowest starting character

4:08 Olajyd: TEttinger, did you notice something the min is suppose to be ["Coke" "2" "3"] but its giving ["Coke" "16" ""]

4:09 ,(reduce (fn [x y] (let [a (get x 1) b (get y 1)] (if (neg? (compare a b)) x y))) [["Coke" "16" ""]["Coke" "35" "3"]["Coke" "2" "3"]])

4:09 TEttinger: ah, that's the thing I was trying to say

4:09 clojurebot: ["Coke" "16" ""]

4:09 Olajyd: oh ok

4:09 TEttinger: comparing strings compares the charactrs

4:09 Olajyd: hmmm

4:09 TEttinger: ,(map int "12")

4:09 clojurebot: (49 50)

4:10 TEttinger: so each char has a number, sometimes called a codepoint, that is how it is stored. you can do...

4:10 (map char [49 50])

4:10 ,(map char [49 50])

4:10 clojurebot: (\1 \2)

4:11 TEttinger: so that "16" and "2" are getting compared with their first chars first, and "16" has 49 first, "2" has 50 first

4:11 Olajyd: ok

4:12 TEttinger, gotcha :)

4:12 TEttinger: so even though "16" is a longer string and a bigger number if you are reading off what it means, the 2 goes first because of that character being later in the order

4:13 ,(map #(Integer/parseInt (str "0" (second %))) ["16" "2" "" "0"])

4:13 clojurebot: (6 0 0 0)

4:13 TEttinger: agh

4:13 Olajyd: So we use the sorting right?

4:13 TEttinger: ,(map #(Integer/parseInt (str "0" %)) ["16" "2" "" "0"])

4:13 clojurebot: (16 2 0 0)

4:13 TEttinger: ,(map #(Integer/parseInt (str "0" %)) ["16" "2" "" "0" "99"])

4:13 clojurebot: (16 2 0 0 99)

4:13 TEttinger: don't need to sort

4:14 your way works fine, but you should do some processing like with the fn I just used on the string-ified numbers

4:14 ,(Integer/parseInt "")

4:14 clojurebot: #error {\n :cause "For input string: \"\""\n :via\n [{:type java.lang.NumberFormatException\n :message "For input string: \"\""\n :at [java.lang.NumberFormatException forInputString "NumberFormatException.java" 65]}]\n :trace\n [[java.lang.NumberFormatException forInputString "NumberFormatException.java" 65]\n [java.lang.Integer parseInt "Integer.java" 504]\n [java.lang.Integer parseInt "Int...

4:14 TEttinger: that's why I add a "0" before the string

4:20 bracki: What's the clojure equivalent of .setFoo(double... foos)?

4:21 (into-array Double '(1 2 3 4))

4:21 ,(into-array Double '(1 2 3 4))

4:21 clojurebot: #error {\n :cause "array element type mismatch"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "array element type mismatch"\n :at [java.lang.reflect.Array set "Array.java" -2]}]\n :trace\n [[java.lang.reflect.Array set "Array.java" -2]\n [clojure.lang.RT seqToTypedArray "RT.java" 1726]\n [clojure.core$into_array invokeStatic "core.clj" 3324]\n [clojure.core$into_array invok...

4:21 bracki: doesn't work

4:24 amalloy: TEttinger, Olajyd: (doc min-key)

4:26 also, vectors compare first by length and then lexicographically

4:26 TEttinger: (inc amalloy)

4:26 lazybot: ⇒ 304

5:15 bracki: ,(into-array Double/TYPE '(1 2 3 4))

5:15 clojurebot: #object["[D" 0x7738ca7d "[D@7738ca7d"]

5:22 TEttinger: ,(double-array '(1 2 3 4))

5:22 clojurebot: #object["[D" 0x7b8d2062 "[D@7b8d2062"]

5:23 noncom: there is clj-slack, an RPC library, does anyone have any thoughts, is it useable to organize a network of agents?

5:24 i presume heartbeat messages in 1 second interval, some RPC calls and occasional continous transfer of text data

5:24 up to 2-3 Mb in 10-20 minutes

5:25 just wondering, maybe someone has some experience with clj-slack

5:27 ashnur: anyone using spacemacs_

5:27 ?

5:28 i am trying to find a suitable replacement for paredit, because this evil-lisp-state thing it has by default doesn't even have documentation

5:29 noncom: ashnur: why don't you just install paredit?

5:29 ashnur: noncom: it has issues with spacemacs, hard to rebind the keys, or so I read

5:30 noncom: heh... well, if the only problem is the keys, i would just somehow try to fix it. because you want functionality of paredit, but the only problem are the keys. why would any other analog of paredit with same functionality have no problems with keys then

5:31 mobius-eng: smartparens

5:31 lispy

5:32 paredit binds the keys in such a way, it's impossible to rebind them

5:32 noncom: ah

5:33 ashnur: thx, checking those

5:34 i saw the names before, but because i am just starting with clojure (or any lisp), i haven't used anything. from the tutorial i can see it's very useful

5:34 mobius-eng: I'm using smartparens at the moment

5:35 it is a bit of work to setup compared to paredit

5:35 ashnur: are you also using spacemacs or just emacs?

5:35 mobius-eng: just emacs

5:36 AFAIK, spacemacs uses evil

5:37 ashnur: yes

5:37 mobius-eng: Not what would be the best way to bind the keys for different modes

5:37 Not sure ...

5:37 ashnur: well, i am trying to find someone who uses both :D

5:38 they will know

5:38 mobius-eng: ok :)

5:38 ashnur: https://github.com/syl20bnr/spacemacs/tree/master/contrib/!lang/clojure#cider-and-clj-refactor there is this layer for spacemacs, but none of the things included seem to be on par with the features of paredit

5:38 i will keep looking, definitely need to check the two you said, maybe there is a layer for those too

5:42 hmm. i should try these :( https://github.com/syl20bnr/evil-lisp-state/blob/master/evil-lisp-state.el

5:42 pydave6367: What is the idiomatic way of storing project settings in Clojure?

5:42 ashnur: this is what i already have

5:45 noncom: pydave6367: you mean the project.clj file that is a project description for the buinding tool "Leiningen" ?

5:45 *building

5:46 pydave6367: I meant things like database info - project.clj is fine for that stuff?

5:47 sm0ke: so i recently faced this problem with a macro i had written which was something like (with-foo bar ....)

5:47 pydave6367: noncom: I should clarify - I am indeed using Leiningen.

5:47 sm0ke: and i was calling the macro like (with-foo (baz) ...)

5:48 and the macro expanded and whereever bar was reference in marco it got expanded to (baz)

5:48 since then i am very scared of macros in general

5:49 do library writers keep this in mind?

5:49 what guidelines do you follow while writing your macro?

5:50 noncom: pydave6367: ah, so you mean just configuration files for your app

5:50 pydave6367: That's exactly right. I should have been more clear - my apologies. Long day!

5:50 noncom: pydave6367: i think that the most idiomatic way is to store them as .edn files and read/write them with the edn reader/writer

5:52 sm0ke: your impression is understandable, it is ok for the initial touches with the macros

5:53 pydave6367: noncom: Hadn't come across .edn files before. Thank you so much for the pointer!

5:53 noncom: sm0ke: your best bet is just to write as much macros is possible for various things. ask here if you have questions. it will sort itself out soon.

5:54 ddellacosta: noncom, pydave6367 I haven't heard that before--I would instead advocate for using environ (https://github.com/weavejester/environ) and using either your ~/.lein/profiles.clj file to store sensitive information, or pass it in as environment vars as described in http://12factor.net/

5:54 sm0ke: hurmm

5:55 ddellacosta: this also has the benefit of avoiding the risk of committing something like AWS config to a repo

5:55 noncom: ddellacosta: pydave6367: yes, this is another approach, from a different angle

5:56 ddellacosta: noncom: what benefit does using edn files give you that you can't get more reliably/safely/with less effort from environ?

5:56 sm0ke: noncom: can you look back and say all my macros are safe against unwated expansion

5:56 pydave6367: ddellacosta: Love 12 Factor! I'll explore both options. Thank you so much for the time, I really appreciate it.

5:56 ddellacosta: pydave6367: sure thing

5:56 sm0ke: ideally one can do something like (let [dup# ~bar] ... reference dup# now..

5:57 but wanted to know if its the right way

5:58 noncom: ddellacosta: probably nothing but simplicity and less dependency. i do not actually see how it helps with safety of not committing something. but you are right, the environ solution can be considered more professional.

5:59 ddellacosta: in the end, environ is just a buildup on working with edn, a library.

6:00 ddellacosta: noncom: yes, but it enforces good practices and keeps config details out of a git repo. And if you want to know why the latter is important, here is a good place to start: https://www.humankode.com/security/how-a-bug-in-visual-studio-2015-exposed-my-source-code-on-github-and-cost-me-6500-in-a-few-hours

6:00 noncom: furthermore, just means less reading in things, parsing them, etc--it's one more step you don't have to do.

6:01 noncom: ddellacosta: yep, all that is true

6:02 sm0ke: not sure i really understand your problem

6:03 but also - nothing prohibits me from not commiting the config file to the repo anyway, don't see it as a problem.. OTOH managing environment variables on Windows is hell

6:04 linux is better for that

6:05 sm0ke: noncom: lets say one person The Great Mogambo has written a macro (defmacro hail [name] `(println ~name ~name)).. and one other person Mr. India is calling it like (hail (very-constly-name-getter)) , unintentionally the macros will expand to (print (costly..) (costly..)) and doom Mr. India

6:06 ddellacosta: noncom: yeah, I'm just saying anything that helps automate that part of it is a good thing--no idea about managing env vars on Windows, obviously I'm biased toward Linux/OS X usage

6:06 sm0ke: although its a stupid contrived example but you get the point ?

6:06 noncom: sm0ke: yes, i see, so you want the (costly...) be evaluated once?

6:06 ddellacosta: noncom: in general, I just questioned you because it's good for newbs to see why people who have been using Clojure for a while think about these things--not sure it would have been clear why to use one over the other for the person asking

6:07 sm0ke: yes of course

6:07 although i can use (let [precious (costly)] (hail precious))

6:07 ddellacosta: and both perspectives have their good and bad points

6:07 noncom: ddellacosta: yeah, sure, this is very good that we have described the moment from these angles!

6:07 sm0ke: but do i really need to keep that in mind?

6:08 noncom: sm0ke: why not (defmacro hail [name] (let [res# name] `(println name# name#)) ?

6:08 sm0ke: i already mentioned that noncom

6:08 noncom: (defmacro hail [name] (let [res# name] `(println ~name# ~name#)) ?

6:08 this is the correct way to do this

6:09 sm0ke: but i am saying is it a common practice? do people keep this in mind while writing macros?

6:09 noncom: omg, i mixed up all the names of the variables :D

6:09 a tough morning for me, sorry )

6:10 sm0ke: yes, this is common. after all, macros is plain clojure code executed to rewrite your original form. it is okay to maintain some computation before you are ready to return the changed form

6:10 sm0ke: can you point me to some famous library or core macro doing this?

6:11 also you want (defmacro hail [name] `(let [res# ~name] (println res# res#))

6:12 noncom: sm0ke: yes, them are pretty common everywhere, like even in the clojure core https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1579

6:13 sm0ke: nope, i mean (defmacro hail [name-producer] (let [res# (name-producer)] `(println ~res# ~res#)))

6:13 sm0ke: noncom: its not the same thing.. that macro is manipulating the list directly

6:14 noncom: sm0ke: what about https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1742

6:14 sm0ke: there is no expansion

6:14 nickenchuggets: I always read Sandra Bullock as Sandra Bollocks

6:14 kungi: Is anyone using expect-call for mocking and testing if a function is called?

6:14 nickenchuggets: oops, wrong channel

6:14 :)

6:14 noncom: :D

6:15 sm0ke: noncom: yep thanks

6:15 when-let is simpler and ideal example of this

6:15 noncom: sm0ke: that is actually an essintial part of the macros - define a tiny computation within computation

6:16 well, not always tiny but you get the idea

6:16 sm0ke: thanks for all the help noncom :D

6:16 noncom: the macros which return a `(...) right away are simply.. what's the term in english... reduced forms maybe

6:16 sm0ke: (inc noncom)

6:16 noncom: yeah yeah :)

6:16 thanks!)

6:16 clojurebot: excusez-moi

6:19 Olajyd: Please I’m not really clear with the use of ->> and ->

6:22 ddellacosta: Olajyd: -> is when you want to push a value through a bunch of functions which take some value as the first argument to the function. ->> is the same but when functions take the value you care about at the end.

6:23 Olajyd: both of them are intended to provide more clarity on sequential operations

6:23 Olajyd: for example

6:23 Olajyd: hmm

6:23 ddellacosta: &(-> {:foo "foo"} (assoc :bar "bar") (update :foo clojure.string/reverse))

6:24 don't fail me now lazybot

6:24 ,(-> {:foo "foo"} (assoc :bar "bar") (update :foo clojure.string/reverse))

6:24 clojurebot: eval service is offline

6:24 ddellacosta: right

6:24 did lazybot's trigger prefix change?

6:24 anyways, Olajyd, that's rather contrived but hopefully expresses the point

6:25 Olajyd: yeaa

6:25 Definitely

6:25 Thanks ddlellacosta

6:26 Thanks ddellacosta

6:26 ddellacosta: Olajyd: I tend to find -> is quite useful when dealing with maps, whereas ->> is better for operations on other collections, to generalize

6:26 Olajyd: sure thing!

6:26 gotta go, cheers

6:30 noncom: Olajyd: just to spice up your day: https://github.com/rplevy/swiss-arrows

6:31 Olajyd: lol noncom :)

6:31 noncom: :D

6:31 TEttinger: I learned what a swiss arrow is outside of that context today

6:31 something like a range extender for a dart

6:32 a heavy arrow with a notch cut in it and a string wrapping the notch

6:33 noncom: wow

6:33 TEttinger: also known as a pathfinder dart it seems

6:34 Olajyd: TEttinger, is (->> (s/split line ";") (map #(Float/parseFloat %))) and (-> (s/split line ";") (map #(Float/parseFloat %))) not the same

6:34 TEttinger: correct, not the same

6:36 ,(->> (clojure.string/split "0.0;4e-4;1.2" ";") (map #(Float/parseFloat %)))

6:36 noncom: -> just puts the previous result on the second place in the next form, and ->> puts it on the last

6:36 clojurebot: #error {\n :cause "java.lang.String cannot be cast to java.util.regex.Pattern"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to java.util.regex.Pattern"\n :at [clojure.string$split invokeStatic "string.clj" 217]}]\n :trace\n [[clojure.string$split invokeStatic "string.clj" 217]\n [clojure.string$split invoke "string.clj" -1]\n [sandbox$eval26 invok...

6:36 TEttinger: ,(->> (clojure.string/split "0.0;4e-4;1.2" #";") (map #(Float/parseFloat %)))

6:36 clojurebot: (0.0 4.0E-4 1.2)

6:37 TEttinger: ,(-> (clojure.string/split "0.0;4e-4;1.2" #";") (map #(Float/parseFloat %))) ;; with -> this fails

6:37 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: sandbox$eval80$fn__81>

6:37 TEttinger: ,(macroexpand (-> (clojure.string/split "0.0;4e-4;1.2" #";") (map #(Float/parseFloat %))))

6:37 clojurebot: #error {\n :cause "Don't know how to create ISeq from: sandbox$eval107$fn__108"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: sandbox$eval107$fn__108"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.core$seq__4116 invokeStatic "core.clj" 1...

6:37 TEttinger: ,(macroexpand '(-> (clojure.string/split "0.0;4e-4;1.2" #";") (map #(Float/parseFloat %))))

6:37 clojurebot: (map (clojure.string/split "0.0;4e-4;1.2" #";") (fn* [p1__133#] (Float/parseFloat p1__133#)))

6:38 TEttinger: that macroexpand shows what -> turns into

6:38 ,(macroexpand '(->> (clojure.string/split "0.0;4e-4;1.2" #";") (map #(Float/parseFloat %))))

6:38 clojurebot: (map (fn* [p1__158#] (Float/parseFloat p1__158#)) (clojure.string/split "0.0;4e-4;1.2" #";"))

6:38 TEttinger: this is more what you want

6:39 Olajyd: Nice

6:39 TEttinger: the first macroexpand shows that it tries to map using a function, but it isn't given one... (clojure.string/split "0.0;4e-4;1.2" #";")

6:39 Olajyd: gotcha

7:29 xeno: hi, is it a good idea to combine lein with idea?

7:37 oddcully: xeno: yo many "idea" we are talking idea intellij?

7:37 xeno: in that case, you should go with cursive. all that other stuff in the plugin repos of jetbrains is basically deprecated

7:38 well

7:40 xeno: oddcully: yes

7:40 and the la clojure plugin

7:41 I notice the leiningen plugin is in version 0.0.3 and not updated in 5 years

7:44 oddcully: xeno: i tried half a year ago and half of the things don't work

7:44 xeno: safe yourself the time and get cursive

7:49 cfleming: oddcully: xeno: Yeah, the other lein plugin is long dead, and La Clojure is now officially deprecated in favour of Cursive

7:51 xeno: sure... is it actually released? on the web page there's "Archive" and "EAP"

7:52 snowell: +1 for Cursive. I went way too long not using it

7:52 oddcully: no it's not yet released

7:52 but it works™

7:56 xeno: that's the important part

8:09 you're sure it works? I tried defining a function now, but it refuses to let me insert the end paranthesis

8:17 snowell: xeno: That's probably because structural editing is on. I always have that same problem

8:18 xeno: do you get used to it or do you turn it off?

8:18 snowell: Edit -> Structural Editing -> Toggle structural editing

8:18 I turn it off because I couldn't figure it out. Chances are its really awesome and powerful, but I may never know ;)

8:19 xeno: I love it in other languages, but there you can override it

8:19 in cursive it seems you can't

8:19 snowell: Well yeah, you can toggle it

8:34 cfleming: xeno: You can turn it off any time

8:35 xeno: I recommend getting used to it though

8:35 xeno: then I'll do that - I don't like to settle for half-arsed quick fix compromises :)

8:36 cfleming: xeno: Some doc (a little outdated) here: https://cursiveclojure.com/userguide/paredit.html

8:38 ceruleancity: structural editing is really awesome once you get used to it. It took me a few days of frustration but I’m glad I stuck with it. I always miss it when I use repl now :(

9:13 snowell: OK fine, you've convinced me to try it again :)

9:14 Maybe I'm getting old or something, when I default to hating something just because I don't understand it immediately

9:26 neurostorm: Best video introduction to Clojure?

9:28 oddcully: introduction for whom? boss, management, java devs, ...?

9:29 neurostorm: Developers with limited experience.

9:29 Limited development experience.

10:18 akabander: So I'm working on a multilingual project, and just spent a couple of weeks in Python-land.

10:18 It's true... You can't go home again.


10:19 snowell: It could be worse. I'm being forced to write…Javascript

10:20 And specifically not allowed to use Clojurescript. Such a tease

10:20 akabander: Oof, that seems like a punitive restriction

10:20 galaux: Hello !

10:21 ceruleancity: I’m with you right now snowell… feelsbad

10:21 galaux: Has anyone ever played with clj-gson configuration?

10:21 I see there is a example.clj-gson.clj in the git tree

10:21 snowell: I gave them compelling reasons to use Cljs/Om/Reagent instead of React.js with a crapton of libraries bolted on. They said "That's nice" and then proceeded to dictate just JS

10:22 Despite the fact that the POC I showed them that took me 2 weeks to write was ahead of the current prototype that's taken a team a month to do

10:23 ceruleancity: so what was the argument for just JS?

10:23 snowell: That down the line it's easier to find developers that know JS instead of this "small, relatively unknown" technology called Clojure

10:23 oddcully: let me guess... everyone knows JS. its easier to find developers?

10:23 snowell: DINGDINGDING

10:23 ceruleancity: lol

10:24 snowell: Plus all the big companies are going this React.js route. "It's not going anywhere"

10:26 ceruleancity: it “won"

10:26 oddcully: well the problem is, to get _good_ JS devs

10:33 TMA: the problem is to get any, when you dont want to pay them much

10:36 snowell: if it is any consolation I have been forced to use plain Java instead of Clojure, even though the POC took half day to write offering more functionality than equivalent java POC that took a week to write

10:37 snowell: I guess it feels OK to know I'm not alone in my suffering ;)

10:50 dstockton: its a good opportunity in a way

10:54 justin_smith: snowell: and the thing is, in half the time it took them to replicate your work in js, they could have gotten the team up to speed to code at least as fast in clojure as they do in js

10:59 snowell: Indeed

11:26 huaoguo: e

11:26 Anybody here?

11:27 MasseR: Nope, completely empty channel

11:27 huaoguo: e..

11:28 MasseR: :)

12:29 sgs03: I have a list of maps where the values are vectors. How can I merge them so that the values end up as lists of the original vectors?

12:31 Bronsa: sgs03: ({:foo [1]} {:foo [2]}) -> {:foo ([1] [2])} ?

12:32 sgs03: Bronsa: yes that's what I'm going for

12:32 Bronsa: sgs03: what if there's no common keys? a list of 1 element or just the element?

12:32 ,(apply merge-with list '({:foo [1]} {:foo [2]}))

12:32 clojurebot: {:foo ([1] [2])}

12:32 Bronsa: ,(apply merge-with list '({:foo [1] :bar [1]} {:foo [2]}))

12:32 clojurebot: {:foo ([1] [2]), :bar [1]}

12:32 Bronsa: do you want :bar to be ([1])?

12:33 sgs03: Bronsa: if no common keys, then just one map with all the keys

12:35 luma: Bronsa, that fails if there are more than two maps with the same key

12:35 ,(merge-with list {:foo [1]} {:foo [2]} {:foo [3]})

12:35 clojurebot: {:foo (([1] [2]) [3])}

12:35 sgs03: luma: yes, that's the problem I've been running into using merge-with

12:40 Bronsa: luma: right, #((if (seq? %) conj list) % %2) should work then

12:40 a bit ugly

12:40 ,(apply merge-with #((if (seq? %) conj list) % %2) '({:foo [1] :bar [2]} {:foo [2]} {:foo [3]}))

12:40 clojurebot: {:foo ([3] [1] [2]), :bar [2]}

12:48 justin_smith: ~.

12:48 clojurebot: No entiendo

12:49 justin_smith: ~. is justin_smith is having screen problems.

12:49 clojurebot: 'Sea, mhuise.

12:50 Bronsa: //win 39 is hiredman having irssi problems

12:51 sgs03: thanks guys

12:57 justin_smith: heh

13:03 Balveda: Anyone using Cursive? For some reason new .cljs files aren't being parsed as such by the IDE

13:04 dnolen: Balveda: I use it, haven't seen that problem

13:08 Balveda: Huh, the problem is only when I try to make a file named components.. weird, fixed

13:24 justin_smith: Balveda: I assume by fixed you mean "fixed" -- as in working around the problem by not naming the file components.cljs?

13:24 Balveda: Yes, "fixed" is right

13:24 I wouldn't dare commit code to Cursive :p

13:27 justin_smith: I don't think cfleming even makes that easy.

13:28 blake_: Balveda: I use Cursive. But not much for cljs yet.

13:29 akabander: I use Cursive, but just clj so far.

14:19 dysfun: i've just added cljs support to one of my libraries, but this means that i now list clojurescript as a dependency. i want the library to be usable from both. what's the best way to proceed?

14:22 dnolen: dysfun: [org.clojure/clojurescript "1.7.NNNN" :scope "provided"]

14:22 dysfun: sorry, what does 'provided' do?

14:24 justin_smith: dysfun: it says that you don't distribute or propagate the dep, because it is provided by your host / end user

14:24 dysfun: aha, perfect

14:24 thanks guys

14:29 uptown: i have an async pub/sub question: if i have subs coming and going all the time, what are my lifecycle responsibilities when a subscriber goes away? do i have to unsub per topic per subscriber or will a publisher see a closed channel and clean up its internals by itself?

14:52 devn: Is there any way of extracting which functions were used in a HOF like comp? For instance, is there any way to tell that `integer?` and `number?` were used in the function returned by (comp integer? number?)

14:55 blake_: devn: I don't see how, not without putting some hook in. Like, you could write your own comp that does that. But generically? I'm not sure whom you'd ask.

14:57 Or when you'd ask. "Hey, remember that function I just called? What'd I do with it?"

14:57 devn: You could try a mocking/stubbing type approach, though.

15:11 Balveda: Any ideas how to call a java function from a lein console? I'm getting an exception I'd like to extend

15:11 devn: i suppose i could use metadata

15:11 Balveda: Rather the exception says to call getNextException to see the cause

15:13 blake_: Balveda: Sure, just "Class/methodName" for class methods, and (.methodName objectOfClass) for regular object methods.

15:15 ,(java.lang.String/CASE_INSENSITIVE_ORDER)

15:15 clojurebot: #object[java.lang.String$CaseInsensitiveComparator 0x33cf5657 "java.lang.String$CaseInsensitiveComparator@33cf5657"]

15:16 blake_: ,(java.lang.String/valueOf 1)

15:16 clojurebot: "1"

15:16 blake_: ,(.indexOf "abcdef" "c")

15:16 clojurebot: 2

15:40 lodin_: devn: What's the use case?

15:40 jack0: Do GSoC students get invited for conferences for free? :)

15:55 justin_smith: devn: these questions you ask make me imagine writing code as if you were a secret agent, and using sneaky methods to extract information from your caller

15:56 devn: actually, in some cases, literally "sneaky methods"

15:59 amalloy: justin_smith: d'ye see these footprints here? and this broken branch? a sure sign there's an integer? about in the underbrush

15:59 justin_smith: haha

15:59 (inc amalloy)

16:03 sdegutis: Is it a best practice to avoid function composition (using comp or similar) for functions you might want to redefine at runtime, and rather call it on an anonymous function?

16:07 troydm: any vim users here who would like to test drive a plugin I'm working on?

16:08 anyway here is a plugin https://github.com/troydm/hiparen.vim just load it and then open any clojure source code and disable syntax highlighting by pressing :set ft= and try navigating parens in normal/insert mode

16:09 if anyone is knowleadgeable enough to suggest me how to make it work with syntax on will be help me a lot

16:11 oddcully: troydm: could you elaborate on how this differs from `showmatch`?

16:12 troydm: oddcully: it highlights paren entirely even if the cursor is not on a matching paren

16:14 justin_smith: sdegutis: for runtime redefinition during dev, it should suffice to put it in a var (rather than using a lexical capture / closure), for production a) why? b) better to use an atom or something I would think

16:14 sdegutis: justin_smith: I think the migration to Components will make this problem almost entire entirely go away, yeah.

16:15 justin_smith: sdegutis: that's almost not a non-sequitor, sure

16:15 sdegutis: justin_smith: But even then, the way Compojure's defroutes works isn't compatible with redefinitions by default.

16:15 justin_smith: yeah, part of why I prefer to use a router that works more directly with regular data

16:16 sdegutis: I'm trying to figure out what else I need to take into account though. For example sometimes I have pretended a little too far that Clojure is Haskell, defining functions like (def f (comp g h)) which isn't friendly to redefining g or h inside CIDER.

16:17 justin_smith: you just need to re-evaluate the def when you do it

16:17 unless your f is captured, which means you need to pass #'f instead of course

16:18 sdegutis: or maybe (comp #'g #'h) would be the secret sauce

16:18 I don't think I like that, but I think it would work

16:18 hrmph

16:19 tolu: Hi

16:19 sdegutis: justin_smith: I don't like it either because it assumes REPL development by default rather than Production use by default.

16:19 justin_smith: ,(do (def f inc) (def g inc) (def h (comp #'f #'g)))

16:19 clojurebot: #'sandbox/h

16:19 justin_smith: ,(h 0)

16:19 clojurebot: 2

16:19 justin_smith: ,(def f dec)

16:19 clojurebot: #'sandbox/f

16:19 justin_smith: ,(h 0)

16:19 clojurebot: 0

16:19 justin_smith: it works!

16:19 sdegutis: Right.

16:19 Why wouldn't it?

16:20 tolu: Please I would like to conjoin multiple elements into a vector at the same time.

16:20 * sdegutis is confued

16:20 sdegutis: tolu: then do so

16:20 tolu: I did this:

16:20 justin_smith: sdegutis: I don't know, maybe I'm just hungry for external validation today

16:20 tolu: (map (fn [row] (conj row ["6" "7"])) [["1" "2" "3"] ["4" "5"]])

16:20 sdegutis: tolu: see (doc conj)

16:20 justin_smith: :P

16:20 tolu: and got thi: (["1" "2" "3" ["6" "7"]] ["4" "5" ["6" "7"]])

16:20 justin_smith: tolu: use into, or apply conj which is basically equivalent

16:20 blake_: justin_smith: You're good enough. You're smart enough. And gosh darnit, people like you.

16:20 justin_smith: (inc blake_)

16:21 tolu: I would like my result like this: ;;=> (["1" "2" "3" "6" "7"] ["4" "5" "6" "7"])

16:21 justin_smith: ,(map (fn [row] (into row ["6" "7"])) [["1" "2" "3"] ["4" "5"]])

16:21 clojurebot: (["1" "2" "3" "6" "7"] ["4" "5" "6" "7"])

16:21 sdegutis: (map (fn [row] (conj row ["6" "7"])) )

16:21 Oops wrong button.

16:22 justin_smith: ,(map (fn [row] (conj row "6" "7")) [["1" "2" "3"] ["4" "5"]])

16:22 clojurebot: (["1" "2" "3" "6" "7"] ["4" "5" "6" "7"])

16:22 justin_smith: tolu: so you have a couple options there

16:22 sdegutis: ,(-> [["1" "2" "3"] ["4" "5"]] (apply conj ["6" "7"]))

16:22 clojurebot: #error {\n :cause "Wrong number of args (3) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (3) passed to: PersistentVector"\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" 40]\n [clojure.lang.AFn applyToHelper "AFn.java" 160]\n [cloj...

16:22 tolu: thanks

16:22 justin_smith: sdegutis: I think you wanted a map and a ->> in there

16:22 sdegutis: Oh yeah oops.

16:22 I'm slow today.

16:22 Just finished today's work, woo! Now to get a head start on tomorrow's work.

16:23 blake_: OK, I have functions f and g, and I want to do this "while f collect g". The thing is, f may raise an exception, at which point I need to call h, but not stop the loop. So, something like -> (try (if (f) (collect (g)) (catch Excepion e (h)))

16:24 sdegutis: blake_: (doc take-while)

16:24 (take-while f g)

16:24 blake_: sdegutis: Yeah, I looked at take-while...but what about h?

16:24 sdegutis: Oh yeah ugh, exceptions.

16:24 blake_: what do you need to do with h?

16:24 blake_: use it in place of f when f throws?

16:25 (let [f2 #(try (f) (catch Exception e (h)))] (take-while f2 g))

16:25 jack0: Do GSoC students get invited for conferences for free?

16:26 blake_: sdegutis: OK, I was sort of headed that way.

16:26 justin_smith: jack0: couldn't hurt to ask for such an invite, puredanger might have more info

16:26 blake_: So, simplify the function so I can use take-while. Lemme see.

16:27 sdegutis: Sure.

16:27 jack0: puredanger: Any info?

16:28 justin_smith: jack0: this being IRC, you might have to wait a while for a reply

16:28 jack0: Sure

16:28 justin_smith :)

16:28 blake_: sdegutis: OK, I think the other part of the problem is that (h) is not guaranteed to ensure the success of (f) on the next call.

16:28 sdegutis: blake_: so you want to quit-out when you get (h)?

16:29 cfleming: jack0: You could also send email, I think events@cognitect.com is the address you want

16:29 blake_: sdegutis: No. It's a DB read where the records may be bad. Multiple records in a row may be bad, but they should be skipped.

16:29 (And skipping might take you to the end.)

16:30 sdegutis: blake_: sounds like you also want filter then

16:31 blake_: I would use map and filter here -- map to call the db-function on the thing and return maybe a map including a status and a db result, and filter to remove ones with invalid status

16:31 blake_: in some cases you can simplify it and just return nil when the db-value returned from (f) will always be non-nil and non-false, and then just do (remove nil?) on the resulting coll to get rid of bad entries

16:31 blake_: sdegutis: OK, cool. Just wanted to make sure I wasn't overcomplicating.

16:32 sdegutis: blake_: but in other times, a simple map works, like {:ok db-value} or {:error error-string}, and then when you're done, (filter :ok) and then (map :ok) to get the db-values

16:33 blake_: don't take my word for it, I may be overcomplicating it too; a lot of it depends on your problem domain

16:33 blake_: are you using datomic?

16:33 blake_: sdegutis: Monger.

16:34 sdegutis: It's got this great thing to download everything as a map, but an exception in the Java just stops it cold.

16:35 sdegutis: Oh cool. That sucks tho btw.

16:37 blake_: sdegutis: Yeah, I'm not crazy about...any of it. Heh.

16:38 sdegutis: Maybe you can use Datomic? We switched from MongoDB to Datomic a few years ago and it's great.

16:38 We've got a low load though, so we're only using Datomic Free, which I'm not entirely comfortable with but it seems to be working fine.

16:38 blake_: sdegutis: I'd be willing to push it. Any good starting references?

16:39 sdegutis: Oh, hell, this mongo stuff is paltry. I'm not convinced of its applicability for high volume. I'd probably store this stuff in text files, frankly.

16:39 But I'm weird.

16:39 sdegutis: I just don't like how MongoDB locks the whole database on /every query/.

16:39 Maybe that's changed since I used it but I doubt so.

16:40 blake_: Sorry, I don't have any references off hand. Ask in #datomic or https://clojurians.slack.com/messages/datomic/

16:41 blake_: sdegutis: Cool. I'll check it out. =)

16:49 sdegutis: This is so exciting! I'm writing an immutable recursive descent parser and lexer that keeps track of file line/char positions and has decent and informative error handling!

16:53 blake_: Neat.

16:57 Balveda-2: I'm getting this error on a response (I suppose), after making a successful entry into a DB

16:57 http://pastebin.com/8Kwvi9md

16:58 I haven't touched the middleware, it's more or less a standard luminus app

17:52 sdegutis: Is it possible to destructure several levels of {:keys} ?

17:52 I don't even know what that syntax would look like.

17:56 gfredericks: sdegutis: maybe not what you're imagining, but you can do nested destructuring

17:56 sdegutis: Yeah that is basically it.

17:56 gfredericks: sdegutis: plumbing.core/{fnk,letk} is a bit more readable for that

17:57 ,(def my-data {:foo {:bar 12}})

17:57 clojurebot: #'sandbox/my-data

17:57 gfredericks: ,(let [{{:keys [bar]} :foo} my-data] bar)

17:57 clojurebot: 12

17:57 sdegutis: So if I have {:foo {:bar [1 2 3]}} then I know I can do (let [{:keys [foo]} m]) but I dunno how to get foo to destructure :bar inside the same {}.

17:57 Oh I see how you did that.

17:57 You used the non-:keys way.

17:57 gfredericks: yeah you have to fallback to non-:keys

17:57 sdegutis: Haven't seen that way in ages.

17:58 I like it.

17:58 gfredericks: it comes up from time to time

17:58 sdegutis: Thanks g-fred

17:59 gfredericks: np

18:11 sdegutis: I really like this state machine. It's just built in plain old clojure.core functions but it feels like the most flexible and expressive thing ever.

18:32 robstory: hi clj friends. looking at http://kotka.de/blog/2010/03/proxy_gen-class_little_brother.html

18:33 are there any current workaround for the proxy multi-arity issue?

18:33 e.g. I need to proxy two arities, and have proxy-super call the other

18:33 reasonably sure the implementation of proxy-super makes this impossible, but wanted to confirm

19:33 ben_vulpes: does anyone use cider for simultaneous clojure+script work?

19:34 the question i'd like to answer is if it's possible to host my nrepl in the browser or if i must connect the browser repl to a process running on the dev machine.

19:41 justin_smith: ben_vulpes: afaik clojurescript repls use an http server plus a websocket connection, and none of them directly implement nrepl (which is a more general tcp based protocl)

19:42 ben_vulpes: for starters, how would you listen for connections on an arbitrary port without this being a huge security hole in the browser?

19:45 ben_vulpes: though, now that cljs has some limited self-hosting, you could eg. connect a repl to a websocket (but this would not be nrepl, though you could make a websocket to tcp bridge as a shim)

20:22 ben_vulpes: blee

20:22 okay okay

20:22 thank you justin_smith

20:23 (although the counterargument is that the browser itself *is* a security hole, but let's let that one lie)

20:23 you are full of wisdom as always

20:23 justin_smith: I'm just saying listening to connections on a random port is more blatent than any other messed up thing we let browsers do

20:23 haha, I try

20:40 fireplaceHelp: hello clojure people. i'm confused about nrepl behaviour when using "vim-fireplace". i start a repl in some terminal, then i connect to it in vim, and i can evaluate expressions *in vim*. but i can't use those definitions in the terminal repl

20:41 i.e. it doesn't seem to be using the same session?

20:41 or do i totally misunderstand how this should work?

20:41 ben_vulpes: fireplaceHelp: are you switching into the correct namespace in your re

20:41 repl*

20:41 ?

20:41 fireplaceHelp: hmm...

20:41 no.

20:41 justin_smith: yeah, probably a question of what ns you are in

20:42 (doc in-ns)

20:42 clojurebot: "([name]); Sets *ns* to the namespace named by the symbol, creating it if needed."

20:42 justin_smith: fireplaceHelp: (in-ns 'your.ns) ; as long as it's been loaded at least

20:42 fireplaceHelp: brilliant.

20:43 working now.

20:43 how stupid of me

20:43 thanks!!

20:44 justin_smith: fireplaceHelp: the only stupid questions on #clojure are the ones sdegutis asks, and he's doing it on purpose

20:54 ben_vulpes: justin_smith: look i can be useful too

20:55 justin_smith: :)

21:00 LelandAero_: hello

21:26 blt: Anyone have an example of using enlive templates in a jar?

21:26 justin_smith: blt: in general the trick to using things packed in your jar is use io/resource instead of io/file

21:27 or (slurp (io/resource "relative/path")) instead of (slurp "the/whole/path")

21:43 blt: justin_smith: it's funny, (io/resource "relative/path") works great when I am just running my server from the repl. When I try to run it from the jar, when i hit the url, it prompts me to download a zero byte BIN file.

21:43 i can replicate it on heroku as well as locally

21:44 justin_smith: blt: is the file in your jar? in order to end up in an uberjar it has to be in a directory that is on the resource-path

21:45 blt: the template files live in resources/client/...

21:45 justin_smith: so you are doing (io/resource "client/...")

21:45 simon1234: Hi all! I'm using a ThreadLocal with a threadpool and with core.async go (no green thread only >!! <!!). And at one point, it seems that some ThreadLocal var get reused in some way but by a different thread (checked by (.getId (Thread/currentThread)) + I think I clear the ThreadLocal var (but this is not even the same thread). Not sure I made myself clear, but how such a behaviour could be made possible? Thanks...!

21:45 blt: justin_smith: yes i am

21:45 justin_smith: simon1234: threadlocals do not work with core.async

21:45 simon1234: justin_smith: even with <!! and >!! ?

21:46 justin_smith: you meantioned go

21:46 simon1234: yeah

21:46 justin_smith: inside go, threadlocals are liable to break

21:46 and to end up being accessed by other go blocks

21:46 simon1234: justin_smith: I'm not using a threadlocal myself but slf4j is (with the logging context)

21:47 and in my test I get weird errors from times to times

21:47 justin_smith: simon1234: perhaps you can move the sl4j calls outside of the core.async context, by making a normal thread that loops and does a blocking read from a channel

21:48 because things that use threadlocals will do weird things inside go blocks, there's not much you can do to prevent that, because of how core.async allocates and re-uses threads

21:50 blt: how might I inspect a the jar file that is created with uberjar? I'd like to explore the resources

21:50 TEttinger: it's actually just a zip

21:50 with a fancy file extension

21:51 justin_smith: blt: it's a zip file, you can use the jar command too (works much like *nix tar)

21:51 blt: TEttinger: oh, well then

21:51 justin_smith: also, you can use the gnu version of the tar command with jar files too

21:51 TEttinger: I usually use 7zip for inspecting things that may or may not be archives. plus 7zip can compress things to outrageously tiny archives in some cases

21:52 justin_smith: also emacs and vim can open jars as if they were folders

21:54 blt: thanks

21:58 justin_smith: so, when I explore the jar file, I see my "client/..." in the root of the jar. But I still get that zero-byte file download prompt when I hit "/" of my app

21:59 justin_smith: blt: do you see the actual template file?

21:59 maybe there's an issue with your routes - are you using wrap-file middleware?

21:59 blt: the template file for "/" is client/index.html and it's listed in the jar

21:59 justin_smith: because if you are using wrap-file you need to turn that into wrap-resource

21:59 blt: justin_smith: negative

21:59 justin_smith: OK

22:00 blt: i don't seem to be using wrap-resource eigher

22:00 either*

22:00 simon1234: justin_smith: oh thanks a lot, sorry I got carried away

22:00 justin_smith: so client/index.html is there, and you are able to do (slurp (io/resource "/client/index.html")) but only from the repl not the jar?

22:00 simon1234: ah yeah so it reuses thread in some way, what is weird is that the thread id does change

22:01 justin_smith: simon1234: that is odd - but core.async definitely has a fixed pool and recirculates the threads, so I wouldn't be surprised by odd things happening when a lib tries to do things based on threadlocal bindings

22:01 blt: justin_smith: (slurp (io/resource "client/index.html")) works in the repl

22:02 justin_smith: oh, I might have been wrong about using the leading slash

22:03 blt: oh well, close enough.

22:04 but yeah, i have to use (template (io/resource "client/index.html")), leaving out the slurp for enlive to work

22:04 but that doesn't work when i generate a jar

22:04 justin_smith: right, slurp was just an example of a thing that requires the valid resource

22:05 blt: gotchya, yep it's valid

22:05 justin_smith: blt: what about (slurp (io/resource "clojure/set.clj"))

22:05 (from the jar)

22:05 just random example of a file that will be there if clojure is

22:06 blt: justin_smith: i'm sorry but I'm actually not sure how to run the repl from the jar

22:06 justin_smith: blt: java -cp your-jar.jar clojure.main

22:06 blt: thanks

22:06 justin_smith: for bonus usability rlwrap java -cp ...

22:07 also you may be able to narrow down how to use the resource with the template

22:07 blt: could it be that the template function requires (io/input-stream (io/resource "your/template.html")) and instead of erroring just returns an empty string?

22:07 because some things refuse to use a resource directly and need you to do the input-stream conversion

22:08 or io/reader (if it's not input stream)

22:08 you can easily try all these from that jar repl

22:08 blt: i'm happy to try both out

22:22 justin_smith: i attempted both io/input-stream and io/reader but still get the zero-byte d/l prompt

22:22 justin_smith: blt: what about directly using the template function from the repl

22:23 seems like you would get quicker feedback on what happens / what goes wrong

22:25 blt: justin_smith: when I try to start the repl I get "could not find or load main class clojure.main"

22:26 justin_smith: uhh - make an uberjar

22:26 (or make sure you are using the uberjar)

22:28 blt: ah, I guess it generated two jars and one of them works. but when I (in-ns 'my-ns) and try the template fn I get unable to resolve symbol, sigh

22:28 justin_smith: blt: you need to require your code

22:29 blt: (require 'my.ns) (in-ns 'my.ns)

22:29 after using in-ns without require you need to do (require 'this.ns :reload)

22:29 blt: justin_smith: thanks, sorry I'm a noob when it comes to the jar stuff

22:29 justin_smith: err

22:30 (clojure.core/require 'this.ns :reload)

22:30 blt: it's OK, I forget that other people don't know the underlying stuff their tooling uses

22:31 blt: but don't worry, it's not that thick a layer between the tools you are used to and what clojure can do on its own

22:31 blt: justin_smith: well, (template "client/build/index.html") actually does the correct thing

22:31 justin_smith: blt: you might need to try this from a different directory?

22:31 since it will be looking in the current dir right?

22:32 or no, wait

22:32 so the whole resource thing was a boondoggle, there is some other problem?

22:32 blt: justin_smith: it would seem so i guess

22:33 boondoggle, nice

22:36 this is some of the code: https://www.refheap.com/327cfbe43e923bf58c6c1fb48

22:39 justin_smith: blt: that "or" call on line 29 is weird

22:39 you know it will always return the first branch, right?

22:40 blt: frick, you're right

22:40 and i'm trying to get into that second case

22:40 justin_smith: you probably wanted an if-let there

22:40 or something

22:40 blt: before they used to be io/resource wrapping the str calls

22:40 justin_smith: ahh, then the or would make sense

22:42 simon1234: justin_smith: so thanks a lot for your input, I removed core.async. No more problem, this is quite dangerous :s Thanks a lot!

22:43 justin_smith: simon1234: you could probably find a way to segregate the slf4j stuff from the core.async

22:44 simon1234: justin_smith: hopefully, but well for now that will do it, I was only relying on core.async for test purpose. Thanks :)

23:06 blt: justin_smith: yeah, definitely seems like it's further up unfortunately

23:08 pretty frustrating that it works when running from the repl but not jar sigh

23:11 my goal is to get a jar that heroku can run

23:26 justin_smith: thanks for the input amigo. i guess i'm going to keep trial and erring and see if i can get it

23:26 * blt bows out

23:59 nowprovision: refactoring a function, my first attempt was pretty poor (having not touched clojure for a few months), v2 seems cleaner, but still seems wrong to take 100 and then do last? any thoughts https://www.refheap.com/109420

Logging service provided by n01se.net