#clojure logs

2009-08-30

00:33liebketechnomancy: very cool image! I just posted a blog entry on using Processing from Clojure: bit.ly/VPCvF
00:34technomancyliebke: cool! I noticed you're moving some of Incanter over to that?
00:35technomancylove the header on that site btw.
00:35liebkeYeah, Processing provides a lot of flexibility for creating visualizations
00:35liebkethanks :)
00:36technomancyliebke: why did you fork clj-processing instead of adding it as a dependency? did you need to modify it too much?
00:36technomancyI contacted the clj-processing author; he seemed to be fairly open to contributions.
00:37liebkeyeah, I go into some of the changes I made in that blog entry. The biggest change was I wanted the PApplet argument to all the functions to be explicit instead of binding it to *applet*
00:38technomancyliebke: is that because you want to be able to juggle multiple applets at once?
00:38technomancyseems for regular processing visualizations it's nice to not have to think about that
00:40technomancyliebke: btw; I think you have the titles of the books mixed up
00:40liebkeI agree, the binding approach makes the api look more like the "real" Processing API, but it made it difficult to figure out which functions could be called outside of the PApplet's methods.
00:40liebkeAh, thanks... let me fix that
00:41technomancyI'm not sure what I think of the multiple versions (-float, -int) of some of the core processing functions; seems awkward
00:42technomancyalso I suggested allowing use of keywords instead of defing all the myriad Processing CONSTANTS
00:42liebkethat's why I merged those functions
00:42liebkeyes, keywords is a great idea
00:45technomancyalso I abstracted away the applet proxy: http://github.com/technomancy/clj-processing/blob/32f26eee13cf5b516f0ac4f33d7ade501a04b0aa/src/rosado/processing/applet.clj
00:45technomancyanyway, I wonder if it wouldn't be worth sharing code since I'm probably going to continue hacking clj-processing and you might want to pull in those updates.
00:46liebkenice approach
00:46liebkethere, fixed the book titles, thanks for pointing that out
00:46technomancymaybe make your non-binding applet functions in a layer on top of clj-processing so the codebases don't have to diverge.
00:47liebkehmm, interesting idea
00:47technomancyof course... handling dependencies in Clojure is not always a lot of fun. =\
00:48technomancybut it's worth considering
00:48technomancyI'm using Corkscrew for my Processing sketchbook experiments and it's not bad: http://github.com/technomancy/sketchbook/blob/6313522c8127a7d896e3d50347ec31b55484c411/project.clj
00:48liebkeI think it's a good idea
00:50andyfingerhutI've used clojure.contrib.trace/deftrace for tracing some Clojure functions, but I was wondering if there was something more like Common Lisp's trace/untrace available, where you can enter an expression at the REPL that enables/disables tracing for the named fn?
00:53technomancyliebke: well, I better take off. looking forward to seeing more on Incanter.
00:53technomancythat's some good stuff you've got going on.
00:53technomancybye!
00:53liebkeThanks, goodnight
00:55andyfingerhut_Or do people perhaps just change "defn" to/from "deftrace" and redefine the function? Or maybe people don't use tracing?
04:57Nate75Sandersin the clojure-dev screenshots on the clojure-dev webpage, do they have spell-checking disabled?
07:05ambientare Waterfront and Light the only text editors done in Clojure? I really like Emacs/SLIME but would like to see a simple REPL implementation done with Clojure. I can do so much with REPL that I might just not need a separate text editor at all. Adding paredit style editing to that and jumping to functions etc would probably work very well.
07:06ambientalso i've been wondering how well would binding namespaces to directories and instantly saving everything defined in a REPL to a file work
07:51ole3ambient: what is Waterfront and Light?
09:10ambientole3: http://sourceforge.net/projects/waterfront/ and http://code.google.com/p/lighttexteditor/
09:23wlrrhickey: re: juxt naming. Semantically comp does a math composition. Doesn't juxt semantically do a math right-distribution? So, maybe "rdist" would be an ugly but meaningful alternative.
09:30rhickeywlr: I think function composition is much more widely known. rdist wouldn't be meaningful to me. Have you got a reference link for right-distribution?
09:33wlrrhickey: http://en.wikipedia.org/wiki/Distributivity
09:33rhickeydistribution makes me think of probability distribution, and this is not distributivity
09:34wlri know. overloaded terms always present problems. distibuted programming is another.
11:13rhickeywlr: sorry, had to step away. ok, I could see how you could consider this right-distributive if you presume there is some concat operation between the fns and apply to the argset - ((juxt a b) x) === (a concat b) applyto x == (a applyto x) concat (b applyto x)
11:17rhickeystill not buying rdist though
11:17rhickey:)
11:19cemerickrhickey: you were right on with the isa? usage :-/
11:19rhickeycemerick: oh good
11:19cemerickheh. I did a :facepalm: when I verified it. I should have caught that early on.
11:23cemerickrhickey: direct isa? usage isn't actually discouraged though, is it?
11:25rhickeynot at all, I was just concerned as you talked about it in the context of multimethods. I wonder though that Java isn't doing more caching of its own to support isAssignableFrom. So far I haven't cached myself in the reflection code
11:26rhickeyyou should use isa? in preference to (contains? supers x) if possible
11:26rhickeyisa? asks a direct question while supers needs to gather
11:26cemerickI definitely don't use supers directly at all.
11:27cemerickThe typical usage is (isa? (type foo) ::some-keyword)
11:27rhickeyah
11:30cemerick...and our primary hierarchy has our set of entity interfaces being derived from higher-level 'types'...so the typical case has supers being called on a class object in every invocation of isa?
11:30rhickeygot it, that's not going to be very fast unless you route it through a multimethod
11:31cemerickyeah...which I obviously don't want to do :-)
11:37angermanis there a markdown parser for clojure?
11:43j-dotangerman: I'm not sure, but I believe the documentation generator for Clojure Contrib now supports markdown. I would check there.
11:44kotarakangerman: there is markdownj
11:44kotarakangerman: http://sourceforge.net/projects/markdownj/
11:51angermanhmmm > 2000loc ok
11:51Chouser&v
11:51Chousersorry
11:53cemerickrhickey: I've got a WeakHashMap-based memoize fn, and a patch to apply that memoization to supers (also easily applicable to bases, to help anyone using parents). Is this something you'd consider for inclusion?
11:53cemerickThe safety issue isn't really something I can determine conclusively.
11:54rhickeyno, I'm quite leery of WeakHashMap
11:55rhickeyalso I recommend against memoizing or otherwise dynamically binding standard fns
11:56cemerickOK -- is there a better approach I can take? It works well enough for us so far, but we have more control over execution environment, etc., than some.
11:56rhickeyyou can of course use your own memoized wrapper fns
11:57cemerickDon't worry, I am :-)
11:57cemerickI'd just like everyone to get the same benefits, if possible.
11:58rhickeysure, but the macro you posted scares me
11:58cemerickheh
11:59cemerickthat was just something I posted so others could easily see what the delta would be for their code.
11:59rhickeyone possibility is to ask a hierarchy to cache a relationship, as a function of the hierarchy
12:01rhickeyare you using your own hierarchy or the global one?
12:01cemerickoh, just the global one
12:02Chousercemerick: on real Java classes only, right?
12:02cemerickChouser: as opposed to fake ones?
12:02cemerick;-)
12:02Chouserheh. as opposed to keywords.
12:02rhickeyit would be relatively straightforward to have the global hierarchy cache isa? keyed on the identity of the hierarchy, as do multimethods
12:03Chouseror symbols
12:03rhickeyChouser: it's the relationships between real classes and keywords that aren't cached/fast
12:03Chouseroh, ok.
12:03rhickeycemerick: The typical usage is (isa? (type foo) ::some-keyword)
12:04cemerickChouser: just classes (interfaces, actually), and namespaced keywords
12:04Chouserok, ok. Sorry for slowing down the discussion.
12:04cemerickrhickey: wouldn't isa? caching have the same issues as memoizing supers, etc?
12:05ambientanyone want to help me with my newbie problem ~20 lines with Java interop? http://paste.lisp.org/+1UK7 I just can't figure out what's causing the error
12:06rhickeycemerick: which issues? class unloading? hierarchy modifications?
12:06cemerickrhickey: Yes :-)
12:06rhickeythey ar edifferent
12:07cemerickactually, supers memoization doesn't affect hierarchy mods, as that's only dealing with classes
12:08Chouserambient: that is indeed odd. You can try (def synth (MidiSystem/getSynthesizer))
12:08Chouserambient: that is indeed odd. You can try (def synth (MidiSystem/getSynthesizer))er
12:08Chouserer
12:09Chouser(def #^Synthesizer synth (MidiSystem/getSynthesizer))
12:09Chouserambient: I can't test that because I'm getting Unavailable expecetions, but it might help.
12:10tashafa,((fn [& v] (apply + v)) 1 2 3)
12:10clojurebot6
12:10ambientok, seems that that did the trick :) I already tried type hints but seems I put them in the wrong place
12:10ambientthanks
12:11Chouserambient: it shouldn't be necessary though. It seems you may have found a discrepency between the compile-time reflection and the runtime reflection code.
12:13ambientmight just be that my Emacs repl is somehow broken
12:13Chouserambient: what's the specific class of Synthesizer that you get?
12:13ambientMixerSynth, but I get it both ways
12:13ambientwith or without type hints
12:14Chouserright
12:14Chouseryou would.
12:14Chouserwhat package is that in?
12:14ambientjavax.sound.midi
12:15ambientiirc
12:15Chouser,javax.sound.midi.MixerSynth
12:15clojurebotjava.lang.ClassNotFoundException: javax.sound.midi.MixerSynth
12:15Chouser,(class (MidiSystem/getSynthesizer))
12:15clojurebotjava.lang.Exception: No such namespace: MidiSystem
12:15Chouser,(class (javax.sound.midi.MidiSystem/getSynthesizer))
12:15clojurebotjavax.sound.midi.MidiUnavailableException
12:16Chouserheh. no playing of midi on clojurebot's server...
12:16Chousermaybe com.sun.media.sound.MixerSynth
12:16JAS415oh man, does clojurebot do techno now?
12:16Licenserdun dun dun :)
12:17rhickeyjava.lang.IllegalArgumentException: Can't call public method of non-public class: public javax.sound.midi.MidiChannel[] com.sun.media.sound.AbstractPlayer.getChannels()
12:18ambientsome JRE's are missing the soundbank from their folders though. don't know about JDK's
12:18tashafa,((fn [& v] (apply + &v)) '(1 2 3))
12:18clojurebotjava.lang.Exception: Unable to resolve symbol: &v in this context
12:19tashafa,((fn [&v] (apply + &v)) '(1 2 3))
12:19clojurebot6
12:19rhickeybetter message with the latest it seems, but this explains why the call must go through the interface via hints (the 'weird reason' the latter works is that the call to static method yields a return value of known type to the compiler)
12:19rhickeythe def'ed synth is just Object to the compiler
12:22tashafa,((fn [&v] (apply + &v)) 1)
12:22clojurebotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer
12:23tashafasorry i'll go play in my repl now :)
12:26LicenserIs there a way to get some more epxressive messagesion from the REPL?
12:26LicenserI've seen some nice stuff in the videos, where an exception sayed which line it came from and showed a little stack trace
12:27ambientwell if someone has that, then i need to get some too!
12:28swdunlopThere are a couple nice hints about stack traces at http://jackndempsey.blogspot.com/2009/07/opening-your-mind-with-clojure.html
12:51Licenserswdunlop: thanks
12:51swdunlopGlad to help. :)
13:00rlbISTR someone mentioning something like and-let*. Does clojure have something similar?
13:13swdunloprlb: Interesting form.. Just read SRFI-2. I haven't seen anything like it in Clojure..
13:14rlbI supppose condp :>> is at least a bit related.
13:18swdunlopIt would be an easy macro to write, just depends on how you wanted to handle the nonlocal exit.
13:18swdunlopI'm assuming just cheating and doing (let [...] (and ...)) is unsatisfactory. :)
13:21cemerickI wonder why Rich is uncomfortable with WeakhashMaps
13:29LauJensenGood evening gents
13:30swdunlopEvening.
13:34rlbswdunlop: right, it's just a syntactic sugar. And actually I was really thinking of the case where you need the value of an if guard in the true clause.
13:34rlbs/true/then/
13:35ChouserI haven't looked -- is that different from if-let?
13:35rlbChouser: ahh, perhaps that's what I was thinking of (and maybe it was you who mentioned it before...). I'll look.
13:36rlbChouser: Looks like that's exactly it. Thanks.
13:37swdunlopChouser: It's similar. Sort of a chained if-let.
13:37rlb(and by exactly it -- exactly what I was thinking of)
13:38swdunlopIf I'm understanding if-let correctly, it permits you to bind the result of the test clause to if to a variable, then use that result in the branches, correct?
13:39Chouserin the 'true' branch anyway
13:40swdunlopand-let* binds each clause in a shortcutting and form.
13:40Chouseryeah, only the true branch.
13:40Chouserif-let can sometimes interact nicely with destructuring, since the latter is only attempted in the true case.
13:42swdunlopYeah. I can see how if-let could be a useful idiom, too. I tend to do a lot of (let [x ..] (if x ..)).
13:42swdunlopand-let is a more general form of if-let, I believe.
13:42rlbIs there an idomatic way to build up a map with optional elements? Of course I know you can build the map with the non-optional elements, and then conj or assoc the optional ones.
13:43swdunloprlb: Like struct v. struct-map ?
13:43Chouserrlb: I've run into that a few times. also with seqs for vectors, but I've not seen a pleasant way to handle it.
13:44swdunlopI'm a Clojure newbie myself.. Coming over from Mosquito. :)
13:44Chousukeif the optional elements have default values, you could have a constant map to use as a base.
13:44rlbChousuke: right. I'm talking about cases where the elements shouldn't exist if they don't have a value.
13:45rlbi.e. you can do (conj m (if x [:x x] []) ...), but I wondered if there was something better...
13:45Chouserfor lists and vectors, you can abuse ` and ~@ ...but that doesn't work for maps.
13:45rlbChouser: ok, thanks.
13:45Chouser, `[:a 1, ~@(when true [:b 2]), :c 3]
13:45clojurebot[:a 1 :b 2 :c 3]
13:46Chouser, `[:a 1, ~@(when false [:b 2]), :c 3]
13:46clojurebot[:a 1 :c 3]
13:46Chouser, `{:a 1, ~@(when true [:b 2]), :c 3}
13:46clojurebot5
13:46Chouseruh
13:46Chousertry that last one yourself. It don't really return 5
13:48rlbI suppose you could also just write the whole construction as one conj with if clauses for the optional members, though presumably that might be a bit less efficient.
13:48rlbChouser: anyway, thanks.
13:49Chouserrlb: so I don't know anyway but to it using conj or assoc after-the-fact. Even then it ca be a bit messy.
13:49Chouser,(-> {:a 1, :c 3} (#(if true (assoc % :b 2) %)) (#(if true (assoc % :d 4) %)))
13:49clojurebot{:d 4, :b 2, :a 1, :c 3}
13:50rlbRight. I was just using (let [x {...}] (conj x (if ...) (if ...))).
13:51Chouser,(into {:a 1, :c 3} (concat (when true [[:b 2]]) (when true [[:d 4]])))
13:51clojurebot{:d 4, :b 2, :a 1, :c 3}
13:52Chouserhm, conj is better than into/concat
13:52Chousukehow about a "maybe-zipmap"? :P
13:52Chouserrlb: yeah, that's the best I've seen yet.
13:53Chouser,(conj {:a 1, :c 3} (when false [:b 2]) (when true [:d 4]))
13:53clojurebot{:d 4, :a 1, :c 3}
13:53Chouserno good for vectors or lists, but good to keep in mind for maps
13:54rlbChouser: "when" is an improvement.
13:56Chouserconj isn't using transients (yet)
13:56rlbChouser: since if guarantees nil when else is missing, if would be fine without an else clause too.
13:57Chouseryes. My understanding is that using 'when' is the preferred style when there is no else clause. *shrug*
13:58rlbyeah, that's fine.
15:14ankouhi, what do I need to do to tell slime where to find clojure?
15:14ankou*on linux
15:26juhalhi, can anyone explain why this fails
15:26juhal(let [hello #(println %)] (eval '(hello "world")))
15:26juhalbut this doesn't
15:26juhal(let [hello #(println %)] (hello "world"))
15:27juhalor how I can make the former work?
15:27rlbjuhal: I haven't use eval in clojure, but I would suspect that eval doesn't evaluate in an envt where hello is visible.
15:28rlbi.e. hello's a local binding, and eval doesn't operate in the local scope.
15:28rlbbut I'm just guessing.
15:29rlbIn guile for example, IIRC, local-eval might do what you seem to want.
15:30juhalthere doesn't seem to be local-eval in clojure
15:30dreishjuhal: What are you trying to do?
15:31rlbdreish: (yes, better question)
15:34juhalI'm writing a clojure based DSL for configuring a system. The configuration contains settings where I want to evaluate arbitrary expressions. Those expressions contain calls to domain specific functions.
15:35dreishSo why are you trying to create them with let instead of defn?
15:36dreishNevermind. Here's the closest alternative in Clojure:
15:36dreish(declare hello)
15:37dreish(binding [hello #(println %)] (eval '(hello "world")))
15:37rlbjuhal: also note that if you have any security/safety concerns, you'll need some kind of restricted reader -- either an envt with no unsafe functions (if that's possible in clojure), or your own (hopefully fairly simple) sexp parser.
15:38Chousukehm, can't you just bind *read-eval* to false?
15:38rlbAgain, in guile, for example, you can create an empty environment and then populate it with whatever you want, then call eval in that envt. I don't know if clojure has something similar.
15:39Chousukeah, never mind, that would only allow you to read the config, not eval it :/
15:39rlbChousuke: would that prevent someone from calling "rm -rf /"?
15:39rlbin the config file?
15:39rlbThat's what I was wondering about.
15:39rlbi.e. can you create an eval environment in clojure that's "safe"?
15:40Chousukerlb: well, it'd basically disallow any evals from just reading the config.
15:40rlbfor whatever your definition of safe is.
15:40Chousukeso you can at least read the file safely.
15:40rlbAhh. The nice thing about the "safe envt" approach is that it makes it much easier to use the language itself as a config file, even for things where safety might matter.
15:40Chousukeevaling it safely is trickier. probably needs code-walking.
15:41Chousukebecause of .
15:41rlbChousuke: or the ability to create an environment that just doesn't have any unsafe bindings...
15:41rlbi.e. (eval foo safe-envt)
15:41Chousukethat's not possible in Clojure at the moment
15:41Chousukebecause of . :)
15:41rlbor (load foo safe-envt)
15:41Chousukethough you *can* use the java sandbox...
15:41rlbChousuke: right, you'd have to omit . from the envt.
15:41Chousuke,(System/exit 0
15:41clojurebotEOF while reading
15:42Chousuke,(System/exit 0 )
15:42clojurebotjava.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.0)
15:42Chousukebut that's still DOSable
15:42rlbChousuke: ahh, I wondered about that -- perhaps that's an alternate approach in some cases.
15:43rlbChousuke: well, even the safe-envt approach I was talking about is probably DOSable, depending on your criteria.
15:43rlb(unless it has no loop constructs, input limits, etc. ;>)
15:44Chousukeit might be useful to be able to arbitrarily disallow some special forms and reader macros...
15:44Chousukebut that probably needs clojure-in-clojure :)
15:44juhalI'm not too concerned with the security issues at this point. I just want to make it work. I was looking for something like the local-eval thing guile has.
15:45rlbjuhal: could you not just load the file and use macros, etc. to build the DSL?
15:45rlbor do you need something sufficiently different from clojure itself, language-wise?
15:45juhalI tried that but the macros got too complicated for a lisp newbie like me
15:45rlb(i.e. is the DSL not sexp based, etc.)
15:46juhalso I ended just parsing the sexps
15:47juhalanyway dresish's workaround seems ok if not elegant
15:47juhalthank's for the suggestion
16:01juhalsigh the binding trick didn't work when going through a proxy object
16:01juhalwhen will I ever learn not to try anything fancy
16:16rlbIs (seq some-set) the appropriate way to convert a set to a list?
16:17rlbActually, maybe that's not what I meant to do...
16:27hiredmanrlb: seq returns a sequence, not a list
16:52hamzahey guys, i have a vector of keywords i would like to append them in to string one after another, how can i a turn a keyword to a string?
16:54LauJensen,(name :foo)
16:54clojurebot"foo"
16:54Chouser,(apply str [:foo :Bar :baz])
16:54clojurebot":foo:Bar:baz"
16:58hamzathx that works.
16:58hamzaone other thing why i can't i use name in apply?
16:58hamza,(apply name [:foo :bar :baz])
16:58clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$name
16:59Chousername takes just one arg
16:59arbschtbecause that effectively calls (name :foo :bar :baz)
17:00Chouser(apply str (map name [:foo :bar :baz]))
17:00Chouser,(apply str (map name [:foo :bar :baz]))
17:00clojurebot"foobarbaz"
17:01hamzakk so map applies the function one by one but apply passes the whole vector right?
17:02LauJensen,(doc apply)
17:02clojurebot"([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."
17:02LauJensen,(doc map)
17:02clojurebot"([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."
17:03hamzathank you.
17:08LauJensennp, if you're running emacs you can fetch those docs straight in your slime-repl
17:10hamzai am using emacs but using inferior lisp, i will check out slime heard a lot about it.
17:42hamzais it possible to do a post request from clojure or do resort to urlconnection?
17:51arbschthamza: there are http libs in clojure.contrib
17:52rlbhamza: this might help http://gnuvince.wordpress.com/2008/10/31/fetching-web-comics-with-clojure-part-1/
17:53hiredmanthat is an old tutorial, so watch out
17:54hamzathank you.
17:54rlbThis will open a stream on a url: (with-open [in (.openStream (URL. address)) ...)
17:55rlbYou might also be able to use duck-streams reader/writer, but I'm not sure offhand.
18:55krumholt__at the start of my file i use (ns my.namespace (:use some.lib)) but i am not able to load my file with (load-file myfile.clj) until i add a line (refer 'some.lib). that should be redundant because i already said (:use ...?
19:02carkshould be (ns my.namespace (:use [some.lib]))
19:03cemerick(:use foo.bar) is just fine
19:03cemerickas is (:require foo.bar)
19:03carkhum ok
19:04carki've always put these in a vector ...for what reason i don't know
19:05cemerickI generally do as well, as (:require [foo.bar :as baz]) is most idiomatic
19:07carkanyways to answer the question, yes it is redundant
19:10krumholt__hm but it is not working without the call to refer
19:10krumholt__maybe i need to put it in a vector
19:11carkmhh maybe your some.lib file is not at the right place
19:11carkwhat's the error you get ?
19:11krumholt__unable to resolve symbol
19:12carkhum you need double quotes around the filename here (load-file myfile.clj) ?
19:12krumholt__yes have that
19:13krumholt__it starts to load the file and then complains that it cannot find a function
19:13krumholt__from some.lib
19:13carkthat's strange, you'd get an error if the lib was not used
19:14krumholt__i just add the line (refer 'my.lib) and everything works
19:16krumholt__it's not that much of a problem. i mean it works in the end i was just wondering what the underlying problem could be
19:33Chouserif file a.clj had (ns a (:use b)), you should not need a (refer b) in that same file.
19:34Chouserif some other place (file c or a repl) does (load-file "a.clj"), you still can't use the names from b until you do (refer b)
19:38krumholt__Chouser, ok thanks that explains it. i can't load-file from the repl
19:48pluijzerCan a function that relies upon a external constant variable be considered a pure function?
19:51pluijzerCan a function that relies upon a external constant variable be considered a pure function?
19:51rathore_i dont see why not
19:53pluijzerwell the functions then has a "relevant environment"
19:58hiredmanwell, if it is really constant...
20:06pluijzeryes 4, 6 and pi are really constant too, but what if it relied upon a constant global variable, the function could behave differently in different programs.
20:06hiredmanthat is not a constant
20:07pluijzerokay
20:07pluijzerso no :)