#clojure log - Jun 13 2008

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

3:58 yrb: can anyone point me to some clojure source to reference when wrapping a java library

4:02 slougi: i was pointed to parallel.clj yesterday. don't know if it's a good example.

4:02 i have some code in user.clj, how can i get command line arguments?

5:35 Chouser: *command-line-args*

7:27 yrb: anyone have any ideas about what concepts would be valuable in a clojure gui toolkit

7:28 blackdog: i was looking at pivot yesterday a nice wrapper for that would be good

7:30 http://weblogs.java.net/blog/gkbrown/archive/2008/06/introducing_piv.html

7:30 yrb: cool, I will take a look

7:31 blackdog: specifing the xml as a clojure map instead would be good

7:42 yrb: yes using maps in place of their xml would be a huge improvement. The java community sure loves xml

7:49 I was thinking of doing a declaritive framework that leverages metadata to take care of rendering

7:49 sort of aimed towards rapid prototyping

8:01 rhickey: The screencasts are a brillant resource :). Any plans to do one focused on structuring data, and living without "objects"?

8:02 rhickey: yrb: glad they are of use. Yes, I hope over time to cover some higher-level things

8:02 blackdog: that

8:03 the move from objects to non objects would be useful for me too

8:05 for example, yesterday i was wondering if the namespace stuff would be better for containing all my swing var components rather than a map, e.g. ui-form1/list1

8:05 ui-form1/combo1

8:05 would that kind of structuring be good practice?

8:05 rhickey: what are list1, combo1?

8:06 blackdog: instances of those objects

8:06 swing components

8:07 i'm sticking them in a map right now, but maybe using defs is better, i dunno

8:07 my point is, when not from functional land i'm not sure

8:08 rhickey: let's say you have a widget that has a combo and list, if you put them in ns vars then creating a second instance of that widget will be a name clash

8:09 yrb: I think I would go with the map, just because it means you can walk it programmatically

8:09 blackdog: yes, but they are per form or per container,

8:09 ok

8:10 ok, i think i was heading in the direction of over using namespaces :)

8:18 yrb: rhickey: Would I be correct in saying that you look at objects more as state containers, rather than a way of encapsulating behavior?

8:20 rhickey: I think CL generic functions were right to take methods out of classes

8:21 yrb: and in clojure namespaces would be the way to encapsulate behavior?

8:21 rhickey: data doesn't behave

8:21 things happen, and there might be new data

8:21 those things might involve multiple entities

8:21 no single one of which 'owns' the activity

8:22 so OO is kind of an oversimplification that gets in the way IMO

8:23 similarly, I think associating behavior with at-birth types is another over simplification that gets in the way of modeling the way we think

8:24 in real world thinking we much more associate 'behavior' with state/attributes than types

8:24 yrb: I would have to agree that once you use multimethods/generic functions you don't want to go back to single dispatch

8:24 rhickey: drunk is not a type

8:24 but people who are drunk walk differently

8:25 similarly, no one is born a plumber or a painter

8:25 Chouser: zipper objects have behavior

8:25 rhickey: not really

8:25 there is an open set of functions that may manipulate them

8:26 also open to functions that manipulate them in combination with other things

8:26 yrb: I suppose this is why you see so many manager types in java....

8:27 blackdog: rhickey, in your gen-and-load-class example, you use a fred.lucy.Ethel namespace and then refer to a (in-ns 'fred.lucy.Ethel__2276) in the implementation, why the __2276?

8:28 Chouser: I'm referring to the functions stored in zipper vector objects metadata.

8:28 blackdog: rhickey, sorry gen-and-save-class

8:29 rhickey: Chouser: buts that's not behavior in the OO Zipper as a class way

8:29 it's a flexible system that makes behavior available as data, or dynamically etc

8:31 yrb: i think i see why structs are the way they are now

8:32 Chouser: I guess I'm not clear on the difference. Each zipper obj is a little bundle of instance data and type- (not class-, I just mean xml vs. vector etc.) -specific code.

8:33 rhickey: blackdog: that's just left over testing cruft, not a real example. I used to have a gensym in there so I could test gen-and-load class without having to keep restarting

8:33 blackdog: ok so usually i'd just do (in-ns 'fred.lucy.Ethel) and create the methods

