#clojure log - May 03 2013

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

0:00 axle_512: Raynes: Cool, I like it. I'll dig a little more into it and see if it's something I can use with my little scheduler

0:00 holo: (inc Raynes)

0:00 lazybot: ⇒ 28

0:05 djwonk: (dec djwonk)

0:05 lazybot: You can't adjust your own karma.

0:05 djwonk: (inc danielglauser)

0:05 lazybot: ⇒ 1

0:05 holo: thanks to Raynes, and numerous contributors for tryclj.com, my girlfriend could try programming without setting her hair on fire. she actually enjoyed it

0:06 djwonk: (inc clojurebot)

0:06 lazybot: ⇒ 21

0:06 djwonk: (inc technomancy)

0:06 lazybot: ⇒ 53

0:06 djwonk: (inc lazybot)

0:06 lazybot: ⇒ 18

0:07 Raynes: holo: It's all a cunning plot to steal your girlfriend.

0:09 holo: she was sad there weren't more levels to solve though.. just imagine how many more girls are out there.. trying clojure

0:09 Raynes: Oh dear. I'll get right on it.

0:10 holo: :>

0:11 amalloy: holo: 4clojure.com?

0:12 holo: amalloy, she gave up on that one. not because of difficulty i think (some problems are indeed really easy), but because it was enough for the day

0:14 axle_512: Raynes and amalloy: Read the code for chronicle. That is slick — I love the lazy seq of times that match the spec.

0:15 amalloy: it's good that you love it, because that is literally the only thing in chronicle

0:15 axle_512: haha

0:15 simplicity is good

0:15 amalloy: yeah, i wrote it in an hour. now Raynes will market it for me

0:24 callen: Clojure: programming without the burning hair.

0:26 holo: Clojure: the fresh maker

0:29 arrdem: Clojure: macros for the JVM

1:00 technomancy: holo: let's film a series of advertisements

2:38 tomoj: should ring provide names for comp and #(comp %2 %1)?

2:42 hmm, not #(comp %2 %1)

2:45 oh, yeah. https://www.refheap.com/paste/163cd2a1090c780ac4b2b8ba2

2:46 I guess I can just keep writing those functions in many namespaces since it's just two lines..

2:52 augustl: pjstadig: ah, the good old source :)

2:52 I guess clojure.core/addMethod could be considered a public and supported API

2:54 tomoj: hmm https://www.refheap.com/paste/765fc76fe098a715d6edd1239

2:56 oh that's just (def in-response ((in-args reverse) (partial partial comp)))

3:55 Glenjamin: tomoj: i don't quote follow the example at the bottom, where abouts in a ring app would you need this?

3:57 mindbender1: what is cljs version of js/Array?

3:57 this issue has been bugging me

4:00 tomoj: mindbender1: (array) ?

4:00 what do you mean

4:00 Glenjamin: anytime you want a middleware which just applies a function to the request or the response

4:01 Glenjamin: doesn't ring have separate request/response maps? or am i just blinkered by compojure here?

4:01 tomoj: yes

4:01 Glenjamin: ah, i see

4:01 tomoj: the example is not ring-conformant

4:01 mindbender1: I mean something that allows me to insert anywhere and have the index re-ordered

4:02 tomoj: and also I was actually thinking of clj-http middleware.. is it the same for ring?

4:02 Glenjamin: ring has request map in, and response map out

4:03 tomoj: oh yeah, it's the same-ish

4:03 Glenjamin: (def app (fn [req] {:status 200, :body "Hello World", :headers {}}))

4:04 tomoj: mindbender1: hmm.. port clojure.core.rrb-vector ?

4:04 mindbender1: let me see..

4:04 Glenjamin: so middleware can either operate on req and pass it along, or call the wrapped function, operate on the returned response and pass it back

4:04 tomoj: then you'd have slice conj slice splice for an insert-at

4:05 or maybe finger trees?

4:05 no cljs version of that yet afaik either

4:07 Glenjamin: yeah -- (fn [app] (fn [req] (app (f req)))) is comp, and (fn [app] (fn [req] (f (app req)))) is #(comp %2 %1)

4:07 ..well, with the f param somewhere in there

4:16 ddellacosta: what's the best way to short-circuit an iteration? I mean, what kind of looping construct to use? filter is close, but I want something more like Ruby's detect: http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-detect

4:16 I feel like I must be missing something obvious.

4:16 Glenjamin: ddellacosta: you probably want some

4:17 ddellacosta: Glenjamin: THAT'S what I've been looking for…thanks!

4:17 Glenjamin: ,(doc some)

4:17 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

4:17 ddellacosta: yes, perfect.

4:17 I always forget about "some."

6:37 augustl: I end up writing this function quite often: (defn assoc-if [m key value] (if value (assoc m key value) m))

6:38 only assoc if the value is truthy. I use this for threading macro goodness, such as (-> base-data (assoc-if :some-key some-value))

6:38 since assoc-if is not in core, and I find it insanely useful, I guess I'm "doing it wrong" :) Anyone got some favorite ways of doing hashmap building based on conditions?

6:39 tomoj: well there is (cond-> m value (assoc key value)) :/

6:41 jballanc: ,(let [value true] (and value (assoc {} :test value)))

6:41 clojurebot: {:test true}

6:41 jballanc: I find 'and' and 'or' are underutilized...but that may just be me

6:43 tomoj: here they are not very helpful

6:44 jballanc: ah, I see...the hash should still be returned if value is false

6:44 hmm...

6:45 ,(let [value false m {:first "thing"}] (and (or value m) (assoc m :test value)))

6:45 clojurebot: {:test false, :first "thing"}

6:45 jballanc: oh, whoops

6:45 hmmm...

6:46 ,(let [value false m {:first "thing"}] (or (and value (assoc m :test value) m))

6:46 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

6:46 jballanc: d'oh

6:46 ,(let [value false m {:first "thing"}] (or (and value (assoc m :test value)) m))

6:46 clojurebot: {:first "thing"}

6:46 tomoj: seems like a strange way to write (if value (assoc m :test value) m) :)

6:46 jballanc: there we go

6:46 heh

