#clojure log - Oct 12 2009

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

4:27 LauJensen: Morning gents

4:53 AWizzArd: Hi the Lau.

4:57 adityo: Totally n00b question..in clojure how will i comapre two strings? eg. "Clojure" and "clojure"?

4:59 hoeck: ,(= "Clojure" "Clojure")

4:59 clojurebot: true

4:59 AWizzArd: adityo: http://java.sun.com/javase/6/docs/api/java/lang/String.html#equalsIgnoreCase%28java.lang.String%29

5:00 ,(.equalsIgnoreCase "cloJURE" "CLOjure")

5:00 clojurebot: true

5:00 hoeck: those were lower and uppercase C's in "clojure"?

5:01 adityo: yeah i dont want to Ignore case?

5:02 hoeck: adityo: then use =

5:03 adityo: okie..is it equivalent to java equals

5:04 hoeck: adityo: yes, = uses equals under the hood

5:07 adityo: stated in the doc of =, try: (doc =)

5:08 adityo: hoeck: yes i did check it out, thanks :)

5:15 triyo: I have a string that contains 2 forms "(print (+ 2 1) (print (- 2 1))". The read function seems to be able to read the forms from the Reader however it seems to only grab the first form. Am I missing some iteration spec to get the next form from my string reader?

5:16 ambient: you're parentheses are unequal

5:16 *your

5:16 triyo: Sorry typo in this message

5:20 hoeck: triyo: are you using the read-string function?

5:20 triyo: ,(-> "(print (+ 2 1)) (print (- 2 1))" java.io.StringReader. java.io.PushbackReader. read)

5:20 clojurebot: (print (+ 2 1))

5:20 triyo: Using read

5:20 As above

5:20 hoeck: triyo: read only reads one object at a time

5:21 to read in the whole string, either wrap it into a seq by using iterate

5:22 triyo: Ok I'll try that

5:22 hoeck: or wrap the string in parens using (str "[" your-string "]") and read that

5:22 Chousuke: don't forget that read-string exists :)

5:23 hoeck: ,(read-string "first second")

5:23 clojurebot: first

5:23 hoeck: ,(read-string (str "[" "first second" "]"))

5:23 clojurebot: [first second]

5:26 triyo: Thx hoeck, that'll work for me.

7:12 ambient: anyone know of the fate of Counterclockwise (clojure eclipse plugin)?

7:12 where would i get the latest, seems that it only supports clojure 1.0.0 and i need to use a newer platform

7:12 ~ccw

7:12 clojurebot: ccw is http://github.com/laurentpetit/ccw

7:15 ambient: not sure who maintains it and is it even actively developed

7:18 rsynnott: isn't there another eclipse plugin?

7:21 ambient: clojure-dev was the original, but it was renamed to counterclockwise

7:31 cgrand: ambient: Laurent Petit (lpetit here) is actually the main developer

7:45 AWizzArd: I have one agent A and many threads which do (send A foo). foo must not threadsafe. The queue of A helps to serialize my requests. Each thread does the (send A...) and then (await A), to get the result. But now the question is how I can (deref A) so that I will get the result which was produce for the current thread.

7:45 What I currently do is (let [x (atom nil)] ... (send A foo x) (await A) and have foo writing its result to x, and then I can work with @x.

7:46 foo must not threadsafe ==> foo is not threadsafe

7:47 cgrand: is there something like await which also returns the result of the agent?

7:50 cgrand: AWizzArd: clojure 1.0 or 1.1?

7:50 AWizzArd: a fresh master

7:50 so, 1.1 i would say

7:51 my *clojure-version* ==> {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "alpha"}

7:51 cgrand: good! you can use a promise instead of an atom, thus you'll don't have to await, just @my-promise (it will block)

7:52 or get rid of agents and use futures with you own executor

7:52 AWizzArd: ah okay, never heard of promises before.. is there already a doc page set up?

7:52 cgrand: I dunno

7:52 AWizzArd: is the promise the replacement for the agent or the atom or their combination?

7:53 cgrand: promises are simple: (def p (promise)) to create, (deliver p value) to set, @p to block and get

7:54 do you _really_ need to proces the returned value on the same thread that dispacthed the action to the agent?

7:55 AWizzArd: It is a thread which jetty/compojure opens and which handles the request.

7:55 cgrand: ok

7:55 AWizzArd: My processing function may run in parallel, and i want the result in the same thread, so i can generate a response.

7:56 The await makes sure that the thread will wait for the (send ..) which I did just one line above, right? I can not accidently await that A returns from a different thread?

7:57 cgrand: await awaits that actions dispatched from the current thread are executed

7:58 AWizzArd: ok good

7:58 and btw, what is the advantage of a promise over an atom?

7:58 cgrand: atom+await ~= promise (in your use case)

7:58 no explicit await

7:58 AWizzArd: well, I have a agent+atom+await

7:59 cgrand: agent+atom+await ~= agent+promise :-)

7:59 AWizzArd: okay good, I will test that - sounds good

8:00 cgrand: (let [x (atom nil)] ... (send A foo x) (await A) (do-something @x)) becomes (let [x (promise)] ... (send A foo x) (do-something @x))

8:02 AWizzArd: yes, I am doing this now, thanks for this tip

8:02 didn't know this promise thing

8:05 adityo: how to convert a string to a number for eg. "2" to 2

8:06 eevar2: (Integer/parseInt "2")

8:07 adityo: hey thanks eevar2

10:09 octe: has anyone used clojure-install to set up slime/swank/clojure recently?

10:09 it seems it sets up the swank-clojure-jar-path variable, but the latest swank-clojure doesn't use it anymore..

