#clojure log - Jul 29 2012

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

0:04 muhoo: huh, suddenly realized i can write SPA's in cljs that compile down to one .js file, and then deploy it on apache or whatever, without clojure (once it's compiled)

0:07 howard_: any Aussie friends?

0:17 Raynes: Crikey mate.

0:27 muhoo: flatstick

0:35 gert: howard_: kiwi here

0:55 howard_: my developer manager is a kiwi D:

0:55 :D

0:56 gert: I'm not a real kiwi though. just a dutchman posing as one

0:56 howard_: hahaha

0:56 Guten tag!

0:56 gert: that's german!

0:56 howard_: oops

0:56 sorry

0:56 haha

0:56 gert: not that there's anything wrong with that :)

0:57 howard_: Dutch is... west germantic

0:57 gert: so is english

0:58 howard_: ok

0:58 gert: just sayin' :)

0:58 howard_: "Dutch is grammatically similar to German, such as in syntax and verb morphology"

0:59 Clojure is grammatically similar to Common Lisp, such as in syntax and macro

0:59 hehe..

1:01 nsxt: hmm... i've a string within a (let), which i want to use to call a function with the same name as the value. the ((resolve (symbol )) etc. trick doesn't seem to work - is this a scope issue that's biting me?

1:02 howard_: dynamic code execution

1:03 have a look at this:

1:03 http://stackoverflow.com/questions/11069825/clojure-why-load-string-does-not-work-in-this-case

1:03 i had some issue with dynamic code executing some time ago

1:03 and there's bit more information in that post

1:06 nsxt: so how would i access that function, without resorting to eval?

1:07 howard_: um..

1:07 nsxt: let me refheap this to make it easier

1:09 howard_: do you wanna use read-string?

1:09 nsxt: https://www.refheap.com/paste/3869

1:10 (useful.string/dasherize operation) evaluates to 'list-tables'

1:11 howard_: let me try something

1:11 i remember people said clojure cannot dynamically execute code in lexical binding

1:12 muhoo: wow, this noir-cljs browser/repl is fragile as hell

1:12 nsxt: thanks, howard_. also, i could be approaching this entirely the wrong way (first project)...

1:13 muhoo: neat hack though

