#clojure log - Nov 04 2008

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

0:00 sohail: my java knowledge is showing... under what situations does -Djava.library.path=/foo not work but export LD_LIBRARY_PATH=/foo work?

0:03 hm, being banned from ##java doesn't help me solve this problem either

0:23 albino: heh

0:24 sohail: so if I have a.b.c(foo,bar) in Java, what is the cleanest way to write it in Clojure?

0:25 albino: Is c an instance of a class?

0:31 sohail: albino, no a function

3:34 lash: how do i join together a sequence of strings? like php's implode(), python's string.join, etc

3:38 hoeck: lash: (apply str '("foo" "bar" "baz"))

3:40 lash: cool. how would i add a space between each one?

3:44 hoeck: lash: then i would simply use print-str instead of str

3:44 like (apply print-str '("foo" "bar" "baz"))

3:46 lash: yes, that's a nice way

3:49 tWip: or you could (apply str (interleave ["foo" "bar" "baz"]) (repeat " ")))

3:49 minus one )

3:49 hoeck: tWip: (butlast (interleave ...

3:50 had the same idea :)

3:50 tWip: yeah, that to remove the unnecessary last space

3:52 (reduce #(str %1 " " %2) ["foo" "bar" "baz"])

3:52 will work also

4:10 lash: http://pastebin.com/d1a0d4590 is this a good use for macros? is it correct? seems to work at least :p

4:13 jdz: lash: that macro is wrong

4:13 lash: and yes, that's a case when a macro should be used\

4:15 lash: if you used 'when' instead of 'if' then you'd be ok.

4:21 hoeck: jdz: are you shure? (if condition expr) works in clojure

4:21 jdz: hoeck: but there can be more than one expr, right?

4:22 hoeck: ah, i see, sorry

4:23 i first thought you that macro is wrong because of the if only having a "then" clause

4:23 but its the missing do around body (which the "when" implies)

4:24 r/you/you mean

4:24 lash: jdz: well, then you'd use "do", right?

4:24 that's how i figured

4:25 and with this i get something like unless with an else ;)

4:26 jdz: lash: building on existing code has many benefits: your code is smaller, you remove code duplication, somebody else smarter than you might have got it right, and you have less ways to get it wrong.

4:27 lash: yes

4:27 jdz: lash: writing more code just because you can is a wrong attitude, imo.

4:29 lash: is it really wrong that my if has the same behaviour as an inverse if?

4:29 s/my if/my unless/

4:30 jdz: lash: if has two branches, so it already is an inverse of itself depending on the ordering of then/else expressions.

4:30 lash: yep

4:31 jdz: and there are 'when' and 'unless' in common lisp already, which have defined semantics...

4:31 lash: did not know :)

4:31 that's the best argument i suppose

4:31 jdz: first rule of good software design: somebody somewhere has already writted what you have in mind :)

4:32 lash: yeah, that's why i was suprised to not find unless in clojure already

4:32 i haven't used common lisp before

4:32 jdz: i avoid using it because i always have to pause for a minute or so to figure out what exactly is happening. especially if the condition contains an 'and' or 'or'

4:33 hoeck: lash: its called when-not

4:33 lash: i mainly wrote it because i wanted to try to write a macro

4:34 hoeck: jdz: yeah, i have the same problems with unless, i prefer the verbosity of (if (not )) in this case

4:34 jdz: hoeck: and i just switch the then/else expressions :)

4:35 or sometimes just make it so that the shorter expression comes in the then spot

4:35 if the other is relatively long

4:36 lash: i hope you learned the lesson that getting macros right is a bit harder than just ordinary functions because you must foresee all the uses of it.

4:40 lash: jdz: yes

8:29 jkantz: in common lisp I would do (find-if 'evenp '(1 2 3 4)) ... what's the idiomatic thing to do in clojure?

8:29 Chouser: that returns true as soon as it finds one?

8:30 duck1123: jkantz: I believe filter is what you're looking for

8:30 AWizzArd: Chouser: yes

8:30 ==> 2

8:30 filter is in Common Lisp remove-if

8:30 Chouser: hm. (first (filter even? [1 2 3 4]))

8:31 jkantz: ok that works for me

8:31 b/c filter returns a lazy sequence

8:33 Chouser: jkantz: right

8:34 fewer built in functions is a goodthing

8:37 AWizzArd: the (first (filter ..)) approach is a bit more "chatty" vs (find-if even? [1 2 3 4]), but also more flexible.

8:42 duck1123: you could always write find-if to wrap that up if you find yourself doing it a lot.

8:43 you could even do a (first-even [1 2 3 4])

8:45 gnuvince: what does FIND-IF do?

8:45 Returns true or false if an element is even?

8:46 Chouser: gnuvince: apparently it returns the first element for which the pred is true.

8:46 gnuvince: ah

