#clojure log - Aug 09 2009

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

0:51 alphaeus: What's the idiomatic way for saying give me the item in coll that maximizes function f?

0:53 _mst: ,(apply max-key #(* % %) [-10 1 2 3 4 5])

0:53 clojurebot: -10

0:54 alphaeus: thanks _mst

0:54 why key in max-key?

0:56 _mst: I know common lisp uses the term "key" for a function that gets applied to a value before a comparison is made. Not sure if clojure adopted it from there

1:01 mark_the_pirate: does anybody know why I can't get threads to print to the emacs+slime repl st. out?

1:03 alphaeus: mark_the_pirate: do they print to *inferior-lisp* buffer?

1:03 mark_the_pirate: yes

1:07 alphaeus: mark_the_pirate: maybe M-x slime-redirect-inferior-output

1:08 mark_the_pirate: alphaeus, that works. thanks.

1:09 alphaeus: de nada

1:44 bradbeveridge: I'm trying to build a simple swing app & I'm having problems with the mixing of functional and imperative. For example, I want to control where something is on a custom JPanel with a slider, but all the ways I've tried to connect the slider to the variable feel bad. What is the idiomatic way to do that kind of thing?

1:53 mebaran151: what import statement would be forward compatible for test-is?

1:54 right now, when I use the latest clojure contrib require test-is from contrib doesn't work

1:54 is there anyway to specify to use either clojure.test or clojure.contrib.test-is, whichever is available?

2:12 tomoj: I need to have a big structmap in mememory at all times, but I also need it to be persistent. suggestions?

2:15 alphaeus: When you memoize a function that has a recur, when it recurs will it consult the cache for those recur arguments?

2:16 hiredman: ~def memoize

2:17 mo

2:17 man

2:17 why did I even get the source

2:17 memoize wraps the function in another function

2:19 cark: i think it will not check the cach on recur

2:19 cache

2:20 hiredman: it cannot

2:20 cark: it might be possible to write a with-memoize-loop macro

2:21 hiredman: the recur takes place in the function that is wrapped by the funtion that memoize creates

2:27 mebaran151: can you catch a StackOverflowException?

2:28 lisppaste8: alphaeus pasted "memoize with recur" at http://paste.lisp.org/display/85081

2:29 cark: waitwaitwait

2:29 alphaeus: cark: hiredman: in that paste I have some code that appears to me to be sped up using memoize with recur

2:29 cark: it isn't

2:29 you're memoizing another function

2:30 (memoize collatz-length)

2:30 instead of function1

2:30 kotarak: I think one cannot memoize recur. Only real recursive calls.

2:30 alphaeus: oh sorry, I was trying to simplify the code. same result if that were to say memoize function1

2:31 hiredman: well

2:31 kotarak: Since recur is not a recursive call.

2:31 hiredman: I can appear to make coins disapear

2:31 but they don't

2:32 Fossi: you do? :o

2:34 hiredman: alphaeus: I don't know what the actual reason for the apparent speed up is, but I can tell you, based on knowledge of the recur mechanism and the source of the memoize function, that recur does not participate in "memoized" calls

2:35 alphaeus: hiredman: ok, that's what I thought from looking at the source, I just couldn't think of another explanation for the 4x speedup

2:36 hiredman: jit?

2:37 alphaeus: I don't think so because if I swap them and run the memoized version first it is still 4x faster.

2:42 http://www.fatvat.co.uk/2009/05/levenshtein-distance-in-clojure-ii.html

2:42 bottom of the third paragraph there sure seems to imply that recur uses memoize

2:44 kotarak: This is not recur. This is a real recursive call.

2:45 hiredman: I am telling you, any website url you paste, no matter what it implies, recur cannot interact with the memoize mechanism as implemented by the memoize function

2:45 _bottomline_

2:52 bradbeveridge: hiredman: what do you mean by "cannot interact"?

2:52 hiredman: bradbeveridge: recur exists within a function

2:53 memoize just wraps the function in another function

2:53 bradbeveridge: yes - recur is basically a goto to a loop or function point

2:53 hiredman: that first function is still there, and recur will recur to that function

2:53 bradbeveridge: oh, you're saying that previous results of recur cannot be memoized naievely?

2:53 kotarak: and hence cannot work with memoize (as it is now), because the function is not called again.

2:54 bradbeveridge: when you memoize a function, it is only replaced once

2:54 hiredman: bradbeveridge: I am saying when you recur, it does not go back through the memoize logic

2:54 it recurs to the first function frame

2:56 bradbeveridge: yes. If you want recur to work in a memoized fashion, you'd need to do the caching yourself

6:33 maacl: Has anyone seen examples of calling Jython functions from Clojure?

7:57 Fossi: damn

7:57 i'm sick of these release cycles

7:59 i really wonder how hard it would be to make a compiler to .dex

8:04 being register based makes it a little funky

8:55 andyfingerhut: Rich, I recently re-listened to your "Clojure for Lisp Programmers" talk from the Boston Lisp meeting, and there were several questions regarding transactions and agents involving what could go wrong if transactions were not pure functions, etc. I was wondering how useful you thought it might be if there were a function that could (at least in some cases, perhaps common ones) determine whether a function was pure or not. Yo

8:56 Shoot, that was way longer than it looked while I was thinking it :-)