6:47 tomoj: &(clojure.walk/macroexpand-all '(or (and value (assoc m :test value))))

6:47 lazybot: ⇒ (let* [and__3822__auto__ value] (if and__3822__auto__ (assoc m :test value) and__3822__auto__))

6:47 clgv: augustl: go for `cond->` as proposed

6:48 tomoj: oops

6:48 &(clojure.walk/macroexpand-all '(or (and value (assoc m :test value)) m))

6:48 lazybot: ⇒ (let* [or__3824__auto__ (let* [and__3822__auto__ value] (if and__3822__auto__ (assoc m :test value) and__3822__auto__))] (if or__3824__auto__ or__3824__auto__ m))

6:49 jballanc: haha

6:49 yeah, I keep forgetting that and/or are macros and if is the special form

6:49 tomoj: semantically equivalent in this case?

6:50 jballanc: I swear that's backward from one of the schemes I've used...

6:50 tomoj: I always think it's the other way too

6:53 augustl: thanks folks :)

6:54 why u not 1.5, http://clojure.org/cheatsheet !

6:55 tomoj: (filter (comp #{"1.5"} :added meta) (vals (ns-publics (find-ns 'clojure.core)))) :)

6:56 I just realized that that's fucking sweet

6:58 augustl: tomoj: ah, nice one :)

7:12 is zipmap "the best" way to map the values of a hashmap?

7:12 seems wasteful to create so many temporary collections

7:13 Velrok: Hi, quick question:

7:14 I have some problems resolving a java class

7:14 cern.colt.matrix.io.MatrixInfo.MatrixField

7:14 CompilerException java.lang.ClassNotFoundException: cern.colt.matrix.io.MatrixInfo.MatrixField, compiling:(NO_SOURCE_PATH:1)

7:14 (import (cern.colt.matrix.tint.impl SparseIntMatrix2D)

7:14 (cern.colt.matrix.tdouble.impl SparseDoubleMatrix2D)

7:14 (cern.colt.list.tint IntArrayList)

7:14 (cern.colt.matrix.io MatrixVectorWriter

7:14 MatrixVectorReader

7:14 MatrixInfo

7:14 MatrixSize)

7:15 user=> cern.colt.matrix.io.MatrixInfo

7:15 cern.colt.matrix.io.MatrixInfo

7:15 works

7:15 brainproxy: Velrok: please use gist or refheap

7:15 noidi: augustl, (into {} (for [[k v] m] [k (f v)]))

7:16 where m is your map and f is the function to map over the values

7:16 augustl: noidi: ah, cool

7:17 noidi: that iterates over the entires in the map, destructuring them into a key and a value, and creating a vector that is close enough to a MapEntry that it can be stuffed into a new map

7:17 Velrok: as suggested here the code as gist: https://gist.github.com/Velrok/5508551

7:19 Do I have to change my import call? I can't access inner classes of MatrixInfo

7:21 noidi: Velrok, try MatrixInfo$MatrixField

7:21 AFAIK that's the real name of the inner class

7:21 MatrixInfo.MatrixField is syntactic sugar provided by Java (again AFAIK)

7:21 Velrok: Indeed

7:22 Thanks @noidi

7:24 cern.colt.matrix.io.MatrixInfo$MatrixField works but

7:24 MatrixInfo$MatrixField fails

7:25 do I have to giv it the complete name space ?

7:27 Ah ok

7:28 I also need to import MatrixInfo$MatrixField

7:28 (cern.colt.matrix.io MatrixVectorWriter

7:28 MatrixVectorReader

7:28 MatrixInfo

7:28 MatrixInfo$MatrixField

7:28 MatrixSize)

8:04 luxbock: has anyone here tried writing a Firefox extension using ClojureScript?

8:34 TimMc: Velrok: Please don't paste more than 1 or 2 lines to the channel -- use a pastebin such as http://refheap.com or http://gist.github.com instead.

8:35 Velrok: @TimMc ok Thanks

8:41 dnolen: luxbock: someone mentioned doing a Chrome Ext at one point I think

10:01 jcromartie: so here's something I wish Clojure had: lazy maps

10:02 i.e. in OOP languages I can make a class with a variety of lazy property getters

10:02 but in Clojure if I want some sort of associative structure it usually has to be all-or-nothing

10:02 like, for parsing content from a URL

10:03 If the map values are functions that use futures or delays, then that is one option

10:04 I guess @(:title foo) is not too bad

10:04 nDuff: jcromartie: you can certainly implement clojure.lang.Associative yourself.

10:04 tomoj: or just ILookup

10:06 but what happens when you print the "lazy map"?

10:06 I was thinking about something somewhat related earlier, I'm putting lazy IO seqs in ring responses, so if you print the response that causes IO...

10:07 well that's probably just nuts

10:08 jcromartie: yeah I suppose there's nothing stopping a lib from implementing this

10:09 tomoj: say, datomic

10:09 with lazy EntityMaps

10:13 juhu_chapa: kjkl

10:22 beaky: hello

10:33 where can I read more about design patterns related to functional programming?

10:39 stuartsierra: clojurescript 0.0-1798 is out the door and on its way.

10:39 poi519: beaky: if you find anything, let me know please. I do not think there are many design patterns already, though.

10:41 beaky: ah

10:43 stuartsierra: beaky - I did a talk at Strange Loop last year called "Functional Design Patterns." The video is on InfoQ. Pretty basic stuff, but maybe useful.

10:46 beaky: ah thanks

10:46 poi519: stuartsierra: thanks, watching

10:47 ambrosebs: It would be nice if *out* had a Writer type hint.

11:58 gdev: ,(= *)

11:58 clojurebot: true

11:59 gfredericks: ,(= * + -)

11:59 clojurebot: false

12:00 kmicu: , (= comp comp comp complement true)

12:00 clojurebot: false

12:01 poi519: ,(if nil true false)

12:01 clojurebot: false

12:03 justin_smith: ,(= (/ 0.0 0.0))

12:03 clojurebot: true

12:03 justin_smith: NaN should not equal NaN, I would call that a bug

12:05 ,(== (/ 0.0 0.0) (/ 0.0 0.0))

12:05 clojurebot: false

12:05 justin_smith: ,(== (/ 0.0 0.0))

12:05 clojurebot: true

12:05 justin_smith: bugs

12:06 IamDrowsy: ,(= (/ 0.0 0.0) (/ 0.0 0.0))

12:06 clojurebot: false

12:06 IamDrowsy: NaN isn't equal to NaN...

12:06 justin_smith: right

12:07 but (== (/ 0.0 0.0)) implies it is

12:07 IamDrowsy: the equality of a single element is true because it makes not alot of sense to check the equality of a single thing

12:07 justin_smith: until things are not supposed to be equal to themselves

12:08 edoloughlin: ,(doc ==)

12:08 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums all have the equivalent value (type-independent), otherwise false"

12:08 edoloughlin: Not 'equal', but 'equivalent'???

12:08 lazybot: edoloughlin: How could that be wrong?

12:17 IamDrowsy: well i dont think you can get it right... because you can always argue in different directions.. so its more a decision then a bug

12:18 TimMc: NaN is a bug. :-/

12:18 justin_smith: yeah, but it is a bug in a standard

12:19 TimMc: I actually don't see what's wrong with (= Double/NaN) => true

12:19 You're not aksing whether NaN = NaN, you're saying that there are no argument pairs where = yields false.

12:19 And there are no argument pairs, period.

12:20 IamDrowsy: so the bug is that (= Double/NaN Double/NaN) is false?

12:20 justin_smith: no

12:20 that is correct behaviour

12:20 TimMc: That's "broken as designed".

12:25 manutter: "NaN is not equal to anything, including itself."

12:26 * manutter read that somewhere..

12:26 clgv: manutter: what's the philosophical or technical idea behind that?

12:26 bbloom: clgv: i believe there are multiple ways to represent NaN

12:27 axle_512: manutter: I think that is correct. Instead of comparing NANs, use isNaN()

12:27 bbloom: so it would be weird to have SOME nans be equal

12:27 yeah, see http://stackoverflow.com/questions/640109/what-is-the-internal-representation-of-inf-and-nan

12:27 manutter: If I understand correctly, NaN represents what something *isn't*, so it's not really a thing in-and-of itself

12:27 clgv: ,-0

12:27 clojurebot: 0

12:27 clgv: ,-0.0

12:27 clojurebot: -0.0

12:28 clgv: ,(= -0,0 0,0)

12:28 clojurebot: true

12:28 bbloom: weeee floating point

12:28 clgv: ^^

12:28 axle_512: bbloom is right, for doubles and floats, there is more than one way a NAN can be represented bitwise

12:29 bbloom: floats are a PITA ##(= (/ 1.0 3.0) 0.33333333333333334)

12:29 lazybot: ⇒ true

12:29 clgv: bbloom: you should learn that in programming courses ;)

12:30 avishai: hi

12:30 i'm a total clojure noob

12:30 doing a ring toturial

12:30 axle_512: avishai: hi

12:30 avishai: hi

12:30 bbloom: clgv: don't they teach twos complement and IEEE representation in early CS courses? i'm pretty sure we covered that...

12:30 avishai: i got not locate ring/middleware/reload__init.class or ring/middleware/reload.clj on classpath

12:31 not sure why

12:31 clgv: yeah they do. that was what I meant ^^

12:31 weavejester: avishai: Have you included the ring/ring-devel dependency?

12:31 avishai: as dev-dependency

12:32 bbloom: the real bitch of floating point math is that it actively thwarts analysis

12:32 clgv: bbloom: I have some thousands of floating point numbers that probably need to be added in a divide-and-conquer manner... :/

12:32 bbloom: you want to do common expression elimination? constant folding? NOPE

12:33 justin_smith: hell, they aren't even transative, yay

12:33 weavejester: avishai: Using :dev-dependencies, or :profiles {:dev {:dependencies …}} ?

12:33 technomancy: at least they're fast =\

12:33 bbloom: clgv: communicative? associative? transitive? NOPE

12:33 avishai: :dev-dependencies

12:33 haven't yet mastered the secrets of lein profiles

12:34 weavejester: avishai: That's been deprecated in Leiningen for a while. I don't think the latest Leiningens support it… do they, technomancy?

12:34 technomancy: yeah, :dev-dependencies is for lein1

12:34 bbloom: technomancy: agreed, but totally the wrong default (holy hell i freak out when i see people tracking money in floats) and absolutely the wrong ONLY POSSIBLE SOLUTION (argh javascript)

12:34 weavejester: avishai: Profiles are pretty easy. They're just maps that are merged into your main project map.

12:34 technomancy: bbloom: are there any languages where decimal literals read as non-floats?

12:35 justin_smith: technomancy: sql?

12:35 not that sql decimals are a good thing mind you

12:35 bbloom: technomancy: common lisp?

12:35 avishai: which means?

12:35 technomancy: justin_smith: heh; I was just wondering whether it would be a cautionary tale of woe =)

12:35 avishai: how do i choose which profile to work with?

12:36 technomancy: bbloom: huh; I had no idea

12:36 bbloom: gnu clisp doesn't even support IEEE floats

12:36 technomancy: haha

12:36 bbloom: IEEE is an extension that most impls have

12:37 technomancy: I am surprised CLers don't lord that over other languages more.

12:37 weavejester: avishai: Well, lets say you have {:dependencies [foo "1.0"]} in your project

12:37 avishai: yes

12:37 bbloom: technomancy: they are too busy arguing about things that don't matter

12:37 weavejester: avishai: And you also have: {:profiles {:dev {:dependencies [bar "1.0"]}}}

12:37 avishai: so far

12:37 bbloom: technomancy: the most important thing that Clojure did for lisp was to change the subject

12:38 weavejester: avishai: Then when the dev profile is active, the content of the dev profile is merged into your main project.

12:38 avishai: that i got

12:38 weavejester: avishai: So with the dev profile, you have deps foo and bar

12:38 avishai: but how do i choose which profile is active?

12:38 technomancy: bbloom: heh

12:38 weavejester: avishai: By default the following profiles are active: user, dev and … um, some other one whose name escapes me

12:39 avishai: You can choose profiles explicitly with "lein with-profile <profile> <command>"

12:39 avishai: ah

12:39 weavejester: avishai: So I usually have a profile for testing different clojure versions

12:39 avishai: and the default is dev?

12:39 weavejester: avishai: So I can run: lein with-profile 1.3 test

12:39 avishai: To test against Clojure 1.3

12:39 avishai: ah

12:40 now i have a ton of other questions....

12:40 weavejester: avishai: And in my project file: {:profiles {:1.3 {:dependencies [org.clojure/clojure "1.3.0"]}}}

12:40 avishai: You can have multiple profiles active at once, so the default is user + dev + something-else

12:40 avishai: found the profiles docs

12:41 i'll look there and not waste your time

12:41 weavejester: Oh, :provided

12:41 :user, :dev and :provided are active by default

12:41 bbloom: technomancy: like on the latest HN post RE: Light Table…. some dude was clojure bashing b/c clearly all good ideas were had by mccarthy

12:41 avishai: 10x

12:41 and dev-dependencies == {:profiles {:dev {:dependencies ?

12:42 technomancy: bbloom: or the one about how we shouldn't have reader syntax for hash tables because the reader doesn't know what performance characteristics we're going to want

12:42 bbloom: technomancy: the most common argument is "reader macros can do that"

12:42 which is the stupidest thing i've ever heard

12:42 turing machines can do it too!

12:43 defaults fucking matter people.

12:43 gdev: tail calls can do it from behind

12:51 avishai: ok, it works with :dependencies

12:51 so i guess :dev-dependencies was just wrong

12:51 10x

12:51 nDuff: ...

12:51 technomancy: avishai: if you can report a bug or whatever with the docs you found that would be decent

12:52 jcromartie: I really appreciate the fact that deploying the average Clojure system requires only Java as a dependency...

12:52 * jcromartie is trying to run a Rails app on EC2

12:53 * nDuff scowls at "10x", and goes on to shake his cane at the damn kids on his lawn.

13:07 ppppaul: i find it a bit strange that dissoc and select-keys have different protocols

13:08 justin_smith: someone probably has a function that returns two maps, the first a select-keys and the second a dissoc - I could imagine that being very useful

13:08 avishai: question

13:08 regarding ring performance

13:08 ppppaul: i just made one

13:08 weavejester: avishai: Go ahead

13:08 avishai: i take it the dev setup isn't optimized

13:09 by after testing a "hello world" handler, it's .... slow

13:09 compared to go or ever cherrypy

13:09 compared to go or even cherrypy

13:09 on my laptop i get around 6k rps

13:10 weavejester: avishai: To be honest I haven't checked the development setup

13:10 avishai: ah

13:10 ppppaul: (def split (juxt select-keys (partial apply dissoc)))

13:10 avishai: so i'll rephrase

13:10 justin_smith: ppppaul: nice

13:10 avishai: is clojure ring performance much worse the say java + jetty?

13:10 ^the^then

13:10 ppppaul: i just find it a bit weird that these functions have such different protocols

13:11 nDuff: avishai: There was a recent benchmark with a huge number of languages/tools that got published around a bit.

13:11 weavejester: avishai: http://www.techempower.com/benchmarks/ indicate it's around twice as slow, at least when deployed as a servlet.

13:11 nDuff: Ahh, that's the one.

13:12 avishai: i can live with twice as slow

13:12 weavejester: I suspect that using dedicated adapter would push up the speed considerably.

13:12 avishai: instead of the jetty adapter?

13:13 weavejester: Yes, because the Jetty adapter sits on top of the servlet interface.

13:13 I've been meaning to run that benchmark suite against something like https://github.com/RallySoftware/netty-ring-adapter

13:14 It should be a fair bit quicker. Enough to push Compojure into the top 10 at least.

13:14 nDuff: avishai: Notably, those benchmarks put compojure and (especially) http-kit well ahead of _any_ Python-based framework.

13:14 avishai: well, since in real life performance degrades mostly due to logic and implementation

13:15 nDuff: *nod*.

13:15 avishai: i prefer a language which is clear but a little slower

13:15 * nDuff wholeheartedly agrees.

13:15 avishai: then tons of horsepower with many quirks

13:15 mefisto: or more to the point, tons of horespower but you have to supply your own wheels :D

13:16 avishai: if only my wheels weren't so edgy

13:19 gdev: i think of it more as mpg

13:19 you get more milage per gallon of effort

13:21 justin_smith: which reminds me, I need to top off my effort tank

13:28 avishai: another question

13:28 is there an encoding middleware?

13:29 e.g. to serialize be accept header?

13:47 justin_smith: avishai: yes, there are middlewares for headers and encoding, for example I am looking at ring.middleware.content-type in my code at the moment

14:03 mabes: whenever I use nrepl-macroexapnd it simply puts the name of the macro I'm trying to expand in the buffer.. so, I must be doing something wrong. I've tried highlighting the form in question but that didn't work.. any tips?

14:04 justin_smith: ,(macro-expand '(#(+ % %) 1))

14:04 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: macro-expand in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:05 justin_smith: ,(macroexpand '(#(+ % %) 1))

14:05 clojurebot: ((fn* [p1__69#] (+ p1__69# p1__69#)) 1)

14:05 mabes: yeah, I've resorted to doing the expansion in the repl... I was just curious if I was making a common mistake in using nrepl.el

14:07 silasdavis: with sqlkorma, where are you meant to place your defentity declarations?

14:07 gdev: silasdavis:) since it uses the last defdb as its default, if you place it after that you won't have to specify the db

14:09 silasdavis: gdev, so do I just have to ensure that file get's loaded before I run queries in another file?

14:09 gets*

14:10 gdev: silasdavis:) yeah definitely

14:11 otherwise you'll get a symbol not found exception

14:11 amalloy: mabes: if it's anything like slime, point has to be on the open-paren at the start of the macro invocation

14:11 mabes: amalloy: ah, that was it. thanks!

14:13 gdev: silasdavis:) is your project on github?

14:13 mabes: I need a macro to reference a var that lives in the same namespace as the macro.. right now I'm manually referencing the fully qualified var in the macro... Is there a better way to do this so that the fully qualified var gets expanded for me?

14:15 i.e. I have something like: (ns foo-bar) (def foo 23) (defmacro my-macro [& body] `(something foo-bar/foo ~@body)) ... can I replace the foo-bar/foo with something that gets expanded to that?

14:17 silasdavis: gdev, not publically I'm afraid

14:17 clojurebot: Gabh mo leithscéal?

14:18 gdev: silasdavis:) that's fine, I just realized mine wasn't either, so I'm putting it up there now

14:20 now i'm trying to figure out how I can set the db connection information from a settings file that gets gitignored instead of putting user names and passwords hardcoded on the internet

14:21 klrr: is there any clojure implementation that compiles to machine code?

14:25 amalloy: mabes: yes, just foo will do that, when inside a syntax-quote

14:26 &`(inc 10), for example

14:26 lazybot: ⇒ (clojure.core/inc 10)

14:26 mabes: amalloy: nice.. I thought I had tried that.. thanks!

14:28 mikerod: Is there a "term" to describe a macro that incorrectly generates code if the arguments given are "complex" forms instead of forms that evaluate to themselves.

14:28 Since this doesn't make sense much as I explain, an example is: (defmacro mc [x] `(let [y ~(resolve x)]))

14:28 nightfly__: broken

14:28 mikerod: Where (mc MySymbol) is ok, but (mc (symbol (str "MySymbol"))) is not.

14:29 nightfly__: Hah, yes broken indeed.

14:29 amalloy: aw, nightfly__ got to my joke before i'd even finished reading the question

14:30 although, mikerod, that particular example is so poorly written that it generates incorrect code no matter what arguments are passed to it

14:30 mikerod: I was just wondering if there is a good way to describe that situation. Where the macro doesn't work depending on how the structure of the argument passed to it.

14:31 amalloy: I know that was a poor example. I'm just looking for a way to describe the macro mistake of assuming the argument takes a certain form before evaluation

14:31 amalloy: mikerod: i mean, a reasonable point of view is that *every* macro and function must assume its arguments take a certain form. the problem you're describing is making the wrong assumption

14:31 so it's really just "bad code"

14:37 gdev: so in leiningen I was trying to create a new project inside an existing directory with the same name that lein new would've generated, --to-dir for the win

14:39 (inc technomancy)

14:39 lazybot: ⇒ 54

14:39 nightfly__: (incf lazybot)

14:40 technomancy: I didn't do that

14:41 gdev: karma for good documentation?

14:42 i didn't have to submit a feature request to see it already existed, just command line help files

14:47 _{^_^}_:) Y U NO pick one name and stick with it?

14:49 _{^_^}_: gdev: cause im indecisive, im seeking help

14:52 nDuff: _{^_^}_: I'd suggest something you'd be willing to live with indefinitely. On which point, cute has a limited shelf life.

14:53 hfaafb: _{^_^}_ clearly has issues picking names

14:55 [tab][tab][tab]: *cough*

15:05 gdev: whats the opposite of currying?

15:05 beaky: uncurrying

15:06 :t uncurry

15:06 (a -> b -> c) -> (a, b) -> c

15:07 bbloom: beaky: eehhh not really

15:08 beaky: :(

15:08 gdev: I thought it was yogurting

15:08 bbloom: beaky: yes, you are correct that that is the type of uncurry in haskell

15:08 however, it's not really the inverse of "curry"

15:08 beaky: ah right

15:09 bbloom: well sorta

15:09 technomancy: a reversible partial application would have to store the original fn somewhere

15:09 bbloom: it IS the inverse of haskell's curry function

15:09 lol

15:09 but haskell functions DO CURRYING

15:09 gdev: i asked for the opposite, not the inverse

15:09 bbloom: and the uncurry function makes them NOT do currying

15:09 rasmusto: is it lunchtime?

15:09 beaky: haskell automagically currys for you

15:09 bbloom: mmm curry.

15:10 beaky: imo curry would be a cool name for a functional programming language

15:10 bbloom: beaky: it was one of the candidate names for haskell, if i recall correctly heh

15:10 curry :: ((a, b) -> c) -> a -> b -> c

15:10 curry converts an uncurried function to a curried function.

15:10 uncurry :: (a -> b -> c) -> (a, b) -> c

15:10 uncurry converts a curried function to a function on pairs.

15:11 that's with the doc strings ^^

15:11 gdev: stuartsierra:) wtf is yogurting?

15:13 raek: beaky: there is a logic programming language called curry..

15:14 beaky: ah

15:14 where did the name 'clojure' come from?

15:14 gdev: closure + java

15:15 pppaul: cloja

15:15 beaky: ah

15:15 gdev: coca-cloja

15:15 beaky: what's a closure?

15:15 gdev: a resolution to a conflict

15:15 pppaul: sounds like an anxiety attack

15:16 raek: beaky: a function with its lexical environment

15:16 gdev: lisp and the jvm had a huge fight, went out for beers and realized they needed clojure

15:17 beaky: a closure is a poor man's objects

15:17 or was it the other way around?

15:17 raek: hehe :)

15:18 gdev: Joel Moses credits Landin with introducing the term closure to refer to a lambda expression whose open bindings (free variables) have been closed by (or bound in) the lexical environment, resulting in a closed expression, or closure

15:19 beaky: ah

15:19 gdev: adopted by Sussman and Steele in Scheme in 75 which is where it became widespread

15:19 beaky: so it's like a function escaping and forming its own universe?

15:20 gdev: it's often mistakenly used to mean an anonymous function

15:20 beaky: ah

15:21 yeah closures are a bit more than lambadas

15:21 gdev: lambadas?

15:21 mikerod_: amalloy: I had a meeting and couldn't follow up earlier (I asked about a a term for a macro that depends on the structure of the unevaluated form).

15:21 beaky: lambads*

15:21 gdev: lambads?

15:21 beaky: lambdas*

15:23 gdev: also to make things even more confusing, http://shop.oreilly.com/product/0636920001416.do

15:23 mikerod_: The concept I was getting at is would you consider a macro to be poorly written, if the caller of the macro had to know to treat it differently than calling a function?

15:23 bbloom: beaky: i think that objects are one way to implement closures :-)

15:24 mikerod_: If a macro specifies that it is to take a symbol as an argument, but then it doesn't accept forms that evaluate to a symbol.

15:24 bbloom: beaky: and, given an alternative implementation of closures, then closures are one way to implement objects ;-)

15:24 beaky: ah thats a nice way to think about that; that's what I use c++ classefor

15:24 clases*

15:28 gdev: Closures were left out of Java initially more because of time pressures than anything else. In the early days of Java the lack of closures was pretty painful, and so inner classes were born: an uncomfortable compromise that attempted to avoid a number of hard issues. But as is normal in so many design issues, the simplifications didn't really solve any problems, they just moved them.

15:28 quote from James Gosling

15:29 bbloom: well yeah, "final" variables plus inner classes ARE closures

15:29 they just aren't also lambdas

15:29 :-P

15:29 beaky: ah

15:29 what's an inner class?

15:30 bbloom: an inner class (in java anyway) is when you define a class within a class

15:30 or even within a method

15:30 * beaky still thinks java is an island in indonesia

15:30 beaky: ah

15:30 bbloom: the compiler will rewrite that class to have a name like TheParentClass$TheChildClass

15:30 gdev: java can only have one public class for every class file, but it can have as many non-public ones it wants

15:30 bbloom: and then rewrite the constructor and calls to 'new TheChildClass(foo)' to be 'new TheChildClass(TheParentClass.this)'

15:31 rather 'new TheChildClass(TheParentClass.this, foo)'

15:31 effectively closing over "this"

15:31 beaky: so in java every file may only export a single class? :(

15:31 bbloom: a single top level class, yes

15:31 beaky: ah

15:31 bbloom: however, if you make a final variable and then use it inside an inner class, the constructor will be rewritten there too to take a copy of that variable

15:31 that's why it needs to be final

15:31 it's not a true closure

15:32 ti's a manually hacky closure via rewriting constructors to patch up the closure

15:32 gdev: on the file system you'll have Foo$InnerFoo.class and Foo$1.class for inner classes and anonymous inner classes

15:32 llasram: Except for may be "static inner classes", which AFAICT are the same damn thing as regular classes modulo the funky `$` in their name

15:32 Plus the convenience of being able to have more than one per file

15:33 gdev: anonymous innerclasses are also a way to add listeners

15:33 bbloom: well, the static modifier on a class just says "dont add TheParentClass.this" to the constructor :-)

15:35 gdev: if you've had to deal with listeners, factory patterns, IOC, decorators, or iterators in java you appreciate Clojure a lot more

15:36 beaky: ah I never programming in java

15:36 I've never coded in java*

15:37 gdev: give it a try =D

15:37 llasram: Just other parts of Indonesia?

15:37 beaky: :D

15:37 I heard that java was a nice programming language

15:38 gdev: depends on your definition of "nice"

15:38 axle_5121: a lot of people pick on java today, but it was one of the first to really reach that holy grail of platform independent executables

15:38 bbloom: axle_5121: people pick on the language more than the virtual machine

15:39 beaky: the virtual machine is genius

15:39 bbloom: axle_5121: the JVM and core libraries was/is/are a fine piece of work

15:39 axle_5121: bbloom: agreed

15:39 bbloom: the language was (obviously) very successful in this respect:

15:40 "We were not out to win over the Lisp programmers; we were after the C++ programmers. We managed to drag a lot of them about halfway to Lisp."

15:40 - Guy Steele, Java spec co-author

15:40 axle_5121: Yes, it definitely was a more palattable version of C++

15:40 TimMc: cemerick: Did you end up creating a ticket for automatic namespace loading for defrecords? https://groups.google.com/forum/#!msg/clojure-dev/4CtSVWcD15A/shpMuyjMpxsJ I can't find one.

15:40 axle_5121: palatable even.

15:42 mikerod_: I'm a bit of an IRC n00b. What causes/caused my "nick" (user name?) to get an underscore after it suddenly?

15:42 devn: what's the pattern for developing a new lein plugin? I have a new clojure project and created src/leiningen/foo.clj which contains a single function: (defn foo "Foo" [] (println "hi"))

15:42 Based on a couple of the other lein plugins I've looked at this should let me run the task inside my lein-foo plugin, is that wrong?

15:43 TimMc: mikerod_: You probably disconnected and then reconnected, and your old nick stuck around just long enough to be unavailable to your new session.

15:43 (aka a ghost)

15:43 devn: I keep getting "Task: 'foo' not found"

15:44 lol nevermind...

15:47 mikerod_: TimMc: That makes sense. Thanks!

15:47 I'm a ghost now. Yikes.

15:51 gdev: mikerod:) welcome back to the land of the living

15:51 jcromartie: this Clojure quiz on Smarterer is driving me insane

15:51 Q: "What are the 3 phases clojure code is processed in?" A: "Read-time, compile-time, run-time"

15:51 gdev: ,(= *)

15:51 clojurebot: true

15:52 gdev: you got it right, why is it driving you insane?

15:52 jcromartie: because every question is weird

15:52 gdev: what about that question is weird?

15:53 mikerod: gdev: Thank you. It feels good to be back.

15:53 jcromartie: because as a user of the language you don't care about a compile phase

15:53 there's a reader, but you don't necessarily need to use it to create Clojure code

15:53 and the code is evaluated, period, from a user standpoint

15:54 the bytecode compilation has no bearing on someone programming clojure

15:54 unless they are doing something tricky with AOT

15:54 TimMc: mikerod: It's actually the old nick that is the ghost. If you register your nick with NickServ, you can kill the ghost and recover your nick.

15:54 gdev: jcromartie:) and if you're using macros

15:54 TimMc: Not all servers have that service, though.

15:55 s/servers/networks/

15:55 gdev: jcromartie:) macros are a way to get the code to program in clojure for you