10:28 ambient: is git integration in emacs ok+

10:28 or would it be better to use it from command line

10:29 (ok this was perhaps too off-topic)

10:30 liwp: ambient: AFAIK there is no git integration in emacs out of the box

10:30 ambient: there is magit, which apparently works ok, but I haven't tried it myself

10:30 noidi: http://zagadka.vm.bytemark.co.uk/magit/

10:31 liwp: noidi: have you used it?

10:31 noidi: I only installed it a few days ago so can't really comment on it yet

10:32 froog: there's a good magit introduction video here: http://www.vimeo.com/2871241

10:32 liwp: I've never used SCM tools from emacs. Some people seem to love the VC-mode integration though. AFAICT it works on a per file basis which seems a bit weird to me, i.e. my commits tend to span more than one file and I'd like those changes to show up as a single commit

10:32 but I've probably misunderstood something...

10:34 ambient: i'd rather use mercurial but git seems to be de facto standard for open source devs, and gaining momentum a lot faster :/

10:36 Raynes: Git is the chit.

11:02 durka42: anybody know why there is no clojure package for debian lenny?

11:04 LauJensen: durka42, debian :P

11:04 durka42: i suppose clojure is not considered "stable"

11:15 ambient: the same code works from command line "java clojure.main gears.clj" but not from emacs using C-c C-k :(

11:16 "could not locate penumbra/opengl__init.class or..."

11:16 LauJensen: ambient, which OS are you on?

11:16 ambient: vista

11:16 LauJensen: aha... and you say you're having problems.... :)

11:17 ambient: i dont have much choice in the matter

11:17 LauJensen: Is it still the LIBRARY_PATH tripping you up ?

11:17 ambient: i have no such thing defined in my env vars

11:18 LauJensen: we can talk in priv if u need help

11:28 chouser: huh, I didn't know this... http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

11:28 octe: i have a vector containing vectors with 2 elements in each one.. i want to create a hash-map from this

11:28 i'm not even sure where to start

11:29 chouser: octe: (apply into {} your-vector)

11:29 wait

11:29 ,(into {} [[1 2] [3 4] [5 6]])

11:29 clojurebot: {1 2, 3 4, 5 6}

11:29 chouser: there you go -- no apply

11:30 octe: cool, now i'm just wondering what the , does :)

11:30 dreish: chouser: Not that I'm endorsing double-checked locking, but the first objection they raise doesn't apply if all fields are final.

11:30 noidi: chouser, cool! :)

11:31 dreish: You can never see a "pre-initialized" value of a final field.

