2008-02-20
| 00: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 | ctp | basically, am i missing something, or is there a 'doto' alike for static methods on a class? |
| 14:21 | ctp | 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 | ericthor | this would work no? |
| 14:23 | ctp | maybe - |
| 14:23 | rhickey | defmacro? |
| 14:24 | ctp | effectively i am typing (. GL11 (glBegin ( |
| 14:24 | ctp | (. GL11 (glEnd)) |
| 14:24 | ctp | over and over - so, yes, defmacro |
| 14:25 | ctp | 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 | ericthor | sorry did not mean to step on this thread |
| 14:25 | ericthor | 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 | ericthor | 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 | rhickey | nested syncs belong to same (parent) transaction |
| 14:35 | hoeck | so they are just noise to the compiler? |
| 14:35 | hoeck | 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 | rhickey | 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 | ctp | (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 | ctp | for example, the lwjgl has a 'Display' class |
| 15:00 | ctp | on which you call 'Display.setFullscreen(false); Display.create()' etc... |
| 15:00 | ctp | which, in clojure, looks like: (. Display (setFullscreen false)) (. Display (create)) |
| 15:01 | ctp | 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 | ctp | 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 | ctp | i'm not happy with 'do-static' - maybe 'do-with-scope' or alike? |
| 15:03 | ctp | its very close to 'doto' in implementation |
| 15:04 | rhickey | yes, Clojure has doto, dotimes, doseq, dorun, doall |
| 15:04 | rhickey | no dashes so far |
| 15:04 | rhickey | doscope? |
| 15:04 | ctp | sounds good to me |
| 15:07 | ctp | 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 | ctp | im coming from GL in c/c++ - but the java lwjgl design does seem odd. |
| 15:09 | ctp | 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 | ericthor_ | (first data) |
| 18:28 | ericthor_ | yields [a * b] |
| 18:28 | ericthor_ | (rest data) |
| 18:28 | ericthor_ | (+ [c * d]) |
| 18:28 | ericthor_ | why (seq? data) |
| 18:28 | ericthor_ | false |
| 18:29 | rhickey | first and rest call seq on their argument |
| 18:29 | rhickey | (seq? (seq data)) will be true |
| 18:29 | ericthor_ | very trickey |
| 18:29 | rhickey | but data is a vector, not a seq |
| 18:31 | rhickey | most sequence functions call seq on their arguments, which can be collections, arrays, strings etc, not just seqs |
| 18:31 | rhickey | you can use seq itself as a predicate, as is done often in boot.clj |
| 18:32 | rhickey | means there is stuff |
| 18:32 | rhickey | 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 | rhickey | 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 | rhickey | 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 | pjb3 | I guess the link off the webpage should have given that away :) |
| 20:53 | pjb3 | 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 | pjb3 | It's kind of the opposite of OOP in that way, right? |
| 21:22 | Chouser | heh. hm. |
| 21:23 | Chouser | 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 | Chouser | 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 | Chouser | 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 | pjb3 | 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 | Chouser | there's info at http://clojure.sourceforge.net/reference/namespaces.html on namespaces. |
| 21:29 | Chouser | 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 | pjb3 | Interesting, so I do a lot of web programming that deals with databases using libraries like Hibernate or Rails' ActiveRecord |
| 21:35 | pjb3 | ORM frameworks |
| 21:35 | pjb3 | not sure if you are familiar with that |
| 21:35 | Chouser | I've used ActiveRecord some |
| 21:35 | pjb3 | Ok, cool |
| 21:36 | pjb3 | so in AR if you have a users database table, you define a User class that subclasses ActiveRecord::Base |
| 21:36 | pjb3 | then you can go User.find(:all) |
| 21:36 | pjb3 | to get an array of user objects |
| 21:36 | pjb3 | representing each row in your db table |
| 21:37 | pjb3 | 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 | Chouser | for simple cases, you could have a single find function that returns a list of StructMaps |
| 21:42 | Chouser | 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 | Chouser | 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 | Chouser | 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 | Chouser | 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 | pjb3 | (User/find) |
| 21:48 | Chouser | probably the wrong approach, but I dunno it might work. |
| 21:48 | Chouser | You should probably try to dissect why you think you want objects or classes, like specifically which features. |
| 21:49 | Chouser | Clojure probably has support for each different feature, just packaged up in different ways. |
| 21:49 | Chouser | 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 | pjb3 | Chouser: got to go for now, thanks for your help |
| 22:03 | ericthor | rich: given (def r (ref 0)) |
| 22:03 | ericthor | (sync nil (alter r (fn [y] y) 15)) |
| 22:04 | ericthor | java.lang.reflect.InvocationTargetException |
| 22:04 | ericthor | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) |
| 22:05 | ericthor | 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 | rhickey | (sync nil (set r 15)) |
| 22:18 | rhickey | alter if for functions that transform the value in a ref rather than replace it |
| 22:18 | rhickey | iis |
| 22:18 | rhickey | is |
| 22:28 | ericthor | what would be the example there? |
| 22:28 | ericthor | @r to 15 |