1:13 howard_: , (let [fun #(prn "ha")] ((resolve (symbol "fun"))))

1:13 clojurebot: #<NullPointerException java.lang.NullPointerException>

1:14 howard_: i think that is the problem you ran into

1:14 clojure apparently does not support dynamically execute code and refer variables in lexical context

1:15 , ((resolve (symbol "prn")) "ha")

1:15 clojurebot: "ha"

1:15 howard_: see, that one works because prn is root binding, not lexical binding

1:15 nsxt: right.

1:16 howard_: actually, i too am developing an application that requires such behaviour

1:16 this problem has good workaroundability

1:16 nsxt: it seemed better to try something like this than to build up a map of strings to functions

1:16 howard_: the solution I worked out is: make a map of keywords -> functions

1:16 nsxt: haha

1:16 howard_: <3

1:16 bingo

1:17 nsxt: yeah, kind of a bummer, but if there's no way around it, then so be it

1:17 thanks for the help

1:17 howard_: i wish i could find a better solution

1:17 dynamically execute code in lexical context will be so helpful

1:18 there's another way, though

1:18 nsxt: hm?

1:19 howard_: not very readable, not elegent

1:19 you can put the whole lexical bindings into the evaluated string

1:19 :D

1:19 nsxt: yeah, i thought about that

1:19 alandipert: the problem is to eval a function named after a string that's been let?

1:19 nsxt: but that reads like garbage

1:19 howard_: yeah...

1:19 nsxt: alandipert: correct

1:20 alandipert: ,(let [x "+"] ((symbol x) 1 2))

1:20 clojurebot: 2

1:20 howard_: symbol + is a root binding and it works

1:20 however, if x was a function, it won't work

1:21 alandipert: oh, i see

1:21 the function you want to invoke is a local

1:21 nsxt: i guess i could always use a function to extract the dasherized name

1:21 so same thing as pulling it out of the let, except not destroying the readability

1:21 alandipert: yes, i think there is probably a better alternative - this would be an exceedingly rare thing to want to do

1:22 macros do have access to the local environment via &env... if you want to keep hacking ;-)

1:22 nsxt: still, i'm glad i stumbled across it

1:22 alandipert: yup that's good stuff

1:25 nsxt: btw, you know you can do: (let [f #(prn "hey")] (f)) ?

1:27 nsxt: the problem is that i don't want to define the function within the scope of let

1:32 alandipert: nsxt: https://www.refheap.com/paste/3871 super hacky and inadvisable, but shows you you can get at locals with a macro

1:33 nsxt: alandipert: ha, cool

1:45 muhoo: cljs stacktraces are so much more awesome than regular jvm stacktraces: https://www.refheap.com/paste/3872

1:57 nsxt: this is driving me nuts, i'm still getting null pointer exceptions

2:18 samrat: how do I use a scala project(https://github.com/jiminoc/goose) in a clojure project?

2:18 I found a few tutorials, but they all involved a .jar file

2:18 and I'm not sure how to make the jar

2:30 alandipert: samrat: if you clone and 'mvn install' you should be able to add [com.gravity/goose "2.1.19"] as a lein dep

2:31 otherwise maybe it can be found in a mvn repo somewhere

3:30 tos9: So, clj will execute a .clj without any namespace declared, but clojure-py does not, and requires an ns. Why is that?

3:32 howard: clear

4:01 emezeske: tos9: Apparently JVM Clojure just uses the user namespace by default if no ns has been set

4:01 tos9: There isn't a language specification per se

4:02 tos9: The JVM implementation sort of is the "language specification", if you will

4:02 tos9: emezeske: Aha cool I was looking for something that clarified whether the spec specified that or not. Good to know.

4:02 (That there isn't one :)

4:02 emezeske: tos9: There might be something like that in the docs somewhere, but I am not aware

4:03 tos9: I think as long as I'm aware of it I can remember to do it always, just hoping that the amount of implementation specific behavior I run into is going to be minimal :)

4:03 (or documented :)

4:04 muhoo: emezeske: lein-cljsbuild or noir-cljs, which do you think i should use? :-)

4:04 emezeske: muhoo: Well, I'm a bit biased ... :)

4:04 muhoo: hehe

4:05 emezeske: I haven't used noir-cljs, so I honestly can't say

4:05 I use lein-cljsbuild for my personal projects, surprise surprise

4:05 muhoo: fair enough. i spent a few hours trying to get noir-cljs to work, next step is to try yours instead

4:07 tomorrow though. it's bed thirty now.

4:23 michaelr525: good morning!

4:34 emezeske: muhoo: I hope it works out!

8:35 rfgpfeif1er: join #lwjgl

8:35 sorry

8:36 rbarraud: Need a leading '/' :)

8:38 hyPiRion: heh

9:04 augustl: want to run "java -jar plovr.jar serve config.js" automatically when I "lein ring server". Is that possible?

10:29 justin173: what's everyone using to manage state in their cljs apps these days? I'm currently using a horrible combination of waltz, Clojurescript One style event dispatch, and route dispatching, and I really can't decide which one to stick with

10:31 pandeiro: justin173: i feel ya

10:31 i was using cljs one's dispatch but i think on my next project i will try waltz

10:33 justin173: yeah waltz seems cool

10:34 pandeiro: what issues (if any) are you having, specifically?

10:35 justin173: well, should I be using waltz for every little widget thing I have?

10:35 pandeiro: ah yeah, right

10:35 justin173: like it's probably obvious it doens't need to track state for little collapse/expand text boxes

10:35 but what about a widget that say has a main-image window then a list of thumbnails that allows you to cycle through them?

10:36 pandeiro: i think you could use it for all of it

10:36 i remember the cljs one dispatch functions for the little text box animation; something so simple had like 12 separate events dispatching

10:37 foodoo: I haven't really workey with Clojurescript before, but maybe this Closure Library is helpful for managing state? http://closure-library.googlecode.com/svn/docs/namespace_goog_storage.html

10:39 justin173: foodoo: yeah that's part of the thing too, there's like a bunch of clojurescript only solutions, and then that doesn't even get into the google closure ways of doing thing. although to be honest the storage aspect isn't the thing I'm having difficulty with

10:42 pandeiro: justin173: i think maybe simpler widgets could just be written as one multimethod

10:42 i mean with different methods dispatched based on state

10:42 but that's basically waltz

10:42 from what i understand

10:43 justin173: yeah

11:32 qerub: Is there any way to simplify (doseq [x xs] (f x)) using clojure.core? (map f xs) would do the trick, but I'm not interested in the return value.

11:36 pandeiro: (defn do-f [xs] (doseq [x xs] (f x))) ?

11:36 i know it's not clojure.core but it's a one-liner

11:43 Bronsa: (dorun (map f xs))

11:48 qerub: pandeiro, Bronsa: Thanks! I'll go with dorun.

12:06 How do I check if a value is an ISeq? (Hint: it's not `seq?`.)

12:07 Something better than (or (seq? x) (vector? x)) would be nice. :)

12:09 antares_: qerub: it is clojure.core/seq?, if all you care about if a structure implements ISeq

12:09 qerub: (seq? []) => false

12:09 Aren't vectors ISeq?

12:10 antares_: ther are also coll? and sequential?, with coll? being typically what people want

12:10 qerub: Hmm, so vectors aren't ISeq.

12:10 Bronsa: they are Seqable

12:11 qerub: OK, this explains everything. Thanks.

12:12 wilfredh: is there a Clojure equivalent of Python's repr()?

12:13 i.e. (some-function [1 2 [3 4]]) => "[1 2 [3 4]]"

12:14 Bronsa: str?

12:14 clojurebot: brehaut: I think struct embedding is monkey patching / mixins, and interface embedding is duck typing / typeclasses

12:14 Iceland_jack: ,(str [1 2 [3 4]])

12:14 clojurebot: "[1 2 [3 4]]"

12:14 qerub: ,(str "foo")

12:14 clojurebot: "foo"

12:15 qerub: repr("foo") => "'foo'"

12:15 Bronsa: ,(str (range 3))

12:15 clojurebot: "clojure.lang.LazySeq@7480"

12:15 Bronsa: (pr-str (range 3))

12:15 ,(pr-str (range 3))

12:15 clojurebot: "(0 1 2)"

12:15 Bronsa: maybe you want pr-str instead of str

12:15 ,(pr-str "a")

12:15 clojurebot: "\"a\""

12:16 wilfredh: ah, I should have thought of str

12:16 I'm trying to get the source of a given function, but it seems clojure.repl/source calls println which is what stopped it worked

12:17 *stopped it working

12:17 Bronsa: ,(with-out-str (println "derp"))

12:17 clojurebot: "derp\n"

12:17 wilfredh: perfect. thanks :)

12:31 antares_: ,(prn [1 2 3])

12:31 clojurebot: [1 2 3]

12:31 antares_: ,(prn [1 2 { :a 1 }])

12:31 clojurebot: [1 2 {:a 1}]

12:38 dp42: Hi everyone, any recommendations on debugging a C2/clojurescript piece of code? The firebug pane is not quite helpful :)

13:15 the-kenny: dp42: Debugging is kinda hard. I'd give the REPL a shot.

13:17 harja: Question on macros. Is there a way to apply something for each element in body and expand that on runtime? I'd need to transform (1 2 3) to (do (foo-do 1) (foo-do 2) (foo-do 3))

13:19 the-kenny: You want unsplice

13:19 ,`(do ~@(1,2,3))

13:19 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

13:19 the-kenny: Whoops

13:20 ,`(do ~@(map (fn [a] `(foo ,a)) '(1 2 3)))

13:20 clojurebot: (do (sandbox/foo sandbox/a) (sandbox/foo sandbox/a) (sandbox/foo sandbox/a))

13:21 the-kenny: gnah. Something like this :)

13:21 harja: the-kenny: wow, exactly what I was looking for

13:21 thanks!

13:24 the-kenny: Let's make it correct and nice: (let [syms (for [a (range 4)] (list 'foo a)) ] `(do ~@syms))

13:43 harja: the-kenny: Is this a good way to do this? https://gist.github.com/3200531 I'm just wondering about the eval-thing on the let form. I'm completely new to clojure and this macro thingy :)

13:44 the-kenny: harja: You almost never need eval. Let me take a look :)

13:44 why do you even eval notes?

13:45 harja: I need to get the result from executing the function (chord xx yy)

13:45 if I did not put eval, it did not work the way I wanted

13:45 it just mapped over the list (chord :A4 :major)

13:45 the-kenny: Why do you even use a macro there? :)

13:46 harja: Well, initially i tried (defn play-chord [ts chord] (at ts (map sampled-piano chord))) but it invoked it immediately

13:47 and then I tried (defn play-chord [ts chord] (map #(at ts (sampled-piano %)) chords)) but it did not work either

13:47 chords => chord

13:47 it just got played immediately I executed the play-chord -function

13:47 with the macro form, it works like it's supposed to

13:48 the-kenny: how do I get rid of the eval?

13:50 the-kenny: I think you want (defn play-chord [ts notes] (doseq [n notes] (at ts (sampled-piano n)))) :)

13:51 harja: ooh :)

13:51 works!

13:51 doseq... okay

13:51 hyPiRion: Hm.

13:51 the-kenny: doseq is like a "conventional" while-loop, running a piece of code with side effects for each element in 'notes'

13:52 harja: the-kenny: yeah, seems logical. Thanks a lot!

13:52 the-kenny: Your map-version most likely didn't work because lazy evaluation. doseq isn't lazy

13:52 harja: But, getting to the original problem, supposing I want to do something like that with a macro

13:52 is the eval necessary there? if it is not, how to overcome it?

13:52 hyPiRion: harja: I don't even think you need a macro here.

13:53 harja: well, supposing I want to generate code on the fly

13:53 the-kenny: hyPiRion: We had that already :) It's just theoretical now