8:34 Chouser: of course you also have type-independant functions that act as a more convenient API, but the methods (sorry, meta-data-stored functions) of the zipper objs form a public API of their own.

8:35 rhickey: Chouser: the difference is Clojure doesn't dictate that is the only way you can do 'behavior'. It's how I chose to do it for zippers. I'm not saying associating behavior with an object is always bad, just that dictating it is bad, tying it to types is bad, and not having other ways to model things is bad

8:36 bpattison: so it's the degrees of freedom that's appealing Clojure and dynamic lanugages in general?

8:37 rhickey: lot's of dynamic languages follow the same OO line

8:37 CL generic functions are the exception

8:38 they too are somewhat stuck to types

8:38 although they support value dispatch

8:38 yrb: well you are free to write your own restrictive OO system ;) that is the wonder of lisp

8:40 Chouser: I expect my first several large clojure projects will be examples of to take advantage of having enough rope to hang yourself.

8:40 s/of/of how/

8:40 bpattison: but doesn't having all that flexibility make it difficult to maintain large scale systems?

8:41 blackdog: i think rich talks about that in the videos, the contention is it's much easier to reason about functional programs and test them

8:41 yrb: you can still drown in a tea cup ;)

8:42 blackdog: i still have to validate that :)

8:42 bpattison: I'll go back and look at the videos

8:42 Chouser: There appear to be several decisions baked into clojure that prevent modules from doing things that would make it impossible to include several foreign modules in the same project.

8:43 after that, it's just up to you to choose to write good code.

8:43 rhickey: bpattison: in many ways no, since a micro-abstraction that serves a small part of an app is easily described and has finite scope. Many people fail to realize how much complexity they bring in every time they say class X...

8:43 http://groups.google.com/group/clojure/msg/ab1b275a1ef8373f

8:45 bpattison: hmmm, interesting ... I think that my biggest hang up in giving up type systems -- there's so many times I've changed abstract classes and the compiler has found all the other places that I need to change the code

8:46 rhickey: bpattison: that's a definite benefit to the straightjacket, I think providing similar refactoring for more dynamic/flexible systems is an area for exploration

8:47 yrb: rhickey: I think it would be good if there was a prominent link to that on the wiki

8:48 rhickey: go for it :)

8:55 yrb: I must say having less restrictions is painful because now that I can do anything what do I do...

8:57 but I know as I get to know the tools it is going allow me to express the design better

8:58 blackdog: bpattison, remeber you can add the type hints to clojure anyway and be as restrictive as you want

8:59 rhickey: but I only use them for optimization, not enforcement

9:03 Chouser: The set of designs that could be enforced with type hints is much smaller than the set of designs possible in clojure.

9:03 bpattison: I guess my issue isn't enforcing types per se -- but being able to maintain code that some one else wrote 2 years ago -- but maybe type safety is the wrong approach to address code maintanability

9:04 yrb: rhickey: along those lines if you could maybe create some high level models with reasoning of a large application, like an architecture overview.

9:04 rhickey: the set of things that types systems can enforce is much smaller than the set of things you need to get right in large systems over time

9:05 note that I do think this is an important area, just don't believe that types are the places to hang this stuff

9:06 constraints, preconditions, rules, contracts

9:06 yrb: it would give me at least a jump start and orientation to start thinking

9:06 rhickey: as with oo, many of these things cross entities

9:06 so attaching them to types is limiting

9:14 yrb: what was your motivating reason for metadata, considering the amount of flexibility you get through the use of maps?

9:15 rhickey: yrb: funny you should mention that right now, one of the reasons was to provide a place to put the info one might need for constraints, preconditions, rules, contracts

9:16 without it being mixed in with the information the app is processing

9:16 it really is 'meta'

9:20 yrb: that is a good point it means the functions that touch the data don't have to know about the metadata

9:27 though it seems like something that should be used more sparingly than I would typically associate with a "metadata" system, where you try to add as much as possible

9:35 something like contextL could be interesting in clojure

