#clojure log - May 07 2015

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

2:23 dysfun: anyone here reasonably familiar with reagent?

2:25 oddcully: just in case: there is also #clojurescript

2:25 dysfun: aha

2:33 Niac: http://paste.ideaslabs.com/show/K4Qbh2CVIh

2:33 what's wrong with my loop

2:35 It's for count the length

2:35 amalloy: Niac: your arguments to recur are in a different order than the loop variables

2:35 dysfun: wow, you spotted that quickly

2:35 i was still stuck on "is reimplementing primitive function"

2:36 amalloy: well, also it's off by one

2:36 dysfun: heh

2:37 Niac: amalloy: yeah ,that's it

2:38 amalloy: i thought it just binding

2:41 dysfun: incidentally, i'd write that as a reduce, assuming i didn't know count existed

2:42 ,(reduce (fn [acc _] (inc acc)) 0 coll)

2:42 clojurebot: #error{:cause "Unable to resolve symbol: coll in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: coll in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6543]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: coll in this context", :at [clojur...

2:42 dysfun: ,(reduce (fn [acc _] (inc acc)) 0 [1 2 3])

2:42 clojurebot: 3

2:43 amalloy: *shrug* there are lots of reasonable ways to reimplement count. if Niac wants to practice loop instead of reduce, no need to do anything different

2:44 dysfun: equally you could write (apply + (map (constantly 1) coll))

2:44 dysfun: yep

2:45 but i'm assuming beginner level, and thus we've succeeded in giving him two more ways to do it. go us!

2:51 Niac: it is cool to use a lisp dialect

2:52 dysfun: one of the nice things about lisp is everything is pretty simple. and the libraries people have written are pretty simple to use as well

2:54 any ideas why this gives me an error?

2:54 (def from-file (comp ImageIO/read io/file))

2:55 -> Unable to find static field: read in class javax.imageio.ImageIO

2:55 it's definitely there. is it something to do with the polymorphism?

2:57 if i turn it into a function, it seems to work fine

2:58 Niac: dysfun: is there any idea about pratice the interop with java?

2:58 dysfun: sorry, i don't understand. you are looking for a way to practice java interop?

2:59 Niac: dysfun: yes

2:59 dysfun: find a java library you like and use it in a project?

2:59 or alternatively write a little library in java and use it from clojure

3:00 but there's not much to practice. most of my interop code consists only of :import , Class/staticmethod and .method, with the occasional doto thrown in

3:01 if you're stuck for a java library to play with, try doing some image resizing stuff (like i've spent the last day doing). that takes you on a whirlwind tour of AWT and ImageIO and such

3:02 Niac: i will try

3:02 daviid: i hope 1 day it will be fully transparent, no more Class/staticmethod and .method

3:03 dysfun: seems unlikely for several good reasons, not least of which is that it's nice to have a separation between immutable and mutable worlds

3:03 daviid: having to write any java is terrible :) , my 2c

3:04 dysfun: although i've been amused to notice that this image resizing stuff, despite using the java core libraries actually doesn't do any mutation in place. quite by accident

3:52 mindbender1: What do I do to stop getting no implementation of protocol messages after reloading a namespace?

4:13 Niac: how to Reverse a Sequence without reverse?

4:16 mpenet: shuffle and a lot of tries :]

4:17 hyPiRion: (comp rseq vec)

4:17 Niac: resq is not allowed too

4:21 mpenet: (partial reduce conj ())

4:21 hairy

4:23 oh well, that's actually what reverse does more or less...

4:27 benhuda: hello

4:28 i've left clojure at 1.3 when it was my hobbie go-to, and now want to start integrating it into an R&D org. any highlights for this blackout period? what's the most important things that happened between 1.3 and 1.7 ? (I just finished reading the release notes, but I would appreciate someone who can share personal experience)

4:36 hyPiRion: benhuda: Mostly reducers, reader literals, core.async, and now lately transducers. But you can still be productive without them (and don't use them if you don't think they would be valuable)

4:38 H4ns: is there an operation that "adds" elements to a vector like (the-operation [:foo] 3 :bar) => [:foo nil nil :bar]?

4:38 wasamasa: oh, clojure got reader literals?

4:39 didn't know about that

4:39 benhuda: hyPiRion I think core.async is where i left off. i needed async capabilities and i migrated to Go and Node.js

4:40 (primarily disappointed with Nodejs in production and then went doing Go mainly)

4:40 so Clojure is doing well in the async / evented space now?

4:41 hyPiRion: benhuda: I haven't done much of it, but apparently it's well designed and heavily used

4:42 wasamasa: like #inst, #object, etc

4:42 ,foo

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

4:42 benhuda: Thanks. one last question - is there a netty based service infrastructure that can challenge Finagle etc ?

4:42 last i check it was Aleph or some sorts

