#clojure log - Dec 10 2015

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

0:09 amalloy: well it wasn't exactly a real question, so much as a social commentary on your asking how people remember things

0:51 TEttinger: ok, that's an exciting outcome...

0:52 I am evaluating YourKit, justin_smith I'm blaming you if it isn't fantastic, but it seems rather great so far

0:53 found that in this java lib that is intended to be used to do heavy work so clojure doesn't have to... 83% of CPU time for this test is spent on one line. it is not a small test.

0:54 the line doesn't seem like it should be that slow. it converts a type-specialized resizable array of short values to a "real" array of short values

0:55 and internally all that does is System.arraycopy

0:57 so... does anyone know if having low memory available to the program would explain the array copy being slow?

1:39 wolgo: Hi. I want to learn clojure. I know some other languages. I learn best by just hacking away but is there a book that the community recommends to supplement my learning? I am starting a new job soon and part of my duties will include writing production quality clojure code. Thanks for helping me.

1:56 TEttinger: wolgo: there's brave clojure, several other good physical books

1:56 ~brave clojure

1:56 clojurebot: Titim gan éirí ort.

1:56 TEttinger: ~brave

1:56 clojurebot: brave is http://www.braveclojure.com/

2:39 wolgo: TEttinger: okay cool, I have been perusing that one

2:40 TEttinger: thank you

2:40 TEttinger: hope you find it useful!

2:47 BRODUS: say i want each of my list items to be an argument to a function call, is there a macro that will do that?

2:48 amalloy: (doc apply)

2:48 clojurebot: "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."

