#clojure log - Apr 21 2008

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

6:25 jteo: is someone working on a clojure tutorial already?

10:00 Chouser: jteo: not that I know of. sounds kinda fun, though. Are you starting one?

10:01 jteo: maybe, if i can get my head wrapped around this.

10:01 Chouser: "this"?

10:01 jteo: certain things are confusing in clojure to someone who just managed to get Common Lisp.

10:01 such as...immutables.

10:01 Chouser: heh. yeah.

10:02 are you trying to do something in particular?

10:04 jteo: clojure is useful for me as a mental challenge.

10:04 anyway, i get bored with imperative languages.

10:06 plus clojure seems much more practical than Common Lisp. as in the library support.

10:09 Chouser: I agree.

10:11 drewr: jteo: We're in the same boat. I've been wanting to use CL, but it's hard to justify when I can get something done quickly in Python. Clojure's been scratching my Lisp itch but with the ability to solve real problems quickly.

10:11 jteo: precisely.

10:12 Practical Clojure would be an absolute gem. :)

10:12 drewr: I've been migrating some data for a client and they gave us part of it in a PDF. I used about 10 lines of Clojure with the PDFBox jar to extract the information.

10:13 It makes me enjoy Java. That's inconceivable.

10:13 Well, Java's libraries.

10:19 lisppaste8: drewr pasted "pwning a pdf" at http://paste.lisp.org/display/59535

10:24 Chouser: drewr: nice.

10:29 drewr: Obviously, you could make a fine PDF library with CL, but I'm guessing that problem is too uninteresting for a Lisper to solve (I wouldn't want to either) since I can't find CL-PDF. Clojure is like having an inexhaustible FFI for the Business Programmer.

10:31 jteo: precisely.

10:31 it's tiring to write libraries/glue from scratch.

13:58 Chouser: it seems like it would be common, when destructuring a map, to use the same names for the local formal args as the keys of the map.

13:59 rhickey: yes

13:59 Chouser: (let [{a :a b :b c :c} x] ...)

14:00 would it be sensible to provide a shortcut?

14:00 rhickey: like?

14:00 Chouser: I have no idea what the syntax would be

14:00 rhickey: therein lies the rub

14:00 Chouser: (let [{{a b c}} x] ...)

14:00 rhickey: but a map is a valid binding form

14:01 Chouser: there might be something analegous on the calling side, such that a similar syntax could be used.

14:01 rhickey: e.g. (let [{{a b c} :abc } x] ...)

14:01 Chouser: when building a hash: (hashsyms a b c) ==> {:a a :b b :c c}

14:02 right. {{ ... }} is a bad syntax.

14:02 (let [(de-hash-syms a b c) x] ...) ?

14:02 rhickey: ugh

14:02 Chouser: I assume callable destruturing forms isn't a can of worms you want to open.

14:03 rhickey: it's something I want to save

14:03 Chouser: yeah, ok.

14:04 but for destructuring maps, if a sane syntax could be found, you'd be open to something like this?

14:04 rhickey: yes, I've definitely thought about it

14:05 Chouser: #:{a b c} ==> {:a a :b b :c c} and (let [#:{a b c} x] ...)

14:05 rhickey: let's leave hashsyms out of it, much less common

14:06 Chouser: ok, fine by me. That's easy to write a macro for if I need it.

14:06 I was bringing it up only for symmetry.