9:15 Chousuke: the io! macro can be used to make a block of code throw an exception if run inside a transaction

9:16 Fossi: which would mean that you would have to flag it before it's being called in one

9:16 which is the unlikely case, or not?

9:16 i mean, it could be considered good style to wrap everything in io!

9:16 Chousuke: well, you could use it inside a function

9:17 and then trying to use that function in a transaction would cause an error

9:17 Fossi: yeah, but then i have to know beforehand that it will be tried

9:17 which i think is unlikely

9:17 Chousuke: hm? :/

9:17 tried?

9:18 Fossi: so i guess i should wrap all sideeffects with io!, to be sure nobody calls them in one

9:18 s/one/a transaction

9:18 Chousuke: well, usually you should keep side-effects in their own functions anyway.

9:18 clojurebot: functions are maps

9:18 Chousuke: separate from pure functions.

9:20 andyfingerhut: But I'm wondering -- if someone never used io! in their code, how tricky can it be to detect whether the function is pure or not, with an algorithm, not with a person reading over it?

9:21 Chousuke: I think it

9:21 ...it's not possible

9:21 andyfingerhut: I'm guessing it cannot be decided in general, but what are the tricky cases?

9:21 Fossi: calling into java would be a sideeffect i guess?

9:21 Chousuke: anything that calls java, or functions not explicitly marked as pure.

9:22 or anything called in an environment with dynamically rebound variables

9:22 andyfingerhut: I agree, calling into Java would be a bit of a tarpit, unless you also wrote a program to decide whether Java methods were pure or not. What would be next most tricky after Java calls?

9:23 Chousuke: you could do (binding [+ evil-+] ...) and "break" pure functions.

9:26 andyfingerhut: Hmmm. I'm missing something. Why doesn't this exhibit your evil-+ behavior? (binding [+ (fn [x y] (- x y))] (+ 4 2)) evaluates to 6 in my REPL. I guess it is because the second + is really clojure.core/+ ?

9:28 Chousuke: hmm

9:28 andyfingerhut: Yep, that must be it. (binding [my-fun1 evil-my-fun1] ...) does override an earlier (my-fun1 ...) in the same namespace.

9:28 Chousuke: ,(binding [+ -] (+ 4 2))

9:28 clojurebot: 6