13:53 harja: this is just purely hypothetical now

13:53 yes

13:53 hyPiRion: Ah.

13:53 the-kenny: harja: You could move the whole map-thingy into the code emitted by the macro itself

13:54 Ew, no. You couldnt :)

13:56 hyPiRion: One would usually take use of apply here.

13:58 Is overtone.live/at a macro?

13:58 harja: hyPiRion: yes

14:08 davidd`: hey guys, I'm confused about some terminology in clojure. what exactly is a form? is it just a list that's going to be executed e.g. (str "1" "2")?

14:09 or is str the form in this case?

14:09 jjido: davidd`: I think it is the list

14:09 davidd`: awesome. thank you jjido.

14:12 harja: hyPiRion: Do you mean I replace eval with something like (apply (resolve (first notes)) (rest notes))

14:17 hyPiRion: harja: If overtone.live/at was a function, you could have done (apply at (+ 1000 (now)) (map sampled-piano (chord :A4 :major7)))

14:17 Though since you're dealing with side-effects, the-kenny's solution seems more appropriate.

14:18 devn: isn't there an apply-at?

14:18 or something?

14:18 maybe im just remembering wrong hyPiRion

14:26 harja: devn: Yeah! Actually there is :)

14:26 Thanks for the info.

14:26 The overtone cheat sheet did not mention that

14:28 hyPiRion: devn: I've not used overtone, so don't ask me ;)

14:36 gfredericks: $findfn pos? [-1 1 -3 3] [[1 3] [-1 -3]]

14:36 lazybot: []

14:37 * gfredericks hmphs

14:38 Bronsa: (juxt filter remove)

14:38 gfredericks: yeah deffing that now

14:38 good point that's too short to def

14:38 Bronsa: it traverses the seq twice though

14:38 gfredericks: yep

14:38 so does split-with

14:39 Bronsa: if I am not mistaken there is a function in flatland/useful that does that without traversing it twice

14:39 gfredericks: I would be shocked if there weren't

14:39 this is cljs though so even if I weren't lazy that wouldn't be immediately helpful

14:40 Bronsa: useful.seq/separate

14:40 oh, ok

14:44 wingy: anyone here knows why i would wanna use https instead of http for fetching libs like jQuery et al

14:46 hyPiRion: wingy: ...security?

14:47 wingy: hyPiRion: but for a lib file?

14:48 what kind of things am i prohibiting an hacker from doing?

14:48 Natch: some browsers will whine if your main pages are over ssl and you fetch stuff unencrypted

14:48 might become a user issue if that's something you need to consider

14:48 wingy: Natch: whine how? as console.logs or does the user sees those warnings?

14:48 Spaceghostc2c: brainproxy: I've decided to start learning clojure. :D

14:49 wingy: Spaceghostc2c: (y)

14:49 Spaceghostc2c: Now to locate the thread in the mailing list about restricting reader macros.

14:49 Natch: wingy: you've never visited a site with mixed connections in firefox? I get those dialogues all the time about site trying to fetch stuff. or maybe it's just send.. might be just send

14:50 presto: wingy, the user does see warnings, yes.

14:50 wingy: ok

14:50 i guess https it is then

14:50 quite impressive how you have added security by just adding an "s" :)

14:51 Natch: well it will probably prevent someone snooping from knowing what you're doing

14:51 and inject stuff mand in the middle

14:51 :P

14:51 *man

14:58 hyPiRion: wingy: as Natch said, it'll reduce the possibility for man-in-the-middle

14:58 wingy: hyPiRion: so they cant manipulate the jQuery file im fetching?

14:58 gfredericks: right

15:02 Spaceghostc2c: Generally, I do most things over https. But if whatever I'm transmitting has nothing to do with authentication or anything remotely important, I'll use http.

15:03 hyPiRion: wingy: Well, it'll be harder, at least.

15:18 Spaceghostc2c: Can I use lein to keep leiningen up to date?

15:19 Natch: Spaceghostc2c: "lein upgrade"

15:19 cmajor7: is there a clojure lib that does registration/activation email thingy?

16:30 Frozenlock: How does one load a binary file in clojure? I tried slurp and spit for a simple copy, but the resulting file is not the same as the original :(

16:39 antares_: Frozenlock: JVM distinguishes between binary streams and character streams. Also, encoding setting matters, especially on OS X. Use http://clojuredocs.org/clojure_core/clojure.java.io and maybe https://github.com/Raynes/fs/

16:41 Frozenlock: Thanks a lot!

16:54 justin173: stupid question but is there an easy wat to get a current index of an item in the middle of a doseq?

16:57 devn: justin173: could you make it indexed first?

16:57 ,(map-indexed vector [1 2 3 4 5])

16:57 clojurebot: ([0 1] [1 2] [2 3] [3 4] [4 5])

16:58 justin173: yup that's exactly what i'm looking for thanks!

16:58 devn: yw

16:58 justin173: i swear I'm never going to fully learn the core api

16:59 devn: justin173: it takes some time to internalize it. it's easy to say: oh ill just use an atom! but usually, TAFFT (There's a Function for That)

17:00 justin173: devn: yeah at least I can sense when there's probably some stupidly simple solution to my issue so I can ask here :)

17:25 Frozenlock: Ok now I'm trying to print the byte-array I have, but instead it only prints "[B@44bcc9bd". Any advices?

17:25 I've tried both println and write method for my printstream.

17:33 aperiodic: huh, that's weird. it seems like its writing out the string representation of the byte array object, rather than its contents

17:34 antares_: Frozenlock: (String. ^bytes your-byte-array) creates a string from it

17:35 aperiodic: byte arrays do not have "string representation" beyond what Frozenlock has demonstrated

17:35 character arrays do but not byte arrays

17:35 but you can instantiate a string from a byte array

17:35 Frozenlock: Wait, I need to convert my byte-array to string?

17:36 antares_: if you want to print it as a string

17:36 if you want to treat it as a byte array, use what you have

17:36 but byte arrays do not have string representation that is human readable

17:36 Frozenlock: Not really, I want to write it as a binary file :s

17:36 aperiodic: antares_: maybe "string representation" is the wrong word, but i mean the string that says "there's an array of bytes at memory location 44bcc9bd"

17:37 antares_: byte buffers kinda do, (java.nio.ByteBufer/wrap …)

17:37 aperiodic: like what shows up in stacktraces

17:37 antares_: aperiodic: [B says "it is an array of bytes"

17:37 aperiodic: yeah

17:37 antares_: that's java.nio.ByteBuffer, of course (double f)

17:41 brainproxy: Spaceghostc2c: awesome, glad to hear it :)

17:42 I've been away from IRC for most of the weekend, leaving again now, but I'll be back on later tonight

17:42 I definitely recommend the O'Reilly book "Clojure Programming" -- good place to start, especially w/ your strong background in ruby

17:43 Frozenlock: That's odd.. I read a .jar file, zip it using the zipping utility, and I get a file twice as large as the original...

17:43 Damn you, file manipulation!

17:44 aperiodic: Frozenlock: (with-open [w (java.io.FileOutputStream. "foo")] (.write w (byte-array [(byte 33) (byte 35)]))) results in a file with just a shebang for me

17:48 guns: The destructuring form [& {:keys [a b] :or {a 1 b 2}] seems clunky. Are there downsides to simplifying that to [& {:keys {a 1 b 2}}]?

17:49 aperiodic: Frozenlock: if you want to do binary output, i think you want a FileOutputStream rather than a PrintStream; PrintStream seems to be designed to print string representations of data, which is probably why you were getting that "[B@..." nonsense in your output (note there's no print(byte[]) method for PrintStream)

17:49 botter: Can anyone here recommend good Clojure books, that they have actually used?

17:49 I have Java experience, but no functional programming experience at all.

17:50 Frozenlock: aperiodic: That makes sense. I mean, NOW that you have said it :P

17:50 botter: And I'm looking at The Joy Of Clojure, and Clojure Programming by OReilly

17:51 johnthejohn: As a programmer new to functional programming, what is the recommended way of learning Clojure?

17:53 guns: botter: Joy of Clojure assumes some familiarity with Lisp

17:53 botter: guns, do you have any experience with Clojure Programming?

17:53 mybuddymichael: I'm reading through Clojure Programming right now. It's better for the newbie than JoC.

17:54 guns: botter: I've heard the book by stu halloway is better if you don't have lisp experience

17:55 johnthejohn: Doing just the first chapter of SICP (in old MIT Scheme) goes a long way

17:55 cemerick: guns, botter: FWIW, we didn't assume any prior lisp experience.

17:56 botter: Ah! The author himself!

17:56 :D

17:57 cemerick: :-)

17:57 *co*author

17:57 botter: Also FWIW, to get a sense of what the objectives were: http://clojurebook.com

17:58 Raynes: cemerick, guns, botter: FWIW, none of the books assume prior Lisp experience. Where people get this stuff in their heads continues to elude me.

17:58 Frozenlock: aperiodic: It was indeed the PrintStream which was messing things up, thank you very much ^^

17:58 botter: Raynes, I assumed they did

17:58 Raynes: AFAIK, most Clojure programmers didn't come from a Lisp background.

17:58 botter: But I'm looking at Amazon's preview of Clojure Programming (the OReilly one) and it looks good

17:59 Frozenlock: Raynes: I come from an Emacs-lisp background :)

17:59 cemerick: Raynes: Quite; although I haven't bought the 2nd ed of PC.

17:59 Frozenlock: But Im no programmer so...

17:59 cemerick: so, I try to not say anything about it. :-)

17:59 * Frozenlock shuts up

17:59 guns: Raynes: maybe you'd agree that JoC is not a very gentle introduction

17:59 antares_: hey cemerick, hey Raynes

17:59 cemerick: are the state of clojure results ready yet?

18:00 Raynes: guns: It wasn't meant to be, but that certainly has nothing to do with requiring prior Lisp experience.

18:00 antares_: I am very curious about them :)

18:00 cemerick: antares_: coming sometime this week.

18:00 antares_: cool

18:00 cemerick: I may not actually read all of the comments this time. *Tonnes* of responses.

18:02 antares_: Raynes: I heard from monger today, it says it badly wants to be reviewed by a rad Clojure hacker. Bonus points if he/she is a southerner.

18:03 cemerick: do you know how many people approximately took the survey?

18:04 cemerick: I do, but don't want to spoil the surprise. :-)

18:04 antares_: ok, fair enough :)

18:04 cemerick: More than 2011, we'll say. ;-)

18:05 Raynes: antares_: I heard from my knuckles today. It says it really wants to be embedded in someone's face. Bonus points for Swedes.

18:06 In all seriousness, just haven't had a chance yet. I apologize. :(

18:07 antares_: it's a good thing I am not a Swede :)

18:21 jamii: First pass at a datalog compiler: https://gist.github.com/3202150

18:48 francis: (((:foo 0) ({:bar :baz} 1)))

18:48 (eval (((:foo 0) ({:bar :baz} 1))))

18:50 sorry, thought that the chatbot would evalute that. Anyway, why does this return a null pointer exception?

18:52 I realize that its this set doing it, and apparently it's getting evaluated as a funciton. Do sets always do this? do I have to quote everytime I end up with somthing like this? ({:bar :baz} 1)

18:54 arohner: ,({:bar :baz} 1)

18:54 clojurebot: nil

18:55 arohner: your real problem is:

18:55 ,(nil nil)

18:55 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0)>

18:55 arohner: (nil)

18:55 ,(nil)

18:55 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0)>

18:56 francis: I

18:57 'm confused (suprise!) why is that nil?

18:57 presto: ,(#{:meh} : meh)

18:57 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: Invalid token: :>

18:57 francis: The set fn (I'm assuming) would return the val at the passed index

18:57 presto: ,(#{:meh} :meh)

18:57 clojurebot: :meh

18:57 francis: ah

18:57 presto: ,(#{:meh} :bleh)

18:57 clojurebot: nil

18:58 francis: thanks

18:58 presto: Hash set. :=D

18:58 francis: nifty stuff

18:59 presto: ,([:meh] 0)

18:59 clojurebot: :meh

18:59 presto: ,([:meh] 1)

18:59 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

19:00 muhoo: ,(:meh #{:meh}) ;; also,too

19:00 clojurebot: :meh

19:01 francis: Sets have no order to them right? Hence the above functionality

19:01 presto: Yes. I prefer the other order though, are both clojurey?

19:01 ^ to muhoo

19:02 francis, yes, no guaranteed order, as far as I know.

19:02 muhoo: presto: i use both, depending on the context

19:03 presto: francis, well, there is sorted-set.

19:03 ,(sorted-set :meh :bleh)

19:03 clojurebot: #{:bleh :meh}

19:03 presto: ,(hash-set :meh :bleh)

19:03 clojurebot: #{:bleh :meh}

19:05 presto: ,(hash-set :b :c :a)

19:05 clojurebot: #{:a :c :b}

19:05 presto: ,(sorted-set :b :c :a)

19:05 clojurebot: #{:a :b :c}

19:05 presto: There we go. o-o

19:25 rbarraud: Hi arbscht

19:34 arohner: francis: (:foo {:foo 3}) is faster than ({:foo 3} :foo), in some circumstances

19:34 in defrecords primarily

19:34 so the usual advice is use (:foo map) everywhere

19:50 francis: noted.

19:52 Frozenlock: Raynes: your tests in `fs' require midje. Should it be added in the project dependencies?

