#clojure log - Jul 03 2012

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

0:03 TimMc: Hi Fare!

0:04 This is my writeup of how collections are organized in Clojure: http://www.brainonfire.net/files/seqs-and-colls/main.html

0:05 Fare: I'd say the biggest pitfalls/tradeoffs (in my personal view) are nil-punning for empty seqs, the similar-yet-different nature of seqs and lists, and the lack of a way to ask whether an object can be seq'd.

0:08 Fare: Also, maps have a weird dual nature as collections of pairs of values vs. collections of values. They make the collections API kind of bumpy.

0:10 Fare: As for docs: http://clojure.org/data_structures#Data%20Structures-Collections and http://clojure.org/sequences

0:10 Fare: TimMc, thanks a whole lot!

0:10 michaelr525: good morning clojurians!

0:10 Fare: quite some reading for me

0:11 I'm meeting with my co-author tomorrow, so I'll try to read it all tonight / tomorrow morning

0:11 talios: Fare: book writing?

0:11 michaelr525: Fare: writing another clojure book?!

0:12 Fare: nah, writing a library for common lisp

0:12 michaelr525: a library of books?!

0:12 TimMc: haha

0:13 carlo_au: TimMc: those tables are good

0:13 with the ticks and crosses

0:13 TimMc: carlo_au: They need better icons. :-/

0:13 michaelr525: we call them light tables!

0:13 locojay: hi i have a clojure noir entry point (defpage '_someentry' [& options]...) when i do (assoc hash-map options) i get java.lang.IllegalArgumentException: No value supplied for key: [:iDisplayStart "0"]

0:13 TimMc: How does one represent logical booleans?

0:14 I was thinking of idealized on/off symbols, like |/O

0:14 carlo_au: TimMc: what's wrong with coloured T and F?

0:14 michaelr525: locojay: hash-map is core function i think and assoc requires 3 arguments

0:15 locojay: (assoc a-map key value)

0:15 TimMc: carlo_au: Too visually similar in shape. Something like 10% of people won't see the color difference clearly enough.

0:16 locojay: michaelr525 : i mean (apply hash-map options)

0:16 carlo_au: TimMc: ah, true.

0:16 locojay: i only what they args (options) as a dict

0:17 Fare: TimMc: what's this seq'd thing? (sorry, I'm not familiar with clojure)

0:17 TimMc: ,(seq "foo")

0:17 clojurebot: (\f \o \o)

0:17 locojay: also tried [& {:as options}] but that raises that exception imediatly

0:17 carlo_au: TimMc: google image search for "icons true false" gives green ticks with red crosses

0:18 michaelr525: locojay: try pprinting options, looks like something is wrong there

0:18 TimMc: Fare: If you give seq a thing that it knows how to make into a sequence, it will hand you back something that implements ISeq, or nil if empty.

0:18 Fare: But if someone hands you a random object, e.g. the number 17, you can't tell if seq will throw an error on it. :-/

0:19 wingy: yezz .. clojure is so concise that its being used as the query syntax in datomic

0:19 lol

0:20 michaelr525: ,(hash-map [:a 1])

0:20 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: [:a 1]>

0:20 michaelr525: locojay: see the problem?

0:20 wingy: doesn't that mean that all coders from other langs will be using clojure when they are using datomic .. what a great marketing for clojure

0:20 michaelr525: locojay: you have to explode(?!) the vector in order to pass it to hash-map

0:20 Fare: so it's an ISeq, nil, or an error?

0:20 michaelr525: ,(hash-map :a 1)

0:20 clojurebot: {:a 1}

0:20 Fare: and you don't have ignore-errors or something to catch the error?

0:21 nDuff: wingy: One can use datomic without any Clojure; it's just a lot more work and boilerplate.

0:21 wingy: ...but then, I expect that Java programmers would feel uncomfortable if they *didn't* need boilerplate to get things done.

0:21 wingy: yeah and convert to clojure :)

0:21 Fare: is datomic free software or a trade secret?

0:21 locojay: michaelr525: explode?

0:22 dnolen: Fare: not free software.

0:22 wingy: Fare: free for Open Source projects

0:22 nDuff: ...free-of-cost

0:22 TimMc: Fare: As far as I know, no. The best I know of is to check whether the object is nil?, coll?, array?, or string?.

0:22 michaelr525: locojay: options in your case is a vector of vectors, it has to be just a vector if you use (apply hash-map..

0:22 nDuff: which is certainly not Free

0:22 technomancy: wingy: that's not what free software means

0:22 michaelr525: locojay: maybe flatten

0:22 * nDuff isn't about to touch it for that reason.

0:23 wingy: technomancy: oh :)

0:23 michaelr525: ,(apply hash-map (flatten [[:a 1] [:b 2]]))

0:23 clojurebot: {:a 1, :b 2}

0:23 locojay: michaelr525 thanks

0:23 works

0:23 michaelr525: my pleasure :)

0:23 wingy: is that a good or bad thing that its not free software?

0:23 Fare: ,(file-contents "/etc/passwd")

0:23 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: file-contents in this context, compiling:(NO_SOURCE_PATH:0)>

0:23 TimMc: Fare: If Clojure were rewritten today, I'm sure the boundaries of what seq accepts would be much clearer.

0:24 wingy: or doesnt it matter

0:24 adu: hry

0:24 TimMc: Fare: clojurebot isn't the most secure thing, but it is backed by the JVM SecurityManager sandbox.

0:25 adu: i.m trying to use ring

0:25 TimMc: Until recently you could still get your paws on eval.

0:25 dnolen: TimMc: I doubt it.

0:25 TimMc: dnolen: No protocol?

0:25 dnolen: TimMc: ISeqable protocol maybe, but Clojure will never validate inputs.

0:26 TimMc: Like 80% of this would be cleaned up with protocols: https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/RT.java#L462

0:26 dnolen: TimMc: at runtime anyhow.

0:26 TimMc: well ... actually never say never ... but I don't see it happening in the near future.

0:26 TimMc: dnolen: I'm not asking seq to validate inputs, I just want something that can tell me whether a thing is seqable if *I* want to know.

0:26 technomancy: it could certainly be clearer

0:27 Fare: how closely do clojure and clojurescript keep in sync with each other?

0:27 technomancy: that's what TimMc said

0:27 dnolen: Fare: as close as possible, concerning data structures pretty much identical.

0:27 Fare: does clojurescript implement all the interface infrastructure of clojure?

0:27 technomancy: that's different from stricter

0:27 Fare: is it the same compiler code base?

0:28 dnolen: TimMc: yes CLJS already has ISeqable

0:28 TimMc: dnolen: Good to hear!

0:28 xeqi: TimMc: I've fairly certain you could still get your hands on eval if you tried

0:28 dnolen: Fare: no, CLJS compiler infrastructure is written in Clojure, Clojure compiler infrastructure in Java

0:29 Fare: interface instructure is actually improved in CLJS

0:29 er infrastructure

0:29 adu: Fare? from TUNES?

0:37 amalloy: ~flatten

0:37 clojurebot: flatten just means you failed to use ->> and mapcat correctly

0:37 amalloy: locojay, michaelr525: ^

0:37 brehaut: haha that sounds snarker than it used to

0:37 Fare: adu: yes

0:37 adu: Fare: I'm a big fan of your writings

0:37 Fare: thanks :)

0:37 amalloy: yeah, that's not very helpful :P

0:37 Fare: <blush>

0:37 adu: I think we talked about 3 years ago

0:38 amalloy: ~flatten list

0:38 clojurebot: list* doesn't actually make a `list?`

0:38 amalloy: i hate you, clojurebot

0:38 Fare: we did

0:38 TimMc: ~flatten

0:38 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

0:41 brehaut: thats much better

0:45 amalloy: brehaut: it's what i put there before you taught him your nonsense :P

0:46 brehaut: me‽

0:46 amalloy: was it not you? i thought it was you

0:47 brehaut: well it might have been me, but i dont thing so

0:47 amalloy: i wonder what kind of detective work i'd have to go through to figure out the magic words to make him unlearn that

0:47 TimMc: amalloy: It was you.

0:48 amalloy: directed by M. Night Shyamalan

0:48 TimMc: directed by M. Night Shyamalog is more like it.

0:49 brehaut: the man reason i dont think it was me is that i dont believei have ever successfully taught him anything

0:49 amalloy: 2011-11-21.txt:[19:34:19] brehaut: ~flatten |just means| you failed to use ->> and mapcat correctly

0:49 brehaut: haha well bugger

0:50 im very sorry

0:50 amalloy: haha

0:50 brehaut: (dec brehaut)

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

0:50 brehaut: bah

0:50 you shuld be able to decrement your own karma

0:50 technomancy: agreed

0:50 amalloy: clojurebot: forget flatten |just means| you failed to use ->> and mapcat correctly

0:50 clojurebot: I forgot that flatten just means you failed to use ->> and mapcat correctly

0:50 amalloy: brehaut: you're just being encouraged to use the clojurebot workaround

0:51 ,(println "(dec amalloy"))

0:51 clojurebot: (dec amalloy

0:51 amalloy: ,(println "(dec amalloy)")

0:51 clojurebot: (dec amalloy)

0:51 lazybot: ⇒ 23

0:51 amalloy: clojurebot: you're my own little tor relay on the way to lazybot

0:51 clojurebot: the best way to represent X is as a regular clojure map. (for most values of x)

0:51 TimMc: This is amazing.

0:52 brehaut: ,(println "(dec brehaut)")

0:52 clojurebot: (dec brehaut)

0:52 lazybot: ⇒ 6

0:52 TimMc: (referring to the provenance of those two factoids)

0:52 amalloy: TimMc: how so?

0:52 brehaut: ive got to stop being an idiot. my karma is going through the floor

0:52 technomancy: brehaut: must conserve vital whuffie

0:53 brehaut: that ones lost on me

0:53 TimMc: amalloy: Unless I misunderstood one of your msgs, I took it that both of you were wrong about who had authored each factoid.

0:53 amalloy: TimMc: i was spot-on, bro

0:53 technomancy: brehaut: admittedly quite obscure: http://en.wikipedia.org/wiki/Whuffie

0:53 TimMc: Hmm, OK. "it" is a tricky pronoun.

0:54 brehaut: technomancy: thats far my sophisticated than my usual reading allows for

0:56 amalloy: Raynes: any idea what's up with lazybot?

0:56 Raynes: amalloy: That'd be me.

0:56 amalloy: I'm done now. Was upgrading his clojail.

0:57 amalloy: k

0:57 did xeqi hack us again?

0:57 Raynes: Nope, this was just something I forgot in the last release.

0:57 Well, I'm sure he did, but this is unrelated to that.

0:57 :p

0:58 michaelr525: ,(apply hash-map (->> [[:a 1] [:b 2]] (mapcat identity)))

0:58 clojurebot: {:a 1, :b 2}

0:58 michaelr525: i'd still use flatten instead of this

0:58 much more concise

0:58 amalloy: michaelr525: flatten is anathema

0:59 do not do it unless you want your program to break the moment it gets more complicated

0:59 xeqi: I try not to actually break anything

0:59 * michaelr525 looks up anathema in wikipedia

0:59 amalloy: &(into {} [[:a 1] [:b 2]])

0:59 lazybot: ⇒ {:a 1, :b 2}

0:59 michaelr525: ok, you win :)

1:00 but why would a program break with flatten?

1:00 TEttinger: it undoes ALL nesting

1:00 not just one layer

1:00 michaelr525: ok, i can see when it can be a problem

1:01 then there must be flatten-1 in core or something like this

1:01 amalloy: it's apply concat, mate

1:01 michaelr525: 'cause all i wanna do is flatten

1:01 brehaut: that would be concat

1:02 michaelr525: ,(apply concat [[:a 1] [:b 2]])

1:02 clojurebot: (:a 1 :b 2)

1:02 brehaut: the other gotcha with flatten is that some times people expect it will flatten maps

1:02 ,[(flatten {:a 1}) (flatten [{:a 1}])]

1:02 clojurebot: [() ({:a 1})]

1:02 michaelr525: ,(flatten {:a 1 :b {:c 2}})

1:02 clojurebot: ()

1:03 michaelr525: ooh ugly ;)

1:03 brehaut: i recall lazybot / clojail being caught by that one for a while

1:03 adu: ,(->> [[:a 1] [:b 2]] (concat) (hash-map))

1:03 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: clojure.lang.LazySeq@2e4f937f>

1:03 adu: ,(->> [[:a 1] [:b 2]] (apply concat) (hash-map))

1:03 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: clojure.lang.LazySeq@1038a40f>

1:03 adu: ,(->> [[:a 1] [:b 2]] (apply concat) (apply hash-map))

1:03 clojurebot: {:a 1, :b 2}

1:04 adu: sorry, I'm learning about ->>

1:04 michaelr525: <amalloy> &(into {} [[:a 1] [:b 2]])

1:04 ^^^^^^^^^ best so far

1:04 brehaut: thats because its the idiomatic way to do it

1:04 michaelr525: brehaut: who says?

1:04 brehaut: the clojure community

1:05 michaelr525: i want to talk with him

1:05 amalloy: the clojure language

1:05 adu: idioms are by definition, not one person

1:05 brehaut: well, rhickey can define any idiom he wants for clojure and we all ussually follow along

1:05 michaelr525: brehaut: that's acceptable

1:05 ;)

1:06 adu: not all idioms are nice, for example, birthday punches

1:07 michaelr525: but seriosly the (into) solution is the most _simple_ one, it does exactly what it says (unlike flatten)

1:07 amalloy: i <3 into/for

1:07 brehaut: i <3 outof/doseq

1:08 not really

1:08 xeqi: who is it that <3 juxt ?

1:08 Raynes: amalloy:

1:08 brehaut: EVERYONE

1:08 Raynes: You did see my talk!

1:08 :D

1:08 brehaut: free all the points

1:08 amalloy: technomancy founded the juxt fan club

1:09 adu: Juxtaposition?

1:09 brehaut: yup

1:09 adu: yup

1:09 brehaut: ,((juxt inc dec) 1)

1:09 clojurebot: [2 0]

1:09 adu: wow

1:10 technomancy: it's so gooooood!

1:10 adu: that is incredibly pointless

1:10 brehaut: ~rimshot

1:10 clojurebot: Badum, *tish*

1:10 amalloy: ~rimshot

1:10 clojurebot: Badum, *tish*

1:10 amalloy: damn you, brehaut!

1:10 adu: er i mean points-free

1:10 brehaut: its hard to snipe from this side of the world!

1:13 michaelr525: ,((juxt inc inc inc) 0)

1:13 clojurebot: [1 1 1]

1:13 michaelr525: what's so good about it?

1:14 (except the cool name)

1:16 ,(juxt juxt juxt inc 0)

1:16 clojurebot: #<core$juxt$fn__2476 clojure.core$juxt$fn__2476@241bd8cd>

1:16 michaelr525: ,((juxt juxt juxt inc 0))

1:16 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core$juxt>

1:17 amalloy: we should see if TimMc can develop a turing-complete clojure dialect using only juxt

1:17 brehaut: lol

1:21 ,((comp (partial apply +) (memfn invoke) (partial apply juxt) (partial map (constantly (constantly 1)))) [1 2 3 4])

1:21 clojurebot: 4

1:23 brehaut: im slightly amazed that that worked

1:23 amalloy: that looks like count

1:23 xeqi: ,(doc memfn)

1:23 clojurebot: "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn."

1:23 brehaut: it is the worlds dumbest count yes

1:23 i had to force the juxt in unnecessarily

1:23 technomancy: stylin'

1:27 brehaut: ,(require 'clojure.reducers)

1:27 clojurebot: #<RuntimeException java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate clojure/reducers__init.class or clojure/reducers.clj on classpath: >

1:27 brehaut: ,(require 'clojure.core.reducers)

1:27 clojurebot: #<RuntimeException java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath: >

1:28 amalloy: brehaut: they're both on 1.4

1:28 brehaut: amalloy: and i got the NS wrong the first time

1:29 talios: brehaut - you just hurt my brain.

1:30 brehaut: talios: i do what i can

1:31 talios: its the dumb version of ##(apply + (map (constantly 1) [1 2 3 4]))

1:31 lazybot: ⇒ 4

1:32 brehaut: but that has no juxt, so who would want that

1:33 talios: sane people not from the 'tron

1:33 brehaut: same people would call count ;)

1:33 s/m/n/

1:33 xeqi: ,(map apply [inc dec] ((juxt inc dec) 0))

1:33 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

1:35 brehaut: ,(map apply [inc dec] ((juxt (comp vector inc) (comp vector dec)) 0)) ; xeqi

1:35 clojurebot: (2 -2)

1:36 brehaut: &(use 'useful.fn)

1:36 lazybot: ⇒ nil

1:36 xeqi: blah, I was hoping for a closer equivalent to &&&

1:36 brehaut: ,((knit inc dec) ((juxt inc dec) 0))

1:36 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: knit in this context, compiling:(NO_SOURCE_PATH:0)>

1:36 brehaut: &((knit inc dec) ((juxt inc dec) 0))

1:36 lazybot: java.lang.RuntimeException: Unable to resolve symbol: knit in this context

1:37 brehaut: xeqi: useful has 'knit which is what you want

1:38 xeqi: &useful.fn/knit

1:38 lazybot: java.lang.RuntimeException: No such var: useful.fn/knit

1:38 brehaut: amalloy: does lazybot roll with an archaic version of useful?

1:38 amalloy: i'm not sure he has useful at all

1:39 oh, he does

1:39 yes, probably ancient

1:40 brehaut: xeqi: https://github.com/flatland/useful/blob/develop/src/useful/fn.clj#L94-100

1:41 also http://swannodette.github.com/mori/#knit

1:41 michaelr525: what would you use to format a date into string in this format: "10/10/2012" ?

1:42 amalloy: $javadoc java.util.text.SimpleDateFormatter

1:42 was i close? maybe not

1:42 $javadoc java.text.SimpleDateFormatter

1:43 i guess for starters i'd advise that you make sure the date is always the same as the month, if you're going to format it that way

1:43 cuz europeans and americans will disagree about what that date means

1:43 brehaut: well, not that date

1:44 thats the tenth of october no matter how you slice it

1:44 augustl: are there any systems for "environments" for Ring apps? Like "development", "test", "production", etc, with different db settings and what not

1:44 brehaut: but 1/10/2012 would the the tenth of jan here

1:44 augustl: there's always environment variables I guess

1:45 brehaut: ring itself doesn't concern itself with settings, but yes, env vars are a common approach

1:45 err apparently i have been americanized

1:45 it woudl the the first of october here

1:45 amalloy: you can also put your config into a .clj file on the classpath and read it at startup

1:45 xeqi: augustl: env vars, or some fun use of lein2's profiles

1:46 augustl: xeqi: looking up lein2 profiles, tnx

1:46 xeqi: basically used as a way to seperate configs in different resource paths, and read it on startup like amalloy mentioned

1:47 clojars does something like that

1:47 augustl: makes sense, so I can have stuff in project.clj without checking it in to git, basically

1:51 michaelr525: i really like the interop stuff in clojure, easier to write java in clojure-java interop than java in java

1:54 ,(-> (java.text.SimpleDateFormat. "MM/dd/yyyy") (.format (java.util.Date.)))

1:54 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class java.util.Currency>

1:56 xeqi: of course, the Currency class is required for one of those

2:00 amalloy: &(-> (java.text.SimpleDateFormat. "MM/dd/yyyy") (.format (java.util.Date.)))

2:00 lazybot: ⇒ "07/02/2012"

2:07 michaelr525: (diff lazybot clojurebot)

2:07 ,(clojure-version)

2:07 clojurebot: "1.4.0-master-SNAPSHOT"

2:07 michaelr525: &(clojure-version)

2:07 lazybot: ⇒ "1.4.0"

2:10 amalloy: really? i thought for sure clojurebot was on 1.4.0

2:23 Raynes: michaelr525: lazybot is a totally different bot.

2:23 You'd have one hell of a diff to look at.

2:26 gtuckerkellogg: ahh, it was

3:27 augustl: how do I access the full request in compojure routes? All I can find is how to access path parameters from the URL.

3:27 weavejester: augustl: (GET "/blah" request …)

3:28 augustl: Or: (GET "/blah" [x y :as request] …)

3:28 augustl: ah

3:28 where x and y are keys in the request map?

3:28 weavejester: augustl: No, where x and y are parameters

3:29 augustl: I want to access more than the parameters, like the request body

3:29 weavejester: augustl: ":as" raises you up, like normal destructuring

3:29 augustl: but that's what 'request' does?

3:30 weavejester: augustl: Yes, so with normal destructuring you could bind "request" or "{:as request}"

3:30 augustl: With the vector bindings you can also use [:as request]

3:31 augustl: I see

3:38 kral: namaste

3:56 augustl: hmm, cheshire doesn't like a org.eclipse.jetty.server.HttpInput

3:57 should I turn it into a string or something by hand?

4:00 slurp to the rescue

4:02 where are the options I can pass to slurp documented? the docs for slurp refer to clojure.java.io/reader, but the docs for that one does not document the options either

4:19 amalloy: augustl: perhaps just in the source, though i imagine clojuredocs has some supplementary explanation

4:19 augustl: amalloy: I'll look that up, thanks

4:33 dsabanin: hey guys

4:34 fmw: this piece of code is irking me somehow: http://paste.lisp.org/display/130373 - there must be a prettier way to write this with the standard functions?

4:35 augustl: fmw: what's the x and y symbols?

4:35 fmw: it feels like I'm missing something very obvious as to how to implement this cleanly

4:35 augustl: just ignore those, its basically a simplified version of some code I'm working on

4:36 augustl: (merge {:bar foo :barfoo :foobar} your-map)

4:37 fmw: augustl: http://paste.lisp.org/display/130374 that is the full version, but the sample should do

4:37 augustl: if I'm reading it correctly

4:37 fmw: augustl: what about the conditionals?

4:37 augustl: ah :)

4:37 fmw: I meant to ignore the values of x/y, should've been clearer there, sorry ;)

4:38 because I still need the conditionals

4:39 augustl: the symbols come from a destructured map, perhaps you should work directly on the map instead of on the destruct values

4:39 fmw: I'm sure I could write a macro to make this prettier, but imho that is overkill, but somehow I have the feeling that I'm overlooking a much prettier solution using the standard stuff that is available in Clojure

4:39 augustl: they don't come from a map and now I'll shut up

4:40 fmw: augustl: don't worry, I'm happy someone is responding ;)

