#clojure logs

2008-02-20

00:10ChouserI guess you just can't use #( % ) in macros.
14:15ctphi - 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:19rhickeycut off?
14:19ctpcut off?
14:19rhickeyyour question is?
14:20ctpahh - sorry - too much text :)
14:20ctpbasically, am i missing something, or is there a 'doto' alike for static methods on a class?
14:21ctpif not, gives me a good reason for a new macro.
14:21rhickeythe 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:23ericthor(defn GL [& body] ~(.. GL11 ~@body))
14:23ericthorthis would work no?
14:23ctpmaybe -
14:23rhickeydefmacro?
14:24ctpeffectively i am typing (. GL11 (glBegin (
14:24ctp(. GL11 (glEnd))
14:24ctpover and over - so, yes, defmacro
14:25ctpjust devising one now - just wanted to check that i wasn't reinventing something in the core
14:25ericthorI have an expression that is returning a vector i want to pass into recur using an apply (apply recur my-vector)
14:25ericthorsorry did not mean to step on this thread
14:25ericthori'll wait......
14:25rhickeyctp: no, but if you think this is something for which there is a general solution, I'll consider adding something
14:26ctpericthor: np - think im done - macro writing.
14:26hoeckhi, mhhh, i found out that you cannot bound a static class to a variable in a let
14:26ericthorenjoy!
14:26ctprhickey: thanks - let you know
14:27hoecksomething like (let [a java.lang.Math) (. a (sin 1) does not work
14:27rhickeyericthor: can't apply recur - it's not a fn
14:27ericthori know...
14:28ericthori can rearrange...lots of options
14:28rhickeyhoeck: dot (.) has special handling of its arguments, so not a function call
14:28ericthorbut i wanted to call apply on recur :)
14:30hoeckok
14:30rhickeyMath is auto-imported, so no need for java.lang
14:31hoecki have another question, are nested `sync' s a problem ?
14:31rhickeyalso check out tiny math lib: http://groups.google.com/group/clojure/browse_frm/thread/d07b93e26b2f0f06
14:32rhickeynested syncs belong to same (parent) transaction
14:35hoeckso they are just noise to the compiler?
14:35hoeckthanks, i already use math.clj :)
14:35rhickeywhich are noise, nested syncs?
14:36hoeckyes, are nested syncs ignored?
14:37rhickeyI prefer to think that they participate in any enclosing transaction. While you may not write nested syncs in a lexical scope,
14:37rhickeyyou may end up with them when a larger transaction calls code that was written independently to be transactional
14:44hoeckokay, i was just thinking wether macros that use sync to wrap arbitrary code should care about syncs in that code
14:46rhickeythey don't need to care, otherwise I think it would be unmanageable to compose code
14:50hoecki was just expecting that, i asked just to be shure
14:50rhickeyit should be fine
14:52hoeckbtw, thank you for your work on clojure, i _really_ enjoy programming in/on clojure
14:52rhickeyyou're welcome!
14:57ctprhickey: this macro seemed to do the work: (defmacro do-static [class & methods] `(do ~@(map (fn [m] (list '. class m)) methods)))
14:57ctp(lost formatting there... ;))
14:58rhickeyso these static methods all have side effects?
14:59ctpyes - they are basically calling gl functions under the covers, afaik
14:59ctpfor example, the lwjgl has a 'Display' class
15:00ctpon which you call 'Display.setFullscreen(false); Display.create()' etc...
15:00ctpwhich, in clojure, looks like: (. Display (setFullscreen false)) (. Display (create))
15:01ctpnaturally, 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:02ctpbut clojure is *very* nice so far.
15:02rhickeyI'm thinking it might be called in-scope
15:02ctpyes - seems like a better name
15:02rhickeybut most imperative things begin with 'do'
15:02ctpi was thinking of Haskell's 'do', yes...
15:03ctpi'm not happy with 'do-static' - maybe 'do-with-scope' or alike?
15:03ctpits very close to 'doto' in implementation
15:04rhickeyyes, Clojure has doto, dotimes, doseq, dorun, doall
15:04rhickeyno dashes so far
15:04rhickeydoscope?
15:04ctpsounds good to me
15:07ctpnot sure how many java libraries use extensive statics, really. and 'doto' already exists for instances, so its probably of limited use.
15:07rhickeystatics just for side-effects I think is rare
15:08ctplots of cases of retrieving static symbols in lwjgl too: (. org.lwjgl.opengl.GL11 GL_QUADS)
15:08ctpim coming from GL in c/c++ - but the java lwjgl design does seem odd.
15:09ctpoh well - it was fun writing the macro! thanks for the help.
15:09rhickeysure
15:09ctpsure beats CFFI + SBCL so far...
15:10rhickeyhaving java libs opens up a huge world
15:11ctpi'll continue my exploration. thanks again!
15:23jgracinwhen 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:25rhickeyIt'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:27jgracinthanks.
18:28ericthor_rich, given: (def data '[[a * b] + [c * d]])
18:28ericthor_(first data)
18:28ericthor_yields [a * b]
18:28ericthor_(rest data)
18:28ericthor_(+ [c * d])
18:28ericthor_why (seq? data)
18:28ericthor_false
18:29rhickeyfirst and rest call seq on their argument
18:29rhickey(seq? (seq data)) will be true
18:29ericthor_very trickey
18:29rhickeybut data is a vector, not a seq
18:31rhickeymost sequence functions call seq on their arguments, which can be collections, arrays, strings etc, not just seqs
18:31rhickeyyou can use seq itself as a predicate, as is done often in boot.clj
18:32rhickeymeans there is stuff
18:32rhickeywhereas seq? is a type test
18:32ericthor_so if I want to test if something is sequencable it should be (seq? (seq data))
18:32rhickeysequenceable?
18:33rhickeynot sure what you mean
18:34ericthor_i guess it's just (not (atom? x)) I'm looking for...thx
18:35rhickeyatom? is still tricky, I guess that's why I've avoided it. For instance strings support seq, but would usually be considered atoms
18:36rhickeybut (instance? IPersistentCollection x) picks out the Clojure aggregates
18:48hoeckbye
20:52pjb3hey, there's a clojure chat room!
20:53pjb3I guess the link off the webpage should have given that away :)
20:53pjb3I've got some beginner questions about FP, anybody care to discuss?
21:06Chousergive it a shot. I *might* be a half-step ahead of you.
21:10pjb3Ok, so with FP you never create objects
21:10pjb3It's kind of the opposite of OOP in that way, right?
21:22Chouserheh. hm.
21:23ChouserThat's kinda loaded.
21:23pjb3ok, well, clojure has no way of defining classes, right?
21:23ChouserThere are languages that allow both FP and objects, but that's not really clojure I guess.
21:24Chouserpjb3: Essentially, I think you're correct. There's StructMap, but as the name suggests thats more of a struct thing than an object.
21:24ChouserYou wouldn't usually put methods inside it.
21:25pjb3Ok, well having done mostly Java and Ruby, that's the part I'm having a hard time wrapping my mind around
21:25pjb3How do you build stuff without objects?
21:25Chouserso, yeah, normally in clojure you'll define functions at the top level of a given namespace, and pass data structures to those functions.
21:26pjb3how do you use namespaces?
21:28Chouseryou can probably start off just using the default "user" namespace
21:28Chouserthere's info at http://clojure.sourceforge.net/reference/namespaces.html on namespaces.
21:29ChouserI 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:31pjb3I see, and then you code that wants to use those functions has switch to that namespace to call them?
21:33Chouseryou can call functions from a different namespace like: (foo/func ...)
21:34pjb3ahh
21:35pjb3Interesting, so I do a lot of web programming that deals with databases using libraries like Hibernate or Rails' ActiveRecord
21:35pjb3ORM frameworks
21:35pjb3not sure if you are familiar with that
21:35ChouserI've used ActiveRecord some
21:35pjb3Ok, cool
21:36pjb3so in AR if you have a users database table, you define a User class that subclasses ActiveRecord::Base
21:36pjb3then you can go User.find(:all)
21:36pjb3to get an array of user objects
21:36pjb3representing each row in your db table
21:37pjb3How do you think you would model something like that in a FP language like Clojure?
21:38Chouserheh, ok, let me take a couple swings at it...
21:41Chouserfor simple cases, you could have a single find function that returns a list of StructMaps
21:42ChouserIf 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:43ChouserIf 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:44ChouserIf 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:45pjb3Is StructMap differenct than the regular {} map?
21:45ChouserAnyway, 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:46Chouseronly slightly. It's more efficient at storing a large number of maps with a common set of keys than regular map.
21:47pjb3what about creating a namespace for each object
21:47pjb3(User/find)
21:48Chouserprobably the wrong approach, but I dunno it might work.
21:48ChouserYou should probably try to dissect why you think you want objects or classes, like specifically which features.
21:49ChouserClojure probably has support for each different feature, just packaged up in different ways.
21:49ChouserFor example if it's polymorphism you want, multimethods are a more powerful way to do that.
21:50pjb3yeah, I was thinking about that
21:50ChouserIf it's data hiding you want, you might be able to get what you want with nested functions (closures).
21:54pjb3does clojure have named params for functions?
21:58pjb3Chouser: got to go for now, thanks for your help
22:03ericthorrich: given (def r (ref 0))
22:03ericthor(sync nil (alter r (fn [y] y) 15))
22:04ericthorjava.lang.reflect.InvocationTargetException
22:04ericthor at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
22:05ericthori'm sure it's right in front of me but i can't see what is wrong with my alter statement?
22:13rhickeyare you trying to set r to 15?
22:18rhickey(sync nil (set r 15))
22:18rhickeyalter if for functions that transform the value in a ref rather than replace it
22:18rhickeyiis
22:18rhickeyis
22:28ericthorwhat would be the example there?
22:28ericthor@r to 15