4:48 hyPiRion: benhuda: I think you can use Finagle with Clojure directly (like https://www.youtube.com/watch?v=-woCYVaMBsg) but I guess I'd use Aleph for something like that. Not too sure about how it compares to Finagle though.

4:49 benhuda: thanks. so how would you do infrastructure level microservices?

4:51 hyPiRion: I haven't done microservices in Clojure unfortunately

4:59 H4ns: it is a popular thing, though. there are a few microframeworks to help with that (based on component, tesla-microservice etc) and there is immutant as the more heavy-weight solution.

5:00 oh. gone.

5:18 bcm: n

5:39 irctc: is there an elegant way to fix this situation. I have a chain of fun calls composed with ->> macro. But in between this calls i have the split function which takes (split arg1 #" "). I can not use split inside the macro since macro would put the current argument as the last of the split fun. I would like to have (split #" " arg1)

5:40 escherize: there are a few ways, yes.

5:41 one is instead of putting (split #" ") you would put (-> (split #" "))

5:41 ,(->> "one two" (-> (split #" ")) count)

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

5:41 escherize: ,(use clojure.string)

5:41 clojurebot: #error{:cause "clojure.string", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassNotFoundException: clojure.string, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6543]} {:type java.lang.ClassNotFoundException, :message "clojure.string", :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}], :trace [[java.net.URLClassLoad...

5:42 escherize: ,(use 'clojure.string)

5:42 clojurebot: #error{:cause "denied", :via [{:type java.lang.SecurityException, :message "denied", :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}], :trace [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69] [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkPropertyAccess nil -1] [java.lang.System getProperty "System.java" 708] [su...

5:42 escherize: ,(->> "one two" (-> (clojure.string/split #" ")) count)

5:42 clojurebot: #error{:cause "java.lang.String cannot be cast to clojure.lang.IFn", :via [{:type java.lang.ClassCastException, :message "java.lang.String cannot be cast to clojure.lang.IFn", :at [sandbox$eval95 invoke "NO_SOURCE_FILE" 0]}], :trace [[sandbox$eval95 invoke "NO_SOURCE_FILE" 0] [clojure.lang.Compiler eval "Compiler.java" 6792] [clojure.lang.Compiler eval "Compiler.java" 6755] [clojure.core$eval invo...

5:42 edbond: ,(doc clojure.string/split)

5:42 clojurebot: "([s re] [s re limit]); Splits string on a regular expression. Optional argument limit is the maximum number of splits. Not lazy. Returns vector of the splits."

5:43 edbond: ,(clojure.string/split "a b" #" ")

5:43 clojurebot: ["a" "b"]

5:43 edbond: escherize, ^

5:43 escherize: well said

5:44 edbond: ,(->> "one two" (clojure.string/split #" ") count)

5:44 clojurebot: #error{:cause "java.lang.String cannot be cast to java.util.regex.Pattern", :via [{:type java.lang.ClassCastException, :message "java.lang.String cannot be cast to java.util.regex.Pattern", :at [clojure.string$split invoke "string.clj" 217]}], :trace [[clojure.string$split invoke "string.clj" 217] [sandbox$eval165 invoke "NO_SOURCE_FILE" 0] [clojure.lang.Compiler eval "Compiler.java" 6792] [clojur...

5:44 edbond: ,(->> "one two" (-> (clojure.string/split #" ")) count)

5:44 clojurebot: #error{:cause "java.lang.String cannot be cast to clojure.lang.IFn", :via [{:type java.lang.ClassCastException, :message "java.lang.String cannot be cast to clojure.lang.IFn", :at [sandbox$eval189 invoke "NO_SOURCE_FILE" 0]}], :trace [[sandbox$eval189 invoke "NO_SOURCE_FILE" 0] [clojure.lang.Compiler eval "Compiler.java" 6792] [clojure.lang.Compiler eval "Compiler.java" 6755] [clojure.core$eval in...

5:44 escherize: ,(->> "one two" ((fn [x] (clojure.string/split x #" ")))

5:44 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

5:45 escherize: ,(->> "one two" ((fn [x] (clojure.string/split x #" "))))

5:45 clojurebot: ["one" "two"]

5:45 mpenet: wont work like this

5:45 ,(macroexpand '(->> "one two" (-> (clojure.string/split #" ")) count))

5:45 clojurebot: (count (-> (clojure.string/split #" ") "one two"))

5:45 mpenet: ,(->> "one two" (#(clojure.string/split % #" ")) count)

5:45 clojurebot: 2

5:45 escherize: right, mpenet

5:46 or, irctc, you could use as->

5:46 (as-> "a b" s (str s " " s) (clojure.string/split s #" "))

5:46 mpenet: yes, as-> is nicer imho

5:47 escherize: agree, mpenet

5:47 or if you have a ton of problems with this you can pull out the swiss arrows

5:47 https://github.com/rplevy/swiss-arrows

5:52 irctc: thanks as worked

5:53 edbond: ,(doc as)

5:53 clojurebot: Titim gan éirí ort.

5:53 edbond: ,(doc as->)

5:53 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

5:54 edbond: ,(source as->)

5:54 clojurebot: Source not found\n

5:54 escherize: yeah i mixed that up, because when you want -> in the middle of a ->>'d section you can wrap a form with -> to get that once. doesn't work both ways though

5:54 irctc: i have the freedom to put the argument wherever i want. But if have many chains that take it as first parameter, so as seems redundant. But the solution with the ann fun is ugly

5:54 drama!

5:55 escherize: yeah

5:55 swiss arrows exactly solves that

5:55 irctc: But I have many chains that take it as the first parameter, so as-> seems redundant*

5:56 what are swiss arrows?

5:56 escherize: https://github.com/rplevy/swiss-arrows#a-generalization-of-the-arrow check the part about default positioning behavior

5:56 i think you may want -<> althought there are a lot of arguments against it, IMO

5:57 is there a way to have clojurebot suck in a library off clojars?

5:58 irctc: I can not even google "-<>" lol

5:58 what is this

5:58 escherize: did my link not go through

5:58 https://github.com/rplevy/swiss-arrows#a-generalization-of-the-arrow

5:58 ^

5:58 irctc: yes, sorry didnt notice it

5:58 escherize: that's ok :)

6:01 irctc: there should be a macro (rearrange a b (string/split b a)) :D

6:09 nice, swiss arrows rock. I feard the would not have the default behaviour of normal ->>. Thanks alot.

6:10 escherize: :) np

6:34 TEttinger: (inc escherize)

6:34 lazybot: ⇒ 1

6:34 TEttinger: swiss arrows are very cool, thanks for linking

6:37 escherize: you made my day TEttinger

6:38 TEttinger: parallel diamond fishing rod is the best idea for a silly name (even though it seems quite useful!)

7:57 CookedGryphon: Hey, does anyone know how I go about getting permission to use the clojure logo in a blog post? Or is that sort of usage just fine with correct attribution?

8:09 puredanger: Just the logo itself?

8:11 CookedGryphon: if you're just including it in a blog post as is, you should be fine

8:33 CookedGryphon: I thought that would be the case, just wanted some reassurance :)

9:08 dysfun: "clojure.lang.ArityException: Wrong number of args (2) passed to: reader/read"

9:08 crops up compiling clojurescript, in which i'm not using read myself

9:09 Bronsa: dysfun: you're pulling an older versin of tools.reader than the one cljs requires

9:10 version*

9:14 dysfun: hrm. how can i figure out what's doing that?

9:15 dnolen: dysfun: lein deps :tree

9:15 dysfun: ta

9:17 ah, much better. thanks.

9:46 kaiyin: Is there a way to search the channel logs?

10:00 pdurbin: kaiyin: they used to be at http://logs.lazybot.org/irc.freenode.net/%23clojure/today.txt but I don't know what happened.

10:00 kaiyin: pdurbin: I meant to search the logs of all time, or within a certain period, if possible.

10:05 tolitius: kaiyin: you can cook something from http://www.raynes.me/logs/irc.freenode.net/clojure/

10:05 it's partitioned by date, should be trivial to filter/reduce

10:07 kaiyin: tolitius: yeah, I can download them and grep, but a search engine might be a better solution?

10:08 tolitius: kaiyin: build it, I'll use it :)

10:08 the data is there

10:08 pdurbin: me too

10:09 kaiyin: I might need to make a mirror of this site, I guess.

10:10 tolitius: you might want to see what raynes does with lazybot: http://lazybot.org/

10:11 maybe a pull request with a "seach" thingy to https://github.com/Raynes/lazybot

10:18 acron^: is there a form for checking if every element of a list of hasmaps contains the same key-value pair?

10:18 ,(def k [{:version 1} {:version 1} {:version 1} {:version 1}])

10:18 clojurebot: #'sandbox/k

10:18 acron^: ,(every? #(= (:version %) (:version (first k))) k)

10:18 clojurebot: true

10:18 acron^: ,(def k [{:version 1} {:version 1} {:version 1} {:version 2}])

10:18 clojurebot: #'sandbox/k

10:19 acron^: ,(every? #(= (:version %) (:version (first k))) k)

10:19 clojurebot: false

10:19 acron^: seems ugly

10:23 chouser: (reduce = (map :version k))

10:23 acron^: perfect :)

10:23 thanks

10:24 chouser: np

10:24 acron^: hmm

10:24 doesn't work :o

10:24 chouser: heh. Shoulda tested, eh?

10:24 acron^: ,(reduce = '(1 1 1 1))

10:24 clojurebot: false

10:25 chouser: oh, no, dumb. Try apply instead of reduce

10:25 acron^: ,(apply = '(1 1 1 1))

10:25 clojurebot: true

10:25 acron^: ,(apply = '(1 1 1 2))

10:25 clojurebot: false

10:25 acron^: :)

10:25 chouser: That was a last minute substitution in my head. reduce was definitely wrong.

10:46 kaiyin: in concurrency settings, how do you make sure that at any moment, only one thread is printing stdout?

10:46 to stdout.

10:47 ToxicFrog: Have a single thread responsible for printing to stdout and have the other threads send it messages?

10:52 kaiyin: ok, i see.

10:57 chouser: that's the Right solution. If you just trying to reduce the likelihood of output interleaving on a single line, you can just (prn-str ...) each thing first, before print'ing and flush'ing it.

10:58 kaiyin: ok

11:16 what is @ for on line 11? https://gist.github.com/kindlychung/7551ac67fe767c769d79

11:17 Bronsa: kaiyin: ~@ is unquote-splicing

11:17 ,`(~[1 2])

11:17 clojurebot: ([1 2])

11:17 Bronsa: ,`(~@[1 2])

11:17 clojurebot: (1 2)

11:27 kaiyin: Bronsa: yeah, but this is not ~@, it's just @

11:28 https://gist.github.com/kindlychung/7551ac67fe767c769d79#file-future-clj-L11

11:29 puredanger: @ is a reader macro for deref

11:29 ,(doc deref)

11:29 clojurebot: "([ref] [ref timeout-ms timeout-val]); Also reader macro: @ref/@agent/@var/@atom/@delay/@future/@promise. Within a transaction, returns the in-transaction-value of ref, else returns the most-recently-committed value of ref. When applied to a var, agent or atom, returns its current state. When applied to a delay, forces it if not already forced. When applied to a future, will block if computation n...

11:30 tolitius: @kaiyin, it is a defer on the future: https://clojuredocs.org/clojure.core/future

11:30 ;; When you dereference it you will block until the result is available.

11:30 user=> @f

11:30 done

11:30 100

11:33 justin_smith: tolitius: s/defer/deref

11:33 for deferring things, we have delay

11:34 martinklepsch: Is there a way to destructure for the last element of a sequence?

11:34 tolitius: justin_smith: light for of dyslexia.. :)

11:34 justin_smith: martinklepsch: no

11:35 tolitius: martinklepsch: can you revere it and destructure on the first one? :)

11:35 justin_smith: tolitius: OK, not trying to pick on you, just making sure things are clear

11:35 tolitius: *reverse

11:35 justin_smith: yep, clarity always welcome

11:42 justin_smith: today is a good day: I solved a problem in core.async elegantly by using mult and tap

11:58 sobel: woah. i just realized i need tap+mult for something. nice timing.

12:03 edbond: how to get all values from chan to coll?

12:06 justin_smith: (<! (into [] ch))

12:06 where into is core.async/into

12:06 edbond: justin_smith, all values I mean read until it's closed

12:06 justin_smith: "Returns a channel containing the single (collection) result of the

12:06 items taken from the channel conjoined to the supplied

12:06 edbond: justin_smith, thanks

12:06 justin_smith: collection. ch must close before into produces a result."

12:07 edbond: Have to read doc first

12:07 justin_smith: sorry for the multi-line paste

12:07 edbond: ,(inc justin_smith)

12:07 (inc justin_smith)

12:07 clojurebot: #error{:cause "Unable to resolve symbol: justin_smith in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: justin_smith in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6543]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: justin_smith in th...

12:07 lazybot: ⇒ 251

12:07 edbond: justin_smith, Thanks a lot

12:07 justin_smith: np

12:21 negaduck: here: (def ^:private event-chan (chan)) -- when we put! something and then <!, is the order guaranteed?

12:21 chan is from clojure.async

12:22 justin_smith: negaduck: it is guaranteed to give you results in the order the chan got them

12:22 negaduck: justin_smith: good

12:22 thanks

12:22 justin_smith: sometimes the order the chan got the results may be unpredictable when you have real threads :)

12:22 negaduck: justin_smith: I need to init things before real threads

12:23 I do this using events

12:23 justin_smith: OK

12:23 yeah, a channel is a queue under the hood

12:23 so that should just work

12:23 negaduck: ok, thanks

12:33 timvisher: anyone aware of some decent tutorials for `java.jdbc/with-db-transaction`?

12:41 gfredericks: ,(let [{:keys [:foo]} {}] foo)

12:41 clojurebot: nil

12:41 gfredericks: ,(let [{:keys ["foo"]} {}] foo)

12:41 clojurebot: #error{:cause "Unsupported binding form: foo", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.Exception: Unsupported binding form: foo, compiling:(NO_SOURCE_FILE:0:0)", :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6644]} {:type java.lang.Exception, :message "Unsupported binding form: foo", :at [clojure.core$destructure$pb__4915 invoke "core.clj" 4291]}], :trac...

12:53 justin_smith: gfredericks: that's weird

12:54 ,(let [{:keys [\f]} {}] f)

12:54 clojurebot: #error{:cause "Unsupported binding form: f", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.Exception: Unsupported binding form: f, compiling:(NO_SOURCE_FILE:0:0)", :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6644]} {:type java.lang.Exception, :message "Unsupported binding form: f", :at [clojure.core$destructure$pb__4915 invoke "core.clj" 4291]}], :trace [[cl...

13:59 chouser: ,(let [{:keys [:foo]} {:foo 42}] foo)

13:59 clojurebot: 42

14:00 Bronsa: ,(let [{:keys [::foo]} {::foo 42}] foo) ;; < this is why this is supported

14:00 clojurebot: 42

14:00 gfredericks: oh right

14:00 I remember now

14:04 timvisher: ah it looks like it might be better to use db-do-commands

14:05 although if i'm reading the docs right on that one it needs a series of sql commands and can't just wrap arbitrary statements. which makes sense

14:11 nope. that's not quite right either.

14:12 so i have a basic data access layer and two tables that should change in concert (job and job_status). To do that i'm using two different parts of the data access layer, one for each table. i'd like to wrap that in a transaction. what are my options?

14:42 is there something like javadoc for clojure?

14:42 i.e. specially formatted docstrings that could become documentation?

14:42 the only thing i'm aware of is something like codox but that doesn't do what i'm talking about

14:42 wasamasa: doesn't the clojure style guide recommend markdown?

14:45 timvisher: wasamasa: it might. that's not what i mean though. for instance, in javadoc documenting your paramaters is standardized and can become nice markup later.

14:45 i've never seen anything like that for clojure

14:45 kaiyin: is it possible to use jar files produced by scala? e.g. http://search.maven.org/#search%7Cga%7C1%7Cjhdf5

14:47 pbx: timvisher, this is all i can find: http://tomfaulhaber.github.io/autodoc/

14:47 amalloy: kaiyin: java is the lingua franca of jvm languages. scala stuff often has a java-friendly interface, and those are easy to use from clojure

14:48 timvisher: pbx: i had forgotten about that. looks interesting.

14:48 pbx: speaking as someone coming from python who uses sphinx docs a lot, even a de facto standard would be nice to have there

14:51 dnolen: timvisher: pbx: https://github.com/weavejester/codox

14:51 also https://github.com/gdeer81/marginalia

14:52 timvisher: dnolen: i knew about codox. doesn't seem to provide the functionality i'm talking about.

14:53 dnolen: timvisher: ah formatted docstrings, yeah not aware of anything

14:54 timvisher: pbx: agreed :)

14:54 puredanger: codox supports markdown in docstrings

14:55 but not the equivalent of param definitions

14:55 timvisher: puredanger: i don't mean manualy formatting. i mean light-weight markup. like javadoc

14:55 yes :)

14:56 well... 'light-weight' :)

14:56 i actually quite liked javadoc

14:56 pbx: i.e. semantic markup

14:56 Bronsa: puredanger: https://github.com/clojure/build.ci/commit/ed394232d4b407e08ac23758752f2ea3cc6704d2 need a hudson restart when you have a second

14:58 puredanger: Bronsa: in process

14:58 Bronsa: thanks

15:10 arohner: is there a way to determine if a core.async channel is closed, without taking from it?

15:17 edbond: how convert css selector "tr~ tr+ tr" to enlive?

15:20 tbaldridge: arohner: there's a predicate inside impl that exposes that, but it's not a public api

15:20 Channel/closed? I think it is...

15:20 arohner: tbaldridge: thanks

15:20 tbaldridge: it looks like there's a workaround using alts!!

15:20 because it always (?) returns nil if a channel is closed

15:22 dfletcher: man, comp is a cool function. just wrote my first function that way. who needs a whole new function when you can just jam the old ones together! defn is for suckers :D

15:23 wasamasa: dfletcher: you'lllike juxt

15:36 dfletcher: huh having a little trouble thinking of a great use case for juxt wasamasa. comp is easy. the first example I saw showed something like (comp resource input-stream slurp) ... so it's really natural to say "okay what more funcs can I add to the top of this to get the data into a usable state"

15:36 juxt - you'd use when you want to compare the output of several algos perhaps?

15:37 amalloy: dfletcher: anytime you want to do two different things to one thing

15:37 wasamasa: same here

15:38 amalloy: eg, ##((juxt filter remove) even? (range 10))

15:38 lazybot: ⇒ [(0 2 4 6 8) (1 3 5 7 9)]

15:38 wasamasa: the most useful example I saw involved using keywords as functions with juxt

15:38 amalloy: wasamasa: that's not a very good example; usually you're better off mapping the hashmap over a list of keywords, vs juxting the keywords together

15:38 dfletcher: ah like ((juxt identity name) :keyword)

15:38 in the docs

15:38 gfredericks: ((juxt identity deref meta) #'+)

15:38 amalloy: dfletcher: yes, that is a good one. (juxt identity whatever)

15:38 gfredericks: ,((juxt identity deref meta) #'+)

15:39 clojurebot: [#'clojure.core/+ #object[clojure.core$_PLUS_ 0x52f4db88 "clojure.core$_PLUS_@52f4db88"] {:added "1.2", :ns #object[clojure.lang.Namespace 0x4dedbf2e "clojure.core"], :name +, :file "clojure/core.clj", :inline-arities #object[clojure.core$_GT_1_QMARK_ 0x74d58b91 "clojure.core$_GT_1_QMARK_@74d58b91"], ...}]

15:39 pyr: dfletcher: i wrote a few words about juxt a while back: http://spootnik.org/entries/2013/05/21_poor-mans-pattern-matching-in-clojure.html

15:41 amalloy: dfletcher: there was a snippet used yesterday, which involved juxt. it's not a good example of code you should actually write, but if you are practicing higher-order functions you may have fun trying to puzzle out what (apply / ((juxt first (partial apply +)) (map (frequencies (repeatedly 1000 #(rand-nth [true false]))) [true false]))) does

15:43 dfletcher: whoa pyr you're case matching with an array? neat!

15:43 that is a pretty clever use

15:48 kaiyin: what does fn* mean?

15:48 amalloy: kaiyin: it's just a more primitive version of fn. pretend the * isn't there and you'll be fine

15:49 kaiyin: ok

15:51 when is :^once fn* useful? don't we just rely on garbage collection?

15:53 dfletcher: alright here's one. noticed that lots of core and some third party stuff takes a seq arg and processes them kinda like program args somtimes single somtimes in pairs: [ :random-thing :do-something :id "TheID" :selector ".poo" ] ... etc. is there magic that makes it easy to process these?

15:54 chouser: I'd recommend against such an api. Just pass in a map.

15:55 dfletcher: alright fair enough heh.

15:55 chouser: :-)

15:55 I've had to write code to produce such fancy inputs often enough to doubt their value.

16:23 Bronsa: kaiyin: http://clj-me.cgrand.net/2013/09/11/macros-closures-and-unexpected-object-retention/

16:24 dfletcher: ah now that I finished the end of this post pyr this really is a neat trick. overriding funcs using facets of data and it's all super clean. you're letting clojure do the dispatching. very good trick to have in the toolbox.

16:27 kaiyin: Bronsa: hm, look quite complicated.

16:27 lokks.

16:27 looks

16:34 Bronsa: kaiyin: it's not really, observe:

16:34 ,(def a (let [a [1 2]] (^:once fn* [] a)))

16:34 clojurebot: #'sandbox/a

16:34 Bronsa: ,(a)

16:34 clojurebot: [1 2]

16:34 Bronsa: ,(a)

16:34 clojurebot: nil

16:35 Bronsa: kaiyin: :once tells the compiler the fn will be executed only once and thus any closed-over local can be cleared after its use

16:35 arrdem: puredanger: seeing the above, is such an official lightweight markup in scope for our gsoc minion?

16:36 amalloy: kaiyin: consider something like (let [xs (range 1000000), f (fn [] (last xs))] (f))

16:36 puredanger: arrdem: explicitly out of scope

16:36 arrdem: mmkay

16:36 amalloy: inside of f, the elements of xs are being realized one at a time, but the GC can't throw them away because you still have a reference to f, and might call it again, which would need to re-walk the sequence again

16:36 puredanger: arrdem: purely to keep scope manageable

16:37 I expect going into that area to open up massive bikeshedding

16:37 arrdem: yeah for general markup, I'd push for at least a var linking and/or param notation tho

16:38 puredanger: see, you're starting it :)

16:39 arrdem: hey if I had my way we'd have a table and example notation :P

16:39 linking is small fry material

16:39 ^{:doc, :fancy-doc}

16:48 dfletcher: ,(str (.substring (clojure.string/join "" (take 10 (repeat (/ 0.0 0.0)))) 0 29) " Batman!")

16:48 clojurebot: "NaNNaNNaNNaNNaNNaNNaNNaNNaNNa Batman!"

16:48 dfletcher: lol im such n00b I'm sure that can be shorter.

16:48 code golf anyone? :>

16:49 tbaldridge: most of the string stuff can be replaced by:

16:49 .(apply str (take 10 (repeat 0)))

16:49 ,(apply str (take 10 (repeat 0)))

16:49 clojurebot: "0000000000"

16:49 justin_smith: ,(apply str (repeat 10 0))

16:49 clojurebot: "0000000000"

16:49 tbaldridge: that too

16:49 Bronsa: 000000000 Batman!

16:49 oddcully: thanks for putting that song again in my brain. this channel attracts this

16:51 justin_smith: ,(str (subs (apply str (repeat 10 (/ 0 0.0))) 0 29) " Batman!")

16:51 clojurebot: "NaNNaNNaNNaNNaNNaNNaNNaNNaNNa Batman!"

16:51 arrdem: heh

16:52 escherize: ,(doc subs)

16:52 clojurebot: "([s start] [s start end]); Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive."

16:55 dfletcher: heh it's weird trying to know what funcs might be wrapped and what I have to jump to Java for. guess it will come with expericence.

16:56 subs++

16:58 is there a way to use the threading macro when some of the funcs take more than one arg? Tried (-> "foo" #(.something other than else %) bar baz) but it explodes. similar when trying fn.

17:00 puredanger: you don't need the #

17:00 well, assuming the threaded value is the first arg that is

17:00 Bronsa: if it's the last you can use ->> rather than ->

17:00 if it's in some random position you can use as->

17:01 chouser: btw, beware of subs. Tends to throw exceptions at the slightest provocation.

17:01 puredanger: or read the multitude of options in this recent thread https://groups.google.com/forum/#!topic/clojure/saeI6tlQ9e8

17:02 dfletcher: ah ty

17:05 Fare: is there a good portable CL library for globbing?

17:05 justin_smith: dfletcher: http://conj.io has a good overview

17:05 amalloy: Fare: i imagine this would be the wrong channel to find an answer to that question

17:06 Fare: oops, wrong channel

17:06 thanks

17:07 in a hypothetical clojure-on-cl variant, should false and nil both be NIL, or should a separate value be create for either (and then which)?

17:14 amalloy: if it were me i'd make them both nil

17:24 kaiyin: ,(into-array (range 1e6))

17:24 clojurebot: #error{:cause "Java heap space", :via [{:type java.lang.OutOfMemoryError, :message "Java heap space", :at nil}], :trace []}

17:24 kaiyin: ,(into-array (range 1e2))

17:24 clojurebot: #object["[Ljava.lang.Long;" 0x5c82e9e "[Ljava.lang.Long;@5c82e9e"]

17:25 kaiyin: how can i solve this?

17:25 puredanger: solve what?

17:27 arrdem: making an array larger than main memory?

17:28 kaiyin: sorry, out of context. https://gist.github.com/kindlychung/455d586af55bb7262407

17:30 puredanger: int-array ?

17:31 (time (array-sum (int-array (range 400))))

17:32 there are of course faster ways to make that int-array as the range will create boxed longs

17:32 you can also get all-unchecked math automatically with: (set! *unchecked-math* true)

17:33 or unchecked math with boxed math warnings with (set! *unchecked-math* :warn-on-boxed)

17:33 that last only in clojure 1.7

17:39 kaiyin: puredanger: what is checked math then, i mean, what is being checked?

17:41 puredanger: overflow checks

17:42 normal math ops check and throw exceptions

17:42 ,(+ Long/MAX_VALUE 1)

17:42 clojurebot: #error{:cause "integer overflow", :via [{:type java.lang.ArithmeticException, :message "integer overflow", :at [clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]}], :trace [[clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501] [clojure.lang.Numbers add "Numbers.java" 1800] [sandbox$eval25 invoke "NO_SOURCE_FILE" 0] [clojure.lang.Compiler eval "Compiler.java" 6792] [clojure.lang.Comp...

17:42 puredanger: ,(unchecked-add Long/MAX_VALUE 1)

17:42 clojurebot: -9223372036854775808

17:42 puredanger: if *unchecked-math* is a truthy value, then you get the latter (faster) behavior

17:43 there is also +' which checks for overflow and auto-promotes

17:43 ,(+' Long/MAX_VALUE 1)

17:43 clojurebot: 9223372036854775808N

17:43 kaiyin: ok, i see.

17:43 thanks.

17:44 puredanger: most hot math loops use primitives and unchecked math for fastest perf

17:44 also, Hot Math, is my new band name

17:44 kaiyin: :)

17:45 what instrument do you play?

17:45 puredanger: in decreasing order of you wanting to listen to it: viola, piano, guitar

17:46 kaiyin: wow, polyglot in music.

17:48 tcrayford____: periodic PSA for folk running clojure in prod on java 7: upgrade to java 8, java 7 is EOL

17:53 ben_vulpes: https://github.com/samaaron/serial-port << what's the story with the "open" function on this page?

17:55 oh derp i'm a derp.

17:56 kaiyin: https://gist.github.com/kindlychung/6b1e2afd269cd3c074ae according to the "mastering clojure macros" book, there should be a 15x performance boost here, but there isn't.

18:02 puredanger: don't always believe what you read, especially when talking about performance :)

18:02 oddcully: benchmarking is believing

18:03 puredanger: range is faster in 1.7

18:03 and both reduce over range and reduce over arrays is significantly faster (neither uses seqs now)

18:04 what difference do you see?

18:06 kaiyin: I didn't see any.

18:06 what difference do you mean?

18:07 puredanger: I mean what was the perf difference

18:08 but you answered that

18:09 there's both allocation and boxing and checked math involved so it's a muddled comparison regardless

18:10 plus int-array is in there twice which does not seem like the intention, probably meant just y on the last line

18:10 kaiyin: puredanger: ah, my bad. will run it again.

18:12 tcrayford____: also you're likely in a lein repl with most of the jvm opts turned off (which is how lein does by default)

18:12 puredanger: yes, you'll want :jvm-opts ^:replace ["-server"]

18:12 or something like that

18:13 tcrayford____: also you're probably benchmarking on a laptop, and it's likely your production hardware isn't a laptop, also you're running the benchmarks in the same jvm (which can really get messed up with the JIT's path dependence), and and benchmarking is nearly always lies

18:14 dnolen: is there something simpler than this transduce for summing?

18:14 ,(transduce (map identity) + 0 [1 2 3])

18:14 clojurebot: 6

18:14 puredanger: why would you use transduce for that?

18:14 dnolen: puredanger: imagine that the last arg is not a collection :)

18:15 and transduce knows how to work on such a thing

18:15 puredanger: so does reduce?

18:15 dnolen: puredanger: imagine the last arg is an async process

18:15 and I've written a async-transduce

18:17 kaiyin: puredanger: there is indeed a 10x boost: https://gist.github.com/kindlychung/6b1e2afd269cd3c074ae

18:19 escherize: the google groups thread that lead to this was very interesting: https://pol.is/7scufp

18:22 puredanger: dnolen: well map identity should work and not do any allocations but it's still doing a worthless invocation

18:23 Bronsa: puredanger: dnolen isn't identity a valid transformation function?

18:23 dnolen: ,(transduce identity + 0 [1 2 3])

18:23 clojurebot: 6

18:24 Retsamtip: is it kosher to mention clojure jobs here? (am a CTO, not a recruiter)

18:24 AimHere: Retsamtip, I imagine it would be welcomed

18:24 dnolen: Bronsa: right nice because identity will return + which is a valid transformer

18:24 Bronsa: dnolen: what's the point of using transduce if you're not using any transducer though? you're just using it as reduce

18:24 oddcully: Retsamtip: in the past, there where jobs posted e.g. once per day

18:25 dnolen: Bronsa: I'm not actually using transduce, I'm using transducers w/ my own async driver

18:25 Retsamtip: ok, if anyone is sensitive to this let me know, thx AimHere

18:26 AimHere: Yeah; your ass is covered. I get the blame for whatever you do next!

18:26 Retsamtip: haha

18:26 oddcully: AimHere: a killban will tell you

18:26 Retsamtip: alright- any Clojurists in the NYC area should reach out, My co, Kontor is hiring actively

18:29 kaiyin: https://gist.github.com/kindlychung/cd025ba6b79848cb2168 why isn't this function working?

18:33 Bronsa: kaiyin: line 4, should be (f ret ..) rather than (f init ..)

18:35 kaiyin: Bronsa: ah, i see, thanks! I am just wondering why areduce has to be such a verbose macro: https://gist.github.com/kindlychung/cd025ba6b79848cb2168

18:36 with 5 args!

18:36 Bronsa: kaiyin: it has to be a macro rather than a function so that it can avoid boxing/reflection

18:36 turbofail: yeah if you were using a function version you could just use plain 'ol reduce

18:37 the only reason you'd use the macro is if you need the extra speed

18:38 kaiyin: ok, where does the avoidance of boxing/reflection occur? Not so obvious.

18:39 turbofail: basically the use of the function call in the function version of areduce requires boxing

18:40 there's no way to use unboxed arguments when calling the `f' argument to areduce1

18:40 Bronsa: kaiyin: say you're reducing a long[], using areduce (aget arr idx) will be inlined and the long will not be unnecessarily boxed

18:41 kaiyin: ok.

18:45 why is let [a# ~a] necessary? https://gist.github.com/kindlychung/cd025ba6b79848cb2168#file-areduce-macro-clj-L5

18:46 turbofail: the expression you pass in to the macro for `a' might not be constant

18:46 and may have side-effects

18:46 if it didn't bind it to a variable it would end up re-executing that expression a bunch of times

18:46 kaiyin: so let [a# ~a] is a kind of snapshot?

18:46 turbofail: yeah

18:52 kaiyin: what about this then: https://gist.github.com/kindlychung/cd025ba6b79848cb2168#file-ar2-clj

18:52 wouldn't it be a simplification?

18:53 Bronsa: kaiyin: as soon as you introduce `f` you're introducing boxing of the args

18:54 kaiyin: ok, i see.

19:07 chouser: No implementation of method: :put! of protocol: #'clojure.core.async.impl.protocols/WritePort found for class: clojure.core.async.impl.channels.ManyToManyChannel

19:08 Surely I'm supposed to be able to >!! on a channel?

19:10 ugh. reloaded protocols or similar. nevermind. :-P

19:25 Am I wrong to want async/keep instead of async/map?

19:29 escheriz`: When setting up a new website-like-project, do folks usually use Luminus? https://github.com/luminus-framework/luminus Or start from scratch? Or something else?

21:13 timvisher: do ns renames work? i.e. `(ns charnock (:require [whitefield :refer [piper] :rename {piper w-piper}]))`?

21:13 i can confirm that the above syntax doesn't work for me right now so i suppose the real question is how do i format that :)

21:13 creese: I'm looking for a JSON Schema library that supports draft 4. Is there such a thing?

21:20 timvisher: where is the documentation for `(:refer` in an ns form? i've never seen this before

21:22 it seems that's the way to get renames, but it would also appear to refer in all the other public vars in that ns

21:22 gfredericks: you can get renames with require

21:22 timvisher: gfredericks: ooo! tell me tell me :)

21:22 gfredericks: ,(require '[clojure.string :refer :all :rename {join uberjoin}])

21:22 clojurebot: #error{:cause "denied", :via [{:type java.lang.SecurityException, :message "denied", :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}], :trace [[clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69] [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkPropertyAccess nil -1] [java.lang.System getProperty "System.java" 708] [su...

21:23 gfredericks: welp

21:23 &(require '[clojure.string :refer :all :rename {join uberjoin}])

21:23 lazybot: ⇒ nil

21:23 gfredericks: &split

21:23 lazybot: ⇒ #<string$split clojure.string$split@330ace48>

21:23 gfredericks: &join

21:23 lazybot: ⇒ #<set$join clojure.set$join@3b7a1bf>

21:23 gfredericks: &uberjoin

21:23 lazybot: ⇒ #<string$join clojure.string$join@459225a0>

21:23 timvisher: gfredericks: i need it in the ns form

21:23 obviously it works with a call to require

21:23 gfredericks: yeah so you can do the same thing with require in the ns form

21:23 timvisher: oh

21:24 weird. let me check again. i thought i did that

21:24 gfredericks: the entries in the ns form are basically just calls to the equivalent functions

21:24 you can actually call any clojure.core function that way I think

21:25 it's a classic clojure party trick

21:25 timvisher: essentially i've got `(:require [compojure.core :refer [ANY context] :rename {routes c-routes}))`

21:25 and that seems to be blowing up

21:25 sec

21:26 gfredericks: you gotta refer routes too

21:26 timvisher: ah

21:26 gfredericks: it's a bit redundant

21:28 ,(require '[clojure.walk :rename {+ taco}])

21:28 clojurebot: nil

21:28 gfredericks: ,+

21:28 clojurebot: #object[clojure.core$_PLUS_ 0x6c2365aa "clojure.core$_PLUS_@6c2365aa"]

21:28 gfredericks: ,taco

21:28 clojurebot: #error{:cause "Unable to resolve symbol: taco in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: taco in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6543]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: taco in this context", :at [clojur...

21:28 gfredericks: well it was worth a try

21:29 timvisher: ,(ns charnock (:require clojure.string :refer [split] :rename {split s}))

21:29 clojurebot: #error{:cause "Unsupported option(s) supplied: :rename", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.Exception: Unsupported option(s) supplied: :rename, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.core$throw_if doInvoke "core.clj" 5626]} {:type java.lang.Exception, :message "Unsupported option(s) supplied: :rename", :at [clojure.core$load_libs doInvoke "core.clj" 57...

21:30 timvisher: hmm... is that the jail doing that? that's not the error i'm seeing

21:30 amalloy: no, you just have a totally wrong ns form

21:30 needs []s

21:31 gfredericks: add moar square parens

21:31 timvisher: lol

21:31 i shouldn't be coding...

21:31 amalloy: arguably you are not

21:32 timvisher: wait... since when have i not been able to use a list instead of a vector?

21:32 am i thinking of project.clj?

21:32 does it have to be a vector in the ns form?

21:33 didn't tbaldridge post some craziness forever ago when proposals were being made to change the ns form?

21:33 great scott! it worked!

21:34 seriously, i don't remember ever having tried this before but i thought vectors or lists there didn't matter one bit

21:34 that's never been a thing?

21:41 gfredericks: well the one you tried above didn't use a list either

Logging service provided by n01se.net