2:50 BRODUS: (apply (map identity) '(1 2 3 4))

2:50 amalloy: well, close. you mean (apply map identity '(1 2 3 4))

2:50 or, well, you don't even mean that, because that's just (map identity 1 2 3 4), which doesn't work

2:51 BRODUS: ok i think i get it

2:52 opqdonut: ,(apply map + [[1 2 3] [4 5 6] [7 8 9]])

2:52 clojurebot: (12 15 18)

3:33 slawo: hey everyone, quick question about profiling a clojure app

3:33 I got myself visual vm open

3:33 connect to a repl session

3:34 and cpu-sample while I run (dotimes [n 1e8] (my-thing))

3:35 visual vm starts producing data alright

3:35 TEttinger: criterium is best for benchmarking

3:35 opqdonut: yeah but profiling /= benchmarking

3:35 TEttinger: yeah

3:36 not sure what the question would be

3:36 slawo: but of course the functions with most self-time are my-ns.$eval12334$fn__3434.invoke()(

3:36 opqdonut: jvisualvm is nice, but you usually need to filter out lots of classes/packages to get a result you can actually interpret

3:36 slawo: if (my-thing) is an actual function in an actual namespace, it will show up as my-ns$my-thing or so

3:37 the evalXXXXX basically refers to the line you typed into your repl

3:37 slawo: cool

3:37 any way to get those fn__3434334’s sorted?

3:38 I assume they are inner functions

3:38 opqdonut: they're closures yeah

3:38 slawo: any way to identify which ones?

3:38 like attaching metadata to them or something

3:38 riceandbeans: brave clojure is confusing the hell out of me

3:39 opqdonut: slawo: sorry, no ideas there. in my experience the profiles for actual clojure programs are quite readable because you tend to have lots of small named functions

3:40 slawo: so it’s not common to use closures in clojure?

3:41 riceandbeans: what is a closure?

3:41 slawo: I mean, if I have to spell out every single reducer function instead of inlining with #() or (fn foo []) … clojure loses some of its appeal, no?

3:41 amalloy: slawo: look more closely at the names of the functions. they'll indicate what top-level var they're apart of

3:41 slawo: amalloy: cool, so the numbers mean something?

3:41 amalloy: ,(class ((fn foo [] ((fn inner [] inner)))))

3:42 clojurebot: sandbox$eval25$foo__26$inner__27

3:42 amalloy: not really, no

3:42 but look at this classname

3:42 slawo: let me see…

3:42 amalloy: ,(defn f [] ((fn foo [] ((fn inner [] inner)))))

3:42 clojurebot: #'sandbox/f

3:42 amalloy: ,(class (f))

3:42 clojurebot: sandbox$f$foo__53$inner__54

3:43 amalloy: you can see what top-level var owns the lambda, and how many nested lambdas "deep" it is, and additionally if any of those are named you can see their names

3:45 slawo: let me see if I can name them

3:48 amalloy: any idea what a …$G__3434_1234.invoke() is?

3:48 the G prefix is different from a fn prefix

3:49 amalloy: ,(class #(inc))

3:49 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: core/inc--inliner--4246"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "clojure.lang.ArityException: Wrong number of args (0) passed to: core/inc--inliner--4246, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type clojure.lang.ArityException\n :message "Wrong numb...

3:49 TEttinger: probably a symbol

3:49 luma: it's a symbol from (gensym)

3:49 amalloy: ,(class #(+ 1 2))

3:49 clojurebot: sandbox$eval128$fn__129

3:49 amalloy: yeah, what luma said

3:49 TEttinger: ,(let [m# 2] (class m#))

3:49 clojurebot: java.lang.Long

3:50 TEttinger: ,(let [m# #(+ %1 2)] (class m#))

3:50 clojurebot: sandbox$eval179$m_SHARP___180

3:50 TEttinger: nooo....

3:50 autogensym doesn't do it?

3:50 ,(gensym +)

3:50 clojurebot: clojure.core$_PLUS_@378fdfe1207

3:51 TEttinger: ,(gensym ++++)

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

3:51 amalloy: TEttinger: # only does anything inside `

3:51 TEttinger: ,(gensym #(+ 1 2))

3:51 clojurebot: sandbox$eval253$fn__254@22ed95cd257

3:54 slawo: all of my slow spots are $G__somethings :)

3:55 jonathanj: so revisiting the repl conversation from several hours ago, it would be pretty cool if you could put nREPL behind SSH with only public key auth

3:55 amalloy: well, figure out what they're inside of

3:55 some macro is generating functions

3:55 ashwink005: has anyone worked with clout?

3:56 is there any support for regex?

4:10 BRODUS: I want to convert a list to a hashmap where every item in the list is a key in the hashmap. is there a better way to do this than 'frequencies' ?

4:11 MJB47: depends what you want the values to be

4:11 BRODUS: doesn't matter

4:12 MJB47: then i dont see why you want a hashmap?

4:12 luma: why do you want a hashmap then?

4:13 BRODUS: i want to later filter another list based on the items presence in the hashmap

4:13 luma: use a set

4:13 MJB47: why cant you do that with a vector or set?

4:13 or even the list

4:14 slawo: prismatic have https://github.com/Prismatic/plumbing/blob/master/src/plumbing/core.cljx#L86 this for this purpose

4:14 BRODUS: using a set makes sense

4:15 slawo: btw. my mysterious G__ appears to be the function dispatch of defprotocol

4:17 shame functions in defprotocol appear as fn_123213, even though they clearly are named

4:19 and shame that function dispatch based on protocols is the slowest of my system… I’ll check if I can get rid of the protocol and call foo-to-this foo-to-that if I happen to know the types

4:30 noncom: slawo: i never use protocols though many say them are good things.. i don't mind, but i just don't use them

4:31 slawo: noncom: they are brilliant for polymorphism

4:31 but you better not have any polymorphism in your cricical paths :)

4:32 noncom: yeah! well, i deal with polymorphism differently, mostly avoiding it

4:33 slawo: noncom: but it’s tempting to use language facilities, no? :)

4:34 noncom: slawo: not really..

4:34 clojurebot: excusez-moi

4:34 noncom: slawo: such a dispatch can be explained by a lesser set of "facilities"

4:35 Trioxin: I was speculating on this yesterday to someone but I need some clarification. I'd like to use Clojure with nwjs so that I can make my clojure GUIs with HTML5. I should be able to just load a clojure jar in the chromium wrapper as an applet right? And also communicate between the applet and code on the page? I've never made an applet.

4:35 noncom: like, reduced to simple operations, without getting a whole other paradigm into the business

4:35 slawo^

4:36 slawo: noncom: well at the lowest level I agree, but once I start putting things together, it helps to think of them as ‘foos-of-a-kind’

4:36 noncom: slawo: maybe, maybe.. but in such cases i just group them in {}s

4:37 see, no garbling of names, no hassle behind the scene..

4:37 slawo: I suppose :)

4:37 erlang is a bit like that no?

4:37 noncom: yeah

4:37 a bit :)

4:37 slawo: my_thing = [:type_of_thing what ever else]

4:38 and then you just match on the first field :)

4:38 everywhere :)

4:40 noncom: slawo: yep, like that too

4:44 Trioxin: how do you want to distribute your app? from what i know, the chromium wrapper allows for getting browser functionality inside, say, a java app, is this what you want?

4:46 Trioxin: noncom, in nwjs, since it's meant for creating desktop apps, things like xss and other system protections are disabled. I intend to use clojurescript and HTML5 code in the dom and the applet will do all the heavy lifting.

4:47 noncom: then what's the problem?

4:47 it looks pretty straightforward...

4:48 you won't need an applet if the wrapper is about wrapping the browser in java app

4:48 i think you'll simply need a java app

4:49 Trioxin: noncom, problem is I don't think I can just run any old jar as an applet and I'm not sure what the procedure for that would be with clojure. I see these http://juliangamble.com/blog/2011/11/27/applets-in-clojure-and-counterclockwise/ and this https://en.wikibooks.org/wiki/Clojure_Programming/Examples/Creating_an_Applet . I intend to load the jar in the browser, not wrap a browser in clojure.

4:51 noncom, I can follow those links I suppose but it's telling me that I won't be able to properly debug (In one example) and that I have to take extra steps to use an repl in the other. I'm wondering if there's an easier way.

4:52 noncom: i don't really get it. you want a java app with HTML gui but applets are forbidden now in browsers, so you're using a bare browser engine to work around the security limitations and run your applet in it. BUT you want to run the applet in an actual browser still!

4:52 Trioxin: noncom, also I think those examples might assume I'm trying to display things using my jar. It's just going to be doing system work.

4:53 noncom, nwjs.. not a browser

4:54 noncom: okay, but from what i see on their page, is like, nwjs will be employed as a plugin for your java app. not like your java app will be running inside nwjs, but vice versa

4:54 Glenjamin: clojurescript is the key point here

4:54 noncom: am i wrong?

4:54 Glenjamin: you said clojure initially, but then mentioned cljs

4:55 noncom: yeah, with clojurescript there's a tonn more variables

4:56 Trioxin: noncom, nwjs is a chromium wrapper with node that has node interop in the dom. I want to load my jar in the dom and communicate with the dom. For that requires an applet. I do plan to use cljs as well but my jar to perform systems operations.

4:57 noncom: hmmmm sounds convoluted ..

4:57 Trioxin: noncom, the jar needs to be in the "Browser," a browser that doesn't have limitations on java and I don't wish for my jar to have it's own GUI. nwjs can take care of that. From an applet I can communicate with javascript or cljs on the page

4:58 noncom: i think it is very unfeasible to manipulate dom from java

4:58 Trioxin: I've seen that done before with Java applets but this is clojure and the examples I saw were creating GUIs with Java which I don't intend to do.

4:59 noncom, they interop

4:59 i could interop with node but I don't want a step in the middle

5:00 noncom: yes, i know.. but why don't you want to use clojurescript for that? you said that java could do system work, so why then involve it into dom alteration?

5:00 Trioxin: noncom, the GUI will enable the user to make use of the jar

5:01 i don't want to make my gui in clojure. I want to use nwjs for several reasons.

5:02 noncom: okay, i understand..

5:02 Trioxin: did you think about creating a clojure app that serves a web gui?

5:03 that would be far more straightforward

5:04 Trioxin: nwjs is very mature, serving a web gui in clojure would be code I don't have to write, and node/dom interop is baked into nwjs so that's always good.

6:14 BRODUS: has anyone else had trouble getting popup clojure documentation to work in emacs?

6:26 ashwink005: anyone used nginx?

6:42 ARM9: what's the easiest way to use antlr to generate a parser in a lein project?

6:47 yenda: people use lein template to make boot templates ?

7:45 jonathanj: why if i have something like: `(let [thrower #(throw %)] (future (try (throw (ex-info "Oh no" {})) (catch Exception e (thrower e))))` does the exception not actually get thrown?

7:46 `thrower` is invoked but apparently trying to rethrow that exception does nothing

7:46 justin_smith: jonathanj: you don't get the exception until you deref the future

7:48 jonathanj: What do you mean?

7:48 What do you mean by "get the exception"?

7:48 justin_smith: jonathanj: if an exception happens inside a future, you can deref the future to get the exception to throw. Otherwise it's a silent failure.

7:49 jonathanj: uh, okay, but in that code there i'm calling a function defined outside the future that rethrows the exception

7:49 that function is being called and the exception is well defined but apparently trying to rethrow it does nothing

7:49 and i'm not deferring the future, so why does rethrowing do nothing?

7:49 justin_smith: jonathanj: throws inside the future are handled differently

7:50 you don't see the exception unless you deref it

7:50 jonathanj: problem is that deref is blocking :|

7:52 i tried to understand agents, but i'm not sure how to apply the "change the agent state" approach to mutable Java stuff

7:52 powered: what's the use for exceptions anyway outside of java interop?

7:52 justin_smith: jonathanj: since the bots don't let us play with exceptions, see this example: https://www.refheap.com/112543

7:52 jonathanj: powered: i dunno, to signal an exceptional state?

7:52 justin_smith: jonathanj: that's not what agents are for - send to an agent changes which object the agent holds, usually

7:53 jonathanj: justin_smith: yeah, that's the picture that was slowly making sense to me

7:53 justin_smith: powered: there's plenty of ways to make an exception happen without interop

7:54 jonathanj: I mean it's hypothetically possible to put a mutable java thing in an agent, and only send functions that poke its mutable state followed by returning the original object

7:54 but this isn't what agents are set up to do

7:54 jonathanj: definitely do not put mutable things in atoms or refs, because retries

7:54 jonathanj: yeah

7:54 powered: yes I guess network request etc has exceptions

7:55 justin_smith: ,(+ 1 "hello") ; all sorts of things are erroneous

7:55 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 add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]...

7:55 jonathanj: exceptions have kind of got a bad rep, for reasons i don't fully understand

7:56 powered: because correct code doesn't encounter exceptions

7:56 and exceptions as flow control mechanism isn't good either

7:56 jonathanj: without exceptions (or some notion of "a thing happened that was not success and now you had better deal with it") you end up with Go-style silliness

7:57 yeah, well the real world isn't always correct

7:57 if some user says "hey, use the certificate with alias X" and there is no such certificate in the keystore, what do you do?

7:57 powered: return nil

7:57 I like the idea of pure functions returning something, not throwing exceptions

7:57 jonathanj: okay, so then the thing that was expecting a result now has to handle nil

7:57 justin_smith: nil is arguably worse than exceptions

7:58 jonathanj: and nobody knows there was an error

7:58 and eventually you get to a piece of code that says "hey, i can't add 1 to nil guys" and you are totally clueless as to what the hell lead you down this path

7:59 ARM9: that's what you get with dynamic typing, time to reinvent the monad

8:00 powered: I'd rather use if vs try catch

8:00 jonathanj: powered: well they're not really comparable

8:00 powered: you can't accidentally ignore an exception

8:01 if you assume code always returns a non-error value it means you can just write what you mean and the "good" code path is much cleaner

8:01 instead of littering it with return code checks

8:01 Glenjamin: if you use the maybe monad with do notation, you still can't tell where the Nothing came from

8:02 powered: yes, so you're saying if something goes wrong: fail right away

8:02 jonathanj: powered: that's usually the best course of action

8:02 Glenjamin: it's the best default imo

8:02 jonathanj: but if you don't want to do that, or you know how to recover, then you catch the exception and do the better thing

8:02 imo, that is a much better case than "always write all of the error handling all over your code"

8:06 justin_smith: i'm not really sure what actually suits my needs then

8:07 justin_smith: i don't want to block on a deref only to determine if there's an exception

8:07 so while i can use `realized?`, what if the exception hasn't occurred by the time i check if it's realized?

8:08 justin_smith: jonathanj: look at my paste - it's possible to ask if it's realized, also consider you could do something other than just a rethrow - you could send a message to some queue or channel indicating the error occurred, or even just log it

8:08 jonathanj: realized? means it stopped - and it should stop at some point right?

8:09 jonathanj: justin_smith: yes, but there is always the possibility that i call realized? one second before the exception occurs, so the question is when do i call realized?

8:10 justin_smith: it really depends what you are doing with that future. Maybe you should just log the error or put a status on a queue being watched somewhere.

8:10 jonathanj: justin_smith: a channel might be a possibility, can i put to a channel from another thread?

8:10 justin_smith: yes, core.async is pretty flexible about where stuff executes

8:11 jonathanj: justin_smith: so the reason i need the exception is because if there is an exception i need to communicate to the client (this is a service handling an HTTP request) that the request failed, so only logging it isn't really an option

8:12 i think if i create a channel for each request and put errors/results on it, that should work quite reliably

8:12 justin_smith: so then you need something to consume the result of that future - something that knows how to communicate with the client

8:13 jonathanj: the service effectively returns immediately with a URI to where the result will eventually be, the GET to that resource will block until the result is actually ready

8:15 anyway, there's definitely some stuff to play with, thanks, i'll try a few approaches and see what works best

8:21 justin_smith: oh something i forgot to mention is that i'm using PipedInputStream and PipedOutputStream, writing to the stream from the future; if the pipe buffer fills up (not reading data fast enough) then writes start blocking, so deref-ing the future too early will cause the reading thread (the main thread) to block and then you enter a deadlock

8:23 this could probably be avoided by using ByteArrayOutputStream or similar but that means allocating all the memory for the output ahead of time

8:25 justin_smith: jonathanj: or you could just check realized? before dereffing

8:25 if it's not realized it's still running

8:29 jonathanj: then we're back to the question of if it's not realized, when do i try deref it?

8:29 justin_smith: you could poll it

8:29 you could have a try/catch/finally where the finally puts something in action

8:29 (inside the future that is)

8:31 Glenjamin: does deref with a timeout help?

8:32 justin_smith: true, that's another option

8:34 jonathanj: what do i do if it times out?

8:35 BRODUS: i'm stumped on this problem http://www.4clojure.com/problem/78, is there a way to tell if a value is a function other than calling 'clojure.test/function?'

8:35 sunset-shimmer: hello, I need some help

8:36 justin_smith: ,(fn? #())

8:36 clojurebot: true

8:37 sunset-shimmer: I have a for loop and a complex structure that I need to update in each iteration step. How to return final and fully updated structure from the loop?

8:37 BRODUS: justin_smith: thanks, i couldn't find that one

8:37 justin_smith: sunset-shimmer: for is not a loop

8:38 sunset-shimmer: you can use reduce with the for comprehension as its input, or perhaps use loop

8:38 but for is not a loop and isn't designed to do what you want

8:38 sunset-shimmer: ah, I see!

8:40 I'll try reduce, loops are boring

8:41 justin_smith: sunset-shimmer: I'll make a guess that using the result of the for comprehension as the collection arg to reduce, you should be able to build up the result you want

8:50 jonathanj: i swear i ask this every week, but how to turn [[1 2] [3 4]] into [[1 3] [2 4]]?

8:51 ,(apply map vector [[1 2] [3 4]])

8:51 clojurebot: ([1 3] [2 4])

8:51 jonathanj: is there a limit on how many parameters can be passed with apply?

8:52 jeaye: ,(doc apply)

8:52 clojurebot: "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."

8:52 jonathanj: i meant like a hard limit

9:04 sunset-shimmer: > derrida has left IRC

9:04 sorry, I am lold

9:23 jonathanj: is there somewhere i could read about some common sync idioms written with core.async?

9:24 synchronous idioms, that is

10:07 powered: this feels wrong: (merge-with merge {:a {:a 1}} {:a {:b 2}})

10:07 is there a better way?

10:08 beaky: ,(merge-with merge {:a {:a 1}} {:a {:b 2}})

10:08 clojurebot: {:a {:a 1, :b 2}}

10:08 beaky: ,(merge {:a {:a 1}} {:a {:b 2}})

10:08 clojurebot: {:a {:b 2}}

10:08 beaky: ,(flatten {:a {:a 1}} {:a {:b 2}})

10:08 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: core/flatten"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/flatten"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 36]\n [sandbox$eval73 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eva...

10:09 beaky: ,(apply into {:a {:a 1}} {:a {:b 2}})

10:09 clojurebot: #error {\n :cause "Don't know how to create ISeq from: clojure.lang.Keyword"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: clojure.lang.Keyword"\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.lang.ATransientMap conj "ATransientMap.java" 4...

10:09 beaky: :(

10:09 ,(merge-with assoc {:a {:a 1}} {:a {:b 2}})

10:09 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: core/assoc--4130"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/assoc--4130"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.RestFn invoke "RestFn.java" 427]\n [clojure.core$merge_with$merge_entry__4637 invoke...

10:09 beaky: ok i guess merge-with merge is the way to go

10:10 powered: I'll keep on mergin

10:10 beaky: you are merging maps nested 1-level deep via merge, see :D

10:10 j-pb: you could do this, sec

10:11 beaky: ,(map merge {:a {:a 1}} {:a {:b 2}})

10:11 clojurebot: ([:a {:a 1} [:a {:b 2}]])

10:15 BRODUS: ,(take 5 (iterate identity :a))

10:15 clojurebot: (:a :a :a :a :a)

10:15 BRODUS: is there a better way of generating identity arrays than that?

10:16 something less verbose?

10:16 powered: repeat?

10:16 luma: ,(repeat 5 :a)

10:16 clojurebot: (:a :a :a :a :a)

10:16 BRODUS: ah, thanks

10:16 beaky: ,(repeat 10 ":D")

10:16 clojurebot: (":D" ":D" ":D" ":D" ":D" ...)

10:17 BRODUS: this language has too many useful functions to remember

10:17 luma: that's why we have http://clojure.org/cheatsheet

10:21 schmir: and http://conj.io

10:21 beaky: i love conj; reminds me of conjuncivitis

10:24 sunset-shimmer: test

10:26 yenda: is it possible to have both a repl and a cljs-repl running with a boot task and connect to them ?

10:26 or it doesn't even make sense ?

10:26 sunset-shimmer: justin_smith: great, I've wrote what I want with "reduce", thank you!

10:27 it is my first usage of "reduce"!

10:47 yenda: I read that boot allows you to add dependencies without restarting the repl how to you do so ?

11:01 marchelzo: hi

11:03 how do most people install clojure? just unzip it and make an alias for 'java -cp /path/to/clojure-1.7.0.jar clojure.main'?

11:03 also is that what most people use for a repl, or is there a better one with readline bindings?

11:04 MJB47: most people use leiningen for both

11:04 http://leiningen.org/

11:05 marchelzo: oh, cool

11:05 thanks

11:06 ARM9: in addition to leiningen I like setting up a clojure alias/script to the jar because lein repl takes an infuriating amount of time to start when you just want to try something quick

11:07 marchelzo: yeah I see that

11:32 justin_smith: ARM9: a similar trick is to make an uberjar, with clojure.core, plus pomegranate for adding maven (eg. clojars) deps at runtime, plus your favorite go-to libs outside core

11:44 marchelzo: how do you load a source file in the repl?

11:44 the lein repl

11:45 justin_smith: marchelzo: require, use, load, or load-file

11:45 same as in any other repl

11:45 marchelzo: I'm new to clojure in general so the fact that it's the same as any other repl doesn't make a difference :)

11:46 ARM9: (load-file "myfile.clj")

11:46 justin_smith: OK, with clojure.repl/doc you can see the docs for any of those functions

11:46 marchelzo: ok thanks!

11:47 justin_smith: marchelzo: see also clojure.repl/apropos and clojure.repl/find-doc which will search function names or docs, based on substrings or regex

11:48 marchelzo: awesome

11:49 justin_smith: also http://conj.io is a good overview of the core language with examples

11:49 marchelzo: so string literals are java.lang.Strings, but they are implicitly coerced to lists sometimes?

11:49 how can I make a list of chars be displayed as a string?

11:49 justin_smith: thanks, I think I need something like that

11:49 justin_smith: marchelzo: many sequence functions call seq on their arg

11:49 ,(seq "hello")

11:49 ARM9: they are never implicitly coerced to lists, but sometimes sequences

11:50 clojurebot: (\h \e \l \l \o)

11:50 justin_smith: ,(list? (seq "hello"))

11:50 clojurebot: false

11:50 marchelzo: ,(take 3 "hello")

11:50 clojurebot: (\h \e \l)

11:50 marchelzo: what if I want that displayed as "hel"?

11:50 justin_smith: ,(source take)

11:50 clojurebot: Source not found\n

11:50 justin_smith: ,(apply str (take 3 "hello"))

11:50 clojurebot: "hel"

11:50 justin_smith: (subs "hello" 0 3) ; more efficient

11:51 ,(subs "hello" 0 3)

11:51 clojurebot: "hel"

11:51 marchelzo: why apply str instead of just str?

11:51 justin_smith: ,(str (take 3 "hello"))

11:51 marchelzo: oh

11:51 clojurebot: "clojure.lang.LazySeq@2076e"

11:51 marchelzo: ,(str \h \e \l)

11:51 clojurebot: "hel"

11:51 marchelzo: I see

11:51 justin_smith: take 3 returns a lazy seq

11:52 and those print weird

11:52 err, those convert to string weirdly

11:53 marchelzo: unlike some functional languages (eg. haskell) a sequence of character and a string are not the same

11:53 and even in haskell they end up needing to make that distinction if they care about performance, eventually

11:54 marchelzo: right

11:54 I've never seen people complaining about clojure's strings so I assumed they didn't use list of char.

11:55 justin_smith: you can use class to find out the real jvm level class behind any piece of data

11:55 ,(class "hello")

11:55 clojurebot: java.lang.String

11:55 justin_smith: ,(class (seq "hello"))

11:55 clojurebot: clojure.lang.StringSeq

11:55 marchelzo: what would be the most idomatic way to apply a function 40 times to an argument?

11:56 TimMc: Do you want the results?

11:56 justin_smith: marchelzo: as in nested?

11:56 marchelzo: yes

11:56 to both

11:56 ARM9: what kind of function? what does it take? what does it return?

11:56 justin_smith: either (take 40 (iterate f arg)) or (nth (iterate f arg) 40)

11:56 marchelzo: its a -> a

11:56 justin_smith: depending if you want all the intermediates or not

11:57 ,(nth (iterate #(* % Math/E) 1) 40)

11:57 clojurebot: 2.35385266837019584E17

11:57 marchelzo: no just the final value; so (iterate f arg) is a lazy infinite sequence?

11:57 justin_smith: ,(take 40 (iterate #(* % Math/E) 1))

11:57 clojurebot: (1 2.718281828459045 7.3890560989306495 20.085536923187664 54.59815003314423 ...)

11:57 justin_smith: marchelzo: indeed

11:58 marchelzo: ok, thank you.

11:58 ARM9: note that you'll run into trouble if you try to use side effects

11:58 justin_smith: marchelzo: sounds like you have enough haskell background that you'll pick up clojure quickly (if you get used to the non-purity thing)

11:59 yeah, laziness and side effects don't mix very nicely, and clojure doesn't enforce keeping them separate

11:59 marchelzo: yeah I've heard that

12:00 I'm sure I'll run into it soon enough

12:00 justin_smith: for example:

12:00 ,(take 1 (map println (range)))

12:00 clojurebot: (0\nnil)

12:00 justin_smith: oh wait...

12:01 well, with the old version of range that used to be an issue :)

12:01 ,(take 1 (map println [:a :b :c :d :e :f]))

12:01 clojurebot: (:a\n:b\n:c\n:d\n:e\n:f\nnil)

12:01 justin_smith: aha! the gotcha is still there in another form

12:02 (chunking is what makes this happen)

12:04 Bronsa: ,(take 1 (map println (range 50)))

12:04 clojurebot: (0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\nnil)

12:04 Bronsa: justin_smith: (range) uses a different impl than (range n)

12:05 justin_smith: so I see

12:05 Bronsa: only the latter is chunked

12:05 justin_smith: Bronsa: were they both chunked at one time?

12:05 Bronsa: yes

12:05 pre 1.7

12:08 momerath: Is anyone using timbre and refactor-nrepl in the same file? When trying to do an extract-function (which was working a dozen dependency-changes ago), I get "<my-ns> is in a bad state! Error: No such namespace: timbre" (no relevant search results)

12:09 justin_smith: momerath: are you explicitly requiring timbre in every namespace where you use it?

12:09 momerath: what's the alternative? I'm requiring it and using the refer-timbre macro

12:10 justin_smith: momerath: some people use a namespace fully qualified, because it is required in some other ns. Which is a bad habit, though it works.

12:11 momerath: I'm guessing refer-timbre and refactor-nrepl don't play nicely. One doesnt' need refer-timbre, you can use regular require with :refer instead.

12:11 momerath: hrm- yeah, I guess I'll try that; thanks!

12:15 Bronsa: justin_smith: I might be wrong but it should be the case that the chunked pre 1.7 (range) would just reach Long/MAX_VALUE while the current non chunked version can promote to BigInt

12:16 momerath: now I just get the "bad state! Error:" with nothing after it

12:17 justin_smith: ,(nth (range) (inc' Long/MAX_VALUE))

12:17 clojurebot: #error {\n :cause "Value out of range for long: 9223372036854775808"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Value out of range for long: 9223372036854775808"\n :at [clojure.lang.RT longCast "RT.java" 1217]}]\n :trace\n [[clojure.lang.RT longCast "RT.java" 1217]\n [clojure.lang.RT intCast "RT.java" 1167]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$e...

12:17 justin_smith: I think the problem here is with nth though

12:17 Bronsa: I think so

12:17 (range) is defined as (iterate inc' 0)

12:18 ,(take 10 (nthrest (range) Long/MAX_VALUE))

12:18 clojurebot: eval service is offline

12:18 Bronsa: :(

12:18 sorry clojurebot

12:18 justin_smith: Bronsa: just tried in my repl, we'll see if it returns this year or not

12:19 Bronsa: lol

12:21 uhm, LongRange could actually be O(1) rather than O(n) on nth

12:21 aurelian: what was the name of that thing that converted _ from json to - in clojurescript? as in: server returns json {"starred_at": "2015-12-09T10:06:23Z"} I want to have it in cljs as :started-at

12:23 justin_smith: aurelian: usually json converters take an optional keywordize option, but there's also valid reason to avoid keywordizing (eg. it's much better to have "foo bar" as a key in your map, as compared to (keyword "foo bar"))

12:23 ,(keyword "foo bar") ; terrible

12:23 clojurebot: :foo bar

12:24 aurelian: hm, I have :keywordize to true

12:24 using cljs-ajax to do the api call

12:24 justin_smith: but it's not doing the _ / - conversion

12:24 aurelian: nope

12:25 I can access it as :starred_at but I think :started-at is nicer :)

12:25 not that it will make a difference, but how I would do this kind of stuff?

12:27 justin_smith: ,(keyword (clojure.string/replace (name :foo_bar) \_ \-))

12:27 clojurebot: :foo-bar

12:27 Bronsa: aurelian: https://github.com/qerub/camel-snake-kebab

12:27 justin_smith: oh yeah, that's a much better way

12:28 aurelian: cheers guys!

12:28 or gals

12:28 or both.

12:39 gfredericks: so it looks like if you accidentally with-redefs a macro you end up permanently unmacrofying it

12:51 yenda: Anybody here is using the system library ?

12:51 danielsz/system

12:54 I'm trying to figure out how I can pass one of my system component to a function I call in my ring app

12:54 in this case it is the db so that i can use the connection in the function

12:56 mavbozo: gfredericks, in my imagination, macro ~ expansion , unmacro ~ contraction, so all macro-expanded code gets contracted

13:00 justin_smith: gf~.

13:01 gfredericks: oops - you should be able to put the :macro metadata back on it, no?

13:01 as long as you didn't mess with the first two magic args

13:01 marchelzo: if i use 'lein deps' to download a dependency, is there a way to load it in the repl?

13:02 justin_smith: marchelzo: lein deps just puts the thing in your local package cache, in order to do the normal require you also need to add it to the classpath

13:02 MJB47: (use '[clojure.data.json :as json])

13:02 obviously use whichever library you are actually using

13:03 justin_smith: there are libs like pomegranate and pallet/alembic that are designed to do both the download and the adding to classpath at runtime

13:03 MJB47: that only works if the dep is on your classpath already

13:03 MJB47: does lein deps not add to classpath?

13:03 justin_smith: MJB47: all lein deps does is download all deps to local cache that are implied by project.clj

13:04 MJB47: update project.clj -> lein deps -> lein repl has always worked properly for me

13:04 justin_smith: MJB47: so if you already had a repl running, that dep is not added to the running repl

13:04 MJB47: oh ye

13:04 need a new repl

13:04 justin_smith: right

13:05 so I might be reading too much into the question - I thought "adding the dep to a running repl" was implied

13:05 MJB47: i assumed the opposite

13:05 oh well

13:06 gfredericks: justin_smith: yeah, I think you could fix it fine by calling .setMacro afterwards

13:06 but it's super confusing

13:06 I made http://dev.clojure.org/jira/browse/CLJ-1867

13:06 justin_smith: yeah, that is an odd behavior

13:06 gfredericks: (which includes the root cause)

13:11 casey1: quite

13:34 wolgo: '/help

15:58 lxsameer: hey folks, I'm looking for a free PaaS for my clojure aoo

15:58 *app

15:58 MJB47: try heroku

16:00 lxsameer: MJB47: heroku has limitations

16:01 MJB47: i doubt you will find a free one without

16:01 lxsameer: MJB47: openshift limiation is kind of nice, but It does not support clojure by default

16:02 celwell: elastic beanstalk micro instance should be free for a year i think

17:07 mjg: Hi! Can I use 'binding' to bind a dynamic var in another ns when the name of the ns is passed to me as a string?

17:08 justin_smith: only if you use eval I think

17:09 mjg: like (binding [*ns* (create-ns 'other-ns) other-ns/*foo* "hello"] (eval (read-string "*foo*"))) ?

17:09 justin_smith: umm... what are you trying to do here?

17:11 mjg: I'm writing a small lazybot-esque thing.

17:12 So, each time my fn is called, there's a string which is the form to evaluate, a string which is the chatroom-name and a string which is the name of the user who spoke to the bot.

17:13 I'd like to eval the form in a ns which is named after the chatroom, with that-chatroom/*me* bound to the user's name.

17:15 justin_smith: so far https://gist.github.com/mjg123/a1dca856cd08682f5676 works, but with only one ns.

17:21 justin_smith: mjg: what about using in-ns inside the eval'd code?

17:22 eg (eval (concat '(in-ns user-specific-ns) user-code))

17:22 or maybe that's missing some parens

17:23 mjg: Where can I re-bind the *me* var in user-specific-ns in that case?

17:23 * mjg goes to try that suggestion, thanks.

17:23 justin_smith: mjg: you can use intern to set the binding

17:24 mjg: justin_smith: can you use intern like that?!

17:24 justin_smith: ,(intern 'foo.bar 'baz "hello")

17:24 clojurebot: #error {\n :cause "No namespace: foo.bar found"\n :via\n [{:type java.lang.Exception\n :message "No namespace: foo.bar found"\n :at [clojure.core$the_ns invokeStatic "core.clj" 4011]}]\n :trace\n [[clojure.core$the_ns invokeStatic "core.clj" 4011]\n [clojure.core$intern invokeStatic "core.clj" 6047]\n [clojure.core$intern invoke "core.clj" -1]\n [sandbox$eval25 invokeStatic "NO_SOURCE_FILE"...

17:25 justin_smith: mjg: oops - ns has to exist first

17:25 ,(in-ns 'foo.bar)

17:25 clojurebot: #object[clojure.lang.Namespace 0x6c822bda "foo.bar"]

17:25 justin_smith: ,(intern 'foo.bar 'baz "hello")

17:25 clojurebot: #'foo.bar/baz

17:25 justin_smith: ,[*ns* foo.bar/baz]

17:25 clojurebot: [#object[clojure.lang.Namespace 0x1227d02b "sandbox"] "hello"]

17:26 justin_smith: so we are still in sandbox (one clojurebot query does not use the ns another creates) but I was able to create foo.bar/baz from sandbox

17:27 mjg: but that's not a dynamic binding is it? All threads will see the interned value.

17:27 justin_smith: mjg: the var belongs to a specific ns

17:29 mjg: I think I need to use 'binding' to avoid different users seeing each other's names (each incoming request is handled by a separate thread_

17:30 justin_smith: they can't have their own namespaces?

17:30 mjg: users? no

17:30 I want one ns per room.

17:31 justin_smith: mjg: you can create the dynamic var with no root binding, then bind it explicitly

17:32 mjg: justin_smith: inside the 'eval ?

17:32 justin_smith: I think so, yeah

17:32 mjg: OK let me experiment with that. Thanks for your help.

17:32 justin_smith: because eval doesn't use your local environment really

17:32 sdegutis: Is there a nicer way to do (->> (for [x] (if? (f x) (g x))) (remove nil?))

17:33 Notice how technically my question still ends in a question mark.

17:33 justin_smith: (keep #(when (f %) (g %)) coll)

17:34 ,(keep #(when (even? %) (inc %)) (range))

17:34 clojurebot: (1 3 5 7 9 ...)

17:34 amalloy: what on earth is if?

17:35 also what is (for [x] ...)

17:35 justin_smith: amalloy: I was going to ask what (for [x] was...

17:35 heh

17:47 ,(defmacro if? [& body] `(boolean (if ~@body)))

17:47 clojurebot: #'sandbox/if?

17:47 justin_smith: ,(if? true 42)

17:47 clojurebot: true

17:51 sdegutis: Thanks justin_smith

17:52 amalloy, justin_smith: It seems I am not fully with it right now.

18:05 rkpaul: I'm trying to reify a class where I have the classname in a string: (reify (resolve (symbol myclassname)) (apply [this, x] "a")) But I'm getting an error message: ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol What am I doing wrong?

18:07 alive876: hi, newbie here, i get this error Could not find artifact secretary:secretary:jar:“1.2.3” , my project.clj is: http://pastebin.com/Vdmn3z9n thanks much!

18:07 amalloy: rkpaul: "trying to reify a class where I have the classname in a string" is the wrong part

18:07 rkpaul: amalloy: wrong part as in that's not causing the error?

18:08 amalloy: as in you can't do that

18:08 rkpaul: ah ok

18:08 amalloy: i mean, it's not impossible but

18:08 it's not easy

18:08 rkpaul: so let's say that I have four different java classes and I want to pick which one to use there based on some predicate... would I be better off just doing a switch statement kind of thing?

18:09 amalloy: yes

18:09 rkpaul: ok thanks

18:11 WorldsEndless: Anyoen have recommendations on debugging a "Exception in thread "main" java.lang.ExceptionInInitializerError" when trying to run my uberjar?

18:13 mjg: justin_smith: So I can't get that to work :( the problem AIUI is that you can't put the 'binding' call inisde the 'eval' cos then you lose access to the outer scope.

18:15 justin_smith: I think I need to create the bindings then eval the code w/those bindings active. But I just can't see how to bind a var in an ns when IDK the name of the ns until runtime.

18:26 justin_smith: mjg: clearly the binding has to also be inside the eval

18:27 sdegutis: Will #(foo %) late-bind so that if I change the function that #'foo points to, my anonymous function will call the new one?

18:27 Thanks in advance. Regards.

18:33 justin_smith: sdegutis: yes, #(foo %) will see new values for foo - the way you get the "stuck" version is if you have ((fn [f] #(f %)) foo)

18:37 sdegutis: justin_smith: why is that?

18:37 justin_smith: sdegutis: ((fn [f] #(f %)) foo) - the function that generates that function never sees the var, just the value of the var

18:37 as opposed to #(foo %) - that actually sees the var

18:39 sdegutis: Oooooh.

18:39 Thank!

19:36 slester: Newb here, trying to (dissoc hashed-map '(list of keywords)) -- is there a way to make that possible? do I need to (apply #(dissoc hashed-map %1) '(list))?

19:37 err, reduce I guess.

19:41 got it, sorry, nvm!

20:02 amalloy: slester: i'd use apply

20:02 (apply dissoc m kws)

20:04 slester: amalloy: thanks!

20:11 sdegutis: justin_smith: it still doesn't make sense to me though

20:11 ((fn [f] #(f %)) foo)

20:11 Isn't writing "foo" just referencing a var?

20:11 justin_smith: So that the anonymous function receives a far?

20:11 *var

20:30 tolstoy: slester You could also use "select-keys" to keep the ones you want.

20:30 BTW, clojure.set.rename-keys -> super handy when you need it.

20:47 BRODUS: one thing im confused about: i read its idiomatic to use vectors in clojure over lists, im currently doing that but im having issues because map, filter, etc.. return lazy sequences which behave like lists, so how do I use map, filter, etc.. without having to use (into [] result) after each one?

20:49 sumobob: whats the clojure equivalent of pushing to an array?

20:49 tolstoy: BRODUS Try mapv and filterv?

20:49 BRODUS: ,

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

20:50 tolstoy: ,(map inc [1 2 3])

20:50 clojurebot: (2 3 4)

20:50 tolstoy: ,(mapv inc [1 2 3])

20:50 clojurebot: [2 3 4]

20:51 BRODUS: ah ok, so that means that i lose the benefits of a lazy sequence then

20:53 tolstoy: Oh, mapv isn't lazy?

20:54 TEttinger: map is. mapv isn't.

20:54 tolstoy: BRODUS: I just use regular lists can convert to a vector only at the end, when I actually need it. (->> (map this seq) (filter that) (reduce whatever) vec).

20:54 sumobob: what is the difference between "a" and \a

20:55 ,(type "a")

20:55 clojurebot: java.lang.String

20:55 sumobob: ,(type \a)

20:55 tolstoy: sumobob First is a string type, the second a char type.

20:55 clojurebot: java.lang.Character

20:55 BRODUS: ,(seq? "a")

20:55 clojurebot: false

20:55 BRODUS: ,(coll? "a")

20:55 clojurebot: false

20:56 sumobob: hmm, i'm trying to do a case statement based on a char, but its not being too friendly with me

20:58 TEttinger: sumobob: there may be a better fit than case

20:59 amalloy: BRODUS: it's certainly not "idiomatic to use vectors instead of lists" in general

20:59 sumobob: I'm working on some problems from a site called adventofcode.com

21:00 amalloy: it's just like when you are typing a list literal into code you'd usually use a vector. when you're building a data structure at runtime, pick the one that has the performance characteristics you want

21:00 sumobob: its basically a massive string like ">>><<v^" which needs to be used as directions, go left, go right etc etc

21:00 TEttinger: which day?

21:00 sumobob: day 3

21:01 I'm doing it recursively

21:01 i have a function that takes a string and an array

21:02 based on the first char of the string, i conj a new object onto the array and call my function again with (rest string)

21:09 BRODUS: amalloy: i agree. I was trying to understand what rich said here: http://stackoverflow.com/questions/1147975/in-clojure-when-should-i-use-a-vector-over-a-list-and-the-other-way-around but i guess "idiomatic" was the wrong word

21:10 amalloy: well yes, you don't super often build lists. but you build seqs all the time

21:14 TEttinger: ,(let [input ">>><<v^"] (count (distinct (reduce (fn [[latest & others :as houses] dir] (conj houses (condp = dir \< (update-in latest [0] dec) \> (update-in latest [0] inc) \^ (update-in latest [1] inc) \v (update-in latest [1] dec)))) '([0 0]) input))))

21:14 clojurebot: 5

21:14 TEttinger: fun

21:40 devn: so, it's been awhile since i looked at this

21:41 but im puzzling a little bit. i don't recall why (+) is the right thing here:

21:41 TEttinger: hey devn

21:41 devn: ,(#(`[[~@%&]] (+)) "A")

21:41 clojurebot: ["A"]

21:41 TEttinger: ,(+)

21:41 clojurebot: 0

21:41 devn: wait, don't finish that thought -- staring at it

21:42 TEttinger: oh I know

21:42 ,(#(`[~@%&]) "A")

21:42 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: PersistentVector"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) 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" 28]\n [sandbox$eval77$fn__78 doInvoke "NO_SOURCE_FILE" 0]\n [...

21:43 TEttinger: see, otherwise it would try to call the vector instead of returning the 0th element of a nesting vector

21:43 ,((fn [& args] [args] 0) "A")

21:43 clojurebot: 0

21:44 TEttinger: ,((fn [& args] ([args] 0)) "A")

21:44 clojurebot: ("A")

21:44 TEttinger: a little more clear why it does what it does, devn?

21:44 devn: haha, im feeling a little slow right now

21:44 im trying to walk it through in my head

21:45 justin_smith: ,(/ (+))

21:45 clojurebot: #error {\n :cause "Divide by zero"\n :via\n [{:type java.lang.ArithmeticException\n :message "Divide by zero"\n :at [clojure.lang.Numbers divide "Numbers.java" 158]}]\n :trace\n [[clojure.lang.Numbers divide "Numbers.java" 158]\n [clojure.lang.Numbers divide "Numbers.java" 3784]\n [clojure.core$_SLASH_ invokeStatic "core.clj" 994]\n [clojure.core$_SLASH_ invoke "core.clj" -1]\n [sandbox$ev...

21:45 TEttinger: ,(#([%&] (+)) "A")

21:45 clojurebot: ("A")

21:45 devn: nono, i get the identity thing for (+)

21:45 justin_smith: devn: I just thought (/ (+)) was a funny way to get a divide by 0

21:45 devn: :D

21:46 ,(/(*)(+))

21:46 clojurebot: #error {\n :cause "Divide by zero"\n :via\n [{:type java.lang.ArithmeticException\n :message "Divide by zero"\n :at [clojure.lang.Numbers divide "Numbers.java" 158]}]\n :trace\n [[clojure.lang.Numbers divide "Numbers.java" 158]\n [sandbox$eval206 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval206 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6943]\n [clojure.la...

21:46 justin_smith: ,(/ (*))

21:46 TEttinger: it's because you can't use alphanumerics in swearjure, and 0 is numeric

21:46 clojurebot: 1

21:46 devn: googly eyes

21:46 TEttinger: it's getting the 0th element of the vector

21:46 that contains a vector of all args passed to it

21:46 devn: why does it need the nesting?

21:46 TEttinger: (where it is the anon fn)

21:47 justin_smith: devn: it needs to become a vector

21:47 TEttinger: ,(#(`[~@%&] 0) "A")

21:47 clojurebot: "A"

21:47 devn: well the unquote splicing

21:47 ahh right

21:47 ok ok

21:47 TEttinger: ,(#(`[~@%&] 0) "A" "B")

21:47 clojurebot: "A"

21:47 TEttinger: ,(#(`[[~@%&]] 0) "A" "B")

21:47 clojurebot: ["A" "B"]

21:47 devn: yes, that's what i needed, makes good sense now

21:47 TEttinger: cool

21:47 swearjure is nice and mindbending

21:48 devn: here's the other one from the same post, weirder still

21:48 justin_smith: ~(#(`[~@%&] 0) "A") makes good sense

21:48 clojurebot: Excuse me?

21:48 justin_smith: haha

21:48 devn: ,(#(`[{~% ~@%&}] (+)) :a 1)

21:48 clojurebot: {:a 1}

21:49 devn: "The Clojure reader enforces all hash maps to contain an even element of arguments—even if the element is going to be unquote spliced. I'm not sure if this is a bug in Clojure or me pushing the limits of what the Clojure reader is supposed to support, though I wouldn't be surprised if it is the latter."

21:49 so, were it not for that limitation, it would be the same as vector, but with no ~% in the key position

21:50 (i think)

21:50 hyPiRion: *waves*

21:51 i kinda like the symmetry of:

21:51 ,(#(`[{~@%& ~@%&}] (+)) :a 1)

21:51 clojurebot: {:a 1}

21:51 justin_smith: ,{#_ foo :a 0}

21:52 clojurebot: {:a 0}

21:52 devn: one fun bit about that is, even though you can't rely on the ordering of maps:

21:52 ,(#(`[{~@%& ~@%&}] (+)) :a 1 :b 2 :c 3)

21:52 clojurebot: {:c 3, :b 2, :a 1}

21:52 devn: ,{:a 1 :b 2 :c 3}

21:52 clojurebot: {:a 1, :b 2, :c 3}

21:52 devn: btw: hi TEttinger :)

21:52 aloha justin_smith

21:53 TEttinger: hallo!

21:53 justin_smith: zdrasvitye

21:53 devn: something clojure this way comes

21:55 sumobob: wtf

21:56 devn: what y'all hackin' on these days?

21:56 sumobob: ,(- 1 0)

21:56 clojurebot: 1

21:56 sumobob: ,(- 0 1)

21:56 clojurebot: -1

21:56 sumobob: whaaat

21:56 justin_smith: ,(- 3 2 1)

21:56 clojurebot: 0

21:56 sumobob: can someone explain this for me?

21:56 justin_smith: sumobob: 0 - 1 is -1

21:56 devn: 1 - 0 = 1

21:56 0 - 1 = -1

21:57 sumobob: what'd you expect?

21:57 ,(< 1 0)

21:57 clojurebot: false

21:57 devn: ,(> 1 0)

21:57 clojurebot: true

21:57 sumobob: for some reason i just thought it would subtract everything haha

21:58 but yeah operational order matters lol

21:58 devn: the lt and gt operators will never get easier for me

21:58 justin_smith: devn: the height moves in the direction of the size of the numbers

21:58 > lower to the right, just like the numbers

21:58 ,(> 5 4 3 2 1 0 -1)

21:58 clojurebot: true

21:59 justin_smith: < higher to the right, just like the numbers

21:59 devn: yeah yeah i know, but man, to think of "the larger number eats the smaller number" from 1st grade in order to remember that kills me

21:59 justin_smith: ,(< 0 1 2 3)

21:59 clojurebot: true

21:59 devn: i haven't golfed in awhile, have been missing it

21:59 justin_smith: devn: no eating - it's a graph of the numbers in the argument list

21:59 line graph

21:59 devn: justin_smith: ah, that's actually a better way of thinking about it

21:59 thanks

22:00 justin_smith: np

22:00 devn: im pretty anti-golf these days

22:00 i prefer explicit (fn [...] ...) over (partial ...)

22:00 justin_smith: devn: oh, I don't golf in real code

22:00 devn: (in shared code that is)

22:01 it kills me when i see a partial, and it's not immediately obvious if it's going to take & args, arg1 arg2, etc.

22:02 i also have pretty much stopped using #()

22:02 justin_smith: if only partial was curry - then you know it always takes exactly one more arg

22:02 devn: explicit fn all the time

22:02 justin_smith: *nod*

22:02 speaking of shared code, programming on a team, etc...

22:03 is there any hope, do y'all think, that we'll ever get a set of standard map-processing functions in core?

22:03 (map-keys) (map-vals) (filter-keys) (filter-vals) (filter-kvs) (map-kvs) etc.

22:05 jhn: all of that is just one reduce away

22:05 devn: that, and as long as im ranting and raving: when are transients gonna get some love? no update! update-in! etc.

22:06 jhn: oh im aware, but when i see people write them, they often forget they can use a transient, or don't use reduce-kv

22:06 it'd be so much nicer if they just lived in core

22:06 no "here, i wrote this utility library that adds functions that ought to be in core"

22:06 jhn: yeah. the one i always see myself reimplementing is map-vals

22:07 amalloy: just use into

22:07 i mean it'd be nice if map-vals existed, but if you implement it yourself use into instead of reduce

22:08 jhn: is this not idiomatic? https://github.com/jhn/tobias/blob/master/src/tobias/util.clj#L17-L18

22:08 devn: amalloy: why not reduce-kv with a transient persistent! around it?

22:08 amalloy: because into already does the transient part

22:09 devn: but it won't work recursively right?

22:09 because the submaps aren't ieditable?

22:09 * devn goes back to ranting about the state of transients in clojure

22:11 devn: ,(let [x (transient {:a 1 :b 2 :c {:d 3}})] (type (:c x)))

22:11 clojurebot: clojure.lang.PersistentArrayMap

22:11 devn: :((((

22:12 i think cgrande wrote something about this a long while back

22:12 ah, im thinking of https://github.com/cgrand/megaref

22:13 perhaps specter is closer to what im after in that case

22:19 mgaare: Yeah, transients aren't recursive like that. Ran into that problem too

22:20 devn: I sat down and started writing a thing to handle the recursive case, but it got ugly quick

22:21 cant remember the exact situation i was in -- pretty sure i was making something that'd give the person using the function the /choice/ of whether they wanted to pass a transient or not

22:21 which meant switching out assoc! for assoc, etc.

22:39 domgetter: Do for loops not work inside go blocks?

22:40 amalloy: ~for

22:40 clojurebot: for is like doseq, but for values instead of side effects

22:40 domgetter: (go (for [x (range 1 10)] (>! c x))) doesn't seem to put anything on channel c

22:40 justin_smith: domgetter: for is lazy

22:40 use doseq there

22:40 devn: domgetter: what happens if you wrap (for ...) with (doall ...)

22:40 justin_smith: for is only for generating values

22:40 devn: but also yes, doseq.

22:41 it's been awhile since i've used core.async

22:41 what does (>! c x) return? a channel?

22:41 justin_smith: devn: nil

22:41 devn: ah

22:41 go returns a chan though

22:41 right?

22:41 clojurebot: right is not wrong

22:42 justin_smith: devn: right, it would either return a list of nils or if you switch for with doseq it would return a single nil

22:42 s/list/seq of course

22:42 domgetter: got it, thank you

22:43 justin_smith: domgetter: I think devn had a point there - if you had read from the channel returned by go, you would get a lazy-seq, and for each value you consumed you would likely make one of those >! calls happen - but doeseq is the right way to do what you are doing there

22:45 or wait, the !> would try to happen in the context where you read the value, which if it was not inside another go block would be a weird error

22:46 devn: ah, now im remembering more transient weirdness

22:46 domgetter: Yea I kept getting cannot convert ISeq to ManyToMany errors

22:46 devn: ,(require '[clojure.walk :as walk])

22:46 clojurebot: nil

22:46 devn: ,(walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})

22:46 clojurebot: #object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x6c509ac3 "clojure.lang.PersistentArrayMap$TransientArrayMap@6c509ac3"]

22:46 devn: ,(def transients-all-the-way-down (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})b)

22:46 clojurebot: #error {\n :cause "Too many arguments to def"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Too many arguments to def, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.RuntimeException\n :message "Too many arguments to def"\n :at [clojure.lang.Util runtimeException "Util.jav...

22:47 devn: ,(def transients-all-the-way-down (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}}))

22:47 clojurebot: #'sandbox/transients-all-the-way-down

22:47 devn: ,(defn transient? [x] (instance? clojure.lang.ITransientCollection x))

22:47 clojurebot: #'sandbox/transient?

22:49 justin_smith: devn: I wonder how the time spent checking for transient status or not compares to the time saved by using transients

22:49 devn: ,(walk/postwalk (fn [x] (if (transient? x) (persistent! x) x)) transients-all-the-way-down)

22:49 clojurebot: {:a 1, :b #object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x247c1594 "clojure.lang.PersistentArrayMap$TransientArrayMap@247c1594"]}

22:51 devn: not sure why that's the case -- postwalk should hit {:g 6}, {:e 4 :f {:g 6}}, {:c 3 :f {e 4 :f {:g 6}}, and then the top level

22:51 justin_smith: sure, but it didn't print readable

22:51 devn: i would have expected the whole thing to be persistent at that point

22:52 justin_smith: or are you saying the top level one should be transient too?

22:52 right

22:52 devn: either that's a bug, or im doing it wrong

22:52 justin_smith: ,(walk/postwalk (fn [x] (if (transient? x) (persistent! x) x)) [transients-all-the-way-down])

22:52 clojurebot: #error {\n :cause "Transient used after persistent! call"\n :via\n [{:type java.lang.IllegalAccessError\n :message "Transient used after persistent! call"\n :at [clojure.lang.PersistentArrayMap$TransientArrayMap ensureEditable "PersistentArrayMap.java" 457]}]\n :trace\n [[clojure.lang.PersistentArrayMap$TransientArrayMap ensureEditable "PersistentArrayMap.java" 457]\n [clojure.lang.ATransient...

22:53 justin_smith: oh, right, that was a side effect

22:54 devn: well, i got further :)

22:54 ,(let [transients (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})] (walk/postwalk (fn [x] (if (transient? x) (persistent! x) x)) (persistent! transients)))

22:54 clojurebot: {:a 1, :b {:c 3, :d #object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x5a88a5eb "clojure.lang.PersistentArrayMap$TransientArrayMap@5a88a5eb"]}}

22:58 justin_smith: devn: I don't think postwalk can do it properly because it doesn't know how to walk down into the transients, but a pre-walk could do it

22:59 devn: oh duh, right

22:59 weird, wonder how i missed that...

23:00 i could swear i tried a prewalk

23:00 ,(let [transients (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})] (walk/prewalk (fn [x] (if (transient? x) (persistent! x) x)) transients))

23:00 clojurebot: #error {\n :cause "No such namespace: walk"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such namespace: walk, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "No such namespace: walk"\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]...

23:00 devn: ,(require '[clojure.walk :as walk])

23:00 clojurebot: nil

23:00 devn: ,(defn transient? [x] (instance? clojure.lang.ITransientCollection x))

23:00 clojurebot: #'sandbox/transient?

23:00 devn: ,(let [transients (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})] (walk/prewalk (fn [x] (if (transient? x) (persistent! x) x)) transients))

23:00 clojurebot: {:a 1, :b {:c 3, :d {:e 4, :f {:g 6}}}}

23:01 devn: huzzah

23:05 justin_smith: I have the same question as you about performance

23:05 that check isn't free

23:05 quite the opposite

23:09 ,(dotimes [_ 1000] (time (let [transients (-> {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}} (update-in [:b :d :f] transient) (update-in [:b :d] transient) (update-in [:b] transient) transient)] (-> transients persistent! (update-in [:b] persistent!) (update-in [:b :d] persistent!) (update-in [:b :d :f] persistent!)))))

23:09 clojurebot: "Elapsed time: 0.323082 msecs"\n"Elapsed time: 0.173159 msecs"\n"Elapsed time: 0.174552 msecs"\n"Elapsed time: 0.166604 msecs"\n"Elapsed time: 0.162875 msecs"\n"Elapsed time: 0.162494 msecs"\n"Elapsed time: 0.162726 msecs"\n"Elapsed time: 0.153142 msecs"\n"Elapsed time: 0.156263 msecs"\n"Elapsed time: 1.078818 msecs"\n"Elapsed time: 0.164292 msecs"\n"Elapsed time: 0.16227 msecs"\n"Elapsed time: 0....

23:10 devn: ,(dotimes [_ 1000] (time (let [transients (walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})] (walk/prewalk (fn [x] (if (transient? x) (persistent! x) x)) transients))))

23:10 clojurebot: "Elapsed time: 0.986332 msecs"\n"Elapsed time: 0.461197 msecs"\n"Elapsed time: 86.447148 msecs"\n"Elapsed time: 0.458364 msecs"\n"Elapsed time: 0.456384 msecs"\n"Elapsed time: 0.456643 msecs"\n"Elapsed time: 0.473551 msecs"\n"Elapsed time: 0.457109 msecs"\n"Elapsed time: 0.457108 msecs"\n"Elapsed time: 0.482885 msecs"\n"Elapsed time: 0.549637 msecs"\n"Elapsed time: 0.459312 msecs"\n"Elapsed time: ...

23:10 devn: A very poor man's benchmark, but I'm seeing ~0.03msecs for the post/pre

23:11 0.01msecs for the straight ahead update-in

23:11 so, specter... :D

23:16 https://gist.github.com/devn/b195dbc67a320021057c here if someone is interested in tinkering with it, would be interested to see other approaches

23:37 domgetter: Is there a way to ask the result of make-array for its size?

23:37 (assert (= 3 (size (make-array Long/TYPE 3))))

23:38 what goes here? ^

23:39 got it. It's alength

23:39 justin_smith: domgetter: count

23:40 domgetter: count also works. are they synonymous?

23:40 justin_smith: ,(count (make-array Long/TYPE 3))

23:40 clojurebot: 3

23:40 justin_smith: domgetter: count is more general

23:40 domgetter: ah okay. Thank you

23:40 justin_smith: ,(count "hello, world!")

23:40 clojurebot: 13

23:40 justin_smith: ,(alength "hello, world!")

23:40 clojurebot: #error {\n :cause "No matching method found: alength"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching method found: alength"\n :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]}]\n :trace\n [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 80]\n [clojure.lang.Reflector invokeStaticMethod "Reflector.java" 207]\n [sandbox$eval73 invo...

23:53 lambda-11235: How do clojurebot's error messages work? Is there a library to do that?

23:54 justin_smith: the message is exactly how exception objects are printed since 1.7

23:56 it was better back when it was just the message - because with a bot we really don't want or need the stack trace

Logging service provided by n01se.net