20:05 gert: weavejester: your `secure-eql?` function in your (excellent) csrf ring middleware still leaks information about the length of the expected string (with the .length check at the beginning)

20:06 it's a bit paranoid to worry about that perhaps, but maybe it's good to be paranoid?

20:06 devn: anyone know of an existing solr-cell clojure lib?

20:06 weavejester: gert: Does that matter? I mean, people can look at the source code and find that out, and knowing that there are 60 bytes of random data doesn't really help an attacker much.

20:07 gert: true, in this case. I'm thinking about a more general string compare function where the length of a string might not be known outside the app

20:08 but good point - in this case it doesn't matter

20:46 * gfredericks keeps finding himself wanting currj

20:50 Raynes: Frozenlock: Midje is a dev dependency. It doesn't need to be a project dependency.

20:51 Frozenlock: Raynes: yeah just realized that... I wasn't in dev :(

20:55 Do you want a new pull request or you'll change it?

21:06 gfredericks: $findfn - [1 2 3] 1

21:06 lazybot: []

21:06 gfredericks: $findfn - 1 2 3 1

21:06 lazybot: [clojure.core/max-key clojure.core/cond]

21:07 gfredericks: huh; somehow have not heard of max-key and min-key before. surely clojure.core is endless.

21:42 Raynes: Frozenlock: You don't have to do another pull request. Just change this one (any changes made in your branch are reflected by the pull request). In fact, just remove the commit entirely and then do a force push to Github.