11:31 noidi: I ended up with: (into {} (map #(apply hash-map %) [[:foo 1] [:bar 2]]))

11:31 plenty of clojure idioms to learn :P

11:31 chouser: octe: , is whitespace in clojure -- , in IRC tells clojurebot to do it.

11:31 octe: oh..

11:31 i thought it meant something special

11:31 chouser: just here

11:31 ,(+ 1 2)

11:31 clojurebot: 3

11:33 noidi: ,(conj {} [[:foo :bar] [:baz :blah]])

11:33 clojurebot: {[:foo :bar] [:baz :blah]}

11:33 noidi: wow, I didn't know that conj is so flexible

11:33 ,(conj {} [:foo :bar])

11:33 clojurebot: {:foo :bar}

11:33 noidi: eh, it wasn't :)

11:34 chouser: noidi: you understand your first example made a vector key?

11:34 noidi: yeah, i see it now

11:34 chouser: ,(apply conj {} [[:foo :bar] [:baz :blah]])

11:34 clojurebot: {:baz :blah, :foo :bar}

11:34 chouser: but don't do that. Use into.

11:36 This surprises me a bit:

11:36 ,(conj {} {:a 1, :b 2} {:c 3, :d 4})

11:36 clojurebot: {:d 4, :c 3, :b 2, :a 1}

11:38 octe: http://pastebin.ca/1615642 <- so this is a good way to do what i want? (parse line with fields seperated by ":" and their key/value seperated by "=" and turn it into a map)

11:38 froog: ,(into {} [[1 2] [3 4] [5 6]])

11:38 clojurebot: {1 2, 3 4, 5 6}

11:39 froog: what version is clojurebot running?

11:39 I get: {5 6, 3 4, 1 2}

11:40 chouser: froog: map order isn't generally guaranteed, so it shouldn't matter to you which you get. I happen to get the same as clojurebot on latest master.

11:42 octe: yep, looks good. you might want to take advantage of #() and the more modern (.method obj arg) interop form

11:43 dreish: as it mentions, though, there are more and more reasons it doesn't work. for example is the pointer assignment atomic?

11:43 durka42: is pastebin.ca dead or is it just me?

11:44 dreish: Like I said, I'm not claiming double-checked locking is okay.

11:44 froog: chouser: that makes sense. Still, would've expected the output to have been the same

11:44 octe: chouser: thanks

11:45 chouser: froog: yeah, I'm surprised by your output. what version are *you* running? :-)

11:45 octe: #().. more magic ungoogable symbols ;) (found the docs on clojure.org though)

11:45 froog: chouser: "1.0.0--SNAPSHOT"

11:45 ,(clojure-version)

11:45 clojurebot: "1.1.0-alpha-SNAPSHOT"

11:47 chouser: octe: and even more: ->> can be used here (though not sure if it's better than without it)

11:47 that's not even on clojure.org yet. :-/

11:48 ,(let [line "version=123:foo=bar:something=moo"] (->> (.split line ":") (map #(vec (.split % "="))) (into {})))

11:48 clojurebot: {"version" "123", "foo" "bar", "something" "moo"}

11:55 * cgrand just realized that Clojure is 2yo at the end of this week

11:56 froog: is 1.1.0 going to be a bugfix release?

11:57 morphling: hi, is there a way to get the argument count of a #(...)-created function?

11:58 I found (count (first ((meta #'foo) :arglists))), but that does not seem work on anonymous functions created by #() or (fn)

12:00 technomancy: cgrand: party time!

12:02 cgrand: morphling: no, you can't get the argcount of a function. What are you trying to do?

12:03 djork: I'm using Aquamacs and it seems like clojure-install from clojure-mode fails to "stick"

12:03 not sure why

12:03 technomancy: djork: did you follow the note at the end of the install process?

12:03 djork: I think so

12:03 (can't remember)

12:04 morphling: cgrand: I'm trying to print a truth table for a boolean function, it would be nice you did not have to specify the argcount explicitly

12:05 chouser: froog: depends on what you mean I guess -- lots of new features coming.

12:06 morphling: you can introspect on the invoke methods of the class created, but it's definitely a hack

12:08 cgrand: other hack: try to call the function and catch the exception when you call with an unsupported argcount

12:08 djork: technomancy: yup, I missed it :)

12:08 that was easy

12:09 <3 swank-clojure and clojure-mode... now that it works every time :D

12:10 morphling: I actually thought of the latter but it's not worth the hacks

12:10 noidi: ,(doc partial)

12:10 clojurebot: "([f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more]); Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args."

12:10 noidi: morphling, maybe that could work for you?

12:11 ,((partial str "foo") "bar" "baz")

12:11 clojurebot: "foobarbaz"

12:12 noidi: oops, i didn't even understand the question properly

12:12 maybe i'll just shut up and call it a day :)

12:25 technomancy: djork: most of the problems people have are missing that notice... I think I might automate the process of adding it to your config.

12:25 djork: it should just be on a separate line, like the "run M-x slime" line

13:03 froog: ,(into {} [[:a 1] [:b 2] [:a 43]])

13:03 clojurebot: {:a 43, :b 2}

13:37 raek: how do I do the dissoc counterpart to assoc-in ?

13:38 nevermind, found clojure.contrib.core/dissoc-in

13:42 ambient: so, did anyone at any point complete the translation of Minilight (ray tracing engine) to Clojure?

13:42 there seem to have been several attempts

13:44 djork: hmm, it appears that Clojure is not suited to serving up dumb cgi scripts :)

13:45 (s/Clojure/Java)

13:47 drewr: not if you'd like to exceed >1 req/s

13:57 funkenblatt: yeah... wouldn't that have to restart the jvm process every time?

14:04 drewr: funkenblatt: yep

14:06 chouser: you at *least* need fastcgi or equiv, and it's hard to find a context where that's a better fit than jetty or some other servlet container.

14:07 LauJensen: funkenblatt, if your only problem is start/stopping the JVM, just use Nailgun

14:07 funkenblatt: heh... not MY problem per se

14:07 but i'll keep that in mind

14:07 drewr: do you guys know if there is a fs-backed version of LinkedBlockingQueue?

14:08 thinking about writing one, but not sure if it's solving the right problem

14:09 I need somewhere to stash data while I process it, but I don't want the heap to fill up

14:09 licoresse: ...

14:11 chouser: drewr: seems pretty reasonable. I think several message-passing libs provide disk buffering

14:11 except I'm probably using all the wrong terminology because I still don't know anything about them. :-)

14:11 drewr: yeah, looks like jms et al have similar func

14:12 wanted something lighter weight than that, but it's not a trivial solution

14:24 raek: I am amazed how simple it is to make a simple event-driven system!

14:24 http://gist.github.com/208575

14:25 technomancy: drewr: rabbitmq is great at that.

14:25 raek: clojure is the only language I've been using where my code actually shrinks in size the more I work on it

14:25 Chousuke: heh

14:25 raek: now: begin coding on irc bot

14:25 Chousuke: hack on Clojurebot :P

14:26 technomancy: clojurebot's nontrivial to set up and hack on. =\

14:26 chouser: raek: that's pretty tidy. I love how all of the code (except the example usage) could be used as-is on any reference type, not just an agent.

14:28 djork: "how simple it is to make a simple ..."

14:28 it always is :)

14:28 chouser: raek: depending on how you intend to use it, you might also consider multimethods instead.

14:28 djork: now make a complex one :P

14:29 raek: chouser: in what way?

14:29 I want to be able to have multiple event handlers

14:30 drewr: technomancy: yeah, we're already using that in our infrastructure, although I wanted to solve this problem inside one jvm

14:31 * raek take a look at clojurebot's code

14:31 drewr: raek: clot has the beginnings of what you want

14:31 hiredman: technomancy: :(

14:32 clojurebot: be simpler

14:32 clojurebot: It's greek to me.

14:32 technomancy: hiredman: well, at the time I tried it, fnparse was totally nonfunctional.

14:32 hiredman: yeah

14:33 technomancy: probably has improved since then

14:33 hiredman: I have had thought perhaps hitching clojurebot's star to fnparse's wagon was not the wisest move

14:33 technomancy: still though, until you get the deps situation improved, recommending it for a newbie to hack on is questionable

14:33 hiredman: yes

14:38 chouser: raek: ah, good point -- multimethods are probably not a good fit then.

14:43 adityo: can anybody provide an example of using sort-by with an comparator?

14:46 ping

14:46 Chousuke: hm

14:47 ,(sort-by count > [[1] [1 2] [1 2 3]])

14:47 clojurebot: ([1 2 3] [1 2] [1])

14:47 Chousuke: like this?

14:48 adityo: yeah, sort-by by default returns in an ascending order

14:49 Chousuke: the docstring is pretty clear

14:50 LauJensen: Speaking of clear, is there some work being put into those backtraces?

14:50 adityo: yep, it is

15:53 ambient: how do i know after which operations i can still use the function lazily?

15:53 for example, does into-array break the laziness?

15:54 chouser: into-array is greedy

15:54 I think everything lazy says it is.

15:55 ambient: eg. range doesn't say it is lazy, nor does map

15:59 Chousuke: ,(doc map)

15:59 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

15:59 ambient: i can define oscillators as infinite sequences :))

15:59 Chousuke: third word. :P

15:59 ambient: hmm, ok i see

16:08 hiredman: if the sequence interface allows it to be lazy, it is

16:08 ambient: (audiochan-play source (into-array Byte/TYPE (take (msec-samples 500) (sin-osc 440.0)))) this works

16:10 i'll see if i can do the whole synth framework lazily

16:10 IIR filters might be a PITA thou

16:13 funkenblatt: there's a recursive sequence thing in clojure-contrib

16:13 that'll do IIR filters

16:13 ambient: sweet

16:16 adityo: how do i remove all nil's in '(1 nil 3 nil 6 nil nil)

16:17 funkenblatt: ,(filter identity '(1 nil 3 nil 6 nil nil))

16:17 clojurebot: (1 3 6)

16:17 adityo: .(doc identity)

16:17 Chousuke: identity does nothing :)

16:17 adityo: ,(doc identity)

16:17 clojurebot: "([x]); Returns its argument."

16:18 Chousuke: a better way would be (remove nil? ...)

16:20 adityo: thanks :Chousuke :funkenblatt

16:26 arohner: Chouser: I asked this question the other day, but I don't think you were around

16:27 in Clojurescript, how do you determine whether a form is a javascript memeber access vs. function call?

16:27 i.e. (. foo bar) turns into "foo.bar()" or "foo.bar"?

16:28 Chousuke: is clojurescript actually functional? :/

16:30 raek: ,(into {} '([:a 1] nil [:b 1] nil))

16:30 clojurebot: {:a 1, :b 1}

16:34 arohner: Chousuke: sort of

16:34 I'm asking because I'm trying to figure out how to handle it in scriptjure

16:34 and javascript cares about the difference between foo.bar and foo.bar()

16:35 Chousuke: does it have static fields like java though?

16:35 arohner: what do you mean by static?

16:36 Chousuke: I mean, if javascript doesn't need it, maybe you could use the Foo/bar notation to differentiate

16:36 arohner: yeah, but so far scriptjure's semantics are largely the same as clojure's

16:37 Foo/bar in clojure can be a variable access or a function call

16:37 which it can do because it can know the type of bar

16:38 if I want to do that, I have to add a check in the generated code

16:38 Chousuke: hmmh :/

16:39 the conceptually valid choice would be to require users to write ((.foo bar) args) but that's not very neat

16:39 arohner: right

16:43 the other thing that's interesting is that in javascript, foo.bar could be a function, so you could want to return the function. you can't do that in Clojure, so that's something else I have to worry about

16:45 Chousuke: hm

16:46 lpetit: ,*clojure-version*

16:46 clojurebot: {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "alpha"}

16:46 Chousuke: I really can't think of any other way than restricting (.foo bar) to be field access only

17:49 itistoday: is it possible to create lexical closure with 'with-local-vars'?

17:49 i.e., I'm trying to see if it's possible to avoid using atoms to create a counter-generator. no practical reason, just an exercise

17:49 this is what i have so far:

17:49 (defn new-counter [] (with-local-vars [a 0] (fn [] (var-set a (inc @a)))))

17:49 and it doesn't work

17:51 yes, i know that code is probably in terrible form ;-)

17:56 ambient: is there a way to polymorphically handle sequences and numbers (floats, integers, etc..)? like (* 10.0 (repeat 5.0))

17:57 vectors and matrices wouldbe gravy

18:05 morphling: ambient: (map (partial * 10.0) (repeat 5.0)) ?

18:05 ambient: the point is that i dont want to use map

18:06 because im using map on every damn line :/

18:06 if * / + - would be polymorphic, my code size would dramatically lessen

18:06 morphling: ah

18:06 ambient: and all basic functions that work on one numeric input

18:06 like sin, cos etc

18:07 perhaps i should write equivalent macroes that just wrap all numbers to (repeat foo)

18:10 simple frequency modulation looks like this: (take 15000 (sin-osc (map + (repeat 440.0) (sin-osc (repeat 100.0)))

18:11 when it could be (sin-osc (+ 440.0 (sin-osc 100.0)))

18:16 itistoday: is it possible to create lexical closure with 'with-local-vars'?

18:17 i.e., I'm trying to see if it's possible to avoid using atoms to create a counter-generator. no practical reason, just an exercise

18:17 this is what i have so far:

18:17 (defn new-counter [] (with-local-vars [a 0] (fn [] (var-set a (inc @a)))))

18:17 it doesn't work though (java.lang.IllegalStateException: Var null/null is unbound.). Yes, I also know that it's probably in bad for, but i was just wondering if it was possible

18:18 it could be thread-safe though if the function were only used in a single thread :-)

18:19 Licenser_: itistoday: everyting is thread safe when only used in a single thread :P

18:20 itistoday: Licenser_: indeed, and that's kinda an interesting point, because Clojure doesn't seem to offer optimizations for that case...

18:20 Licenser_: I know, but it

18:20 I know, but it's a tradeoff for the fact that we get thread safety for most of everything for no extra work ;)

18:22 itistoday: it would be cool though if you could bind a function, or an "instance" of a function to a specific thread. that would be a neat optimization, and a sort-of "best of both worlds" approach i think

18:22 but i have a feeling that the mindset of clojure is "we don't want you shooting yourself in the foot accidentally"...

18:23 it might be possible to ensure thread-safety though. sortof how you can't use set! except in (binding ..)

18:23 technomancy: you can use alter-var-root outside of binding, but it's almost always the Wrong Thing to Do.

18:24 itistoday: technomancy: thanks, didn't know of that function

18:24 why then are there atoms?

18:24 danlarkin: unless you're using with-alter-var-root!!!

18:25 itistoday: that's another thing i'm having difficulty understanding, is the point of atoms

18:25 or perhaps the point of vars.

18:25 (i.e. use atoms everywhere instead of vars)

18:27 gbj: i love with-alter-var-root!!

18:27 danlarkin: gbj: you would!

18:27 itistoday: what is the reasoning to have atoms and vars as opposed to just one of them?

18:28 danlarkin: itistoday: vars are threadlocal

18:28 itistoday: danlarkin: what about vars bound to the root?

18:28 with def?

18:29 are they threadlocal?

18:29 kib2: Hi; is there any way to repeat a string a given times ?

18:30 itistoday: quiet day?

18:31 danlarkin: well it's more nuanced than vars just being threadlocal

18:31 itistoday: kib2: (repeat 4 "foo") ?

18:31 danlarkin: bindings are thread local

18:31 itistoday: sure, bindings are threadlocal, but does that make vars threadlocal? i don't think they are

18:32 kib2: itistoday: so simple! I was looking for java solutions! thanks.

18:32 itistoday: and as technomancy pointed out, you have alter-var-root

18:32 which seems very similar to set!

18:32 rhickey: taskete! save me!

18:33 technomancy: dude.

18:33 no offense, but I think Rich has more important things to do than explain this to you.

18:33 danlarkin: +1

18:33 itistoday: technomancy: probably, couldn't hurt to ask though?

18:34 if he didn't want to be bugged would he be on this channel?

18:34 :-)

18:35 chouser: vars are what namespaces intern

18:35 danlarkin: every time rich answers a question in IRC he's not accepting technomancy's patches :)

18:35 chouser: hehe

18:36 itistoday: chouser: i guess i'm asking, why have vars and atoms? why not just have one of them? and aren't symbols interned, not vars?

18:37 chouser: itistoday: symbols are not interned

18:38 itistoday: chouser: i'm reading through clojure.org/vars and i don't quite get it

18:38 chouser: itistoday: a namespace holds a bunch of named vars because that provides useful semantics for named globals with optional thread-local dynamic scope

18:39 atoms provide no thread-local or dynamic scope, but use fast CAS to make changes to the value they store.

18:40 itistoday: chouser: and they are also not named...?

18:40 and by that meaning they are not "interned"?

18:40 chouser: that's true, though the fact that vars know their own name (if any) may be more of an implementation detail.

18:41 octe: is there a repository for clojurebot's code?

18:41 itistoday: chouser: i suppose being more anonymous does give them a unique use

18:42 chouser: and the fact that vars, unlike atoms, can be used with 'with-local-vars'

18:42 chouser: itistoday: interned I think in this case means that there is a single place for each named var -- if you do (def foo) two different times in the same namespace, there will still be only the one var

18:42 with-local-vars is how you can create anonymous vars -- an *extremely* rarely used feature afaik

18:43 itistoday: ahhhh, so both atoms and vars can be anonymous

18:43 but vars... unlike atoms, can be "non-anonymous"... eh...

18:43 my head hurts

18:43 i guess the main thing is that atoms are always global

18:43 or rather, always "shared data" CAS stuff

18:44 and vars are less likely to be mutated

18:44 and can be local

18:44 chouser: get-var/set-var do not use CAS, correct?

18:44 chouser: itistoday: correct -- I believe they use a lock on the var

18:45 itistoday: a lock??

18:45 technomancy: itistoday: clojure existed for quite some time without atoms... if you're just getting started it would probably be easier to just ignore them and focus on refs and functional code first.

18:45 chouser: ,(.sym (var *print-length*))

18:45 clojurebot: *print-length*

18:45 chouser: ,(with-local-vars [x 5] (.sym x))

18:45 clojurebot: nil

18:45 itistoday: neat

18:45 chouser: are you sure they use a lock?

18:45 chouser: itistoday: so there is a named vs. an anonymous var

18:45 itistoday: why would they use a lock?

18:46 chouser: itistoday: just for you, I'll check.

18:47 danlarkin: itistoday: clojure itself has lots of locks. The point is that it has them so you don't have to

18:47 itistoday: chouser: sorry, you don't need to trouble yourself for me

18:47 chouser: but if you do i'm thankful!

18:47 danlarkin: well let me rephrase that... not "lots of locks", but it uses locking

18:47 chouser: itistoday: var-set is thread local, so there are no locks or anything there.

18:48 itistoday: chouser: that's what i thought, which is why i was shocked when you said it

18:48 chouser: itistoday: alter-var-root is a sychronized function, so it's essentially a lock.

18:48 itistoday: chouser: that's also good to know... although i think someone said it was CAS

18:48 chouser: atom is CAS

18:49 if it helps, here's how I think of them...

18:49 vars are how you build up the global definition of your program, but using them to store functions and configuration type values in namespaces.

18:50 on rare occasions it's useful to give a particular var a thread-local binding, perhaps to tweak the definition of a function or adjust one of those config values

18:51 they can be used in other ways, but it's hardly ever a good idea

18:51 I would not recommend storing any of your applications actual state in a var, for example.

18:52 atoms on the other hand are the very simplest way to store application data

18:52 itistoday: instead store it in an atom? or a ref?

18:52 chouser: right, or an agent

18:52 itistoday: gotcha

18:53 ambient: anyone know how i could make this into an actual infinite sequence? http://paste.pocoo.org/show/144606/

18:53 seems that (iterate inc 0.0) can't be infinite

18:53 at least performance wise

18:53 chouser: although both atoms and vars overlap in a subset of their technical feature support, I've never had any trouble choosing between the two for any particular purpose.

18:54 itistoday: chouser: thanks, that helps a bit

18:55 chouser: ambient: few things have infinite performance

18:55 :-)

18:55 sorry, I guess I don't know what you're asking.

18:55 ambient: what i meant that eventually it will jump into bignums and the program will DIE

18:55 chouser: ah

18:55 itistoday: chouser: the other day Chousuke helped me with a function i was trying to write, here it is: (defn new-counter [] (let [a (atom 0)] (fn [] (swap! a inc))))

18:56 ambient: because oscillators are by definition looping inside a defined waveform, im just trying to find out how to do an infinite stream of sin oscillator

18:56 which can be modulated by frequency

18:56 itistoday: chouser: (defn c (new-counter)) (c) => 1 (c) => 2, etc. Is there a way to do that instead with with-local-vars or is that not possible?

18:56 chouser: i.e. i tried this and it failed: (defn new-counter [] (with-local-vars [a 0] (fn [] (var-set a (inc @a)))))

18:57 chouser: itistoday: right, vars aren't for that.

18:57 ambient: perhaps i should give up this stream based approach and just start managing global state :|

18:57 chouser: ambient: wait wait

18:57 :-)

18:57 itistoday: chouser: k, thanks!

18:58 chouser: ambient: could you use bignum for all of them?

18:59 ambient: i'd rather not use bignum anywhere, because afaik it kills performance

19:00 here's the full app. im not sure my approach is the right one http://paste.pocoo.org/show/144608/

19:00 chouser: well, at some point your float is going be out of precision such that adding 1 to it wouldn't produce any different number if it were still a float.

19:00 what would you like it to do at that point?

19:01 ambient: i just want to loop between 0 and PI * 2

19:01 but twisting my brain around how to do that with streams, especially with phase and frequency modulation is just too much

19:02 itistoday: ambient: what does the function (or macro) 'do' do? i couldn't find it in the api

19:02 (looking at your paste)

19:03 ambient: it does, sequentially

19:03 :p

19:03 itistoday: ,(doc do)

19:03 clojurebot: Pardon?

19:03 itistoday: why isn't it in the API?

19:03 chouser: itistoday: do is a special operator, like if

19:04 itistoday: chouser: ah, ok. hopefully i'll stumble upon an explanation on the clojure site

19:05 found it: http://clojure.org/special_forms

19:05 chouser: itistoday: http://clojure.org/special_forms#do

19:05 :-)

19:05 itistoday: hehe :-)

19:05 it's like prgn?

19:05 (or 'begin' in other languages)

19:05 chouser: ambient: do you need to be able to change the frequency during the course of the oscillation?

19:05 ambient: chouser yes

19:07 itistoday: ambient: sorry to bother, but if 'do' is like begin/prgn, why do you use it in audiochan-close/audiochan-play? doesn't defn allow you to not use it?

19:07 ambient: itistoday yes, probably

19:07 itistoday: ambient: ah k, just wondering, guess it's a matter of style

19:08 ambient: nah, it's completely redundant

19:08 itistoday: i wasn't going to say it ;-)

19:08 ambient: you're not clearly finnish

19:08 itistoday: :)