9:36 rhickey: the fact that defn-ed fns can be dynamically rebound directly supports some context-like programming

12:03 Lau_of_DK: Am I the only one here having trouble with Blip.tv ?

12:04 blackdog: been ok for me

12:04 Lau_of_DK: Are you in Firefox?

12:04 blackdog: yes ff3 on ubuntu

12:05 Lau_of_DK: ok.. Maybe its cause Im on ff2 - It crashes my sound system and if I fiddle with the window (position/size) it crashes Gnome

12:05 Almost like being back in Windows

12:06 cgrand: there's a drop-down which enable you to download a .mov

12:13 Lau_of_DK: cgrand, thanks :) And btw the prime generator made perfect sense, its an impressive func

13:52 Question

13:52 user> (rem-exacts "ABCD" "BBBB")

13:52 (\A \x \C \D)

13:52 user> (apply str (rem-exacts "ABCD" "BBBB"))

13:52 "AxCD"

13:53 I in the defn (rem-exacts) I wrap the code in (apply str (...)) it still returns 4 char values, and not a string... why is there a difference if its wrapped in the function, or on the result?

13:56 Chouser: *whew* I'm so relieved that my meta-data can have meta-data.

13:57 (def x (with-meta [] (with-meta {:is :meta} {:is :meta-meta})))

13:57 ^^x

13:58 Lau_of_DK: you'd have to paste rem-exacts for us to see the problem.

13:58 Lau_of_DK: Chouser, here goes

13:59 (defn rem-exacts

13:59 ([guess] (rem-exacts code guess))

13:59 ([code guess]

13:59 (map (fn [c g]

13:59 (if (= c g) \x c)) code guess)))

14:00 Chouser: (apply str (map ... )) should work

14:00 Lau_of_DK: Thats what I was trying to explain: It doesnt

14:00 It still returns chars

14:00 If I do it IN the defn, I does not work, if I apply on the result, it works

14:01 hmm

14:01 and now it works - all I did was evaluate it again...

14:01 hope its not a bug in the new Clojure release

14:03 I had the same problem with another function, once evaluated the 3.rd or 4.th time, the REPL understood the changes.. And this happens directly after updating

14:05 * Chouser updates

14:11 hoeck: revision 906 was broken on my machine, but 905 worked

14:12 Lau_of_DK: Broken, how?

14:12 Chouser: I had to clean and rebuild.

14:12 Lau_of_DK: I just checkout the latest SVN, built it, removed old directory and copied to that location

14:14 hoeck: Lau_of_DK: weird Exception after starting clojure. But your rem-extracts function works fine under 905.

14:15 oh, sorry, needed just a clean rebuild, thanks chouser for that hint.

14:20 Lau_of_DK: k :)

14:23 grosours: hi everybody

14:24 Chouser: hi

14:24 * Chouser isn't quite everybody, but he'll have to do.

14:25 grosours: ^^ hi specially to you the Chouser

14:25 Chouser: :-)

14:25 grosours: ^the^then

14:25 jgracin: hi grosours

14:41 Lau_of_DK: hey jgracin & grosours :)

15:03 jgracin: hi Lau_of_DK. slow reflexes, watching soccer. :-)

15:06 Lau_of_DK: Thats good man, soccers great for people with slow reflexes - 10 goals scored every year

15:28 ed-t8: hello, i am totally newb to clojure and java, can you call libs that you create in java in clojure?

15:29 Chouser: ed-t8: yes

15:29 ed-t8: I realise that there is the (. notation) to call classes which are already part of JVM

15:29 but what about classes that you want to create, say i want to create a form in java but call its methods from clojure, is that doable

15:29 Chouser: that notation works for all Java classes in your classpath

15:29 ed-t8: oh right

15:30 Chouser: but why do you want to create a form in Java? ;-)

15:30 ed-t8: because netbeans comes with a nice gui designer :)

15:31 * Chouser narrows his eyes suspiciously at the IDE.

15:31 ed-t8: is there a good IDE for clojure?

15:31 Chouser: Actually, netbeans is probably your best bet. There's a plugin for it called enclojure.