21:43 Frozenlock: Or, if all that seems complicated, I can just cherry pick around that commit.

21:43 Yeah, I'll just do that.

21:43 Frozenlock: Thanks! :)

21:43 Frozenlock: Thanks to you, I read 4 times what you said and was like "waaaaaa..."

21:43 One day, one day I'll understand git.

21:44 BTW you might want to take a look at the make-zip-stream. I use it with Noir to let users download stuff made on-the-fly, with nothing written to disk. Pretty cool :)

21:45 * emezeske hates people that force-push to public branches.

21:58 jcao219: $help

21:58 lazybot: You're going to need to tell me what you want help with.

21:58 jcao219: $help commands

21:58 lazybot: Topic: "commands" doesn't exist!

21:59 gfredericks: lazybot: you're going to need to do a better job indicating what you're capable of helping with

21:59 xeqi: $help list

21:59 lazybot: xeqi: Lists the available help topics in the DB.

21:59 gfredericks: $list

22:00 lazybot: I know about these topics:

22:00 gfredericks: those are some nice topics.

22:00 xeqi: lazybot is smart

22:00 gfredericks: lazybot: I know about all those topics too

22:23 estebann: quick question. why does this not work? (let [thesym "funngames"] (eval '(println thesym)))

22:24 gfredericks: eval doesn't use the local scope

22:25 estebann: that seems weird to me

22:27 gfredericks: the only justification I can think of is that the primary purpose for eval is loading code, and if it used the local scope you'd probably get unintentional shadowing for that use case

22:28 if you want to add some locals to an expression you can wrap it in a let before evaling

22:28 estebann: yeah, good point

22:30 presto: ,(let [thesym "funngames"] (eval `(println ~thesym)))

22:30 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

22:30 presto: Meh.

22:30 Anyway, what about that?

22:30 * presto pings estebann.

22:31 estebann: hmmm... possible, but I want the code that's going to be evaled to be easy to write

22:31 gfredericks: an eval-with-locals macro wouldn't be hard

22:32 emezeske: Presto, the second one you pasted should work fine

22:32 estebann: is there a way to access local bindings?

22:33 Raynes: emezeske: That's pretty unreasonable.

22:33 emezeske: There are situations where it is perfectly acceptable to do so.

22:33 gfredericks: well I was thinking explicitly given, but you could do the current local scope as well I think, using the &env variable accessible in a macro

22:33 Raynes: To fix a pull request that was issued 30 seconds ago is, in my opinion, acceptable.

22:34 emezeske: Raynes: Nah, it is a bad thing to do, all the time. Once it's public,anyone who has grabbed it gets screwed if you rebase or force push

22:34 gfredericks: emezeske: +1

22:34 emezeske: Raynes: Well, if you know for certain nobody has grabbed, sure

22:34 Raynes: But if you rebase or force a branch that someone else has already pulled, you are giving them grief

22:34 Raynes: emezeske: The odds that someone had grabbed some random branch of fs and had committed changes based on that tree is pretty ridiculous.

22:35 emezeske: Raynes: Doesn't matter if they committed, it is still grief to have a branch you're tracking get rebased

22:35 gfredericks: Raynes: you only need "having grabbed" not committing changes

22:35 Raynes: Silliness.

22:36 gfredericks: you'll likely not notice and end up merging every time you pull until you finally commit this parallel history

22:36 Raynes: I wouldn't have recommended he force pushed if it wasn't some random fork that was pushed minutes before on a project that nobody really cares about.

22:37 estebann: gfredericks: thnks for the suggestions

22:37 Raynes: But anyways, if anyone is ever mortally wounded by my actions in the future, please come forward and I will offer reparations in the form of sacrifice.

22:37 Frozenlock: "... that nobody really cares about" Oh, I see...

22:37 * Frozenlock cries in a corner

22:38 Raynes: Frozenlock: I was referring to the project, silly, not your contributions.

22:38 Frozenlock: I've been hoping someone would add zip.

22:38 emezeske: Raynes: Heh, you can do whatever you want on your project. All I did was state my hatred for rewriting history on public branches. :)

22:38 Tis but my opinion.

22:38 gfredericks: Frozenlock: clearly despite nobody caring about the project everybody loves your contributions to it

22:38 Frozenlock: lol

22:38 Yeah sure :p

22:38 gfredericks: actually I care about fs and have contributed to it

22:38 Frozenlock: My first pull request, so I'm proud.

22:39 Raynes: emezeske: Fair enough. I don't get it in this context, but meh.

22:39 You're still one of my favorite people. You had that paredit.vim repo.

22:39 Made me so happy.

22:39 emezeske: Raynes: You are one of my favorite people for convincing Tomas to bust out paredit from slimv for real. :)

22:39 <3

22:40 Raynes: <3

22:41 gfredericks: well I tried to contribute; apparently Raynes just did a big rewrite and obsoleted my contribution

22:41 Raynes: I did? :o

22:41 gfredericks: yeah but you did it conciously, because you closed the issue with the commit

22:41 Frozenlock: Oh in my case I wouldn't mind about that, as long as there's zip capabilities.

22:41 gfredericks: well I mind. I DID IT FOR THE GLORY.

22:42 Raynes: Oh, with-dir.

22:42 gfredericks: not only does nobody care about the library, but Raynes has bigger ideas for it than I do.

22:42 yeah with-cwd is a more internally consistent name

22:43 Raynes: gfredericks: Ah yes. It was actually because the fix for another issue was to make it all work differently.

22:43 gfredericks: I told my mother I was going to be in the commit history for fs. I don't know if I have the strength to tell her what really happened.

22:44 Raynes: I'm so sorry.

22:44 * gfredericks runs sobbing to his room

22:45 Hodapp: ...

22:50 muhoo: i'm kind of tired of getting clojurescript errors complaining about Could not locate clojure/instant__init.class or clojure/instant.clj on classpath:

22:51 casion`: I'm an an impasse in understanding

22:52 does iterate make a lazy sequence in the same way reduce works imperitively?

22:53 muhoo: ,(doc iterate)

22:53 clojurebot: "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

22:53 muhoo: hmm, says it returns a lazy sequence

22:53 and "free of side effects" seems kind of purely functional to me.

22:54 technomancy: FSVO "must"

22:54 uvtc: casion`: I don't know what you mean by "way reduce works imperatively". In what way does `reduce` work imperatively?

22:54 casion`: it evaluates immediately

22:55 uvtc: casion`: Right. The point of `reduce` is to keep evaluating until it gives you a single result in the end. Which is different from the functions that lazily return a list which you can realize at your liesure. :)

22:56 Gah. *leisure.

22:56 casion`: uvtc: I'm having difficulty grasping lazy sequecnes in general, but I get the concpet

22:56 just the application is bewilderring me, so I'm trying to make connections

22:57 muhoo: what application?

22:57 Frozenlock: I always get screwed by lazy sequences. In the REPL they print fine, but in the real world... Oh boy!

22:57 Raynes: Frozenlock: Pulled your stuff. Excellent work!

22:57 casion`: muhoo: I'm pretty bad at choosing words heh..

22:57 uvtc: casion`: There's a neat example of a creating a lazy sequence in the Clojure Prog (O'reilly) book. Oh, let's see ... where is it ...

22:58 muhoo: i wish there were a way to suppress evaluation of lazy seqs in the repl, to get a "real world" sense of where there may be dragons

22:58 casion`: application in the literal sense, not an 'app'

22:58 Frozenlock: Raynes: Yay!

22:58 casion`: noun form of apply

22:59 Raynes: muhoo: The dragons are in the house of the undying.

23:00 casion`: in the volkmann tutorial for instance, this line confuses me '(def f-seq (map f (iterate inc 0)))'

23:00 muhoo: Raynes: i wasn't making a game o thrones joke, but ok

23:00 Frozenlock: Raynes: How does github work in this case? Should I delete my forked repo?

23:00 Raynes: Frozenlock: You can. You don't have to.

23:00 uvtc: casion`: Ah, here we are. Page 94. There's a neat example, where, you create a lazy list by writing a function which wraps `lazy-seq` around `cons` of a value and the result of calling the fn again.

23:01 Raynes: Frozenlock: Your changes are now in my fork. That's how git works. One copy of a repo doesn't rely on stuff from another copy of that repo.

23:01 casion`: uvtc: that book arrives on tuesday for me

23:02 uvtc: casion`: That is, you ask it for the next value, and it produces the next one plus "whatever else comes after that which I haven't yet bothered to compute --- I'll compute it when you need it quit bugging me already">

23:02 :)

23:02 casion`: I'm mostly relying on the clojure docs and volmann tutorial while browsing other people's code

23:02 in the meantime

23:02 uvtc: I get that conceptually

23:03 but like the line '(def f-seq (map f (iterate inc 0)))' at http://java.ociweb.com/mark/clojure/article.html#Sequences

23:03 it's making a lazy sequence of a lazy sequence? or?

23:04 Raynes: iterate returns a lazy seq and so does map. Nothing happens until you start looking at items in the sequence returned by map. It'll start realizing the sequence from iterate.

23:05 casion`: what I think is happening is (iterate inc 0) is like a lazy sequence version of (range _), and it's using that as an argument to f, and that's mapped to the lazy sequence f-seq

23:05 Raynes: I wouldn't overthink it too much.

23:05 uvtc: casion`: here's the example from the book https://www.refheap.com/paste/3878

23:05 casion`: is that close to corrrect?

23:05 Raynes: range is lazy too.

23:05 casion`: is it?

23:05 Raynes: mhm

23:06 muhoo: well, if it wasn't, then your computer would hang when you do (range)

23:06 uvtc: The way it works is, if you just go ahead and call the function in the repl, the repl will try and realize the whole thing. So, that's no good. But,

23:06 casion`: why iterate there instead?

23:06 or would range work the same...

23:06 may as well trry

23:06 uvtc: Oh, sorry. I don't mean to cross wires.

23:06 * uvtc hangs on a sec. :)

23:06 casion`: uvtc: I'm following you

23:07 I can handle 2 conversations ;)

23:07 uvtc: casion`: Ah. I tend to be one-track minded in that way. :)