19:14 ambient: i think there's no going around it, oscillator has to have state

19:14 chouser: ambient: how will state help?

19:14 ambient: it will define at which point the oscillation is

19:14 which can then be phase modulated, and checked against limits

19:14 chouser: ambient: personally, I'd try bignum first since it's so easy. if the performance is unacceptiable, then take another look.

19:17 ambient: with state i can just do new_phase = (old_phase++)%256 in some old arcaic language, which keeps the oscillation inside 0..255

19:17 oops ++old_phase

19:18 immutability has corrupted my mind. it's phase = (++phase) % 256 of course

19:18 chouser: ah, that kind of "state" isn't so bad -- you can still use that to produce a lazy seq and therefore remain purely functional.

19:19 ambient: hmm i dont know how

19:19 chouser: seq-utils/reductions is one way to produce a lazy seq where each new value depends on the previous value.

19:19 ambient: because i have to modulate the phase delta

19:19 ok i'll check that out

19:19 chouser: but in this case it's probably easiest to use the lazy-seq macro directly

19:20 I hope lazy sequences themselves aren't too slow for your application.

19:20 ambient: yeah, we'll see

19:21 itistoday: what happened to lazy-cons?

19:21 chouser: itistoday: gone the way of all dinosaurs

19:21 funkenblatt: sleeping with the garbage collected fishes