15:31 ed-t8: yeah i've tried that but i can't figure out how to make .clj files the main class

15:32 i've also tried SLIME but that didn't seem to work very well

15:32 Chouser: I haven't used either of those enough to help you. sorry.

15:32 ed-t8: what do you use?

15:32 Chouser: vim

15:33 ed-t8: argh

15:33 Chouser: and a REPL in an xterm

15:33 blackdog: i have a syntax mode for jedit

15:33 ed-t8: i'm more of an emacs used

15:33 user*

15:33 blackdog: and the beginnings of a repl

15:33 Chouser: I know people have gotten SLIME to work.

15:33 dudleyf: ed-t8: The SLIME mode works pretty well for me

15:33 ed-t8: dudleyf: does it work for loading say a JFrame ?

15:34 dudleyf: i can get SLIME to work for basic clojure expressions, just not for anything that uses the JVM (for some strange reason)

15:34 lisppaste8: blackdog pasted "clojure with miglayout" at http://paste.lisp.org/display/62182

15:34 dudleyf: I've never tried gui stuff with it

15:34 blackdog: ed-t8, i use clojure with miglayout for gui stuff

15:34 it loooks a bit like the lisppaste there

15:35 ed-t8: blackdog: what is miglayout?

15:35 blackdog: i just found it last week, it's a layout manager

15:35 but it's very easy to use

15:36 ed-t8: nice, i would definitely rather use the netbeans gui designer though. :)

15:37 blackdog: no gui editor of course but i just got fed with 200mb going to netbeans

15:37 i used to complain with 60mb going to jedit but now that's negligable :)

15:38 ed-t8: :D yeah it is quite large

15:38 la_mer: ed-t8: You can bootstrap a clojure app by just starting clojure with clojure.lang.Script as the main java class instead of the Repl, and then pass the path to your .clj file as an argument

15:39 ed-t8: la_mer: nice, can it handle multiple files?

15:39 blackdog: i think it does

15:40 la_mer: ed-t8: Sure, you can pass as many files as you want, if you can build your environment serially like that. There are some modules floating around (perhaps built in to clojure these days?) that will allow you to load in other files using (require 'foo) as well.

15:40 blackdog: (load-file 'foo)

15:41 la_mer: Sure, there's that, too. Wasn't someone working on a require mechanism?

15:41 blackdog: oh don't know

15:41 what would the difference be?

15:41 Chouser: clojure-contrib lib.clj I think, but I still haven't looked at it.

15:42 blackdog: like a require from a CLOJURE_LIBS env var or something?

15:42 la_mer: blackdog: here's one reference of an implementation from March: http://groups.google.com/group/clojure/browse_frm/thread/7e30c97c0b31c11a

15:42 blackdog: thanks,

15:43 that's useful :)

15:46 la_mer: I think Rich said at some point that some kind of require/provides mechanism would be rolled up into the core distribution (or at least a "blessed" contrib module), but I haven't kept track of developments there.

17:07 lisppaste8: Lau_of_DK pasted "Bug?" at http://paste.lisp.org/display/62190

17:07 Lau_of_DK: rhickey, can you look at that paste, I think it might be a bug

17:08 rhickey: what does 'blows up' mean/

17:08 ?

17:09 Lau_of_DK: It means "Wrong number of args: PersistantVector", but I found the error, it was a sloppy naming of "score" in the args... :( Sorry.

17:09 Would be sweet if the REPL could provide that sort of information, but I guess that impossible

17:18 rhickey, note: That Java talk was really good, if advertised a little it should draw quite a crowd from Java/C# - All you need now is a few ShowMeDo videos where you code some cool stuff, and you're all set :)

17:18 rhickey: all I need now is some more hours in a day :)

17:19 Lau_of_DK: you're telling me :) There's definiately an addictive scent to Clojure, especially since this is the first time Im using functional style programming.

17:19 Anyway, until we make that happen, try coffee

17:19 * rhickey drinks tea

17:20 * Chouser too

17:20 Lau_of_DK: A bit atypical for hackers, but alright, things change I guess :)

17:20 Chouser: just made up a gallon of iced tea this morning. Should last a day or two.

17:24 Lau_of_DK: rhickey, speaking of time. How do you actually find the time to be so productive with Clojure - Is this your full time occupation?

17:27 wybiral: rhickey must realize that time is an illusion caused by believing in state. Much like functions, rhickey simply "exists" ...

17:27 Chouser: heh

17:29 rhickey: part-time

17:36 slava: how long have you been working on clojure?

17:37 albino: ahh, slava came here

17:40 Lau_of_DK: slava, I think he said 2 years active development and 4 years of dreaming about it

18:01 if I need to do a (max (list 1 2 3)), how do I splice the list to evaluate the members, I suppose there's some sugar for it?

18:02 Chouser: Not sure what you mean. (max 1 2 3) and (apply max (list 1 2 3)) both work

18:02 Lau_of_DK: apply - thanks :)