23:08 casion`: Anyhow, the way it works is this: if you call that function such that it doesn't need to return all the values at once,

23:09 casion`: it won't. It'll come up with the first rand-int,

23:09 casion`: but then just defer computing the rest until later on.

23:09 casion`: That is, if you only ask for one value from it, it will remain

23:10 casion`: suspended with something like `(cons 42 (random-ints 100))`, and not

23:10 casion`: so it need not be incremental?

23:10 uvtc: casion`: make that call to random-ints until you ask for more values.

23:10 casion`: ok let's see

23:11 ahem.. not in the repl I suppose

23:11 uvtc: casion`: That's the thing; the repl is a people-pleaser. :)

23:11 casion`: It wants to realize lazy lists so it can display them for you.

23:12 casion`: However,

23:12 casion`: ok, i just dod something wrong

23:12 did*

23:12 uvtc: casion`: Right. Sorry. I was too slow at typing: you shouldn't just call that function,

23:13 casion`: because it will just try to realize the infinite list and take over your repl. Sorry.

23:13 casion`: too late

23:13 uvtc: casion`: You can call it like so though, `(take 5 (random-ints 100))`,

23:13 casion`: and... time to restart emacs

23:13 uvtc: casion`: and it'll give you just 5 of the infinite list.

23:13 casion`: brb

23:13 uvtc: casion`: Oh shoot. Sorry about that.

