#clojure logs

2009-09-30

00:45thedoorwow
00:45thedoora lot of people at this channel :P
00:45arbschtit is growing :)
00:46thedoora work friend talk to me about clojure today, now im installing the nescessary thing to star :)
00:46thedoorstart*
00:51Raynesthedoor: And it's the middle of the night for a lot of people. We get new people in here all the time.
00:52Raynesthedoor: I hope you have lots of fun with Clojure. :)
00:52thedoorhere is 02:00 am :)
00:53thedoori need to sleep but i need to star this :P
00:53thedoorstart*
00:53thedoorsorry my bad english :(
01:44hiredmanclojurebot: ping?
01:44clojurebotPONG!
02:56yasonre
03:06vyReading the Agents documentation... What does "dispatch" in "If during the function execution any other dispatches are made (directly or indirectly), they will be held until after the state of the Agent has been changed." expression?
03:07hiredmansend or send-off
03:08vyThanks.
03:11vyDispatches on an agent are placed in a queue that are consumed by a thread pool? Right? If so, assuming mutation of the agent is serialized, what's the necessity/role of a thread pool in here? Wouldn't it be more simple to dedicate a single thread for an agent and its dispatch queue?
03:13vyHrm... Or that "thread pool" is dedicated to "whole available agents"?
03:14hiredmansend sends to a fixed size threadpool (I think it as 2+core count last I checked)
03:14hiredmansend-off sends to a non-fixed size threadpool
03:15hiredmanwell, have 200 threads try to run on a 2 core machine is kind of, well, not entirely optimal
03:16jdzhiredman: optimal for what?
03:17jdzwhen i look in the process browser on my machine, there are 261 threads running currently
03:17hiredmanthats a lie
03:17vyHrm... Yeah, that's for sure. What I now realize is that: 1) There is a single (actually 2, one for "send" and another one for "send-off") dedicated thread pool and mutations to a single Agent is serialized. 2) No more than one thread tries to write to the same Agent at a time in the pool.
03:17jdzhiredman: says who?
03:18hiredmanthe processor is switching back and forth between 261 processes
03:18hiredmanjdz: I just did (according to my logs)
03:18jdzwell, then by your logic, what's the point of having 2+core count threads? why 2 more?
03:19jdzand JVM starts with how many threads?
03:19hiredmanjdz: because threads might block for io or whatever
03:19jdzso, the original question stands...
03:19vySun Java System Application Server 9.1 Performance Tuning Guide > Thread Count [http://docs.sun.com/app/docs/doc/819-3681/6n5srlhod?a=view]
03:26jdzvy: that's about very specific purpose
03:27jdzvy: namely HTTP request handling
03:27hiredmaneveryone has some heuristic
03:28hiredmanI've seen 1+core count, 2+core count, 5*core count
03:28hiredmanthere was a paper in acm like eight years ago that did some real math on the subject
03:28jdzlol, "real math"
03:29hiredmanwell, more than multiplication and addition
03:33Fossihi
03:38Fossicgrand: sorry to bother you, but you seem to be involved into hashmap development: is there a chance to make it serializable?
03:52cgrandFossi: personally I don't care about java serialization so I won't push for it. Plus other clojure data structures doesn't implement serializable either.
03:54Fossicgrand: well, at least in my clojure PersistenHashMap implements Serializable, but BitmapIndexedNode prevents it from actually being it
03:54cgrandhmm let me check
03:55Fossiand it's a pita to serialize a deep map (for memcache/jcache in this case) either way through serializable (because of maps and keywords) and through the reader because of 'custo,m' java classes that we can't read back
03:56Fossiso wanting to cache an object graph, we're stuck with walking it and transforming or such
03:56hiredmanFossi: you know about print-dup and #=()?
03:56Fossihiredman: what does #=() do?
03:56hiredman#=() allows for limited read time evaluation
03:56Fossii've tried print-dup and we couldn't get the things to read back in
03:57hiredmanso you hook a custom method into, uh, I think it's called print-method
03:57hiredman,(doc print-method)
03:57clojurebot"; "
03:57hiredmanhow useful
03:57Fossi;D
03:57hiredmanwhich prn uses
03:57Fossiyeah, i get that part, but how do i read it back in?
03:58hiredmanit emits a some thing like "#=(java.util.ArrayList (1 3 4 5))"
03:58hiredman,#=(java.util.ArrayList (1 3 4 5))
03:58clojurebotCan't resolve java.util.ArrayList
03:58hiredman,#=(java.utils.ArrayList (1 3 4 5))
03:58clojurebotjava.utils.ArrayList
03:58hiredmanbah
03:58hiredman,#=(java.utils.ArrayList. (1 3 4 5))
03:58clojurebotjava.utils.ArrayList
03:58Fossiok, that should prolly work
03:59hiredman,#=(java.util.ArrayList. '(1 3 4 5))
03:59clojurebot#<ArrayList [quote, (1 3 4 5)]>
03:59hiredman,#=(java.util.ArrayList. (1 3 4 5))
03:59clojurebot#<ArrayList [1, 3, 4, 5]>
03:59hiredmangah
03:59hiredmanread time arraylist
04:01Fossihiredman: i'll try and snoop around some more in the read and print code
04:05cgrandFossi, for the record, PersistentHashMap implements Serializable through AFn and AFn was marked Serializable in commit "cleanup for findbugs" http://github.com/cgrand/clojure/commit/7cd3b285328e7e7e71b23080303d66640e0f21e8#diff-0
04:14LauJensenMorning cgrand
04:14cgrandmorning LauJensen
04:24Fossicgrand: ok, so i guess that's a smallish 'bug' then
04:24Fossisince a lot of stuff is marked serializabel since a lot of things implement ifn :)
04:24cgrand,(ancestors (class #(42)))
04:24clojurebot#{clojure.lang.IMeta clojure.lang.IFn clojure.lang.IObj java.lang.Object clojure.lang.Fn clojure.lang.Obj java.util.Comparator java.util.concurrent.Callable java.lang.Runnable :clojure.contrib.generic/any java.io.Serializable clojure.lang.AFunction clojure.lang.AFn}
04:26Fossialso a bit weird to have something callable marked as serializable :)
04:36serp_,(funcall)
04:36clojurebotjava.lang.Exception: Unable to resolve symbol: funcall in this context
04:37serp_,(#(42))
04:37clojurebotjava.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
04:37serp_,#(42)
04:37clojurebot#<sandbox$eval__4764$fn__4766 sandbox$eval__4764$fn__4766@1324de2>
04:37serp_I don't get it =(
04:37serp_why would the second one work.
04:39funkenblattwell i think a better question is why the first one didn't work
04:39funkenblattthe second one is supposed to work
04:41serp_I'm talking about ,(#(42))
04:41funkenblattoh
04:41serp_shouldn't #(42) return a lambda function that simply returns 42, and is later evaluated
04:43Fossi,(macroexpand-1 '(#(42)))
04:43clojurebot((fn* [] (42)))
04:44serp_oh I see...
04:44Fossia smallish annoyance and source of common confusion
04:44Fossibut better than having to type #(( all the time
04:45serp_I don't know... seems like magic to me... makes the language harder to understand
04:45opqdonutyou can always use #(int 42) ;)
04:45serp_unless...
04:45serp_,(macroexpand-1 '#42)
04:45clojurebotNo dispatch macro for: 4
04:46serp_,#42
04:46clojurebotNo dispatch macro for: 4
04:46serp_nope
04:46Fossi# is not the reader macro #( is
04:46opqdonutanyways, (constantly 42) is better
04:46Fossisind # is used for a lot of things
04:46Fossi*since
04:46opqdonut, ((constantly 42) 0)
04:46clojurebot42
04:47serp_so a construct with #( has an implied function call in it
04:47Fossiotherwise you would have to type #((some-fn %)) all the time
04:48serp_sure, but then it is very clear what's going on =)
04:51jdzno, if just don't use the #() construct at all
04:51jdzthen it's very clear what's going on
04:57Chousuke#() is a very useful shortcut sometimes, but it's not intended to replace fn
04:58Chousukeyou can think of # as transforming a single expression into a function, if you want :P
04:59Chousuke(and that expression must be a list form)
05:27Fossisometimes i miss #([(:a %) (:b %)]), but destructuring works better anyway
05:41ChousukeFossi: or the new juxt
05:41Chousuke,((juxt :a :b) {:a 1 :b 2 :c 3})
05:41clojurebotjava.lang.Exception: Unable to resolve symbol: juxt in this context
05:41Chousukehm
05:42Chousukeclojurebot: you're old :(
05:42clojurebotNo entiendo
05:43ChousukeFossi: well, anyway, a new function was added recently, and #(vector (:a %) (:b %)) = (juxt :a :b)
05:44cgrand,(#(map % [:a :b]) {:a 1 :b 2 :c 3}) ; not a vector though -- and juxt is better
05:44clojurebot(1 2)
05:44serp_,(#(list % %) 1 2)
05:44clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--4786$fn
05:44cgrand(#(list %1 %2) 1 2)
05:45serp_what does just % mean?
05:45Chousukesame as %1
05:45serp_oh
07:42Drakesonhow can I use incanter on a headless machine? incanter imports processing.PApplet, which apparently asks for a graphical environment. Is there a standard way to deal with graphical packages when you run on a headless machine and don't need them but they are imported in the package?
07:46dliebkeDrakeson: I shouldn't import PApplet in incanter.core, I'll try and remedy that today
07:47Drakesonthanks
07:49Drakesonone more thing, incanter places the dependencies in the git repos. maybe what compojure does is a bit better. compojure zips and puts the deps in github using the `upload' feature, and just places a link in the main repo.
07:50dliebkeDrakeson: there has been discussion about using Maven to manage dependencies
07:52Drakesonthat would be cool :) (I often follow discussions about package managers, and dependency resolvers).
08:38Fossii'm getting a "Caused by: java.lang.NoSuchMethodError: clojure.lang.Namespace.importClass(Ljava/lang/Class;)Ljava/lang/Class;" when building from ant, but not from emacs using the same clojure.jar
08:39Fossiit's behaving really weird
09:00ar1It's so quiet.
09:16Fossiar1: so?
09:16Fossibtw: my problem was solved by running ant clean and thus deleting our target dir. no idea what went wrong inbetween
09:38AWizzArdIs there an easier way to do (.toString (.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.) (StringBuffer.) (java.text.FieldPosition. 0)))?
09:38AWizzArd,(.toString (.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.) (StringBuffer.) (java.text.FieldPosition. 0)))
09:38clojurebot"2009-09-30_06-43-03-925"
09:39rsynnottheheh, poor clojure hasn't quite escaped the terrifying Java date classes, then? :)
09:39rsynnottsomeone should write a nice wrapper
09:39chousersomeone did
09:39chouserthey got shouted down for not just using JediDate or whatever it's called
09:40chouser,(.format (java.text.SimpleDateFormat. "yyyy-MM-dd_HH-mm-ss-SSS") (java.util.Date.))
09:40clojurebot"2009-09-30_06-45-36-693"
09:41rsynnott(presumably there on the basis that the world might arbitrarily start using a different calendar)
09:41AWizzArdchouser: oh good, this is much nicer
09:42AWizzArdstrange i didn't see this on the api page of SimpleDateFormat
09:44manic12this may sound like backward steps to clojurites, but it is true that ordinary single-object dispatch (smalltalk/flavors style) is quite useful to engineers...
09:45chousermanic12: sure. Clojure uses it all the time.
09:45manic12I haven't learned enough clojure to do that in clojure
09:45chouserbecause the JVM can do it *fast*, mostly.
09:46manic12and I also haven't learned how to create generative style extensions to that
09:47chouserconj is single-dispatch on the type of the first arg
09:48chouserfor example
09:50manic12another thing, I haven't learned how to write declaratively in clojure, just functional with procedural aspects mostly talking to java libs
09:52Fossire serialization: now we have some trouble serializing structs. it seems that they are treated as an persistentMap and that has a "create" method, but the structs don't
09:53Fossiso naturally, things break
09:57manic12I would like to create an 'object' which behaves a bit like a map, that instead of simply fetching the value, it calls a function on itself to compute and memoize the value, seems a bit anti-immutable
09:59manic12but maybe that's ok, because it would be easier to implement 'undo'
09:59manic12anybody there?
10:00chouserdid you ask a question?
10:00manic12i am asking how to do that sort of thing with clojure
10:01chouserone way would be to implement clojure.lang.IPersistentMap using proxy
10:01manic12what about just deriving a actual java class?
10:03chouser,(let [m (proxy [clojure.lang.APersistentMap] [] (valAt [_] 5) (seq [] nil))] [(get m :foo) (:bar m) (seq m)])
10:03clojurebot[5 5 nil]
10:04tmountainchouser: that's pretty nifty
10:06jdzwhy the hell does slurp declare the f parameter as String?
10:07tmountainjdz: it takes a string pointing to the file
10:07jdzand why does it care if i pass it an instance of java.io.File?
10:07tmountain$ echo "foo" > /tmp/foo.txt
10:08tmountain(slurp "/tmp/foo.txt")
10:08tmountain"foo\n"
10:09jdztmountain: and notice that (slurp (new java.io.File "/tmp/foo.txt")) does not work :/
10:10tmountainjdz: yeah, looking at its implementation, slurp creates a FileInputStream in the background with f as it's argument
10:10jdzdespite the fact that java.io.FileInputStream accepts java.io.File in the constructor
10:10tmountainjdz: yeah, that does sort of limit it's utility
10:13tmountainjdz: slurp uses the two argument form for the FileInputStream constructor
10:14tmountainjdz: to allow specification of encoding
10:14jdztmountain: your point being?
10:14jdztmountain: it uses it anyway even when passed only one parameter
10:15tmountainjdz: point being, you'd need another declaration to make it work with both a File and String
10:15jdzno
10:16jdzjust drop the #^String thing
10:16jdzeasy as that
10:16manic12chouser: how do I access the proxy object if valAt is being defined in the proxy definition?
10:17manic12i need the keys to be able to reference other keys
10:17tmountainjdz: my mistake, I see it's the InputStreamReader that takes the encoding argument
10:18jdztmountain: my gripe with this is that somebody added the declaration although it does no good.
10:18jdztmountain: same for the encoding
10:19tmountainjdz: yeah, you're right, I removed the type hint, and it works with a File as well
10:20ChousukeI suppose the type hint gives no measurable performance gain. :P
10:21Chousukeso it'd be better to remove it.
10:21tmountainyeah, I'd imagine there's miniscule difference in performance
10:22Chousukeif you wanted performance you wouldn't use slurp anyway
10:22Chousukeit's wasteful ;P
10:22tmountainusing string builder
10:22Chousukestr uses a string builder internally. I mean storing an entire file in a string
10:23tmountainwasteful memory wise
10:24manic12chouser: if you're there I want to post something
10:28AWizzArdCompojure users: anyone here who handles json requests?
10:36manic12i would like to use clojure in a practical application, is there anyone here who can discuss how i might be able to satisfy some of the requirements with clojure?
10:38manic12is anyone here at all?
10:39rsynnotthiding :)
10:40manic12must be a coffee break
10:44cemerickwe're all working :-P
10:44arbschtmanic12: state your question and anyone who can answer it may...
10:46manic12clojurebot: lisppaste
10:46clojurebotIt's greek to me.
10:46manic12is there a specific lisppaste for this irc channel?
10:47ambientM-x package-install lisppaste ;)
10:47manic12tehe
10:49Fossilisppaste8: url
10:49lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
10:50Fossimanic12: there you go
10:51lisppaste8manic12 pasted "how to do in clojure?" at http://paste.lisp.org/display/87950
10:51manic12thx
10:58raekhow do I add my own directory to the CLASSPATH and still have the library paths in it?
10:58raekor -- how do I find my system default CLASSPATH?
10:59raekI ran "find /usr -name \*.jar -print" to find the jars in my system
10:59raekbut they're evererywhere!
11:05liwpraek: on unix with bash: export CLASSPATH=path/to/foo.jar:path/to/classes:$CLASSPATH
11:05raekyes, I know
11:06raekbut I sort of found a solution to my problem
11:06liwpok, so what's the problem exactly
11:06liwpok
11:06raekI specified the path to my own clj files with the -cp option to java
11:06liwpraek: that'll work
11:06raekbut then I also had to add the path to the system jar files
11:07liwpyou shouldn't have to do that. What do you mean with system jar files?
11:08raekI'm trying to get compojure running
11:08raekbut it turned that I missed a dependency
11:09raekjava.lang.ClassNotFoundException: org.mortbay.jetty.servlet.Context (jetty.clj:0)
11:09raekthis is what I get when evaluating (use 'compojure)
11:10raekoh wait
11:10raekforgot to put the jar files produced by "ant deps" into my classpath
11:11raekyou may ignore my previous 10 lines
11:12liwpheh
11:12raekjava.lang.SecurityException: sealing violation: package org.mortbay.jetty.servlet is sealed (jetty.clj:0)
11:13raekok, what have I done now?
11:21raekok, working now
11:22raekremoved jetty and firends with my package manager and used the jars supplied by compojure
11:29kunjanIs Clojure dynamically scoped in some cases?
11:36yasonkunjan: I'm not an expert by any means but IIRC no. You could probably simulate dynamic scope with vars and (binding ...)
11:40raek(let) in clojure introduces lexically scoped variables
11:40raekand (binding) dynamically scoped ones
11:44rhickeyraek: they aren't dynamically scoped, just dynamically bound. If you do (defn foo [] (use-some free-var)) it will fail at compile time if free-var isn't in scope, vs true dynamic scope where someone could establish free-var then call foo and have it find it
11:45sproingiehttp://onclojure.com/2009/05/06/simulating-dynamic-scoping/
11:46raekah, please bear with me. i've only used clojure for a week
11:46sproingiedoesn't look like a general solution tho
11:47raek:rhickey ah, I see.
11:49raekthese things are new to me, as I come from languages that doesn't have these things
11:49raekor I wasn't aware of them
11:53raekis it un-ideomatic to use variables with dynamic bindings as a way to not have to pass a certain arg to function?
11:53raeki'm coding some things that calculates the width and height of texts that will be drawn
11:53raekand these things depends on the Metrics of the font in use
11:54rhickeyraek: if you are just starting out you should avoid dynamic binding
11:54yasonraek: so what you want is an easy way to pass on state?
11:55stuartsierraI think it's idiomatic, but subject to a number of tricky bit when laziness & concurrency are involved
11:55raek(binging [metrics (.. label .getFont .getMetrics)]] (calculate-width "text"))
11:56raekand (calculate-width) then uses metrics
11:57raekbut as the width is a function of both the text and the metrics, maybe I should pass along metrics as an arg
11:58raekthat is the way I do it now
12:04manic12_are object systems in general anti-clojure philosophy?
12:05rhickeymanic12_: http://clojure.org/state
12:05Makoryumanic12_: Stateful objects are the bane of both concurrency and common sense.
12:06rhickeyI don't know that anyone has reconciled OO with the problems enumerated there, but I don't think it is impossible. Whether the result would be considered OO anymore is another question
12:07rhickeyOO includes a lot of things that Clojure delivers a la carte, like polymorphism and hierarchy
12:07manic12__sorry my internet connection dropped, i think the router was rebooted
12:08Makoryumanic12__: http://clojure-log.n01se.net/ <- You can always use this to see what you missed.
12:08manic12__thanks
12:08MakoryuOr, er, not, I suppose
12:08MakoryuI thought it updated more frequently
12:09chouserevery 15 minutes right now
12:09chouser20 minutes
12:10Makoryumanic12__: Anyway... https://gist.github.com/61e9ffb761b574428cc4
12:10manic12__i've got a declarative DSL built into clos, and i am interested in doing the same things with clojure
12:11sproingiemight try spinoza or categories. not tried either myself so i couldnt say how good they are
12:12sproingiedammit..
12:12sproingiemanic12__: ^^^
12:13manic12__are those on github or somewhere?
12:13sproingiegoogle code i think
12:13sproingieteh googelz knows :)
12:13DraggorAre there any lexers for Clojure? Something like cl-yacc?
12:13manic12__oh wow
12:14sproingieneither spinoza nor categories defines a call-next-method tho, let alone a formal MRO
12:15manic12__i actually don't need call-next-method because it makes no sense in the DSL
12:16manic12__so categories is a drinking game
12:16sproingiehard to reconcile with the predicate dispatch of multifn's anyway
12:16stuartsierraDraggor: you could use ANTLR or JavaCC to generate a lexer
12:17sproingiemanic12__: categories is at http://code.google.com/p/explorersguild/
12:17sproingiesomewhere in the source
12:17Draggorstuartsierra: the JavaCC site appears to be down. Does one have any particular features over the other?
12:18cemerickwasn't cgrand working on a slick clojure DSL for grammars?
12:18sproingieantlr has oodles of features. also a vertical learning curve, and some annoying conventions around lexer/parser distinctions
12:20cgrandcemerick: still working
12:22cemerickcgrand: just giving you the intro to do some promotion :-)
12:22stuartsierraDraggor: ANTLR is generally considered easier to use, but it requires a runtime library to run your parser. ANTLR generates recursive-descent parsers, JavaCC generates (I think) bottom-up parsers
12:23cemerickI got tired of javacc and antlr years and years ago.
12:23stuartsierraFor very simple grammars (e.g., Lisp) they're overkill.
12:23stuartsierraBut essential for parsing something like C.
12:25manic12__cannot each change to an object be a new structure entirely?
12:25DraggorI'm just having fun and writing a parser for a die roller, something like [5d6] or [[1d6]d6]
12:26DraggorAnd then put math operations in it too
12:26rsynnottstuartsierra: quite a few C compilers have awful hand-made parsers
12:27DraggorReally it's just a calculator with another operator d and using [] for grouping instead of ()
12:27sproingieisn't g++'s new parser a hand-rolled recdescent parser?
12:28stuartsierrarsynnott: really? ugh
12:32manic12__i don't understand the difference between altering a ref and mutating state
12:34sproingiethey are state
12:34sproingiebut you can only change them in a transaction
12:34manic12__it says that is "identity"
12:34manic12__it doesn't matter if it's transactional
12:35sproingieclojure doesn't lack state completely, it just shoves it into some well-defined areas
12:36manic12__that statement should be put on the clojure.org/state webpage
12:39sproingiethat page gets a little overly focused on identity. refs are essentially first-class slots, just not necessarily "owned" by some structure.
12:39manic12__ok
12:40manic12__but oo is a bad idea?
12:40sproingiehardly
12:41sproingieoo doesn't even necessarily have to throw around uncoordinated mutable state
12:41sproingieit's just that most oo languages have few alternatives to doing so
12:42sproingiejava has some immutable collections in libraries that are pretty efficient, but most people don't use them
12:42sproingieC++ STL is pretty much hopeless
12:43sproingiescala's the only oo language i can think of that has seriously decent functional objects
12:43manic12__I'm looking at the "memoize" example and thinking about declarative oop
12:45arohnermanic12__: in clojure, refs, atoms etc are a way to cleanly declare and isolate when & how state changes happen
12:45manic12__not absolute declarative like prolog though, declarative where it makes sense to do so: storing knowledge
12:45arohneryes, they're all state changes, but clojure has much stricter guarantees about how they happen
12:46sproingieclojure has all the state of any imperative language, but everything stateful in clojure has some kind of synchronization primitive baked into it
12:46sproingierefs are transactional, agents have asynchronicity, and atoms are, well, atomic
12:46sproingieclojure has all kinds of state, it just doesn't have "naked state"
12:46manic12__i haven't determined the difference yet
12:47manic12__that's good
12:47manic12__because it will make it easier to implement undo
12:48sproingieyou could easily write a clojure program in completely imperative style, it's just that clojure steers toward a functional style
12:48sproingieby using immutable collections and so forth
12:49rhickey_a point of Clojure is to separate identity, state and value
12:49manic12__so clojure needs some object systems
12:49rhickey_people throw around the term state without considering its meaning
12:50manic12__i read the clojure.org/state page, and i'm one of those people apparently
12:50sproingiemost people who aren't FP geeks will conflate them somewhat :)
12:51sproingie"pure" fp geeks don't even go in for the concept of "identity"
12:51sproingieinsofar as being distinguishable from value that is
12:51manic12__fp=functional programming?
12:51sproingieyep
12:51milepHello, is there a good/standard way to use structmaps with sorted-set? Or should I create custom compare function and use that with normal set?
12:51dnolensproingle: being the creator of spinoza, I would say don't bother. I haven't touched that project in ages :) it's best to just dive into fp style programming.
12:51rhickey_by being atomic, and pointing to immutable composites, Clojure's reference types ensure transitions from value to value, and you can grab one of those values without getting trounced by future state transitions
12:52rhickey_contrast that with objects that change in your hands
12:52sproingiednolen: aw. i rather liked the idea of first-class protocols.
12:52rhickey_those objects don't have obtainable state at all
12:52dnolensproingie: yes, I think mikel's generic functions project is less half-baked tho.
12:53sproingiednolen: is that the categories thing in explorersguild?
12:53manic12__so if one thread grabs the state from the ref, it won't change on it underneath if another thread grabs it next
12:53dnolensproingie: yes
12:53rhickey_a state is a value at a point in time, being a value it can't change
12:53rhickey_references just manage time
12:54rhickey_objects typically conflate all three and become impossible to reason about
12:54manic12__the most unfortunate thing about my code is that i use a huge c++ library!
12:56manic12__but is my statement correct? about the state not changing from under a function in one thread because it's immutable?
12:57rhickey_manic12__: state of what? values don't have state. If you get a value from a ref you are done with state
12:57manic12__ok, so yes
12:58manic12__the state doesn't change because it's not a state in the first place it's an immutable value
12:59rhickey_manic12__: there is a thing with state (the reference). When you dereference it, you obtain its value at a point in time. That value is an immutable thing and has no state/time at all
12:59manic12__i understand now
13:00rhickey_I don't mean to be pedantic, but I am on a mission to clarify this I guess. So tired of OO muddle...
13:01manic12__the c++ library suffers from exactly this stuff clojure is intended to solve
13:01rhickey_Clojure disassembles OO and delivers it in orthogonal pieces
13:01manic12__that's fine, i get it
13:03manic12__but to do what I have coded in clos will require implementing some constructs i didn't have to before, that's what i was wondering
13:03rhickey_the prize is obtainable values and the fact that you can write pure functions that work with them, completely independent of things relating to state. In most OO values are relegated to primitives
13:03manic12__i should say meta programming in clos
13:04rhickey_manic12__: porting from CLOS will require looking at how it is being used, what's stateful, what's inheritance driven etc. It is a rich polymorphism system for sure
13:04manic12__it uses memoization heavily
13:06manic12__i don't want to introduce uses of 'state' just because that's the way clos does it
13:08manic12__the C++ code often destroys objects you pass into functions and you have to explicitly copy them first if you want to keep it
13:10manic12__so it will be a challenge to make it appear like native code
13:11chouser"Take an old man's word; there's nothing worse than a muddle in all the world. It is easy to face Death and Fate, and the things that sound so dreadful. It is on my muddles that I look back with horror--on the things that I might have avoided." -- http://tinyurl.com/ychwqfp
13:18rhickey_Chouser: love it!
13:18DraggorAnyone tried http://kotka.de/projects/clojure/parser.html ?
13:19chouserrhickey_: I'm not sure he was talking about identity-value conflation, but it'll do.
13:30drewr,(#{false} [true false])
13:30clojurebotnil
13:30drewrshouldn't that be false?
13:31chouser,(#{false} true false)
13:31clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: PersistentHashSet
13:31chouserhm
13:31stuartsierra,(#{false} false)
13:31clojurebotfalse
13:32chouserdrewr: sets return the matching value, else nil.
13:32stuartsierra,(#{:a} :a)
13:32clojurebot:a
13:32stuartsierra,(#{:a} [:a])
13:32clojurebotnil
13:33stuartsierra,(some #{false} [true false])
13:33clojurebotnil
13:33stuartsierra,(some #{:a} [:b :a])
13:33clojurebot:a
13:35drewrchouser: isn't false the matching value though?
13:36chouser#{false} does not contain the vector [true false]
13:36chouser,(#{:foo [true false] :bar} [true false])
13:36clojurebot[true false]
13:42hiredman(#{false} false)
13:42hiredman,(#{false} false)
13:42clojurebotfalse
13:42hiredman,(#{nil} nil)
13:42clojurebotnil
13:42hiredman:(
13:43chouser,(#{'spam} 'spam)
13:43clojurebotspam
14:02drewrchouser: oh, ok; I thought it wanted a coll there
14:02drewrwhich is what stuartsierra was demonstrating :-)
14:04drewrwhich makes sense when the set is callable there
14:09bitbcktAnybody have an easy way of taking an Array of N^2 items and splitting it into an NxN matrix?
14:11ambientx+y*width
14:11chouser,(partition 4 (range 16))
14:11clojurebot((0 1 2 3) (4 5 6 7) (8 9 10 11) (12 13 14 15))
14:11bitbcktchouser: That's what I was looking for. Thanks.
14:16tmountainhas anyone seen this before? http://pleac.sourceforge.net/
14:17tmountainit's a website featuring recipes from the perl cookbook implemented in a variety of programming languages
14:17tmountaingood resource for finding out how to do something quickly in a given language
14:18tmountainI was thinking of starting a clojure module if anyone else is interested
14:19tmountainI contributed the ruby section on directories, and it was pretty fun
14:20sproingiepleac is pretty nifty
14:20sproingiegood way to compare expressiveness
14:20sproingieadding clojure would be awesome
14:21tmountainsweet, I'll contact the project admin and see about getting it added
14:35drewrstuartsierra: your some example was also confusing me
14:36stuartsierrawhich one?
14:36drewr,(some #{:foo} [:foo false true])
14:36clojurebot:foo
14:36drewr,(some #{false} [:foo false true])
14:36clojurebotnil
14:36stuartsierraThat happens because "some" tests the result of applying the predicate to an element in the sequence. "false" tests false!
14:37drewrthat seems like a bug
14:37stuartsierraNot a bug, I think, but certainly an edge case.
14:38stuartsierra,(some #(false? %) [:foo false true])
14:38clojurebottrue
14:38chouseryou just have to be careful dealing with collections that might contain nil or false
14:46drewrkotarak: how's ClojureCheck coming?
14:47kotarakdrewr: uhweuhm oehmm...
14:47kotarakdrewr: falling off the spare time clip at the moment, I'm afraid.
14:48kotarakAlthough I'd really like to work on it.... I have to cut done my projects...
14:49drewrwhat's it lack?
14:49kotarakdrewr: The TAP part is more or less complete, but the QuickCheck clone is a mess. I'd really like to clean that up.
14:51drewrk
14:51kotarak.. and make it work, actually...
14:52drewra coworker started working on his own and didn't know whether to tell him to use yours :-)
14:53kotarakdrewr: -.- I have to win in the lottery, so that I can quit my day job and start working full time on fun projects. )
14:53kotarak:)
14:54drewryep
14:55kotarakthe job cuts away 43h (effectively 48h) per week, with the recently grown family and soon to be bought apartment the prospects are rather depressing from the clojure project point of view. (Although the last two points have higher priority than clojure... :))
14:57drewrplease put your family before clojure :-)
14:58kotarakOf course! :D
14:59kotarakdrewr: but now that you asked, I will probably invest some time to drive CC a bit more. VimClojure ate a lot of time lately, too...
16:08ngocWhy "Logging str" is output 5 times in the example at http://clojure.org/concurrent_programming?
16:10kotarakngoc: What do you expect? Have you had a look at the implementation of str?
16:10arohnerlisppaste8: url
16:10lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
16:11kotarakngoc: http://groups.google.com/group/clojure/browse_frm/thread/9f8b14cd7cdf9f4d/90158571284ac1ef?q=loves+ethel+lucy+group:clojure for details
16:12lisppaste8arohner pasted "get the value of a local at runtime?" at http://paste.lisp.org/display/87966
16:13arohneris there any way to get the value of a local at runtime? and is there any way to implement value-of in a way that doesn't use eval?
16:14hiredmanuh
16:14kotarakarohner: the only way I see is just returning expr from my-fun.
16:14arohneris there a way to edit the paste?
16:14kotarakyou can annotate it
16:14hiredmanthere is no value at runtime
16:14hiredmanerr
16:14hiredmanat compile time
16:15lisppaste8arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#1
16:15hiredmanwhen is when macro expansion happens
16:15hiredmanthere is just a datastructure
16:15kotarakarohner: that's not possible, as hiredman says.
16:16arohnerthe macro turns into code that calls (my-fun 'foo)
16:16arohnermy-fun is run at runtime
16:16arohnerah, the paste is missing a `
16:17kotarakAnd a quote on the expr.
16:17lisppaste8arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#2
16:17kotarakBut here expr gets evaluated.
16:17manic12__i implemented a "destructive" assoc for structmaps which obviously doesn't destroy anything but does allow for undo and redo, you have to pack the structmap in another map and make a ref to it and pretend the ref is the structmap
16:18arohnersorry for the mistakes. I'm trying to create a simplified example. obviously I'm making mistakes in the translation
16:18arohner`(my-fun expr)
16:18hiredmanmanic12__: sounds horrible
16:18manic12__that would have been a pain in CL because you need to copy the objects yourself
16:18lisppaste8kotarak annotated #87966 "quoted expr" at http://paste.lisp.org/display/87966#3
16:19manic12__hiredman: why?
16:19hiredmanmanic12__: because then you are going to have a lot of little "mutable" structmaps
16:20manic12__but you can undo them
16:20arohnerinteresting kotarak. is it possible to do the work in my-fun?
16:20kotarakarohner: which work?
16:20tomojbeing able to undo doesn't make mutable state a good thing :)
16:20hiredmanwhile controled mutation is better than uncontroled, immutability is better still
16:20arohnergetting the value of expr. doing it in the macro rather than the function would make my code a lot more complicated
16:20arohner(or maybe my design is just wrong)
16:21kotarakarohner: well you do the work in the function. The macro just wraps everything up in a thunk, which is (maybe) called in the function to obtain the value.
16:22manic12__i want to be able for the user of the DSL to def to the ref and keep a constant ref to an dynamic object
16:23hiredman:(
16:23manic12__for animation and changing inputs/attributes
16:25Chousukewouldn't a simple ref for the input do?
16:25Chousukeor inputs.
16:26manic12__how do you synchronize the state of the object to acheive the undo/redo?
16:26lisppaste8arohner annotated #87966 "untitled" at http://paste.lisp.org/display/87966#4
16:26Chousukehm.
16:27ChousukeI'm not quite sure what it is that you are doing now
16:27Chousukehow does your scheme allow for undo/redo? :/
16:27wavismanic12__: instead of using a ref, just create and undo function that returns the previous map, which you had originally used assoc on
16:28manic12__and even if the struct map gets really big I don't think clojure's copying of it would slow it down compared to the fact that the object may need to recompute all of it's values
16:28kotarakarohner: that cannot work, you can't eval an expression passed to a function (at least not in general)
16:28manic12__generators?
16:28manic12__wavis
16:28Chousukeno, really, I have no idea what you're thinking
16:28Chousukeyou might have a good idea but I can't make sense of it.
16:29kotarakarohner: besides the macro would need to look like: `(my-fun (quote ~expr)). Your expansion is (my-fun your.name.space/expr).
16:29ngockotarak: Thank you. This is a pitfall for new comers. Since this example is for new comers, I think it should be explained in the example.
16:30manic12__it's like a spreadsheet
16:30manic12__but it's a tree of objects
16:30manic12__(refering to clos implementation)
16:31manic12__inputs and specially declared modifiable attributes can be changed
16:31tmountainmaniac12__: I'd determine if you really need "objects" or if you can use Clojure's native types to represent whatever data you're referring to
16:32manic12__i'm using structmaps from spinoza
16:32Chousukehm
16:32manic12__i'm trying to implement a declarative DSL from clos to clojure
16:33manic12__i haven't used cells very much at all, but it's like cells but lazy eval
16:35manic12__it's not for specially trained computer scientists, it's a DSL for mechanical & civil engineer types
16:35wavis,(defn undoable-assoc [the-map key val] (with-meta (assoc the-map key val) {:undone the-map}))
16:35clojurebotDENIED
16:36manic12__wavis: at some point the user needs handlebars
16:36wavismanic12__: anyway, with that you could (^new-map :undone)
16:36wavishandlebars?
16:36manic12__probably
16:37manic12__there has to be at least one mutable thing in the program, and that is the object which gets displayed in the viewer
16:39Chousukethe object displayed is probably a function of the inputs, which are the mutable stuff :)
16:39wavisassuming I have a clue, you just need to change what the viewer is holding to display. the collections to display can still be immutable
16:39ngocIs there a way to redefine functions? (defn str [& args] 123) will throw error.
16:40wavisso represent the whole display as an immutable structure and swap it
16:40manic12__the inputs are just going to be entries in the struct map and clojure will copy the whole struct map which gives the ability to synchronize an undo/redo
16:40hiredmanngoc: because str is not defined in the namespace you are in
16:40manic12__wavis: you are correct
16:41ngochiredman: How to solve the problem?
16:41manic12__but sometimes it's nice to spawn one at the repl
16:41manic12__if it's not viewing properly or something
16:42kotarakngoc: you don't want to do this!
16:43Chousukengoc: redefining core functions is going to break everything
16:43Chousukengoc: what you might do is temporarily rebind them though.
16:43hiredmanngoc: there are many ways to solve it
16:43ngoc(ns clojure.core) then (defn str [& args] "123") solved the problem
16:44hiredman#$%@#$%
16:44hiredmanthat is not a solution
16:44Chousukeand created a thousand more :)
16:44hiredmanclojure.core/str is part of the core of clojure and depended upon by other functions
16:44hiredmanchanging it breaks all those functions
16:44kotarakPeople sure have funny definitions for "solved" and "problem"...
16:44manic12__mutable is not a dirty word
16:44hiredmanyes, it is
16:45manic12__then get rid of refs, agents and atoms
16:45Chousukecutting off your head solved headache but...
16:45Chousukesolves*
16:45kotarakChousuke: hmmm? Phantom pain?
16:45sproingieit's a dirty word, but sometimes your problem wants you to talk dirty ;)
16:45ngocI want to do alias_method_chain like in Ruby/Rails: http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Module.html#M001219
16:45technomancynoooo!~
16:45sproingieclojure gives you mutability all over the place. it's just managed.
16:46technomancyalias_method_chain is a maintenance nightmare
16:46hiredmanmanic12__: but mutation is needed
16:46hiredmanso you minimize/control it
16:46manic12__exactly
16:46sproingieheck atoms arent even all that managed
16:47ngocI save the original str, redefine it, and call the original function inside the new one
16:47sproingiethat's what let is for
16:47hiredmanthey are managed in the sense that future state is a function of past state
16:47hiredmanngoc: don't
16:47kotarakngoc: and broke the whole system....
16:48kotarakngoc: monkey patching is not a good idea. Don't do it.
16:48ngocBut Rails plugins all work this way, and they do work
16:48hiredmanngoc: when you create a new namespace you have the option of not aliasing bindings from clojure.core
16:48technomancyngoc: no, they break
16:48technomancyall the time
16:49hiredmanso you can leave str out of your namespace and redefine it there
16:49manic12__I have to implement a memoization scheme for rest of that attributes, but it has to be finer grained than copying the whole struct map, it has to memoize each attribute individually but be able to unbind itself when dependent things change
16:49Chousukemanic12__: copies are cheap
16:49Chousukemanic12__: just give the user a reference :P
16:49manic12__but for EVERY attribute call?
16:50hiredmanattribute call?
16:50manic12__message
16:50hiredmanI would not use spinoza
16:50Chousukemanic12__: in which situation would you even copy the struct map entirely? :/
16:50technomancyngoc: rails 3 is removing as many alias_method_chain calls as possible due to this
16:50Chousukemanic12__: I mean, if you assoc to it, that doesn't copy the whole map
16:51ngocIf redefining does not "solve" the problem, is there a way? I want to add feature to an existing function, just like in Rails plugins.
16:51Chousuke(doc binding)
16:51clojurebot"([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before."
16:51kotarakngoc: you want multimethods
16:51sproingie"just like in Rails" often means "doing it completely wrong"
16:52hiredmanI'm pretty sure the original author of spinoza even removed his repo
16:52sproingiemonkeypatching everything onto Object... OOP, You're Doing It Wrong
16:52hiredmanor not
16:53sproingiethere's reasonable use cases for opening up base classes, sure. most of ruby's uses aren't it
16:53manic12__Chousuke: yeah but I should only need to copy the struct map when information "changes" that invalidates dependent attributes
16:53Chousukemanic12__: I still don't see what "copying" happens if the struct map doesn't change
16:54sproingieyou don't need to copy the whole map, you just record a sequence of changes
16:54manic12__clojure copies just about everything you can look at the source code
16:55sproingiewhen you need to get everything into the same state, you can condense the changes to a minimal set then generate exactly one new object from that
16:55hiredmaneh?
16:55Chousukehuh?
16:55hiredmancopies?
16:55Chousukemanic12__: you need to copy *something* to keep the data structures immutable, but it doesn't copy *everything* all the time.
16:55Chousukethat'd be slow
16:55manic12__sproingie: you're right and that's what i do in clos
16:56hiredmanhttp://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/
16:56Chousukehmm, well, that's possible with clojure transients.
16:56manic12__go to IPersistentMap assoc method and show me that it's not copying every value
16:56Chousukemanic12__: it's not.
16:56Chousukeit shares structure.
16:56Chousukewith its "parent" maps
16:56ngocHow to implement something like (defn f (+ (original-f) + 1)) with multimethods or binding? Binding does not work as expected as the example at http://clojure.org/concurrent_programming shows ("Logging str" is output 5 times).
16:56manic12__newVals[i]=val;
16:57hiredmanngoc: it does work as expected
16:57kotarakngoc: bindings works as expected, the output depends on the definition of the original str
16:57hiredmanstr is called internally by println and the love function
16:57Chousukemanic12__: if you have a map with a thousand objects and you assoc to it, Clojure surely does not copy each of those thousand values
16:57sproingielove?
16:57manic12__PersistentStructMap.java
16:58Chousukemanic12__: assoc is O(log_32 n)
16:58hiredmansproingie: if I recall, the example on that page defines a function named love
16:58sproingieah
16:58hiredmanloves, pardon me
16:58sproingiei was digging around in the API looking for it ;)
16:59manic12__ok, Chousuke if you're right than that's even better
16:59tomojChousuke is right
16:59Chousukemanic12__: how many items will your struct maps have, anyway?
16:59stuartsierra~seen jochu
16:59clojurebotno, I have not seen jochu
16:59ngochiredman: I thought str called itself, not by println
16:59manic12__they can have alot, but not enough to make a full copy slow, like 100 to 200 "slots"
17:00sproingielog32 n aka "fast enough for you old man"
17:00kotarakngoc: yes, str calls itself, which is your str (it print logging and then calls the orig-str)
17:00Chousukemanic12__: maybe *struct* maps do copy all of their values (because usually you don't have so many of them). but it's hopefully not going to be too slow
17:00hiredmanngoc: that is possible as well
17:00Chousukemanic12__: after all, every value is just a pointer. copying a hundred pointers is not too expensive :P
17:01manic12__it won't
17:01manic12__no
17:01sproingiei thought structs used a vector underneath
17:01manic12__in the clos version, it would have to actually go through and unbind dependent slots, I'm sure that's slower than just copying it
17:02hiredmanI wonder if there is a point to using structmaps with 200 keys
17:02sproingieoh right struct vs structmap. confoozing
17:02Chousuke... creating instances of them would be painful :)
17:02hiredmanstructmaps are supposed to be a optimized case for small maps with the same keys
17:02manic12__yeah, after a point you would think it would have the offsets in a class object
17:02sproingiehiredman: i could see writing a virtual machine with a slot per bytecode
17:03sproingiebut chances are it'd be a singleton
17:03hiredmansproingie: eh?
17:03sproingieyou know a big table
17:03manic12__i'm using structmaps right now because that's what spinoza uses
17:03sproingienevermind my babbling
17:03hiredmanI wonder at what number of keys a struct map ceases to be an optimization
17:03sproingiemanic12__: the author of spinoza told me not to waste my time with it
17:04hiredmanspinoza :(
17:04Chousukehiredman: probably never, as the keys are shared between structmap instances
17:04manic12__maybe so, but I don't plan on using it like a clos, it's a learning tool
17:05sproingieif it's just to learn, then stop optimizing up front
17:05manic12__real clos does all kinds of optimization tricks for fast generic function dispatch and accessor methods
17:05manic12__who's optimizing?
17:05hiredmanmultimethods!
17:05manic12__i implemented an undo
17:06sproingieyou're fretting about copies of data structures that never actually get copied
17:06ngocHmm, I feel that binding forces the callers to explicitly list all the plugins they wants to use all the time, like (with-feature1 (with-feature2 (with-feature3 str))), this is ugly. How to plug all the plugins only once when the program starts?
17:06sproingiesounds like optimization concerns
17:06tomojngoc: the whole point is that you shouldn't do that :)
17:07hiredmanngoc: I would really recomend you spend more time learning clojure before you begin worrying about writing something that needs a plugin system
17:07sproingiemultifns have the start of a nice generic function dispatch, but building on that is still in roll-your-own territory
17:07Chousukengoc: design a system that allows people to create new functions by combining the plugins with the base functions
17:07manic12__there is no declarative programming paradigm in clojure
17:07sproingielooking at watches, i would argue otherwise
17:07Chousukeie. (def my-cool-function (plugin1 (plugin2 (plugin3 base-function)))))
17:07sproingieit's certainly not declarative like prolog, no
17:08manic12__i'm not saying declarative is the best, but it makes sense for my application
17:08manic12__mechanical engineers are visual people
17:08manic12__spatial
17:09manic12__(they're so spatial)
17:10hiredmanthere are a lot of primitives available that a declarative system can be built upon
17:10manic12__so far I feel like I can't describe anything geometric with clojure because it feels like some kind of strange scheme with an emphasis on immutability
17:10hiredmanpromises,delays,etc
17:10manic12__structmaps and vectors?
17:10ngochireman: I have been studying Clojure for one month, no big progress at all. Do you have any tips on studying Clojure?
17:11hiredmanngoc: write something small first, the sidebar on the clojure.org website has a list of features to try out
17:11manic12__as "dumb" as smalltalk and flavors, or even clos is, you can still describe types of objects and how they are contained
17:12hiredmanmanic12__: erm
17:12sproingieyou do have to think functionally. clos with all its declarative syntax sugar still usually comes down to OO
17:12manic12__um, yeah
17:12hiredmanwe may have different understandings of "declarative programming"
17:12manic12__declarative and object oriented are not mutually exclusive
17:13hiredmanwhat do you mean by declarative?
17:13sproingieyou can get a lot of declarative behavior out of multifns
17:13manic12__car has chassis, chassis has wheels
17:14sproingiestruct, works fine
17:14manic12__you can but you can get a lot of milage of of single object dispatch too!
17:14ngocChousuke: Do you mean I should study macro?
17:15sproingiemultifns have multiple dispatch, they just don't have any kind of MRO for call-next-method to work
17:16manic12__sproingie: i am very familiar with multiple-object dispatch from clos
17:16sproingiemultifns are insanely more powerful than just switching on class. you can destructure an object and switch on some arbitrary function of it
17:16hiredmanmanic12__: that seems to relate to the dictionary definition of Declarative in that you are declaring relationships, but I don't see how it relates to declarative programming
17:16sproingiethat's probably why there's no MRO, how the heck do you determine what the "next" thing is from that
17:17kotarakngoc: consider a simple program, eg. a logfile parser or something overlookable. And start implementing that.
17:17kotarakngoc: get comfortable in Clojure before you start with macros...
17:17manic12__sproingie: that's great, get a bunch of gearheads doing it
17:17sproingiefloating around in my head is the idea of dispatching on a sequence instead of a single value, but i don't know offhand what the code would look like
17:18sproingiemanic12__: make a bunch of macros that look like autolisp, done
17:18sproingienot saying it's a good lisp, just saying that's what they know
17:18manic12__they also know icad
17:18manic12__which is built on flavors
17:19hiredmansproingie: you can dispatch on sequences, just works better with vectors
17:19Chousukesproingie: the dispatch fn would just be (comp vec map your-dispatch-fn) :P
17:19Chousukeer, wait
17:19hiredman↑ yeah, use vectors
17:19Chousuke(partial map dfn)
17:19sproingiehiredman: yeah a vector would probably be more efficient, i'm thinking the sequence could be lazy though.
17:20sproingiegiven arguments foo, bar, baz, generate a MRO. now given foo, bar, baz, a MRO, and a current position, find the next method
17:20hiredmansproingie: the isa stuff is all built to work on vectors already
17:20hiredman(isa? [Object Object] [String Character])
17:20hiredman,(isa? [Object Object] [String Character])
17:20clojurebotfalse
17:20hiredmanbah
17:20manic12__it's great that clojure has all of these great features with multifns & metadata, but if simple people have a hard time doing simple programming, well I'm sure you would say they need to re-learn
17:21hiredman,(isa? [String String] [Object Object])
17:21clojurebottrue
17:21sproingieit ain't logo yet
17:21manic12__I'm trying to apply a simple object system paradigm from flavors and clos to clojure
17:21sproingiei'd rather the bike gets built before the training wheels
17:22sproingieclos is anything but simple
17:23hiredman(defmulti new (fn [& args] (vec (conj (map class (rest args)) (first args)))))
17:24hiredman(defmethod new [:box String Integer] [_ name size] {:name name :size size})
17:24manic12__yeah, well clos can be simplified with some meta programming and macros
17:24hiredmanof course you couldn't call it new
17:25hiredmanit would have to be my-new
17:25manic12__make-instance?
17:25hiredmanand you'd want to map type not class
17:26hiredmanand you'd want to add :box as the :tag metadata to the resulting {}
17:26manic12__you know why java is popular...it creates a framework where programmers don't have to think as hard
17:26hiredmanthat is a lie
17:26sproingie*snort*
17:26manic12__icad is the same way
17:27hiredmanwell, they don't think they have to think
17:27hiredmanso they write crap
17:27sproingiei have to think all the time, long and hard, about how to get around the limitations in the language
17:27manic12__and i hit a limitation in clos, that's why I'm here
17:27sproingieusually i can find a nice library that helps out. which is great til i want to make it work with another library that solved another problem
17:28manic12__i would like to create a dead-simple geometric library for the icad style declarative/generative/object-oriented programming
17:29sproingieyou may be the only one familiar with it. pastebin an example of what it looks like?
17:30manic12__sometimes i think computer scientists have lost touch with the problems the science was created to solve
17:31kotarak"Computers help us to solve problems we wouldn't have without them."
17:31hiredman~clojure
17:31clojurebotclojure is a very attractive hammer with a nice heft to it
17:33manic12__if you have used parametric cad to design physical objects such as machine parts, it shows that things have progressed, but at the same time the software designers lock out the user from being able to really write flexible applications
17:34manic12__that's why I became a programmer
17:35sproingiecomputer scientists have never particularly been in touch with the real world. that's not their job.
17:35sproingieengineers create stuff, scientists figure out new principles to create stuff on.
17:36sproingietheory, meet practice. practice, theo-- hey theory, stop wandering off, pay attention.
17:37hiredmanmanic12__: I think you might want to get a blog
17:39manic12__i don't think anyone would read my blog
17:41hiredmanI dunno, you could grab the mic and inspire the masses to rise as one and throw off the shackles of the computer science intelligentsia
17:41sproingieyou have nothing to lose but your boot times!
17:41manic12__i think i should be an arborist
17:42drhodesthere's a race of men who live in the trees
17:43manic12__tarzan of the kbe trees here
17:45manic12__i am going to have to get this thing to do a deep copy
17:46manic12__if it finds a "pointer" to a struct map as a value of an entry, it needs to copy that whole thing too, not just the pointer
17:46hiredmanmanic12__: :(
17:46hiredmanthat is horrible
17:48manic12__the structmaps don't need to contain keys for every message, just the ones that are "changeable" (I hate these "")
17:50hiredmanstill sounds horrible
17:52Chousukewhy does it need a deep copy?
17:53ChousukeI mean, maps nest just fine. :/
17:53manic12__alibre design is written i java, i should just get a license to that and run clojure as a scripting language and be done
17:54manic12__because if you don't deep copy, you when you undo or redo you will get state that belongs to something else
17:54manic12__it's a very thin skeleton
17:54Chousukeoh, so the pointer is a ref then?
17:55manic12__no, by "pointer" i mean (identical? val1 val2)
17:55Chousukebut that's not true
17:55Chousukeor, at least I think it isn't.
17:58sproingienot that i don't love clojure, but if you have a clos thing you want to port to java, perhaps you should consider ABCL?
17:58sproingieor one of the many scheme implementations where there's a tinyclos port
17:58Chousuke,(let [a {:a {:deep :map}} b {:b 1} ] [(assoc b :foo (:a a)) b a])
17:58clojurebot[{:foo {:deep :map}, :b 1} {:b 1} {:a {:deep :map}}]
18:00Chousukethe :foo value and :a value are identical, but there is no connection between the "parent" maps
18:02Chousukemanic12__: is that what you're worried about, or something else? :/
18:03Chousukemanic12__: the submaps can freely be the same object, because it's not like anything can change them :)
18:23spuzHello, I've having a really straing problem accessing external files from clojure
18:23spuzfirst of all, I cannot load any files using load-file
18:25hiredmanhave you read the load-file docs?
18:25spuzalso, I cannot seem to 'see' files on my hard disk. Running (.exists (java.io.File. "C:/pe5.clj")) returns false even though that file exists
18:26spuzhiredman: yes, I can use relative or absolute paths apparently, but neither seem to work
18:26hiredmanhave you tried "C:\pe5.clj"
18:26spuzyes
18:27spuzat least "C:\\pe5.clj"
18:27manic12__Chousuke: those sub objects may be immutable, but if they are the wrong ones then that is a problem
18:27spuzhowever "C:/Windows" returns true
18:27spuzit's very strange
18:28hiredmanspuz: does the pe5.clj file exist?
18:28spuzhiredman: yes!
18:28Chousukemanic12__: how would they be wrong?
18:29spuzI've tried putting it in the current dir and using "pe5.clj" as well
18:29hiredmanspuz: what does dir c:\pe5.clj say?
18:29Chousukemanic12__: or is there some situation where the deep copy actually "changes" some of the inner map? :/
18:29spuzhiredman: hmm file not found!
18:30hiredmanso it doesn't exist
18:30hiredmanproblem solved
18:30spuzhiredman: uh well, not exactly, typing that path into explorer finds the file, but clearly it's not a clojure problem
18:32spuzhiredman: ah, how annoying, I have extensions turned off on this machine and the file was actually called "pe5.clj.txt"!
18:32spuzyes I'm a retard
18:34sproingieblame notepad
18:35akhudekWhile playing around building a small svg-like vector library using Java2d, I ran into an interesting problem dealing with mutable trees.
18:35akhudekI decided to represent a scene graph as nested vectors inside a ref.
18:35hiredmannotepad++
18:36akhudekSince the scene graph is a shared mutable resource that theoretically multiple threads may modify.
18:36hiredmanI actually did a few euler problems in notepad++
18:36akhudekNow, a common operation may be to frequently change one specific node in the graph.
18:36akhudekSay for a text label during an animation.
18:37hiredmanhave you seen zippers?
18:37akhudekyes, but you can't have multiple cusors
18:37akhudekA simple animation would likely change a label node in one place, and say another object somewhere else.
18:37akhudekTraversing the tree between both positions each frame seems ineffecient.
18:38hiredman(require '[clojure.zip :as zip])
18:38hiredman,(require '[clojure.zip :as zip])
18:38clojurebotnil
18:39akhudekThe only decent solution seems to be to put frequently mutated nodes into references.
18:39akhudekAnd have the rendering code automatically deref any references it encounters.
18:40hiredman:(
18:40hiredmanwhy do you want multiple cursors?
18:40hiredmanhow deeply nested are the vectors?
18:41akhudekSo that you can refer to more than one object in the scene.
18:41hiredmaneh?
18:41hiredman,(-> '[:a [:b :c]] zip/vector-zip zip/next zip/next zip/next (zip/replace :x) zip/next (zip/replace :y) zip/root)
18:41clojurebot[:a [:x :y]]
18:41akhudekRight, but in a graphics context where you modify more than one node each frame.
18:42akhudekYou'd need to move between all nodes you need to change
18:42hiredmanthat modifies two nodes
18:43akhudekmy complaint is that having to move between the two nodes may be a lot of work
18:43sproingiecould collect a list of changes and sort it
18:43sproingiesort of like elevator queueing
18:43hiredmanyou could use something besides vectors
18:43sproingiethat too
18:44akhudeksuch as?
18:44hiredmanyou could flatten nest vectors by wrapping them into a map
18:44akhudekand have nested maps?
18:44sproingieyou normally have to sort scenegraph updates anyway
18:44hiredman{[0 1] :x [0 0] :a} => [[:a :x]]
18:44hiredmanno, just one map
18:45akhudekhmm, maybe the problem is in my representation of the graph then
18:45hiredman{[0 1] :x [0 0] :a [1] :p} => [[:a :x] :p]
18:46akhudekI was translating svg elements into vectors like [:group :width 10 :height 10 [:rect :x 1 :y 1] [:rect :x 20 :y 20]]
18:46akhudekmy idea was to render these during paint
18:47akhudekby traversing the tree and carrying the state as needed by the svg rendering model
18:47hiredmanakhudek: have you looked at how clojure.xml/parse represents xml?
18:47akhudekI should probably do that.
18:47akhudekIt doesn't use zippers?
18:48hiredmanno, it uses a structmap, but you can traverse it via zippers
18:48akhudekok, I'll take a look, thanks
18:49hiredmanI am rather taken with {[0 1] :x [0 0] :a [1] :p} => [[:a :x] :p] myself
18:59danlarkin,(+ nil 1)
18:59clojurebotjava.lang.NullPointerException
18:59danlarkinsuggestions other than try/catch?
18:59hiredman,(or nil 0)
18:59clojurebot0
19:00hiredman,(-?> nil (partial + 1))
19:00clojurebotnil
19:00hiredman,(when nil (+ nil 1))
19:00clojurebotnil
19:01akhudekah, my current code is actually nearly the same as clojure.xml in terms of representation
19:01danlarkinI think the first suggestion is best so far
19:01akhudekI simplified to nested vectors here, but really I use structs where a content field contains a vector of structs
19:02akhudekit's great for reading the data, but not so great for rapidly changing several deeply nested nodes
19:03akhudekhiredman: you're representation is interseting
19:04hiredman"I find your representation intriguing, and I would like to subscribe to your newsletter"
19:05Chousukedanlarkin: the maybe monad :P
19:05danlarkinChousuke: oh jeez!
19:06Chousukehey, monads are sometimes actually useful :)
19:06Chousukenot just for pretending IO is mathematically pure.
19:19akhudekhmm, your rep. with using a sorted map with an appropriate sort function defining dfs order would work. I'll work with that for now, thanks. :)
20:52bpattisonis there anyway in clojure to create/define a hash value through a macro? something like (defmacro m [a] `(func :~a)) ?
20:55arohnerbpattison: can you give an example of how you want it to work?
20:56arohnermacros transform s-exprs, so it's much easier to figure out what you want if you know the start and end points
20:56arohner:-)
20:57bpattisonhere's the macro I'm trying to get working
20:57bpattison(defmacro def-keyword [word]
20:57bpattison `(def k-~word
20:57bpattison (constant-semantics
20:57bpattison (lit-conc-seq "~word" nb-char-lit)
20:57bpattison (make-node-keyword :~word))))
20:57bpattisonsorry about all the newlines
20:58Makoryubpattison: http://gist.github.com
20:58Makoryu:p
20:59arohnerright, but you haven't explained where you're starting and where you're ending up, and I have to guess at what this code is supposed to do
20:59arohnergive me an example of working code without the macro, and what you want the result of the macro to be
20:59bpattisonhttp://gist.github.com/198618
21:01bpattisonokay, I want it to create a def named "k-~word" that makes use of a hash named ":~word" so the macro would produce "k-new" with hash value ":new" when the macro is invoked with word=new
21:02bpattisonand so :new would used in other parts of the code
21:03arohnerso calling (m {:word "new"}) would call (def k-new) ?
21:04arohneror (m {:word :new}) would call (def k-word :new) ?
21:06bpattisonhmm, its more like creating a short-cut for a larger expression and naming it k-new where that larger expressions uses a hash key of :new as well
21:08bpattison(def-keyword new) would produce (def k-new .... :new ...)
21:10bpattisonbut I get a syntax error on :~word in the macro
21:19arohner:word is a literal
21:20arohnerif you want the keyword-ized version of an argument, use (keyword word)
21:20arohnerwhere word is a symbol or a string
21:20arohnersorry, only a string
21:20arohneri.e.
21:20arohner,(keyword "foo")
21:20clojurebot:foo
21:20hiredman,(keyword (name 'foo))
21:20clojurebot:foo
21:28bpattisonarohner: excellent! thanks
21:46Makoryu, (+ 1 "food")
21:46clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
22:01kevin__, (+ 1 2 3) ; curious
22:01clojurebot6
22:02kevin__nice, i can write a distributed computing app
22:23hiredman~suddenly
22:23clojurebotCLABANGO!