#clojure logs

2015-12-10

00:09amalloywell it wasn't exactly a real question, so much as a social commentary on your asking how people remember things
00:51TEttingerok, that's an exciting outcome...
00:52TEttingerI am evaluating YourKit, justin_smith I'm blaming you if it isn't fantastic, but it seems rather great so far
00:53TEttingerfound 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.
00:54TEttingerthe 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
00:55TEttingerand internally all that does is System.arraycopy
00:57TEttingerso... does anyone know if having low memory available to the program would explain the array copy being slow?
01:39wolgoHi. 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.
01:56TEttingerwolgo: there's brave clojure, several other good physical books
01:56TEttinger~brave clojure
01:56clojurebotTitim gan éirí ort.
01:56TEttinger~brave
01:56clojurebotbrave is http://www.braveclojure.com/
02:39wolgoTEttinger: okay cool, I have been perusing that one
02:40wolgoTEttinger: thank you
02:40TEttingerhope you find it useful!
02:47BRODUSsay i want each of my list items to be an argument to a function call, is there a macro that will do that?
02:48amalloy(doc apply)
02:48clojurebot"([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."
02:50BRODUS(apply (map identity) '(1 2 3 4))
02:50amalloywell, close. you mean (apply map identity '(1 2 3 4))
02:50amalloyor, well, you don't even mean that, because that's just (map identity 1 2 3 4), which doesn't work
02:51BRODUSok i think i get it
02:52opqdonut,(apply map + [[1 2 3] [4 5 6] [7 8 9]])
02:52clojurebot(12 15 18)
03:33slawohey everyone, quick question about profiling a clojure app
03:33slawoI got myself visual vm open
03:33slawoconnect to a repl session
03:34slawoand cpu-sample while I run (dotimes [n 1e8] (my-thing))
03:35slawovisual vm starts producing data alright
03:35TEttingercriterium is best for benchmarking
03:35opqdonutyeah but profiling /= benchmarking
03:35TEttingeryeah
03:36TEttingernot sure what the question would be
03:36slawobut of course the functions with most self-time are my-ns.$eval12334$fn__3434.invoke()(
03:36opqdonutjvisualvm is nice, but you usually need to filter out lots of classes/packages to get a result you can actually interpret
03:36opqdonutslawo: if (my-thing) is an actual function in an actual namespace, it will show up as my-ns$my-thing or so
03:37opqdonutthe evalXXXXX basically refers to the line you typed into your repl
03:37slawocool
03:37slawoany way to get those fn__3434334’s sorted?
03:38slawoI assume they are inner functions
03:38opqdonutthey're closures yeah
03:38slawoany way to identify which ones?
03:38slawolike attaching metadata to them or something
03:38riceandbeansbrave clojure is confusing the hell out of me
03:39opqdonutslawo: 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
03:40slawoso it’s not common to use closures in clojure?
03:41riceandbeanswhat is a closure?
03:41slawoI 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?
03:41amalloyslawo: look more closely at the names of the functions. they'll indicate what top-level var they're apart of
03:41slawoamalloy: cool, so the numbers mean something?
03:41amalloy,(class ((fn foo [] ((fn inner [] inner)))))
03:42clojurebotsandbox$eval25$foo__26$inner__27
03:42amalloynot really, no
03:42amalloybut look at this classname
03:42slawolet me see…
03:42amalloy,(defn f [] ((fn foo [] ((fn inner [] inner)))))
03:42clojurebot#'sandbox/f
03:42amalloy,(class (f))
03:42clojurebotsandbox$f$foo__53$inner__54
03:43amalloyyou 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
03:45slawolet me see if I can name them
03:48slawoamalloy: any idea what a …$G__3434_1234.invoke() is?
03:48slawothe G prefix is different from a fn prefix
03:49amalloy,(class #(inc))
03:49clojurebot#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...
03:49TEttingerprobably a symbol
03:49lumait's a symbol from (gensym)
03:49amalloy,(class #(+ 1 2))
03:49clojurebotsandbox$eval128$fn__129
03:49amalloyyeah, what luma said
03:49TEttinger,(let [m# 2] (class m#))
03:49clojurebotjava.lang.Long
03:50TEttinger,(let [m# #(+ %1 2)] (class m#))
03:50clojurebotsandbox$eval179$m_SHARP___180
03:50TEttingernooo....
03:50TEttingerautogensym doesn't do it?
03:50TEttinger,(gensym +)
03:50clojurebotclojure.core$_PLUS_@378fdfe1207
03:51TEttinger,(gensym ++++)
03:51clojurebot#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...
03:51amalloyTEttinger: # only does anything inside `
03:51TEttinger,(gensym #(+ 1 2))
03:51clojurebotsandbox$eval253$fn__254@22ed95cd257
03:54slawoall of my slow spots are $G__somethings :)
03:55jonathanjso 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
03:55amalloywell, figure out what they're inside of
03:55amalloysome macro is generating functions
03:55ashwink005has anyone worked with clout?
03:56ashwink005is there any support for regex?
04:10BRODUSI 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' ?
04:11MJB47depends what you want the values to be
04:11BRODUSdoesn't matter
04:12MJB47then i dont see why you want a hashmap?
04:12lumawhy do you want a hashmap then?
04:13BRODUSi want to later filter another list based on the items presence in the hashmap
04:13lumause a set
04:13MJB47why cant you do that with a vector or set?
04:13MJB47or even the list
04:14slawoprismatic have https://github.com/Prismatic/plumbing/blob/master/src/plumbing/core.cljx#L86 this for this purpose
04:14BRODUSusing a set makes sense
04:15slawobtw. my mysterious G__ appears to be the function dispatch of defprotocol
04:17slawoshame functions in defprotocol appear as fn_123213, even though they clearly are named
04:19slawoand 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
04:30noncomslawo: i never use protocols though many say them are good things.. i don't mind, but i just don't use them
04:31slawononcom: they are brilliant for polymorphism
04:31slawobut you better not have any polymorphism in your cricical paths :)
04:32noncomyeah! well, i deal with polymorphism differently, mostly avoiding it
04:33slawononcom: but it’s tempting to use language facilities, no? :)
04:34noncomslawo: not really..
04:34clojurebotexcusez-moi
04:34noncomslawo: such a dispatch can be explained by a lesser set of "facilities"
04:35TrioxinI 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.
04:35noncomlike, reduced to simple operations, without getting a whole other paradigm into the business
04:35noncomslawo^
04:36slawononcom: 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’
04:36noncomslawo: maybe, maybe.. but in such cases i just group them in {}s
04:37noncomsee, no garbling of names, no hassle behind the scene..
04:37slawoI suppose :)
04:37slawoerlang is a bit like that no?
04:37noncomyeah
04:37noncoma bit :)
04:37slawomy_thing = [:type_of_thing what ever else]
04:38slawoand then you just match on the first field :)
04:38slawoeverywhere :)
04:40noncomslawo: yep, like that too
04:44noncomTrioxin: 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?
04:46Trioxinnoncom, 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.
04:47noncomthen what's the problem?
04:47noncomit looks pretty straightforward...
04:48noncomyou won't need an applet if the wrapper is about wrapping the browser in java app
04:48noncomi think you'll simply need a java app
04:49Trioxinnoncom, 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.
04:51Trioxinnoncom, 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.
04:52noncomi 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!
04:52Trioxinnoncom, 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.
04:53Trioxinnoncom, nwjs.. not a browser
04:54noncomokay, 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
04:54Glenjaminclojurescript is the key point here
04:54noncomam i wrong?
04:54Glenjaminyou said clojure initially, but then mentioned cljs
04:55noncomyeah, with clojurescript there's a tonn more variables
04:56Trioxinnoncom, 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.
04:57noncomhmmmm sounds convoluted ..
04:57Trioxinnoncom, 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
04:58noncomi think it is very unfeasible to manipulate dom from java
04:58TrioxinI'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.
04:59Trioxinnoncom, they interop
04:59Trioxini could interop with node but I don't want a step in the middle
05:00noncomyes, 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?
05:00Trioxinnoncom, the GUI will enable the user to make use of the jar
05:01Trioxini don't want to make my gui in clojure. I want to use nwjs for several reasons.
05:02noncomokay, i understand..
05:02noncomTrioxin: did you think about creating a clojure app that serves a web gui?
05:03noncomthat would be far more straightforward
05:04Trioxinnwjs 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.
06:14BRODUShas anyone else had trouble getting popup clojure documentation to work in emacs?
06:26ashwink005anyone used nginx?
06:42ARM9what's the easiest way to use antlr to generate a parser in a lein project?
06:47yendapeople use lein template to make boot templates ?
07:45jonathanjwhy 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?
07:46jonathanj`thrower` is invoked but apparently trying to rethrow that exception does nothing
07:46justin_smithjonathanj: you don't get the exception until you deref the future
07:48jonathanjWhat do you mean?
07:48jonathanjWhat do you mean by "get the exception"?
07:48justin_smithjonathanj: if an exception happens inside a future, you can deref the future to get the exception to throw. Otherwise it's a silent failure.
07:49jonathanjuh, okay, but in that code there i'm calling a function defined outside the future that rethrows the exception
07:49jonathanjthat function is being called and the exception is well defined but apparently trying to rethrow it does nothing
07:49jonathanjand i'm not deferring the future, so why does rethrowing do nothing?
07:49justin_smithjonathanj: throws inside the future are handled differently
07:50justin_smithyou don't see the exception unless you deref it
07:50jonathanjproblem is that deref is blocking :|
07:52jonathanji tried to understand agents, but i'm not sure how to apply the "change the agent state" approach to mutable Java stuff
07:52poweredwhat's the use for exceptions anyway outside of java interop?
07:52justin_smithjonathanj: since the bots don't let us play with exceptions, see this example: https://www.refheap.com/112543
07:52jonathanjpowered: i dunno, to signal an exceptional state?
07:52justin_smithjonathanj: that's not what agents are for - send to an agent changes which object the agent holds, usually
07:53jonathanjjustin_smith: yeah, that's the picture that was slowly making sense to me
07:53justin_smithpowered: there's plenty of ways to make an exception happen without interop
07:54justin_smithjonathanj: 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
07:54justin_smithbut this isn't what agents are set up to do
07:54justin_smithjonathanj: definitely do not put mutable things in atoms or refs, because retries
07:54jonathanjyeah
07:54poweredyes I guess network request etc has exceptions
07:55justin_smith,(+ 1 "hello") ; all sorts of things are erroneous
07:55clojurebot#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]...
07:55jonathanjexceptions have kind of got a bad rep, for reasons i don't fully understand
07:56poweredbecause correct code doesn't encounter exceptions
07:56poweredand exceptions as flow control mechanism isn't good either
07:56jonathanjwithout 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
07:57jonathanjyeah, well the real world isn't always correct
07:57jonathanjif some user says "hey, use the certificate with alias X" and there is no such certificate in the keystore, what do you do?
07:57poweredreturn nil
07:57poweredI like the idea of pure functions returning something, not throwing exceptions
07:57jonathanjokay, so then the thing that was expecting a result now has to handle nil
07:57justin_smithnil is arguably worse than exceptions
07:58jonathanjand nobody knows there was an error
07:58jonathanjand 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
07:59ARM9that's what you get with dynamic typing, time to reinvent the monad
08:00poweredI'd rather use if vs try catch
08:00jonathanjpowered: well they're not really comparable
08:00jonathanjpowered: you can't accidentally ignore an exception
08:01jonathanjif 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
08:01jonathanjinstead of littering it with return code checks
08:01Glenjaminif you use the maybe monad with do notation, you still can't tell where the Nothing came from
08:02poweredyes, so you're saying if something goes wrong: fail right away
08:02jonathanjpowered: that's usually the best course of action
08:02Glenjaminit's the best default imo
08:02jonathanjbut if you don't want to do that, or you know how to recover, then you catch the exception and do the better thing
08:02jonathanjimo, that is a much better case than "always write all of the error handling all over your code"
08:06jonathanjjustin_smith: i'm not really sure what actually suits my needs then
08:07jonathanjjustin_smith: i don't want to block on a deref only to determine if there's an exception
08:07jonathanjso while i can use `realized?`, what if the exception hasn't occurred by the time i check if it's realized?
08:08justin_smithjonathanj: 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
08:08justin_smithjonathanj: realized? means it stopped - and it should stop at some point right?
08:09jonathanjjustin_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?
08:10justin_smithit 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.
08:10jonathanjjustin_smith: a channel might be a possibility, can i put to a channel from another thread?
08:10justin_smithyes, core.async is pretty flexible about where stuff executes
08:11jonathanjjustin_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
08:12jonathanji think if i create a channel for each request and put errors/results on it, that should work quite reliably
08:12justin_smithso then you need something to consume the result of that future - something that knows how to communicate with the client
08:13jonathanjthe 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
08:15jonathanjanyway, there's definitely some stuff to play with, thanks, i'll try a few approaches and see what works best
08:21jonathanjjustin_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
08:23jonathanjthis could probably be avoided by using ByteArrayOutputStream or similar but that means allocating all the memory for the output ahead of time
08:25justin_smithjonathanj: or you could just check realized? before dereffing
08:25justin_smithif it's not realized it's still running
08:29jonathanjthen we're back to the question of if it's not realized, when do i try deref it?
08:29justin_smithyou could poll it
08:29justin_smithyou could have a try/catch/finally where the finally puts something in action
08:29justin_smith(inside the future that is)
08:31Glenjamindoes deref with a timeout help?
08:32justin_smithtrue, that's another option
08:34jonathanjwhat do i do if it times out?
08:35BRODUSi'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?'
08:35sunset-shimmerhello, I need some help
08:36justin_smith,(fn? #())
08:36clojurebottrue
08:37sunset-shimmerI 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?
08:37BRODUSjustin_smith: thanks, i couldn't find that one
08:37justin_smithsunset-shimmer: for is not a loop
08:38justin_smithsunset-shimmer: you can use reduce with the for comprehension as its input, or perhaps use loop
08:38justin_smithbut for is not a loop and isn't designed to do what you want
08:38sunset-shimmerah, I see!
08:40sunset-shimmerI'll try reduce, loops are boring
08:41justin_smithsunset-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
08:50jonathanji swear i ask this every week, but how to turn [[1 2] [3 4]] into [[1 3] [2 4]]?
08:51jonathanj,(apply map vector [[1 2] [3 4]])
08:51clojurebot([1 3] [2 4])
08:51jonathanjis there a limit on how many parameters can be passed with apply?
08:52jeaye,(doc apply)
08:52clojurebot"([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."
08:52jonathanji meant like a hard limit
09:04sunset-shimmer> derrida has left IRC
09:04sunset-shimmersorry, I am lold
09:23jonathanjis there somewhere i could read about some common sync idioms written with core.async?
09:24jonathanjsynchronous idioms, that is
10:07poweredthis feels wrong: (merge-with merge {:a {:a 1}} {:a {:b 2}})
10:07poweredis there a better way?
10:08beaky,(merge-with merge {:a {:a 1}} {:a {:b 2}})
10:08clojurebot{:a {:a 1, :b 2}}
10:08beaky,(merge {:a {:a 1}} {:a {:b 2}})
10:08clojurebot{:a {:b 2}}
10:08beaky,(flatten {:a {:a 1}} {:a {:b 2}})
10:08clojurebot#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:09beaky,(apply into {:a {:a 1}} {:a {:b 2}})
10:09clojurebot#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:09beaky:(
10:09beaky,(merge-with assoc {:a {:a 1}} {:a {:b 2}})
10:09clojurebot#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:09beakyok i guess merge-with merge is the way to go
10:10poweredI'll keep on mergin
10:10beakyyou are merging maps nested 1-level deep via merge, see :D
10:10j-pbyou could do this, sec
10:11beaky,(map merge {:a {:a 1}} {:a {:b 2}})
10:11clojurebot([:a {:a 1} [:a {:b 2}]])
10:15BRODUS,(take 5 (iterate identity :a))
10:15clojurebot(:a :a :a :a :a)
10:15BRODUSis there a better way of generating identity arrays than that?
10:16BRODUSsomething less verbose?
10:16poweredrepeat?
10:16luma,(repeat 5 :a)
10:16clojurebot(:a :a :a :a :a)
10:16BRODUSah, thanks
10:16beaky,(repeat 10 ":D")
10:16clojurebot(":D" ":D" ":D" ":D" ":D" ...)
10:17BRODUSthis language has too many useful functions to remember
10:17lumathat's why we have http://clojure.org/cheatsheet
10:21schmirand http://conj.io
10:21beakyi love conj; reminds me of conjuncivitis
10:24sunset-shimmertest
10:26yendais it possible to have both a repl and a cljs-repl running with a boot task and connect to them ?
10:26yendaor it doesn't even make sense ?
10:26sunset-shimmerjustin_smith: great, I've wrote what I want with "reduce", thank you!
10:27sunset-shimmerit is my first usage of "reduce"!
10:47yendaI read that boot allows you to add dependencies without restarting the repl how to you do so ?
11:01marchelzohi
11:03marchelzohow 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:03marchelzoalso is that what most people use for a repl, or is there a better one with readline bindings?
11:04MJB47most people use leiningen for both
11:04MJB47http://leiningen.org/
11:05marchelzooh, cool
11:05marchelzothanks
11:06ARM9in 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:07marchelzoyeah I see that
11:32justin_smithARM9: 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:44marchelzohow do you load a source file in the repl?
11:44marchelzothe lein repl
11:45justin_smithmarchelzo: require, use, load, or load-file
11:45justin_smithsame as in any other repl
11:45marchelzoI'm new to clojure in general so the fact that it's the same as any other repl doesn't make a difference :)
11:46ARM9(load-file "myfile.clj")
11:46justin_smithOK, with clojure.repl/doc you can see the docs for any of those functions
11:46marchelzook thanks!
11:47justin_smithmarchelzo: see also clojure.repl/apropos and clojure.repl/find-doc which will search function names or docs, based on substrings or regex
11:48marchelzoawesome
11:49justin_smithalso http://conj.io is a good overview of the core language with examples
11:49marchelzoso string literals are java.lang.Strings, but they are implicitly coerced to lists sometimes?
11:49marchelzohow can I make a list of chars be displayed as a string?
11:49marchelzojustin_smith: thanks, I think I need something like that
11:49justin_smithmarchelzo: many sequence functions call seq on their arg
11:49justin_smith,(seq "hello")
11:49ARM9they are never implicitly coerced to lists, but sometimes sequences
11:50clojurebot(\h \e \l \l \o)
11:50justin_smith,(list? (seq "hello"))
11:50clojurebotfalse
11:50marchelzo,(take 3 "hello")
11:50clojurebot(\h \e \l)
11:50marchelzowhat if I want that displayed as "hel"?
11:50justin_smith,(source take)
11:50clojurebotSource not found\n
11:50justin_smith,(apply str (take 3 "hello"))
11:50clojurebot"hel"
11:50justin_smith(subs "hello" 0 3) ; more efficient
11:51justin_smith,(subs "hello" 0 3)
11:51clojurebot"hel"
11:51marchelzowhy apply str instead of just str?
11:51justin_smith,(str (take 3 "hello"))
11:51marchelzooh
11:51clojurebot"clojure.lang.LazySeq@2076e"
11:51marchelzo,(str \h \e \l)
11:51clojurebot"hel"
11:51marchelzoI see
11:51justin_smithtake 3 returns a lazy seq
11:52justin_smithand those print weird
11:52justin_smitherr, those convert to string weirdly
11:53justin_smithmarchelzo: unlike some functional languages (eg. haskell) a sequence of character and a string are not the same
11:53justin_smithand even in haskell they end up needing to make that distinction if they care about performance, eventually
11:54marchelzoright
11:54marchelzoI've never seen people complaining about clojure's strings so I assumed they didn't use list of char.
11:55justin_smithyou can use class to find out the real jvm level class behind any piece of data
11:55justin_smith,(class "hello")
11:55clojurebotjava.lang.String
11:55justin_smith,(class (seq "hello"))
11:55clojurebotclojure.lang.StringSeq
11:55marchelzowhat would be the most idomatic way to apply a function 40 times to an argument?
11:56TimMcDo you want the results?
11:56justin_smithmarchelzo: as in nested?
11:56marchelzoyes
11:56marchelzoto both
11:56ARM9what kind of function? what does it take? what does it return?
11:56justin_smitheither (take 40 (iterate f arg)) or (nth (iterate f arg) 40)
11:56marchelzoits a -> a
11:56justin_smithdepending if you want all the intermediates or not
11:57justin_smith,(nth (iterate #(* % Math/E) 1) 40)
11:57clojurebot2.35385266837019584E17
11:57marchelzono just the final value; so (iterate f arg) is a lazy infinite sequence?
11:57justin_smith,(take 40 (iterate #(* % Math/E) 1))
11:57clojurebot(1 2.718281828459045 7.3890560989306495 20.085536923187664 54.59815003314423 ...)
11:57justin_smithmarchelzo: indeed
11:58marchelzook, thank you.
11:58ARM9note that you'll run into trouble if you try to use side effects
11:58justin_smithmarchelzo: sounds like you have enough haskell background that you'll pick up clojure quickly (if you get used to the non-purity thing)
11:59justin_smithyeah, laziness and side effects don't mix very nicely, and clojure doesn't enforce keeping them separate
11:59marchelzoyeah I've heard that
12:00marchelzoI'm sure I'll run into it soon enough
12:00justin_smithfor example:
12:00justin_smith,(take 1 (map println (range)))
12:00clojurebot(0\nnil)
12:00justin_smithoh wait...
12:01justin_smithwell, with the old version of range that used to be an issue :)
12:01justin_smith,(take 1 (map println [:a :b :c :d :e :f]))
12:01clojurebot(:a\n:b\n:c\n:d\n:e\n:f\nnil)
12:01justin_smithaha! the gotcha is still there in another form
12:02justin_smith(chunking is what makes this happen)
12:04Bronsa,(take 1 (map println (range 50)))
12:04clojurebot(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:04Bronsajustin_smith: (range) uses a different impl than (range n)
12:05justin_smithso I see
12:05Bronsaonly the latter is chunked
12:05justin_smithBronsa: were they both chunked at one time?
12:05Bronsayes
12:05Bronsapre 1.7
12:08momerathIs 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:09justin_smithmomerath: are you explicitly requiring timbre in every namespace where you use it?
12:09momerathwhat's the alternative? I'm requiring it and using the refer-timbre macro
12:10justin_smithmomerath: some people use a namespace fully qualified, because it is required in some other ns. Which is a bad habit, though it works.
12:11justin_smithmomerath: 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:11momerathhrm- yeah, I guess I'll try that; thanks!
12:15Bronsajustin_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:16momerathnow I just get the "bad state! Error:" with nothing after it
12:17justin_smith,(nth (range) (inc' Long/MAX_VALUE))
12:17clojurebot#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:17justin_smithI think the problem here is with nth though
12:17BronsaI think so
12:17Bronsa(range) is defined as (iterate inc' 0)
12:18Bronsa,(take 10 (nthrest (range) Long/MAX_VALUE))
12:18clojureboteval service is offline
12:18Bronsa:(
12:18Bronsasorry clojurebot
12:18justin_smithBronsa: just tried in my repl, we'll see if it returns this year or not
12:19Bronsalol
12:21Bronsauhm, LongRange could actually be O(1) rather than O(n) on nth
12:21aurelianwhat 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:23justin_smithaurelian: 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:23justin_smith,(keyword "foo bar") ; terrible
12:23clojurebot:foo bar
12:24aurelianhm, I have :keywordize to true
12:24aurelianusing cljs-ajax to do the api call
12:24justin_smithbut it's not doing the _ / - conversion
12:24aureliannope
12:25aurelianI can access it as :starred_at but I think :started-at is nicer :)
12:25aureliannot that it will make a difference, but how I would do this kind of stuff?
12:27justin_smith,(keyword (clojure.string/replace (name :foo_bar) \_ \-))
12:27clojurebot:foo-bar
12:27Bronsaaurelian: https://github.com/qerub/camel-snake-kebab
12:27justin_smithoh yeah, that's a much better way
12:28aureliancheers guys!
12:28aurelianor gals
12:28aurelianor both.
12:39gfredericksso it looks like if you accidentally with-redefs a macro you end up permanently unmacrofying it
12:51yendaAnybody here is using the system library ?
12:51yendadanielsz/system
12:54yendaI'm trying to figure out how I can pass one of my system component to a function I call in my ring app
12:54yendain this case it is the db so that i can use the connection in the function
12:56mavbozogfredericks, in my imagination, macro ~ expansion , unmacro ~ contraction, so all macro-expanded code gets contracted
13:00justin_smithgf~.
13:01justin_smithgfredericks: oops - you should be able to put the :macro metadata back on it, no?
13:01justin_smithas long as you didn't mess with the first two magic args
13:01marchelzoif i use 'lein deps' to download a dependency, is there a way to load it in the repl?
13:02justin_smithmarchelzo: 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:02MJB47(use '[clojure.data.json :as json])
13:02MJB47obviously use whichever library you are actually using
13:03justin_smiththere are libs like pomegranate and pallet/alembic that are designed to do both the download and the adding to classpath at runtime
13:03justin_smithMJB47: that only works if the dep is on your classpath already
13:03MJB47does lein deps not add to classpath?
13:03justin_smithMJB47: all lein deps does is download all deps to local cache that are implied by project.clj
13:04MJB47update project.clj -> lein deps -> lein repl has always worked properly for me
13:04justin_smithMJB47: so if you already had a repl running, that dep is not added to the running repl
13:04MJB47oh ye
13:04MJB47need a new repl
13:04justin_smithright
13:05justin_smithso I might be reading too much into the question - I thought "adding the dep to a running repl" was implied
13:05MJB47i assumed the opposite
13:05MJB47oh well
13:06gfredericksjustin_smith: yeah, I think you could fix it fine by calling .setMacro afterwards
13:06gfredericksbut it's super confusing
13:06gfredericksI made http://dev.clojure.org/jira/browse/CLJ-1867
13:06justin_smithyeah, that is an odd behavior
13:06gfredericks(which includes the root cause)
13:11casey1quite
13:34wolgo'/help
15:58lxsameerhey folks, I'm looking for a free PaaS for my clojure aoo
15:58lxsameer*app
15:58MJB47try heroku
16:00lxsameerMJB47: heroku has limitations
16:01MJB47i doubt you will find a free one without
16:01lxsameerMJB47: openshift limiation is kind of nice, but It does not support clojure by default
16:02celwellelastic beanstalk micro instance should be free for a year i think
17:07mjgHi! 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:08justin_smithonly if you use eval I think
17:09mjglike (binding [*ns* (create-ns 'other-ns) other-ns/*foo* "hello"] (eval (read-string "*foo*"))) ?
17:09justin_smithumm... what are you trying to do here?
17:11mjgI'm writing a small lazybot-esque thing.
17:12mjgSo, 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:13mjgI'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:15mjgjustin_smith: so far https://gist.github.com/mjg123/a1dca856cd08682f5676 works, but with only one ns.
17:21justin_smithmjg: what about using in-ns inside the eval'd code?
17:22justin_smitheg (eval (concat '(in-ns user-specific-ns) user-code))
17:22justin_smithor maybe that's missing some parens
17:23mjgWhere can I re-bind the *me* var in user-specific-ns in that case?
17:23justin_smithmjg: you can use intern to set the binding
17:24mjgjustin_smith: can you use intern like that?!
17:24justin_smith,(intern 'foo.bar 'baz "hello")
17:24clojurebot#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:25justin_smithmjg: oops - ns has to exist first
17:25justin_smith,(in-ns 'foo.bar)
17:25clojurebot#object[clojure.lang.Namespace 0x6c822bda "foo.bar"]
17:25justin_smith,(intern 'foo.bar 'baz "hello")
17:25clojurebot#'foo.bar/baz
17:25justin_smith,[*ns* foo.bar/baz]
17:25clojurebot[#object[clojure.lang.Namespace 0x1227d02b "sandbox"] "hello"]
17:26justin_smithso 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:27mjgbut that's not a dynamic binding is it? All threads will see the interned value.
17:27justin_smithmjg: the var belongs to a specific ns
17:29mjgI 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:30justin_smiththey can't have their own namespaces?
17:30mjgusers? no
17:30mjgI want one ns per room.
17:31justin_smithmjg: you can create the dynamic var with no root binding, then bind it explicitly
17:32mjgjustin_smith: inside the 'eval ?
17:32justin_smithI think so, yeah
17:32mjgOK let me experiment with that. Thanks for your help.
17:32justin_smithbecause eval doesn't use your local environment really
17:32sdegutisIs there a nicer way to do (->> (for [x] (if? (f x) (g x))) (remove nil?))
17:33sdegutisNotice how technically my question still ends in a question mark.
17:33justin_smith(keep #(when (f %) (g %)) coll)
17:34justin_smith,(keep #(when (even? %) (inc %)) (range))
17:34clojurebot(1 3 5 7 9 ...)
17:34amalloywhat on earth is if?
17:35amalloyalso what is (for [x] ...)
17:35justin_smithamalloy: I was going to ask what (for [x] was...
17:35justin_smithheh
17:47justin_smith,(defmacro if? [& body] `(boolean (if ~@body)))
17:47clojurebot#'sandbox/if?
17:47justin_smith,(if? true 42)
17:47clojurebottrue
17:51sdegutisThanks justin_smith
17:52sdegutisamalloy, justin_smith: It seems I am not fully with it right now.
18:05rkpaulI'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:07alive876hi, 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:07amalloyrkpaul: "trying to reify a class where I have the classname in a string" is the wrong part
18:07rkpaulamalloy: wrong part as in that's not causing the error?
18:08amalloyas in you can't do that
18:08rkpaulah ok
18:08amalloyi mean, it's not impossible but
18:08amalloyit's not easy
18:08rkpaulso 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:09amalloyyes
18:09rkpaulok thanks
18:11WorldsEndlessAnyoen have recommendations on debugging a "Exception in thread "main" java.lang.ExceptionInInitializerError" when trying to run my uberjar?
18:13mjgjustin_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:15mjgjustin_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:26justin_smithmjg: clearly the binding has to also be inside the eval
18:27sdegutisWill #(foo %) late-bind so that if I change the function that #'foo points to, my anonymous function will call the new one?
18:27sdegutisThanks in advance. Regards.
18:33justin_smithsdegutis: yes, #(foo %) will see new values for foo - the way you get the "stuck" version is if you have ((fn [f] #(f %)) foo)
18:37sdegutisjustin_smith: why is that?
18:37justin_smithsdegutis: ((fn [f] #(f %)) foo) - the function that generates that function never sees the var, just the value of the var
18:37justin_smithas opposed to #(foo %) - that actually sees the var
18:39sdegutisOooooh.
18:39sdegutisThank!
19:36slesterNewb 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:37slestererr, reduce I guess.
19:41slestergot it, sorry, nvm!
20:02amalloyslester: i'd use apply
20:02amalloy(apply dissoc m kws)
20:04slesteramalloy: thanks!
20:11sdegutisjustin_smith: it still doesn't make sense to me though
20:11sdegutis((fn [f] #(f %)) foo)
20:11sdegutisIsn't writing "foo" just referencing a var?
20:11sdegutisjustin_smith: So that the anonymous function receives a far?
20:11sdegutis*var
20:30tolstoyslester You could also use "select-keys" to keep the ones you want.
20:30tolstoyBTW, clojure.set.rename-keys -> super handy when you need it.
20:47BRODUSone 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:49sumobobwhats the clojure equivalent of pushing to an array?
20:49tolstoyBRODUS Try mapv and filterv?
20:49BRODUS,
20:49clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
20:50tolstoy,(map inc [1 2 3])
20:50clojurebot(2 3 4)
20:50tolstoy,(mapv inc [1 2 3])
20:50clojurebot[2 3 4]
20:51BRODUSah ok, so that means that i lose the benefits of a lazy sequence then
20:53tolstoyOh, mapv isn't lazy?
20:54TEttingermap is. mapv isn't.
20:54tolstoyBRODUS: 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:54sumobobwhat is the difference between "a" and \a
20:55sumobob,(type "a")
20:55clojurebotjava.lang.String
20:55sumobob,(type \a)
20:55tolstoysumobob First is a string type, the second a char type.
20:55clojurebotjava.lang.Character
20:55BRODUS,(seq? "a")
20:55clojurebotfalse
20:55BRODUS,(coll? "a")
20:55clojurebotfalse
20:56sumobobhmm, i'm trying to do a case statement based on a char, but its not being too friendly with me
20:58TEttingersumobob: there may be a better fit than case
20:59amalloyBRODUS: it's certainly not "idiomatic to use vectors instead of lists" in general
20:59sumobobI'm working on some problems from a site called adventofcode.com
21:00amalloyit'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:00sumobobits basically a massive string like ">>><<v^" which needs to be used as directions, go left, go right etc etc
21:00TEttingerwhich day?
21:00sumobobday 3
21:01sumobobI'm doing it recursively
21:01sumobobi have a function that takes a string and an array
21:02sumobobbased on the first char of the string, i conj a new object onto the array and call my function again with (rest string)
21:09BRODUSamalloy: 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:10amalloywell yes, you don't super often build lists. but you build seqs all the time
21:14TEttinger,(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:14clojurebot5
21:14TEttingerfun
21:40devnso, it's been awhile since i looked at this
21:41devnbut im puzzling a little bit. i don't recall why (+) is the right thing here:
21:41TEttingerhey devn
21:41devn,(#(`[[~@%&]] (+)) "A")
21:41clojurebot["A"]
21:41TEttinger,(+)
21:41clojurebot0
21:41devnwait, don't finish that thought -- staring at it
21:42TEttingeroh I know
21:42TEttinger,(#(`[~@%&]) "A")
21:42clojurebot#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:43TEttingersee, otherwise it would try to call the vector instead of returning the 0th element of a nesting vector
21:43TEttinger,((fn [& args] [args] 0) "A")
21:43clojurebot0
21:44TEttinger,((fn [& args] ([args] 0)) "A")
21:44clojurebot("A")
21:44TEttingera little more clear why it does what it does, devn?
21:44devnhaha, im feeling a little slow right now
21:44devnim trying to walk it through in my head
21:45justin_smith ,(/ (+))
21:45clojurebot#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:45TEttinger,(#([%&] (+)) "A")
21:45clojurebot("A")
21:45devnnono, i get the identity thing for (+)
21:45justin_smithdevn: I just thought (/ (+)) was a funny way to get a divide by 0
21:45devn:D
21:46devn,(/(*)(+))
21:46clojurebot#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:46justin_smith,(/ (*))
21:46TEttingerit's because you can't use alphanumerics in swearjure, and 0 is numeric
21:46clojurebot1
21:46devngoogly eyes
21:46TEttingerit's getting the 0th element of the vector
21:46TEttingerthat contains a vector of all args passed to it
21:46devnwhy does it need the nesting?
21:46TEttinger(where it is the anon fn)
21:47justin_smithdevn: it needs to become a vector
21:47TEttinger,(#(`[~@%&] 0) "A")
21:47clojurebot"A"
21:47devnwell the unquote splicing
21:47devnahh right
21:47devnok ok
21:47TEttinger,(#(`[~@%&] 0) "A" "B")
21:47clojurebot"A"
21:47TEttinger,(#(`[[~@%&]] 0) "A" "B")
21:47clojurebot["A" "B"]
21:47devnyes, that's what i needed, makes good sense now
21:47TEttingercool
21:47TEttingerswearjure is nice and mindbending
21:48devnhere's the other one from the same post, weirder still
21:48justin_smith~(#(`[~@%&] 0) "A") makes good sense
21:48clojurebotExcuse me?
21:48justin_smithhaha
21:48devn,(#(`[{~% ~@%&}] (+)) :a 1)
21:48clojurebot{:a 1}
21:49devn"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:49devnso, were it not for that limitation, it would be the same as vector, but with no ~% in the key position
21:50devn(i think)
21:50devnhyPiRion: *waves*
21:51devni kinda like the symmetry of:
21:51devn,(#(`[{~@%& ~@%&}] (+)) :a 1)
21:51clojurebot{:a 1}
21:51justin_smith,{#_ foo :a 0}
21:52clojurebot{:a 0}
21:52devnone fun bit about that is, even though you can't rely on the ordering of maps:
21:52devn,(#(`[{~@%& ~@%&}] (+)) :a 1 :b 2 :c 3)
21:52clojurebot{:c 3, :b 2, :a 1}
21:52devn,{:a 1 :b 2 :c 3}
21:52clojurebot{:a 1, :b 2, :c 3}
21:52devnbtw: hi TEttinger :)
21:52devnaloha justin_smith
21:53TEttingerhallo!
21:53justin_smithzdrasvitye
21:53devnsomething clojure this way comes
21:55sumobobwtf
21:56devnwhat y'all hackin' on these days?
21:56sumobob,(- 1 0)
21:56clojurebot1
21:56sumobob,(- 0 1)
21:56clojurebot-1
21:56sumobobwhaaat
21:56justin_smith,(- 3 2 1)
21:56clojurebot0
21:56sumobobcan someone explain this for me?
21:56justin_smithsumobob: 0 - 1 is -1
21:56devn1 - 0 = 1
21:56devn0 - 1 = -1
21:57devnsumobob: what'd you expect?
21:57devn,(< 1 0)
21:57clojurebotfalse
21:57devn,(> 1 0)
21:57clojurebottrue
21:57sumobobfor some reason i just thought it would subtract everything haha
21:58sumobobbut yeah operational order matters lol
21:58devnthe lt and gt operators will never get easier for me
21:58justin_smithdevn: the height moves in the direction of the size of the numbers
21:58justin_smith> lower to the right, just like the numbers
21:58justin_smith,(> 5 4 3 2 1 0 -1)
21:58clojurebottrue
21:59justin_smith< higher to the right, just like the numbers
21:59devnyeah 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:59justin_smith,(< 0 1 2 3)
21:59clojurebottrue
21:59devni haven't golfed in awhile, have been missing it
21:59justin_smithdevn: no eating - it's a graph of the numbers in the argument list
21:59justin_smithline graph
21:59devnjustin_smith: ah, that's actually a better way of thinking about it
21:59devnthanks
22:00justin_smithnp
22:00devnim pretty anti-golf these days
22:00devni prefer explicit (fn [...] ...) over (partial ...)
22:00justin_smithdevn: oh, I don't golf in real code
22:00devn(in shared code that is)
22:01devnit kills me when i see a partial, and it's not immediately obvious if it's going to take & args, arg1 arg2, etc.
22:02devni also have pretty much stopped using #()
22:02justin_smithif only partial was curry - then you know it always takes exactly one more arg
22:02devnexplicit fn all the time
22:02devnjustin_smith: *nod*
22:02devnspeaking of shared code, programming on a team, etc...
22:03devnis there any hope, do y'all think, that we'll ever get a set of standard map-processing functions in core?
22:03devn(map-keys) (map-vals) (filter-keys) (filter-vals) (filter-kvs) (map-kvs) etc.
22:05jhnall of that is just one reduce away
22:05devnthat, and as long as im ranting and raving: when are transients gonna get some love? no update! update-in! etc.
22:06devnjhn: 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:06devnit'd be so much nicer if they just lived in core
22:06devnno "here, i wrote this utility library that adds functions that ought to be in core"
22:06jhnyeah. the one i always see myself reimplementing is map-vals
22:07amalloyjust use into
22:07amalloyi mean it'd be nice if map-vals existed, but if you implement it yourself use into instead of reduce
22:08jhnis this not idiomatic? https://github.com/jhn/tobias/blob/master/src/tobias/util.clj#L17-L18
22:08devnamalloy: why not reduce-kv with a transient persistent! around it?
22:08amalloybecause into already does the transient part
22:09devnbut it won't work recursively right?
22:09devnbecause the submaps aren't ieditable?
22:11devn,(let [x (transient {:a 1 :b 2 :c {:d 3}})] (type (:c x)))
22:11clojurebotclojure.lang.PersistentArrayMap
22:11devn:((((
22:12devni think cgrande wrote something about this a long while back
22:12devnah, im thinking of https://github.com/cgrand/megaref
22:13devnperhaps specter is closer to what im after in that case
22:19mgaareYeah, transients aren't recursive like that. Ran into that problem too
22:20devnI sat down and started writing a thing to handle the recursive case, but it got ugly quick
22:21devncant 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:21devnwhich meant switching out assoc! for assoc, etc.
22:39domgetterDo for loops not work inside go blocks?
22:40amalloy~for
22:40clojurebotfor is like doseq, but for values instead of side effects
22:40domgetter(go (for [x (range 1 10)] (>! c x))) doesn't seem to put anything on channel c
22:40justin_smithdomgetter: for is lazy
22:40justin_smithuse doseq there
22:40devndomgetter: what happens if you wrap (for ...) with (doall ...)
22:40justin_smithfor is only for generating values
22:40devnbut also yes, doseq.
22:41devnit's been awhile since i've used core.async
22:41devnwhat does (>! c x) return? a channel?
22:41justin_smithdevn: nil
22:41devnah
22:41devngo returns a chan though
22:41devnright?
22:41clojurebotright is not wrong
22:42justin_smithdevn: right, it would either return a list of nils or if you switch for with doseq it would return a single nil
22:42justin_smiths/list/seq of course
22:42domgettergot it, thank you
22:43justin_smithdomgetter: 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:45justin_smithor 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:46devnah, now im remembering more transient weirdness
22:46domgetterYea I kept getting cannot convert ISeq to ManyToMany errors
22:46devn,(require '[clojure.walk :as walk])
22:46clojurebotnil
22:46devn,(walk/postwalk (fn [x] (if (map? x) (transient x) x)) {:a 1 :b {:c 3 :d {:e 4 :f {:g 6}}}})
22:46clojurebot#object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x6c509ac3 "clojure.lang.PersistentArrayMap$TransientArrayMap@6c509ac3"]
22:46devn,(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:46clojurebot#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:47devn,(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:47clojurebot#'sandbox/transients-all-the-way-down
22:47devn,(defn transient? [x] (instance? clojure.lang.ITransientCollection x))
22:47clojurebot#'sandbox/transient?
22:49justin_smithdevn: I wonder how the time spent checking for transient status or not compares to the time saved by using transients
22:49devn,(walk/postwalk (fn [x] (if (transient? x) (persistent! x) x)) transients-all-the-way-down)
22:49clojurebot{:a 1, :b #object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x247c1594 "clojure.lang.PersistentArrayMap$TransientArrayMap@247c1594"]}
22:51devnnot 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:51justin_smithsure, but it didn't print readable
22:51devni would have expected the whole thing to be persistent at that point
22:52justin_smithor are you saying the top level one should be transient too?
22:52justin_smithright
22:52devneither that's a bug, or im doing it wrong
22:52justin_smith,(walk/postwalk (fn [x] (if (transient? x) (persistent! x) x)) [transients-all-the-way-down])
22:52clojurebot#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:53justin_smithoh, right, that was a side effect
22:54devnwell, i got further :)
22:54devn,(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:54clojurebot{:a 1, :b {:c 3, :d #object[clojure.lang.PersistentArrayMap$TransientArrayMap 0x5a88a5eb "clojure.lang.PersistentArrayMap$TransientArrayMap@5a88a5eb"]}}
22:58justin_smithdevn: 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:59devnoh duh, right
22:59devnweird, wonder how i missed that...
23:00devni could swear i tried a prewalk
23:00devn,(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:00clojurebot#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:00devn,(require '[clojure.walk :as walk])
23:00clojurebotnil
23:00devn,(defn transient? [x] (instance? clojure.lang.ITransientCollection x))
23:00clojurebot#'sandbox/transient?
23:00devn,(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:00clojurebot{:a 1, :b {:c 3, :d {:e 4, :f {:g 6}}}}
23:01devnhuzzah
23:05devnjustin_smith: I have the same question as you about performance
23:05devnthat check isn't free
23:05devnquite the opposite
23:09devn,(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:09clojurebot"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:10devn,(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:10clojurebot"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:10devnA very poor man's benchmark, but I'm seeing ~0.03msecs for the post/pre
23:11devn0.01msecs for the straight ahead update-in
23:11devnso, specter... :D
23:16devnhttps://gist.github.com/devn/b195dbc67a320021057c here if someone is interested in tinkering with it, would be interested to see other approaches
23:37domgetterIs there a way to ask the result of make-array for its size?
23:37domgetter(assert (= 3 (size (make-array Long/TYPE 3))))
23:38domgetterwhat goes here? ^
23:39domgettergot it. It's alength
23:39justin_smithdomgetter: count
23:40domgettercount also works. are they synonymous?
23:40justin_smith,(count (make-array Long/TYPE 3))
23:40clojurebot3
23:40justin_smithdomgetter: count is more general
23:40domgetterah okay. Thank you
23:40justin_smith,(count "hello, world!")
23:40clojurebot13
23:40justin_smith,(alength "hello, world!")
23:40clojurebot#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:53lambda-11235How do clojurebot's error messages work? Is there a library to do that?
23:54justin_smiththe message is exactly how exception objects are printed since 1.7
23:56justin_smithit was better back when it was just the message - because with a bot we really don't want or need the stack trace