14:08 rhickey: maybe sets (let [#{:a :b :c} x] ...)

14:08 uses name of key for local name

14:09 will work with maps with keyword, symbol and string keys

14:09 Chouser: right. there's no other useful meaning for a set as a binding form?

14:09 rhickey: not right now

14:10 Chouser: the only thing I can think of would be to allow you to pluck out truth values from a passed-in set, but that doesn't seem terribly useful.

14:12 rhickey: no. but note you can't have what you want (let [#{a b c} x] ...)

14:12 because you don't know the type of the keys

14:14 Chouser: I don't understand.

14:14 I mean I'm content with #{:a :b :c} instead of #{a b c}...

14:14 rhickey: your first example presumed keyword keys

14:15 Chouser: oh! good point!

14:17 (let [#{:a :b :c} x] ... ) would be fantastic.

14:18 and if 'name' worked for strings, then you could get the formal param name for each key by calling 'name' on the given key.

14:21 rhickey: right, that would be added

15:07 Chouser: No way to use :as in a set.

15:08 rhickey: right

15:08 Chouser: are you working on this already?

15:08 rhickey: no

15:08 Chouser: ok

15:12 Modius: rhickey: Sent you a private message/question - uncertain if you have them filtered, or if you don't want to answer - if the former, just wanted to get feedback.

15:19 abrooks: Modius: Doesn't freenet filter private messages?

15:20 Modius: abrooks: Not for users registered with nickserv

15:20 abrooks: er... not freenet, freenode

15:21 Modius: Ah, okay.

15:35 Chouser: rhickey: should symbol keys for sets be quoted or not? That is, should #{:a "b" 'c} work, or #{:a "b" c}, or both?

15:37 landonf: Howdy all. Anyone have a preferred unit testing framework?

15:47 Reading Kearsley Schieder-Wethy's work

15:50 rhickey: Chouser: in the macro, no. They are not evaluated, just as in the map case: {a :a b :b}

15:50 drewr: landonf: You could use jUnit.

15:51 But it would be more pedagogical to write your own.

15:58 Chouser: ok, so (let [#{a b c} x] ...) would work, it just wouldn't do what I originally suggested.

15:58 rhickey: right, that would match symbol keys only

15:59 keywords: (let [#{:a :b :c} x] ...), strings: (let [#{"a" "b" "c"} x] ...)

15:59 Chouser: great. Well, I have those cases working.

16:00 rhickey: cool

16:01 Chouser: I'll post a patch in a minute, though I have no idea if the code is up to your standards. ;-)

16:02 rhickey: does it work when x is a set?

16:03 Chouser: nope, that gets you nils

16:03 rhickey: hmm...

16:04 Chouser: I'm using 'get'

16:05 I could put the map in function position instead, and that ought to work.

16:05 rhickey: right

16:05 but not with nil x

16:05 Chouser: indeed.

16:06 I could put the key in function position, but of course that would only work for keywords. ;-)

16:06 rhickey: you'll need to special-case nil x

16:07 Chouser: I could wrap x in (or x #{})

16:07 rhickey: (and x (x k))

16:07 Chouser: would you prefer your special case on each binding, or mine on the first one?

16:08 rhickey: either

16:09 Chouser: done.

16:10 rhickey: the set stuff will be nice for boolean-flag style & keyword lists

16:22 Chouser: http://n01se.net/paste/SgX -- Destructure maps using sets

16:22 drewr: rhickey: What was that paper on tries you used to implement maps in Clojure?

16:22 (I'm giving you some props on reddit.)

16:23 rhickey: http://citeseer.ist.psu.edu/459691.html

16:29 drewr: what reddit thread?

16:30 drewr: rhickey: http://reddit.com/r/programming/info/6gov3/comments/

16:31 I'm recommending Clojure in there, but I'm attempting to explain why it's compelling. :-)

16:34 Do I remember in the concurrency talk that your hash maps are near O(1)?

16:37 rhickey: They are log32N, so for a million items that's 3 hops, and for a billion, 6. IMO, that's small enough to ignore.

16:41 * bgeron remembers from Datastructures lecture that the log-base doesn't matter in asymptotic notation, but it does matter in real life

16:42 rhickey: right

16:52 nsinghal: Var fnptr = RT.var("nspace", "function"); returns a function - can i pass that variable to another clojure function in Invoke?

16:52 rhickey: sure

16:53 nsinghal: can i return a multimethod? so that the caller can call the method using the arity?

16:54 rhickey: an arity-overloaded function

16:54 sure

16:56 nsinghal: how can i return that? I have written a multimethod. then when i will retunr that in a separate fn - wont it evaluate or something?

16:56 rhickey: ?

16:56 functions ar evalues like any other

16:56 they don't get evaluated until called

16:57 nsinghal: sorry i was confused with multimethid and arity-overloaded fn - i think i understand now. thx

16:59 rhickey: all interested - here's an amortized O(1) persistent array design, but the constant factors are substantial, and the implementation very complex; http://citeseer.ist.psu.edu/328736.html

17:11 nsinghal: (defn multi-arity []

17:11 (fn ([] (this false))

17:11 ([b]

17:11 (if b (str "hello") (str "bye bye")))))

17:12 what should i use where (this false) is? i want to call the same fn with a default argument

17:12 rhickey: ns: you can't have the [] after multi-arity

17:12 nor the fn

17:13 nsinghal: i want to create a function which returns a function with different arity

17:13 rhickey: ah

17:14 ok, what is this?

17:14 'this'

17:15 nsinghal: i just used it - i didnt know how to call the same function with arg

17:15 rhickey: put the name after fn

17:15 nsinghal: ok let me try that

17:16 worked like a charm- great

17:30 Chouser: rhickey: I don't know if I quite love the set destructuring syntax. (of course I think of this after I'm done...)

17:30 This is the first time you can bind to a symbol name without actually mentioning the name as a symbol.

17:31 a naive text editor looking for "foo" may not find where it's bound using #{:foo} or #{"foo"}

17:31 rhickey: right, and no :as bothers me

17:32 drewr: thanks for the mention: http://reddit.com/r/programming/info/6gov3/comments/

17:33 Chouser: (let [{_ :a _ :b} {:a 1 :b 2}] [a b]) ==> [1 2] ?

17:33 (let [{* :a * :b} {:a 1 :b 2}] [a b]) ==> [1 2] ?

17:35 rhickey: that still doesn't have the name as a symbol

17:36 Chouser: oh. heh. right.

17:36 well, it's going to be impossible to have the name as a symbol *and* allow for keyword/string/symbol keys.

17:37 unless there's a completely different syntax for indicating which of the 3 it is.

17:37 rhickey: right, or marrying keywords

17:38 Chouser: {a :string b :keyword} <-- icky

17:38 rhickey: this is the thought process I went through and didn't find anything great

17:38 Chouser: hmph.

17:39 rhickey: :string and :keyword might be keys

17:41 as could any other value

17:41 Chouser: yeah. But it only gets worse. {[:string a] * [:string b] *}

17:41 rhickey: nope, becaue maps can be binding forms and nested

17:41 Chouser: * could be a value

17:41 and, right, nested vector form.

17:42 did you borrow :as from somewhere?

17:43 rhickey: not specifically, but other pattern matchers have similar things

17:43 the Clojure trick is that the binding forms are still data structures and non-conflicting with the things to which they bind

17:45 Chouser: there's no :as for vectors, though I guess & helps out.

17:46 rhickey: yes there is

17:46 Chouser: even just using sets to bind sets would cause problems for :as or & -- no order like & needs, and no value position like :as needs.

17:46 oh, ok. It uses order then as well, like & does?

17:46 rhickey: ?

17:47 Chouser: [a & b] works because [] has order and b comes after &

17:47 #{a & b} can't mean anything about b specifically

17:48 rhickey: :as works in vectors because it is a keyword and thus can't be a bound name

17:48 user=> (let [[a b c :as d] [1 2 3 4]] d)

17:48 [1 2 3 4]

17:49 Chouser: right, and it's still relying on vectors having order. :as modifies the followind d -- meaningless in a set.

17:49 rhickey: ok, right

17:51 Chouser: I'm thinking that almost completely rules out sets as a robust binding form. If you were open to sets binding maps, would you be open to other mis-matches?

17:51 drewr: rhickey: You're welcome. Unfortunately, that lame link is getting down-modded so no one will see it. :-/

17:53 Chouser: I don't even know where that leads. Gah. I'm going home.

17:54 rhickey: (let [#{a b c :str/:key/:sym :anything-else-is-as} x] ...)

20:22 blbrown: hello

20:22 rhickey: hi

20:25 blbrown: rhickey, I am thinking of converting some swing/abcl code to clojure. it isn't much, but 6 months to a year from now, I think I will have made the right choice

20:25 rhickey: cool

20:40 Chouser: so (let [#{a b c :str} x]) would be the same as (let [{a "a", b "b", c "c"} x]) ?

20:40 rhickey: prefereably let [#{:str a b c} x])

20:40 preferably

20:40 yes

20:41 Chouser: and if unspecified it would default to :key, I hope?

20:41 but what's :anything-else... ?

20:43 rhickey: only one of :str, :sym, :key can be supplied, if another keyword is supplied, it names the aggregate (i.e. fills the role of :as)

20:43 (let [#{:str a b c :fred} x]) would be the same as (let [{a "a", b "b", c "c" :as fred} x])

20:57 Chouser: really? I guess that's better than what I've got, but will you be satisfied with it?

20:58 rhickey: I don't know, I wasn't thinking about it until you brought it up - just brainstorming

20:59 Chouser: ok

21:16 {a :a, :keys [b c d], :strs [e f g], :as foo} = {a :a, b :b, c :c, d :d, e "e", f "f", g "g", :as foo}

21:19 rhickey: neat

21:28 Chouser: I guess anything that destructures maps can destructure sets just as well.

21:29 rhickey: yup

21:30 * Chouser backs out his last patch and tries again.

22:37 blbrown: thank god there is an ant script as opposed to mavent

22:38 or not

23:05 rhickey: is it not working?

23:06 blbrown: no, I was just making a general comment.

23:13 Chouser: I build with ant all the time.

23:40 insectmessiah: Is anyone using webjure on a regular basis? Or is everyone basically rolling their own web frameworks right now?

23:41 I need to stop being lazy and learn a Lisp, and no matter how many times I fire up SBCL, I keep coming back to wanting to pick up Clojure instead :D

Logging service provided by n01se.net