23:14 casion: heh

23:14 well, obviously I didnt understand that well enough to not do that

23:16 uvtc: casion: Point is, the function returns a lazy infinite list, and so will generate items as you need them, for example,

23:16 casion: I think where I'm caught is how the sequence is evaluated

23:16 or stored

23:16 uvtc: casion: if you have a function that needs some values from it, `random-ints` will supply as many as it needs:

23:16 casion: orr both

23:17 uvtc: Ex: `(zipmap [\a \b \c \d] (random-ints 100))`

23:17 There, zipmap wants to create a map for you made out of zipping those keys and values.

23:17 `random-ints` supplies 4 values, because that's all that zipmap needs.

23:18 casion: ok

23:18 uvtc: The way that random int list looks as it's being evaluated looks something like this:

23:18 (50 (the rest))

23:18 Ooof. I mean:

23:18 (cons 50 (the-rest))

23:19 (50 (cons 39 (the-rest)))

23:20 (50 39 (cons 42 (the-rest)))

23:20 (50 39 42 (cons 28 (the-rest)))

23:20 And it only evaluates that cons when it needs the next one.

23:20 casion: ahh ok

23:21 I'm still getting used to the idea of immutable.. everything

23:21 uvtc: (where, `(the-rest)` is that call to `random-ints`. I probably should've written that instead of "the-rest")

23:21 casion: no, I got what you were saying

23:22 uvtc: casion: I'm not sure where the sequence "is stored" ... It's floating there in space waiting to be asked for more of its values. :)