18:38 rhickey: slava: 3 years, released last fall

18:51 Lau_of_DK: user> (count '((1 2 3) (1 2 3)))

18:51 2

18:52 Is there a version of disj or something, that will allow me to retrieve number of elements, in this case, 6

18:52 ?

18:56 Chouser, cgrand , anybody ?

18:57 cgrand: you need to code a flatten function

18:57 Lau_of_DK: exactly

18:59 Do you know whats available in Clojure?

19:00 cgrand: not tested & going to bed: (defn flatten [x] (if (seq? x) (mapcat flatten x) (list x)))

19:01 Lau_of_DK: I'll fiddle with it, thanks, sleep tight :)

19:18 albino: Has anyone tried to use the STM model from clojure in straight java?

19:20 Lau_of_DK: you mean compared to gay java?

19:20 (sorry bad joke)

19:20 How do you mean in straight java ?

19:20 albino: I wasn't speaking of the sexual preference of the language :)

19:20 I mean without using the clojure language

19:21 Lau_of_DK: I havent, no. But why would you bother ?

19:22 albino: well because a lot of programmers in the world don't like the syntax of lisp and only know java

19:22 Lau_of_DK: Thats true

19:22 albino: it was more of curriosity question, whether people had tried to import the clojure stm libraries and then made the right method calls

19:26 JamesIry: albino, there are STM impls for Java that might have a more "natural" api for that language.

19:26 albino: JamesIry: do you know if there are any which are being proposed as a default to be shipped with the jvm?

19:27 JamesIry: albino: nope, not even close

19:28 albino: JamesIry: thanks

19:28 JamesIry: albino: STM isn't on the Java radar right now. I think Java 7 will have some new concurrency stuff with a fork/join style library that will be very nice and might be a good thing to add to Clojure

19:28 blackdog: it's in JamesIry

19:29 JamesIry: It's in me?

19:29 blackdog: riich gas added an implementation of the fork join jsr

19:29 JamesIry: Oh, cool!

19:29 blackdog: parallel.clj

19:30 Lau_of_DK: Has anyone here found an easy way to build a complex GUI in say Netbeans, and then drive it from Clojure ?

19:30 blackdog: nopes, I'm using miglayout to layout my swing, it's quite easy

19:31 Lau_of_DK: miglayout? Never heard of it

19:31 blackdog: i just heard about it last week, it's a layout manager, but it's designed for use from code, it's kind of css'ish

19:33 Lau_of_DK: Have you got a link and a Hellomiglayout tutorial?

19:34 blackdog: this is the article i found about it first

19:34 http://www.devx.com/Java/Article/38017

19:34 JamesIry: http://www.miglayout.com/

19:35 Lau_of_DK: But do you then manually reformat that to the (. obj method) standard?

19:36 blackdog: yes,

19:36 Lau_of_DK: What I was trying to avoid :)

19:36 blackdog: i;ve nver done swing before, and I more or less have got what I wanted

19:36 Lau_of_DK: Would be sweet if I could visually build the whole thing, then import some class, and be done with it

19:36 blackdog: without thinking too much

19:36 which was what i wanted :)

19:36 Lau_of_DK: hehe

19:36 Alright blackdog , I'll have a closer look

19:38 lisppaste8: blackdog pasted "migpanel" at http://paste.lisp.org/display/62197