15:55 jcromartie: yeah

15:55 devn: jcromartie: from a "user" standpoint you don't care at all about the code, you just care that it works.

15:55 jcromartie: I'm not talking about a user of an application, I'm talking about a user of the Clojure language.

15:56 A programmer writing Clojure.

15:56 gdev: jcromartie:) those are called developers

15:56 jcromartie: sure

15:56 ToxicFrog: ...and as a programmer writing Clojure, you are in fact interested in the distinction between the read, compile, and run phases, because macros are tasty

15:56 devn: ^

15:56 That was what I driving at

15:57 Mainly trying to demonstrate that "user" is ambiguous. Some programmers might not need to care about read, compile, and run, but some care.

15:58 gdev: There's a Rich Hickey video where he talks about why homoiconicity is so important and goes into comparing languages that compile from text into byte code with lisp

16:00 gfredericks: clojure supports annotations?

16:00 jcromartie: I feel like this test was created to troll Clojure developers

16:00 "True or False? A symbol in Clojure can contain symbols that most imperative language variables can't handle. (Example. You can't define a variable with the name of +1-.)"

16:01 gdev: jcromartie:) I took the Sun Certified Java Programmer exam, that one is a huge troll to a clojure programmer

16:01 * technomancy o O ( "imperative"? )

16:01 jcromartie: Q: "True or False? The Clojure language is a data manipulation language written in data." A: True