19:21 itistoday: is lazy-seq its replacement?

19:21 chouser: ambient: have you used lazy-seq directly?

19:21 ambient: i think once, a month ago

19:22 :p

19:22 chouser: itistoday: http://clojure.org/lazy ...except what is future there is now past

19:22 itistoday: chouser: thanks

19:23 chouser: ambient: one technique would be to write your function as a infinitely recursive loop

19:23 ambient: yeah i was thinking about that too

19:23 chouser: (defn foo [i] (prn i) (foo (inc i)))

19:24 ...that prints your new values.

19:24 then you can transform that into a lazy seq

19:24 (defn foo [i] (lazy-seq (cons i (foo (inc i))))))))) ; lost track of parens

19:25 itistoday: ambient: is your code somewhere? i'd love to see the finished version when it's ready

19:25 ambient: just tried, sounded cool

19:26 ambient: well all the synth code is in the paste

19:26 itistoday: ambient: just wondering if you had it up, i.e. github or something like that

19:27 ambient: its on bitbucket but i'd rather not yet publish it anywhere

19:27 itistoday: mmk

19:31 chouser: Audio Device Unavailable ...my java audio setup must be completely broken and I just hadn't noticed before.

19:31 ambient: there might be some type hints missing

19:31 i stopped debugging when mine started working