19:39 Lau_of_DK: Looks very easy - Considered doing a little lib as a User contrib to clojure ?

19:39 lisppaste8: blackdog pasted "moremig" at http://paste.lisp.org/display/62198

19:39 Lau_of_DK: Do I have to import anything other than javax.swing JPanel to get that working ?

19:40 lisppaste8: blackdog pasted "swing imports" at http://paste.lisp.org/display/62199

19:41 Lau_of_DK: blackdog - Have you got a .clj file with all these imports on common functions that I can see ?

19:42 blackdog: no, I just the basic JButton etc

19:42 i only wrapped panel so i could set the title easil

19:43 lisppaste8: blackdog pasted "easy on the fingers" at http://paste.lisp.org/display/62200

19:52 Lau_of_DK: thanks blackdog, thats actually exactly what I need - its easy to customize

19:52 blackdog: cool,

19:52 yea it's not too daunting

20:07 fyuryu: blackdog: what is the purpose of the tilda in ~'actionPerformed in that macro? I know what ~ and ~@ are for but the quote puzzles me

20:08 blackdog: ah, rich showed me that and said he would fix it

20:08 but it isn't yet as of todays new release

20:08 it's something to do with how the proxy function finds varaibles

20:09 but apart fromthat I know no more,

20:09 fyuryu: aha, ok. Thanks

20:09 blackdog: it is a bug workaround AFAIK

20:54 jcrites: hey.... I was wondering if someone could give me a hint for how I would go about porting to or implementing the visitor pattern in clojure

20:55 slava: clojure has multi-methods, so...

20:55 jcrites: oh, I don't need it then :)

20:55 are they reflection-based?

20:55 not that I need performance for my application

21:03 is it possible to create classes in Clojure that are visible to Java?

21:03 blackdog: there's a gen-and-save-class function

21:03 haven't used it

21:04 genclass.clj

21:08 slava: ther'es also 'implement'

21:08 which allows you to create an anonymous implementation of an interface inline

21:08 blackdog: proxy now

21:08 slava: that's a really neat feature

21:08 blackdog: think implement was deprecated in favor of proxy - same thing

21:11 jcrites: hmmm I'm having trouble udnerstanding how to do things in Clojure; it's so different :)

21:11 does it have something like a record type?

21:11 what if I want a structure that represents a person, with a name and an age? how would I represent it?

21:12 blackdog: the map i suppose but you can have a struct-map which is for space saving of records

21:12 jcrites: I could use a list, but then the semantics would depend on arbitrary ordering of the records, which is bad...

21:12 blackdog: if you have a look at resultset-seq it uses a struct map

21:12 jcrites: I'll take a look at it, thanks

21:14 yup, struct maps look like what I want. thanks again! :-) so struct maps with functions that operate on them take the place of traditional Java classes?

21:15 blackdog: i'm just using resultset-seq as is can't comment further

21:16 i'm not sure that oo is encouraged at all :) by rich anyway, he's quite down on it for data

21:17 here's a comment i snagged earlier today

21:17 <rhickey> data doesn't behave

21:17 <rhickey> things happen, and there might be new data

21:17 <rhickey> those things might involve multiple entities

21:17 <rhickey> no single one of which 'owns' the activity

21:17 <rhickey> so OO is kind of an oversimplification that gets in the way IMO

21:17 jcrites: everyone is certainly entitled to his opinion, especially a language designer :)

21:18 blackdog: http://clojure-log.n01se.net/date/2008-06-13.html

21:18 for more on typing and oo etc

21:24 jcrites: hmmm

21:24 * jcrites considers inheritance without oo ... doesn't exist in any languages but could

21:25 jcrites: you could imagine C-like structures with an inheritance model, providing an IS-A relationship, but with non-OO style operations on them (clojure-style :)

21:41 pjb3: is when-not different than if?

21:43 ah, if has to have multiple arguments, never mind

21:50 slava: rhickey: a struct-map is essentially just an optimization right?

21:50 rhickey: yes

21:51 when you'll have lots of maps with the same fields/keys

Logging service provided by n01se.net