#clojure log - Feb 20 2008

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

0:10 Chouser: I guess you just can't use #( % ) in macros.

14:15 ctp: hi - sorry if this has already been covered, but I am currently doing some work in clojure with lwjgl, getting opengl going etc. All going well at the moment, but I have one question: lwjgl uses static methods on the 'GL11' class quite a lot, and im ending up with lots of similar lines like: (. GL11 (glColor3f 1 1 1)), followed by more beginning (. GL11 ...) - I have tried the '(doto ..)' macro, but this only seems to work for instances... i guess my question

14:19 rhickey: cut off?

14:19 ctp: cut off?

14:19 rhickey: your question is?

14:20 ctp: ahh - sorry - too much text :)

14:20 basically, am i missing something, or is there a 'doto' alike for static methods on a class?

14:21 if not, gives me a good reason for a new macro.

14:21 rhickey: the idea behind doto is that all of the methods will somehow side-effect the object, for statics I presume you'll want the return values?

14:23 ericthor: (defn GL [& body] ~(.. GL11 ~@body))

14:23 this would work no?

14:23 ctp: maybe -

14:23 rhickey: defmacro?

14:24 ctp: effectively i am typing (. GL11 (glBegin (

14:24 (. GL11 (glEnd))

14:24 over and over - so, yes, defmacro

14:25 just devising one now - just wanted to check that i wasn't reinventing something in the core

14:25 ericthor: I have an expression that is returning a vector i want to pass into recur using an apply (apply recur my-vector)

14:25 sorry did not mean to step on this thread

14:25 i'll wait......

14:25 rhickey: ctp: no, but if you think this is something for which there is a general solution, I'll consider adding something

14:26 ctp: ericthor: np - think im done - macro writing.

14:26 hoeck: hi, mhhh, i found out that you cannot bound a static class to a variable in a let

14:26 ericthor: enjoy!

14:26 ctp: rhickey: thanks - let you know

14:27 hoeck: something like (let [a java.lang.Math) (. a (sin 1) does not work

14:27 rhickey: ericthor: can't apply recur - it's not a fn

14:27 ericthor: i know...

14:28 i can rearrange...lots of options

14:28 rhickey: hoeck: dot (.) has special handling of its arguments, so not a function call

14:28 ericthor: but i wanted to call apply on recur :)

14:30 hoeck: ok

14:30 rhickey: Math is auto-imported, so no need for java.lang

14:31 hoeck: i have another question, are nested `sync' s a problem ?

14:31 rhickey: also check out tiny math lib: http://groups.google.com/group/clojure/browse_frm/thread/d07b93e26b2f0f06

14:32 nested syncs belong to same (parent) transaction

14:35 hoeck: so they are just noise to the compiler?

14:35 thanks, i already use math.clj :)

14:35 rhickey: which are noise, nested syncs?

14:36 hoeck: yes, are nested syncs ignored?

14:37 rhickey: I prefer to think that they participate in any enclosing transaction. While you may not write nested syncs in a lexical scope,

14:37 you may end up with them when a larger transaction calls code that was written independently to be transactional

14:44 hoeck: okay, i was just thinking wether macros that use sync to wrap arbitrary code should care about syncs in that code

14:46 rhickey: they don't need to care, otherwise I think it would be unmanageable to compose code

14:50 hoeck: i was just expecting that, i asked just to be shure

14:50 rhickey: it should be fine

14:52 hoeck: btw, thank you for your work on clojure, i _really_ enjoy programming in/on clojure

14:52 rhickey: you're welcome!

14:57 ctp: rhickey: this macro seemed to do the work: (defmacro do-static [class & methods] `(do ~@(map (fn [m] (list '. class m)) methods)))

14:57 (lost formatting there... ;))

14:58 rhickey: so these static methods all have side effects?

14:59 ctp: yes - they are basically calling gl functions under the covers, afaik

14:59 for example, the lwjgl has a 'Display' class

15:00 on which you call 'Display.setFullscreen(false); Display.create()' etc...

15:00 which, in clojure, looks like: (. Display (setFullscreen false)) (. Display (create))

15:01 naturally, there are quite a few static methods - this seems to be the way it is implemented. only started playing with it today, so it is entirely possible i am wrong...

15:02 but clojure is *very* nice so far.

15:02 rhickey: I'm thinking it might be called in-scope

15:02 ctp: yes - seems like a better name

15:02 rhickey: but most imperative things begin with 'do'

15:02 ctp: i was thinking of Haskell's 'do', yes...

15:03 i'm not happy with 'do-static' - maybe 'do-with-scope' or alike?

15:03 its very close to 'doto' in implementation

15:04 rhickey: yes, Clojure has doto, dotimes, doseq, dorun, doall

15:04 no dashes so far

15:04 doscope?

15:04 ctp: sounds good to me

15:07 not sure how many java libraries use extensive statics, really. and 'doto' already exists for instances, so its probably of limited use.

15:07 rhickey: statics just for side-effects I think is rare

15:08 ctp: lots of cases of retrieving static symbols in lwjgl too: (. org.lwjgl.opengl.GL11 GL_QUADS)

15:08 im coming from GL in c/c++ - but the java lwjgl design does seem odd.

15:09 oh well - it was fun writing the macro! thanks for the help.

15:09 rhickey: sure

15:09 ctp: sure beats CFFI + SBCL so far...

15:10 rhickey: having java libs opens up a huge world

15:11 ctp: i'll continue my exploration. thanks again!

15:23 jgracin: when there are two threads that use "set" on the same ref, when does the restart of transaction happen? When the slower one tries to commit or as soon as it tries to set the ref?

15:25 rhickey: It's pretty complex. A thread will block a bit while another has the ref locked, but there are also timeouts, barging, and priorities for older transactions.

15:27 jgracin: thanks.

18:28 ericthor_: rich, given: (def data '[[a * b] + [c * d]])

18:28 (first data)

18:28 yields [a * b]

18:28 (rest data)

18:28 (+ [c * d])

18:28 why (seq? data)

18:28 false

18:29 rhickey: first and rest call seq on their argument

18:29 (seq? (seq data)) will be true

18:29 ericthor_: very trickey

18:29 rhickey: but data is a vector, not a seq

18:31 most sequence functions call seq on their arguments, which can be collections, arrays, strings etc, not just seqs

18:31 you can use seq itself as a predicate, as is done often in boot.clj

18:32 means there is stuff

18:32 whereas seq? is a type test

18:32 ericthor_: so if I want to test if something is sequencable it should be (seq? (seq data))

18:32 rhickey: sequenceable?

18:33 not sure what you mean

18:34 ericthor_: i guess it's just (not (atom? x)) I'm looking for...thx

18:35 rhickey: atom? is still tricky, I guess that's why I've avoided it. For instance strings support seq, but would usually be considered atoms

18:36 but (instance? IPersistentCollection x) picks out the Clojure aggregates

18:48 hoeck: bye

20:52 pjb3: hey, there's a clojure chat room!

20:53 I guess the link off the webpage should have given that away :)

20:53 I've got some beginner questions about FP, anybody care to discuss?

21:06 Chouser: give it a shot. I *might* be a half-step ahead of you.

21:10 pjb3: Ok, so with FP you never create objects

21:10 It's kind of the opposite of OOP in that way, right?

21:22 Chouser: heh. hm.

21:23 That's kinda loaded.

21:23 pjb3: ok, well, clojure has no way of defining classes, right?

21:23 Chouser: There are languages that allow both FP and objects, but that's not really clojure I guess.

21:24 pjb3: Essentially, I think you're correct. There's StructMap, but as the name suggests thats more of a struct thing than an object.

21:24 You wouldn't usually put methods inside it.

21:25 pjb3: Ok, well having done mostly Java and Ruby, that's the part I'm having a hard time wrapping my mind around

21:25 How do you build stuff without objects?

21:25 Chouser: so, yeah, normally in clojure you'll define functions at the top level of a given namespace, and pass data structures to those functions.

21:26 pjb3: how do you use namespaces?

21:28 Chouser: you can probably start off just using the default "user" namespace

21:28 there's info at http://clojure.sourceforge.net/reference/namespaces.html on namespaces.

21:29 I haven't done much with them, but you can use (in-ns 'foo) to switch into the foo namespace, then all your defn function declarations get added to the 'foo namespace.

21:31 pjb3: I see, and then you code that wants to use those functions has switch to that namespace to call them?

21:33 Chouser: you can call functions from a different namespace like: (foo/func ...)

21:34 pjb3: ahh

21:35 Interesting, so I do a lot of web programming that deals with databases using libraries like Hibernate or Rails' ActiveRecord

21:35 ORM frameworks

21:35 not sure if you are familiar with that

21:35 Chouser: I've used ActiveRecord some

21:35 pjb3: Ok, cool

21:36 so in AR if you have a users database table, you define a User class that subclasses ActiveRecord::Base

21:36 then you can go User.find(:all)

21:36 to get an array of user objects

21:36 representing each row in your db table

21:37 How do you think you would model something like that in a FP language like Clojure?

21:38 Chouser: heh, ok, let me take a couple swings at it...

21:41 for simple cases, you could have a single find function that returns a list of StructMaps

21:42 If you needed to specify some extra details that ActiveRecord might find in your subclass, you could pass those in as a separate data structure.

21:43 If that separate data struct is stored in a var called User, then your example call above could be traslated to something like (db/find User :all)

21:44 If you wanted more advanced features like callbacks or overriding of accessors or mutators, you should be able to do something with clojure's multimethods.

21:45 pjb3: Is StructMap differenct than the regular {} map?

21:45 Chouser: Anyway, that's a sketch of how I'd start, but I've done a lot more large-scale design in OO langs than non-OO, so .. this might not be the right approach. :-)

21:46 only slightly. It's more efficient at storing a large number of maps with a common set of keys than regular map.

21:47 pjb3: what about creating a namespace for each object

21:47 (User/find)

21:48 Chouser: probably the wrong approach, but I dunno it might work.

21:48 You should probably try to dissect why you think you want objects or classes, like specifically which features.

21:49 Clojure probably has support for each different feature, just packaged up in different ways.

21:49 For example if it's polymorphism you want, multimethods are a more powerful way to do that.

21:50 pjb3: yeah, I was thinking about that

21:50 Chouser: If it's data hiding you want, you might be able to get what you want with nested functions (closures).

21:54 pjb3: does clojure have named params for functions?

21:58 Chouser: got to go for now, thanks for your help

22:03 ericthor: rich: given (def r (ref 0))

22:03 (sync nil (alter r (fn [y] y) 15))

22:04 java.lang.reflect.InvocationTargetException

22:04 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

22:05 i'm sure it's right in front of me but i can't see what is wrong with my alter statement?

22:13 rhickey: are you trying to set r to 15?

22:18 (sync nil (set r 15))

22:18 alter if for functions that transform the value in a ref rather than replace it

22:18 iis

22:18 is

22:28 ericthor: what would be the example there?

22:28 @r to 15

Logging service provided by n01se.net