20:08 octe: i've been reading up on concurrency-stuff in clojure and i'm kind of understanding how to deal with concurrent access to data objects, but what about sharing non-data non-threadsafe objects, like an OutputStream?

20:12 chouser: well, you've got to be careful. :-/ Often one nice way to handle an output stream use an agent to control access to it, so threads can send-off write functions to it.

20:14 octe: ok, i was thinking about agents but i wasn't sure that it "fit"

20:14 i'll try it

20:16 itistoday: in http://clojure.org/lazy, why does he say use 'rest' instead of 'next' here: (lazy-cons (f (first coll)) (map f (rest coll)))))

20:17 all that's said is "if consuming another seq, use rest instead of next", no clear explanation given

20:18 err, rather, i copied the wrong code (from the old way)

20:18 this is the one i'm referring to: http://paste.pocoo.org/show/144619/

20:18 (copied from "The new way")

20:20 rhickey_: itistoday: using next would make it eager by one

20:20 chouser: next never returns an empty collection, but nil instead. This can be handy, but it means the next step of the lazy seq is forced so sometimes it's inappropriate

20:22 itistoday: does not compute

20:22 sorry :-(

20:23 i'm trying to understand this in terms of cons

20:23 or rather... one sec

20:23 rhickey_: itistoday: it's not about the cons, but the args to cons, you'd be forcing the second arg (if it was lazy) by using next

20:24 (next x ) === (seq (rest x))

20:25 itistoday: do i understand correctly...

20:25 rest returns a delay

20:25 and next does not?

20:25 or rather, next forces the delay returned by rest?

20:26 octe: chouser: i guess another alternative is to use something like a shared threadsafe queue object?

20:26 that something reads off and sends off on the OutputStream..

20:26 chouser: octe: yes, that can work well. a BlockingQueue perhaps.

20:31 itistoday: a delay is something else specific. but if x is (cons a (lazy-seq ...)) then (rest x) doesn't force the lazy-seq while (next x) does.

20:33 itistoday: chouser: thanks, i think that helps a bit

20:33 i'm playing around with the repl, hopefully that'll help clear up my confusion

20:33 i think the problem is that i'm thinking in terms of streams

20:33 what does lazy-seq do?

20:34 nm.. reading the docs...

20:35 ,(doc first)

20:35 clojurebot: "([coll]); Returns the first item in the collection. Calls seq on its argument. If coll is nil, returns nil."

20:35 itistoday: ,(doc next)

20:35 clojurebot: "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil."

20:36 itistoday: ,(doc rest)

20:36 clojurebot: "([coll]); Returns a possibly empty seq of the items after the first. Calls seq on its argument."

20:37 itistoday: ,(doc seq)

20:37 clojurebot: "([coll]); Returns a seq on the collection. If the collection is empty, returns nil. (seq nil) returns nil. seq also works on Strings, native Java arrays (of reference types) and any objects that implement Iterable."

20:38 ambient: how do i generate infinite seq of random numbers? (take 10 (repeat (rand))) print out just one number for each run

20:39 chouser: repeatedly

20:39 funkenblatt: ,(take 5 (map rand (repeat 1)))

20:39 clojurebot: (0.7265724927209442 0.3998850009265046 0.008882990808162017 0.1862657057261602 0.2660922579606133)

20:40 funkenblatt: there's probably a better way than that, but that's what came immediately to mind

20:41 ambient: (take 10 (repeatedly rand)) seems to work :)