8:46 If it had only returned true or false, `some� would've been appropriate.

8:47 Chouser: yep

8:52 jdz: there are some, every, notevery and notany in common lisp, too

8:56 Cark: hey there ... i come with a question

8:56 using slime (widows) i can't seem to make the gui examples work

8:56 it just hangs

8:56 while it works from the *inferior-lisp*

8:57 any idea on how to fix this ?

9:01 hoeck: Cark: have you any examples?, just opening swing frames (using cgrands wonderful javadoc) works here (slime + w2k)

9:03 Cark: i just copy pasted the temperatur converter example at in a file http://en.wikibooks.org/wiki/Clojure_Programming

9:03 then (require 'my-file)

9:05 i also tried doing this manually ... you know : import the java classes, then create and setVisible a frame from the repl

9:07 hoeck: sometimes java windows just don't appear for the first time, or they are hidden behind all other windows

9:08 Cark: it's not behind a window ... i checked that =)

9:09 but yes, once i do it from the *inferior-lisp* it works under slime-repl

9:09 just can't do it from slime first or it will lock it

9:09 hoeck: well, maybe its hidden in other obscure ways

9:09 Cark: btw i tried the cgrand javadoc and same thing

9:14 that wouldn't prevent slime's next prompt to show up

9:14 hoeck: right

9:23 SnowBuddy: is it not possible to run a .clj file without pasting into the REPL, or am I just incompetent? ;)

9:24 gnuvince: SnowBuddy: it is possible

9:24 SnowBuddy: java -cp clojure.jar clojure.lang.Script foo.clj

9:25 Cark: or (load-file "my-file.clj") from the repl

9:33 SnowBuddy: hmm, ClassNotFoundException when I try running it through clojure.lang.script. i think i just don't understand how this stuff is supposed to work

9:33 Cark: uppercase S in clojure.lang.Script ?

9:34 hoeck: Cark: i just tried to open a swing frame on windows vista with slime+xemacs+jdk6_10 without any problems except the window doesn't appear on top the first time its opened

9:34 SnowBuddy: with or without uppercase S, same result

9:34 Cark: hoeck : there must be some problem with my slime installation ... i'll just open it first from the inferior-lisp

9:34 thanks anyways

9:42 abrooks: clojure-spec looks like a nice example+test mechanism: http://www.bitbucket.org/BestFriendChris/clojure-spec/wiki/Home

9:42 Chouser: SnowBuddy: you can get a repl, though?

9:43 SnowBuddy: Chouser: yep, everything works fine interactively

9:43 Chouser: SnowBuddy: what if you just add a filename at the end of the command-line you use to start the repl?

9:44 SnowBuddy: same thing, class not found exception on clojure.lang.Repl instead of clojure.lang.Script

9:45 Chouser: but it must be finding the class when you don't provide a .clj

9:45 can you paste your whole command-line and the whole stack trace?

9:46 at http://paste.lisp.org/new/clojure

9:47 lisppaste8: SnowBuddy pasted "Error running script" at http://paste.lisp.org/display/69696

9:48 Chouser annotated #69696 with "try this instead" at http://paste.lisp.org/display/69696#1

9:51 SnowBuddy: Chouser: no errors now, but nothing seems to happen. it pauses for a moment and then goes back to the command prompt

10:12 Chouser: SnowBuddy: well, what does scratch.txt do? is it supposed to print anything?

10:19 SnowBuddy: that's it. i wasn't doing anything that would show an effect ^_^

10:21 Chouser: i had exactly the same "problem" when I started.

11:03 kib2: hi, did someone here played with the Processing backend ?

11:04 Lau_of_DK: Hi guys

11:05 Chouser: hi

11:05 duck1123: hey Lau_of_DK

11:40 sohail: any of you guys ever see 2 prints with the same output when you only expected one?

11:41 tomppa: with SLIME?

11:41 sohail: tomppa, yes

11:42 jdz: sohail: are you sure they are both prints? one of them might be the return value of the expression you evaluated.

11:42 sohail: jdz, pretty sure because this isn't the last statement in the function

11:43 tomppa: at least some older versions of clojure-slime evaled expressions twice

11:43 sohail: tomppa, ok I don't think that is my problem

11:43 tomppa: but I think it has been fixed in the latest versions

11:43 sohail: well might as well do an update anyway

12:21 fyuryu: kib2: I played with it

13:05 tomppa: what is the right way to build paths and filenames in Java? I'd need to have a list of paths and

13:06 then go through them and find if a specific file exists in one of them

13:06 I guess the paths would be URLs

13:06 Cark: there is the File class i think for that

13:07 leafw: Chouser: I can't get your pasted jambi example to work

13:07 Chouser: http://paste.lisp.org/display/69450

13:07 tomppa: Cark, I found it, thanks

13:08 leafw: Chouser: two errors: first, the *command-line-args* may be null (easy to solve)

13:08 Chouser: ah, sorry.

13:08 Cark: tomppa : all-files (. (new File base-path) (listFiles))

13:08 leafw: Chouser: second, the .ui file: I made a simple .ui file in the qt designer, but I get this error on the clojure side: com.trolltech.qt.designer.QUiLoaderException: Unsupported language: '', expected 'jambi'

13:08 Chouser: should one specify somewhere this "language" option?

13:09 Chouser: in the designer, I mean.

13:09 Chouser: leafw: yeah, I don't know what that's about, but that's why I have the comment in there about editing the .ui file manually

13:09 leafw: Chouser: oops, should read better myself, thanks.

13:10 Chouser: someone who knows jambi better should find the "right" way to set the language.

13:10 leafw: Chouser: ok, that's a small problem, there must be an option among the gazilions somewhere in the designer app.

13:12 also fails for silly things like unsupported properties such as Qt::LeftToRight enum for a QMenu widget ... weird

13:12 because that's the default

13:14 also, I had to explicitly add the LD_LIBRARY_PATH to /usr/lib/jni ... or jambi .so files could not be found.

13:15 Chouser: (doc into-array) claims to accept only one argument

13:15 Chouser: but your example used (into-array String *command-line-args*), which fails.

13:20 Chouser: leafw: maybe I have a newerversion of clojure?

13:21 sorry,my space key is failing today.

13:21 leafw: np

13:42 lau_: Has anybody here got the JLine functionality working in Emacs ?

13:44 leafw: Chouser: also, strangely enough, I can't run the example from the interpreter (gets an exception). But when pasted line by line, it works.

13:44 Chouser: weird. let me try it again

13:44 leafw: I mean, from a file as in (load-file "/path/to/file.clj")

13:46 Chouser: oh! ok.

13:47 works fine for me, with main.clj on the command line or with load-file

13:48 leafw: weird

13:48 Chouser: I'm using latest svn clojure -- doesn't seem to have a problem with an empty *command-line-args* either.

13:48 leafw: also, from the interpreter, if I quit the application and then just run it again with (QApplication/exec), then the UI doesn't show ... and the interpreter is locked. Lots of gotchas.

13:49 Chouser: proper use of Qt will, I think, require some special thread and/or repl setup.

13:50 the Qt gui functions must be run in the main thread, QApplication should only be exec'ed once, etc.

13:50 these are all well documented in Qt, but not quite as natural as swing.

13:51 ...although apparently swing stuff is supposed to be runin it's own thread as well, it's just not as enforcedas Qt's restriction.

13:51 leafw: I did Qt in c++ years ago, most faded ... but the native look in ubuntu of the gui is very appealing.

13:52 Swing does not enforce anything: one must run it all via SwingUtilities.invokeLater(new Runnable() { ...} )

13:52 which is a pain -- just so it gets executed in the queue of the EventDispatchThread.

13:52 Chouser: I'm a bit of a Qt fanboy for C++, but very much less so in Java, andeven less than that for Clojure.

13:53 leafw: Swing is a pain to build guis with --I've done many. Mostly manually, in the end.

13:53 Lau_of_DK: I think Qt can be used in a very limted scope in Clojure, but it definately has its purposes

13:55 leafw: unless jdk7 solves the non-native look of java apps, Qt-jambi-java has plenty of future with clojure, Lau_of_DK .

13:55 Chouser: For me the upsides of Qt in Clojure would include very fast native libraries with good support forhardware accel., integrated opengl with accel, featureful gui designer, well-designed and beautiful-looking multi-language text support.

13:57 downsides: 3rd party lib, including platform-specific downloads, awkward thread requirements, some use of global state (QApplication, for example), and requirement to do have some direct clojure support to handle signals and slots fully and easily.

13:59 leafw: is there any clojure function to empty the current namespace?

13:59 i.e. forget all vars

14:00 AWizzArd: yes

14:00 Lau_of_DK: leafw, depends a little on how you look at it. The threading in QtJambi is not very intelligently designed. For instance when you start using slots and signals you'll find out that any fail will drop silently and QApplication will ignore it. That means that if all goes well, no problem, but if/when somethings breaks, you'll never know about it. I expect that for larger apps we'll see concurrency issues and the likes. This might all be fixed, but so far Q

14:00 t is useful for good looking simple GUIs and such

14:01 AWizzArd: leafw: (ns-interns 'user) ==> map of all your bindings

14:01 leafw: woah and now qt java segfaulted the VM ... when trying to re-run a QApplication.

14:01 Chouser: leafw: you could try: (doseq [n v] (ns-interns *ns*) (ns-unmap *ns* n))

14:01 leafw: thanks AWizzArd

14:01 Chouser: leafw: yeah, you can't do that.

14:01 AWizzArd: (ns-unmap 'namespace 'yourvar) ==> removes the var

14:02 leafw: thanks

14:02 Chouser: leafw: the "right way" to do qt would be to start a new repl prompt in another thread, allowing Qt to "own" the main thread so you don't need to re-run QApplication

14:02 I think.

14:03 leafw: I see what you mean about requiring some clojure support from within

14:07 Chouser: latest svn is what I have, from 6 days ago, and the (into-array String *command-line-args*) fails

14:07 AWizzArd: To release all your vars you could do something like:

14:07 (map #(ns-unmap 'user %) (keys (ns-interns 'user))) where 'user is your namespace

14:08 leafw: thanks AWizzArd, I figured that one out :)

14:08 Chouser: AWizzArd: you missed my post? :-) you'd have to watch out that "map" is lazy.

14:08 AWizzArd: Chouser: I just saw it when scrolling back *sigh*

14:08 maybe I need more sleep

14:09 Chouser: AWizzArd: thanks for ns-interns, though. I only knew of ns-publics which would have been insufficient.

14:09 AWizzArd: Chouser: btw, good explanation in the GG about Stuarts code with his (map identity map) thing

14:10 Chouser: AWizzArd: thanks!

14:10 that was a tricky one

14:30 AWizzArd: about what "Clojure actors" is Rich talking in posting 4 here? http://groups.google.com/group/clojure/browse_frm/thread/2a2b24ffef5d1631/f4c4cdf44d00f70c?tvc=1

14:31 Chouser: that's old!

14:31 AWizzArd: yes

14:31 Chouser: they're called "agents" now

14:32 AWizzArd: so with idle actors he means: threads in a threadpool, yes? (not running)

14:33 Chouser: no, an agent that is not running doesn't have a thread

14:35 when you send an action to an agent (using"send"), the agent either gets a thread from the pool or gets queued up for when a thread is available.

14:44 AWizzArd: So what does he mean with having millions of agents ideling around?

14:45 Chouser: an agent is an object. It holds onto a state value. You can have millions of those idle

14:45 AWizzArd: oh okay, sure

14:46 Chouser: if you want to change an agent's state value, you send it an action, at which point the action executes on a thread or gets queued up to do so in the future.

14:47 AWizzArd: Yes, this I fully understand. I was just mislead to think about Erlang having tens of thousands of processes running at the same time, and so came to the idea of threads.

14:48 So conceptually Rich just had a collection of some million objects in memory. In this case it were agents, but it could have been numbers as well

14:48 Chouser: right. I think partof why Clojure uses the word agent is to remind us they're not quite like erlang actors.

14:48 AWizzArd: yes

14:49 Chouser: AWizzArd: sure, but agents are not just numbersof course, they have their own semantics. Specifically they manage mutability.

14:49 AWizzArd: yes, I just wanted to express that it is IMO nothing spectecular of them in a col

14:50 It would be nice if they were actually running on a 10mio-Core cpu ;-)

14:50 Chouser: well, if you had that many cores and that much work to do,they would.

14:51 AWizzArd: In fact, I could probably easily get billions of those systems to 100% load for my problems

14:51 Chouser: it's not in itself "impressive" that he's got amillion of them, but when you're designing a solution in some frameworks you'd use athread instead of an agent.

14:52 AWizzArd: btw, to have millions of them one has to start java with a respective heap size I guess

14:52 Chouser: having a million threads may not work well, even if they're idle. so by providing agents, clojure lets you deal with a useful abstraction that allows millions.

14:54 Lau_of_DK: kotarak, good evening

14:54 AWizzArd: Does java offer some constructs that allow me to fine tune the priority of threads? Maybe I want that some agents get very much cpu time, while others are really not important at all

14:54 kotarak: hi Lau_of_DK

14:54 AWizzArd: Moin kota :-)

14:54 Chouser: AWizzArd: I've no idea. I don't really know Java well.

15:10 rapido: question: immutable data OK. But is it possible to have immutable functions/code? (or immutable curried functions)

15:11 if code is data and data is immutable - why not?

15:11 wwmorgan: rapido: functions are immutable

15:13 eg. (partial + 2) returns a new function and doesn't change +

15:13 rapido: wwmorgan: good example

15:14 wwmorgan: but the top level environment is mutable

15:14 the definition of + is mutable

15:14 AWizzArd: it would be even better if we had currying, so we could say $(+ 2) instead

15:15 wwmorgan: rapido: not quite. The name + can be changed to refer to a different function (or any value), but if you did (def plus +) and then (def + -) then (plus 2 2) would still be 4

15:16 rapido: what does (+ 2 2) mean without an definition of +?

15:16 the environment is implicit

15:17 to get absolute immutability, the environment should be made explicit in the context of every expression.

15:18 AWizzArd: rapido: what do you mean by that?

15:18 wwmorgan: since the underlying functions aren't changing, functions are immutable. I think you're suggesting that it shouldn't be possible to change the value of vars

15:19 Chouser: clojure isn't tryingto get absolute immutability.

15:20 I think clojure's aiming for minimal and well-managed mutability.

15:21 gnuvince: Quick announcement: because of my incapability at composing a decent blog post in French, I'll be writing my draft in English and I'll translate to French afterwards. Again, if some people are interested in proof-reading, I'll be posting the link to a draft in the coming days.

15:21 rapido: Chouser: yes, i know - i'm just theorizing about immutable environments, together with immutable expressions and immutable data :)

15:23 AWizzArd: rapido: Clojure is a dynamic system. We *want* it to be changable. Only during programming in the repl, or later for administration you would overwrite existing bindings with a (def ...)

15:24 rapido: naively, immutable code can be achieved with namespaces + version numbers

15:24 Chouser: rapido: sounds like a poor man's monad.

15:24 rapido: i want to refer to a specific piece of code that is immutable

15:24 AWizzArd: And only there those cases it should happen that you overwrite something. You *could* do it anytime, but you *should* not.

15:25 rapido: just store that piece of code in a collection

15:25 and collect code pieces there

15:26 rapido: AWizzArd: when i 'overwrite' code i want a new immutable version (just like clojure data)

15:27 that maximally shares code 'structure' with the 'overwritten' version

15:28 wwmorgan: rapido: clojure is a compiled language. Once that code is read in, the S-expressions are no longer retained

15:28 rapido: it's just an idea

15:29 wwmorgan: i know s-expressions

15:29 danlarkin: clojure code _is_ immutable

15:29 kib2: gnuvince : I can help in French if you want to

15:29 danlarkin: remember code is data

15:29 AWizzArd: rapido: put the function into a hashmap on which you have a ref and do not use defn instead

15:30 or write a macro that puts the functions into a defn for nice usability, but also adds it to a copy of the collection

15:30 gnuvince: kib2: the words just don't come as easily in French as in English when I write about programming. I'll just get something down in English and do the translation afterward.

15:30 kib2: gnuvince : as you want, I suppose it's better for all that you write in English.

15:31 Chouser: functions are just another data object. In fact, some data objects are also functions. Thus they can be stored in any of the ways other clojure data is stored: immutably in locals, or in the mutable objects var, ref, or agent

15:31 rapido: danlarkin: what about redefinitions in the top level environment?

15:32 gnuvince: kib2: I still intend to post the final draft in French: I have not seen any mention of Clojure on any French web site or blog or forum. I would like to stir the interest of the French programmers just a little bit.

15:32 danlarkin: rapido: that isn't changing code, it's just changing where the variable points to. The old function still exists unchanged (until it gets GCed of course)

15:33 kib2: gnuvince : good idea indeed. I saw you were in 'Developpez!' forum, that may be a good idea to start from there.

15:33 gnuvince: kib2: that's where I want to start.

15:33 kib2: post something in the Java and Functional Programming sections and see if anyone seems interested.

15:33 rapido: danlarkin: true - but doesn't that change the definition of all the 'immutable' code that refers to that variable?

15:34 gnuvince: (I'm guessing I'll have more success in the Lisp forum)

15:34 AWizzArd: rapido: you can look at some example code here: http://paste.lisp.org/display/69638

15:35 there you will have a basic macro that you could use for making your own, to define functions but keeping their sources

15:35 wwmorgan: lisppaste8: url

15:35 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

15:35 danlarkin: rapido: clojure is dynamic, so if I get passed a variable called foo, I'm not getting passed a pointer to a memory location, I'm basically getting passed a name that resolves at runtime

15:35 kib2: gnuvince : yes, I think there will be some interest from the FP forum, I don't know about the Java one (and in fact I don't know anything about Java yet) .

15:36 Chouser: danlarkin: umm... I'm not sure that's quite right.

15:36 rapido: danlarkin: ok, so it's essentially about variables, not about immutable code/data whatever

15:36 danlarkin: Chouser: isn't it?

15:36 rapido: variables that are resolved at runtime defy immutability

15:37 Chouser: (let [foo (Object.)] (my-fn foo)) ; in this case my-fn is passed essentially a pointer to the Object I created.

15:37 wwmorgan: rapido: the canonical example is "today". "today" is a name that refers to the current date. The date that it refers to changes

15:37 Chouser: my-fn doesn't have any way of know it was in any way related to something called "foo"

15:38 rapido: would it be feasible to make clojure's environment immutable?

15:38 AWizzArd: rapido: just offer your own version of def

15:38 write a macro for that.. it won't allow redefinition

15:39 then you would say (defconstant ...) instead of (def ...)

15:39 The thing is: you *should* treat (def ..) as if it were a constant

15:39 Chouser: rapido: if A calls B and I create a new version of B, you want A to continue to behave the old way?

15:39 AWizzArd: In principle you can use def as you use = in Java

15:40 rapido: couldn't redefinition copy the old environment to a new environment with the redefinition?

15:40 AWizzArd: this was explicitly not wanted

15:40 in static systems like Haskell or ML it works like that

15:41 in their repl you can define a function foo, then bar which calls foo and then redifne foo. Bar will still call the first foo.

15:41 Clojure explicitly does not want this. It is a dynamic system.

15:41 For administrative tasks you want to be able to override code.

15:42 rapido: Chouser: yes, i want A to explicitly bind to the new B instead of impliticly

15:42 AWizzArd: This will allow you to fix bugs in a running computer program without restarting it.

15:42 It is regarded as bad style to overwrite functions outside of the repl and you should never do this in principle.

15:43 But in Lisp you log in to the computer of your customer and while his program is running you integrate a compiled version of the function that is now patched.

15:43 rapido: AWizzArd: I understand the practicality of implicit redefinitions - but i work for a bank :)

15:43 AWizzArd: While you have your customer on the telephone and talk with him you will fix his bug.

15:44 Chouser: rapido: how would you accomplish explicitly re-binding A? Provide the code for it again, so the reference to B could be resolved to thelatest version?

15:44 AWizzArd: rapido: then simply store your functions inside a ref.

15:44 In a ref on a vector or map I mean

15:44 rapido: Chouser: A shouldn't be bound to B in the first place

15:44 AWizzArd: whenever you first touch (get-the-right-one-out-of @your-functions) it will continue to support that version.

15:45 lisppaste8: danlarkin pasted "immutable code/data" at http://paste.lisp.org/display/69712

15:45 AWizzArd: this is MCC, Clojures Multiversion Concurrency Control system

15:45 rapido: if A refers to B this should be resolved against a specific version of the environment

15:46 i mean: A shouldn't be bound to a specific version of B

15:46 lisppaste8: wwmorgan pasted "IOW, rapdio: this is NOT what you want" at http://paste.lisp.org/display/69713

15:46 Chouser: rapido: I'm not following you -- that sounds like the opposite of what you were asking for before.

15:48 rapido: env1 -> (A -> B B) (B -> 1)

15:48 ooops

15:48 env1 -> (A=B B) (B=1)

15:49 damn it: smileys get in the way

15:49 AWizzArd: I see no smileys

15:50 Chouser: me neither

15:50 rapido: env1 = (A=B B, B=1)

15:50 env2 = (A=B B, B=2)

15:50 env1 and env2 share the defintion of A

15:50 env1 and env2 differ in the definition of B

15:50 AWizzArd: yes, you want the same thing that ML or OCaml are doing

15:51 rapido: but ML nor OCaml shares (immutable) structure between env1 and env2

15:52 AWizzArd: Well, you got some suggestions how to solve this in Clojure. It's now your choise what you will do

15:53 choice even

15:55 rapido: AWizzArd: thanks - i'm going to try your suggestion: the redefinition of def

15:56 wwmorgan: rapido: you actually can't redefine def, because it's a special form

15:56 Chouser: rapido: note that clojure hash-maps have specifically the sharing of common entries that you seem to desire for the "environment"

15:56 AWizzArd: but in your own namespace you can offer a new version of def

15:56 or call it defconstant

15:58 rapido: AWizzArd: let me try to hack it - and see if i can achieve it in plain clojure (no java source hacking)

15:59 duck1123: is it possible to set up some sort of security policy where re-definition would not be allowed?

15:59 AWizzArd: sure, this is possible

15:59 duck1123: you would ruin the power of the repl, but that's what you get

16:00 AWizzArd: It's against the Clojure way to solve thins and more MLs way of doing it. But with some macros you can integrate that behaviour into Clojure as well and let it seem more natural.

16:01 rapido: got to run, later...

16:02 duck1123: truthfully, if you lock it down properly, someone who has access to the repl, probably has access to do other nasty things to the system anyway.

16:04 AWizzArd: yes

16:04 seems there is no 100% safety

16:04 Chouser: clojure doesn't have features to protect against malicious code

16:04 you can switch to the clojure namespace and wreak havok

16:05 AWizzArd: in the real world you are not supposed to drive into trees with your car, but in principle you *could* do it

16:05 (probably not very often though, if you are not really slow)

16:05 Chouser: but it's pretty good about helping you avoid doing bad things.

16:09 AWizzArd: Why does (take 8 fac) result in a stackoverflow for (def fac (lazy-cat [1 2 6 24 120] [(* (last fac) (inc (count fac)))])) ?

16:09 at the same time I can (def fac [1 2 6 24 120]) and in the repl repeat (def fac (assoc fac (count fac) (* (last fac) (inc (count fac))))) a few times without problems

16:12 gnuvince: Wouldn't it be easier to do: (def fact [x] (reduce * (range 1 (+ 1 x)))) (def facts (map fact (iterate inc 0))) ?

16:13 wwmorgan: AWizzard: for the same reason that (def foo (lazy-cat [4] [(last foo)])) generates a stack overflow

16:13 Hun: that's a pretty stupid algorithm. it throws away the precomputed factorials

16:16 AWizzArd: gnuvince: I was thinking about (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs)))), so, doing it without defn

16:16 wwmorgan: I think what you're looking for is (def facts (lazy-cat [1] (map * facts (iterate inc 1))))

16:17 gnuvince: AWizzArd: ok.

16:18 AWizzArd: wwmorgan: why can fibs continue appending numbers to the vector although it does not produce an infinite sequence?

16:19 wwmorgan: AWizzArd: because lazy-cat, map, and drop are lazy

16:19 AWizzArd: oh okay, drop is lazy too

16:20 didn't look into its doc, sorry

16:38 gnuvince: using a lazy sequence has the advantage of automatic memoization. So if (time (nth lazy-seq 10000)) takes 10 seconds, then (time (nth lazy-seq 10001)) will only take one msec. And every access between 0 and 10k will return immediate results

16:40 But you could also write a macro for memoization... (memoize my-function)... and from then on a call to my-function will return its result immediately when called with the same arguments as before.

16:40 Peter Norvig showed this in 1990 in his book, which is btw one of the very best about programming in general

16:41 Lau_of_DK: Theres a memoize in Clojure.contrib

16:41 AWizzArd: great

16:41 Lau_of_DK: But Wizkid, are you sure that lazy is auto memoized ?

16:41 AWizzArd: I wanted to suggest anyway to have that

16:42 yes Lau, see: (def sum (lazy-cat [0] (map + sum (iterate inc 1)))) and then: (time (nth sum 80000)) needs 522 msecs for me. But (time (nth sum 81000)) is done within 24 msecs

16:42 Lau_of_DK: ok cool

16:42 I just noticed a tremendous slowdown as you parse further and further down the lazy seq

16:42 So much that I had to abandon that approach entirely for certain calculations

16:43 AWizzArd: and it comes with the disadvantage of eating up your ram

16:48 Lau_of_DK: do you have an example for the tremendous slowdown at hand?

16:48 Lau_of_DK: No sorry Im on my Work PC atm

17:45 AWizzArd: is there something like (Math/pow ..) that returns BigDecimals?

17:46 Lau_of_DK: (.pow (Bigint %) %)

17:46 (bigint, not Bigint)

17:48 AWizzArd: hmm, (Math/pow (bigint 3) (bigint (Math/pow 3 3))) ==> 7.625597484987E12 and not 7625597484987

17:48 Lau_of_DK: .pow

17:48 user=> (.pow (bigint 3) (.pow (bigint 3) 3))

17:48 7625597484987

17:54 AWizzArd, you got it?

17:58 lisppaste8: AWizzArd pasted "how to convert to bigints?" at http://paste.lisp.org/display/69721

17:59 AWizzArd: no Lau, I can't use .pow but only Math/pow instead

17:59 .pow is unknown

18:00 Lau_of_DK: Get the latest version then

18:00 AWizzArd: I have the one from Oct. 29

18:01 Lau_of_DK: You must have done something with the namespace

18:01 Its standard

18:01 Anyway, gotta hit the sack, as you saw, it worked on mine, which is the latest :)

18:01 wwmorgan: my guess, AWizzArd, is that you're not passing an int to pow

18:02 AWizzArd: (.pow 2 4) ==> java.lang.IllegalArgumentException: No matching method found: pow for class java.lang.Integer

18:03 wwmorgan: (.pow (bigint 2) 4)

18:06 AWizzArd: I see

18:06 lisppaste8: wwmorgan annotated #69721 with "another way to do it" at http://paste.lisp.org/display/69721#1

18:07 wwmorgan: although I'm not quite sure what graham's number is so the math might be wrong

18:07 it sure grows fast, though

18:08 AWizzArd: wwmorgan: yes.. but this is even not grahams number

18:08 for x=4 it explodes already

18:08 wwmorgan: is that right?

18:08 AWizzArd: yes

18:09 Ackermanns function is a bad joke in comparison ;-)

18:09 wwmorgan: well. That's not a very useful function then

18:09 AWizzArd: it is very useful

18:09 it's used for a mathematical proof

18:10 and it (Grahams Number) holds the record of being the biggest number ever used in a meaningful proof

18:10 wwmorgan: I mean compared to (def grahams-number-test [3 27 7625597484987])

18:10 AWizzArd: ah okay ;-)

18:27 OT but funny: http://andrewsullivan.theatlantic.com/the_daily_dish/2008/11/a-different-rac.html

18:32 Again OT, but even funnier: a voting machine elected itself to be next president: http://www.theonion.com/content/node/89550 ;-)

18:32 There is definitly some AI around in these voting machines. Probably programmed in Clojure

20:01 kwatford: Beta is out for Programming Clojure: http://www.pragprog.com/titles/shcloj/programming-clojure

20:03 duck1123: sweet

20:05 gnuvince_: yay!

20:06 duck1123: I wish I wasn't so broke right now, or I'd buy it now

20:08 kwatford: It does still have a bunch of empty chapters, so probably no need to rush

20:09 Chouser: kwatford: you bought it already, eh? pretty cool.

20:10 kwatford: Yeah, I've been itching to use my praprog coupon.

20:12 Chouser: nice

20:13 duck1123: kwatford: how did you get a coupon?

20:15 kwatford: People who have purchased books from them recently got coupons for their anniversary celebration.

20:42 AWizzArd: n8

20:58 Drakeson: how do you serialize/pickle? python has cPickle.dump(...,fd). Is there an easy way to serialize into an XML or S-expr file, and also do the reverse?

21:02 Chouser: prn and read

21:03 Drakeson: is there a with-open-file?

21:04 Chouser: there's a with-open

21:05 but it doesn't open a file, it just closes it at the end of the block

21:06 Drakeson: Is it what we should use when we open and close files (in addition to something that actually opens the file)?

21:07 Chouser: yep

21:08 Drakeson: good. thanks :)

21:08 Chouser: files, urls, sockets, anything with a .close method.

21:09 kwatford: I believe it closes the object almost always, yes?

21:10 Chouser: it calls the .close method of whatever you've got.

21:11 Drakeson: is it possible to compile .clj's into bytecode?

21:11 Chouser: it's the only way it works. there is no interpreter

21:13 kwatford: Right, but does it *guarantee* that it calls .close (in all reasonable situations)? The API page mentions a finally block, so I'm assuming it does.

21:13 Drakeson: I mean, can I get a compiled file/directory as a way to deployment on an inferior platform?

21:13 Chouser: kwatford: ah, yes.

21:13 Drakeson: ah, to a .class file. Around here we call that AOT compilation, and it as of today: no

21:14 but it's in the works, should be available before too long.

21:14 kwatford: Drakeson: You can produce a jar file with clojure and your cljs in it. Haven't tried it though.

21:16 Drakeson: kwatford: but the cljs need to be compiled on the inferior machine as well

21:17 What are the important options for a web application server? Are there many good ones?

21:17 kwatford: Drakeson: That's ok, since you can put clojure in with them, and it is small. A stub main class can launch the script.

21:18 Chouser: Drakeson: yes. as of today, you can bundle up a .jar with everything you need, as long as the target has a "regular" JVM.

21:18 but if you need .class files to convert them to something else, for example to run on an Android phone, you can't do that without AOT

21:19 sohail: are there any android phones?

21:19 kwatford: yes, the G1 from T-mobile

21:21 sohail: is it out?

21:21 can I buy it?

21:21 can I hack it?

21:21 seriously? I hate iPhone

21:21 Drakeson: I have to build the target myself. Is Jetty a good option?

21:22 (I have no idea what are popular/good java based web servers)

21:22 kwatford: sohail: http://www.t-mobile.com/shop/phones/Cell-Phone-Detail.aspx?cell-phone=T-Mobile-G1-with-Google-Black

21:27 RadioApeShot: Anyone else using compojure?

21:27 Or have experience with jetty?

21:27 albino: Drakeson: I have a friend who like Jetty and Tomcat both a lot

21:28 duck1123: RadioApeShot: I am using compojure

21:28 RadioApeShot: So where should I put my stylesheets?

21:29 I can't seem to make my pages see them.

21:29 duck1123: do you read the mailing list

21:29 RadioApeShot: Not actively

21:29 duck1123: there was just recently a thread about this

21:29 RadioApeShot: I have searched (via google) for compojure and stylesheets

21:29 But had no luck

21:30 Can you give me a link?

21:30 duck1123: http://groups.google.com/group/compojure/browse_thread/thread/c2dae4830ac04008

21:30 RadioApeShot: duck1123: Thanks.

21:30 duck1123: the method should be the same for stylesheets

21:33 RadioApeShot: Excellent

21:33 I will see if I can make it work

21:34 duck1123: np

21:36 RadioApeShot: I don't know how much you've done, but have you been finding you need the request object in many of your page view fns?

21:36 I'm trying to get support for making request/response thread-local, but my experience may be atypical

21:37 RadioApeShot: I haven't implemented very much yet

21:37 Just a very basic skeleton

21:37 I am not that experienced with the web.

21:37 I put together a rails app while back

21:37 But that is about it

21:38 I am more of a scientist by trade.

21:38 duck1123: so far the only things I've really gotten done is basic CRUD operations, and OpenID authentication

21:39 I only work on it when I have free time

21:39 RadioApeShot: I am not even sure what CRUD stands for

21:39 I have this super simple project I am doing more for fun than anything

21:39 I am really glad to have found Clojure

21:39 duck1123: Create Read Update Delete

21:40 RadioApeShot: I am pretty sure Clojure is a Lisp I will basically stick with from here out.

21:40 Common Lisp is too old and crusty

21:43 arohner: do clojure maps implement java maps yet?

21:45 Chouser: arohner: yes

21:46 since Oct 6

21:49 arohner: cool, thanks

21:49 is there any easy way to figure that out? I remember reading the discussion on the mailing list, but didn't remember if it ever made it in

21:50 Chouser: the way I just did it was using git log and searching for "java.*map"

21:51 duck1123: isn't there a implements? type call in java?

21:51 Chouser: but that was to get the date

21:52 (supers (class {}))

21:52 or for your specific question: ((supers (class {})) java.util.Map)

21:53 or yes, (instance? java.util.Map {})

21:54 arohner: very cool, thanks

22:25 is there a way to cast a java.util.Map that is a generic?

22:25 i.e. java.util.Map <String,Object>

22:25 Chouser: just ignore the generic part. It'll work.

22:26 arohner: sorry, is there a way to pass a clojure map to a function that expects a Generic map?

22:26 duck1123: coerce ?

22:26 Chouser: you shouldn't have to do anything special.

22:27 just make sure the actual keys in your clojure map are Strings, and you should be able to pass it right in.

22:28 arohner: hrm. ok. maybe I'm doing something else wrong

22:28 kwatford: Are you passing it in from the Clojure side or the Java side?

22:29 arohner: yeah, looks like I was doing something else stupid. misreading the javadocs of the API I was calling

22:29 kwatford: I was creating a clojure map and trying to pass it to a java function

22:30 kwatford: Right, but that doesn't tell me what language you're doing it from

22:33 arohner: oh, I was creating a clojure map literal in clojure

22:35 kwatford: I assumed so, but having to juggle generics made me wonder

22:48 wwmorga1: is metadata attached to the Symbol or the Var?

22:49 kwatford: to the object

22:53 wwmorga1: what about when you do (defn #^{:a :b} foo [] 1)

22:56 kwatford: Both the function and the symbol foo are objects, but it doesn't look like either of those have the metadata you're trying to put on.

22:57 wwmorga1: you have to do ^#'foo to get at it. Alternatively (meta (var foo))

22:57 kwatford: ah, right

22:58 in that case, it's on the function, not the var or the symbol

22:58 wwmorga1: So it looks like the metadata is attached to the Var, but the documentation says metadata is associated with symbols & collections only

22:58 kwatford: I think

22:58 hmm, maybe not.

22:59 wwmorga1: it isn't attached to the function, else ^foo would work

22:59 kwatford: yeah, gotta be the var then

22:59 Chouser: when you def a var and attach metadata, yes, it goes on the var

23:00 wwmorga1: that's what I thought, but this recent post on the google group has thrown me for a loop

23:00 Chouser: (def foo #^{:a :b} [])

23:00 that attaches to the val: ^foo

23:03 * Chouser tries to concentrate on Clojure, which makes him happy, rather than other sad things going on in the world.

23:03 sohail: Chouser, what is making you sad

23:03 kwatford: hmm, should (def foo #^{:a :b} (fn [] 1)) put the metadata on the function?

23:04 wwmorga1: kwatford: functions can't have metadata. Only collections, and symbols and/or vars can

23:05 I think I'm just going to have to wait for someone smarter than me to answer the question

23:05 kwatford: Ah. That explains why it didn't work the last time I wanted to do that, but why?

23:07 wwmorga1: that's a language design choice that I don't quite understand. I'm sure rhickey has explained it before

23:08 kwatford: I wonder how non-helpful a search for "metadata on functions" on the list would be...

23:13 Chouser: sohail: non-clojure, and therefore off topic. :-)

23:14 sohail: Chouser, nonsense, if clojure can't save the world, there is no hope

23:14 Chouser: :-)

23:22 arohner: one thing I find amusing and slightly annoying about working in clojure:

23:22 I've found that using clojure to call the java API of some libraries is *less* verbose than their usual XML configuration

23:23 except that the java guys all expect that you want to use the XML interface, so the programmatic way is usually poorer documented than the XML way

Logging service provided by n01se.net