9:28 Chousuke: ,(binding [+ -] (#'+ 4 2))

9:28 clojurebot: 2

9:29 Chousuke: ,(binding [+ -] (#(+ 4 2)))

9:29 clojurebot: 6

9:29 Chousuke: hm

9:29 ,(binding [clojure.core/+ -] (+ 4 2))

9:29 clojurebot: 6

9:29 Chousuke: puzzling

9:30 ,(let [foo #(+ %1 %2)] (binding [clojure.core/+ -] (foo 4 2)))

9:30 clojurebot: 6

9:30 andyfingerhut: But for user-defined functions, it is easy to rebind, so that can make it a more global program property to decide whether a particular function x that calls another function y is pure or not. It is if y is pure, but the tricky part is knowing what the definition of y is at the time of the call.

9:30 Chousuke: ah

9:31 inlining!

9:31 ,(binding [+ -] (+ 4 2 3))

9:31 clojurebot: -1

9:32 Fossi: heh. extra confusing ;D

9:33 ,(binding [+ -] [(+ 4 2 3) (+ 4 2)])

9:33 clojurebot: [-1 6]

9:33 Chousuke: I wonder if that's a bug or just a gotcha :P

9:33 Fossi: that would be terrible hard to find out ;D

9:34 andyfingerhut: OK, let's back off from that for a second, and ask whether we can make a program that takes the text of one function foo, and perhaps give an answer like "foo is pure, if the functions bar and baz, called within foo, are pure"

9:34 Fossi: if you really don't like your collegues you write that somewhere up the chain

9:36 andyfingerhut: but it doesn't necessarily try to determine what the bindings of bar and baz are, although in the absence of dynamic bindings, a programmer could run the same program on the source code of bar and baz, and so on, until they got a warm fuzzy feeling :)

9:40 I'm not trying to be frustrating here -- I'm recording the tricky cases as we go. I just want to peel the onion a little and see what the next tricky cases might be.

9:41 Chousuke: is there an easy case? :)

9:43 andyfingerhut: Well, I think I can say that if none of +, -, *, / etc are rebound, then a function with args [x y z] that only calls those functions and uses values x, y, and z is pure. Generalize to other known pure functions besides +, -, *, /

9:44 I think I can throw in uses of let, loop/recur, cond, if, when, and a few other things like that for good measure.

9:45 There should be plenty of useful functions one can write that are straightforward to see for a human, and for a program to automatically decide, are pure.

9:45 Chousuke: hmm

9:46 it probably helps if you macroexpand the function first, too :)

9:46 andyfingerhut: definitely

9:46 For which we've got clojure.contrib.macro-utils

9:47 That gets the number of special forms down to a more manageable number.

9:48 Chousuke: though, higher order functions will still be a problem :/

9:49 you'd have to know which parameters are functions.

9:50 andyfingerhut: Well, map is pure if the function you pass to it is pure. That is similar to saying that (defn my-plus [x y] (+ x y)) is pure as long as + hasn't been rebound to something non-pure.

9:50 i.e. it is a "conditional guarantee".

9:51 Given that can be violated with sufficiently tricky uses of binding, I'm willing to think of the output of such a function as hints for a developer, rather than something that makes guarantees on its own.

9:51 Fossi: time to hack away at the dalvik dexer with clojure, making it more parallel ;D

9:51 clojurebot: "[Clojure ...] feels like a general-purpose language beamed back from the near future."

9:56 andyfingerhut: I guess exceptions are not exactly pure, and some things that are "normally pure" like nth can throw exceptions

9:59 Chousuke: andyfingerhut: functions that throw exceptions are pure as long as the outcome depends only on the parameters.

10:00 it's just undefined for certain values, like division by zero.

10:01 andyfingerhut: Sure. I guess if I'm willing to "document" gaping holes like "pure if bar and baz haven't been dynamically rebound", then tossing in "may throw an exception rather than return a value normally" is fine, too.

10:12 pdo: Newbie question: anybody doing anything with complex numbers in Clojure?

10:20 I'm new to Clojure and am wondering if there are any libraries available for complex arithmetic? I have some common lisp code I want to translate to Clojure.

10:22 Fossi: might be in contrib

10:22 http://code.google.com/p/clojure-contrib/wiki/ComplexNumbersApiDoc seems pretty unfinished

10:23 pdo: Thanks Fossi, will take a look.

10:24 Fossi: http://www.mail-archive.com/clojure@googlegroups.com/msg11037.html seems to be the 'announcement'

12:06 AWizzArd: Let's say I have a Java method foo which takes a clojure function object f and wants to calls it, and then returning the return value of (f). How should the Java code look like?

12:06 public Object foo(clojure.lang.Function x) { return RT.call(x); } or something like that?

12:06 I am looking especially for the call hook, the method which will do the call

12:07 (defn foo [function] (function)) is the equivalent in Clojure.

12:10 leafw: AWizzArd: since all fn are objects and implement Callable, then return x.call() (without arguments) should be what you want.

12:11 AWizzArd: i only guessed that "call" is the right name

12:11 okay, so I will try that

12:12 funny :)

12:12 thx leafw

12:12 leafw: you're welcome.

12:14 AWizzArd: http://clojure.org/special_forms#fn provides some extended info. It says, among other things, that you can use x.invoke(arg1, arg2); if you need to.

12:20 AWizzArd: Oh thanks, this is good

12:24 leafw: I am writing a Clojure lib which will make a Java lib usable, and that Java lib takes strings that can also include Java code which will be executed.

12:25 As I don't want to have my Clojure users write Java but Clojure instead, I will need a mechanism to call that Clojure code.

12:48 leafw: AWizzArd: reading

12:49 AWizzArd: so you want a clojure user to programmatically pass a String containing clojure code to a java program that then will execute the clojure code?

12:49 it's doable: you need a PushBackLineReader and just parse it, like the old clojure.lang.Repl class used to do (see a few revisons back, before it was emptied.)

13:20 AWizzArd: I think i have even fewer requirements. Having my users use a macro which will do all the magic under the hood will be fine.

13:20 I will let you know in some days/weeks, depending on how much time I have to progress with the project.

16:20 ataggart: Anyone else occasionally overcome with joy when writing in clojure?

16:21 hiredman: I have a high tolerance for joy

16:22 ataggart: it might be the large run and coke I have next to me

16:22 *sum

16:22 *rum

16:26 Raynes: ataggart: I think it's the Clojure.

16:26 ataggart: heh, concurrent use of both is ideal

16:28 Fossi1: synchronous? asynchronous?

16:28 organized?

16:30 mark_the_pirate: does anybody know of a good way to kill an infinitely looping script in the slime+emacs repl without having to restart emacs?

16:31 killing the slime buffer i start the loop in doesn't seem to work

16:34 ataggart: Fossi1: Right now its synchronous; if I had a straw I could make the process asynchronous.

16:34 Fossi1: ataggart: you need an agent

16:34 ataggart: agreed, alas my gf is out of town

16:44 is it improper (or is there a better idiom) to use an agent to perform logging even if the agent holds no useful state? The only reason I'm using agents is so that logging behave correctly within a tx

16:47 Fossi1: logging is a side effect, so why not?

16:48 ataggart: yep, the rub is I have to pass it an action function that will ignore the first arg

16:48 so it looks bit messy

16:49 Fossi1: dunno, i'm not the crack really

16:49 off to bed. n8.

17:08 hiredman: ~the mosth horrible thing?

17:08 clojurebot: I don't understand.

17:08 hiredman: ~the most horrible thing?

17:08 clojurebot: most horrible thing is http://tinyurl.com/b65o8e

17:14 ataggart: n: awesome

17:14 hiredman: awesome

17:15 alrex021: I have a (let [guest (session :login)]) ... how do I assign a value to guest if :login is nil in session, within the same block?

17:21 hiredman: alrex021: you can give a default value

17:21 (session :login default-value)

17:22 or (:login session default-value)

17:22 alrex021: ahh, I c

17:22 hiredman: or (get session :login default-value)

17:22 alrex021: so session being a map...it is also a func that takes default val

17:23 hiredman: oh

17:23 I just sort of assumed session was a map

17:23 it is, right?

17:23 alrex021: yup it is

17:24 as far as I know...:) ...I am trying to use compojure .... with-session

17:24 d2dchat: How would you get a random item from a vector?

17:25 alrex021: so I am trying to check if session has a :login key.....if not, do session-assoc to associate :login with current session

17:26 it works...but my control flow not looking right yet

17:26 hiredman: ,([1 2 3 4] (rand-int 3))

17:26 clojurebot: 2

17:26 hiredman: ,([1 2 3 4] (rand-int 3))

17:26 clojurebot: 3

17:26 hiredman: alrex021: you can use if-let

17:26 alrex021: ;hiredman

17:27 hiredman: I just came across that macro a sec a go...cool thx

17:28 d2dchat: hiredman: thx! Although it never hit 4

17:28 after 20 tries

17:28 lol

17:28 hiredman: ,(rand-int)

17:28 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$rand-int

17:28 hiredman: er

17:28 ,(doc rand-int)

17:28 clojurebot: "([n]); Returns a random integer between 0 (inclusive) and n (exclusive)."

17:28 d2dchat: right, does the vector index start at 0?

17:28 hiredman: of course

17:28 d2dchat: Try seeign if you ever get 4

17:30 hiredman: you won't with rand-int of 3

17:30 d2dchat: so rand-int 4 then?

17:31 hiredman: d2dchat: what do you think?

17:34 d2dchat: (def my-vector [1 2 3 4])

17:34 (my-vector (rand-int (count my-vector)))

17:35 seems to work :)

18:10 alrex021: could someone pls explain how I go about using the if-let

18:11 I am looking at the clojure api, but don't understand how to use this macro

18:14 hiredman: ,(if-let [a false] a :not-a)

18:14 clojurebot: :not-a

18:14 hiredman: ,(if-let [a nil] a :not-a)

18:14 clojurebot: :not-a

18:15 hiredman: ,(if-let [a (+ 1 2)] a :not-a)

18:15 clojurebot: 3

18:24 alrex021: hiredman: http://clojure.pastebin.com/m18c956bf

18:24 line 3 is my problem

18:24 the guest-account generates a guest account

18:25 but I also need to bind that result form that function to session-assoc

18:26 so something like: (let [guest (session :login (session-assoc :login (guest-account)))] ... however session-assoc doesn't return the value...so I have to run session-assoc and return result from guest-account

18:27 so my code in pastebin is running but session never has :login, because session-assoc is not called...I need to somehow added like above code

18:27 I'm have tried about 100 different ways so far :(

19:29 osaunders: I'm confused. Is Clojure object-oriented? How do I create an object?

19:34 Chousuke: osaunders: clojure is not very object oriented.

19:34 osaunders: it has access to the java facilities, but Java OO is not really idiomatic clojure.

19:38 osaunders: usually, you just write functions that take in certain kinds of data structures and output other kinds of data structures. the exact class is not relevant.

19:39 osaunders: many clojure core functions work on "sequences" and there are many things that can work as a sequence.

20:38 Anniepoo: ,(doc vector)

20:38 clojurebot: "([] [& args]); Creates a new vector containing the args."

20:38 Anniepoo: how am I to read the arg list of that?

20:39 hiredman: Anniepoo: it meens vector is a multifn, one definition takes no args, one takes a variable number of args

20:39 Anniepoo: ah, ok, thanks

20:54 hmm... using my first multimethod, and wondering if I should be

20:55 my code preps data to be transmitted to another system, so I need at some points to be talking to it in

20:55 the other system's (typed) language (LSL, if you're wondering)

20:55 I have some 'type hint' functions that add metadata saying how to encode as LSL

20:56 (defn lsl-int [x] #^{:lsltype TYPE_INTEGER} (int x))

20:58 now I have some method (in this case, serialize) and want tohave it do the right thing will all these various types

20:59 Anniepoo[1]: sorry, bailed

21:06 melling: I just tried this on a Mac on got "No such namespace: Double" --- http://clojure.org/jvm_hosted

21:07 Java 1.6

21:08 arbscht: what version of clojure are you using?

21:09 melling: 1.0

21:10 arbscht: you might want to try a newer build

21:11 melling: that was the latest from clojure.org

21:11 need to check out src?

21:12 arbscht: yes, http://github.com/richhickey/clojure/tree/master

21:12 melling: k. thx.

21:14 arbscht: hm, just tried and it works for me with clojure 1.0 on java 1.6

21:16 melling: on mac?

21:16 arbscht: no, GNU/Linux

21:16 melling: let me check out on my linux box.

21:16 arbscht: how are you loading and running the example?

21:22 melling: works on my Fedora 9 system.

21:22 java -cp clojure.jar foo.clj

21:23 clojure.lang.Repl

21:23 forgot that.

21:24 maybe i have my Java 1.6 CLASSPATH whacked on my mac?

21:24 arbscht: seems likely

21:41 LauJensen: Good night gents

21:59 Noones having a good night?

22:00 arbscht: it isn't night time yet :)

22:00 LauJensen: oh - its 04:01 here

22:05 Anniepoo: clojurebot paste

22:06 darn, how do you address a message to the clojurebot?

22:06 arbscht: clojurebot: paste

22:06 clojurebot: lisppaste8, url

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

22:07 Anniepoo: thanks

22:07 clojurebot: paste

22:07 clojurebot: lisppaste8, url

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

22:08 Anniepoo pasted "untitled" at http://paste.lisp.org/display/85106

22:08 LauJensen: Anniepoo: Why always "untitled" ?

22:08 Anniepoo: am I doing a bad thing naming files like this?

22:09 what good would a name do? nobody on earth will be interested in this in 5 minutes

22:10 my question is "am I doing a bad thing naming files like this?"

22:10 LauJensen: I sometimes review the list to find interesting pastes. I have to check everyone named "untitled"

22:10 Anniepoo: my repl's obviously looking for a java-compatible filename

22:10 ah, sorry, good reason not to

22:10 then I'll start naming them

22:10 I usually set the expiration

22:11 as well

22:11 LauJensen: Thanks. Regarding the name there is a java convention about using - in namespaces and _ in files. Or perhaps the other way around. You can check out contrib for examples, like lazy-seq

22:12 Anniepoo: ok, so if my namespace is foo-utils it should be in a file called foo_utils.clj

22:12 8cD we are happy to comply

22:12 might be why my repl seems so broken

22:13 LauJensen: It might be like that, I think you should check out lazy-seq in contrib, its more reliable than my faulty memory. For the same reason I never use anything but alphaNumeric in my naming :)

22:13 Anniepoo: yes, I was leery of - in names when I first saw it.

22:14 and there are no spaces in my directory names that *I* put there

22:19 even more puzzling, namespace edu.uh.test.testUploadDialog is in test-upload-dialog and works fine

22:20 LauJensen: The worst part about Lisp is Java :)