20:41 itistoday: ,(take 10 (repeatedly rand))

20:41 clojurebot: (0.7418891709881609 0.5002349453871904 0.6923304956080272 0.23683099175381928 0.6196438692623625 0.5261268340502978 0.4262760865021553 0.1628545274801868 0.8089272143742726 0.9269205296576724)

20:41 * ambient haz got white noise

20:41 funkenblatt: oh standard libraries

20:42 coming from scheme i'm totally used to not having any

20:43 itistoday: (defn rand-seq [] (lazy-seq (cons (rand) (rand-seq))))

20:43 that works too

20:45 ambient: i'm wondering if i can keep a short ring-buffer inside a lazy-sequence

20:45 tomoj: itistoday: that's exactly what repeatedly does :)

20:45 ambient: loop/recur can be used to maintain some sort of state but dont know if it works with lazy-seq

20:46 chouser: you want something other that 'cycle' I guess?

20:46 itistoday: chouser: check this out:

20:46 ,(rest (cons 1 (lazy-seq (println "foo"))))

20:46 clojurebot: ()

20:46 itistoday: ,(next (cons 1 (lazy-seq (println "foo"))))

20:46 clojurebot: foo

20:46 chouser: ring-buffer sounds mutable -- not a good idea for a lazy seq

20:47 itistoday: illustrating your point right?

20:47 ,(seq (rest (cons 1 (lazy-seq (println "foo")))))

20:47 clojurebot: foo

20:47 ambient: chouser perhaps ring-buffer is not the right term, values that depend on the previous values

20:47 and roll-around depending on conditions

20:47 chouser: ambient: yeah, you can do that with lazy-seq