16:01 gfredericks: any language that wants infix notation tends to disallow -

16:01 Pupnik: gdev, got a link to that talk?

16:02 Chousuke: :P

16:02 gdev: Pupnik:) I'm googling for it as we speak =D

16:02 jcromartie: technomancy: you may also be surprised to learn that Clojure is NOT an imperative language :)

16:02 Pupnik: rich hickeys talks are always very interesting and i havent heard this one

16:02 jcromartie: technomancy: if you just ignore `do' and atoms and all that

16:05 muhoo: does this really not exist anywhere in the clojure standard libraries? https://www.refheap.com/paste/14188

16:06 jcromartie: muhoo: it really does not… that's specialized enough and not hard to write

16:07 mikerod: TimMc: Thanks, I will look at this. I use the freenode webchat client right now. I think my network blocks me from connecting through the IRC client I usually use.

16:09 muhoo: jcromartie: it wasn't hard to write, but it sure ain't specialized. many languages have a "capitalize words" function

16:09 devn: Is there an easy way to build a leiningen plugin to add a key/val to the user's project.clj?

16:10 * muhoo adds it to his own vanity utility library

16:10 Pupnik: muhoo, does java have one?

16:10 jcromartie: muhoo: right… just not Ruby or Java or JavaScript or ...

16:10 Python does

16:11 gdev: Pupnik:) I think this is the one, or at least he's talking about the same thing at about 24 minutes into it http://channel9.msdn.com/Shows/Going+Deep/Expert-to-Expert-Rich-Hickey-and-Brian-Beckman-Inside-Clojure

16:12 Pupnik: gdev, im always interested to here bits about homoiconicity and macros, I still don't particularly know under what circumstances they are useful

16:13 jcromartie: C# has the ever-so-intuitive System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase("exAmpLe sTrinG")

16:13 gdev: Pupnik:) at about 48 minutes in he gives a better explanation with better visuals http://www.youtube.com/watch?v=P76Vbsk_3J0

16:14 brainproxy: dnolen: in your opinion, is mori still a viable approach to provide persistent data structures to JavaScript? I tried building after cloning and updating to latest cljsbuild, but the more.node.js it outputs is throwing errors realated to goog.string

16:14 rather than spend a bunch of time hunting that down, i figured i would ask if you still think mori is worthwhile, or if things have happened with cljs that make it unviable

16:14 gdev: actually, the "Clojure for Java Programmers" videos were the most entertaining because of the old guy that kept interupting

16:14 muhoo: jcromartie: python, perl, php, from memory. hmm, if java string library has one, i should just use that.

16:16 brainproxy: jimduey: you might like https://github.com/michaelsbradleyjr/jonas/blob/master/index.js

16:17 i took what I learned from protocol-monads and used technique to build a State monad abstraction for JavaScript that layers on top of JS promises

16:17 Pupnik: cheers gdev

16:17 muhoo: jcromartie: CurrentCulture???!! what are they doing, growing yogurt?

16:17 gdev: Pupnik & jcromartie actually at 58 minutes in to "Clojure for Java Programmers" video he has all three phases that clojure is processed in

16:19 Chousuke: brainproxy: that's funny, promises form a sort of monad by themselves :P

16:19 muhoo: ah, commons has one http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/text/WordUtils.html

16:20 brainproxy: Chousuke: they do, yes

16:20 jimduey: brainproxy: nice

16:20 Chousuke: I've got to look at it more, but I think promises are more like comonads.

16:20 brainproxy: Chousuke: but my thought is that the State monad idiom of [state, value] and the standard "helpers" is pretty useful

16:21 especially if you have a "do" like thing

16:21 jimduey: but they're also easy to think about as monads.

16:21 brainproxy: that gives you a lexical environment for chaining operations wherein you can refer back to results of previous steps

16:21 which I'll be working on soon

16:21 Chousuke: there's a yo dawg joke here somewhere. but I bet you could get a monad out of DAWGs too and then it would get ridiculous

16:21 jimduey: Chousuke: lol

16:21 brainproxy: :)

16:23 gdev: Pupnik:) macros are useful when you want something to be in the language that isn't. most people take it for granted. Macros are way better than JSRs

16:23 brainproxy: the downside in JavaScript is that mutable state can bite you in the butt if you're not careful regarding how you work with the the state and values you're passing through a program

16:23 Pupnik: gdev, JSRs?

16:23 gdev: Pupnik:) Java Specifications Requests

16:23 brainproxy: promises and I think my State abstraction help, but don't completely eliminate the problem

16:23 Pupnik: ah, I don't know java

16:23 muhoo: Pupnik: consider yourself lucky.

16:23 Pupnik: I only know actionscript 3, lua and a little bit of C/C++ and Clojure

16:23 Chousuke: promises are a great tool in JS though

16:24 brainproxy: Chousuke: they are, but I now suddenly have a renewed interest in dnolen's mori

16:24 Chousuke: handling all that async code control flow explicitly is a huge pain in the butt

16:24 gdev: Pupnik:) okay, well in java if you want something in the language you have to go through a huge ceremony

16:24 brainproxy: as mori's persistent data structures are the perfect kind of things to use for state/values

16:25 gdev: I can't tell you how many goats were sacrificed just to get the foreach keyword

16:25 jcromartie: gdev, Pupnik: JSRs are one thing… not to mention the huge ceremony of actually implementing it!

16:25 brainproxy: Chousuke: yep, except you can still end up with a bunch of boilerplate depending on how you are chaining promises

16:26 the other night I was doing some complex chains that drove me toward a helpful pattern, which when I stood back and looked at it, I said "hey, that's more or less the state monad"

16:26 Chousuke: brainproxy: sure, but it's probably way less than all the nested anonymous functions. :)

16:26 gdev: being a java developer around clojure developers who've never used java, I feel like one of those old vietnam vets who always says "i've seen some things, and some stuff...i wouldn't recommend it"

16:26 brainproxy: Chousuke: exatcly, but I think w/ an abstraction layered on top of promises, we can make it even better

16:27 iow, callbacks < promises < State

16:27 in terms of efficiency of abstraction

16:28 Chousuke: as far as I understand state should be orthogonal to promises. Combining them can of course be useful (composition is great, after all)

16:29 technomancy: "I've seen things you people wouldn't believe. Build servers on fire off the shoulder of Orion. I watched maven artifacts glitter in the dark near the Tannhäuser Gate. All those... moments... will be lost in time, like tears in the rain."

16:30 jcromartie: (inc technomancy)

16:30 lazybot: ⇒ 55

16:30 clojurebot: that will show you what jars (including the clojure jar) leiningen is using

16:30 jimduey: brainproxy: perhaps of interest http://www.cs.umd.edu/~jfoster/papers/cs-tr-4923.pdf

16:31 brainproxy: Chousuke: you may be right

16:31 technomancy: "We couldn't find any repositories matching 'tannhauser'" <- github, I'm disappointed.

16:31 gdev: technomancy:) everytime you quote something I assume its from bladerunner

16:32 jimduey: brainproxy: or this might be a better link http://www.cs.umd.edu/projects/PL/arrowlets/

16:32 brainproxy: jimduey: very cool

16:32 I spent a loooong time working with Flapjax a couple of years ago

16:33 which is related

16:33 devn: (inc technomancy)

16:33 lazybot: ⇒ 56

16:33 technomancy: huh; Tannhauser is a Wagner reference. nicely played, Rutger Hauer.

16:34 brainproxy: jimduey: i mean related conceptually

16:34 Chousuke: brainproxy: It's always interesting to me to see how people are implementing more and more Haskell idioms in other languages

16:34 devn: parsec all the languages!

16:34 tieTYT2: why doesn't clojure have (all)?

16:35 devn: tieTYT2: like, (all even? [2 4 6]) or?

16:35 tieTYT2: the first

16:35 it has an every?

16:35 ok i'll use that

16:35 devn: yes

16:36 tieTYT2: ugh but it doesn't takes multiple args

16:36 jimduey: Chousuke: I see them more as category theory abstractions than Haskell idioms

16:36 and it's my mission in life to implement all of them in Clojure. :)

16:36 Chousuke: jimduey: same thing. it's funny how category theory translates into practical programming

16:36 tieTYT2: i'll just wrap my args in a vector

16:36 brainproxy: jimduey: have you seen bilby.js

16:37 Chousuke: though I still have no idea what the hell profunctors are supposed to be about

16:37 tieTYT2: i feel (every? nil? [e1 e2]) is more readable than (nil? (or e1 e2)) Is there an even clearer way?

16:38 brainproxy: jimduey: https://github.com/pufuwozu/bilby.js <-- the author is doing some pretty serious work with functional programming for javascript

16:38 Chousuke: functors I can see, they're really useful all the time, but I don't even understand the definition of a profunctor, much less why it would ever be useful.

16:38 * jimduey puts profunctor on the list of things to learn about

16:39 Chousuke: jimduey: it's just one of those things I've encountered reading random things about haskell that I haven't yet been able to make sense of

16:40 Pupnik: man i could listen to rich hickey all day

16:40 jimduey: brainproxy: bilby looks ambitious. I think most of the libraries I've done so far that are based on protocols will be portable to clojurescript

16:40 pjstadig: tieTYT2: if you're using it as a conditional, then just use (and e1 e2)

16:40 or whatever

16:40 jimduey: brainproxy: protocol-monads already has been

16:40 brainproxy: jimduey: yeah, saw that

16:40 Chousuke: jimduey: but apparently the lens library uses profunctors so it must have some practical use

16:40 tieTYT2: pjstadig: ha, I feel dumb

16:41 pjstadig: well actually I'm doing the opposite of and

16:41 jimduey: Chousuke: lenses are also on my list. BTW, it's a really long list.

16:41 tieTYT2: i'm checking that they're both null

16:41 not that they both exist

16:41 amalloy: mikerod: https://www.refheap.com/paste/776ba83c0bcd45f07eb024dae

16:41 Chousuke: jimduey: as far as I can tell lenses are the ultimate code golfing tool

16:42 pjstadig: tieTYT2: yeah so you could do (not (or e1 e2)) or (and (nil? e1) (nil? e2))

16:43 tieTYT2: pjstadig: you think that's easier to read than (every? nil? [e1 e2]) ?

16:44 tomoj: bilby lenses aren't van laarhoven, right?

16:44 tieTYT2: IMO the latter expresses its intent better

16:44 pjstadig: tieTYT2: it may depend on the context, but i think i'd favor something with ands or ors to using every? and making a vector out of the expressions

16:46 gdev: "Quite an experience to live in fear, isn't it? That's what it is to be a java dev doing concurrency"

16:47 tomoj: I just got this passing https://www.refheap.com/paste/242b5b8583854d7411312acf1 but what's the point, I want van laarhoven :(

16:47 technomancy: heh nice

16:48 justin_smith: tieTYT2: (empty? (remove nil? [e1 e2]))

16:48 rodnaph_: using enlive, is it possible to do a selector using element attributes? like jquery would be: input[name=foo] ?

16:48 brainproxy: gdev: http://image.slidesharecdn.com/concurrencygotchas-100408105435-phpapp01/95/slide-7-728.jpg?1270742095

16:49 nkoza: how you can see the tcp port used by nrepl to listen for connections from inside the nrepl session?

16:51 rodnaph_: to answer my own question, yes, using (attr= :href "foo")

16:52 tieTYT2: rodnaph_: you want to check that the name = foo?

16:52 yes

16:52 i hate enlive btw

16:52 rodnaph_: whaaa? i am currently loving enlive. what don't you get on with?

16:52 gdev: brainproxy:) i thought that was going to be a link to some slideshow, i almost fell out of my chair laughing

16:52 tieTYT2: I don't like the double nested vectors

16:52 gfredericks: TimMc: I like your inclusion of hiredman as a debugging requirement

16:53 tieTYT2: and their significance, it's confusing to me

16:53 and i wish the selectors were better documented

16:53 gdev: (inc brainproxy)

16:53 lazybot: ⇒ 1

16:53 rodnaph_: i haven't gone too deep into the selector syntax tbh (as u can tell from my q)

16:53 brainproxy: gdev: :) that came from one of Alex Miller's slideshows

16:53 tieTYT2: i've only used the selector part

16:54 rodnaph_: i use it for html templating, works really nicely.

16:56 tieTYT2: can someone explain to me why I should have to use a dorun when I use map in a precondition?

16:57 Chousuke: tieTYT2: map is lazy

16:57 tieTYT2: yeah but why isn't pre trying to get the results?

16:59 mikerod: amalloy: Thanks. I think I can see your point on that with functions and macros having some assumptions on argument forms.

16:59 Raynes: gfredericks: Wtf, I wasn't following you on twitter? No wonder my life is so empty.

17:00 gfredericks: I have finally made it!

17:00 no more striving for me

17:01 Raynes: I have a haircut.

17:01 gfredericks: so no more striving for you either

17:01 "v1.9" == birthday?

17:02 Raynes: gfredericks: Nope.

17:02 technomancy: just minor bugfixes

17:02 or a complete VM rewrite, if you're ruby

17:03 Raynes: $google list of burn centers

17:03 lazybot: [List of burn centers in the United States - Wikipedia, the free ...] http://en.wikipedia.org/wiki/List_of_burn_centers_in_the_United_States

17:05 gdev: gfredericks:) after i starting following you it suggested i also follow the parody account for charles manson

17:07 gfredericks: gdev: good?

17:08 gdev: gfredericks:) depends, I'm just assuming its a parody account, but I'm too scared to google search if charles manson is still alive while at work

17:09 AimHere: I believe he's still alive, yes

17:12 gdev: is there a safer way to do this? (read-string (slurp "some.properties"))

17:12 justin_smith: clojure.data.edn/read-string

17:12 for 1.5+

17:13 there is also a thing before 1.5 where you can turn some magic evaluation reader macros off

17:16 oh, yes - it is good to bind *read-eval* to false - but there are still gotchas

17:17 gdev: justin_smith:) thanks

17:18 justin_smith:) am I being too paranoid if the file I'm reading from is a properties file i wrote?

17:18 justin_smith: heh, maybe, but we have had the exact same conversation at my workplace :)

17:19 but clojure.data.edn/read-string, in 1.5+, is the thing that is designed to be safe to read without weird unintended security issues

17:20 tieTYT2: I have a bunch of date Intervals and I need to do certain things with them. EG: If one contains the other, keep the container. If one is after the other, keep both. At first I thought a (reduce) would be a good fit. But I'm having second thoughts because if I return both, the reduce function now has to check if the input is a Interval or a vector of two Intervals.

17:20 gdev: justin_smith:) if I just use an edn file instead of a properties file couldn't I just validate the data its reading

17:20 tieTYT2: oh i left out a detail: I've got a list of the details, and I'm trying to decide which ones to keep and which to throw away

17:21 gfredericks: what do you folk use instead of capistrano?

17:21 justin_smith: gdev: the issue is that just in being parsed, it can make other things happen, even before you use the data

17:21 unless you are using c.d.edn

17:21 http://clojuredocs.org/clojure_core/clojure.core/read toward the end of that page it is explained in more detail

17:22 gdev: justin_smith:) yeah that's what i meant, I'll use an edn file with the edn reader and I'll sleep safe at night

17:22 mkay I'll check out that link

17:34 TimMc: gfredericks: That was ha-ha-only-serious -- I'm really not sure I would have gotten to the bottom of that without the help of someone well-versed in JVM.

17:36 gdev: so now I've painted myself into an awkward corner; (def configs (read-string (slurp "super-secret.config"))) (def oracle-db {:user (:user configs) ...})

17:37 i elipsed out the rest of the def, but you get the idea, i have to deref with the same key as the key i'm trying to set a value for

17:37 could i simply say (def oracle-db configs) ?

17:37 justin_smith: why not make the oracle db a submap of the config? {:db {:user ...}} then (def orcle-db (:db config))

17:38 gdev: the file has the exact map that the def needs

17:38 TimMc: gdev: select-keys

17:38 justin_smith: if that will always be the case and any other configs will be in another file, why not (def orcale-db configs)

17:39 gdev: justin_smith:) yeah, that's what i'm going for, just trying to keep company server, username, passwords etc off the interwebs

17:39 justin_smith: makes sense, yeah

17:40 gdev: it's tricky posting database examples since to connect you have to have username and passwords stored

17:40 TimMc: &(select-keys {:user {:blah "blah"} :un "related"} [:user])

17:40 lazybot: ⇒ {:user {:blah "blah"}}

17:41 justin_smith: TimMc: my problem with doing configs that way is you end up with unrelated configs interleaved, when nesting would clearly indicate the separation. And then some configs should use the same key with different values...

17:41 avishai: q

17:41 require vs use

17:41 u probably get that a lot

17:42 gdev: avishai:) I have to look it up every time

17:42 TimMc: avishai: Are you asking whether to use :require or :use? Definitely :require, almost always.

17:42 avishai: really?

17:42 TimMc: And only use :use with :only.

17:42 avishai: why?

17:42 clojurebot: http://clojure.org/rationale

17:42 TimMc: Namespace pollution.

17:43 avishai: why require and not use

17:43 justin_smith: yeah, use makes reorganizing code a pain in the ass, or even reading it

17:43 gdev: avishai:) you can use :as with require

17:43 akhudek: use :require and :refer rather than :use

17:43 TimMc: avishai: It's really hard to read code that heavily refers vars.

17:43 akhudek: if you really want to use everything, you can do (:require [library :refer :all])

17:44 avishai: so (ns blah (:require [some-ns :as n])) ?

17:44 TimMc: Yep.

17:44 avishai: so other then style use and require do the same thing?

17:45 akhudek: avishai: require with refer is the same as use with only, but is now the preferred style as I understand

17:45 TimMc: avishai: (:use foo) == (:require foo :refer :all) -- but you really don't want that anyway.

17:45 akhudek: and as TimMc, it is better to require :as if most cases

17:46 justin_smith: avishai: they both make libraries accessible - but if your json lib and your xml lib both have a parse function, then require is your only option, use just won't work

17:46 TimMc: People will hate reading your code.

17:46 avishai: can i import with the full name/

17:46 ?

17:46 justin_smith: require lets you use the full name

17:46 avishai: ah

17:46 justin_smith: but also lets you use :as

17:46 avishai: so i want just (:require some-ns)

17:47 justin_smith: if you want to spell it all the way out, yeah

17:47 avishai: great

17:47 10x

17:47 gdev: although the only pain point for me in using ":as" is when i have (kd/this (kc/that (ps/i-like-turtles (ps/wat 42) all the slashes, slashes everywhere =(

17:47 justin_smith: but (:require [foo.bar :as bar]) ... (foo.bar/x ...) still works

17:48 (let [foo bar/foo] ...) is helpful sometimes

17:48 still more readable than a :use

17:49 avishai: i find long names more readable

17:49 and if you work with autocompletion writing is easy

17:50 nkoza: how you can get the tcp port used by nrepl to listen for connections from inside the nrepl session?

17:51 gdev: so i would say (let [this kd/this that kc/that i-l-t ps/i-like-turtles wat ps/wat] (this (that (i-l-t (wat 42)))) ?

17:52 who is working on the strunk and white for clojure?

17:53 justin_smith: well, it doesn't help much for that example, but if you were using string/join over and over in one block but not in the rest of your ns, (let [join clojure.string/join] ...) totally makes sense

17:53 akhudek: bbatsov

17:53 https://github.com/bbatsov/clojure-style-guide

17:53 justin_smith: but yeah, pretty much

17:58 tomoj: you lose typehints in that case right, or is clojure smart enough?

17:59 gdev: i'm totally forking that repo, not in a pycon way either, like literally

17:59 pppaul: clojure brains

17:59 tomoj: nope, not smart enough

17:59 hiredman: clojure-style-guide is silly

18:00 gdev: hiredman:) yes, once you've used the language for a while, but when first starting out it seems helpful

18:01 hiredman: I submitted a pr to make it less so, but it was rejected https://github.com/hiredman/clojure-style-guide/commit/0e904f2b41866fcccddc924a3e5faf5660b2cb4a

18:01 gdev: hiredman:) oh i thought you were talking about the idea of a style guide, i didn't know you meant that specific one

18:02 justin_smith: gdev: read his rq, you were right

18:03 gdev: justin_smith:) his rq?

18:03 justin_smith: the pull request he linked

18:03 you were right the first time

18:03 hiredman: the style guide is basically "let's write down how emacs formats lisp", which even as an emacs user I think is silly

18:04 justin_smith: the reason emacs formats it that way is because reasonable people wanted that as a default

18:04 gfredericks: if macros could include metadata to suggest formatting, would that be cool or stupid?

18:04 technomancy: gfredericks: CL indents differently depending on whether slime is connected or not

18:04 do not want

18:04 clojurebot: No entiendo

18:04 gdev: lol i just read the pull request very clever hiredman, very clever

18:04 hiredman: that is almost how the emacs indenting system works

18:04 you add indenting info to the plist of symbols

18:04 technomancy: but emacs is always "live"

18:04 elisp

18:05 gfredericks: hiredman: that's symbol based instead of var based though, right?

18:05 technomancy: gfredericks: symobls in elisp are kind of like vars

18:05 they are storage locations

18:05 hiredman: technomancy: works for non-elisp lisps too

18:05 justin_smith: yeah, every symbol has a plist, like in cl

18:06 hiredman: technomancy: I have a little mode for the lisp I am writing that does it

18:06 gfredericks: technomancy: are you still bullish on racket?

18:06 technomancy: hiredman: right, but the whole "language describing its own indentation" thing only works for slime and elisp

18:06 gfredericks: there are a couple things about it I hate. but there's a lot to like.

18:06 hiredman: technomancy: sure, or a pretty printer

18:07 technomancy: gfredericks: it seems like a good fit for this project I'm doing on the raspberry pi.

18:08 hiredman: I'm telling you, the jvm will run great on that

18:08 technomancy: my fallback plan is elisp =P

18:12 wait is bullish good or bad?

18:13 hiredman: https://en.wikipedia.org/wiki/Market_trend

18:13 TimMc: Good, I think.

18:13 technomancy: huh. I assumed with such a low edit distance from "bullshit"...

18:14 hiredman: yo, it's the animal spirits

18:15 http://en.wikipedia.org/wiki/Animal_spirits_%28Keynes%29

18:18 mthvedt: well a lot of bullish opinions are reflective of that edit distance

18:18 learner: Hello Clojure Gurus, I have been learning clojure. Trying to understand apply function more clearly. I executed "(apply vector [:a :b] [:c :d])" expecting result [:a :b :c :d] -- one single vector --> instead I got [[:a :b] :c :d]. If any of you explain me how exactly apply works, it's great. Thanks for your time.

18:18 TimMc: hiredman: Not to be confused with spirit animals.

18:19 trptcolin: learner: apply unrolls only the last arg given; the rest of the args are passed directly (in front of the last arg)

18:19 ,(apply vector :a :b [:c :d])

18:19 clojurebot: [:a :b :c :d]

18:19 gfredericks: which is useful a lot of the time

18:21 learner: trptcolin: Thanks. Excuse me for my lack of knowledge and little brain, would it be possible to explain me in simple words. what do you mean by "apply unrolls only the last arg given"

18:23 trptcolin: learner: here's an easier-to-understand example: you can think of (apply + 1 2 [3 4]) as more or less the same as (+ 1 2 3 4)

18:23 the last argument [3 4] needs to be a sequence-like thing, and it gets "unrolled" when it's passed to the function (the first argument to `apply`)

18:25 TimMc: http://dev.clojure.org/jira/browse/CLJ-1208 "Namespace is not loaded on defrecord class init"

18:25 learner: trptcolin: Exactly that example confused me. I was expecting (apply vector [:a :b] [:c :d]) to behave (apply vector [:a :b :c :d]).. but it's not

18:26 trptcolin: (apply vector [:a :b] [:c :d]) is like (vector [:a :b] :c :d)

18:26 TimMc: (apply vector [:a :b] [:c :d]) => (vector [:a :b] :c :d)

18:26 sniped

18:26 trptcolin: hehe

18:27 tomoj: do you really want to be using records directly from java anyway?

18:27 TimMc: Yep.

18:30 learner: trptcolin: Based on your explanation, I tried couple of examples on REPL. I am clear now. Cheers mate. BTW, quoting-without-confusion -> is my one of my favourite bookmark.

18:31 TimMc: Thanks for clarifying apply vector question

18:34 mikerod: What is "quoting-without-confusion"?

18:35 learner: mikerod: it's Colin's article. trptcolin: http://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html

18:37 mikerod: learner: Ah, I didn't realize that. I have read this before and agree that it is useful.

18:42 learner: Another question Gurus. To practice & improve my clojure skills, I am planning to write a simple password cracker (brute force). I would like to control number of threads I initiate, and if password found I update an atom(found) value to TRUE. Loop terminates if TRUE found. I am using https://github.com/clojure/math.combinatorics to get various combinations. But I am not sure on how to control threads and stuff. Any pointers are rea

18:47 SegFaultAX: learner: That's a really inefficient way to crack passwords. Dictionary attack is much better.

18:48 AimHere: Phishing scam is better still!

18:48 SegFaultAX: learner: http://www.openwall.com/john/

18:48 Not that I'm endorsing that sort of thing for malicious purposes, you see.

18:48 I'm just sayin...

18:49 learner: SegFaultAX: Thanks for your reply. I don't mean to crack passwords really. But to learn concurrent programming and experiment on threads. If I were to crack password, Yes I target to get Hash!

18:52 SegFaultAX: learner: This sounds like an awesome opportunity to learn about reducers and Fork/Join!

18:53 learner: SegFaultAX: True. I am not sure where to start though. I am wondering if the community can point me to couple of examples.

18:54 SegFaultAX: learner: Probably do it in phases. Start with a single threaded synchronous version, then a second version built on futures, etc.

18:55 But get a working conceptual model first before you try and add paralellism.

19:01 learner: I think understanding clojure way of solving sleeping barber's problem gives me a good start on concurrency. Just in case if any of you also looking for examples. Thanks for all your support.

19:06 amalloy: SegFaultAX: this sounds like a terrible opportunity to use fork/join, right?

19:07 or, at any rate, a bad time to use reducers

19:07 since r/fold has no provisions for stopping early

19:07 or in fact coordinating at all with the other threads working on the task

19:08 really he wants like...a queue of "passwords to try", and a threadpool of workers taking jobs from there; he just stops putting stuff on the queue, or shuts down the threadpool, when an answer is found

19:10 tieTYT2: is a reducer different from the reduce function?

19:14 amalloy: $google clojure reducers

19:14 lazybot: [Clojure - reducers] http://clojure.org/reducers

19:14 tomoj: "reducers are composable", huh

19:15 apoc: whats (fn*)? I get it from something like '#(+ % 1) but I've trouble finding out what the * does

19:15 tomoj: reducer combinators are composable, but they're just functions, so what does that even mean?

19:16 SegFaultAX: amalloy: I didn't know that about reducers, I just lumped that into Fork/Join. Probably misspoke. But FJ is still reasonable here.

19:16 tomoj: I guess maybe it means that there are functions in the reducers library :)

19:16 which is better than lots of collection libraries at least

19:18 amalloy: tomoj: composable is just a word rhickey likes. saying it soothes him

19:18 SegFaultAX: tomoj: Not all functions are composable.

19:19 tieTYT2: thanks

19:20 tomoj: I mean reasonable functions :)

19:20 SegFaultAX: tomoj: "Reasonable" isn't a word I understand in this context.

19:20 tomoj: "composable"

19:20 justin_smith: apoc: fn* is a function, that the fn macro calls

19:20 similar let* / let

19:20 tomoj: or, say, "pure"

19:20 justin_smith: maybe special form? anyway it doesn't do data decomposition and stuff

19:21 SegFaultAX: tomoj: Pureness is not what makes functions composable.

19:21 apoc: the * makes it really difficult to search for, looks like most search engines ignore it ;)

19:21 maybe have a doc link for me?

19:21 SegFaultAX: tomoj: For two functions f and g to be properly composable with each other (f . g) the co-domain of g must be a subset of the domain of f

19:22 tomoj: ok, so "composable" then. my point is just that reducers themselves seem very uncomposable. if I've got two reducers, well, shit

19:22 SegFaultAX: It may or may not be a proper subset (eg the co-domain of g may match the domain of f exactly, but that's not a requirement)

19:23 tomoj: but I guess maybe that enables the kind of composition that is there

19:25 justin_smith: apoc: you can expand the source tab on this page to see how fn calls fn* http://clojuredocs.org/clojure_core/clojure.core/fn

19:26 fn* isn't meant to be called by normal code, it is just a less useful primitive that fn is made of

19:41 tieTYT2: I'm reading this fogus article: http://www.drdobbs.com/architecture-and-design/the-clojure-philosophy/240150710

19:41 he uses this code as an example: x = [5]; process(x); x[0] = x[0] + 1

19:42 you can't tell what x will become because you don't know if process mutates

19:42 and clojure is better because locals are immutable

19:42 BUT, if x is a java object, aren't you just as unsure as any other language?

19:43 technomancy: tieTYT2: yes

19:43 it's just that it's easy to avoid that in clojure and nearly impossible in most languages

19:43 tieTYT2: i must be writing clojure wrong if it's easy to avoid that

19:44 also some of my clojure is embedded in a java app

19:44 SegFaultAX: tieTYT2: Are you using lots of POJOs in your Clojure code?

19:44 tieTYT2: SegFaultAX: not lots, but usually a main one

19:44 i've used seesaw, clj-http and things like that

19:44 they're all using java objects under the hood

19:45 SegFaultAX: tieTYT2: Yea, there really isn't anything you can do about that.

19:45 Clojure isn't a pure language and Java sure as hell isn't a pure runtime.

19:45 tieTYT2: right, so in that case I don't understand the clarity argument

19:46 if I don't use any java libraries directly or indirectly things are easy to understand, but otherwise you never know, right?

19:46 technomancy: you can get a seq over a mutable java object

19:46 and it's guaranteed to be stable

19:47 tieTYT2: what do you mean? Like (let [x [java-object] ...) ?

19:47 technomancy: (seq java-list-thingy) ; <- not gonna change

19:47 tieTYT2: but the objects inside could

19:48 when I pass that seq into any function, right?

19:48 technomancy: well, you have to apply the seq at the right level

19:48 if it's a list of strings or numbers, you're fine

19:48 tieTYT2: right

19:48 technomancy: otherwise maybe you (map bean list-of-pojos) instead

19:49 tieTYT2: yeah I suppose that's better

19:50 technomancy: clojure encourages you to keep the yucky mutable bits as small as possible

19:50 tieTYT2: pure clojure does, yes

19:51 technomancy: so you do your interop in one namespace, and as long as you don't let the objects escape, your namespaces implementing the rest of the logic are clean

19:51 tieTYT2: maybe the unusual thing with my experience is I've always been using java somewhere

19:51 SegFaultAX: tieTYT2: Well, all Clojure encourages you to keep the lucky bits isolated.

19:51 tieTYT2: Even when you're working in Java interop, it's still encouraged.

19:52 s/lucky/yucky/

19:52 tieTYT2: SegFaultAX: maybe as a philosophy. But I can take a seesaw label and call (.setText l "foo") on it any time I want.

19:53 SegFaultAX: Why is the null check in RT.seqFrom second?

19:53 technomancy: more importantly, someone else could do that

19:53 tieTYT2: technomancy: you mean a library that requires label's?

19:53 SegFaultAX: tieTYT2: Clojure is not a pure language. It doesn't claim to be.

19:53 technomancy: I guess? I don't know swing

19:53 or java

19:54 SegFaultAX: There is absolutely nothing to stop you from doing that.

19:54 technomancy: it's just more insidious when mutation comes from places you don't control

19:54 SegFaultAX: But if that's the way you choose to do it, why use Clojure at all?

19:54 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L489

19:57 hiredman: SegFaultAX: because you might call seq on nil?

19:59 SegFaultAX: hiredman: But why is the null check second?

20:01 hiredman: SegFaultAX: *shrug*, as as it is before the method calls

20:15 tomoj: "values of type X are composable" =?= "the X library provides at least one non-identity function of type X -> X (in spirit)"

20:37 axle_512: anyone recommend a good continuous build setup for lein? Is jenkins an option or is there something better?

20:38 justin_smith: we use jenkins with hooks on git

20:38 I am not the one that set it up, but it works fine

20:38 axle_512: justin_smith: thanks. Does it require a jenkins plugin?

20:38 justin_smith: and we all get to ritually humiliate the one who checked in the bad commit

20:39 the guy who set it up is out of office (late on a friday), I only know it oworks, sorry

20:39 axle_512: cool. thanks, will look into it

20:39 justin_smith: jenkins even has an irc bot - think of the possibilities

20:40 axle_512: I've used jenkins with jabber to get IM notifications, that was pretty cool

20:40 amalloy: travis seems popular for clojure folks

20:41 axle_512: will take a look at travis as well. thanks

20:52 lpetit: axle_512: Travis also has handful of options for post build notifications (email, irc, etc.): http://about.travis-ci.org/docs/user/notifications/

20:52 axle_512: lpetit: thanks, I just signed up on travis-ci.org.. digging deeper

20:54 lpetit: axle_512: it's very straightforward, read about it a little bit, then tried to push my maven + tycho (for Eclipse plugins) tonight. First successful build in less than an hour

21:13 Apage43: when I kill an nrepl evaluation (ctrl-c) is there a way to see the stack trace as of when I killed it?

21:14 Trying to debug a deadlock

21:15 gdev: Apage43: trace log?

21:19 nkoza: I want to test if something can be converted to a seq with (seq x) ... there is some predicate to know if that is possible? (seq? x) doesn't work, for example (seq? [1 2]) evaluates to false

21:22 I see in clojure 1.2 there was a clojure.contrib.core/seqable? function, where is now?

21:22 axle_512: lpetit: saw you over on #travis as well. travis ci is quite nice, I'm already up and running with a little help from henrikhodne.

21:23 Apage43: nkoza: you can grab it from the old repo. https://github.com/clojure/clojure-contrib/blob/b8d2743d3a89e13fc9deb2844ca2167b34aaa9b6/src/main/clojure/clojure/contrib/core.clj#L78

21:23 nkoza: there is no modern way?

21:24 Apage43: don't know what you mean.

21:24 gdev: ,(instance? clojure.lang.Seqable [1 2 3])

21:24 clojurebot: true

21:25 Apage43: ,(instance? clojure.lang.Seqable "i'm a string")

21:25 clojurebot: false

21:25 Apage43: ,(seq "I'm a string")

21:25 clojurebot: (\I \' \m \space \a ...)

21:26 Apage43: so no. If you want to check if seq will succeed you have to check all the things it works on

21:26 nkoza: I mean, seems to be some very basic, I'm surprised there is no official predicate to check for that

21:26 but thanks for the link, I will use it

21:27 gdev: thats not that many checks in an or statement

21:27 tomoj: presumably it was removed for a reason :)

21:28 gdev: don't be presumptuous

21:28 amalloy: Apage43: "all the things it works on" is an open-ended set

21:28 Apage43: mm, it could increase in the future

21:29 amalloy: Apage43: it can increase right now. [B, [[B, [[[B...

21:29 there are already an infinite number of seqable classes

21:29 Apage43: amalloy: right, but that's checkable

21:29 amalloy: sure, using reflection

21:30 if you can find it, dnolen has a blog post about memoizing that reflection check for seqable? by dynamically extending protocols at runtime

21:30 gdev: ,(seq \x)

21:30 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Character>

21:30 gdev: ,(seq 42)

21:30 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

21:31 gdev: ,(seq 'seq)

21:31 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>

21:32 tomoj: http://web.archive.org/web/20120726061808/http://dosync.posterous.com/51626638

21:33 I figured extending protocols at runtime was evil

21:34 amalloy: well, basically yes. but the goal is evil too, so it evens out

21:34 tomoj: I guess it's only evil if I use it to implement implementation inheritance?

21:34 ah :)

21:34 dnolen: tomoj: extend-type is inately a runtime thing

21:35 tomoj: dunno how to say what I mean but I figure you know?

21:35 I guess I mean extending in a default impl

21:35 dnolen: tomoj: it's your protocol, what's the problem?

21:35 Apage43: okay, I broke emacs enough times today, time to head home

21:36 tomoj: I think the problem is that my goal is evil

21:36 dnolen: tomoj: oh I probably missed that

21:37 tomoj: I want protocol<->protocol extension

21:37 dnolen: tomoj: terrible idea

21:37 well IMO, I know other people have done it and like it.

21:37 tomoj: so I'm left thinking that there is something wrong with reducers, because it has an ugly workaround for that

21:38 dnolen: tomoj: that said, extending protocols to interfaces is less of a hassle in CLJ

21:38 tomoj: oh, yeah, but that's cheating :)

21:38 dnolen: in CLJS you gotta do that work in default implementations

21:38 amalloy: tomoj: what workaround?

21:39 tomoj: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/protocols.clj#L39

21:40 dnolen: tomoj: that's just the default implementation

21:41 tomoj: the 'ugly workaround' is to use the default impl to extend a protocol to a closed set of other protocols

21:42 nkoza: maybe is simpler to do (defn seqable? [x] (try (seq x) true (catch Exception e false)))

21:42 Apage43: nkoza: well, that'll also eat any exception realizing the first element of a lazy seq

21:43 amalloy: it also doesn't work for empty collections, but that's an easy fix

21:44 nkoza: true, maybe there is a way to check if the exception was made before or after realizing that element... maybe inspecting the stack or something

21:44 amalloy: the original implementation wasn't evil enough for you, nkoza?

21:44 tomoj: I hadn't noticed that cljs has the IReduce impls directly on all the concrete seq types

21:44 that is nice

21:44 nkoza: learning is to explore all the evil corners :)

21:45 can you call (seq col) without realizing the seq first element?

21:46 tomoj: if that's what clj wants to do, then I retract my complaint - I'll just have to implement IReduce directly on all my concrete types

21:46 otoh if clj really wants to abuse the default impl, it seems unfair :)

21:46 dnolen: tomoj: it's the right way if more tedious.

21:47 tomoj: hmm

21:48 dnolen: tomoj: it does make a compelling argument for some language level type union.

21:49 solves the tedium - tho not the closed problem

21:49 tomoj: so should (into [] (reify clojure.lang.ISeq (seq [this] this) (first [_] :foo) (next [_]))) fail?

21:50 er, (r/reduce conj [] (reify ...)) say

21:50 (oh, same thing-ish)

21:51 not sure what you mean about the union, but I'm guessing it would allow that to succeed, and then like you say the problem is just that it won't work for (reify com.example.MyISeq ...) ?

21:53 dnolen: tomoj: sorry I'm talking about a problem for CLJS which does get to ride on interface inheritance to avoid tedium.

21:53 doesn't

21:54 tomoj: yeah, like clojure.data.diff? and the reify thing fails there iirc

21:55 ah well, moot if I'm right that IReduce is wrong

21:56 dnolen: tomoj: I'm missing some context here, why is IReduce wrong?

21:57 nkoza: btw, I found two posts by Rich about the "seqable?" issue: https://groups.google.com/d/msg/clojure/sqok3RqGEC8/m63Kv_qYUDgJ https://groups.google.com/d/msg/clojure/CPFPkyTYXGc/jfuaHOjWPPwJ

22:00 dnolen: nkoza: those are old posts, CLJS has ISeqable and seqable?

22:00 in fact strings and arrays were extended to ISeqable until recently

22:00 tomoj: dnolen: reducers need to be broken up more, I think. CollReduce specifies synchronous single-threaded execution and CollFold (sort of) specifies ForkJoin

22:01 dnolen: they no longer are, but I pretty much agree on the minor utlity of seqable?

22:01 tomoj: I'd rather those concerns be separate

22:02 nkoza: dnolen: "grep -r ISeqable *" gives nothing on clojure 1.5.1 source

22:02 dnolen: tomoj: reading the code I don't really agree.

22:02 nkoza: ClojureScript

22:03 sorry I abbreviated it as CLJS

22:03 nkoza: why ISeqable exists on CLJS and not in CLJ? CLJS is more based on protocols, like a CLJ cleanup? (I'm new to CLJS)

22:04 tomoj: say I have some other way to execute a binary tree of tasks besides FJ -- I have to copy+paste foldvec, replace the FJ bits, and then wrap my vectors in a special CollFold wrapper that uses my execution mechanism?

22:06 "wrong" was probably too strong - I quite like reducers, I just want more (really, less?)

22:06 dnolen: tomoj: it might be usefult to break out the strategy, but then why not make a more flexible protocol for your own use?

22:07 clojurebot: forget chouser: it's tougher with guards (arbitrary tests), where grouping is less clear. I need to work that out still.

22:07 dnolen: nkoza: CLJS is newer is all

22:07 tomoj: dnolen: yeah, that's what I hope to be able to do

22:08 nkoza: dnolen: ok, thanks

22:09 amalloy: dnolen: that seems like a weird answer to nkoza's question. you couldn't define ISeqable usefully in clj-jvm. you have to either make it an interface, in which case it can't be extended to existing jvm types; or a protocol, in which case it's very hard to bootstrap the compiler up to the level where protocols exist

22:11 dnolen: amalloy: I didn't mean to imply that CLJ JVM could solve this issue easily - I just meant that CLJS is newer and designed w/ protocols in mind from the beginning.

22:12 nightfly__: is cljs self hosting yet?

22:12 dnolen: nightfly__: nope

22:13 nightfly__: That's too bad. I really like the idea of it but am really attached to macro expansion happening in the same dialect/implementation as the runtime.

22:15 dnolen: nightfly__: I've written some fancy macros and never needed access to the runtime so it doesn't bother me. But it's useful for the very fanciest of fancy macros.

22:16 nightfly__: CLJS will likely bootstrap at some point but there's a quite a bit of work to do. There is a fork of CLJS that bootstraps - http://github.com/kanaka/clojurescript

22:17 nightfly__: I'll definitely check that out, thanks.

Logging service provided by n01se.net