4:40 reading other peoples code is always a pain.

4:41 augustl: especially when you're not very familiar with the language ;)

4:41 fmw: augustl: liking Clojure so far?

4:43 augustl: very much so

4:43 it's mostly just the lispyness that's causing trouble

4:43 fmw: loving the separation of values, identity and time!

4:44 fmw: it takes some getting used to, but once the pieces starting falling into place and you wrap your head around it, it feels so natural

4:45 s/starting/start

4:45 augustl: fmw: btw have you considered changing your API to take a map instead of a large vector?

4:45 noidi: the CCW documentation states that "Once you have started a REPL for your project, eclipse will use a backdoor connection to this REPL to automatically compile and load the files you edit (if the eclipse Project > Build automatically option is selected, of course)."

4:45 augustl: that will solve your problem and make for a better api imo :)

4:45 noidi: and "In conjunction with auto-compile functionality, compilation problems are reported as problem markers"

4:45 does that work for anyone else? I can't get it to work.

4:46 augustl: fmw: indeed, it feels very natural. Like Rich Hickey said in a talk, it doesn't really make much sense to change the date of a month (like with date.setMonth in Java), immutability maps much better to the real world as long as you leave time out of the equation

4:46 fmw: augustl: the API isn't taking a vector, I'm just using it for destructuring optional values

4:46 noidi: I've tried this on two boxes now (Linux and Windows) and neither report compilation problems, even if the source is not valid and I get an error if I try to load it

4:46 augustl: and in most programs, you do want to leave time out of the equation, usually in the form of locks

4:47 fmw: you call it like e.g. (get-documents-for-feed "vix" "en" "blog" 10)

4:47 where 10 is the first optional argument, you can have two more (i.e. startkey and startkey_docid)

4:47 augustl: fmw: well, a list of some kind, if not a vector

4:48 it's just that in general I prefer APIs like (get-documents_for_feed {:db "vix" :language "en"}) etc

4:48 I've programmed too much Objective-C I guess

4:48 fmw: augustl: I see. I'm not sure if that is idiomatic in Clojure, but I guess it is a matter of taste.

4:49 augustl: fmw: perhaps a multi-method is better in your case

4:49 fmw: it is practical for some functions, but doesn't have added value for most, yet still adds a lot of cruft you have to type all the time

4:50 augustl: that could work, yes!

4:52 augustl: fmw: iirc the syntax is something like this http://paste.lisp.org/display/130375

4:52 not sure if there's a clever way other than named refs to avoid duplication of the defaults

4:52 and obviously some definitions are missing from that example

4:52 fmw: augustl: a multimethod is with (defmulti ...)

4:53 augustl: yeah not sure what the difference is there..

4:53 I think my paste is a valid method for creating a function that dispatches based on the number of args though

4:54 fmw: augustl: the syntax you pasted is nice for simple cases, defmulti gives control over the dispatch if you want to dispatch by custom things, like type

4:54 yes, it is

4:54 augustl: its actually exactly like my original implementation of the dispatch: https://github.com/fmw/vix/blob/master/src/vix/db.clj#L204

4:55 I'm currently refactoring that code to make it cleaner, with the knowledge I gained since I wrote it

4:55 e.g. fixing silly things, like (map #(:value %) some-map) into (map :value some-map)

4:56 augustl: clojure does have a gazillion small features

4:57 fmw: I'm actually refactoring those (defn some-fn ([x y] (some-fn x y nil)) ([x y z] (do-something x y z))) into (defn some-fn [x y & [z]] (do-something x y z))

4:58 I prefer the latter, because it is more concise and arguably makes it more clear which variables are optional at a glance

5:00 augustl: I'm quite fond of multimethods for more complicated dispatch scenarios, though, like https://github.com/fmw/alida/blob/master/src/alida/lucene.clj#L90

5:00 dsabanin: fmw: what about http://paste.lisp.org/display/130376?

5:01 fmw: dsabanin: I think that must be the solution, thanks. let me adapt it into my code and see

5:02 dsabanin: fmw: cool, np

5:02 well, actually it's even better

5:02 merge accepts nil as arguments

5:03 so it's just http://paste.lisp.org/display/130377

5:04 damn, not, you just can do (if x {:bar :foo})

5:04 fmw: dsabanin: I think you can, but I'd use when?

5:04 dsabanin: yep

5:04 augustl: what's the #^ part of this? `(defn #^IndexWriter create-index-writer`

5:04 the docs for defn doesn't seem to mention it

5:04 dsabanin: augustl, it's a type hint for performance optimization

5:05 it specifies the kind of java type that is being returned

5:05 fmw: augustl: that is like soft typing (telling Clojure what type to expect, for performance gains)

5:05 augustl: it's not documented for `def` either, where is it documented?

5:05 clgv: augustl: #^IndexWriter is deprecated! use ^IndexWriter instead

5:06 augustl: clgv: and where's _that_ documented? :P

5:06 clgv: augustl: it is called a typehint

5:06 fmw: augustl: http://clojure.org/java_interop#Java Interop-Type Hints

5:07 clgv: augustl: you'll only need those if clojure complains when compiling and having set *warn-on-reflections* to true

5:07 fmw: clgv: that was my code actually, thanks for pointing it out, will have to fix that at some point

5:08 I actually like type hints as semi-documentation in java glue code too, not just for performance gains

5:08 because it makes it instantly clear what your fn is supposed to return

5:08 augustl: fmw: out of curiousity, do you do any locking etc to make the IndexWriter work across threads? I'm currently writing an HTTP API that will write to Lucene indexes actually, and need to handle that.

5:09 fmw: augustl: which version of Lucene?

5:09 augustl: 3.6

5:09 fmw: augustl: Lucene 4.0 has built-in stuff for that

5:09 (so does 3.x, afaik, but you really should be using 4.0)

5:10 augustl: hmm, IndexWriter is thread safe it says for the 3.6 docs

5:10 fmw: 4.0 has been used in production for a while and should be released soon with a lot of backwards compatibility breakage and all sorts of improvements, so best to use it for new code already

5:11 augustl: hmm

5:11 fmw: augustl: yes, they have their own manager classes that deal with your writers/readers (4.0 fully breaks them apart, btw, while in 3.x you could write using a reader IIRC)

5:11 augustl: 4.0 is not even mentioned on http://lucene.apache.org/

5:12 fmw: augustl: https://twitter.com/kucrafal/status/218633823976566784

5:13 augustl: it has been stable for the last 12 months, or so, and people have been using it in production a lot, so it is a safe bet, imho

5:13 Lucene developers are *very* conservative and don't generally break things

5:13 augustl: why not (tm) :D

5:14 fmw: do you happen to know if there are JavaDocs hosted for 4.0 anywhere?

5:14 fmw: augustl: yes, let me find them. there are also some very good background docs on the changes

5:15 augustl: https://builds.apache.org//job/Lucene-trunk/javadoc/

5:15 augustl: yay

5:15 wut, why does it say 5.0? :)

5:16 fmw: augustl: good question. I think they've updated their trunk to 5.0 now, to make the 4.0 branch stable for release

5:16 http://blog.mikemccandless.com/ is a good resource about some of the changes in 4.0, too, btw

5:16 augustl: makes sense

5:18 Lucene is pretty darn awesome. After struggling to figure out a way to start Solr other than the start.jar in the "example" of the tarball and browsing through a zillion XML files, I thought I'd might as well use Lucene directly

5:18 turned out to be a sound decision ;)

5:18 fmw: augustl: feel free to use http://github.com/fmw/alida as a starting point for your stuff, as I wrote it as example code for a Lucene talk (and don't be afraid to ping me if you have any questions/requests for improvement, as I'm planning to build a real-world thing out of the alida project)

5:19 augustl: yes, Solr is nice if you don't have access to a JVM or need some of their specific features, but I haven't used it at all so far, despite doing quite a lot of search-related work

5:21 augustl: fmw: great :D

5:26 fmw: very off topic, but there's not much activity in #lucene.. My data will always be queried by a foreign key. Do you think I should put everything in one index, and always add the foreign key to all queries, or have a separate index per foreign key/group?

5:27 fmw: augustl: can you specify the foreign key?

5:27 augustl: fmw: I'm indeing attendants, the foreign key is an alphanumeric id, "event_id"

5:28 fmw: augustl: unless you're data is really big, just put the event_id in a field and filter your queries on that

5:28 no need to split anything

5:28 augustl: I'm thinking one large index, and shard it manually later. The number of events will grow and grow, which means a lot of files in one folder, lots of open files, etc.

5:28 fmw: yeah makes sense

5:30 fmw: augustl: Lucene has built-in IndexReaders for that, and you can also write your own

5:31 augustl: fmw: as in built-in IndexReaders for foreign key type queries?

5:31 fmw: dsabanin: thank you, that was exactly the cleaner solution I was looking for.

5:31 augustl: as in dealing with large datasets

5:33 the foreign key type thing is just something to filter on in Lucene, next to your query. There is a performance consideration, though, because Lucene 4.0 has switched to byte indexing, so its actually fast to store/filter on numbers now

5:33 augustl: fmw: ah

5:33 the semantics of a progammatic API vs query strings is reason enough to use Lucene directly imo

5:33 fmw: so if its an integer that won't take up much space and its best to store it as a numeric value

5:34 augustl: yes, even though you can use both.

5:34 augustl: the foreign keys are alphanumeric, but I suppose I'll figure something out

5:34 (ObjectID's from MongoDB)

5:35 fmw: augustl: probably not worth changing them to numeric values in that case

5:42 I'm going for a swim now, getting too hot in the afternoon sun here in Greece (I'm a northener and not used to the heat). Feel free to contact me if you have more questions about using Lucene from Clojure (https://twitter.com/#!/filipdewaard or fmw@vixu.com).

7:40 augustl: is there a function to flip a boolean? Need it for dosync/commute.

7:40 AWizzArd: augustl: you could use “not”.

7:40 augustl: oh wait I can just pass in my own function I guess

7:40 AWizzArd: ah, of course

7:40 AWizzArd: $(not true)

7:40 ,(not false)

7:40 clojurebot: true

7:40 AWizzArd: ,(not true)

7:40 clojurebot: false

7:41 augustl: or just ref-set I guess

7:41 Licenser: worth reading: http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/

7:54 wink: worth reading, yes. but it's written by a seemingly very angry person, it's not necessarily very correct

8:35 jweiss: just discovered edebug in emacs. is there any reason (beyond that no one has sat down to do it yet) that clojure couldn't have a similar debugger?

8:38 romain_p: Hi everyone, can anybody help me create the simplest possible raphaeljs example (e.g. a circle) using clojurescript (maybe starting from cljs-template)? I am just beginning with cljs and a bit bewildered... :)

8:39 gfredericks: romain_p: I'm doing cljs + raphael right now! :D

8:39 I'm doing it all with js interop though, so if you know how to do it in js it shouln't be hard

8:39 romain_p: gfredericks: awesome :D could you point me in the right direction?

8:41 gfredericks: romain_p: (def paper (js/Raphael ...args...))?

8:41 (.circle paper ...)

8:42 not sure what you're having trouble with

8:42 romain_p: gfredericks: ah well, it's more about setting stuff up. Where should I import the raphael lib?

8:43 gfredericks: romain_p: I just have the js file lying around

8:43 and a <script> for it in my html file

8:44 romain_p: ah OK, will try. I started from the cljs-template leiningen target, so I do not use a static html file, but I suppose I can require the javascript from the hiccup template

8:44 include-js or something

8:45 gfredericks: romain_p: I don' know anything about cljs-template

8:46 romain_p: gfredericks: it is a sample noir+cljs+hiccup application, kind of a "getting started" kind of thing apparently...

8:47 gfredericks: ah ha

8:52 Is there no easy way in cljs to dynamically call a method? i.e., ob[s]()?

8:52 I just wrote a macro for it

8:53 augustl: are therre any utils for making a string of hex encoded bytes into a byte array?

8:55 jcromartie: "A LISP dialect? LISP was far and away the worst language I ever had the misfortune of having to use in school" - people keep saying this

8:56 romain_p: gfredericks: OK, that did it. Thanks for the help!

9:00 augustl: jcromartie: I like to say that Lisps are as similar to other lisps as Java and JavaScript are similar.

9:01 jcromartie: people I interview, new hires out of school, people who call themselves "Java EE guys"

9:01 augustl: jcromartie: "Lisp is a language" doesn't make sense to me, it's a bit like saying "camel case and curly brackets is a language"

9:02 jcromartie: and saying "Lisp is for AI" is like saying "Ruby is for web apps"

9:02 not even… "Ruby is for web apps" is at least closer to truth in a statistical sense

9:03 but anyway, yeah, there's an image problem there

9:03 I don't know what people do with Lisp in school… I never went, myself

9:03 BRB… going for a run

9:12 mystiiq: can anyone point out an example how to use declare function. basically some my functions want to use a shared Java object and I want that the first one who will try to use it must initiate it

9:13 gfredericks: mystiiq: would delay do what you want? or does the first one trying to use it also have to decide _how_ to initiate it?

9:14 ,(let [foo (delay (make-foo))] (defn get-foo [] @foo))

9:14 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

9:14 gfredericks: mystiiq: something like that ^

9:15 mystiiq: the first one does not have to decide how to initiate it

9:15 gfredericks: delay should work then

9:27 TimMc: amalloy_: Just juxt and parens, eh? You'd have to use encoded numerals, but it might actually be possible.

9:28 amalloy_: Wait, no -- juxt produces vectors, which expect system integers for dereference. Not feeling it.

9:28 uvtc: What does "immutability precludes backreferences" mean? (seems to be in the context of nested data structures)

9:31 gfredericks: uvtc: backreferences I think is synonymous with self-reference or cycles

9:31 uvtc: It's mentioned in the CP chapter on zippers.

9:32 augustl: waat. What am I not getting here? `(byte 0xff)` => IllegalArgumentException Value out of range for byte: 255

9:32 what kind of bytes are these? ><

9:32 gfredericks: uvtc: it's why you can't use normal mutable-data-structure approaches to walking a tree

9:32 like parent.children() and child.parent()

9:33 for going down and up respectively

9:33 uvtc: Hm.

9:34 gfredericks, Ok. I was thinking I could "walk the tree" by using assoc-in...

9:34 mystiiq: in java !false is true, what's the similar syntax in clojure?

9:34 gfredericks: well that's good for single updates

9:34 mystiiq: (not false)

9:34 augustl: oh, bytes are signed

9:34 mystiiq: ok thanks

9:35 gfredericks: uvtc: if you want to be effiient and you have a lot of work to do at the bottom of the tree you don't want to keep walking from the root for each operation

9:35 uvtc: it's a lot of time and unnecessary object allocations

9:35 TimMc: ~byte

9:35 clojurebot: http://homepages.inf.ed.ac.uk/kwxm/JVM/codeByNo.html

9:35 TimMc: feh

9:36 augustl: TimMc: :D

9:38 TimMc: Although I do like that URL: "code by number"

9:38 uvtc: gfredericks, why would a data structure being immutable have anything to do with being able to figure out where a parent/child is? Seems like that's more related to the items in the d/s not being OO-style objects...

9:38 gfredericks: uvtc: figuring out the child is usually easy, but not the parent

9:39 TimMc: uvtc: Try to build a Clojure list or vector that contains a reference to itself.

9:39 Or two that reference each other, rather.

9:39 gfredericks: if I have a tree [:ul [:li] [:li]] and call (nth tr 2) on that,, the return value has no idea that it "is in" a tree

9:40 it is simply [:li] and has no reference to its parent

9:40 so when you get to that point you can't get back up

9:40 tbaldridge: .parent() is a horrible way to transverse a tree anyways (IMO)

9:41 recursive functions have always done the trick for me.

9:41 gfredericks: yeah they work for most cases

9:42 hell if I've ever used a zipper for anything

9:42 TimMc: tbaldridge: Unless you're doing zipper type stuff, of course.

9:42 gfredericks: TimMc: have you ever done zipper type stuff?

9:42 TimMc: It's sueful if you need to carry child information back up to parents.

9:42 gfredericks: No, but I told someone else to use them once. :-P

9:42 gfredericks: :)

9:43 it's like refs. We all know what they do.

9:43 tbaldridge: TimMc: if you need to carry data up to the parent. Then start at the top, and have the function applied to the child return the data to the parent

9:43 gfredericks: and then we use proper databases instead because they are persistent

9:43 TimMc: Say you have a tree of maps, and you want to add an incrementing :id field to each map according to an in-order walk.

9:43 That's a use-case for zippers.

9:45 uvtc: TimMc, if I try to make 2 data structures with parts that refer to parts of eachother, it fails because I Clojure gives me the value of things, not references to them.

9:45 TimMc, but this appears to me to be because of not using any reference types ... not because of immutability...

9:45 TimMc: (Specifically, a binary tree.)

9:46 gfredericks: uvtc: no it's because of immutability

9:46 you do have references

9:46 TimMc: uvtc: You get references to their values.

9:46 gfredericks: in the jvm sense

9:46 TimMc: Those references are immutable in Clojure.

9:46 Or, well, they're immutable anyway.

