#clojure log - Sep 26 2009

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

1:37 LauJensen: Morning gents

1:57 wavister1: ~def doubles

2:25 LauJensen: ,(use 'clojure.contrib.pprint)

2:25 clojurebot: nil

2:29 LauJensen: java.lang.ClassNotFoundException: clojure.contrib.pprint.PrettyWriter (pprint.clj:14)

2:29 I get that when calling the above use statement, using latest contrib - w00t?

2:37 Can somebody from the contrib team tell me if this is an error in your build (which Google leads me to think), or if Im missing something?

2:42 leafw: how can one declare the type of an array? like #^String[] ?

2:43 will that work?

2:45 doesn't work

2:46 arbscht: ,(doc into-array)

2:46 clojurebot: "([aseq] [type aseq]); Returns an array with components set to the values in aseq. The array's component type is type if provided, or the type of the first value in aseq if present, or Object. All values in aseq must be compatible with the component type. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

2:48 LauJensen: ,(doc make-array)

2:48 clojurebot: "([type len] [type dim & more-dims]); Creates and returns an array of instances of the specified class of the specified dimension(s). Note that a class object is required. Class objects can be obtained by using their imported or fully-qualified name. Class objects for the primitive types can be obtained using, e.g., Integer/TYPE."

2:49 LauJensen: arbscht: Since you're up - Can you test if you can use pprint ?

2:49 arbscht: I suppose I could

2:55 LauJensen: got a test case?

2:55 LauJensen: yea, fire up a REPL having contrib in your cp, eval (use 'clojure.contrib.pprint) and see what happends

2:56 Mine will bork saying it cant find PrettyWriter.clj

2:56 @ arbscht

2:56 arbscht: works for me

2:56 LauJensen: How old is your contrib?

2:56 arbscht: up to date as of 5 minutes ago

2:57 LauJensen: man thats weird

2:57 so it must be a local cp thing for me...

2:57 Thanks for helping

4:28 leafw: LauJensen: about "#^String[]", I didn't explain it correctly. I want to add a type tag to a variable's metadata, just like one would add #^String to a "text", how can one do so to what is returned by make-array ?

4:29 or into-array, same thing?

4:29 for primitives, there is #^ints, etc.

4:33 LauJensen: leafw: I don't think you can do that with make-array

4:33 leafw: no, not make-array ..

4:34 just to declare the type of a variable, and that type being any array type, like String[], Potato[], ...

4:36 LauJensen: Make array returns a String[] array, but has nothing to do with meta data

4:36 leafw: LauJensen: I know tht. Never mind. You don't know the answer, or don't understand my question.

4:36 LauJensen: I gotta jet, sorry if I seem a bit confused, very distracted

4:36 as you just noticed :) good weekend

4:36 leafw: (let [#^String[] (get-some-string-array)] ... )

4:37 hiredman: uh

4:37 leafw: that, fails. One can't declare array types. That is all.

4:37 so I wonder whether it's possible at all.

4:37 (let [#^String[] arr (get-some-string-array)] ... )

4:37 --missed the actual var.

4:38 hiredman: have you profiled and found that there is a bottleneck with the array?

4:38 leafw: hiredman: it's about avoiding pain in the future. I want to declare types here.

4:38 and you didn't answer the question either :)

4:38 hiredman: while there is a big difference between boxed integers and primitives I doubt it's huge between Objects and Strings

4:38 what question?

4:39 leafw: how to give an array type to a var?

4:39 hiredman: there is no class named String[] so there is no way that type hint will work

4:39 leafw: i.e. #^String text "text" would do it. How about arrays of String?

4:39 hiredman: arrays are funky

4:39 leafw: well: in java, one can (String[]) cast to that.

4:39 hiredman: ,(class (into-array ["foo"]))

4:39 clojurebot: [Ljava.lang.String;

4:39 leafw: ok, so the answer is no, I can't. Ok.

4:39 hiredman: ^-

4:40 leafw: hum

4:40 right--so that is the type

4:40 hiredman: yes

4:40 leafw: I wonder if with semicolon or not

4:40 clojure would hiccup at the ;

4:40 hiredman: the arrays of primitives are just special cased with #^ints in the compiler

4:41 leafw: ,(let [#^[java.lang.String; arr (into-array ["foo"])] (println arr))

4:41 clojurebot: EOF while reading

4:41 hiredman: I would not bother, unless profiling has revealed it to be an issue

4:41 leafw: it's not about performance, hiredman. It's about type safety/integrity.

4:42 ,(let [#^[Ljava.lang.String; arr (into-array ["foo"])] (println arr))

4:42 clojurebot: EOF while reading

4:42 hiredman: perhaps you would be more interested in #scala

4:42 leafw: *sigh* no.

4:42 I'll make my own macros to test for what I want.

4:43 hiredman: ~ticket #172

4:43 clojurebot: {:url http://tinyurl.com/ya742mz, :summary "#^objects type hint shortcut", :status :fixed, :priority :normal, :created-on "2009-08-11T09:44:36+00:00"}

4:45 leafw: cool -- thanks. So #^"[Ljava.lang.Object;" is possible, and soon a better way. Nice.

4:46 hiredman: ,(let [#^"[Ljava.lang.String;" arr (into-array ["foo"])])

4:46 clojurebot: nil

4:47 leafw: hum, cgrand's patch is limited to Object[] only ..

4:47 hiredman: correct

4:48 leafw: menos da una piedra -- at least it's something.

4:58 cgrand: leafw: I thought about allowing #^[String] but never discussed it nor implemented it

4:59 leafw: cgrand: sounds like a List<String> rather than a String[]. Perhaps another array representation is needed.

5:00 the plural 's' would be a hint, but of course there's no guarantee that someone won't create a class whose name finishes with s (like Class)

5:00 cgrand: except List<String> doens't exist for the JVM

5:00 leafw: I am interested in developer's perception when reading code, not JVM

5:00 hiredman: I think looking to type hints to enforce types is a bad idea

5:00 they are there to coerce the compiler

5:01 leafw: or the reader.

5:01 the point is, if one can type hint, one should be able to type hint any type. Arrays included.

5:01 this exception is just weird.

5:01 hiredman: you can

5:02 ,(let [#^"[Ljava.lang.String;" arr (into-array ["foo"])])

5:02 clojurebot: nil

5:02 leafw: true, but it's not elegant.

5:02 hiredman: ideally you should not need any type hints

5:03 leafw: hiredman: for single-developer project, indeed no. For multiple-dev or for broad-time-single-dev (i.e. next year myself), yes.

5:04 hiredman: no

5:04 you need to specify types, but not via hints

5:04 hints are the wrong mechanism for it

5:04 they are for bashing the compiler over the head

6:16 LauJensen: leafw: I appologize about that earlier, you have my full attention now :)

6:17 leafw: LauJensen: no problem, read back the log :) problem solved.

6:17 LauJensen: ~logs

6:17 clojurebot: logs is http://clojure-log.n01se.net/

6:17 LauJensen: Ok, glad to hear it

6:20 Hmm, still reading, you're still dragging hiredman along :)

6:22 check, I'm up to date. I seems weird though that you want to introduce static typing into Clojure, but why just just use comments if it's purely for perception? (let [foo bar] ; String[] ...?

6:23 leafw: dev perception ... and enforcement.D ebugging clojure is sometimes very hard, like C with gdb: the stack trace leads to the wrong place.

6:23 LauJensen: Thats certainly true

6:47 mrsolo: ... Perhaps these are why pointfree style is sometimes (often?) referred to as pointless style.

6:47 :-)

6:49 oops wrong channgel

9:43 ngoc: Lisp has many dialects, which Lisp is the most similar to Clojure?

9:52 arbscht: ngoc: clojure :)

9:52 hoeck: ngoc: IMO scheme, as it is a lisp-1 too

10:04 ambient: i've been wondering if clojure truly is completely homoiconic

10:05 if i wanted to convert clojure code to my own defined bytecode reader macros and concurrency structures might hinder that

10:07 to use a clojure subset to write domain specific code

10:27 rhickey: ambient: the reader reads data structures, whether they are defined by "reader macros" or not

10:44 chouser: rhickey: you are considering having ` at read time expand only to (syntax-quote ...), correct?

10:45 rhickey: Chouser: yes

10:47 chouser: ok. I think that might make this make-myfoo cleaner to write: http://paste.lisp.org/display/87734

11:04 rhickey: (defmacro make-myfoo [] `(defmacro ~'myfoo [s#] `(~~''foo ~s#)))

11:11 Chouser: no?

11:11 ^^

11:11 emacsen: don't we have any kind of time representation stuff in contrib yet??

11:18 chouser: rhickey: I don't think so -- that pushes the unqualified symbol all the way through to myfoo's expansion.

11:19 rhickey: ah

11:19 Chouser: so if I did (make-myfoo) in each of ns1 and ns2, hoping for them to refer to ns1/foo and ns2/foo, I'll be disappointed

11:21 I want to control the timing when ` does its qualifying magic to be when (make-myfoo) is expanded.

11:30 rhickey: Chouser: yeah, we have to move syntax-quote out of read time for that

11:42 Chouser: Chousuke: did you say you had syntax-quote implemented as a macro?

12:56 djork: hi

12:57 I'm trying to run the penumbra examples, but I can't figure out how to resolve the classpath. I'm in the src directory of penumbra, running like this: java -cp /Library/Java/Extensions/*.jar:../lib/osx/*.jar:. clojure.lang.Repl examples/gears.clj

12:57 java says java.io.FileNotFoundException: Could not locate penumbra/opengl__init.class or penumbra/opengl.clj on classpath: (gears.clj:0)

12:58 although penumbra/opengl.clj is clearly there and that path should resolve quite easily

13:01 clojure loads fine

13:18 OK so I figured out the (massive) classpathit needs

13:23 yay, finally gears

13:23 I don't know which imaginary world these instructions work in: http://wiki.github.com/ztellman/penumbra/getting-started

13:23 :)

13:23 no mention of the clojure-contrib dependency

13:26 danlei: how would I give re-matches regex options (like DOTALL)?

13:31 cemerick: danlei: re-matches takes a Pattern as a first arg -- you need to supply options when the Pattern is created

13:43 Chouser: danlei: one way to do that is to put (?s) at the front of the pattern, like #"(?s).*"

13:45 danlei: ok, thanks

14:31 hamza`: i have a bunch of functions that transform a string each one replaces a regex in the string. is there a reverse of map such that it will apply the list of functions to the string and return the result?

14:31 LauJensen: Chouser: Wouldn't ->> do what hamza` is asking for ?

14:32 hamza`: (doc ->>)

14:32 clojurebot: No entiendo

14:32 hamza`: ,(doc ->>)

14:32 clojurebot: excusez-moi

14:36 Chouser: ->> is new -- clojurebot doesn't have it yet

14:37 hamza`: i have -> in docs but not ->> which one i should be looking for?

14:37 Chouser: hamza`: you want the result of each fn to be fed into the next?

14:38 emacsen: Chouser: so, no datetime lib?

14:38 hamza`: yes start with a string apply each replace fcuntion and get the resulting string..

14:39 each one will use the output of the the one before it..

14:39 Chouser: hamza`: you can use map, or perhaps -> or ->>

14:39 what hn are you using to replace

14:39 ?

14:40 I'll try again: what fn are you using to replace?

14:40 LauJensen: hamza`: you're just calling replace/replaceAll on it ?

14:40 hamza`: (replace-1 (replace-2 (replace-3 input))) now i have this but as the regexs grow lists grow how can i change this into map or -> ?

14:40 arbscht: compose them?

14:40 hamza`: i am calling replace all on the string..

14:42 Chouser: ,(-> "hello, there" (str2/replace #", " "-") (str2/replace #"ello" "i"))

14:42 clojurebot: java.lang.Exception: No such namespace: str2

14:42 Chouser: ,(require '[clojure.contrib.str-utils2 :as str2])

14:42 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/str_utils2__init.class or clojure/contrib/str_utils2.clj on classpath:

14:42 Chouser: bah

14:43 maravillas: ,(doc comp)

14:43 clojurebot: "([& fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

14:43 Chouser: (->> "hello, there" (re-sub #", " "-") (re-sub #"ello" "i"))

14:44 so thats at least 2 options, -> with str-utils2/replace and ->> with str-utils/re-sub

14:45 hamza`: ok thanks, did not about comp too.

14:46 Chouser: ,(reduce #(%2 %1) "hello, there" [#(re-sub #", " "-" %) #(re-sub #"ello" "i" %)])

14:46 clojurebot: "hi-there"

14:47 Chouser: ,((comp #(re-sub #"ello" "i" %) #(re-sub #", " "-" %)) "hello, there")

14:47 clojurebot: "hi-there"

14:48 LauJensen: ,(reduce #(.replaceAll %1 (first %2) (last %2)) "choiser is foo bar baz" [["foo" "going to the"] ["baz" "now!"]])

14:48 clojurebot: "choiser is going to the bar now!"

14:48 LauJensen: :P

14:48 (he's Chousers evil twin)

14:49 Chouser: note comp needs the fns in revers order of the others

14:50 of those I like -> and str2 the best

14:50 LauJensen: ,(.. "foo bar baz" (replaceAll "foo" "doo") (replaceAll "baz" "daz"))

14:50 clojurebot: "doo bar daz"

14:50 LauJensen: '..' also works

14:50 Chouser: but you have to encode your regexen as strings which is unfortunate

14:52 LauJensen: ~regex

14:52 clojurebot: Sometimes people have a problem, and decide to solve it with regular expressions. Now they have two problems.

15:35 hamza`: btw, has anyone got etags to index clojure files?

15:40 konr: Guys, ~/src is on my classpath. Isn't ~/src/lancet the right directory to put step-1-complete.clj, which contains (ns lancet.step-1-complete) ?

15:41 I'm getting a file not found exception (Could not locate lancet/step_1_complete__ini

15:41 t.class or lancet/step_1_complete.clj on classpath)

15:50 hiredman: konr: http://clojure.org/libs checkout "Lib Conventions"

15:59 konr: hiredman: thanks!

15:59 clojurebot: hiredman is slightly retarded

16:18 konr: I still don't get it. If ~/src/ is on my classpath, shouldn't java be able to locate ~/src/lancet/foo.clj?

16:19 LauJensen: do you literally mean ~ ?

16:20 konr: LauJensen: no, it is just 'src' on my classpath

16:20 LauJensen: if it's like you describe above, you should be able to call (use 'lancet.foo)

16:23 konr: LauJensen: Hmmm, it turned out to be a problem with the "src", which I solved by changing it to "/home/me/src". Thanks!

16:24 LauJensen: ah ok

16:29 spuz: This sounds like a stupid question but, how do I modify a var? For example, if I want to track the number of calls made to a function, how do I increment a count var?

16:30 LauJensen: (def counter (atom 0))

16:30 (swap! counter inc)

16:31 @ spuz

16:32 spuz: LauJensen: swap! seems to apply to atoms, not vars

16:33 LauJensen: It's only for atoms, thats why I defined counter as such - You specifically need a var for this? why ?

16:34 spuz: I guess I assumed that var meant variable

16:34 so it would seem there should be a way to modify a variable

16:34 LauJensen: Clojure vars are immutable

16:35 spuz: make sense

16:35 LauJensen: http://clojure.org/vars

16:41 spuz: it seems you can use (binding) to redefine a var, if I'm assuming this var is only accessible to a single thread, how do I decide whether to use an atom or a var?

16:42 LauJensen: For those who liked the ikeda sim, it's been updated with an opengl and .net version, http://bestinclass.wordpress.com/2009/09/24/chaos-theory-vs-clojure/

16:47 spuz: LauJensen: The open gl version looks even simpler than the plain swing version ;)

16:47 LauJensen: It should be, or he failed making 'wrappers' :)

16:49 spuz: It's a very useful example by the way. I would love to see how you would make a multi threaded version of it though.

16:49 LauJensen: I was actually thinking about something along those lines myself

16:52 lpetit: vars are not immutable

16:59 LauJensen: spuz: I see I misled you, a Var can be rebound with 'binding'

17:00 lpetit: and in extreme cases, the root binding of a var can be altered with (alter-var-root

17:00 LauJensen: But for a counter I'd go with the atom :)

17:01 lpetit: but this is really just intended for use e.g. when writing a REPL, so 99.99999999999999% of the time one should just consider a var is used for providing dynamic binding

17:01 @LauJensen : +1

17:02 spuz: but even dynamic binding does not appear to be very common

17:03 lpetit: even less in clojure, since it is very error prone when used (almost inevitably) in conjunction with lazy sequences and multithreading

17:03 spuz: there's an example in the programming clojure book which redefines a function to be a memoized version of that function but it seems unlikely you would need to do that in practice.

17:04 so I guess atoms are the way to go

17:06 lpetit: memoization (caching) can certainly be a way of shooting yourself in the foot, if you don't take great care (like any caching mechanisms, whatever the language)

17:21 somnium: using def to redefine values is generally frowned upon but wondering if this is a special case...

17:23 if I have a macro (deflayout :name layout) that creates/updates 'layoutmap with {:name layout}, it uses def to alter 'layoutmap every time its called, but this all happens when the file is read in, no changes to 'layoutmap at runtime.

17:24 rafsoaken: what is wrong with (use 'clojure.parallel) ?

17:24 somnium: so managing state with a ref seems strange

17:25 rafsoaken: when (use 'clojure.contrib.math) works?

17:25 hiredman: somnium: don't re-def

17:25 use an atom or a ref

17:25 rafsoaken: look at the exception

17:26 somnium: hiredman: all the calls at runtime have the form (with-layout :name & content)

17:26 hiredman: most likely you will see a class not found exception

17:26 somnium: use a ref or an atom, do not re-def

17:26 rafsoaken: hiredman: ClassNotFoundException - even though it's described in the API?

17:27 hiredman: rafsoaken: go read the docs for clojure.parallel

17:27 * technomancy saw two copies of Programming Clojure at Barnes and Noble today

17:27 technomancy: nice to see it in Real Life

17:27 somnium: hiredman: ok, I really just want to define it once, I guess I could do (deflayouts & key-val-pairs) and do it one shot

17:28 hiredman: rafsoaken: http://clojure.org/other_libraries

17:28 lpetit: @somnium : yeah

17:28 somnium: just wondering what the best way to allow separate calls and still create one central 'layouts var

17:28 hiredman: an atom or a ref

17:28 rafsoaken: hiredman: thanks, i'm just ignorant sometimes

17:29 hiredman: you are talking about mutating something bound to a name

17:29 so use a ref or an atom

17:29 somnium: ok ok

17:30 ah, atoms are perfect, sorry for dumb questions

17:37 LauJensen: somnium: Don't appologize, it wasn't dumb

17:39 lpetit: somnium: multimethods rebind the var root of the method every time you add a new method, so that may not be dumb

17:40 somnium: thanks for the support :)

17:40 it just seems odd to consider it 'state', since its really a declarative api, at least in my head

17:41 hiredman: lpetit: well multimethods predated atoms

17:41 lpetit: are you sure of that?

17:41 lpetit: hiredman : I remember reading this on one of cgrand's blog posts

17:42 LauJensen: then it must be true

17:42 hiredman: ~def c.l.MultiFn

17:42 lpetit: http://clj-me.blogspot.com/2008/05/multimethods-aren-magic-nor-mutable.html

17:42 or it was true (very old post)

17:43 * hiredman waits for firefox to condescend to load github

17:43 * LauJensen recommends gitorious

17:43 LauJensen: You give up the Gists, the watcher system, probably more, but you get fast page rendering - I considered it a good trade

17:44 hiredman: anyway, defmethod calls .addMethod on the multifn, and doesn't touch the Var at all

17:45 lpetit: so it used to be mutating the var, sorry for the outdated info

17:46 hiredman: I wonder why it used to do that, seems like such an icky thing to do

17:51 lpetit: indeed, as expected by looking the code at http://tinyurl.com/ycm4ude , the current version does not make Christophe's example fail anymore

17:52 licoresse: ,(doc ->>)

17:52 clojurebot: Excuse me?

17:55 lpetit: all in all, what is the added cost of using an atom ? I mean, vars are still there ...

18:11 hiredman: vars can be dynamically rebound

18:18 lpetit: hiredman : so maybe it's more appropriate for somnium to directly place the map in a var. It depends on the use case. If as he said mutating the var is just "project configuration / wiring" done in multiple places (imagine a modular GUI), then maybe it's ok. But if this modularity is not just at compile time, but also at runtime (dynamic plugins), then I think using an atom then becomes...

18:18 ...inevitable ...

18:44 rabidsnail: Is there a way to use epoll/kqueue from clojure? Is there some other way to cheaply sit on thousands of open tcp sockets?

18:45 Chouser: rabidsnail: there's a built in java lib for that. looking now...

18:45 rabidsnail: thanks

18:47 Chouser: http://java.sun.com/javase/6/docs/api/java/nio/channels/ServerSocketChannel.html

18:48 That ties in somehow, but I've not actually used it.

18:48 so I'm a bit vague on the details

18:49 rabidsnail_: Sorry, I missed the last minute. My iphone battery died somehow.

18:51 Chouser: http://www.java2s.com/Code/JavaAPI/java.nio.channels/SelectableChannelregisterSelectorselintops.htm

18:51 I think that's an example of what you want.

18:52 it creates a single Selector and incoming tcp connections are registered with it

18:52 it blocks on the selector and wakes up when any of the registered connections has some data to read.

18:53 I believe that uses epoll or whatever's appropriate on the given OS internally.

18:54 rabidsnail: Yes, that seems like what I want. Thanks.

19:05 somnium: ant-question: what's the tersest way to glob everything in src for a compile target?

23:26 konr: Is there a particular swing book you guys recommend?

Logging service provided by n01se.net