20:47 hiredman: you can implement a ring buffer with a vector and an index to the currect position in the vector

20:48 all very immutable

20:48 itistoday: chouser: so, clojure isn't helping me here

20:48 chouser: i see that that happens, but i still don't know why

20:48 i guess i'm trying to figure out how 'seq' forces it

20:49 as well as, what is returned by this: (rest (cons 1 (lazy-seq (println "foo"))))

20:49 steiger: why can't multimethods have '?' in their name? i always get: don't know how to create ISeq from: Character

20:51 hiredman: eh?

20:51 pastebin

20:51 itistoday: tomoj: gotcha: (defn rep [f] (lazy-seq (cons (f) (rep f))))

20:52 steiger: hmm, seems it has nothnig to do with '?'

20:53 tomoj: itistoday: yup, that is exactly the source of repeatedly

20:53 steiger: hiredman: http://paste.lisp.org/display/88563

20:54 itistoday: i won't wrack my head about this a anymore

20:54 i blame the documentation

20:55 will just take hichey's word on it

20:55 rhickey_: ,(doc lazy-seq)

20:55 clojurebot: "([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls."

20:56 itistoday: rhickey_: "i guess i'm trying to figure out how 'seq' forces it", and "what is returned by this: (rest (cons 1 (lazy-seq (println "foo"))))" ?

20:57 rhickey_: how seq forces it? you can read the source

20:57 what does how matter for understanding the use?

20:57 itistoday: good point

20:57 hiredman: steiger: and the exception?

20:58 rhickey_: LazySeq.java has the gory details

20:58 steiger: hiredman: Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Character (graphutilsNew.clj:9)

20:58 itistoday: rhickey_: thanks

20:58 steiger: sorry, forgot to paste it to pastebin

20:59 hiredman: huh

20:59 oh

20:59 defmethod's don't take docstrings

20:59 steiger: oh

20:59 yeah

20:59 just noticed that

21:00 that's odd, it feels very natural to put docstrings in defmethods

21:01 hiredman: how would you read the docstring?

21:01 clojurebot: with style and grace

21:01 hiredman: ~botsnack

21:01 clojurebot: thanks; that was delicious. (nom nom nom)

21:01 itistoday: how would you read the docstring?

21:02 damn bot

21:02 steiger: hiredman: how would i read? using (doc) ?

21:02 hiredman: steiger: but how would you pick out the particular method's docstring?

21:03 itistoday: how would you ______? => "with style and grace" chance of 5%?

21:03 steiger: oh. i see the dilema, hiredman

21:03 hiredman: ~literal [?] how

21:03 clojurebot: 1

21:03 hiredman: ~literal [1] how

21:03 clojurebot: It's greek to me.

21:03 hiredman: ~literal [0] how

21:03 clojurebot: <reply>with style and grace

21:04 itistoday: neato

21:04 hiredman: and clojurebot has a 1/100 chance of treating any line not addressed to it as addressed to it

21:04 itistoday: ah, thanks, good to know

21:04 steiger: maybe it should print all avaliable docstrings, i don't know. anyway, eliminating the possibility of having a docstring doesn't feel right

21:04 itistoday: why not put it in the defmulti?

21:05 steiger: defmulti supports it, right?

21:05 itistoday: i've no idea

21:05 steiger: itistoday: yeah, that's what i thought

21:05 it supports it

21:05 itistoday: :)

21:05 steiger: hm. weird.

21:05 ok, i'll put it in the defmulti

21:05 hiredman: you have to use the whole #^{:doc "foo bar"} stuff, if I recall

21:06 steiger: hiredman: it compiled nicely with the friendly syntax

21:07 i.e, after defmulti and the name

21:32 what's the cleanest way to check if a vector contains an item?

21:33 tomoj: ,(.contains ["foo" "bar" "baz"] "bar")

21:33 clojurebot: true

21:33 steiger: thankyou tomoj

21:33 tomoj: of course it's slow

21:33 hiredman: eh?

21:34 right

21:34 steiger: i see

21:34 maybe i should use hashmaps.

21:35 hiredman: well, key looks up would be fast, but not value lookups

21:36 steiger: i gotta think.

21:36 tomoj: key lookups in this case are really just checking whether the vector is at least that long, right?

21:36 ,(contains ["foo" "bar" "baz"] 2)

21:36 clojurebot: java.lang.Exception: Unable to resolve symbol: contains in this context

21:37 tomoj: ,(contains? ["foo" "bar" "baz"] 2)

21:37 clojurebot: true

21:39 arohner: ,(some #{:foo} [:bar :foo :baz])

21:39 clojurebot: :foo

21:39 arohner: ,(some #{:bogus} [:bar :foo :baz])

21:39 clojurebot: nil

21:39 arohner: of course, that's a linear scan

21:39 if you want sublinear, use a map

21:39 tomoj: or a set, no?

21:40 arohner: tomoj: yes

22:12 ambient: ,(take 10 (rec-cat fibs [0 1] (map + fibs (rest fibs))))

22:12 clojurebot: (0 1 1 2 3 5 8 13 21 34)

22:14 tomoj: is that new? I don't have it

22:14 ambient: clojure.contrib.seq-utils

22:15 tomoj: ah

22:15 sweet

23:41 durka42: can clojureql do persistent connections?

23:52 tomoj: durka42: not yet, I believe

23:52 btw, coi

23:52 durka42: coi lojbo

23:53 tomoj: there's some discussion about it on the lighthouse

23:54 i mi gleki lonu lo lojbo cu pilno la klojur

23:54 durka42: ie la klojur cu logji

23:56 tomoj: ui ji'a melbi

Logging service provided by n01se.net