9:46 gfredericks: in java you could (let [a (new A), a' (new A)] (.setFoo a a') (.setFoo a' a))

9:46 * TimMc offs to work

9:47 gfredericks: the only difference between that and clojure data structures is mutability

9:47 uvtc: TimMc, thanks. gfredericks : still reading your comments.

9:47 gfredericks: you can't set a vector's contents after you construct it

9:47 you CAN do this with lazy-seqs I believe

9:48 lazy-seqs have a kind of mutability

9:52 ,(let [x (promise), self-containing-seq (lazy-seq (cons @x ()))] (deliver x self-containing-seq) self-containing-seq)

9:53 clojurebot: ((((((((((#))))))))))

9:53 gfredericks: o_O

9:53 &(let [x (promise), self-containing-seq (lazy-seq (cons @x ()))] (deliver x self-containing-seq) self-containing-seq)

9:53 lazybot: java.lang.StackOverflowError

9:53 gfredericks: that's better

9:53 uvtc: gfredericks, you wrote "the return value has no idea that it "is in" a tree ... it is simply [:li] and has no reference to its parent ... so when you get to that point you can't get back up". I see what you mean here. Thanks!

9:54 gfredericks: uvtc: awesome

10:04 scriptor: have a question that isn't really clojure-related, but still fp-related

10:04 I'm trying to stick to the idea of data as data, and just using plain hashmaps instead of more complex objects

10:05 however, I'd also like to be able to listen for changes to the data and re-render parts of the interface when needed

10:06 augustl: what's the canonical way of despatching a method based on the types of its arguments? Multimethods? Protocols? Something else?

10:06 scriptor: should I just create an interface through which the hashmaps are 'modified' (either in-place or by doing something assoc-style) and then these functions are responsible for updating the view?

10:07 dnolen: scriptor: I need to start keep track of how many times this question comes up :)

10:08 scriptor: nothing exists, we need a functional answer to data binding - probably something FRP-like that isn't a hassle to use.

10:08 scriptor: dnolen: not surprised, I'm basically asking for very limited FRP :p

10:09 hmm, I'm trying to at least move away from the idea of models in js

10:10 dnolen: cljs.core.rx sounds like a pretty compelling contrib ...

10:11 scriptor: link please? Can't find anything on google or github

10:11 dnolen: doesn't exist.

10:11 zerokarmaleft: dnolen: reactive extensions?

10:12 scriptor: ah, as in a name idea :)

10:12 dnolen: zerokarmaleft: yes

10:14 tbaldridge: I've been playing around with trying to do something rx-esque in Clojure. My work still is way too mutable for my liking though

10:14 Ot'

10:14 madsy: Is there a nice article somewhere on how to setup lein-cljsbuild and clojurescript manually? The stuff on Maven is like a century old, with non-official version numbers.

10:15 tbaldridge: From my reading FRP is functional, but highly complex (at least the flapjax way), while Rx is highly un-functional, and mutable, but easier to learn/design

10:15 dnolen: tbaldridge: my sense is we need to learn from both and design something better

10:16 TimMc: dnolen: In FRP as you used it, R = relational?

10:16 or reactive?

10:16 scriptor: TimMc: I think it's Reactive

10:16 dnolen: TimMc: no, Functional Reactive Programming

10:17 tbaldridge: dnolen: agreed. That's why I've been looking into dataflow recently, it's not quite there either, but it's simpler than the hardcore FRP stuff.

10:17 scriptor: you represent an otherwise mutable value as a behavior, which represents both the present and all future values

10:17 TimMc: OK. I'm reading Out of the Tar Pit and keep getting mixed up when I see "FRP". :-)

10:17 tbaldridge: madsy: this tut worked for me when I used it last week: https://github.com/emezeske/lein-cljsbuild

10:18 madsy: i was using lein2, so I had cljsbuild to my .profile.clj but besides that it "just worked(TM)"

10:19 otfrom: CfP for 6 December Clojure eXchange if anyone fancies giving a talk in London. :-D http://bit.ly/clojurex12-cfp

10:19 madsy: tbaldridge: How does lein2 find your custom-built lein-cljsbuilt plugin? Did you just copy it to the ~/lein/plugins directory?

10:20 Or did you set up a local maven repo?

10:21 tbaldridge: madsy: I mis-typed there. You need to add {:user {:plugins [[lein-cljsbuild "0.2.2"]]}} to a file in ~/.lein/profile.clj Then just do lein deps and lein will install it.

10:21 madsy: tbaldridge: Maybe what needs to be done is supposed to be obvious from the github readme, but it's not obvious to me

10:21 tbaldridge: madsy: https://github.com/technomancy/leiningen/wiki/Upgrading

10:22 madsy: tbaldridge: So you got lein-cljsbuild prebuilt from maven?

10:22 Because, that's not what I asked about.

10:23 tbaldridge: madsy: bleh, my bad...I missed that first part. Sorry, I thought you were just trying to get it working with lein2

10:23 madsy: No worries :)

10:24 But yes, incidentally I should get lein2

10:25 xumingmingv: hi all, need help on this line of code: https://github.com/xumingming/storm/blob/master/src/clj/backtype/storm/thrift.clj#L19

10:26 it creates a new java object according to the classname using the *new* macro

10:26 my question is: the corresponding class is not imported, why this line of code can work?

10:27 mystiiq: when a java method returns an array of strings, how can I extract first one from the array in clojure ?

10:28 xumingmingv: mystiiq: (aget arr 0)

10:29 mystiiq: xumingmingv: thanks

10:30 mduerksen: mystiiq: ##(first (long-array [1 2 3]))

10:30 lazybot: ⇒ 1

10:30 dnolen: tbaldridge: let me know where the dataflow stuff goes, would like to check it out.

10:35 lynaghk: your todo example looks nice, tho I agree, not really MVC (which is a good thing)

10:36 scriptor: I was dissapointed by the move article that floated around yesterday

10:37 it's basically just MVC+events

10:39 mystiiq: how can I make java String array or convert clojure array into one

10:40 list is also an option

10:40 augustl: "To re-iterate: MVC is awesome, but it's designed with decades old technologies. MOVE is just a update to make better use of the new tools we have." is that content-free or what

10:41 mystiiq: lets hope to-array works

10:41 augustl: mystiiq: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/to-array

10:41 afaik

10:43 S11001001: mystiiq: no

10:43 ,(instance? (map identity [1,2,3]) java.util.List)

10:43 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Class>

10:43 S11001001: right

10:43 TimMc: S11001001: You lost the argument order lottery.

10:43 S11001001: ,(instance? java.util.List (map identity [1,2,3]))

10:43 clojurebot: true

10:44 S11001001: the way I do

10:44 TimMc: mystiiq: Do you need a list, or any sequential coll?

10:44 mystiiq: Also, there's no "clojure array".

10:44 S11001001: ,(type (to-array [1,2]))

10:44 clojurebot: [Ljava.lang.Object;

10:45 mystiiq: TimMc: I need something that implements java.util.List interface or String array

10:45 lancero: what am I doing wrong here: http://pastebin.com/JRBW1ckb ? I expect that when test-promises gets called it will start delivering 5 futures into promises, then start blocking (since old isn't realized yet). Instead the function returns immediately with nothing delivered.

10:45 S11001001: mystiiq: then all you have to deal with is the nil case

10:49 lancero: for isn't a looping construct

10:50 jweiss: (binding [*print-length* 50] (iterate inc (System/currentTimeMillis))) -> OOM. what am i missing?

10:52 TimMc: jweiss: The print is happening outside your binding.

10:53 S11001001: I wish for required you to specify what monad you wanted

10:53 jcromartie: *facepalm*

10:53 locojay: hi i m using jayq and would like to do something like this in js $("td:eq(1)", this).text(); (.text ($ "td:eq(1)")) works but i need this so i don't always get the same val

10:53 jcromartie: the "LISP was far and away the worst language I ever had the misfortune of having to use in school" guy

10:54 I said, "well I didn't go to school, I don't know how they tortured you with it there"

10:54 and I get "You didn't get a degree, are you joking with me? How did you get a job?"

10:54 TimMc: haha

10:55 "Market forces."

10:56 jweiss: TimMc: ah yes, knew it had to be something obvious

10:56 thanks

10:58 mefisto`: jcromartie: I think people who went to school for it can more easily miss the fact that we are living in the most exciting time for computing ever :D

10:59 jcromartie: mefisto`: I just don't know how you can work in programming for any length of time and still be incredulous about non-credentialed professional programmers

11:00 mefisto`: I mean this guy has even written books (not great ones…)

11:00 wkelly: it is easy to be oblivious when you are self-absorbed!

11:02 lancero: S11001001: I changed for to doseq. Now test-promises returns after about 10 seconds like I expected. But everything is already realized immediately when on return.

11:02 mefisto`: jcromartie: same reason he didn't like LISP I imagine... he's stuck in some fixed idea of the way things are "supposed to be" and so is blind to seeing anything that challenges that

11:03 tbaldridge: mefisto: I agree. Our architect told me "I just don't like this FP stuff...I mean we abandoned it when we invented OOP. It's all just such a step backwards..."

11:03 gfredericks: haha

11:03 tbaldridge: then he goes and sits for a day trying to figure out what a object does with its mutable state

11:03 So yeah...my face and my palm are well acquainted

11:05 mefisto`: tbaldridge: try not to blame him too much, because he's half right. OOP was invented because FP was too difficult for some people to understand, and there was unmet demand for programmers

11:05 dnolen: mefisto`: I hope you don't really think that :)

11:07 acheng: why not? mefisto`s just describing well-intentioned wrong people.

11:07 gfredericks: plausible != accurate

11:08 dnolen: acheng: "OOP was invented becausae FP was too difficult"

11:08 acheng: too difficult for some

11:08 gfredericks: also that part

11:08 dnolen: far as I know, Smalltalk OOP (which is in wide use in various perverted forms), was created as a response to Lisp's special forms.

11:08 nothing to do w/ difficulty around FP or anything else.

11:08 acheng: oh. ok

11:08 gfredericks: what's wrong with special forms?

11:09 acheng: nothing :)

11:09 dnolen: gfredericks: nothing, but nobody at the time had a good answer why we needed them.

11:09 hyPiRion: Yeah, it's not like people say "Oh, this is too hard! Let's invent something easier" and then magically came up with OOP.

11:09 gfredericks: dnolen: as if you can have a language with no primitives? :/

11:09 dnolen: gfredericks: so Alan Kay et al looked at messages.

11:09 tbaldridge: And SmallTalk is not very much like what the Java/C# people think it is.

11:09 hyPiRion: But OOP was a concept which was easier to understand for imperative programmers.

11:10 (I suppose?)

11:10 mefisto`: dnolen: Well, only sort of. But OOP allows you to substitute a large number of easy to understand problems (tracking down where some variable is getting changed or some little bug is happening) for the smaller number of hard to understand problems (really understanding the algorithm and modeling the problem properly). So I guess I'm really talking about why OOP became popular for business programming rather than why it was invented :D

11:11 dnolen: mefisto`: hyPiRion: these arguments don't really make that much sense considering the amoutn of pushback there was too OO in the 80s, the slowness of C++ etc.

11:11 OO wasn't taken seriously by the mainstream until the mid 90s I'd say.

11:12 wkelly: when craziness ensued with STL and java

11:13 mefisto`: yeah, I wonder if that wasn't just a function of tooling and platform maturity

11:13 tbaldridge: And even Alan Kay didn't mean for OOP to end up like Java. To quote him "Erlang looks like almost what I've been talking about since the mid-60s, I wonder how I missed it for so many years?"

11:13 scriptor: or marketing ;)

11:14 when did java become the defacto language for cs curriculums?

11:14 because I wonder how much of a cause it was for OOP popularity vs how much it was a reaction

11:14 mefisto`: scriptor: somewhere in the 90s is when that really started, from what I heard

11:15 acheng: scriptor: at MIT it felt like a reaction

11:15 ohpauleez: Scriptor: Yeah, later 90's it started to get picked up. Early 00's it was pretty well established - mostly because other school started doing their research in Java

11:16 scriptor: acheng: how long ago? I know they continued to use scheme until a couple years ago for sicp, but I don't know about their other courses

11:16 ohpauleez: so if you wanted to build off of it, or interop with it, you also had to use Java, and if you wanted your lab to be well established in Java, you used it as the intro language

11:16 scriptor: mefisto`: ohpauleez: ah, thanks, so it sounds pretty reaction-y

11:16 ohpauleez: At Drexel, you learned Java, Python, JavaScript, C++, and a little Common Lisp

11:17 acheng: scriptor: there were classes using java, maybe in 96-97

11:17 ohpauleez: Scriptor: it's a reaction to the fact that some DOD and DOJ bids HAD to be in Java

11:17 jcromartie: Was the adoption to OOP really a reaction to FP? I don't think so.

11:17 "adoption of"

11:18 scriptor: not reaction to FP

11:18 mefisto`: I think the less prestigious schools just picked up java because the top schools started using it, but more because it was becoming the most popular enterprisey langauge

11:18 jcromartie: Nobody had heard of FP when they were picking up OOP in the industry…

11:18 scriptor: well, I was talking about adoption of java in school as a reaction to OOP and Java popularity rising

11:18 jcromartie: ah yeah

11:19 it reminds me of "if we evolved from monkeys, why are there still monkeys?"

11:19 scriptor: heh

11:20 borkdude: because they also evolved from monkeys we evolved from?

11:20 pipeline: afaik modern OOP came from an older OOP that was built around message passing

11:20 scriptor: we didn't evolve from monkeys ;)

11:20 acheng: the universe could have been created 2 seconds ago and we wouldn't know the difference :-P

11:21 borkdude: acheng most git repositories histories are fake too, just for messing up with people's understanding of it

11:21 acheng: adam and eve stood next to a tree... did it have rings? :-P

11:22 tbaldridge: acheng...that's actually close to the truth. See, the universe is immutable. So what we see as reality now is just a copy of the universe as it was a microsecond ago, with certain parts replaced. This sounds expensive, but the universe uses some interesting trie structures so it's all not that computationally expensive.

11:22 :-P

11:22 acheng: first saw message passing in lisp with sicp

11:23 TimMc: Nah, the universe is mutable. It has some nasty race conditions, too.

11:23 jcromartie: (inc tbaldridge)

11:23 lazybot: ⇒ 1

11:23 scriptor: tbaldridge: so you're saying that the day we verify string theory is the day FP becomes faster than C?

11:23 TimMc: There isn't even a universal clock, just local clocks that are always going out of sync.

11:24 acheng: if C code tends to be buggier, then FP is faster

11:24 borkdude: history is mutable, just study the history of writings about WW2 for example

11:25 jcromartie: I was just thinking last night: I think it's impossible to create a computer to simulate the universe in real time

11:25 i.e. all the particles

11:25 uvtc: TimMc, sounds like time in fast-moving threads runs slower relative to slow-moving threads. :)

11:25 jcromartie: and I don't mean that it's impossible today

11:25 I mean ever

11:25 mefisto`: jcromartie: only impossible if you care about it being accurate :D

11:25 borkdude: jcromartie you don't say?

11:25 scriptor: jcromartie: I think there's an smbc comic about that

11:26 jcromartie: you could simulate a smaller universe

11:26 acheng: there is a computer that does that. it's God's mind (allegedly)

11:26 borkdude: jcromartie it could ir the behavior of the universe is like a fractal, according to a repeating pattern, maybe

11:27 jcromartie: acheng: and I think some sophisticated theology could make a solid argument there

11:27 uvtc: acheng, Wait, are you thinking of the Milliard Gargantubrain at Maximegalon?

11:28 jcromartie: when you zoom in enough, things just start flitting in and out of existence, effectively "off limits" to conventional observation

11:28 anyway

11:28 acheng: it's how i think of free will and election :-P the author writes, the character chooses. i don't know Milliard.

11:28 jcromartie: I'd better be careful or I won't get anything done today

11:28 borkdude: http://en.wikipedia.org/wiki/G%C3%B6del's_ontological_proof

11:29 jcromartie: and of course, Gödel, Escher, Bach started all of this :)

11:30 fantastic book

11:30 borkdude: jcromartie I missed that part

11:30 jcromartie: good for Lispers too

11:31 I just mean it started me thinking about the nature of information and the universe

11:32 lynaghk`: Is there a core fn to check if something is between two other things? E.g., (between? 5 [2 9]) ;=> true

11:32 borkdude: how is the find-fn syntax in here again? ;)

11:32 lynaghk`: I can never remember the clojurebot syntax for looking up fns by arguments

11:32 borkdude: $find-fn

11:32 lynaghk`: yeah, right!

11:33 borkdude: $find-fn 5 [2 9] true

11:33 something like that?

11:33 lynaghk`: clojurebot: help

11:33 clojurebot: http://www.khanacademy.org/

11:33 borkdude: $findfn 5 [2 9] true

11:33 lazybot: [clojure.core/not= clojure.core/distinct?]

11:33 borkdude: hmm...

11:33 clgv: lynaghk`: how about ##(< 2 5 9) ;?

11:33 lynaghk`: $findfn [2 9] 5 true

11:33 lazybot: ⇒ true

11:33 [clojure.core/not= clojure.core/distinct?]

11:34 * uvtc loves how helpful clojurebot was there. :)

11:34 lynaghk`: clgv: yeah, I was thinking that. Just thought I'd check the enormity of clojure.core first =) thanks

11:34 borkdude: lynaghk` yes, the answer is not= :P

11:34 ,(doc <)

11:34 clojurebot: "([x] [x y] [x y & more]); Returns non-nil if nums are in monotonically increasing order, otherwise false."

11:34 clgv: lynaghk`: depending on your semantic you should maybe switch to <= ;)

11:35 borkdude: ah monotonically increasing, I didn't know that!

11:35 clgv: borkdude: pairwise could be useful as well ;)

11:35 borkdude: even about the most simple of things there's something new to learn every day

11:35 ,(doc pairwise)

11:35 clojurebot: Cool story bro.

11:36 S11001001: lancero: yes, all your promises will have values when you return from that

11:36 borkdude: clgv what's that

11:36 clgv: not a clojure function ;) nvm

11:36 scriptor: ,(-> 5 (< 2 9))

11:36 clojurebot: false

11:36 borkdude: Nice, Clojurebook 50% off today (ebook): http://shop.oreilly.com/category/deals/best-of-oreilly-dotd.do

11:37 scriptor: argh

11:37 (-> 2 (< 5 9) doesn't seem as clear

11:37 borkdude: ,(macroexpand '(-> 5 (< 2 9))

11:37 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

11:38 scriptor: borkdude: it makes it the 2nd argument

11:38 jcromartie: borkdude: is it worth getting that book? I feel like Clojure moves too fast

11:38 borkdude: scriptor anyway, it expands to (< 5 2 9)

11:38 scriptor: so it'd be (< 5 2 9)

11:38 zoldar: Is it possible and reasonable to use different url patterns based on server name in scope of a single django project?

11:38 borkdude: jcromartie yes, get it

11:39 jcromartie: if I buy the ebook do I get updates?

11:39 S11001001: ,(partition-all 2 1 [1,2,3,4,5]) ; clgv, pairwise

11:39 clojurebot: ((1 2) (2 3) (3 4) (4 5) (5))

11:39 borkdude: "Ebooks from oreilly.com are DRM-free. You get free lifetime access, multiple file formats, and free updates."

11:39 zoldar: oops

11:39 jcromartie: yeah

11:39 zoldar: sorry

11:39 S11001001: jcromartie: yes (generally for o'reilly), but not new editions

11:39 jcromartie: I just wonder if that encompasses editions

11:39 oh, OK right :)

11:39 still a good deal

11:40 foxdonut: never bought an ebook at more than 50% or 60% of the retail price

11:40 borkdude: jcromartie I like it, I have the paper version as well, but I read it from my screen most of the time anyway..

11:40 foxdonut: or more clearly, at least 40% off, most often 50%

11:40 uvtc: lynaghk, (defn between? [x a b] (and (< x b) (> x a)))

11:41 metellus: that gets messier if you also want it to work for (between? 5 [9 2])

11:41 TimMc: (< a x b)

11:42 uvtc: TimMc, ah, missed that. Thanks!

11:42 TimMc: The more interesting case is when you want a half-open range: (and (<= a x) (< x b))

11:42 borkdude: ,(apply (fn between? [x a b] (< a x b)) 5 [2 9])

11:42 clojurebot: true

11:43 borkdude: TimMc this begs for a macro...?

11:44 cemerick: borkdude: thanks for linking people up :-)

11:44 borkdude: cemerick what do you mean, linking up? ;)

11:44 scriptor: borkdude: why a macro?

11:44 lancero: S11001001: why? Using printouts I can see that the function starts blocking during the sixth element (waiting for the first element to be reliazed), then continues to deliver the rest of the elements and returns. The last 5 elements should still be sleeping when the function returns (I mean this is the behaviour that I'm trying to create).

11:44 cemerick: borkdude: RT'ing the oreilly link here

11:45 borkdude: cemerick sure!

11:45 TimMc: borkdude: A fn will do.

11:45 scriptor: right, a macro might introduce unneeded complexity

11:45 S11001001: lancero: you delivered 5 immediately, all at once, then slept long enough for them all to finish

11:46 borkdude: TimMc what if you have a half open range, like: [-2,2[, it would be nice if you could check for that with this short notation? well, maybe too complex to be worth it, I realize

11:46 TimMc: That wouldn't even read. :-/

11:47 borkdude: TimMc that is the mathematical notation I learned at high school

11:47 TimMc -2 is included, 2 is excluded

11:47 scriptor: it's invalid clojure, unfortunately

11:47 borkdude: scriptor TimMc I said "like", not "exactly this notation" :P

11:48 (is-in-range? x (range -2 2))

11:48 forget it :P

11:49 scriptor: could try (between? 2 [-2 2 _])

11:49 borkdude: a math dsl would be appropriate if you use it very much

11:49 for convenience

11:50 scriptor: and have it so that 3 arguments makes it exclusive for the max

11:50 TimMc: (map (partial inside? (range-co -2 2)) [-3 -2 1 2 3]) => [false true true false false]

11:50 co = closed, open

11:51 borkdude: TimMc the normal range is already closed, open, but it contains only integers

11:51 TimMc: You could have a whole lib for ranges: Membership, union, etc.

11:51 borkdude: TimMc yes, maybe it already exists in incanter or smth?

11:51 (never used incanter really)

11:52 scriptor: there's probably something like it in haskell

11:53 TimMc: borkdude: Oh, incanter is a good bet.

11:53 kremlon: wtf is clojure

11:53 borkdude: kremlon your next addiction

11:53 foxdonut: borkdude: :)

11:53 kremlon: hope so

11:53 bhenry: how can i make a &nbsp; in clojurescript without it being escaped and displayed in the browser?

11:53 foxdonut: next thing you know, you're reading a novel and you think "closure" has a spelling mistake.

11:53 TimMc: "I'm sorry, Bill, I just need clojure."

11:54 foxdonut: she said in response to "how about going out with me for a Java?"

11:54 jcromartie: loving the DRM-free ePub

11:55 TimMc: jcromartie: The only kind worth buying. :-)

11:55 jcromartie: kremlon: someone needs to make an introductory "WTFAQ"

11:55 foxdonut: lol

11:55 TimMc: jcromartie: Isn't clojure.org just that?

11:55 llasram: Well, any EPUB can become DRM-free with a little elbow grease...

11:55 borkdude: closure means 1) google closure, 2) a spelling mistake for clojure and 3) a function capturing its environment, in that order for me

11:55 kremlon: lol do u geise get that question alot

11:55 scriptor: is the oreilly clojure book easy to read on smaller kindle?

11:55 jcromartie: clojure.org is for people who can learn by reading man pages

11:55 TimMc: I'm pretty sure I'm not a geese.

11:55 foxdonut: jcromartie: that is just too funny. what the FAQ?!

11:56 jcromartie: scriptor: I shy away from tech books on Kindle… they never fit right, code looks awful, etc.

11:56 borkdude: jcromartie I tried clojurebook on kindle and it's doable

11:56 scriptor: jcromartie: yep, some books work alright though

11:56 as long as the code samples are short

11:56 borkdude: jcromartie but wth man, you always want a REPL close to your book for trying it out

11:56 TimMc: bhenry: Sounds like what you want is either non-HTML-encoded output or a NBSP character.

11:56 foxdonut: scriptor: I don't know about the kindle, but my sony reader uses epub, and epub is just html+css in a zip file, so I totally hack mine to use the fonts that I want :)

11:57 bhenry: TimMc: any way for me to put an empty html tag that won't lose its shape for being empty

11:57 scriptor: foxdonut: ah, neat, my biggest issue with tech books on an e-reader is that they're never wide enough

11:58 jcromartie: borkdude: yeah, but I like the iPad because I can at least pick it up and sit on the couch if I don't need a REPL

11:58 and touch controls for reading

11:58 I hate reading on a monitor

11:59 foxdonut: scriptor: sure. some tech books don't work well. it depends. novels are best on the e-reader. I still hack the fonts though :D

11:59 scriptor: foxdonut: hah, yep, novel's are so much easier to fit to the screen

12:00 I have 80 minutes of commute time, so I'm toying with the idea of using some of it for technical books

12:00 in addition to novels

12:00 borkdude: I like novels on the kindle, but also non-fiction non-tech books (lots of text, no code, big pictures)

12:01 clojure literature is better suited for small screens though, the code is usually more compact

12:01 scriptor: true

12:01 borkdude: why don't they make e-readers a bit bigger I wonder though

12:01 scriptor: don't they already do?

12:01 llasram: foxdonut: That's funny -- I do that too, re: ebook fonts. I have this pipeline using a custom-hacked version of Calibre from back when I used to contribute to it which basically auto-reformats most stuff I read

12:02 scriptor: kindle fire is an inch bigger, which isn't much I guess

12:02 borkdude: scriptor fire isn't e-ink

12:02 Wild_Cat: Kindle Fire is LCD though. It's meh.

12:02 scriptor: yea :/

12:02 DX is 9.7, but way too expensive

12:02 borkdude: scriptor there are some bigger models, but one company who made that is now bankrupt :(

12:03 Wild_Cat: for reading novels though, I'm totally in love with my Kindle Touch.

12:04 ...although I am sort of disappoint that the Kindle version of A Dance With Dragons doesn't come with a map of Westeros.

12:05 scriptor: is the resolution good enough to support a map like that?

12:06 Wild_Cat: scriptor: it's 600x800, landscape mode should do the trick.

12:06 zoldar: scriptor: I've got one DX under a thin cover of dust - sadly in current conditions I can't use it - do my reading mostly from phone with 4.2" inch screen - far from the eink comfort but must put up with that.

12:06 Wild_Cat: it's working okay for the map at the beginning of Greg Rucka's "Alpha" (which I'm currently reading), at the very least.

12:07 I mean, it's not ideal, but it's better than no map :p

12:12 zoldar: also, with DX it's beter to read with support for arms. It get's quite heavy on arms when holding it in air for example when lying on bed

12:12 *gets

12:14 borkdude: for novels I'm quite happy with my kindle touch, I get the impression that I read faster than on paper

12:14 because turning pages is effortless

12:15 this is off topic, but novel reading can sometimes be very important for programmers to keep sane ;-) @technomancy

12:15 technomancy: FSVO sane

12:18 I'm bummed they dropped the analog scroll wheel that's in the v1 kindle

12:18 that's one of my favourite parts of the design

12:24 borkdude: technomancy no need when touch screen right?

12:25 technomancy: borkdude: depends on the refresh rate. the scroll wheel has a realtime indicator that lets you make selections without being tied to the e-ink screen for input feedback

12:30 dnolen: EuroClojure core.logic video is out, http://twitter.com/euroclojure/status/220185504744878081

12:40 jcromartie: man, this guy… the last word is "As for lisp, I'm a mediocre programmer, so don't plan on using lisp.... :-/"

12:45 gfredericks: jcromartie: you're reading something?

12:45 jcromartie: no just a conversation with a recent hire

12:45 gfredericks: ah right

12:46 tbaldridge: I don't understand why someone wouldn't want to self improve, that seems so backwards.

12:47 technomancy: I find it kind of refreshing for someone to admit they're not so hot.

12:47 being OK with staying that way, not so much though.

12:47 gfredericks: "I'm a mediocre programmer, so I intend to stay mediocre"

12:48 ^ non-sequitur?

12:52 of course if it's just a job then it's hard to fault the person

12:52 as a person at least; maybe not as an employee

12:53 tbaldridge: eh...I disagree though. There's an apathy I've seen in the programming world. People accept that Java is all they'll ever be able to use, so the learn java, and just deal with the crap day in and day out.

12:54 gfredericks: but if they're not doing it for the love, what does it matter? as long as they're employed.

12:54 technomancy: yeah, but maybe his passion is to write a novel in the wee hours of the night and he writes java to pay the bills.

12:54 tbaldridge: So for instance, here at work, I complained that our serializer was slow. The response I got was "eh...it uses .NET's serializer, it works...if you think you can do better than MS, try...hahaha...."

12:55 gfredericks: as long as the industry is booming you can't expect everybody to be an idealist

12:55 tbaldridge: But for me, I couldn't take that, so I rewrote it using multimethods (ported to C#) and code generation, and the new serializer is about 20x faster and produces data 1/10th the size.

12:56 zoldar: tbaldridge: what was their reaction?

12:56 tbaldridge: We use it in production right now ;-)

12:57 S11001001: wait, tbaldridge, did someone suggest that doing better than ms would be difficult, in earnest?

12:57 foxdonut: llasram: that's very cool! (custom calibre to format your ebooks)

12:57 tbaldridge: oh yes, yes they did.

12:58 uvtc: tbaldridge, zoldar asks an interesting question though. "What was their reaction?" That is, at some places, you might get, "did you do this on company time? Were you asked to do this?" etc.

12:59 foxdonut: I'm interested in the reaction as well

12:59 uvtc: My point is, sometimes doing things one better isn't rewarded, and so that behaviour isn't selected for among sucessful employees...

12:59 zoldar: uvtc: that's what I wanted to ask, but due to my crap english I couldn't put it into words

13:00 tbaldridge: uvtc: well we ended up hitting a brick wall at one point. Loading data for a certain project was crashing .NET because the to serialize 20k records it was taking 700MB. So I developed in my spare time (on company time) and presented it as "look, now it doesn't crash, it's way faster, and we can actually send these datasets over the internet".

13:00 That's about all it took to convince them.

13:02 mabes: that is probably the key point.. if the company didn't need a faster serializer then they may have still used the slower MS one due to maintenance concerns

13:02 tbaldridge: But what irks me is that no one even thought enough about the process to say "hey...maybe XML serialization isn't best here". No it was "this framework has existed for 5+ years, let's just use that and slap a ORM on to it, and barf it all up on the UI, and YAY! we're done!"

13:02 uvtc: tbaldridge, Ah, so in this case it was indeed solving a concrete problem the team was facing.

13:02 tbaldridge: uvtc: exactly

13:03 zoldar: tbaldridge: maybe that's something for a success story blog post material ? :)

13:04 tbaldridge: perhaps

13:06 zoldar: especially that it leverages the not (yet) so common platform for clojure

13:06 tbaldridge: but back to the original topic, I have to wonder sometimes if we teach people to be too apathetic, Java/C# is so complex that people don't have time to do anything but read up no the latest features of IIS, EF, Spring, etc.

13:07 As I told a co-worker the other day: "I really don't care to know where IHttpHandler fits into the IIS stack vs IHttpModule..." When simplify the web server down to a few functions (like Ring does) suddenly we have more time to think about things that really matter.

13:08 At least that's my idea </rant>

13:09 Jayunit100: Wow this reduce word-count function is really slow : http://pastebin.com/raw.php?i=2X5UaTG3 … I'm not sure why though. any insights? Im using let with assoc to bind new words into a map and increment their count iteratively.

13:11 gfredericks: Jayunit100: why passing a single arg to assoc even do anything?

13:11 s/assoc/reduce/

13:11 ohpauleez: Jayunit100: You also can get rid of that let and just destructure

13:12 gfredericks: &(doc reduce)

13:12 lazybot: ⇒ "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as... https://www.refheap.com/paste/3429

13:12 Jayunit100: ah the reduce … yeah well it needs to sum

13:12 ohpauleez: they pre clause can use `string?`

13:12 gfredericks: there is no single-arg version of reduce

13:12 uvtc: Jayunit100, what is that hash-map doing there underneath `[str_in]`?

13:12 mhanson: ,(doc constantly)

13:12 clojurebot: "([x]); Returns a function that takes any number of arguments and returns x."

13:13 Jayunit100: the hash map is counting words

13:13 ohpauleez: uvtc: it's how you do constraints/contracts in Clojure

13:13 foxdonut: tbaldridge: what was the reaction from "haha you will never be able to do it" to "here, I did it" ?

13:13 Jayunit100: so, it assocs a new word to the hash map every time it sees one

13:13 uvtc: ohpauleez, Oh, don't know about those yet. Thanks. :)

13:13 Jayunit100: and (inc)s it the 2nd time, 3rd, etc....

13:14 so if input is "a b b" the output is {"a" 1,"b" 2"{

13:14 ohpauleez: Jayunit100: You can use group-by

13:14 gfredericks: or frequencies

13:14 ,(frequencies ["a" "b" "b"])

13:14 clojurebot: {"a" 1, "b" 2}

13:15 zoldar: ,(frequencies (map str (seq "a a b")))

13:15 clojurebot: {"a" 2, " " 2, "b" 1}

13:15 Jayunit100: UHOH ! :)

13:16 well… i wrote the code for pedagogical purposes so I'm still curious about why it is slow.

13:16 but thanks everybody for your help. Im wondering -- is there anything truly unidiomatic in the function that i pasted ?

13:17 ohpauleez: Jayunit100: Turn the let to destructuring

13:17 The pre should use string?

13:17 dnolen: Jayunit100: "slow" for what size input and compared to what?

13:17 ohpauleez: but no, using reduce to build up collections is standard

13:18 tbaldridge: foxdonut: the reaction was "heh...good job". I don't think it really sunk in that we had something really usable until the framework we use (CSLA.NET) decided to accept my patch (or the ideas behind it) and use them by default in the framework.

13:18 Jayunit100: it must be the let, that is taking a while.

13:18 so how does reduce optimize creating a new map over and over agin ?

13:18 (i.e. how does reduce optimize assoc)?

13:18 pbostrom: Jayunit100: there is also reduce-kv

13:18 dnolen: Jayunit100: it doesn't optimize assoc

13:19 Jayunit100: Is it a "bad" idea to do an assoc in a reduce where we expect a large number of elements in the [ ] ?

13:19 dnolen: Jayunit100: no

13:19 uvtc: pbostrom, reduce-kv?

13:20 pbostrom: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reduce-kv

13:20 uvtc: pbostrom, Oh, whoops. Didn't see it on clojuredocs, but it's here in my repl.

13:20 pbostrom, thanks.

13:21 pbostrom: I believe that might provide some optimization, but I'm just guessing

13:22 foxdonut: tbaldridge: wow..well done!

13:23 Jayunit100: how does assoc implement performance under heavy insert load given the immutability constraints of clj ?

13:24 S11001001: Jayunit100: structure sharing

13:24 gfredericks: Jayunit100: I think you use transients if you can't bear the immutability overhead

13:24 Jayunit100: ah ok

13:24 jweiss: any slimv users know if you can do the equivalent of kill-sexp?

13:26 dnolen: Jayunit100: without explaining what kind of performance you're looking for, or without any extra information about how you are running your environment (JVM server setting etc). it's really hard to say anything meaningful in response.

13:26 Jayunit100: are you expect it to be 2X faster? 4X faster? 10X faster?

13:26 uvtc: Jayunit100, re. your word-enrichment func; personally, I usually like using the fn form instead of the function literal #() --- so that you can give your parameters descriptive names.

13:28 nDuff: Jayunit100: ...in a lot of cases, the immutable types are fast enough -- they *don't* involve full copies.

13:30 scriptor: does it still use copy-on-write for small numbers of assoc?

13:30 dnolen: scriptor: yes

13:40 tbaldridge: cemerick: ping

13:41 lynaghk: dnolen: re: TODO, thanks. Any suggestions for cleanup before I submit it to the wider JS world?

13:42 dnolen: lynaghk: hmm not really, though I expect it to be thoroughly misunderstood

13:42 lynaghk: dnolen: heh. I'm still trying to train myself out of the OO/MVC mindset a lot of the time.

13:43 "This is simple. Too simple. I must be doing something terribly wrong."

13:43 brainproxy: lynaghk: what are you about to unleash on the world?

13:43 dnolen: lynaghk: it could get a lot simpler ...

13:43 lynaghk: I'm realizing that JS MVCs are just queries+databinding, not much else.

13:44 scriptor: a lot of people won't be used to cljs's mutability primitives, so you'll see complaints about that

13:44 dnolen: lynaghk: I'm looking forward to to getting the DB functionality of core.logic working under CLJS - then you can run arbitrary queries over indexed data.

13:44 lynaghk: instead of this linear filtering crap

13:44 lynaghk: dnolen: yeah, I'd be all about that.

13:45 brainproxy: Todo app written in cljs using C2's new databinding stuff: https://github.com/lynaghk/c2-demos/tree/master/todoMVC

13:46 dnolen: lynaghk: also thinking it would be cool to support using raw JSON as the data source instead of converting into CLJ data structures.

13:46 lynaghk: dnolen: You can get core.logic to work directly against an array of js objects?

13:46 brainproxy: lynaghk: sweet!

13:47 dnolen: lynaghk: core.logic can unify anything so I don't see why not.

13:47 scriptor: what does bind! do?

13:47 brainproxy: i know i've asked this before, but I want to get into the core.logic stuff, but I feel a bit lost; recommendations for getting up to speed when armed w/ general knowledge of clojure but no logic prog experience

13:47 ?

13:48 lynaghk: dnolen: I think that would be pretty powerful. I'm not sure how well that would work for doing actual data manipulation in CLJS though---i.e., if you want to change the underlying data. You'd need to drop to aset, no?

13:48 dnolen: brainproxy: it's an up hill battle - and then it seems so simple ...

13:48 brainproxy: it's worth investing in a good Prolog book + The Reasoned Schemer

13:48 brainproxy: meaning links to books, ebooks, tutorials that help one to dive in, but don't require a B.A. in math

13:49 lynaghk: scriptor: there's a bit of explaination in the release announcement: https://groups.google.com/forum/?fromgroups#!topic/clojure/KCe96DbMD6k

13:49 brainproxy: dnolen: i tried looking at the minkanren dissertation, but the learning curve seemed n^n

13:49 scriptor: lynaghk: ah, nice, was just about to suggest something like that announcement

13:49 TimMc: brainproxy: Fast, then?

13:49 :-)

13:50 Jayunit100: dnolen: good point. well…. this whole thing came from an experiment - i wanted to see if (reduce) with (assoc) would indeed be "fast".. by fast, i mean that its O(n) time would be steady as the # of words increased. Indeed, it did. I just was having some fears that it wasn't "fast enough". But now, after benchmarking it against standard java/maps and another clojure impl, I'm pretty happy :)

13:50 dnolen: brainproxy: yeah, requires a couple of reads. The Reasoned Schemer + Prolog book. Then some head-scratching, then try dissertation again :) and only chapter 3.

13:50 Jayunit100: well there you go :)

13:50 scriptor: lynaghk: before releasing it to the js world, just make sure to explain some of the more clojure-y bits, mutability, dereferencing, destructuring, and the templating

13:51 brainproxy: dnolen: recommendation for prolog books?

13:51 free, paid, out of print, whatever

13:51 lynaghk: scriptor: I've been meaning to just ping the TodoMVC guys and see what they think about including such a black sheep.

13:51 Jayunit100: dnolen: . thanks for your help. I believe you were the one that said "tools don't mean s**t without a good community"… and the clj community is always there for me in times of despair :)

13:51 lynaghk: scriptor: but yeah, I've been thinking about this kind of stuff for a bit. I'm giving a talk at OSCON in two weeks about this compared to MVC, so I'll probably record a screencast and get everything written down.

13:52 dnolen: brainproxy: Bratko Prolog book (new edition!) or Sterling Shapiro Prolog

13:52 scriptor: lynaghk: one other recommendation is that I'd make another very simple js app and see how much code you can share between the two

13:53 lynaghk: but I remember you mentioning that it gets rough when you factor in edge cases, still, one major complaint will be what it offers over plain js :)

13:53 lynaghk: scriptor: Not sure what you mean / what that would show. Whenever something seems useful to share between apps, I put it in a library.

13:55 dnolen: lynaghk: I think it could work fine with most JS MVC workloads, I think the whole datomic DB as value thing could work well and be efficient for many use cases.

13:55 lynaghk: dnolen: think you could find some time to write the TodoMVC data fns in core.logic?

13:55 dnolen: lynaghk: most JS MVCs require cloning anyhow ... so it possible we could do better ...

13:56 pbostrom: are there any plans to add (:require ... :refer ...) to cljs?

13:56 dnolen: lynaghk: yes, gotta wrap up this other core.logic stuff first ... but beefing up CLJS core.logic is on the list

13:56 pbostrom: it's already there.

13:57 pbostrom: well in master, perhaps not in a release

13:57 lynaghk: dnolen: cool. I worked through the reasoned schemer but the most advanced example was building some bit-manipulation adding circuits, and I didn't have the energy to try and work from that to something closer to my day-to-day domain.

13:57 pbostrom: ah, ok, thanks, I guess it hasn't made it through to cljsbuild (still a little unsure of the relation between versions of those 2)

14:00 scriptor: lynaghk: well, let's start with this, how *is* it better than plain (non-mvc) js?

14:00 besides that it's in clojure :)

14:03 dnolen: scriptor: people use JS MVCs for a reason - it does control complexity in larger JS apps.

14:04 scriptor: dnolen: right, so how does using cljs also control complexity?

14:04 dnolen: scriptor: having done both - IMO, yes.

14:05 scriptor: how, exactly? The mutability primitives?

14:06 dnolen: scriptor: simpler notions of truth, sensible extensibility, namespaces, no aliasing, no pervasive mutability, useful sugar, recursive definitions, etc

14:07 brainproxy: anyone got an example of a cljs project using domina which makes heavy usage of XHR

14:09 lynaghk: scriptor: the biggest part for me is moving away from thinking of the DOM as some mutable thing that you want to hit with stuff (addClass, appendChild, ...) and starting to think of it as a plain data structure (e.g., Hiccup vectors). Write functions to transform your domain data to "view data", and then let the library handle updating the DOM for you.

14:10 scriptor: ah, so representing the DOM in the same data structures that the language uses, that's pretty big

14:10 clojurebot: make a note of http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php it is yet another article about picking c or c++ for performance being naive

14:10 dnolen: scriptor: oh, unified iteration for all types, and protocols prevent API proliferation / incompatibility also big.

14:10 lynaghk: scriptor: yeah, because you can use your actual programming language in that case. Not some janky franken-handlebar-js-html crap.

14:10 scriptor: hehe

14:11 lynaghk: scriptor: I wrote Singult to be usable from plain JS, and I'm interested to see if anyone actually tries using it out from there since that idea---treating your view as just another data structure---isn't Clojure-specific.

14:11 Though, like dnolen says, there's also a ton of great shit in Clojure =)

14:11 scriptor: wait, singult can be used from native js?

14:12 holy shit, that's pretty awesome

14:13 lynaghk: scriptor: yeah, JavaScript has Arrays and Objects, so you can play the Hiccup game there too.

14:13 You just need a hell of a lot more commas =P

14:13 goodiebo_: how do you write (append) to a file in clojure?

14:13 borkdude: goodiebo_ http://stackoverflow.com/questions/7756909/in-clojure-1-3-how-to-read-and-write-a-file/7757674#7757674

14:14 goodiebo_: ha geez, thanks!

14:17 scriptor: lynaghk: bind! seems to solve the problem of binding data to view data structures really well

14:18 lynaghk: scriptor: checkout the source. it's just using computed-observables (from the Reflex library) and merge (from Singult).

14:18 scriptor: so, when you release this more widely, I'd definitely stress that clojure's forcing you to constrain mutability to only what you must mutate means that you can easily listen for changes

14:19 lynaghk: computed-observables are pretty simple, and handy for data stuff too.

14:20 scriptor: I think knockoutjs is the only other tool that does a similar thing in js

14:21 ohpauleez: Scriptor: As a corollary, a lot of my CLJS apps deal with stream data and a specific process

14:21 so something like enfocus works great for me

14:22 where I want to take one piece of a the DOM (like a container) and represent all of my search results in there

14:22 where my search results from from a JSONP request to a different server

14:22 scriptor: got it

14:23 dnolen: scriptor: I refuse to use anything with the word Model in it anymore when it comes to JS.

14:23 scriptor: dnolen: agreed :)

14:23 ohpauleez: but it requires me to wire up my apps differently, so I use a lot of pubsub stuff

14:24 scriptor: I sent out a long email to the dev list this morning that basically amounted to "hashmaps are better than models"

14:24 lynaghk: scriptor: yeah, knockout is where I took the computed-observable idea from. The implementation too---they did a great job of design documentation.

14:24 ohpauleez: the misunderstanding of (or perhaps overuse of) "model" and MVC is laughable

14:25 and a little annoying

14:26 so I'm with you guys

14:44 mhanson: Anyone else see that ebook Clojure Programming is half-off today?

14:47 borkdude: mhanson it has been noted, but can not be overemphasized

14:47 mhanson: Hah. Excellent.

14:48 tbaldridge: mhanson: is that through O'Reily?

14:49 mhanson: tbaldridge: Yep.

14:49 tbaldridge: hrm, I'm not seeing the 50% off part...

14:49 mhanson: I believe the discount code is "deal".

14:50 If you go to the shop front page, it's under the daily deals section.

14:50 tbaldridge: ah yeah, discount code

14:50 mhanson: But yes, on the actual book page that is not reflected.

14:51 tbaldridge: cool, thanks, I think I'll pick it up

14:52 ptambala: hi

14:52 are you talking about Clojure Programming or Programming Clojure?

14:52 foxdonut: the former

14:52 ptambala: ok, I'm currently reading Clojure Programming.

14:53 foxdonut: the latter has a 2nd edition out, btw.

14:53 ptambala: yep, I saw this

14:53 but I don't like the swan on the cover, so I'm not really tempted to buy it :)

14:54 borkdude: =)

14:54 johndeo: I'm reading it now. It is good.

14:54 borkdude: I don't like the clojure logo, so I will stop using clojure

14:55 ptambala: ok

14:55 I was thinking about buying a 2nd book, and I was thinking about Joy of Clojure, dunno

14:55 borkdude: ptambala http://stackoverflow.com/questions/2578837/comparing-clojure-books

14:55 ptambala: so many choices...

14:55 oh thx

14:57 foxdonut: ptambala: JoC probably has the least overlap with CP

14:58 johndeo: Datomic looks super cool, but I'm hesitant about a cloud-only proprietary app for the DB. Should I be? Does someone have a perspective on this?

14:58 technomancy: johndeo: seems reasonable to have hesitations about that

15:00 ptambala: foxdoughnut: after reading the description JoC seems to be the right book indeed. thanks.

15:01 borkdude: ptambala can't go wrong with that one

15:04 devn: johndeo: free for open source FWIW

15:06 TimMc: *gratis

15:16 nDuff: devn: ...bah; "free-of-cost for open source" ~= useless

15:16 almost all the OSS work I do is backing commercial projects, and selling them on a for-pay database backend, however much better it may be, when there are more battle-tested Free ones available is basically impossible.

15:16 dustingetz: whats the easiest way to make async http requests in clojure

15:17 jsabeaudry: dustingetz, jayq

15:17 dustingetz: even from the server? not in browser e.g. not using cljs

15:18 jbarrios: I am hiring for backend engineering positions, if anyone's looking. We are starting to introduce Clojure into the mix.

15:18 dustingetz: link to jobs page?

15:18 jbarrios: digging it up now.

15:19 jcromartie: dustingetz: clojure-http-client

15:19 vojd: is there any clojure service out there i can point to, stating "THIS is a full fledged clojure app"

15:19 jcromartie: er never mind

15:19 technomancy: no don't use clojure-http-client

15:19 jcromartie: how about https://github.com/neotyk/http.async.client

15:20 sorry :)

15:20 vojd: for those colleagues and friends saying "but meh, clojure is just a research language right?"

15:20 dustingetz: http.async.client

15:20 technomancy: vojd: clojars

15:20 clojurebot: success stories?

15:20 clojurebot: clojure success stories is http://dev.clojure.org/display/community/Clojure+Success+Stories

15:20 technomancy: ^ if it doesn't need to be OSS

15:20 vojd: super :D thanks

15:20 dustingetz: final question, for mocking async queries, i basically want `(defn sleep-async [ms callback] …)`

15:20 jbarrios: dustingetz: here's one: https://sjobs.brassring.com/1033/ASP/TG/cim_jobdetail.asp?partnerid=25348&siteid=5039&jobid=42321

15:21 dustingetz: not exactly sure how to go about implementing that without having my own while loop

15:21 i want the OS to do the polling/eventing/reactor/whatever for me

15:21 jcromartie: dustingetz: you can use Thread/sleep

15:21 dustingetz: asynchronously?

15:21 jcromartie: put it in another thread :)

15:22 dustingetz: it gets really really complicated, i want the callback to happen in my main thread

15:22 im exploring continuations

15:22 jcromartie: I don't think it needs to be that complicated

15:22 jbarrios: how about a future?

15:22 dustingetz: futures imply threads

15:22 jcromartie: and futures block while they wait

15:23 but it shouldn't be that hard to dispatch something on the main thread, right?

15:23 hm, yeah you'd need something like a run loop

15:23 dustingetz: i guess i can have a reactor loop on my main thread polling some cross-thread queue

15:23 but this isn't how things look in real life

15:23 jcromartie: no

15:24 scriptor: with clojurescript, are error line numbers mapped back to the original cljs yet?

15:24 jcromartie: you can use exceptions

15:24 :)

15:24 scriptor: but in the case of syntax errors and such?

15:25 jcromartie: dustingetz: this is your ticket http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html

15:26 dnolen: scriptor: nope, help welcome

15:26 scriptor: dnolen: where would I start?

15:27 dnolen: scriptor: read up on SourceMap v3, once you understand the format it's pretty clear what needs to be done.

15:27 scriptor: VLQ64 encode/decode already in a branch, so that part is done

15:28 scriptor: but we need to write the code that can actually decipher a source map as well as generate one.

15:29 scriptor: where is the sourcemap project located? This/ http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

15:29 jcromartie: I love it when someone gets mad at me for not telling them something that I googled

15:30 dnolen: scriptor: that's the goto high level explanation, also links to the Google doc describing it.

15:31 scriptor: another good reference is Mozilla's JS implementation, which also linked to.

15:32 jcromartie: hm, how the heck would I access this interface from Clojure http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html

15:33 ah

15:33 http://blog.jayfields.com/2011/01/clojure-using-java-inner-classes.html

15:33 amalloy: dnolen: i noticed that != doesn't seem to have the same "descend into lists" behavior that == does: https://gist.github.com/3042234 - is there a reason this isn't possible, or is otherwise a bad idea? (i think i'm still using != too much, but i was surprised this doesn't do what i expected)

15:35 dnolen: amalloy: what is suprising you there?

15:36 amalloy: dnolen: i thought that x would fail to unify with [1 d], because c is 1 and i said x is not [c d]

15:37 if i'd said (== x [c d]), then a and b would be in lockstep with c and b, respectively; but using != they seem to be entirely unconnected

15:37 dnolen: amalloy: ?

15:38 amalloy: dnolen: i'll rephrase: i expected (!= x [1 d]) to mean: "x is not a two-element list whose first element is 1"

15:38 dnolen: amalloy: you say that (== x [a b]), then you unify a & c with 1, so (== x [1 b]), (!= x [1 d]) doesn't say anything - b has no value, nor d.

15:38 amalloy: yeah that's not how disequality works.

15:39 amalloy: right. i've figured that much out, i was wondering why

15:39 dnolen: amalloy: != just means two terms should never unify, that's it. nothing more.

15:40 amalloy: if you want your behavior you have to use firsto + !=

15:40 amalloy: *nod*

15:40 okay, thanks. i'll come back to this when i understand more about the mechanics of unification

15:40 (or not, since most of the time when i use != it's a mistake)

15:41 dnolen: amalloy: != is very useful - it's kind of a limited form of negation.

15:41 amalloy: it really helps with conde where you want the clauses to be non-overlapping w/o resorting to cut (conda/u)

15:42 otherwise all clauses get tried - which may not be what you want.

15:43 amalloy: yeah. actually, do you have a moment to look at http://stackoverflow.com/questions/11256242/solving-dinesmans-multiple-dwelling-example-using-clojures-core-logic-core-mat/11280559#11280559 ? my first implementation used conda and != in not-adjacento, and then i realized that was causing problems so i went back to conde and ==

15:44 specifically (not-adjacento x y l) is supposed to say "x and y are not next to each other in the list l", but i couldn't get that to work in a purely relational way, so i backed off to "x and y are both in l, separated by a gap of at least one"

15:49 dnolen: amalloy: looking

15:56 ipostelnik: what's the difference between (next) and (rest)?

15:56 gfredericks: expressing negatives is pretty hard :(

15:56 amalloy: &((juxt rest next) [1])

15:56 lazybot: ⇒ [() nil]

15:58 gfredericks: amalloy: x and y are from a finite domain?

15:59 maybe I should read the SO thing first

15:59 amalloy: gfredericks: in not-adjacento? in my first draft they were and it didn't really work; i think the current version works for any x, y, l

16:01 gfredericks: this is assuming x and y occur exactly once?

16:01 man I like the vector syntax there; I've never seen that done

16:02 amalloy: currently (not-adjacento 1 2 [1 1 2]) succeeds, because the first 1 is not adjacent to the 2

16:02 gfredericks: what vector syntax?

16:02 uvtc: ipostelnik, for one thing, compare the output of `(next [1])` and `(rest [1])`.

16:02 gfredericks: all my code is a pile of parens

16:02 (conde [(...) (...)]) instead of (conde ((...) (...)))

16:02 amalloy: i didn't even know parens were an option

16:03 gfredericks: and vice versa

16:04 ignacio: is anyone deloying a ring app as a WAR file?

16:04 gfredericks: I've done that before I think

16:04 but not currently

16:04 ignacio: I just have a question about resources in the file

16:04 gfredericks: yes?

16:04 clojurebot: yes is is

16:05 TimMc: clojurebot: forget yes |is| is

16:05 clojurebot: I forgot that yes is is

16:05 ignacio: i'm looking to preproces some of the files in resources :)

16:05 i'm looking to preproces some of the files in resources

16:05 gfredericks: clojurebot: yes |isn't| is

16:05 clojurebot: Roger.

16:05 TimMc: What have you done?!

16:05 gfredericks: ignacio: at build-time?

16:05 ignacio: and am going to copy the code out of ring.util.response/resource-response

16:05 Raynes: TimMc: It just occurred to me that I'm an idiot.

16:05 ignacio: actually, it can be at deploy time

16:05 either.

16:05 but not at request time

16:06 gfredericks: ignacio: so a leiningen hook would be appropriate?

16:06 ignacio: (where i have a "servlet context" or some such)

16:06 Raynes: TimMc: You want to 'safe-require' a file. You can't do that with 'require'. You want to load the file yourself, pumping the code through a sandbox, right?

16:06 gfredericks: clojurebot: yes?

16:06 clojurebot: yes isn't is

16:06 Raynes: TimMc: You'll have to write your own thingy for that. Sorry for being so dense.

16:06 amalloy: clojurebot: forget everything, man. it's all too difficult

16:06 clojurebot: RickInGA: of course :-) *everything* is in Clojure

16:06 ignacio: well,

16:06 fenton1: technomancy: Phil, what was the darker color theme you use for emacs again?

16:07 ignacio: @gfredericks: well, a leiningen hook wouldn't be totally appropriate, because i need access to the file contents when serving a response

16:07 TimMc: Raynes: I just want to load an entire namespace that someone hands me (as file, inputstream DB field, etc) and then safely call fns that are in that ns.

16:07 gfredericks: ignacio: pre-processed or post-processed?

16:07 ignacio: (eg: imagine that i want to minify JS and then include it directly in the body of hte returned html)

16:07 Raynes: TimMc: Right, but you can't safely call a fn loaded with require unless you know it is safe.

16:07 gfredericks: ignacio: I'm not sure why hooks aren't appropriate; in the hook, muck with your resources directory until you have it like you like it

16:08 Raynes: TimMc: You have to look at the defns first before you load them and not even let them load of they aren't safe.

16:08 amalloy: fenton1: i use tty-dark, if you want high-contrast really-dark

16:08 Raynes: clojail can't look inside of functions.

16:08 ignacio: gfredericks: then read the file using servlet-context?

16:08 would that be the preferred way?

16:08 fenton1: amalloy: thx, i'll try that....

16:08 gfredericks: ignacio: I dunno, however you read resources

16:08 TimMc: Raynes: My outer code isn't going to try to use an actual :require block or anything, I'm speaking in analogy.

16:08 gfredericks: ignacio: your app shouldn't have to care if the file was there before deploy-time or not

16:09 technomancy: fenton1: I use monokai and zenburn

16:09 ignacio: right, that's what i'm looking for: it seems that ring.util.response/resource-response will do exactly what i want, but i just want to verify that there's no security issue there

16:09 TimMc: Raynes: 1) Someone submits a .clj file 2) I load it into a sandbox (which might reject it), 3) I call a fn in that sandbox and get the results back.

16:10 Raynes: TimMc: Cool. That will work fine for you.

16:10 TimMc: sweet

16:10 Raynes: TimMc: If you write a safe-require function, send me a pull request and I'll put in clojail.

16:10 foxdonut: technomancy: is it molokai or is there a different one called monokai?

16:11 fenton1: technomancy: thank you!!!

16:11 foxdonut: its monokai

16:11 technomancy: foxdonut: it's this one: http://marmalade-repo.org/packages/monokai-theme

16:11 TimMc: Raynes: Could I keep the sandboxed ns around and periodically make timeout-limited calls into it?

16:12 Raynes: TimMc: Not sure I understand the question.

16:12 foxdonut: technomancy, fenton1: got it. sorry about the confusion. I didn't realize you were talking emacs. molokai is monokai port to vim :)

16:13 fenton1: foxdonut: ah ok.

16:13 foxdonut: fenton1: definitely one of my faves.

16:14 TimMc: Raynes: The .clj file (containing one namespace, as usual) represents a user-submitted bot that will compete against others. I'd like to load it up and then call it repeatedly over time with a game-state object so that it can make moves.

16:15 Raynes: TimMc: What if two people use the same namespace?

16:15 TimMc: ...and I want a timeout on each of those calls. I'll have to set up my own timeouts for those calls, yes?

16:15 nicholasf: hi, I'm working through some clojure basics (with SICPs and 'Clojure Programming'). I have my lein repl open and am trying to define an anonymous function and pass it a number: https://gist.github.com/ada8e7fb1454afa8ee53

16:15 shouldnt this work?

16:15 amalloy: &((fn [x] (+ 10 x)) 8)

16:15 lazybot: ⇒ 18

16:15 Raynes: TimMc: The sandbox will timeout for you.

16:16 But still, I'd be worried about namespaces.

16:16 nicholasf: amalloy: ok thanks

16:16 TimMc: Oh, hmmm.

16:16 amalloy: nicholasf: sure should work in the repl, yes

16:16 the & is just asking the bot to eval it for us, not part of clojure syntax

16:16 nicholasf: ok it's not working in my repl, so that must be what's wrong here

16:16 uvtc: nicholasf, Are you using Leiningen to create a project and start a repl in it?

16:16 nicholasf: yeh, it's definitely my lein repl

16:17 fenton1: foxdonut: yeah, i liked it...phil's got good taste ;)

16:17 nicholasf: amalloy uvtc I just tested it in my clj repl (homebrew repl project) and it worked

16:17 so I was assuming that 'lein repl' worked anywhere I typed it, like a regular repl

16:17 amalloy: nicholasf: i wonder if you've accidentally redefined the 'fn macro

16:17 since i can't think of any other way you'd get this behavior

16:17 TimMc: def fn

16:17 nicholasf: amalloy: I think Ive just gone to any directory and used lein repl, and it hasnt found important class files in the background

16:17 TimMc: That might do it.

16:18 nicholasf: k cheers guys

16:18 amalloy: nicholasf: i don't think so. you'd get failures long before this, if something this fundamental were broken

16:18 uvtc: nicholasf, right. You need to run it from your top-level project dir.

16:18 TimMc: lein repl will work anywhere, it just might give you a random version of clojure.

16:18 amalloy: are you guys all crazy? lein repl works anywhere

16:18 foxdonut: fenton1: no doubt he does. there is also Tomorrow that you might find nice.

16:18 nicholasf: amalloy: I think lein even requires clojure for you, so if I'm opening lein in a dir without clojure, it wont be able to evaluate basic stuff

16:19 amalloy: nicholasf: humor me: if you just type (without quotes) "fn" into the broken-looking repl, what do you get?

16:19 uvtc: amalloy, Whoops. I suppose so. I didn't know you could just run `lein repl` in any old directory.

16:19 TimMc: nicholasf: Run lein repl anywhere and execute this: *clojure-version*

16:19 nicholasf: amalloy: https://gist.github.com/4616b766bb428a4d4d0b

16:20 amalloy: but i bet in that repl your ((fn [x] (+ x 10)) 8) construct works

16:20 nicholasf: user=> *clojure-version*

16:20 {:major 1, :minor 2, :incremental 1, :qualifier ""}

16:20 fenton1: foxdonut: I'm on the road and having trouble loading the color theme, what is it again I need to throw into my .emacs?

16:20 nicholasf: it only works if Im doing it in a lein project directory (that I've run deps in)

16:22 uvtc: nicholasf, which version of lein are you using? Run: `lein version`

16:22 nicholasf: Leiningen 1.7.1 on Java 1.7.0_05 Java HotSpot(TM) 64-Bit Server VM

16:22 foxdonut: fenton1: sorry friend, I don't know :( I use vim

16:23 raek: nicholasf: is that paste *exactly* what you typed?

16:24 nicholasf: raek: yeh

16:24 foxdonut: fenton1: source is here if it helps: https://github.com/chriskempson/tomorrow-theme

16:24 fenton1: foxdonut: ok, i'll keep looking...I look into tomorrow after i get *any* theme working!

16:25 Raynes: What theme?

16:25 raek: nicholasf: and if you try running `lein repl` outside a project (which is supposed to work), does the problem still occur?

16:25 Raynes: tomorrow?

16:25 If you're using Emacs 24, just put the latest tomorrow themes somewhere and then (add-to-list 'custom-theme-load-path "/path/to/dir/with/themes") and then (load-theme 'that-theme t). For tomorrow, it'd be (load-theme 'tomorrow-night) or whatever tomorrow varient you want.

16:25 fenton1: ^

16:25 nicholasf: raek: that is what I'm doing in the gist. If I run lein repl in a lein project, fn won't have that problem

16:26 raek: yeh, I think I picked up using 'lein repl' from something written in Clojure Programming (OReilly)

16:26 raek: nicholasf: and that happens every time?

16:26 nicholasf: but it's obviously stopped working how people think it should

16:26 raek: each time so far, yes :)

16:27 foxdonut: we need an abbrev. for Clojure Programming (O'Reilly)

16:27 uvtc: foxdonut : CP ?

16:27 TimMc: nicholasf: At times like this I tend to blow away ~/.m2/repository

16:27 raek: yes, lein repl outsude a project is one of the most common ways to start a "just clojure" repl

16:27 TimMc: foxdonut: CPOR?

16:27 nicholasf: TimMc: hrm ok

16:28 fenton1: Raynes: thx i'll try that.

16:28 TimMc: Maybe you have a corrupted Clojure 1.2.1 binary.

16:28 nicholasf: like I said, all of these tools are new to me, but this felt wrong

16:28 uvtc: nicholasf, I go a step further than TimMc ; `rm -fr ~/.lein` `rm -fr ~/.m2` `rm ~/bin/lein`, then download the latest lein and start over. :)

16:28 nicholasf: hang on, let me try using lein repl on my mac air (currently on another machine)

16:28 foxdonut: uvtc, TimMc: I was thinking one of those, yeah.. alongside JoC, CiA, PC

16:28 nicholasf: ok, Ive installed lein on two machines in the last week

16:29 they are both behaving the same way

16:29 raek: this is very, very odd

16:29 TimMc: nicholasf: Is your gist a *precise* copy of your REPL, or did you retype anything?

16:30 foxdonut: JoC, CiA, PCAP, PCPP, CPOR

16:30 nicholasf: TimMc: it's a precise copy

16:30 raek: nicholasf: is there something else that doesn't work, for instance let expressions?

16:30 nicholasf: ive programmed a bunch of other languages, I know about the importance of sharing info

16:30 raek: I guess let would be broken too, if fn is

16:30 TimMc: nicholasf: How about arithmetic expressions like (+ 2 3)?

16:31 nicholasf: https://gist.github.com/357cf99cdc5982fc0015 TimMc and raek

16:31 TimMc: nicholasf: 'let and 'do are no surprise

16:31 Try (let [x 5] (+ x 4)) and (do 1 2 3)

16:32 nicholasf: https://gist.github.com/75eee8531281f8b84700 they work

16:33 altho that confuses me a little

16:33 cos if let works I would have assumed fn would too

16:33 TimMc: The compiler may handle them at different levels.

16:34 nicholasf: yeh ok, I guess special forms arent all equal

16:36 raek: this is very odd. I can't reproduce that with my lein 1.7.1 / clojure 1.2.1 repl

16:36 ppppaul: anyone here using clojurscript and couchapps?

16:36 nicholasf: raek: you're cding into a dir that doesnt have a lein project, right?

16:37 raek: nicholasf: yes

16:37 nicholasf: what does `sha1sum ~/.m2/repository/org/clojure/clojure/1.2.1/clojure-1.2.1.jar` return on your computer?

16:37 nicholasf: raek: that is strange

16:37 raek: we should be using the same clojure jar

16:37 * nicholasf installing sha1sum

16:38 nicholasf: that's not available via brew

16:38 * nicholasf looks at the jar size

16:38 nicholasf: andromeda:~ nicholas$ ls -ltrh ~/.m2/repository/org/clojure/clojure/1.2.1/clojure-1.2.1.jar

16:38 -rw-r--r-- 1 nicholas staff 3.1M 28 Jun 10:34 /Users/nicholas/.m2/repository/org/clojure/clojure/1.2.1/clojure-1.2.1.jar

16:39 but I'm using clojure-1.3.0 in my lein projects

16:39 raek: nicholasf: try replacing "sha1sum" with "openssl sha1"

16:39 nicholasf: (that's the jar it pulls down)

16:39 ok

16:40 raek: I get be088d20c078ce48d42afba05984f1ef7c02142b here

16:40 nicholasf: SHA1(/Users/nicholas/.m2/repository/org/clojure/clojure/1.2.1/clojure-1.2.1.jar)= be088d20c078ce48d42afba05984f1ef7c02142b

16:40 TimMc: nicholasf: When not run from a project, lein uses its own Clojure dependency for the REPL environment. In this case, 1.2.1.

16:40 nicholasf: TimMc: ok thanks

16:41 raek: nicholasf: and the same thing happens if you write a similar expression, like ((fn [y] (+ y 5)) 3) ?

16:41 brainproxy: anyone using visionmedia's superagent lib in conjunction w/ their cljs projects?

16:44 nicholasf: raek: https://gist.github.com/7f52d9573761da1e9e0e

16:44 that's interesting

16:44 raek: now that's expeced behavior

16:44 I wonder why it doesn't like your xs... :)

16:45 nicholasf: hrm

16:45 * nicholasf scrolls up

16:45 wingy: what does the # in the first line mean: https://gist.github.com/3042912

16:45 raek: nicholasf: is your OS set to a language that uses right-to-left directioned writing, like Arabic or Hebrew?

16:45 nicholasf: wait something is different

16:45 my original example (which wasnt working) now passes

16:46 TimMc: nicholasf: Try *clojure-version* in that REPL.

16:46 nicholasf: raek: nope

16:46 user=> *clojure-version*

16:46 {:major 1, :minor 2, :incremental 1, :qualifier ""}

16:46 TimMc: wingy: That's the new reader literal datatype something something syntax.

16:47 nicholasf: something bizarre is happening

16:47 raek: indeed

16:47 TimMc: I blame leap-seconds.

16:47 nicholasf: haha

16:47 raek: I blame invisible characters

16:47 nicholasf: hrmn

16:47 TimMc: indeed

16:47 amalloy: oh, that's an interesting possibility

16:47 though i still think his original broken repl had just redefined fn accidentally

16:47 nicholasf: it must be something like that

16:48 TimMc: amalloy: But it failed on two machines.

16:48 nicholasf: the function I tested with just works on my mac air

16:48 no, what failed on the mac air was me writing 'fn'

16:48 TimMc: Ah! Yes, that would.

16:48 nicholasf: I thought that was an adequate test

16:48 so I'm sorry for wasting people's time

16:48 amalloy: &(let [fn inc] ((fn [x] (+ 1 x)) 2))

16:48 lazybot: ⇒ 3

16:48 amalloy: ,(let [fn inc] ((fn [x] (+ 1 x)) 2))

16:48 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0)>

16:48 amalloy: there we go. man, i need to fix that issue in clojail

16:48 raek: nicholasf: 'fn' is hardcoded into the compiler, but only at "call positsion"

16:49 amalloy: raek: no it isn't

16:49 TimMc: fn* is

16:49 raek: ah, sorry

16:49 amalloy: fn* is; fn is just a regular macro

16:49 raek: it's a macro, yeash

16:49 nicholasf: ah ok, fn is a macro using let and do, right?

16:49 TimMc: More complicated.

16:49 amalloy: well, using let and fn*

16:49 nicholasf: ok

16:49 * nicholasf goes back to basics

16:49 TimMc: nicholasf: (source fn) in your repl

16:50 raek: no, it expands to fn*, which is like fn but without destructuring, IIRC

16:50 * nicholasf does that

16:50 nicholasf: ha cool TimMc

16:50 that is *really* cool

16:52 jeremyheiler: ,(interleave [1 2 3] ['a 'b]) ; is there a nice way to have the 3 added to the end?

16:52 clojurebot: (1 a 2 b)

16:53 jeremyheiler: i mean, have the 3 be part of the lazy sequence.

16:53 TimMc: jeremyheiler: An interleave-all, in other words?

16:53 jeremyheiler: yeah

16:59 I know I can hack on the interleave implementation, but was just wondering if there's another way.

17:04 S11001001: jeremyheiler: do you know which list is shorter?

17:05 jeremyheiler: Yes

17:05 S11001001: what happens for [1 2 3 4] and ['a 'b]?

17:06 jeremyheiler: For my purposes, I would be ok with (1 a 2 b 3 4) but that is not an expected use case. I really only care about the second list being one element smaller.

17:07 S11001001: ,(rest (interleave (cons nil ['a 'b]) [1 2 3 4]))

17:07 clojurebot: (1 a 2 b 3)

17:10 raek: ,(let [a ['a 'b] b [1 2 3]] (cons (first b) (interleve a b)))

17:10 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: interleve in this context, compiling:(NO_SOURCE_PATH:0)>

17:10 raek: ,(let [a ['a 'b] b [1 2 3]] (cons (first b) (interleave a b)))

17:10 clojurebot: (1 a 1 b 2)

17:10 raek: ,(let [a ['a 'b] b [1 2 3]] (cons (first b) (interleave a (rest b))))

17:10 clojurebot: (1 a 2 b 3)

17:10 raek: :)

17:11 jeremyheiler: nice, i guess that last use-case makes it that much simpler :-P

17:11 thank you both

17:12 solussd_: is it possible to add custom json encoders for use with noir.response/json ?

17:13 TimMc: jeremyheiler: Will either list ever be of length 1?

17:16 wingy: TimMc: where can i read about it?

17:16 jeremyheiler: TimMc: Yeah, but never both at the same time.

17:20 TimMc: It seems raek and S11001001 solutions work for my current problem. but a proper interleave-all would be nice addition to core, i think.

17:21 nDuff: dnolen: Should I file a ticket against zi for that classpath issue (being unable to find clojure.plexus.compiler.impl)?

17:21 raek: (defn alternate [long short] (lazy-seq (when (seq long) (cons (first long) (alternate short (rest long))))))

17:22 jeremyheiler: ^

17:22 S11001001: jeremyheiler: not useful enough

17:22 nDuff: err

17:22 raek: another solution I came up with once

17:22 hugod: nDuff: if you meant me, then yes please - sorry haven't got to it yet

17:22 nDuff: indeed.

17:23 raek: for some reason that old gist 404s for me...

17:24 jeremyheiler: raek, nice, i like it

17:27 solussd_: dakrone: you there? :)

17:27 dakrone: solussd_: yes

17:29 solussd_: dakrone: excellent… quick cheshire question: so I'm trying to add a json encoder for org.bson.types.ObjectId, did this: (add-encoder org.bson.types.ObjectId (fn [o json-generator] (.writeString json-generator (str o)))), but calling (generate-string (org.bson.types.ObjectId.)) still throws a JsonGenerationException. Am I missing something?

17:30 dakrone: solussd_: and you're sure you're using cheshire.custom/generate-string instead of cheshire.core/generate-string?

17:31 solussd_: dakrone: ah, I am not. :) I'm trying to add an encoder so noir.reponse/json will encode ObjectIds… looks like this wont help me then. :/

17:31 dakrone: noir should support being able to override the json encode/decode methods with whatever you'd like

17:31 too bad it doesn't

17:32 solussd_: (it does work with cheshire.custom/generate-strin)

17:32 yes.. too bad. :/

17:32 dakrone: maybe open an issue with the noir project and see if they have any way to work around it?

17:32 TimMc: wingy: See 2.1: https://github.com/clojure/clojure/blob/master/changes.md

17:33 solussd_: k. thanks

17:43 hugod: nDuff: you'll need mvn 3 for zi

17:56 nDuff: hugod: ...ahh.

17:57 dnolen: amalloy: ping

17:57 amalloy: dnolen: pong

17:58 dnolen: amalloy: heh that problem was annoying enough that I added permuteo :)

17:58 amalloy: hah

18:00 dnolen: amalloy: some of those answers on Rosetta are epically convoluted

18:00 amalloy: http://gist.github.com/3043632

18:00 amalloy: based on core.logic master

18:00 talios: 'lo hugod

18:01 anyone using maven should be using maven 3 by now anyway.

18:01 nDuff: ...looks like Atlassian's plugin development toolchain is rather tied to Maven 2.

18:01 dnolen: amalloy: the only subtle one is not-above1o, this is a bit tricky because I'm trying to be pure, no cut.

18:01 wingy: seems that clojure 1.4 has some features added for datomic

18:02 uuid, instant and reader literals

18:02 technomancy: fact: no one outside datomic has ever cared about uuid reader literals

18:03 wingy: yeah thats why they added it in 1.4?

18:05 i mean that datomic needed uuid literals and added it to clj 1.4

18:07 amalloy: dnolen: i haven't really tried to learn the defne and/or matching syntax that you're using, yet. certainly looks like a nice shorthand for piles of conso's

18:08 dnolen: amalloy: cleaned up the gist a bit.

18:08 amalloy: yes conso and raw conde usage drives me insane now :)

18:09 amalloy: is there a reason you went with != for not-above1o, instead of taking the approach in my not-adjacento? it seems like if the list elements are unique, then just asserting that they're separated by at least one is equivalent to asserting that they're not next to each other with !=

18:11 nDuff: hugod: Hmm. After moving to Maven 3, I'm not getting that issue -- but I'm also not getting line numbers or useful error messages on compile errors; they're all of the form file.clj:[0,0] null

18:12 dnolen: amalloy: yes that approach seems just as good, but perhaps this shows how you can use != and non-overlapping clauses to accomplish the same thing.

18:13 amalloy: note in my not-above1o it's only possible for one clause to ever succeed.

18:15 amalloy: same thing with aboveo, using != will be more efficient than using rembero.

18:15 amalloy: *nod* because you turned not-adjacento into two separate applications of aboveo

18:15 dnolen: amalloy: yeah

18:17 amalloy: again your not-adjacent approach seems good in this case. items are unique and membero after a gap.

18:17 jcromartie: there is only one thing that I can think of when people discuss core.logic http://wonkette.com/assets/resources/2007/12/awesomeo.jpg

18:17 amalloy: okay. i think performance concerns are a little beyond me for now, so i'll just file that away

18:18 technomancy: jcromartie: nice!

18:19 brehaut: thats something clojurebot should learn

18:19 dnolen: amalloy: thanks for bringing it up. your run* looked solid ... reads like the puzzle :)

18:19 brehaut: haha

18:20 brehaut: (historical evidence suggests that i am not the right person to be teaching clojurebot facts however)

18:20 amalloy: dnolen: so i'm not sure i understand the implementations of rembero and permuteo you committed (aside from me not understanding defne syntax). does your rembero remove *all* instances of x? if so, permuteo will have surprising results

18:21 i wrote it to remove a single instance of x, so that, for example, (permuteo [1 2 2] [2 1 2]) succeeds

18:22 but if you're removing all instances of x it seems to me that (permuteo [1 2 2] [1 2]) will also succeed

18:22 dnolen: amalloy: it doesn't not remove all occurrences

18:22 amalloy: okay. i'll just squint at the defne some more, then

18:23 dnolen: amalloy: this is what I mean by non-overlapping. either we found it & we're done - or we didn't find it (guaranteed by !=) and we keep looking.

18:23 amalloy: this is where Prolog used to cause a lot of trouble, no disequality operator. I forget which Prolog (II ? III?) got it

18:24 amalloy: dnolen: so your rembero removes specifically the first instance of x?

18:24 dnolen: amalloy: yes

18:26 amalloy: and if you removed the != assertion it would still work, but be willing to remove any instance of x. i wrote it to remove any instance of x because i imagined that was useful for permuteo, but i suppose it actually doesn't need to be that general

18:28 dnolen: amalloy: that might be useful - hard to say w/o people sending me to fun logic puzzles on SO ;)

18:28 amalloy: permuteo is definitely useful tho - that should have been there.

18:28 amalloy: dnolen: i'm on target though, right? != is what makes it remove exactly the first instance, and do so quickly; if you removed it it would remove any instance, more slowly?

18:31 dnolen: amalloy: yes

18:31 hugod: talios: hi!

18:31 dnolen: amalloy: if != fails if unification succeeds.

18:31 er I mean "!= fails if unification succeeds"

18:31 amalloy: cool. glad to see permuteo and rembero added, even if i didn't write them; i feel like i've impacted core.logic now :)

18:32 dnolen: amalloy: you have! thanks!

18:32 hugod: nDuff: mm, that sounds strange - any chance of adding a minimal failing java file to the issue

18:32 wolgo: when destructuring a map to bind I see the following in a clojure book: (let [{k :unknown x :a :or {k 50}} m] -rest of the code here-

18:32 what is :unknown doing?

18:32 I see that the :a value gets assigned to x, that is fine

18:33 amalloy: ,(macroexpand-1 '(let [{k :unknown x :a :or {k 50}} m] foo))

18:33 clojurebot: (let* [map__30 m map__30 (if (clojure.core/seq? map__30) (clojure.core/apply clojure.core/hash-map map__30) map__30) k ...] foo)

18:33 amalloy: &(macroexpand-1 '(let [{k :unknown x :a :or {k 50}} m] foo))

18:33 lazybot: ⇒ (let* [map__10199 m map__10199 (if (clojure.core/seq? map__10199) (clojure.core/apply clojure.core/hash-map map__10199) map__10199) k (clojure.core/get map__10199 :unknown 50) x (clojure.core/get map__10199 :a)] foo)

18:34 amalloy: wolgo: you can see that this expands to (let [k (get m :unknown 50)])?

18:34 wolgo: let me take a tias break. I didn't try enough stuff to teach myself. Sorry

18:35 amalloy: thanks, I do see that

18:40 okay so :unknown is not a special argument

18:40 I understand

18:41 clojure is cool man

18:41 lots of neat ideas.

18:42 locojay: hi i m new to cljs : is it a big deal to mix js and cljs (most in cljs via closure opt and some part in js like d3 charts...)

18:42 ohpauleez: locojay: You can use c2 for the charts (a d3-like library)

18:43 and you can mix JS as you need

18:43 there's (js* …) for that very purpose

18:43 but you'll soon find out that JS offers you little once you're embedded in CLJS

18:47 locojay: yeah i ve seen c2 but i have lots of animation's ... I could reference d3 and use (js* -) as you mentioned but since the code is already their i don't think i will refactor to cljs for the time beeing. mixing parts in cljs and js seems like a good approach to me until i get more familiar with cljs

18:48 ohpauleez: locojay: talk to lynaghk - I think you can pull off all the animations you need

18:49 and you should prefer CSS animations and effects when possible

18:50 locojay: ohpauleez: thanks will do (looking for thing's like brush... will send mail to userlist)

18:51 ohpauleez: np

18:54 emezeske: locojay: FYI you should probably never be using (js* ...)

18:55 locojay: I do a ton of interop and it has never been necessary to use it

19:16 wingy: upsert = UPdate + inSERT :)

19:16 first time i heard that

19:22 emezeske: Anyone else using clojurescript 0.0-1424? I am seeing (:dne {} 42) return nil instead of 42... :(

19:24 wingy: why is datomic using a dash as in -10000002 in the id nr: {:db/id #db/id[:db.part/user -1000002], :neighborhood/name "Capitol Hill",

19:26 http://datomic.com/company/resources/transactions

19:26 Bronsa: emezeske: http://dev.clojure.org/jira/browse/CLJS-330 i think this issue refers to that problem

19:26 emezeske: Bronsa: thanks!

19:27 Bronsa: That's a pretty major bug to slip into a release O_o

19:27 Bronsa: yeah

19:28 but clojurescript is still alpha i think

19:28 emezeske: alpha != super obvious regressions should go into tagged releases

19:45 melipone: I am using math.numeric-tower and when I do (ceil (/ 4 5)) I get 1N. What does the N mean?

19:45 hiredman: ,(type 1N)

19:45 clojurebot: clojure.lang.BigInt

19:46 melipone: hiredman: thanks!

19:46 sjl: anyone know what incantation I need in :repositories in my Leiningen map to get one of these suckers to work? https://repository.sonatype.org/index.html#nexus-search;quick~lanterna

19:46 melipone: Still, why is it a BigInt?

19:57 dnolen: ,(.numerator (/ 4 5))

19:57 clojurebot: 4

19:57 dnolen: ,(inc' (.numerator (/ 4 5)))

19:57 clojurebot: 5N

19:57 dnolen: (doc inc')

19:57 clojurebot: "([x]); Returns a number one greater than num. Supports arbitrary precision. See also: inc"

19:58 dnolen: melipone: ^

19:59 melipone: under the hood it uses a primitive long until it no longer can - does that address your concern?

20:10 gfredericks: ,(-> (iterate #(*' 2 %) 7) (nth 383) type)

20:10 clojurebot: clojure.lang.BigInt

20:15 gfredericks: what are "reify" and "this-as" in cljs?

20:15 (is there some better way to find that out than asking here?)

20:15 dnolen: ejackson's core.logic presentation is pretty nice!

20:16 gfredericks: reify is the same as Clojure's

20:16 gfredericks: this-as is a interop thing.

20:16 gfredericks: yeah I shoulda checked what clojure's does first :)

20:16 dnolen: is it like (let [foo js/this] ...)?

20:17 dnolen: gfredericks: except no promise that js/this will continue to work.

20:18 gfredericks: oh I didn't even know if it did

20:18 dnolen: gfredericks: it probably won't, I think this always becomes this$

20:18 gfredericks: it doesn't work in himera

20:18 dnolen: okay cool thx

20:44 weird himera behavior: () => (), ()() => nil, ()()() => (), ()()()() => nil, and apparently all nil after that

20:44 Raynes: Hah

20:44 * gfredericks must be a little bit bored

20:50 dnolen: pretty cool http://github.com/jonase/scape/commit/51d75b11b5919a1b019d4d3288b8cc28c0ee32f5

20:54 pdk: what i learned today:

20:55 don't dispatch a bunch of agents grinding on a search tree in parallel on your local machine

20:57 sabe: evening

21:01 I'm craking my head but I can't find a solution. Perhaps someone can help?

21:01 given this: https://gist.github.com/3044453

21:01 how can I call "f" with ["a" "b" "c"] and an initial "context"?

21:03 dnolen: (->> 0 (fn "a") ...) doesn't work?

21:03 sabe: ^

21:04 sabe: hm but how can I create that call from a seq?

21:04 dnolen: neat http://code.google.com/p/lanterna/

21:04 sabe: what do you mean?

21:05 Raynes: dnolen: Like reduce.

21:06 sabe: dnolen: given that I have ["a" "b" "c"], how do I call f 3 times passing the result of the first call to the second one and so forth

21:07 dnolen: sabe: like Raynes said, why not reduce?

21:08 sabe: lemme try

21:08 gfredericks: ,(reduce str "teehee" ["a" "b" "c"])

21:08 clojurebot: "teeheeabc"

21:08 sjl: dnolen: sabe: the context being the second arg is going to bite you when you try to reduce

21:08 sabe: sjl: that's exactly the problem :(

21:09 sjl: otherwise (reduce f 1 ["a" "b" "c"]) would work

21:09 gfredericks: sabe: you can wrap it in an anon fn to reverse the args

21:09 sjl: unfortunately I don't think Clojure has a flip function, but it should be trivial to write http://zvon.org/other/haskell/Outputprelude/flip_f.html

21:09 sabe: sjl: :[ ]

21:09 it works :~ you guys rock

21:09 gfredericks: I'm sure useful has it

21:09 Raynes: It actually doesn't.

21:10 gfredericks: wat

21:10 Raynes: I added it once, but amalloy didn't like my version, preferring his 20 line version that he never actually added.

21:10 gfredericks: Raynes: does it have (partial partial apply)?

21:11 sabe: thanks sjl, dnolen, Raynes, and gfredericks

21:11 amalloy: gfredericks: no, though at one point i was thinking of adding that

21:11 gfredericks: ,(let [pap (partial partial apply), + (pap +)] ((comp + range) 10))

21:11 clojurebot: 45

21:11 amalloy: i called it ap, not pap, personally

21:11 gfredericks: amalloy: for some reason I woke up one morning with that function in my head

21:12 I don't know why I called it pap. should be ppa if anything.

21:12 oh Partial APply was it

21:12 amalloy: right

21:12 gfredericks: but I like ap too

21:12 amalloy: i just called it ap because who cares that partial is involved in the impl

21:12 (map (ap +) (...))

21:12 gfredericks: yeah who cares

21:13 sjl: (defn flip [f] #(apply f (reverse %&))) ?

21:14 gfredericks: (defn flop [f] #(apply f (shuffle %&)))

21:15 brehaut: gfredericks: i believe the canonical name for that operation is PHP

21:17 gfredericks: why aren't there more newbs having trouble with macros?

21:19 amalloy: isn't the most common macro-newbie problem "help, i foolishly wrote a macro"

21:19 gfredericks: yes

21:20 sabe: give me a couple days ;)

21:21 gfredericks: &clojure.tools.macro/macrolet

21:21 lazybot: java.lang.RuntimeException: Can't take value of a macro: #'clojure.tools.macro/macrolet

21:21 gfredericks: sweet we can write macros on lazybot

21:23 sabe: danger

21:23 gfredericks: &(clojure.tools.macro/macrolet [(fark [expr] (clojure.walk/postwalk #(cond (seq? %) (vec %) (vector? %) (seq %) :else %) expr))] (fark [let (foo 12 bar 15) [+ 12 [- 15 18]]]))

21:23 lazybot: ⇒ 9

21:39 dnolen: amalloy: fwiw, I think a cKanren dinemans solution might look something like this - https://gist.github.com/3044626, which would be close to the brevity of Haskell's solution.

21:40 amalloy: dnolen: fd is some kind of...constraints-based numbers thing?

21:40 dnolen: amalloy: yep

21:40 gfredericks: just finite domains right?

21:40 dnolen: amalloy: so no permutations, should be fast

21:41 gfredericks: dnolen: (interval 1 5) takes linear space?

21:42 dnolen: gfredericks: stores lower and upper bound. might grow as constraints run of course, but as a sequence of intervals.

21:42 gfredericks: all this stuff is done on protocols so optimizations possible - bit vectors, discrete interval encoding trees, etc

21:43 gfredericks: dnolen: oh nice; I must misunderstand the finite domain idea then

21:43 i.e., why not simply all integers?

21:43 dnolen: gfredericks: what do you mean?

21:44 gfredericks: dnolen: it wouldn't support (interval -infinity +infinity) for example, would it?

21:45 Shambles_: There was a lot of discussion about OO in history that I just see now. Few people seem to understand 'how we got there'.

21:46 It makes quite a lot of sense if you consider that we started out with unstructured code, so you couldn't tell what modified a particular variable, or where the code you needed to change was.

21:46 dnolen: gfredericks: protocol waiting to happen, pretty sure unbounded intervals could work.

21:46 Shambles_: Structured programming got the code packaged in orderly procedures, but you still couldn't figure out what modified a particular variable.

21:46 gfredericks: dnolen: oh nice; I'll stop doubting then. really looking forward to arithmetic.

21:47 dnolen: gfredericks: in fact probably a requirement for the kinds of things I'd like pred dispatch do.

21:47 Shambles_: OO bundled the variables with the code that modified them (assuming you didn't use any public variables, which, if memory serves, Simula and Smalltalk don't allow).

21:48 From the imperative programming point of view, OO really was 'easier to understand', since you didn't have to read the entire program to understand how to fix a bug.

21:50 I think functional programming was its own thing. It was the first (as far as I know Lisp was the first) attempt at declarative programming. I don't think it had to do with ease of anything.

21:51 kovasb: is functional programming declarative programming?

21:52 gfredericks: I can imagine an argument that HOFs allow more declarative things

21:52 brehaut: you can do declarative programming with functional programming

21:53 Shambles_: kovasb: It's usually lumped in that category, along with everything else that isn't (blantantly) imperative, yes. Other things that are in that category are concatenative, dataflow, and logic programming languages.

21:53 dnolen: gfredericks: well read a POPL12 paper where Scala folks got it to work, can't let them show us up or anything!

21:54 gfredericks: dnolen: did you attend that?

21:55 dnolen: gfredericks: nope

21:55 Shambles_: kovasb: Theoretically declarative languages let you worry less about control flow. They 'figure it out' for you. In practice they either aren't much help (e.g. Fortran-like and Lisp-like languages don't tend to do anything particularly 'clever' for you), or you end up fighting them every time you want to do I/O (e.g. when doing logic programming), since the order of evaluation in I/O matters.

21:56 kovasb: I guess i think of declarative as something that possible in parts of the program

21:57 like, you have a spec for something

21:57 eg project.clj file

21:57 and something else interprets that, but its pretty domain specific

21:58 basically declarative == parameterized in this POC

21:58 POV

21:58 Shambles_: kovasb: I think the problem is people really need to be able to use different language designs for different purposes. I/O hurts less in imperative style than anything else. GUI's probably should be built out of some weird mishmash of OO and dataflow. Functional and logic programming are probably handy where you'd want to do fancy math, including symbolic math, or proofs and planning and the like.

21:59 kovasb: Of course Lisp lets you embed domain-specific languages so you can actually do that.

21:59 kovasb: yeah

21:59 a computation for every occasion

22:01 dnolen: kovasb: I think declarative programming can be much broader than people think. People always consider putting everything into one paradigm or another. Instead if you understand what's possible in a declarative paradigm, you have a better understanding where it can be powerfully applied - i.e. a rich assertion language that you gradually annotate your program w/.

22:01 kovasb: right

22:01 dnolen: kovasb: jonasen's scape is great example, dump your code into a DB and figure out meaningful queries over it.

22:02 kovasb: i guess declarative programming is where data meets programming constructs

22:02 dnolen: yes i agree it can be much broader

22:03 Shambles_: It does make me a bit sad when I see people bash on OO without even understanding why it exists, which is pretty often. It really is nice not to have to wonder where to look for code that might have corrupted your variable.

22:04 dnolen: kovasb: I think part of the problem is that people consider code some holy kind thing instead of just another piece of data. In this regard Lisp still got the one-up - you don't lose that clarity.

22:05 kovasb: dnolen: another problem is they don't have nice homoiconic datastructures

22:05 amalloy: Shambles_: doesn't help much if you expose setFoo(x) methods that just do what they're told

22:06 dnolen: kovasb: that's what I mean about the clarity. You can do the same thing with many languages - but people consider that the realm of the compiler / tool writer.

22:06 kovasb: right

22:06 hugod: nDuff: your repro case works for me - Apache Maven 3.0.4 (r1232337; 2012-01-17 03:44:56-0500), Java version: 1.6.0_33 or 1.7.0_4

22:06 Shambles_: kovasb: Well, there's two reasons for the 'holy code' point of view too. Until fairly recently (about the 90's), there were a lot of programmers that considered self-modifying code to be great. They were rather famous for creating unmaintainable messes. The other is the drive toward better security that was hardware-based (non-executable pages). This drove programming toward very-static environments where code wasn't dat

22:06 That probably got cut off. Sorry. "This drove programming toward very-static environments where code wasn't data."

22:06 kovasb: dnolen: i watched the guido pydata talk .. the whole thing was people asking for extending language syntax, and wanting macros

22:07 dnolen: kovasb: haha

22:07 kovasb: Shambles_: right

22:07 dnolen: it was crazy. that was the the "python scientific community" has on the frontburner

22:08 Shambles_: amalloy: It's not /as/ helpful as it could be, perhaps, but nobody is forcing you to do that with OO, and it's still better than the structured code situation, because if you need something to happen whenever that variable changes, you can at least stick it in the setFoo method and take comfort in knowing it will always occur when appropriate.

22:08 kovasb: for core language dev at least

22:09 dnolen: btw got the cljs tagged literal support working in session. bit of a hack but

22:09 Shambles_: I'm a Python (my preferred language anyway) programmer trying to move to Lisp. It's close enough for me to understand why people would be asking for those things in Python. There's not a lot else missing.

22:10 kovasb: Shambles_: i am not against OO, just the programs people tend to write with it

22:10 Shambles_: I don't think they can add it without causing major headaches, and Guido is dead set against it.

22:10 dnolen: Shambles_: it not clear to me that self-modifying in the mainstream was ever popular. Do you mean in languages like C++ / C ? If so, yeah nightmare.

22:11 amalloy: dnolen: before that, i think. assembly

22:11 dnolen: amalloy: that would have been in the 50s and 60s then.

22:11 kovasb: Shambles_: yes he did a good diplomatic job of knocking them down

22:11 dnolen: and was probably better than writing all the assembly by hand.

22:11 amalloy: oh, i missed his "recently" claim. yeah, i agree that doesn't seem true

22:11 Shambles_: kovasb: Self-modifying code was, until about the miod 90's *wildly* popular with assembly programmers. You could get away with that stuff easily in DOS. It was used to save RAM, do copy protection, and in rare cases improve speed (by removing the need for subroutines or branches).

22:12 kovasb: Assembly seems to have fallen out of favor, even with game programmers, and given higher level languages were trying to avoid quite so much mess, it's not surprising it's not as doable now.

22:12 dnolen: Shambles_: do you have any evidence that it's not popular among assembly devs today?

22:13 Shambles_: isn't the whole point of modern runtimes self-modifying code?

22:13 kovasb: somehow "self-modifying code" tends to sound more scary than it usually is

22:13 Shambles_: dnolen: It's not as popular today due to most OS's (Windows and Linux at least) setting most pages non-executable.

22:14 kovasb: i think it's fair to say we have OO in clojure

22:15 Shambles_: dnolen: Using data to decide what code to execute usually achieves the same ends as self-modifying code, but it's more painful, so isn't done when you don't really *need* to. It also makes it blatantly clear that that is being done from looking at the source.

22:16 dnolen: Shambles_: completely disagree with that. Data is control is great.

22:16 Data as control.

22:17 kovasb: i agree they are very similar

22:17 also data as control is great so long as writing the executor is easy

22:18 Shambles_: dnolen: I didn't say anything about whether it was 'great' or not. I just said it's clearer that it's being done (no mystery code overwrites at some point in your memory map), and that it's more painful, which it is, since you have to manually specify the mapping rather than relying on what the hardware considers a particular binary sequence to 'mean'.

22:19 dnolen: I also have a healthy respect for the lessons of history. 'Cute' control flow may be necessary, but I don't like to use it when I don't *need* to. There's no point in using a kaiser bomb to kill a housefly.

22:19 dnolen: Shambles_: yes, self-modifying assembly is not something I want to know anything about.

22:19 Shambles_: no argument there. I'm not going to replace my ifs with maps.

22:20 kovasb: i definitely went through i stage in mathematica programming where i tried to do everything with replacement rules

22:20 technomancy: has anyone written ring applications that return DB-altering functions in parallel to the HTTP response map?

22:20 kovasb: but if is pretty good

22:21 technomancy: it's probably not feasible, but I'm curious if anyone's tried it

22:21 kovasb: more complex control often indicates you are doing it wrong

22:22 ohpauleez: technomancy: can you give an example?

22:22 Shambles_: As for OO in Clojure, I guess you have it due to Java interoperability, and reference types, but mutable variables are clearly the red headed stepchildren in Clojure, and I'm finding the adjustment to extreme-minimal-mutation to be rather painful. I've been trying to get my head around zippers for that. I don't think anybody would like it if I just kept to a OO style.

22:23 technomancy: ohpauleez: {:status 201 :body "dude I made a thing for you" :db ["INSERT INTO widgets VALUES ('hello', 'world')"]} or some variant

22:23 kovasb: Shambles_: one big argument for the declarative style is that there are fewer functions to worry about.

22:23 Shambles_: and so tends to be easier to copy code, serialize it etc

22:23 technomancy: ohpauleez: you'd probably want DB functions to work like swap! or alter functions

22:23 dnolen: Shambles_: not true, about the OO stuff & Java interop.

22:24 kovasb: Shambles_: i think the datatypes and record lend it OO status -- functions and data together

22:24 dnolen: Shambles_: Clojure distills the good OO stuff - and leaves the baggage behind.

22:24 Shambles_: kovasb: You are kidding right? Functional programming tends to be all about having lots of itty bitty functions. In theory if they're named well (i.e. not like a mathematician would), they read a bit like a English description. If you're using Forth, they even call them "words" that are in a "dictionary", but it all reads like Yoda talking.

22:24 technomancy: ohpauleez: it probably wouldn't work without PLV8 and cljs I think

22:24 ohpauleez: technomancy: not via ring explicitly, but I have done something similar with CLJS and datomic

22:24 only as a thought experiment

22:24 dnolen: Shambles_: also, local mutation is perfectly acceptable in Clojure.

22:25 kovasb: Shambles_: i mean, in my definition of declarative. Its just some piece of data.

22:25 Shambles_: like, the datomic api is 1 function

22:25 Shambles_: and then you pass in the declarative spec of your query

22:26 technomancy: ohpauleez: I think plv8 makes it feasible in postgres, but I imagine the build to get there could be a worlde o' pain.

22:26 Shambles_: dnolen: Trying to figure out how to alter a simple tree, based on user response, is giving me a headache. It wouldn't if I just used vars, but I'm sure that's not the 'correct' style. I'm pretty sure what's excpected is for me to use zippers and only one var to hold the root.

22:27 ohpauleez: technomancy: Would be interesting to see how far you could get in a day though

22:27 dnolen: Shambles_: do you know the path to the thing you want to change? If so why do you need zioppers?

22:27 kovasb: Shambles_: do you have a function that outputs the modified tree?

22:28 technomancy: ohpauleez: I suck at both postgres and cljs, so I'm going to delegate that to someone else who happens to be listening to this conversation

22:28 ohpauleez: but the details are most certainly difficult - datomic has some padding that made it easier (queries are just data structures - remoting via CLJS to the server-side peer was an easy hack to tie over pieces)

22:28 kovasb: Shambles_: (swap! your-atom your-function function-arg)

22:29 technomancy: ohpauleez: I suspect queries are just data structures with cljs/plv8 too

22:29 Shambles_: dnolen: It's a 'toy' program to try to help me understand things. It's basically a miniature expert system. It traverses a tree to answer questions. If it can't answer the question it needs to add a new node at the tip of what was a 'leaf'.

22:29 kovasb: where you have (defn your-function [original-tree function-arg] ..produce new tree..)

22:29 technomancy: but you have to do the heavy lifting yourself I guess

22:30 kovasb: Shambles_: zippers create new data structures as you are doing your insertions etc

22:30 Shambles_: dnolen: My current thoughts are to keep passing a path as it gets built up traversing the tree, then convert that into zipper operations to modify the tree if necessary. That would keep the tree from mutating. There'd only have to be one point of mutation in the program; the variable that holds the current tree's root.

22:30 dnolen: Shambles_: is a tree a good representation? Why not tuples + indexing?

22:31 kovasb: Shambles_: if the issue is saving it at the end, there is a function to output the new modified tree. you can stuff that into a ref type

22:31 technomancy: anyway, someone who's good at postgres should implement that; kthxbai

22:32 Shambles_: dnolen: I'm not sure what you have in mind, but yes, a tree is a good representation. There are questions, whose yes or no answers lead to more questions.

22:33 dnolen: Shambles_: so you have indexes, why do you need a tree?

22:33 Shambles_: dnolen: I don't have a index in the sense of 1 through n. It's not look-up-able like a index in a array.

22:34 dnolen: Shambles_: don't the questions have ids? And each question can point to the next one?

22:34 Shambles_: dnolen: In the sense that there is a pointer, I suppose.

22:35 dnolen: Shambles_: so flatten the tree, create a pointer. Less programming.

22:35 kovasb: i don't see why bother

22:35 update-in works fine

22:36 step 1. look up in tree using get-in

22:36 step 2. update tree with update-in

22:36 or assoc-in

22:36 dnolen: kovasb: it mostly does, but it really depends on the use case. nested update costs add up.

22:36 kovasb: indexed tuple representation is cheap to update.

22:36 kovasb: it sounds like performance is not a concern in this case :)

22:37 Shambles_: dnolen: Why would I want to flatten the tree? If something has a natural branching tree structure based on yes or no answers, cramming it into a flat data structure seems rather ugly. It also means I'll have to start manually managing what pointers were doing for me. I'll have to say "jump to question 1... uh, okay, now let's go lookup 1, alright, ask question, get answer, now I need to jump to question 89, let's look tha

22:37 dnolen: Shambles_: because now you're playing around with zipper which makes no sense to me.

22:38 Shambles_: you have first class data structures, getting the next question is trivial.

22:38 kovasb: Shambles_: i would check out get-in, assoc-in, update-in

22:38 dnolen: (questions (:next question))

22:38 Shambles_: dnolen: What I want to do is mutate a tree. Mutating is demonized, so I need to find a way to do it without mutation. Zippers appear to be the promoted salve for the need to mutate a tree.

22:39 kovasb: Shambles_: use swap! in combination with the aforementioned functions

22:39 dnolen: Shambles_: your assessment would be incorrect.

22:40 Shambles_: if you want to mutate a tree you're bringing a solution to a problem - not solving the problem.

22:40 kovasb: zippers do not mutate. they generate new datastructures

22:40 dnolen: not "actually" solving the problem.

22:40 kovasb: its just a more cumbersome way of doing the retrieval/update operatons

22:40 Shambles_: I have no trouble imagining how to flatten this into a list. I've seen people do that in one language I've had the misfortune to use, since it had no pointer or reference type. It wasn't easy to tell what was going on when reading such code (it didn't /look/ like a tree). But with enough blood sweat and tears it could be made to work. Lists could be appended in the language so you could add new nodes that way.

22:41 That was actually the only aggregate data type. There were strings, but you couldn't interact with them like arrays. Very unpleasant, especially given lists were not nestable.

22:42 dnolen: Shambles_: huh, databases work like this - even graph databases - it's not that bad.

22:43 Shambles_: dnolen: I suppose I've gotten spoiled by 'easy' data structures. In Python if you want a tree, you make a class, and assign instances of that class type to various variables. There ya go. Easy to understand, easy to read. Everybody knows what you're up to. Anything else seems like handcuffs on.

22:44 dnolen: Shambles_: too many things to not like about Python to care about "easy" mutable graphs.

22:44 for me

22:44 Shambles_: I could flatten this into a list, and avoid learning how to use a zipper I guess.

22:45 kovasb: what is wrong with {:node value :children [ … ]}

22:46 dnolen: kovasb: Shambles_: I agree if this is a "toy" that works best.

22:46 kovasb: i mean, that is pretty easy to iterate over

22:46 Shambles_: kovasb: As for zippers don't mutate, I'm aware of that. I said it's the promoted salve for /wanting/ to mutate a tree. When you say "I want to mutate" and the response is "mutation is bad", there has to be a solution "so do it this way". You end up needing to understand category theory if it's Haskell. Other languages usually have easier solutions. :P

22:47 kovasb: if i knew what computation you wanted to do, I'm sure it would be a one or two liner

22:47 dnolen: ,(update-in {:value 'foo :children []} [:children] (fn [c] (conj c {:value 'bar :children []})))

22:47 clojurebot: {:value foo, :children [{:value bar, :children []}]}

22:48 Shambles_: There is at no point a need to 'iterate over' the tree. It's a tree. You need to be able to crawl it based on responses. You definitely don't need/want to pass over the entire tree. The only problem is trying to figure out how to change the tree (without mutation) when it needs to be updated.

22:48 technomancy: wanting to mutate a tree for the sake of mutation doesn't sound like a very useful goal

22:48 kovasb: ,(assoc-in {:value 'foo :children []} [:children] {:value 'bar :children []})

22:48 clojurebot: {:value foo, :children {:value bar, :children []}}

22:49 kovasb: whoops

22:49 ,(assoc-in {:value 'foo :children []} [:children 0] {:value 'bar :children []})

22:49 clojurebot: {:value foo, :children [{:value bar, :children []}]}

22:49 kovasb: dang

22:49 there we go

22:50 Shambles_: The code is a lot easier for me to understand. If this was Python I'd just use a reference to the current node to change the values. That's quite possible in Clojure too (you can apparently put reference types in data structures), but apparently not the way you're supposed to do things, so I've been trying to figure out how to drive mutation out of the program except where it *has* to exist.

22:50 dnolen: Shambles_: you can keep on talking or you can show your code at this point :)

22:50 kovasb: ,(get-in {:value 'foo, :children [{:value 'bar, :children []}]} [:children 0 :value])

22:50 clojurebot: bar

22:51 dnolen: Shambles_: I'm sure people will / can offer up improvements to your approach.

22:52 kovasb: i guess i am not seeing where the zippers are falling down

22:52 Shambles_: dnolen: The code doesn't exist, since, as I said, I've been trying to figure out how to update the tree, but essentially it's this Python program ported to Clojure: http://openbookproject.net/py4fun/animal/animal.py

22:53 kovasb: you use the zipper, and then.. ? how is that not working

22:53 iDesperadO: Could not transfer artifact org.mongodb:mongo-java-driver:pom:2.6.5 from/to central (http://repo1.maven.org/maven2): Checksum validation failed, no checksums available from the repository

22:53 how about this error?

22:54 kovasb: sounds like a busted artifact no?

22:55 dnolen: Shambles_: for that I agree w/ kovasb, that seems trivial w/ zippers

22:56 kovasb: dnolen: one limitation i can see, is if you want to maintain tree position, but also make the new tree concurrently available

22:57 dnolen: because you need to emerge from the zipper to create the new top level value

22:57 Shambles_: kovasb: It's mostly me trying to understand how to do it. Currently my only guess is to pass a list, probably of symbols, that states the path taken to the node (it depends on the answers someone has given), as a argument, so if its guess is wrong, it can use that to reach and change the appropriate node.

22:57 technomancy: iDesperadO: whoever deployed the java mongodb driver screwed up pretty badly

22:57 iDesperadO: so...how to fix it?

22:57 Shambles_: Zippers don't exist in any language I've used before, so the idea is pretty foreign.

22:57 kovasb: Shambles_: if you already have the path in-hand, why not just use update-in or assoc-in ?

22:58 iDesperadO: technomancy: I just git cloned incanter project and run `lein deps` only to find the dependencies can't be met

22:58 technomancy: iDesperadO: you can add :checksum :warn to project.clj, but that opens you up for accepting corrupted jars into your projects

22:58 kovasb: the only reason to incrementally walk the tree is if the next step in the walk is dependent on an answer you don't have yet

22:58 technomancy: iDesperadO: probably better to add :exclusions for the mongo junk

22:58 dnolen: kovasb: hmm, the cursor is purely functional tho right? you can hold on to it like any other value.

22:58 Shambles_: kovasb: You wouldn't necessarily have the path. You just need to loop (or recur) and follow the references so long as the tree doesn't need changing.

22:59 technomancy: or just delete it out of project.clj if it's mentioned explicitly

22:59 kovasb: dnolen: yes, but if someone else changes the tree at the ref, you won't see that

22:59 dnolen: kovasb: is that relevant here?

22:59 kovasb: no idea

22:59 Shambles_: kovasb: That's what's happening with the while loops in the Python code. When it needs to modify the tree it does it by mutating it, by using the reference to the current node.

23:00 iDesperadO: technomancy: im afraid the incanter project uses mongodb...

23:00 dnolen: kovasb: it is not relevant

23:00 technomancy: iDesperadO: really? I thought it was optional.

23:00 kovasb: Shambles_: i see. should be able to do a direct port with zippers

23:01 dnolen: kovasb: the questions are asked once you have an aswer you can then update the zipper

23:01 Shambles_: kovasb: I would need to keep passing the path as it's traversed, right?

23:01 kovasb: right

23:01 Shambles_: i don't think so

23:01 dnolen: Shambles_: in this case I think a zipper is more natural for a close port.

23:02 kovasb: Shambles_: i believe the path is accessible natively in the zipper

23:02 Shambles_: when you are at a child, pretty sure that data structure keeps its path around. don't know the zipper api offhand

23:03 Shambles_: kovasb: The tutorials I've read on zippers show a long series of down, left, right, and so on, to be able to modify something. This one looked like what I'd need to use. http://tech.puredanger.com/2010/10/22/zippers-with-records-in-clojure/

23:03 kovasb: Shambles_: check out this talk, it has everything i know about zippers http://blip.tv/clojure/luke-vanderhart-clojure-zippers-4521622

23:04 Shambles_: i suggest that talk, it does simpler stuff

23:05 Shambles_: kovasb: I'll see if I can find the "pwd" equivalent in the API. If it exists, yes, this would be easier.

23:05 kovasb: pwd?

23:06 Shambles_: kovasb: Path to Working Directory. Unix command.

23:06 kovasb: Shambles_: that exists in zippers

23:07 i believe its :ppath

23:07 i mean, the zipper is a datastructure

23:07 i suggest making one and just looking at its contents

23:07 its actually pretty instructive of the benefits over oo

23:08 you can just print it out and its a collection of normal clojure datastructures

23:09 i suggest watching the last 4th of the talk where heres doing stuff at the reok

23:09 repl

23:10 amalloy: kovasb: annoyingly, it's a collection of normal data structures...but with some hidden metadata that doesn't print unless you ask for it

23:10 kovasb: lol

23:11 technomancy: so I was listening to ejackson's core.logic talk in the car today and I'm pretty sure there was a siren in the background of the talk's audio track.

23:11 had me kind of confused for a minute

23:12 amalloy: that was just the thought police

23:12 kovasb: i was trying to listen to that talk, but the speech pattern was too much

23:13 technomancy: his pronunciation of A in a few words didn't match my conception of the british accents I'm familiar with

23:13 I guess there are tons of regional variations

23:17 gnarmis: Hey all, I was wondering if anyone knows where the latest snapshots of lobos are? They don't seem to be on clojars

23:20 Btw, currently using [lobos "1.0.0-SNAPSHOT"]

23:21 botter: Is there anything like ClojureBox for Windows for 1.5?

23:21 gnarmis: but found a closed issue which suggested there's a newer one on clojars. https://github.com/budu/lobos/issues/36

23:23 technomancy: botter: clojurebox is old and unmaintained; recommend you not use it

23:23 botter: Yea, I'm looking for an alternative

23:25 technomancy: you'll probably have to download the parts separately

23:25 botter: :|

23:26 technomancy: orthogonal things are best kept orthogonal

23:26 trust me, you don't want to have to upgrade your editor just because a new version of clojure came out

23:27 botter: I only want to try CLojure for a bit, so I don't want to spend too much time setting up the environment

23:27 But I'll give it a shot

23:28 technomancy: if you don't already have Emacs set up, you probably shouldn't learn it at the same time you're learning Clojure

23:29 kovasb: botter: does clooj work for you?

23:29 botter: I'll try clooj, I've never head of it before

23:30 kovasb: its pretty good for a quick editing and repl solution

23:30 botter: technomancy: Setting up emacs right now. I've only used vi

23:31 technomancy: botter: strongly advise you wait on that until you know your way around clojure

23:31 learning two things at once is a recipe for a headache

23:31 botter: Wait on what?

23:31 technomancy: wait on Emacs

23:32 iDesperadO: technomancy: how to download org.mongodb/mongo-java-driver? there are pom/jar/javadoc.jar/sources.jar to download...I have to download them all?

23:32 botter: So clooj then

23:32 kovasb: iDesperadO: you can also clone the repo and install it locally. very easy with lein install

23:33 o wait.. that is not a clojure package

23:33 iDesperadO: http://search.maven.org/#search|ga|1|a%3A%22mongo-java-driver%22

23:33 technomancy: iDesperadO: are you sure you need it? from what I heard it's just a convenience thing for incanter; it's not really required.

23:33 iDesperadO: O

23:34 technomancy: but you can set :checksum :warn in project.clj to turn off verification if you must =(

23:34 iDesperadO: what if i need it? I want to know how to download it manually

23:35 I see lein install dependencies in ~/.m2/repository/. I guess I can do it manually

23:35 technomancy: don't do it manually

23:35 just turn off checksum verification in project.clj

23:35 iDesperadO: O

23:35 technomancy: lesser of two evils

23:35 sjl: ,(when-let [foo false bar true] 1)

23:35 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: when-let requires exactly 2 forms in binding vector in sandbox:>

23:36 sjl: :(

23:36 is there an idiomatic way to do that other than nested when-lets?

23:36 technomancy: sjl: the official story is that it's ambiguous whether the two conditions would be ANDed together or ORed.

23:37 kovasb: and-let

23:37 iDesperadO: I've already done that

23:37 kovasb: or-let

23:37 sjl: technomancy: I'd assume ANDed

23:37 xeqi: I think I remember that spawning a long mailing list thread

23:37 technomancy: not saying I agree, but that's the official position

23:39 sjl: how would or even make sense? would it short-circuit the binding like (or) and leave one unbound?

23:40 I guess it could just do them all and leave them bound to falsy stuff

23:40 wheras AND would behave the same as (and) where it short-circuits

23:40 kovasb: you let them bind to whatever the value was

23:40 what the multi form should do is

23:40 let you specific which variables must not be nil

23:40 sjl: kovasb: yeah, just seems weird since (or) short circuits but (when-let-or) wouldn't

23:41 kovasb: good point

23:41 michaelr525: good morning!

23:41 sjl: whereas both (and) and (when-let-and) short circuit the same way

23:42 and there's no nice way to do the and version now, wheras you can do the or version with a single (let [...] (when (or bindings...) ...)) now

23:42 botter: clooj is what I'm looking for. thanks.

23:42 kovasb: botter: np

23:43 something like (when-let2 [a … b …] [a b] …)

23:43 where a b specifies that a and b must be not falsey

23:43 sjl: kovasb: eh, that's getting a bit fiddly

23:44 kovasb: seems flexible to me

23:44 unless you want to only all or any behavior

23:44 if you want all, might as well list them out

23:45 or just give a symbol :all, or :any, and then have the vector case for specifying granularly

23:45 sjl: well, the when-let-or version can be done in a 3-level structure for N bindings right now

23:45 but the when-let-and version requires N levels for N bindings

23:45 so it seems that AND would be more beneficial

23:46 kovasb: i haven't had a need so i can't really tell :)

23:46 amalloy: $google github egamble let-else

23:46 lazybot: [egamble/let-else · GitHub] https://github.com/egamble/let-else

23:46 kovasb: but its pretty reasonable to have a spec that says how the logic should work

23:46 unless there is a slam dunk case for a more specific taylored version

23:46 technomancy: amalloy: fancy-town

23:47 amalloy: eh?

23:47 technomancy: let-else

23:47 lots of options there

23:48 amalloy: yeah. i don't like it enough to use it myself, but i helped him write it, and it seems like the road these folks are headed down

23:49 sjl: I don't need lots of crazy functionality -- I was just thinking when-let would do something useful instead of just explode

23:49 brehaut: looks like a special syntax version of the maybe monad

23:50 sjl: but it's only three levels right now so I'll just type the extra when-lets

23:51 brehaut: (that wasnt intended to sound disparaging. merely an observation)

23:52 technomancy: brehaut: "That looks like a monad. Not that there's, you know, anything wrong with that."

23:52 brehaut: haha

23:54 technomancy: sjl: what was the dependency you were having trouble with?

23:55 sjl: technomancy: Lanterna -- it's a Java lib and the version I want/need is only on Sonatype

23:55 technomancy: and I couldn't find the magic :repository incantation to get it working, so I just ended up using lein-localrepo to install the jar

23:55 technomancy: =(

23:56 sjl: meh, it's a throwaway project to relax and unwind after a day of tracking down git/python insanity -- getting it working is more important than 100% build purity

23:58 technomancy: for the record, it goes like this :repositories {"sonatype-snapshots" "https://oss.sonatype.org/content/repositories/snapshots"}

23:58 sjl: hmm, I could have sworn I tried that...

23:58 does the key matter?

23:58 (the "sonatype-snapshots")

23:58 technomancy: shouldn't

23:58 sjl: hmm

23:59 I thought I tried that, but maybe not

23:59 anyway, how would I have figured that out? I looked for a repository URL on the sonatype page for that lib, but there wasn't one

23:59 (I only vaguely know Maven, etc so it might be over my head)

Logging service provided by n01se.net