23:23 The values you've asked for are "realized" (computed and made available).

23:23 casion: I have this need to have at least a basic idea of the implementation

23:23 or I feel like I don't understand it

23:24 uvtc: `(source lazy-seq)` ?

23:24 casion: yeah, i'm going through a few now

23:24 I just don't know enough clojure yet to grasp some of it

23:24 this is all a massive brainfuck to me

23:34 uvtc: casion: In that example you gave above, `(def f-seq (map f (iterate inc 0)))`; both the `iterate` and the `map` are lazy. `iterate` only generates values it's asked for, and same with `map`. So, if you ask for a value from the list --- say, (nth the-list 5), `nth` asks `map` to start walking through values 'til it gets to the 5th one, and it in turn asks `iterate` for values.

23:34 casion: so iterate just recurisively cons a result of f?

23:35 uvtc: (sorry -- replace "the-list" with "f-seq")

23:35 `iterate` just gives you f(x), f(f(x)), f(f(f(x))) , ... as you ask for them.

23:35 casion: doesn't it take the nth result from iterate, then map that?

23:36 uvtc: No, it has to work up to it. :)

23:36 casion: doesnt map need a collection though?

23:36 uvtc: `iterate` hasn't generated a list yet. It generates it as it's asked for values --- no sooner.

23:36 casion: so iterate would have to returrn first?

23:37 uvtc: No. `map` just needs something that's promised to look and act like a list. :)

23:37 casion: hmm

23:37 uvtc: AFAIU, it's a train of lazy functions. You ask `map` for the next one, and it asks `iterate` for the next one.

23:38 But if you ask here during eastern daylight time working hours, I'm sure the wizards will be able to explain exactly how it works.

23:38 casion: that doesn't make sense to me at all... I would think iterate needs to be evaluated first?

23:38 but I'm in no position to disagree heh

23:39 thank you very much though, you've made a lot more clear for me

23:39 uvtc: y/w. :)

23:43 xeqi: &(class (iterate inc 0))

23:43 lazybot: ⇒ clojure.lang.Cons

23:53 ivan: &(take 25 ((fn fibs [] (concat '(1 1) (lazy-seq (map +' (fibs) (drop 1 (fibs))))))))

23:53 lazybot: ⇒ (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025)

23:56 uvtc: ivan, what is +' ?

23:57 ivan: it's + with arbitrary precision

23:57 that is, supports adding a small and large number

23:57 uvtc: ,(doc +')

23:57 clojurebot: "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Supports arbitrary precision. See also: +"

23:57 uvtc: Hm. Didn't know you could use a single-quote mark like that.

23:58 Thanks.

23:59 Ah. You're mapping +' onto 2 collections: one shifted by 1 from the other...

Logging service provided by n01se.net