22:20 Are you using this from a .jar file or classes or what?

22:20 Anniepoo: inside IntelliJ

22:21 the source is supposedly on the classpath

22:21 LauJensen: Oh, then Im totally blank. I stick with Emacs and SLIME, and even with that cocktail SLIME can sometimes obscure the issue

22:22 Anniepoo: anyway, it looks like my problems not the underscores anyway.

22:22 LauJensen: ok

22:22 Are you sure, that you dont want to import it instead of using it?

22:23 (import '(edu.uh.hhp.sl.automation.primbot builder-bot-language)) ?

22:23 Anniepoo: no, it's a clojure file

22:23 I shouldn't import it

22:23 LauJensen: oh ok

22:24 Anniepoo: I think I'm about to give up my beloved IntelliJ and use emacs for this stuff

22:25 thanks for the help

22:26 I'm gonna take a break.

23:31 baetis-fly: can you provide different doc strings depending on the number of args to a function?

23:31 LauJensen: I dont know, but if you have the need I think you need to reconsider your design

23:32 No you cant

23:32 hiredman: baetis-fly: no, you don't look up docs via name+arg list you look them via the name

23:32 baetis-fly: many thanks.

23:34 i just seemed to recall (doc something) providing different strings after the different argument lists. my mistake.

Logging service provided by n01se.net