#clojure logs

2010-10-12

00:01amalloyjkkramer: so the idea is to avoid creating a new future for every task?
00:03kmcis there a preferred pastebin here?
00:04ohpauleezjkkramer: kmc That gist is nearly identical to the code the source of pmap
00:04jkkrameramalloy: in that example, the idea is to create an optimal number of futures given a certain number of processors
00:05amalloykmc: gist.github.com is nice, but we can live with anything
00:05ohpauleez~source pmap
00:06amalloykmc: and if you're using emacs (you sounded like a lisper), there's a plugin to automatically create gists from emacs
00:07kmcso pmap is already chunking by the number of processors?
00:07ohpauleezkmc: yes
00:07ohpauleezyou only need to junk if you abuse agents or you need to manually do the futures
00:08ohpauleezotherwise pmap does 2 + num of processors
00:08kmcok, so now i'm back to wondering why it's slower than map
00:08kmcif it's only making 4 futures
00:08kmc(i implemented my own batching, no change in runtime)
00:08ohpauleezthe cost of starting threads, even pulling them from the pool
00:08jkkramerpmap doesn't create batches
00:08ohpauleezcan be higher than the actual computation
00:09jkkrameras i understand it, pmap starts a future for each item in the collection
00:09hiredmanohpauleez: pmap does not chunk
00:09jkkramerbut only processes them n (# of processors) at a time
00:09hiredmanpmap tries to stay N ahead of the consumer of the pmap
00:09kmcah
00:10hiredmanbut if you consume it eagerly
00:10ohpauleezah, ok
00:10hiredmanit will force the whole thing
00:11kmci just want to compute these 60,000 function applications in parallel on a few threads
00:11kmci'm fine waiting for that to finish before moving on
00:12kmci don't need laziness
00:12jkkramerpartition it into batches of whatever-size, then send those pieces to pmap or futures
00:12kmci did that and it was still slower than map
00:12kmc(for 3 batches)
00:13jkkramercode?
00:13clojurebothttp://homepages.inf.ed.ac.uk/kwxm/JVM/codeByNo.html
00:13kmci don't need some runtime option to enable threading, do i?
00:13ohpauleezkmc: How many cores is it running on?
00:13ohpauleez(do you have)
00:13mabeskmc: what do you mean enable threading? pmap uses a thread pool already
00:14kmci have 2 cores
00:14ohpauleezhmm, you should see some difference
00:14jkkramerkmc: can you share the code?
00:14kmcyeah, sec
00:14ohpauleezcool, thanks
00:15kmchttp://gist.github.com/621651 is my batching
00:16jkkramerit's worth noting that upcoming work leveraging fork/join may make this kind of thing easier
00:16kmcthat's cool
00:16hiredmanhow are you timing this?
00:16kmcwith /usr/bin/time -v
00:17amalloyi'd like to join in on this discussion as one of the clueless
00:17hiredmankmc: use the time macro
00:17amalloy,(time (dotimes [_ 100000] 10))
00:17clojurebot"Elapsed time: 15.95 msecs"
00:17TeXnomancyclojurebot: clojurebot?
00:17clojurebotclojurebot is not a benchmarking platform
00:17TeXnomancy=)
00:18hiredmanI think you'll find pmap is faster, the jvm just hangs around waiting for the threadpools to die
00:18amalloydamn, TeXnomancy, you're on the ball today
00:18kmcah, weird
00:18hiredmanyou can call shutdown-agents to end the threadpools manually
00:20amalloyi'm performing some computations on a tree with smallish branching factor. i had assumed it would be faster to just make the recursive call use pmap; am i right in thinking that this discussion means i'd be better off calling pmap on the first N (for some N) levels, but doing the deeper levels with plain map?
00:20hiredmanbench and see
00:22amalloyhm. currently my toy/test data is too small to bench, and it's not fast enough to do real data yet. i guess i have to write a function to generate specifically-sized data
00:24kmcamalloy, i know that's a common technique in Haskell
00:24kmc(parallelize first N levels)
00:25amalloythanks kmc. i benchmarked pmap-only way at the beginning; it was slower, so i gave up and went back to map. glad i heard this discussion; i'm sure i can utilize pmap now, if i do it right
00:28kmcshutdown-agents helped
00:28kmcnow the version with a batched pmap is only a few sec slower
00:35kmci can share the whole program, if anyone's interested
00:36kmci'd also be thankful for any general suggestions regarding style, libraries to use, etc.
00:40ohpauleezkmc, you might want to take a look at work: http://github.com/clj-sys/work
00:40ohpauleezI have a similar, lighter-weight and naive project called tee
00:40ohpauleeznot sure what the scope of your project is
00:41kmcohpauleez, looks cool
00:42kmchmm, this is distributed too?
00:42kmcthat's quite nice
00:42amalloykmc: i don't have anything better to do than nitpick other people's code :) why don't you share it?
00:42kmccan you serialize closures in clojure?
00:42kmcamalloy, http://gist.github.com/621663
00:42kmcthis prints a mandelbrot set on stdout in text PGM format
00:43TeXnomancykmc: sorta; see http://github.com/Seajure/serializable-fn
00:43TeXnomancyobviously if you close over a non-serializable object it won't work
00:43kmccool
00:44hiredmanmmm
00:44hiredmannon-printable
00:44kmcis it recommended to use any particular jvm parameters? i note that the 'work' library ohpauleez mentioned suggests '-server'
00:45kmcmy code for pmap-batched and -main has some doall which i think are unnecessary
00:45kmci was testing to see if my performance problems were laziness-related
00:45pmooserI have a question ... is there any particular reason that clojure doesn't have any bitwise function corresponding to java's >>> operator (right logical shift) ? Does anyone know ?
00:45ohpauleezI use -server for everything when I'm not doing repl stuff. Server will be a slower startup, but possibly better runtime performance
00:46ohpauleezpmooser: They exist, I think it's called bit-shift-left
00:46ohpauleezand bit-shift-right
00:46pmooserThose are arithmetic shifts, if I'm not mistaken, rather than logical shifts.
00:46kmcok, pmap is still slower even with -server
00:47amalloykmc: (inc n) is more usual than (+ 1 n); you can use (println x) instead of (print x "\n"); you don't need to put spaces between the arguments to print. but mostly it looks quite nice
00:47pmooserThe right logical shift (>>>) does a right shift with no sign extension ... ie, it fills from the left with 0's, rather than the normal rule of "fill from the left with 0 if leftmost bit 0, otherwise fill with 1" ...
00:47kmcthanks
00:47pmooserSince it's a fundamental java operator, I was hoping clojure would have some direct analog
00:48pmooserand since JVM languages have no concept of unsigned primitives, it's pretty convenient when doing certain kinds of bitwise manipulations.
00:48amalloypmooser: i remember reading something on the google group about someone wanting to add this feature to core
00:49amalloypmooser: http://tinyurl.com/24lzxgc
00:49pmooseramalloy: Ahh, thanks. Reading.
00:50pmooseramalloy: Ah, OK. So I'm guessing that guy isn't a contributor (hasn't signed a CA) and he also called the function in his patch >>>, whereas I'm guessing in clojure it should probably be called something more like bit-shift-logical-right ...
00:51pmooserIn any case, thanks for the pointer ... Maybe it is just missing due to an oversight.
00:51amalloyheh, i dunno. from me, you get that link. for more details, consult google :)
00:51pmooserWhat's the procedure for filing an enhancement request ticket for clojure? Does such a concept exist?
00:52TeXnomancypmooser: you need to discuss it on the mailing list before opening a ticket
00:52amalloypmooser: i don't know. you could try http://groups.google.com/group/clojure-dev
00:52TeXnomancythen you wait. =\
00:53pmooserTeXnomancy: When you say the list, you mean the standard user list, as opposed to the developer list ?
00:54kmcpmap-batched is still slower. 'time' shows a lot of extra time spent in the OS, presumably waiting on locks?
00:54TeXnomancya post to the dev list theoretically has a lower chance of being ignored, but I guess you need to request membership to it first or something.
00:54pmooserThanks for the pointers. Maybe I'll send in a CA and then apply to that group.
00:54kmcin fact that accounts for about half of the difference in runtime
00:56kmcmaybe i should give up on the pmap idea and have explicit threads write to a mutable array
00:57amalloykmc: transients, maybe, as a compromise?
01:02kmci dunno
01:02kmcthis is my first clojure program
01:02kmcmaybe i should accept that parallel pure computation is not a beginner topic
01:02amalloyhaha
01:02amalloyyou and me both
01:02kmci was hoping i'd found a language where it is
01:04pmooserkmc, what is the computation you're performing?
01:04kmciterating «z ← z² + c» until |z| > 2, or to a maximum number of iterations
01:05kmcfor computing a mandelbrot set
01:05kmchttp://gist.github.com/621663
01:07amalloykmc: you might also consider creating a github account. i know you've got a lot to absorb already with clojure, so don't rush to do it; git takes some time to get the hang of, but it's worth it (as someone who is still using only a small subset of its features)
01:07kmci've used git quite a bit, though not github
01:07amalloyah
01:09jkkramerkmc: http://gist.github.com/621688
01:09jkkramerpmap-batched needed a doall
01:10pmooserI'm squinting as well.
01:10kmclooks like the same pmap-batched i have at http://gist.github.com/621663
01:10pmooserDon't both bits of code have the same doall?
01:11jkkrameroh, so it does. didn't see that one. the original one didn't
01:11kmcyeah
01:12kmcthe two performed the same on my mandelbrot program
01:12jkkramerthat's odd
01:12kmci'm not surprised it works on some functions though
01:12kmcis there any way i could be introducing locking / thread contention?
01:13kmci think my code is a pretty straightforward pure-functional mandelbrot, but i'm not familiar with clojure idioms and idiosyncrasies
01:16pmooserIs there a way to set things up so that lein will compile that code (from the mandel example) AOT,
01:17pmooserwithout me directly doing some kind of "java -cp clojure.jar clojure.lang.Compile mandel" sort of thing?
01:18TeXnomancypmooser: set :aot [mandel.core] in project.clj and do lein compile
01:18pmooserThank you TeXnomancy. I use lein in very simple-minded ways.
01:19kmcon a side note, i am really enjoying vim's rainbow parentheses for Clojure
01:19kmcmakes my code look so much happier
01:20pmooserInterestingly, when I try to do that AOT compilation, I get this error upon invoking lein compile:
01:20pmooserException in thread "main" java.lang.ClassNotFoundException: clojure.contrib.math (core.clj:3)
01:20kmcyou probably need a dep. on that package?
01:20kmchttp://gist.github.com/621696 project.clj
01:20pmooserHmm, I would have thought this would cover that:
01:20pmooser [org.clojure/clojure-contrib "1.2.0"]]
01:20kmcyeah that's what i have
01:20pmooserSorry, that is a :dependencies entry.
01:23pmooserI think this is my fault (predictably). I think I know what I did.
01:24TeXnomancypmooser: try the leiningen tutorial, it's pretty short and covers most of this
01:25pmooserSorry, it's my fault - I flubbed the namespace declaration in a way that made it fail but not itself generate an error.
01:25pmooserTeXnomancy, thanks for the tutorial pointer - I'll definitely read it again.
01:26TeXnomancysure
01:27TeXnomancyand make a noise if there's something missing too; I want to make sure it covers all the bases for getting started.
01:30pmooserI have started using lein for some spare-time projects, but when I use clojure at work, I can't use lein because we have a monolithic build system of our own. So, unfortunately I haven't dug into it quite enough for me to have much facility with it yet.
01:41jameslHi, is there any function - e.g andf (andf f1 f2 f3 … fn x) will do something like (and (f1 x) (f2 x) (f3 x) … (fn x)).
01:41jameslThanks.
01:42jkkramerkmc: replacing math/expt with Math/pow makes pmap behave as expected. i'm not sure if that messes up the numerical accuracy
01:42rich_holygoatjamesl: look at reduce and apply
01:43kmcoh, very strange
01:43jkkrameryeah
01:43kmcany idea why that matters, jkkramer?
01:44jkkramerkmc: no idea, just tried swapping out pieces until pmap-batched worked as expected
01:44jkkramerkmc: what version of clojure are you using?
01:45kmc1.2.0
01:45jameslrich, Thanks. I think about reduce, apply or partial. But ..:>
01:47rich_holygoat(reduce #
01:47rich_holygoatbah
01:47raek(every? #(% x) fns) ; maybe something like this
01:47rich_holygoat(reduce #(and %1 %2) (map #(apply % x) [f1 f2 f3]))
01:48rich_holygoatevery? should work too
01:49jameslThanks.
02:03yayitsweiwhat's a simple and quick way to persist data structures in clojure?
02:04jacortinaslike a database?
02:05yayitsweiyes, or even a file if that's simpler
02:05yayitsweijust need to be able to (save data) and (load data)
02:06jkkramer(spit filename (pr-str data)) (read-string (slurp filename)) might work
02:08yayitsweijkkramer: thanks, trying that now
02:09jkkramerthat should work with most of the basic data structures
02:14pmooserThanks for the help, everyone. Beditme!
02:14pmooserGoodnight.
02:15yayitsweijkkramer: that works, thanks! just needed a quick and dirty way to persist stuff while prototyping my webapp
02:16LauJensenGood morning all
02:17notsonerdysunnyGood Morning LauJensen
02:22kryftGood morning, LauJensen. Any luck installing xmonad yet?
02:23lpetitGood morning all
02:25LauJensenkryft: Havent tried yet - Im feeling a little married to my awesome config
02:28amalloyspeaking of which, i haven't found a description of monads that "speaks to me" - i don't really grok what they are
02:28amalloyanyone have a favorite tutorial?
02:29KirinDaveYou just have to slog through
02:29KirinDaveThey're actually just a specification for functions to allow meta-functions to operate on them.
02:29coldheadmmm gonads
02:30KirinDaveIt's really more of a notational thing than complex implementation details.
02:31amalloyKirinDave: yeah, i grasped that it was "simple", but it was a high-level thing i *almost* followed :)
02:35cpfrhey, what's the best way to execute a compiled clojure project
02:36yayitsweicpfr: java -jar project.jar
02:36cpfryayitswei, will this automatically call the -main function?
02:36yayitsweiyes I believe so
02:36cpfrFailed to load Main-Class manifest attribute from
02:38yayitsweihmm. the jar file isn't compiled to be executed as an application
02:38yayitsweiI think you will have more options with clojure.contrib.command-line
02:39amalloycpfr: you have to set the main-class attribute (or something similarly-named) in project.clj
02:39amalloyand then lein jar or cake jar should put in the manifest for you
02:40cpframalloy, how do I set the main-class attribute?
02:40LauJensenamalloy: The Wiki page seems good. Monads are a way of controlling state and wrapping side-effects, ie. not useful in Clojure
02:40amalloycpfr: i'm not sure; it should be in the leiningen tutorial though
02:40yayitsweicpfr: in my project.clj, i have :main project.core
02:40yayitsweithat works in lein
02:40cpfrah ok
02:40cpfrthanks!
02:41LauJensencpfr: also works in cake
02:41notsonerdysunnyhttp://gist.github.com/621773
02:41cpfrcake?
02:41clojurebotcheesecake is delicious.
02:41yayitsweicpfr: http://github.com/ninjudd/cake
02:42KirinDaveLauJensen: The state monad is not a bad way to model some things, even in clojure.
02:42notsonerdysunnyHello everybody, I want to do some symbolic math using mathematica as the back-end-symbolic engine.. I have trouble converting a sexp returned from mathematica evaluation into a function via a macro .. however a small piece of it is pasted in the above paste .. can anybody help me fix this...
02:43LauJensenKirinDave: Can you give a convincing example?
02:43KirinDaveLauJensen: There was a neat example for compojure awhile back.
02:44cpfrwow cake is like leningen on steroids
02:44LauJensennotsonerdysunny: Im not sure what you're trying to do. Are you looking to inject the values of x and y into the evaluation ?
02:44LauJensencpfr: true.. :)
02:44KirinDavecpfr: No, it's just lein. With some stuff to help textmate achieve parity with slime.
02:45kmcLauJensen, amalloy, no, monads are not about state / side effects in general
02:45kmcF# has syntactic support for monads despite also allowing unrestricted side effects
02:45kmcand C#'s LINQ is quite close to monad comprehensions
02:46KirinDaveC#'s linq. :\
02:46kmcultimately "monad" is just the name of a small, very general API which is used by lots of stuff
02:46LauJensenkmc: Author of Haskell says "The primary uses of monads in functional programming are to express input/output (I/O) operations and changes in state without using language features that introduce side effects"
02:46kmcLauJensen, well that's weaker than what you said — "primary"
02:46kmcbut also i disagree with that statement
02:47kmceven if it was uttered by Simon Peyton-Jones or Elvis Presley
02:47notsonerdysunnyLauJensen: third expression is just a combination of the first and second .. I want the third one to work
02:47LauJensenI think if you disagree with Simon L Peyton Jones, you're likely wrong
02:47notsonerdysunnyLauJensen: return the value I got in the second evaluation
02:47kmccommon uses of monads in Haskell include IO, state, error handling, concurrency, parsing, code generators, logging, etc.
02:48LauJensennotsonerdysunny: Im guessing Variables is a macro that only accepts literals
02:48kmcanyway you can pop over to #haskell if you want some other people to tell you monads aren't just about state and IO
02:48kmcin fact the IO monad in Haskell is a weird, atypical monad -- not good for building intuition about what monads in general are
02:49kmcamalloy, http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
02:49amalloykmc: thanks. i'll check it out
02:49notsonerdysunnyActually math is a macro that calls the function corresponding to Variables in mathematica and returns the value
02:49notsonerdysunnyLauJensen: *
02:50notsonerdysunnyLauJensen: all this is happening via the Java Link that mathematica provides
02:51notsonerdysunnyI am using Clojuratica which brings the Java Link to clojure with additional syntactic sugar
02:52raekyayitswei: you might find this interesting: http://gist.github.com/606840
02:52ohpauleezkmc, can you better shape my personal definition of a monad, which I typically think of a way to do orderly functional combination with a contextual closure
02:52raekyayitswei: usage: (file-stored ref "path/to/file.clj")
02:52KirinDaveohpauleez: I don't think monads necessarily imply a shared closure
02:52cpfryayitswei, I am getting java.lang.ClassNotFoundException: clj_termine.core
02:53yayitsweicpfr: what command are you using?
02:53cpfr java -jar clj-termine-1.0.0-SNAPSHOT.jar
02:53yayitsweiraek: interesting. have you used this before?
02:53KirinDaveOh hell yes.
02:54KirinDaveOh _hell_ yes.
02:54KirinDavehttps://gist.github.com/3085f7636f6be32b2ef4
02:54cpfrgenerated by lein deps; lein compile; lein jar
02:54KirinDaveBrowser to jetty.
02:54KirinDaveOr rather, browser to ring to jetty
02:54ohpauleezKirinDave: m-result isn't a shared closure?
02:54ohpauleezisn't that the idea of monads, at their core?
02:55KirinDaveI dont think it has to be?
02:55yayitsweicpfr: did you compile to uberjar? lein uberjar
02:55ohpauleezahh ok
02:55cpfryayitswei, i did not
02:56cpfris there a way that doesn't entail making an uberjar
02:57yayitsweisomeone else might have a better suggestion, but I think you have to set the classpath in your java -jar command if you don't have an uberjar
02:58raekyayitswei: actually, I made that when I was developing a web app too. I needed a quick and simple way to persist the state
02:58raekalso, when giving jav the -jar option, the -cp option is ignored...
02:59raek*java
02:59yayitsweiraek: nice. did you run into any performance issues?
02:59cpfryayitswei, like java -cp .:classes -jar clj-termine-1.0.0-SNAPSHOT.jar?
02:59raekyayitswei: I haven't used it for serious things yet...
02:59raekI will write something with agents that store the data every now and then
03:00raekwhen a ref gets altered, an agent gets sent a fn that adds the ref to a "to-save" set
03:01raekthe agent sleeps for some minutes, then processes any changed refs and goes back to sleeping
03:01raekthis is just some idea I had
03:02KirinDaveWhy use agents for that?
03:02yayitsweiraek: similarly for me, I assume I'll add a database and learn JDBC when my app grows to need it
03:02raekI don't want the code that alters stuff to block
03:02raekbut a BlockingQueue might make sense too
03:02KirinDaveOkay.
03:02yayitsweialthough, does that mean the data has to fit in memory in its entirety?
03:02raekyes
03:03KirinDaveAgent semantics are more than just non-blocking.
03:03raekI'm aware of that. this use case is probably very close to the border of agent-abusing
03:04raekI'm not sure of which side of that border it is on... :-)
03:05yayitsweicpfr: sorry, I don't know the classpath syntax off the top of my head. what's the reason you can't build the uberjar? i'd try that first to see if it works
03:05KirinDaveraek: Would future work?
03:05cpfryayitswei, I can and it did work
03:05cpfrI just like lean deployments
03:05kmcohpauleez, each individual monad is a type. we could call values of that type "actions".
03:05yayitsweiah
03:06kmcso "IO actions" are recipes for doing IO, "parse actions" are parsers; "nondeterminism actions" are (lazily-deferred) lists of "possible results", etc.
03:06kmcnote that the values making up monadic type A don't look anything like the values making up monad type B
03:06ohpauleezright right
03:06kmcthey just share a common generic API
03:06ohpauleezlike the sequence monad, etc
03:06raekKirinDave: I don't want to save the state each time it gets updated. I want something more like "sleep for 5 mins and check if anything has changed. in that case, store it"
03:07kmcthe reason the IO type is special in Haskell has nothing to do with monads
03:07ohpauleeztotally, I agree with that
03:07kmcand monads are useful in general even if you don't use them to do IO
03:07kmcok
03:07ohpauleezI also agree with that
03:07kmcso this generic API provides something that looks a little like function application or function composition
03:08raekI think an agent holding a set of refs would solve this pretty neatly
03:08kmcyou can formalize that by talking about the "Kleisli category of M" for some monad M
03:08ohpauleezI really want to use them more, I just think I have to force myself to do so
03:08kmcwell, monads aren't really a language feature, but most languages don't have the right set of features to make them convenient
03:08ohpauleezright, I know most of this from the various tutorials I've read
03:08kmcone application i could see in clojure is
03:08kmcif you had to chain a bunch of actions, each of which can return nil
03:09kmcand you want to stop as soon as you hit nil
03:09kmci bet there's already something built-in for that
03:09ohpauleezright
03:09kmcbut that's essentially the Maybe monad from Haskell, one of the simplest monads
03:09kmcyou could certainly implement Haskell-like "do" notation as a macro
03:09kmcor go without; it's not too bad
03:09kmcespecially in a Lisp syntax where you're used to building lots of nesting
03:10raekjust (send persist-agent conj changed-ref) and eventually it gets saved. the agent also handles a (fn sleep-and-store [refs] (doseq [r refs] (store r ...)) (Thread/sleep sleep-interval) (send *agent sleep-and-store) #{})
03:11ohpauleezkmc: cool, thank you
03:11kmci can find plenty of stuff about monads in clojure
03:11kmcbut i'm not sure if it's considered idiomatic
03:11kmchaving only just started using the language
03:11kmcno problem ohpauleez
03:11kmcdo you know any Haskell btw?
03:11ohpauleezenough to read and understand it.
03:12raekI guess -?> is very similar to the Maybe monad
03:12Adamantkmc: you might also want to look at Scala
03:12Adamantespecially ScalaZ
03:12ohpauleezI've never written more with it than a tutorial
03:12kmcyeah Adamant
03:12kmcScala is an interesting language; it's definitely on my to-learn list
03:12Adamantkmc: I'm starting to look at both since they may be easier to get in the door at a business than Scheme or Haskell
03:13kmcyep
03:13Adamantand the only real suck I can see so far is basically the JVM's fault
03:13ohpauleezI've played around with the mondad library in clojure. Also fnparse uses it at its core, which I've done a lot with
03:13kmci'm interested in Clojure for that reason; because of Java libraries; and because I like metaprogramming and find TH to be annoyingly difficult
03:14Adamantyeah
03:14kmcand because i want to avoid taking Haskell as a Blub language
03:14AdamantI still think Lisp is the best for metaprogramming
03:14kmcyeah
03:14kmci like the idea of a Lisp-like variant syntax of Haskell for metaprogramming
03:14kmcLiskell did this
03:14kmcbut is kind of a dead project, and not easy to use (it's a set of patches to GHC)
03:15Adamantyeah
03:15kmci agree about things being the JVM's fault
03:15kmcbasically every annoyance i ran into so far in setting up clojure and finishing one program
03:15kmchas been from Java stuff poking through
03:19LauJensenAdamant: Why do you find Scala interesting?
03:19yayitsweiraek: what do I pass in for ref-type when calling file-stored?
03:19KirinDaveraek: About your agent thing
03:19AdamantLauJensen: because it's a ML or Haskell for places that can't handle ML or Haskell
03:20KirinDaveraek: You said the agent would hold the ref?
03:20LauJensenAdamant: Ah ok, so you like the functional paradigmes put on the imperative stack ?
03:20Adamantyes, the big attraction is a ML-like language that you can actually get companies to adopt
03:21LauJensenAdamant: This is probably a dumb question, but how much do Scala and ML have in common ?
03:21AdamantLauJensen: a fair amount
03:21KirinDaveAdamant: You can get companies to adopt all sorts of things.
03:21LauJensenKirinDave: true
03:21AdamantML is kind of the progenitor os such languages
03:22KirinDaveI mean, I was a full time erlang programmer for nearly 2 years at a company that originally didn't do any erlang.
03:22AdamantKirinDave: sure, but Scala and Clojure are generally a easier sell than Scheme or Haskell
03:22KirinDaveThose who dare; win.
03:22LauJensenAdamant: As they should be
03:23raekKirinDave: no, a set of refs.
03:23KirinDaveraek: Why wouldn't it hold the file?
03:23KirinDaveraek: That's what the agent is changing.
03:23AdamantLauJensen: I'm not sure about "should be", but they are.
03:23raekyayitswei: re, atom or agent
03:24LauJensenAdamant: Well. Clojure has more to offer in a business setting than Haskell, in no small part due to its integration with everything Java. Ditto for Scala. Clojure then goes the step further in that it builds incredibly robust and maintainable software. Which isnt the worlds hardest sell
03:24KirinDaveRight.
03:24KirinDaveWe chose Clojure and Scala because we need to work with java but realize it's a lousy language for people who are not retarded.
03:25LauJensenKirinDave: Wow, and people call me harsh
03:25raekyayitswei: the agent things I mentioned were only ideas...
03:25bartjLauJensen, why doesn't your blog link work? http://blog.bestinclass.dk/index.php/2009/10/python-vs-clojure-evolving/
03:25AdamantLauJensen: from my perspective, it's more about being able to say "JVM-based language" repeatedly until it bores into the skull of people making decisions
03:25LauJensenbartj: The blog.bestinclass hasn't been active in over 12 months I think. Try www. instead of blog.
03:25KirinDaveLauJensen: http://www.youtube.com/watch?v=iwGFalTRHDA
03:25bartjLauJensen, ah thanks
03:26yayitsweiraek: i see, I'm just trying to understand what your function does
03:26LauJensenbartj: and notice the .php goes away automatically, nginx doesnt like it
03:26KirinDaveLauJensen: Or perhaps: http://www.youtube.com/watch?v=ounTVG6paBM&feature=related
03:26AdamantI'd rather use either Scheme or Haskell, although I'm new at both Scala and Clojure so that may change.
03:26LauJensenKirinDave: hehe
03:26bartjLauJensen, yeah, saw your article when you re-vamped your site
03:27bartjLauJensen, would be good if you could handle the blog.bestinclass as well
03:27LauJensenAdamant: Well, Haskell has many virtues, though it still seems like a bit of an island. And also 'purely functional' is not a plus in my book, when building real software.
03:27raekyayitswei: it sets a watcher fn that is called every time the ref/atom/agent is changed, and stores the value it changed into into a file
03:27bartjLauJensen, found that link on HN
03:27LauJensenbartj: Why, many legacy links floating around?
03:27kmcHaskell is an island but that island is growing rapidly due to, uh, volcanic eruption?
03:27LauJensenAh.. I heard a report that 6000 sites are linking bestinclass.dk, so if 10% of them is blog.* I guess I should fix it
03:28raekyayitswei: it also loads the contents of the file and uses that as the initial value for the ref/atom/agent
03:28AdamantLauJensen: understood, it takes a good long while to get used to IO, ST, etc. stuff to the point you can do things as efficiently as in an imperative language if you're doing a lot of imperative manipulations.
03:28tobiasraedermorning :)
03:28LauJensenAdamant: Oh dont get me wrong, I really dislike imperative programming. And I hate the resulting software, at least debugging it. But Clojures approach is ingenious if you ask me.
03:28Adamantefficiently in terms of programmer time.
03:29AdamantLauJensen: yup, I generally agree.
03:29kmci think the biggest barrier to widespread use of Haskell is not purity but laziness, and the tricky performance reasoning that comes with it
03:29Adamantagree there too
03:29Adamanteager is easier for most programmers to reason about, including me
03:29kmcpurity is great for concurrent and parallel programming; this is one point where Clojure and Haskell are philosophically very close
03:29bartjLauJensen, about 1250 I think, according to Google
03:30bartjLauJensen, do a "blog.bestinclass.dk" on Google
03:30LauJensenok, I'll have a talk with nginx
03:30kmc'pure functional' for real software is just another learning curve, as are 'functional' and 'not terrible' etc.
03:30kmcyou can do all the same things
03:30kmcit's just a matter of what's taught and commonly practiced
03:30bartjLauJensen, also seems odd that the link: blog.bestinclass.dk points to Conj Labs
03:31LauJensenkmc: http://news.ycombinator.com/item?id=1531441
03:31bartjLauJensen, because Conj Labs is not a blog in itself :)
03:31kmcLauJensen, i've seen that troll-fest
03:31KirinDaveLauJensen: It's too late for me to pull my punches on the subject.
03:31LauJensenbartj: Thats a barf in the way nginx handles sites. If there's no hit it just picks one :)
03:31kmci'd like to point out that there's a number of PhD dissertations about Java too
03:31bartjLauJensen, oh! :)
03:31LauJensenKirinDave: You flamed in that post?
03:32KirinDaveLauJensen: Oh, no, what I was saying earlier.
03:32LauJensenkmc: And many many more about Scala I think, but none of Clojure :)
03:32LauJensenKirinDave: ok
03:32KirinDaveLauJensen: Java, these days, is basically run by people who think I need a UML diagram to successfully wipe my own ass.
03:32KirinDaveIt's really tedious.
03:33LauJensenhehe. To me Java is really a nutty language. Its amazing how it makes the simplest things incredibly verbose
03:33KirinDaveEven worse because I know there actually are people who are that bad. I'd rather alienate them out of the industry rather than pander to them.
03:33kmcmerits of individual languages aside, i'm disappointed that i keep seeing an anti-intellectual streak among certain communities of programmers online
03:33LauJensenKirinDave: Yea I totally agree
03:33LauJensenkmc: you mean #php? :)
03:33KirinDavekmc: Node.
03:33KirinDaveLauJensen: No, man. Node.js
03:33LauJensen?
03:33KirinDaveWrite once, rewrite for scale NEVER.
03:34KirinDaveThis idea that asynch is magic performance sauce.
03:35tobiasraederis there a way to add static functions to a deftype? since it can't implement its "own" functions and interfaces cant have static functions i guess no, right?
03:35kmcKirinDave, how is Java "these days" different from before?
03:35kmcis it that they stopped innovating in the language design after 2004?
03:35LauJensentobiasraeder: right. static functions are compiled to statics of their own classes IIRC
03:36KirinDavekmc: It isn't. The times are though, and Java hasn't changed much.
03:36tobiasraeder@LauJensen k crap :) thanks
03:36kmcor more recently that Oracle bought Sun and sees Java mostly as a source of lawsuit ammunition?
03:36kmccool there's 2^8 people in this room
03:38kmci hear Java will support λ by late 2012 now ;)
03:38AdamantLauJensen: public static void main()
03:38AdamantI would appreciate it more if it supported continuations in the JVM
03:38Adamantso the mini-interpreter could be dumped
03:38KirinDaveHa.
03:38kmcor just TCO (you can do CPS then)
03:39KirinDaveMan, unlikely
03:39Adamantgood point
03:39kmci think learning Clojure or Scala would be good for my employability
03:39kmcmakes a whole class of "JVM only" jobs tolerable
03:39KirinDavekmc: More salable than common lisp, anyways.
03:39Adamantmaybe even fun
03:40kmchehe
03:40Adamantand Scheme, as much as I still love it.
03:40kmcKirinDave, also a saner and prettier language, from what i see
03:41kmc(Clojure is)
03:41Adamantwell, CL was a compromise language.
03:41LauJensenkmc: Sure, the Clojure Era is now
03:42Adamantthe community also seems fairly nice so far.
03:42Adamantthat's always a plus.
03:42LauJensenYea we're an okay bunch
03:42notsonerdysunnyLauJensen: http://groups.google.com/group/clojure/browse_thread/thread/fcaffc66d5dbf053 describes the problem I was trying to solve in greater detail
03:42LauJensen:)
03:43LauJensennotsonerdysunny: I'm trying to look at it while compiling and deploying, its a little busy today :)
03:43AdamantLauJensen: #haskell has a crazy amount of people in it mostly because people are terminally nice there. it's more important for language communities than most people know.
03:44notsonerdysunnythanks LauJensen .. I just wasn't happy the way I described the problem before.. So I wanted to let you know ..
03:44LauJensenAdamant: Yea Ive always been very comfortable in here.
03:44LauJensennotsonerdysunny: thanks :)
03:45amalloykmc: i am sad to discover that monads aren't something simple like burritos :)
03:46KirinDaveamalloy: Burritos are a subtle and complex art.
03:46amalloybut in a way it's good news; now i won't stay up until i understand it
03:46amalloynight all
03:48kryftLauJensen: You seemed to imply earlier that clojure would produce more robust and maintainable software than haskell; why is that, or did I just misunderstand you?
03:49LauJensenkryft: Yea you misunderstood, I think Haskell produces more robust software than Clojure. What Im saying is Clojure will always produce more robust software than imperative languages (php, java, scala, python, ruby, etc)
03:49kryftLauJensen: I'm only learning clojure and have no haskell experience, so I have no preconceptions about this, just curiosity. :)
03:49kryftLauJensen: Ah, ok.
03:49kryftLauJensen: I blame you because you were explaining why Clojure is an easier sell than Haskell. ;)
03:50LauJensenAh ok. Well, honestly I havent tried to sell Haskell anywhere, but the benefits of Clojure are benefits that customers understand and relate to. Some devs might prefer Scala to Java because of style issues, like not having the 1 billion semicolons, but customers wont care
03:51kryftLauJensen: Right; I can see why clojure would produce more robust software than java. :P
03:51LauJensennotsonerdysunny: Am I correct in reading that (mathematica-eval "D[x*x+y*x,x]") => (+ (* 2 x) y) ;sexp1 and (math (Variables (+ (* 2 x) y)) => [x y] ;sexp2 both work, but (math (Variables (mathematica-eval "D[x*x+y*x,x]"))) is not working ?
03:52kryftUnless it's supposed to be maintained by an average java progammer? :)
03:52LauJensenkryft: Luckily Java programmers dont know how to maintain Clojure :)
03:52LauJensenWell. I guess Rich is actually a Java programmer :)
03:55kryftLauJensen: Precisely, which might make clojure a harder sell. I would expect that many companies like java because labor is cheap and plentiful. Then again, I guess those companies don't care about robustness anyway.
03:55kryftLauJensen: (That is, they like the fact that they can get something implemented in java now, and then later get some other code monkey to extend or maintain it.)
03:55LauJensenkryft: Oh right, to more exact: Innovative companies will buy it. The big corps who dont mind wasting 100 million USD on a dead end project, will still prefer Java or C++
03:55kryftLauJensen: Right.
03:57LauJensenBut that might be changing. Nokia has a seat at the next Conj Labs for instance :)
03:57LauJensenThough I guess you could say they've always tried to be innovative
03:57kryftHere's hoping Nokia doesn't hang itself with Symbian first. ;)
03:57LauJensenNo no, soon it'll all be Symbjure
03:57kryftOo.
03:59kmcLauJensen, funny that you listed Scala as an imperative language
03:59LauJensenfunny like if I said Java was a curly braces language?
03:59kmc'imperative vs functional' is a silly distinction; every usable language supports both features, and they work great together
03:59LauJensenYou need to look at little closer at both Clojure and Scala
04:00Adamantkmc: C doesn't really
04:00kryftLauJensen: So scala isn't as functional as clojure?
04:00LauJensenkryft: Not by a LONG shot
04:00kmcyeah, C gets a pass for being a low-level systems language and not general-purpose
04:00kryftC++ is finally getting lambda functions. =)
04:00kmcLauJensen, i'm aware that Scala is more liberal with mutation than Clojure, which is more liberal with mutation than Haskell
04:00kmchowever all three support it
04:01kmcit's silly to draw this arbitrary line
04:01notsonerdysunnyLauJensen: yes what you are saying is what I meant
04:01kmcand to act like imperative and functional programming are enemies
04:01LauJensenkmc: Not silly at all, its very important actually
04:01kmcwhen the best imperative code i've written is also deeply functional
04:01LauJensennotsonerdysunny: you didnt post the macro that works halfway did you ?
04:01kmcimperative by necessity, functional by design
04:01kmcLauJensen, so what's your criterion?
04:02notsonerdysunnyLauJensen: I don't quiet get what you are saying
04:02LauJensenkmc: The default of the core data types must be immutability, otherwise you'll get in trouble
04:02ChousukeI'm not sure how imperative and (pure) functional programming work together.
04:02notsonerdysunnyboth of those are part of Clojuratica LauJensen
04:02Chousukeyou *can't* do imperative programming with functional data structures
04:02kmcChousuke, in Haskell you write pure functions which return descriptions of IO to perform
04:02kmcthis is a powerful technique
04:02Chousukeyeah, sure.
04:03kmcyou decouple execution order from evaluation order
04:03kmcand you can do imperative programming with functional data structures -- sometimes the most efficient mutable data structure is a ref cell holding a persistent data structure
04:04Chousukemy point is that the stuff you do in the IO monad is no longer functional
04:04Chousukeeven though it integrates with the "outside" functional world.
04:04kmcChousuke, that's not true. IO actions can produce functions which can return IO actions which produce functions ad infinitum
04:04kmcthe idea that Haskell code separates to "pure functional" vs. "in the IO monad" is useful at a certain learning stage, but not really accurate
04:05LauJensenIts wrapping state, pretending its functional
04:05kmcno, it's not pretending anything
04:05LauJensenThough its cute, chousuke is right :)
04:05kmcit's *describing* IO without performing it
04:05kmcthen passing that description off to a component of the runtime system to be performed
04:05LauJensenkmc: I think you need to square off your haskell-fu with Simon Peyton, then we can pick this up again :)
04:05Chousukekmc has a point.
04:06LauJensentrololololo :)
04:06kmcthe other day I solved a practical problem with a function of type «Int → IO (IO a → IO a)»
04:06kmctell me that's not imperative functional programming
04:06ChousukeI suppose we have different ideas about imperative programming
04:06kmcof course the same can be done in Clojure or any half-decent language
04:07LauJensenso both Clojure and Scala?
04:07kmcyes
04:08kmcHaskell has first-class functions and first-class IO actions. in a language which does not distinguish between the two, the same tricks are still possible
04:08kmcassuming you have first-class functions which can also perform side effects
04:08kmcthis is what is usually meant by "impure functional language"
04:12ChousukeI suppose it is true all programs contain some amount of imperative programming by necessity, but I still think the design has to be have a focus on either.
04:13kmcyes
04:13ChousukeIn languages like Clojure and Haskell, the focus is on functional programming; and if you try to use imperative techniques with a functional design, you will run into problems.
04:13kmcthe choice of defaults is very important
04:13kmcas are community norms
04:14kmcbut we should not put the functional tools away when it comes time to interact with the outside world
04:14LauJensenkmc: Where Haskell typically uses monads, we have references types, have you looked at those yet ?
04:14kmcyes
04:15kmcand again, Haskell uses monads for a lot of things
04:15kmcnot all of them have to do with state
04:15ChousukeMonads (and arrows) are a neat tool; it's too bad they pretty much require a static type system to be practical :P
04:15kmcHaskell has reference types too
04:15Chousukethere is a monad library for clojure but... no-one's using it. :P
04:18kmci'm not sure why they require static types
04:18kmclike any generic API, the monad functions need to do type-dependent dispatch
04:18kmcbut this is a standard thing to do in dynamically typed languages as well
04:19kmcmonads in a statically-typed language require a pretty high level of type system sophistication, but that's not an issue with dynamic types
04:32LauJensen,(java.net.URLEncoder/encode "x y")
04:32clojurebot"x+y"
04:32LauJensenShouldnt that be "x%20y" ?
04:32kmc+ is allowed too, i think
04:32nlogaxyes
04:32LauJensenWell, Tomcat doesn't grok it
04:33kmchow does clojurebot know what parts of java are safe to expose?
04:33LauJensenkmc: Whitelist
04:33kmccool
04:33Adamantkmc: also uses Java security stuff for the VM
04:33kmcah, of course
04:34kmcis that using a class as a namespace to get at its static method?
04:34LauJensenYep
04:35esjmorning all
04:35LauJensenMorning esj
06:13bobo_oh, i can see conj-labs in "uppcomming events" in my calendar!
06:29kryftChousuke: Why do monads require a static type system to be practical?
06:42Chousukekryft: I guess my idea of monads is just haskell-centric, but they kind of feel out of place in a dynamic system.
07:02lenwhi all
07:03lenwwhats an easy way to check if one map contains another map ?
07:05LauJensen,(->> {:one {:map :in :another :map} :two 2} vals (some map?))
07:05clojurebotjava.lang.VerifyError: (class: sandbox$eval9725, method: <clinit> signature: ()V) Incompatible argument to function
07:05MrHus(not (= 0 0))
07:05LauJensen-> (->> {:one {:map :in :another :map} :two 2} vals (some map?))
07:05MrHus,(not (= 0 0))
07:05clojurebotfalse
07:05LauJensenlenw: well, that should work :)
07:06lenwLauJensen: digesting that
07:06LauJensennom nom
07:07lenwLauJensen: thnks
07:08LauJensenOk, you have a map with another map inside it. So you pass that to vals to get the values (a map and an int), you pass those values to (some map?) if asks... you guessed it, if any of them is a map. returns nil for false
07:08carkhhum that really should work =/
07:08carkhwhat's wrong with clojurebot !
07:09carkh,(->> {:one {:map :in :another :map} :two 2} vals (some map?))
07:09clojurebotjava.lang.VerifyError: (class: sandbox$eval9729, method: <clinit> signature: ()V) Incompatible argument to function
07:09LauJensenno idea
07:09carkh(doc ->>)
07:09clojurebot"([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc."
07:09LauJensen$mail Raynes Where's your bot?
07:09LauJensenoh wait, its his bot that has $mail, haha :)
07:10esjhehe
07:30jjido_,'foo
07:30clojurebotfoo
07:30jjido_,foo\'
07:30clojurebotjava.lang.Exception: Unable to resolve symbol: foo in this context
07:31jjido_,'foo\'
07:31clojurebotfoo
07:31jjido_,'foo'
07:31clojurebotfoo
07:31LauJensenjjido_: That also works in private with the bot actually
07:31LauJensenand 'symbol' will work in 1.3, but not 1.2
07:32jjido_sorry for the noise heh
07:32LauJensennp
07:33jjido_laujensen: will it give a name ending in ' ?
07:33LauJensenyea. We'll have new functions called +' -' /' and *'
07:34LauJensenThey will auto-overflow, as opposed to throw an exception like + - / *
07:37sandGorgonanybody using openbixo with clojure ? I cant seem to find any docs or how-tos on this.
07:49@rhickeyso, this seems promising: http://www.sutor.com/c/2010/10/ibm-joins-the-openjdk-community/
07:49Adamantwill the openjdk finally have a TCO instruction?
07:49@rhickeyAdamant: as soon as someone does the work
07:50Adamantrhickey: my impression was the problem was political
07:52@rhickeyAdamant: the jdk is a large project with many consumers - it can't simply be about giving everyone whatever they want. So, yes, there will always be some aspect of convincing the majority that your minority feature is for the greater good. Or, if it's just politics, take your technical solution and put it in a fork of Java, then you'll just have the problem of convincing people to run it :)
07:53@rhickeyon a positive note, it seems like Doug Lea could use TCO in his fork/join stuff. Requirements like these (that serve Java in general) are the best hope for these features
07:53Adamantrhickey: that sounds like another way of saying no :P
07:54@rhickeyAdamant: what do you want?
07:54Adamantrhickey: what I said.
07:54@rhickeyAdamant: go make it happen then
07:54Adamantrhickey: if I make it happen, will it get accepted?
07:54@rhickeySersiously, John Rose has asked for volunteers t help with these new features in MLVM, and has gotten few
07:55Adamantok. what's MLVM?
07:55@rhickeyhttp://openjdk.java.net/projects/mlvm/subprojects.html#TailCalls
07:56Adamantrhickey: if there's a decent chance it may actually see the light of day, working on it makes sense.
07:56LauJensenAdamant: The fame is unlimited for the guy who gets TCO on the JVM :) If you're the lucky guy, please do FIXNUMS next :)
07:57@rhickeyPlease do fixnums first
07:57fhdHi. When declaring a bunch of things in a let block, how to best abort if some value isn't as expected?
07:57LauJensenhehe
07:57fhdI haven't run into this issue before for some reason, but I don't know how to solve it elegantly. Here's example code: http://paste.lisp.org/display/115434
07:57fhdIf x is nil, I want to return nil and that's it. If it isn't, I want to continue with the other lets and the function's body.
07:58mrBlissfhd: http://gist.github.com/595634 lazy-let
08:00fhdThats a pretty decent solution for the problem!
08:00carkh(doc nthnext)
08:00clojurebot"([coll n]); Returns the nth next of coll, (seq coll) when n is 0."
08:00carkhhum parameter order is not consistent for nthnext and take
08:01carkhor nth and take
08:03fhdmrBliss: Thanks, looks like a pretty good solution.
08:03carkhi remember there were talks about a threading macro where you could select the position of the threaded argument
08:03carkhdid it eventually make it ?
08:05LauJensenNot that Ive heard of. Sounds scarcely useful as well
08:06carkhwell there is your use case : you need to produce a opaged table for a web page : (-? customers (take 10 ?) (nthnext ? offset))
08:06carkh*paged
08:07carkhthough i inverted the function calls =P
08:17carkhhttp://gist.github.com/622084
08:17carkhfunctional programming to the rescue
08:18carkh(doc trush)
08:18clojurebotI don't understand.
08:21@rhickeywanted - better names than unchecked-* for truncating math ops. We have a new set of truncating coercions (to complement int/long/etc) that need names, and I'd like to do something else for unchecked-add etc
08:21carkhint-add long-add ?
08:22carkhalways seemed like very long names those unchecked-*
08:22@rhickeycoercions need names first
08:23carkhdo you mean for what is now (long value) ?
08:23carkhbut truncating
08:24@rhickeyno, (int val) checks that val is in range, these new ones won't
08:24carkhi can see you going for unchecked-int =)
08:24carkhor truncated-int
08:24carkhbut that's very long again
08:35jarpiainmaybe (int! value) ?
08:41@rhickeyjarpiain: I like !, but overloads its current meaning
08:43carkhint!! keep the ! and show it's not your usual !
08:44carkhint\ : the \ cuts the int
08:45carkhah the reader doesn't like it it seems
08:46carkhint| a vertical truncation
08:53AWizzArd(int: value)
08:59AWizzArdDo we happen to have an expert for JEditorPanes here?
09:00LauJensenAWizzArd: More like a victim them of them, whats up ?
09:03AWizzArdLauJensen: I have a JEditorPane jep, set to "text/html" with a text set to "<font id='0' color='red'>hello world</font>". How can I get the font element itself, and how can I extract its color? I thought to do a (.getDocument jep) and then (.getElement doc "0"). But this seems not to work. Any ideas?
09:04LauJensenSo you want "<fond id='0' color='red'>" and "red" ?
09:06AWizzArdLauJensen: yes.
09:06AWizzArdThe .getElement seems to give me what is *inside* the font tag.
09:06AWizzArdI get an Element whose .getName ==> "content". I expected "font".
09:07LauJensenWhen you set the type to "text/html" that just means tht you get a wrapper around your actual content, with html/head/body etc. So why dont you just pick out what you want with an Enlive selector?
09:07AWizzArdAnd I can not call .setInnerHTML on it, because it is a leaf element.
09:07AWizzArdLauJensen: you mean picking it out on the String that (.getText jep) returns?
09:08LauJensenyea
09:09LauJensen(select (-> t .getText html-snippet) [:font])
09:09LauJensen({:tag :font, :attrs {:color "red", :id "0"}, :content ("hello world")})
09:10LauJensenAWizzArd: ^^ If there's a built-in way for the JEditorPane I would be surprised. Though that would ofc be easier
09:13AWizzArdLauJensen: yes, especially when I want to change it. Maybe I would like to change the color to blue, without generating&setting the whole html string again.
09:14LauJensenYea. You still need a way of selecting that specific font tag though. Hard to make that part simpler than what enlive gives you
09:14noidi_has anyone here written complex, testable GUIs in Clojure?
09:15LauJensennoidi: Depends a little on what you mean by testable. I have written a complex GUI app in Clojure/swing. Which was detestable :)
09:15LauJensen(Swing that is)
09:15noidihehe
09:15noidiI'm reading up on patterns like MVP and presenter first, which all make sense but unfortunately are very OO
09:16noidiand I'm trying to figure out how to get the same separation of concerns out of Clojure code
09:17noidie.g. how one should convert this example to Clojure http://codebetter.com/blogs/jeremy.miller/archive/2007/05/23/build-your-own-cab-part-2-the-humble-dialog-box.aspx
09:17LauJensenWell. We're still breaking new ground. GUI design is usually inseperable from a lot of state. What I tried to do what separate everything into small logical units with no shared state. Cant say Im ready to write a book on the design pattern yet though
09:20noidiyeah, GUIs are pretty much just mutable state (all the components in a window) and side effects (showing pop up dialogs, etc)
09:21bobo_from my experience (in java though) the most important thing when testing GUI's is to ponder what your are actualy testing.
09:25bmhI'm trying to use some java code in a clojure project. I've chucked the java source into src/java and built it with lein-javac, but import can't seem to find it.
09:32AWizzArdLauJensen: yes, the enlive selectors would be very helpful I guess, especially when I can directly search for tags with specific ids.
09:55lenw,(let [m {:one 1 :two 2}] (for [k (keys m)] (prn k)))
09:55clojurebotjava.lang.VerifyError: (class: sandbox$eval9768, method: <clinit> signature: ()V) Incompatible argument to function
09:57chouserweird error
09:57chouserworks fine here
09:58lenwwhy does that print nil nill at the end ?
09:59chouserfor returns a sequence of the return values of its body
09:59chouserthe body is (prn k) and prn returns nil
09:59chouser,(prn :hi)
09:59clojurebot:hi
09:59lenwaah thanks
09:59chouserhm. clojurebot ate the nil.
10:00bmhso, as I asked a bit earlier. I'm trying to use some java code from clojure and the universe is exploding with classNotFoundException. I looked in classes in my source directory and everything seems to be there
10:01chouserso :one and :two are not in the sequence returned, they were just printed out
10:01lenwchouser: yes that makes sense now
10:01lenwchouser: (let [m {:one 1 :two 2}] (for [k (keys m)] k))
10:01lenwno nils there :)
10:02chouserbmh: that means your classpath doesn't have the .class files in it, or not in the right place
10:02chouserbmh: I would think lein should take care of that sort of thing for you, but I don't know lein well at all
10:04bmhchouser: That's what I would have thought too. I have a classes dir sitting at the root of my project, yet in the lein repl the universe explodes when I, say, type kylm.util.KylmMathUtils
10:05chouseryou have a file classes/kylm/util/KylmMathUtils.class ?
10:06bmhclasses/kylm/util/KylmMathUtils.class, yes
10:07bmhperhaps I should upgrade lein, I'm running 1.2.0
10:07chouserthen you simply need to make sure that classes is on your classpath. If that's not a default for lein, I wouldn't know how to add it.
10:09lpetitbmh: yeah, upgrade lein first, you have a very old version, IMHO
10:11bmhlpetit: I'm on it. Let's see if it fixes anything
10:14bmhchouser, lpetit: wonderful! Fixed
10:14bmhlein 1.2.0 was bunging up the classpath
10:14lpetitbmh: happy for you !
10:27LauJensenAWizzArd: Ok great
10:27AWizzArdLauJensen: thanks for the ideas. Though I would really prefer reading/updating just that one node, and not mess with html strings.
10:28LauJensenAWizzArd: Well, with Enlive you can update/query that single node and then return the modified html. It doesnt change the fact that you'll be calling setText with a new body though. But is there a problem in that ?
10:32AWizzArdLauJensen: I don't know yet.
10:33nollidjfor some bizarre reason, my repl says the fns union, intersection, and difference don't exist. what's going on?
10:34nollidjare they in a namespace outside of core?
10:34nollidjah, they are...
10:50LauJensenAWizzArd: If its a problem, you could actually just diff the to strings and update on index.
10:50LauJensento/two
10:57pdkjust for the record
10:57pdk.bat file syntax is retarded
10:57pdkand fragile
11:04LauJensenpdk: why on earth are you using .bat ?
11:04pdkmakin it so i can type clj on the command line to start a clojure session
11:04pdkand its less roundabout than writing a script in python or something for a simple task
11:04LauJensenpdk: why not just use cake?
11:06pdkhm looking into it
11:09LauJensenpdk: simply do this: http://github.com/ninjudd/cake/wiki/Cake-on-Windows, then type 'cake repl' and have fun
11:11kryftLauJensen: Would you recommend cake for OSX as well?
11:12LauJensenkryft: I havent tried it there actually.
11:13lypanovworks for me.
11:13briggsI find that on OS X (or any *nix type system) it's just easier to create a shell script to fire off a repl, if that is all you need:
11:13briggs#!/bin/sh
11:13briggsjava -cp jline-0.9.94.jar:clojure.jar jline.ConsoleRunner clojure.main
11:14lypanovthats much slower than cake.
11:14LauJensenand less tasty as well
11:15pdklike how it crashes to shell if you have any clojure syntax errors
11:15LauJensenpdk: what does?
11:15briggsRunning a simple jline console?
11:16pdknah doing it with jline and the bat seems fine
11:16chouseranyone know how to ask maven to build a jar containing just the uncompiled clojure code?
11:16pdkstarting it with cake repl though any error in a line you write gets you a huge ruby stack trace and goes back to the shell
11:16briggs:pdk, ahh.
11:18hugodchouser: if you are not compiling at all, add your source directory to the build resources
11:23chouserhugod: then just mvn install ?
11:23hugodchouser: or mvn package, if you don't actually want to install it
11:27tonylhello
11:27chouserhugod: thanks, but it still seems to compile the .clj and put the resulting .class files in the jar
11:27chouserhugod: do I need to exclude src/main/clojure from the build somehow?
11:28tonylDoes anyone know how to use the for form?
11:29chousertonyl: ooh ooh, I do!!
11:29LauJensenpdk: I cant reproduce that on linux, could you file an issue on github for it?
11:29tonylthanks chouser
11:29pdkhm
11:29tonyli have a question about the modifiers in the bindings
11:29tonylhow is that expanded?
11:30pdkwhat sort of info would you need to make it a useful bug report
11:30tonyllike :while and :when
11:30pdklike the stack trace and the line causing it
11:30chousertonyl: complicatedly
11:30hugodchouser: do you have packaging set to clojure? - if so remove it, or use compileDeclaredNamespaceOnly as described on http://github.com/talios/clojure-maven-plugin
11:30tonylis it done in the inner loop
11:30pdkthe short version is with ruby 1.8.7 + cake on windows 7 64 bit
11:30chousertonyl: it's generally done at the point in the loop where you list it
11:31pdksomething like say (prints "this will break") makes it dump a ruby stack trace then exit to console whereas you'd just get the exception message and chug along starting clojure the old "java -cp blah clojure.main" way
11:31chouserhugod: <packaging>jar</packaging>
11:31chouserah, I see that in the docs now, thanks.
11:31tonylok so if a do it after the second binding it will run in the iteration of the second binding
11:33chouser,(for [a [1 2 3] :when (== a 2), b [7 8 9]] [a b])
11:33clojurebot([2 7] [2 8] [2 9])
11:34LauJensenpdk: Yes, all of the above sounds great, thanks
11:34bmhIf I create an instance of a java class in Clojure and then invoke a method that mutates the instance, other references to the intance will refer to the mutates version, right?
11:34tonylyeah i tested it out, great, so I can put multiple modifiers for each binding
11:34hugodchouser: remove executions/execution for phase/compile under the clojure-maven-plugin configuration (assuming it is there :)
11:34pdkwould it help to get the actual stack trace
11:35tonylfor is awesome, thanks chouser
11:36chousertonyl: yw
11:36tonylwhy does for can't be expanded with the macroexpand, macroexpand-1 functions?
11:36tonyl,(macroexpand-1 for)
11:36clojurebotjava.lang.Exception: Can't take value of a macro: #'clojure.core/for
11:36chouserhugod: oh!
11:36lpetitI'm getting crazy. 2 hours fighting maven 3 to get it accept a command line argument for filtering ... If there's any maven expert in there, could we talk in private (to not pollute the list, it's a little bit OT)
11:37chousertonyl: that's not how macroexpand works
11:37chouser,(macroexpand '(for [a [1 2 3] :when (== a 2), b [7 8 9]] [a b]))
11:37clojurebot(let* [iter__4059__auto__ (clojure.core/fn iter__9825 [s__9826] (clojure.core/lazy-seq (clojure.core/loop [s__9826 s__9826] (clojure.core/when-first [a s__9826] (if (== a 2) (clojure.core/let [iterys__4055__auto__ (clojure.core/fn iter__9827 [s__9828] (clojure.core/lazy-seq (clojure.core/loop [s__9828 s__9828] (clojure.core/when-let [s__9828 (clojure.core/seq s__9828)] (if (clojure.core/chunked-seq? s__9828) (clojure.core/
11:37tonylok makes sense now, i need to do some digging
11:37tonylthanks
11:37pdkreminds me what is the preferred way to quit a clojure repl session anyway
11:37pdki'm noticing with jline included in -cp doing ctrl C won't work
11:38pdkso just (. System exit 0) which is kinda roundabout
11:38lpetithugod: maybe you're the man ? :-)
11:39lpetithugod: you're too modest ;-)
11:40briggspdk: Control+D
11:41pdkavast!
11:54briggsSo, I am sure that it has been asked... but anyone else going to clojure-conj? I am wondering how many people are going.
11:57hvIs there a way to make clojure `require' a namespace when something from there is used? (purpose is convenience in a REPL)
11:57KirinDaveI wish I could go to conj
11:57KirinDaveIt's just, getting there is so ridiculous from sanfran
11:57KirinDaveLike a 6000 hour flight. :\
11:57gary_posterheh
11:57hvdo they up any podcasts?
11:58KirinDaveAnd I found out my dog has cancer, so I'm staying around to help him through the chemo.
11:58gary_poster:-/ sorry, good luck
11:58TeXnomancyI thought only non-natives called it sanfran
11:58yayitsweimorning everyone
12:00KirinDaveTeXnomancy: if I called it "the city", would you know what I meant? :)
12:03amalloyKirinDave: speaking of which, how did your coffee shop thing on sunday go?
12:03KirinDaveamalloy: No one showed. :)
12:04KirinDaveI am going to go again today, i think someone from greplin is going to come pair with me
12:04KirinDaveamalloy: Which is good, because clothesline is really flying along
12:04KirinDaveamalloy: Last night I got requests through and through: https://gist.github.com/3085f7636f6be32b2ef4
12:04ohpauleezI had to cancel my conj plans for work. Life gets in the way of living I suppose.
12:10tobiasraederis there a way to iterate over a seq and generate a function each named like the symbol in the seq? i tried it with doseq but it doesn't work out the way i thought it would
12:10chouserohpauleez: :-(
12:10KirinDavetobiasraeder: Could you be more specific?
12:11Chousukein a macro?
12:11KirinDaveChousuke: That'd only work if the contents of the seq are known at compile time.
12:11ohpauleezchouser: I wanted to stand up in the crowd and cheer finger trees into clojure.core
12:11ohpauleez:)
12:11chouserohpauleez: :-)
12:11tobiasraederyeah in a macro
12:11ChousukeKirinDave: well in general generating named functions at runtime is not very useful :/
12:11tobiasraederthe contents are known at compile time
12:11tobiasraederill make a gist quick
12:12KirinDaveChousuke: Hum. Maybe.
12:12Chousuke,(do ~©(for [s names] `(defn ~s ...)))
12:12clojurebotjava.lang.Exception: Unable to resolve symbol: © in this context
12:12Chousukeops
12:12Chousuke@ even
12:12KirinDaveSweet.
12:12Chousukealso should be `(do ...) of course
12:12KirinDaveChousuke: I think it could be useful in some cases.
12:12tobiasraederill try
12:13KirinDaveChousuke: Most of the cases in my head are compiler-ish though, a bit of the beaten track of daily use.
12:15hvIs it possible to install "hooks" into the REPL? the hook I am interested is something that require's missing namespaces before evaluating the form.
12:15KirinDavehv: Well you can't hook before evaluating the form any way but a macro, and even that is @ evaluation time.
12:15KirinDavehv: You can just replace require with your own.
12:16KirinDavetobiasraeder: Are you going to gist what you need, or should I get going? :)
12:17tobiasraeder@KirinDave i just tried Chousukes idea and it worked
12:17tobiasraederwas about to let you know
12:17chouseris it bad form to include test .clj in a lib's .jar?
12:17tobiasraederbut thanks a ton
12:17KirinDaveAh
12:17KirinDavetobiasraeder: So your seq's contents are known at compile time?
12:17hvKirinDave: I didn't mean before evaluating *literally*. They could be called pre-eval-hooks-list, or some such. Something that pre-processes the form, and then calls the normal eval in the REPL.
12:18tobiasraeder@KirinDave yeah
12:18tobiasraeder@KirinDave it's a huge java interop mess really which knows pretty much everything at compile time
12:18hvKirinDave: ummm, I cannot see how overwriting `require' can help. could you elaborate, please?
12:19KirinDavehv: Well, it's not like how things are loaded in a magical mystery. If you want to step in front of that then you could do so by just replacing forms like require and use (or load).
12:20KirinDaveSo, am I the only person who uses a macro like this all the time?
12:20KirinDavehttp://gist.github.com/622458
12:20KirinDaveShould be standard. :)
12:21jarpiainhv: you could (defn custom-repl [] (loop (print (eval (preprocess (read)))) (recur))
12:22Chousukerpepl :P
12:22jarpiainpreprocess would walk the form and call require for namespace of each qualified symbol meant to be evaluated
12:22KirinDaveSeriously, so useful.
12:23hiredmanKirinDave: yes, you are the only person
12:23KirinDavehiredman: Why? :\
12:24hiredmanbecause it's not needed
12:24KirinDavehiredman: Except that it is?
12:25hiredmanthe most names I've ever needed to forward declare in a file is four
12:25ohpauleezYeah, I've only ever needed to forward declare when using fnparse
12:26KirinDavehiredman: You never had a situation like https://gist.github.com/793bda15a3b48b704cbf ?
12:27hiredmanKirinDave: the bighttpgraph doesn't have any loops in it, so so I don't see why you would need to forward declare names
12:27KirinDavehiredman: Because otherwise I'd have to declare them backwards?
12:27KirinDavehiredman: Which would make reading it a huge pain in the ass?
12:28hiredmanbackwards in what sense?
12:29hvKirinDave: I would turn the states into keywords or numbers, not functions.
12:30chouseris it bad form to include test .clj files in a lib's .jar?
12:31arohnerchouser: I don't think so
12:31TeXnomancychouser: yeah, sorta.
12:31chouserawesome
12:31TeXnomancyI wouldn't sweat it unless it's an OSS thing though.
12:32carkhKirinDave: what's this defstate thing ?
12:32KirinDavehiredman: I need to declare the states at the bottom of the graph before the states at the start.
12:32KirinDavehiredman: If I didn't have that macro.
12:33KirinDavehiredman: Which was tedious, because then you read the state defs in a different direction from the graph.
12:33KirinDavehv: I did that, but then you're left to resolve them at runtime.
12:34KirinDavehv: So it still does that, but if you don't have it being a keyword it won't try.
12:34hiredmanKirinDave: it's tedious no matter which order you do it in
12:34hiredmananything where you end up def'ing a bunch of names like h13 is going to be tedious
12:35hvKirinDave: why wouldn't you have a map, e.g.: ({:b13 {:test (...) ...} ...} current-state) ?
12:35KirinDavehv: It still might be that under the covers.
12:35KirinDaveRight now they get transformed to functions that call each other.
12:36KirinDaveI confess, increasing the call stack depth by 35+ does worry me some.
12:36KirinDaveBut I dont' think it's much to worry about at this point.
12:36KirinDavehv: It's easier to read as it is now, and provides a lot of flexibility.
12:36carkhah i like the idea of a map, then build an interpreter on top of that data
12:36KirinDavehiredman: The docstrings will fix that once I ad them.
12:36KirinDavecarkh: Slow.
12:36hiredmanno they won't
12:37hiredmanit will already have been tedious, unless your doc strings go back in time
12:37KirinDavehiredman: If I am explicitly implmenting from a reference graph, using those names.
12:37hiredmanI know
12:37KirinDavehiredman: then it makes sense.
12:37hiredmanI am not picking fault with you implementation
12:37hiredmanyour
12:37KirinDaveWell anyways
12:37KirinDaveThe pre-declaration stuff is necessary in this case.
12:37KirinDaveI'm just surprised people accept that it's needed to care about order of definition in everyday use.
12:38KirinDaveIt's not a good thing. It's just an implementation detail
12:38hiredmanI am saying that saying "oh that other way will be tedious" is ridiculous because the task is tedious no matter which way its done
12:38KirinDavehiredman: There are degrees of tedious.
12:38KirinDaveWriting and reading that graph backwards would be at least 3.23 (repeating of course) times more tedious than forwards. :)
12:39hvKirinDave: I am not sure what is more efficient, and my hunch is that (get state-transistion-vector current-state) with states defined as numbers is faster. I would just add some macros to reduce verbosity ...
12:39KirinDavehv: Is faster than a ^:static call? It is certainly not.
12:41hiredmanKirinDave: why do you say it's "just an implementation detail" is there a different implementation of clojure that does it differently?
12:41amalloyKirinDave: the tendency to build things "upside-down" for dependencies is not unique to clojure. i personally don't find it any more difficult to read the concrete layer first and then the abstract layer, but if you do then it's no problem to start reading at the bottom of the file instead of the top
12:42pdkmoreso that it's a simple fact of how they chose to implement it
12:43ohpauleezKirinDave: Really? What's the use case that the map is too slow?
12:45hvKirinDave: I certainly believe there should be a builtin or standard way of building the fastest possible state machine (with minimal verbosity, of course). I am just not sure if your example achieves that.
12:46carkhwell the fastest would be using gotos, but then you would be stopped by the 64kb limit at some point
12:46carkhso there's always a tradeoff
12:47chouserinline is faster, which can happen with java method calls and :static function calls
12:48hiredmanthere are levels of inlining
12:48carkhbut wouldn't it also bump on the limit ?
12:48carkhor is it all taken care of by the jvm ?
12:49hiredmancarkh: if you write code jvm can inline it doesn't have limits in its inlining
12:49carkhoh i see
12:49hiredmanbut clojure's inlining can run into those limits (inlining via definline)
12:49hiredmanalso macro expansion, etc
12:49carkhright
12:50hvperhaps something like the way small maps start as vectors could be applied here. for small state-machines use static calls, for larger ones use transition matrixes, and optimize the keyword-to-number mapping.
12:50hiredman:static I don't think inlines, it just removes the overhead of var derefing
12:51carkhi guess it *might* inline if the jvm feels like it
12:51chouserright, it makes the fn call look like a java static method call, which the jvm should be able to inline if it wants to
12:52hiredmanreally? a static method?
12:52dnolencarkh: which it most definitely will if it's hot code. in my experience the craziest macro tricks, array tricks, what have you is pathetic to a whole series of static calls. your mileage may very.
12:52yayitsweiKirinDave: what's this coffee shop thing?
12:53hiredmanchouser: if it made it a static method call then :static "fn"s can't be closures, is that true?
12:53chouserhiredman: yup
12:53chouser(let [a 5] (defn ^:static foo [] a))
12:53chouserIllegalArgumentException static fns can't be closures clojure.lang.Compiler$FnExpr.parse (Compiler.java:3471)
12:53hiredmanno kidding
12:54chouserI thought you might be kidding around, quoting the error word-for-word like that
12:56hiredmanI have used any of the new stuff in 1.3
12:56hiredmanhaven't
12:56hvis big-num promotion gone forever?
12:57dnolenhv: R.I.P.
12:57ohpauleezthat's not totally true, right?
12:57hvany binding/sub-environment/whatnot you can do to get it back in a limited context?
12:58ohpauleezYou can still signal you want promotion
12:58amalloyyayitswei: KirinDave is trying to get people to meet him at coffee shops in san francisco and do all his work for him :)
12:58dnolenhv: I believe there are auto-promoting variants like +'
12:58KirinDavehiredman: No.
12:59KirinDavehiredman: What I meant was, "It is not some important or interesting behavior of clojure that things have to be declared in order of dependency at compile time.
12:59rlbWhy does string/join return "/" for (string/join [] "/")? The docs say it behaves like perl's, but at least taken literally, that's not correct.
12:59hvdnolen: I see, thanks. that's a relief
12:59KirinDaveamalloy: When you're mirroring some other representation of the chart, I think it's better to have the code go in the direction of the chart.
13:00rlb$ perl -e 'print join("/", ()) . "\n";'
13:00rlb
13:00rlb
13:00dnolen,(+ Long/MAX_VALUE 1)
13:00clojurebot9223372036854775808
13:00KirinDaveamalloy: And the cost is what? Controlled use of (declare ...)? I'm not sure why there is antipathy towards that approach.
13:00dnolenclojurebot is still 1.2.0 hv:, that would throw an overflow exception, +' would retain old behavior
13:00rlb,join
13:00clojurebotjava.lang.Exception: Unable to resolve symbol: join in this context
13:00yayitsweiwow, I'd be down if it means learning clojure from the pros :) incidentally, just posted this question about cafes in SF on hacker news: http://news.ycombinator.com/item?id=1783882
13:00KirinDaveyayitswei: Amalloy is correct.
13:01KirinDaveI am extremely lazy and untrustworthy. I actually hope to rob people while they look at my code.
13:01hvdnolen: yeah, I just tried *' (1.3 here).
13:01yayitsweiKirinDave: I'll have to remember not to bring anything of value
13:02rlbuser=> (str/join [] "/")
13:02rlb"/"
13:02rlb
13:02clojurebot<monads> is "yea, though I should walk in the valley of imperative code, I shall fear no evil, for your monad comforts me" - seen in #haskell
13:02tomojaren't there any nice coffee shops that aren't starbucks?
13:02KirinDavetomoj: Yes.
13:02rlbtomoj: there are here.
13:02tomojpreferably with gelato?
13:02KirinDavetomoj: Esp in the city.
13:02KirinDavetomoj: Coffee Bar is great. Epicenter cafe is popular. There isn't much electricity at Ritual Coffee, but it's historical
13:03tomojcool. plan to come to SF ASAP
13:03amalloyi'd love to get involved in an SF meetup of some kind
13:03KirinDaveFour Barrel has no electricity, but it's gorgeous.
13:03KirinDaveamalloy: Just so you know, I am not tring to make competition to runa's thing. :)
13:03KirinDaveamalloy: I think hackfests and pair sessions would be a nice complement.
13:04amalloyi don't even know what runa's thing is. is that the bay area clojure group?
13:04KirinDaveYes.
13:04amalloyk. i found out about that just days after the one in SF :P
13:04KirinDaveI just want to make it clear.
13:04jkkramerrlb: join takes the separator as the first arg
13:04KirinDaveRuna is awesome and their meetups are cool.
13:04ohpauleezIs there anyone who hangs out here that is between Portland, OR and Eugene, OR?
13:05amalloyjkkramer: but it still does the weird thing with args ordered right
13:05KirinDaveohpauleez: My boss and co-worker are in portland and getting into clojure and scala.
13:05ohpauleezI really miss Philly Lambda and the philly clojure group
13:05KirinDaveohpauleez: Maybe I can convince them to begin something.
13:05rlbjkkramer: ?
13:05amalloyjkkramer: oh, i take it back
13:05rlbuser=> (doc str/join)
13:05rlb-------------------------
13:05rlbclojure.string/join
13:05rlb([coll] [separator [x & more]])
13:05rlb
13:05ohpauleezKirinDave: Spread the word, I'll help out for sure
13:05KirinDaveohpauleez: You asked what the use case for a map deref + invoke being too slow.
13:05amalloyrib: the second arglist is the one youo're using
13:05KirinDaveohpauleez: I'm not really optimizing hard at this point, but
13:05yayitsweiohpauleez: not me, but aren't Portland and Eugene pretty far apart?
13:05amalloyseparator coll
13:06jkkramer,(clojure.string/join "/" [])
13:06clojurebot""
13:06KirinDaveohpauleez: This graph is executed through jetty calls. I'd love to keep good performance for trivial responders.
13:06rlbOh, right -- totally misread that.
13:06KirinDaveohpauleez: The more pre-compiled the graph is, the more the compiler can do, the less runtime work there is, the less overhead per request is incurred.
13:06rlb(wasn't thinking about parallel args, and of course "/" is a coll...)
13:06ohpauleezyayitswei: It's far apart in east coast terms, but not bad in west coast terms. I just hop on the train
13:06yayitsweiKirinDave: will you be there tomorrow?
13:06rlbthanks
13:06KirinDaveyayitswei: Where?
13:06yayitsweiKirinDave: wednesday
13:07yayitsweiKirinDave: at a cafe
13:07KirinDaveOh yes
13:07KirinDaveExactly where, I am not sure yet.
13:07KirinDaveProbably epicenter or coffee bar.
13:07ohpauleezKirinDave: for sure.
13:07KirinDaveohpauleez: Eventually I'll perf audit the macro and make sure everything ends up being static calls and all redundancy is eliminated. That's the benefit of the macro approach.
13:08KirinDaveAnyways, i should get to aforementioned cafe.
13:09plathropHas the Clojure community settled on an idiomatic way to do unit testing?
13:09dnolenplathrop: clojure.test
13:10ohpauleezplathrop: You can also look at lazytest, which gives you a little bit more
13:10ohpauleezit's like clojure.test 2.0
13:17plathropIs there good docs / tutorials for those? Will a quick Google get me up and running?
13:19dnolenplathrop: clojure.test http://richhickey.github.com/clojure/clojure.test-api.html, lazytest http://github.com/stuartsierra/lazytest
13:22replaca_chouser: you're using showoff for your conj preso?
13:22chouserreplaca_: that's the plan
13:22chouserI'm definitely using it for strange loop
13:23replaca_chouser: what are you doing for code formatting? Does it have support for that?
13:23chouseroh, I patched it
13:23chouserfor syntax coloring
13:23replaca_chouser: wanna share? :)
13:23chouserI should put that somewhere. :-)
13:23chouseryeah, just a sec
13:23replaca_I would love it!
13:24chouserit's not much, but it's something.
13:24plathroplazytest looks awesome
13:24replaca_That's more than I got!
13:25replaca_I'm just trying to avoid <div> as much as I can nd stay on the playing field
13:27chouserreplaca_: http://github.com/n01se/showoff
13:27chouserthen @@@clojure blocks should get colored a bit
13:28replaca_chouser: you da man!
13:28replaca_if I do more, I'll send it back
13:28chousergreat, thanks.
13:28chouserthere's actually a "source" for the .js.min files that I added. I wonder where I put that...
13:29replaca_I'm still trying to get the hang of showoff
13:30replaca_we need to have an emacs "de-min" mode or something for working with js
13:32chouserHere's the file I used to generate clojure.js.min: http://gist.github.com/622574
13:33chouserI started with a lisp lang file or something and hacked it up pretty bad
13:33chouserI don't much like the syntax highlighting engines being used here, but they're ok for basic stuff.
13:34chouserI want map to be two different colors in (map (fn [map] ...) [{:a 1}])
13:35replaca_chouser: cool. I've used pygmentize (directly out of emacs) in the past, which is OK, but it feels wrorg in the context of showoff
13:35replaca_*wrong
13:35chousernothing is wrong
13:35replaca_well, wrong as in "likely to cause issues later on" :)
13:36chouserA presentation is one-time performance art, not software. Do what gets it done.
13:36replaca_yup
13:36chouserexcept
13:36replaca_...
13:36chouserstrange loop wants a 1-up pdf, so now I'm screwed.
13:36chouserprinting from the browser appanretly only prints the one slide that's currently visible.
13:37replaca_there was code in their to generate pdfs, but I couldn't get it to run
13:37chouseroh, yeah. hm...
13:37chouserI looked but didn't see anything.
13:37replaca_but I didn't try real hard
13:38chouseroh, I see it now. hmmm...
13:38replaca_showoff static pdf
13:38replaca_once you've installed princely
13:39replaca_but I still got some error
13:40replaca_I like to have a 1-up pdf as a backup in case of various catastrophes
13:40chouseryeah
13:41chouserI have a static .html and heroku install for contingency
13:41chouserpaper would be nice
13:41replaca_yeah
13:41replaca_that's what I was thinking too
13:41replaca_is strange loop this weekend?
13:42jameslHow can I represent extremely big number(infinity) in clojure? Is Float/POSITIVE_INFINITY a right way to go? What if I want is infinity for integer?
13:47rlbHow would you end up with an integer infinity?
13:47rlbOh wait, I see.
13:47rlb(conceptually anyway)
13:51chouserreplaca_: yep
13:51chouserwell, late this week
13:53replaca_cool. Good luck! I wish I could be there, but I can't travel twice so close together
13:55TeXnomancyreplaca_: have you seen epresent? it turns org-mode files into presentations. no extra render phase (don't even have to save); it just uses Emacs' font-lock rules directly.
13:56replaca_TeXnomancy: oh interesting. I haven't seen that, and I'm probably too far into showoff to change horses at this point
13:56replaca_too bad too, since the source material is mostly in org-mode
13:57TeXnomancyyeah. there are other (possibly better) ways to get PDFs out of org-mode, but this is the simplest thing for my needs
13:58replaca_for general pdf or word, I usually just go to HTML and print or import
13:58replaca_from org-mode
13:58TeXnomancycan't imagine keeping slides in something that couldn't go in version control though
14:00replaca_yeah, showoff is good that way (as you would expect from someone who works at github)
14:01chouserMy favorite thing about showoff so far (and it's really just from using the browser to run to preso) is embedded svg that I can edit directly in inkscape and just reload to see.
14:01chousermost preso software chart-drawing tools just don't cut it
14:01TeXnomancyI really like having the whole presentation in a single file though. my last talk I had one per slide and it was a nuisance.
14:02replaca_showoff lets you choose
14:02chouseryeah, one file per slide is no good.
14:02replaca_as many slides per file as you'd like
14:02TeXnomancynice
14:03chouserok, I've got showoff onepage sorta working. 1-up pdf looks to be withing striking distance now.
14:03replaca_chouser: let me know the recipe when you peg it
14:03chouserwill do
14:05chouserhm, the css being used for printing seems ... off
14:06replaca_:)
14:08Drakesonhmm, what is good about showoff? I was about to make a presentation.
14:08Drakesondo you build the pres in json?
14:10replaca_Drakeson: mostly in markdown with some extra stuff
14:10replaca_there's a json file that points to the set of directories you want to use so you can easily enable/disable chunks of the preso
14:11DrakesonI see. I have been working on something that resemples slidy, but using clojure and based on ring
14:11replaca_cool.
14:11DrakesonI guess I should give showoff a try
14:11Drakeson(at least to see if I am missing something)
14:12replaca_showoff's big thing is that it's very interactive. No postprocessing cause it's based on a sinatra server
14:13Drakesonwhat is interactive? building slides or the show time?
14:13replaca_Drakeson: both
14:13replaca_sorry, the show
14:13replaca_but on both the client and server
14:14Drakesonis it ajax?
14:14replaca_authoring is mostly just like writing mardown
14:14replaca_Drakeson: sort of, but no support for real live data
14:14replaca_*markdown
14:15replaca_it does pull a base page and then fills it in with content via ajax
14:15replaca_it's built on top of jquery on the client side andyou can open that up if you want
14:16Drakesonbut what about after that? what else is interactive after the slides are built up?
14:16replaca_just the way you can control them
14:16replaca_and you can add your own js to the mix if you want
14:17replaca_easy support for some kinds of incremental stuff
14:17replaca_simpler than slidy, I think
14:17DrakesonI should give it a try, then.
14:18Drakesonpersonally, I prefer editing sexps with paredit over markdown
14:18replaca_Drakeson: I think that's going to be a tough sell in the wider world :)
14:19Drakesonlisp and clojure are also tough sells ;)
14:20Drakesonreplaca_: do you have to edit any ruby to build up your pres with showoff?
14:20replaca_yeah, but to use showoff (or slidy or whatever) I didn't need to do any ruby hacking
14:21replaca_no, though I had to read some
14:21replaca_to overcome the light docs
14:21replaca_more likely to end up writing css/js
14:21replaca_I've already done some css and chouser did some js.
14:23replaca_bye, y'all
14:23Drakesonreplaca_: thanks, bye
14:46jjidocan you do "import" of a Java package?
14:47jfieldsI'm doing something with refs where I'm concerned about write-skew. I can't find any examples of using ensure. Do I just use ensure instead of deref or am I supposed to use it in some other way?
14:48kumarshantanujjido: (ns xyz (:import java.util.ArrayList)) ?
14:48jweiss_does anyone here know of a way to get fp-like functionality in a unix shell? i'm aware of scsh, lush, eshell. They have little to no tab completion and/or paredit.
14:48jweiss_also there is rush (ruby) shell, but while it has some fp type stuff, i prefer lisp
14:48jjidokumarshantanu: looks good, thanks
14:50klangjweiss_: M-x bash followed by M-x paredit-mode .. I suppose ..
14:50klangM-x shell (unless you have a bash setup)
14:51chouserjfields: doing the ensure once in the transaction is enough
14:51chouseryou use it where you'd otherwise do a dummy write to avoid skew
14:51klangjweiss_: apart from that, the unix shell does let you pipe output from one function to the next ..
14:51jweiss_klang: how does that give me fp functions
14:51jweiss_klang: yeah, but where's filter and map?
14:52klangjweiss_: it doesn't .. it gives you paredit-mode, if you want it..
14:52jweiss_i suppose xargs is like map
14:52jweiss_klang: why would i need paredit for bash :)
14:52ohpauleezjjido: Just a comment, I love watching you really taking a hard grasp of Clojure
14:52klangjweiss_: not really ..
14:52jweiss_i meant i wanted paredit for lispy shells
14:53jfieldschouser: so I use ensure to read the value, make a change to my other ref, then close the transaction, correct?
14:53jjidocan I specify only one jar in the classpath? It does not find classes in the second jar
14:53jweiss_bash doesn't really let you write inline functions
14:53ohpauleezjjido: You do it like this onething:another_thing:last_thing
14:53kumarshantanujjido: the classpath should be delimited by semicolon on Windows and by a colon on *nix
14:53klangjweiss_: I think you have to switch to the bash mindset if you want to do bash stuff .. :-)
14:54jjidoohpauleez: kumarshantanu: I think I have another problem
14:54klangjweiss_: but you could do a lot of things from within clojure
14:54kumarshantanujjido: the CLASSPATH can of course have multiple JARs specified
14:54jweiss_klang: i don't want to do *bash* stuff, just shell stuff
14:55jweiss_scheme shell is awfully close
14:55klangjweiss_: is there a difference?
14:55jweiss_but no completion or paredit.
14:55jweiss_klang: of course there is
14:55jweiss_there are other types of shells than bash.
14:55jweiss_check out http://rush.heroku.com/
14:56klangjweiss_: maybe I am just too bash-centric. I'll crawl back under my rock.
14:57jweiss_klang: my desire to find a new kind of shell was from writing clojure code in emacs (with tab-complete and paredit). thought, "why am i not doing my command line stuff in a similar environment?"
14:57jweiss_and went off looking for one, and haven't found it
14:58klangjweiss_: you can do some commandline stuff from within clojure, but wouldn't that become tedious?
14:59jweiss_klang: yeah, clojure repl really isn't a shell - it's not that easy to connect unix command in/output, do process control etc from clojure, it's not really meant for that (although it may be possible to create that functionality)
14:59klangjweiss_: on rush .. well, it has the advantage of keeping you in the same mindset all the time .. I see your point
15:01klangjweiss_: shell-out or pallet .. but not entirely what you are looking for..
15:12d0mA clojure shell would def. be awesome.
15:14kotarakd0m somehting scsh?
15:14kotarak-.-
15:14ohpauleezd0m: zsh, plus a function to push to nailgun
15:14kotaraksomething like scsh?
15:14d0mWell a little bit as what jweiss_ was talking about with rush.heroku.com
15:15jweiss_i looked at scsh, which is almost perfect - except it breaks emacs paredit. and no tab completion that i can find.
15:15chouserI dunno. quoting filenames all the time sounds tedious
15:16jweiss_chouser: that's the nice thing, you don't quote file names
15:16jweiss_but no tab completion is still too tedious, i agree.
15:16chouserso -- custom reader?
15:16kotarakjweiss_: I guess that's backwards. paredit is "broken" in sense of not supporting scsh. Not the other way around...
15:16chouseror at least custom eval I guess
15:17jweiss_kotarak: well, i guess. paredit is not really meant for a shell prompt. i think it's designed for source files.
15:17jweiss_although it does work fine for slime
15:17jweiss_i think it's scsh's use of the pipe symbol that breaks paredit
15:17d0m[tab] could still work
15:17d0mit could even be improved by adding a little fuzzy matching
15:18hiredmanchouser: well you need to model the filesystem as a set of namespaces and when in the directory of a namespace the symbols of the filenames are bound to the files
15:18jweiss_d0m, any idea how that would be done?
15:18jjidoso the first jar was loading, the second wasn't. Turns out bash expansion of ~ does not work in the middle of the classpath.
15:18chouserhm. interesting. so, custom 'resolve'
15:18d0mWell, it depends of many things.. but I wouldn't be against using ncurses to be able to use clojure and [tab]
15:19jweiss_d0m: yeah i'd be all for that as well :)
15:19jweiss_although clojure is pretty heavy for a shell.
15:19hiredmanchouser: right, being able to alter the behaviour of var resolution is really useful for sandboxing too
15:19jweiss_i'd still use it - just for interactive, not running scripts
15:20hiredmanyou could hook the resolve function, but the compiler doesn't use the resolve function
15:21d0mbut that would kind of be ironic to use clojure ->> which mimic a shell instance.
15:21chouserrhickey wants the compiler to use a more flexible resolve policy for interop
15:22hiredmanArkham lets you change how var resolution happens so clojure.core/eval always resolves to #'arkham.evil
15:22chouserso the compiler doesn't have to load a class into the compiler's running jvm in order to compile calls to that class's methods
15:23hiredmanthat's hard, because is (foo.bar/baz 1 2) a static method call or what?
15:23hiredmandepends on what is loaded
15:23chouserwell, it will examine .class files directly I think
15:23hiredmanmmm
15:23hiredmaninteresting
15:24chouserexactly what I thought
15:26hiredmanhttp://github.com/hiredman/Archimedes/blob/master/src/Archimedes/compiler.clj
15:27jjidoClojure can't find my compiled class, though it is in the classpath: Unable to resolve classname: dodo0Lexer (runner.clj:5)
15:27hiredmanI've been playing with defining a sort of abstract clojure machine as a protocol
15:28hiredmanhttp://github.com/hiredman/Archimedes/blob/master/src/Archimedes/compiler/jvm.clj implementation of the machine for compiling to java bytecode
15:28jjidook it works with (ns (:import))
15:33jjidoCan Clojure transform a String into a program?
15:33jjido,(eval "[1 2 3]")
15:33mrBliss,(doc read-string)
15:33clojurebotDENIED
15:33clojurebot"([s]); Reads one object from the string s"
15:34kotarak,(eval (read-string "[1 2 3]"))
15:34clojurebotDENIED
15:34jjidomrBliss: thanks
15:34mrBlissyw
15:35jjidoWow that works! Clojure just ran my first dodo program :)
15:37plathropAnyone using lazytest that can point me to some good examples? Do people tend to split their tests into separate files and/or namespaces?
15:37ohpauleezjjido: Congrats!
15:39jjidoohpauleez: I love that. Very limited at the moment but a good start
15:45bhenryis the 1st fibonacci number 0 or 1?
15:45amalloy0
15:45amalloy0 1 1 2...
15:46bhenryso (nth-fib 1) should be 0? i have (nth-fib 0) as 0 and (nth-fib 1) as 1 (nth-fib 2) 1 etc.
15:46bhenryso it's 0 indexed i guess
15:46bhenrybut i want it to make sense
15:47amalloyi think your description is right. it's 0-indexed just like nth, no?
15:47amalloy,(nth 1 (range))
15:47clojurebotjava.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Number
15:48amalloy,(nth (range) 1)
15:48clojurebot1
15:48amalloygets you the natural number at offset 1, whiuch is the second one in the list
15:49bhenryso (nth-fib 0) should be 0?
15:49bhenrythat does make sense
15:49amalloyyes
15:49amalloyi agree whole-heartedly with that assertion/question
15:49kotarakWhere it might be disputed whether 0 is a natural number..
15:50amalloykotarak: sorry, i was compiled with --no-pedantic today. if you prefer, s/natural/non-negative/
15:50coldheadsup ChanServ
15:51kotarakamalloy: ;)
15:52bhenryamalloy are there any drawbacks to this? it took 400 msecs to find the 100th fib 1000 times. but i don't have anyone else's nth-fib function to compare. https://gist.github.com/8223ea8e8d2db70f54f2
15:53amalloy|lunchbhenry: check out rosettacode's fibonacci problem
15:53amalloy|lunchthe clojure implementation is very nice
15:55bhenryoh cool it's almost the same. except they are generating the list of fibs and i'm generating a way to find the nth fibs.
16:10plathropI must be doing something wrong. I've defined a function with defn and a docstring, but when I do (meta #'myfn) the doc isn't included...
16:11ohpauleezplathrop: can you post a gist of your code?
16:11ohpauleezalso, does (doc myfn) show anything?
16:11kotarakplathrop: the string goes in front of the args
16:11plathropohpauleez: sure, 1 sec
16:12plathropkotarak: oh, that's probably it
16:12kotarakplathrop: usual suspect
16:12ohpauleezmeta doesn't show the doc for me
16:12plathropkotarak: yeah, that was it, now showing up in both meta and doc
16:12plathropthanks
16:13hiredmanohpauleez: meta of the var, not meta of the fn
16:13kotarakplathrop: np
16:13plathropthat kinda sucks, though, imho
16:13plathropfor reading the code
16:13kotarakplathrop: it does not, because you can have multiple aritites
16:13ohpauleezhiredman: ah, I see that now
16:13plathropI guess that makes sense.
16:14plathropI'm just coming from CL, so I guess it's "DIFFERENT IS BAD ARGH!" on my part
16:15kotarakplathrop: which is kind of a strange attitude, IMHO. Why learn something different if it's bad?
16:15plathropkotarak: Was making fun of myself
16:15plathropMy gut was that it was bad, but gut is often wrong
16:17kotarakplathrop: no offense intended.
16:18plathropNone taken
16:32amalloybhenry: the rosettacode version is "better", though, because it lets you compute a range of fibonacci numbers, or keep around a local cache of them in whatever range you need, without inefficiently recomputing the whole thing every time
16:35dpritchettisn't there a clojure macro for applying a bunch of different setters to an object all at once without spelling out the object on each line?
16:35amalloy,(doc doto)
16:35clojurebot"([x & forms]); Evaluates x then calls all of the methods and functions with the value of x supplied at the front of the given arguments. The forms are evaluated in order. Returns x. (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))"
16:35amalloydpritchett: ^^
16:36amalloydpritchett: see also -> and ->>, which are different but in sorta the same vein of code restructuring
16:37arkhis there a function that will expand the following? [1 [2 3] [4 5 [6 7]]]
16:37arkhto this [1 2 3 4 5 6 7]
16:37amalloy,(flatten [1 [2 3] [4 5 [6 7]]])
16:37clojurebot(1 2 3 4 5 6 7)
16:37arkhamalloy: thank you
16:47lrennninjudd: http://gist.github.com/622884
16:48lrennninjudd: not sure if that is a concern or not as I switch around versions and branches fairly often.
16:48ninjuddlrenn: that is the bug i just fixed
16:49amalloyninjudd: it's so exciting to be using a product maintained by someone with psychic powers, who can fix bugs before you submit them
16:49ninjuddheh
16:50lancepantzheh, his super hero is now totally jean gray
16:53ninjuddamalloy, made --no-destroy-host-system the default now too ;)
16:53ohpauleez~seen ato
16:53clojurebotno, I have not seen ato
16:54amalloyninjudd: was it a real problem, or something with kmc's setup?
16:54astoddardWhat is the "size" of the element of a clojure vector? Is it the size of an object reference?
16:54chouserastoddard: there is some overhead
16:54arohnera java box is what, 4 pointers?
16:55hiredmandepends on the implementation
16:55ninjuddamalloy: a real problem, though he likely didn't have a lot of memory.
16:57ninjuddamalloy: there are two separate fixes in 0.5.0-SNAPSHOT that should help, one that reduces the default JVM memory usage and one that kills defunct JVMs better
16:59astoddardchouser: Thanks, so on a 64bit JVM I am looking at 24+ Gb for a 3 billion element vector (which just happens to be around the size of the human genome...) ?
17:00amalloyastoddard: why are you storing it in a vector? do you really need it all in memory at once?
17:01arohnerastoddard: what kind of operations do you need to do on the vector? If it's read-only, you could use a java array
17:01chouserwhat are you storing in each element?
17:01astoddardamalloy: not necessarily but I was just quickly trying to work out what a naive implementation would come too.
17:01amalloyninjudd: nice. this machine has plenty of memory, but if i'm ever foolish enough to run clojure on my home machine i need all the memory i can get
17:01chouserprimitive vectors might be smaller
17:02hiredmanyou could use an array even if it is not read only, you just have to be careful
17:02chouser(vector-of :byte)
17:03astoddardchouser: that's one thing I was wondering. I only need 3 bits per element AGCT or N (for unknown).
17:03AWizzArdThat has a good performance, as it uses real byte[] under the hood
17:06chouserastoddard: I doubt it's worth packing your bits in any kind of "naive" solution, but (vector-of :byte) will be more memory-efficient and just as easy to use as a vector of Objects.
17:07chouserwhen/if you're willing to write more complex code to gain performance or memory efficiency, packing bits into a Java array of bytes will be hard to beat
17:08amalloychouser: except by lazy seqs, if he only needs chunks at a time
17:09chouserthough ... it might be fun to write a (vector-of-nucleotides)
17:09astoddardamalloy: For my purposes I need index based access. So that excludes lazy seqs.
17:09chouseras an adapter on top of (vector-of :byte)
17:10amalloychouser: if you're going to do vector-of-nucleotide you might as well go a bit further and layer huffman coding under it, or something similar
17:11chousercompression?
17:11astoddardThanks for the suggestions, I had missed vector-of being added to 1.2.
17:11amalloysince i bet N is either quite common or quite uncommon in his data set
17:11amalloyyeah, i guess any old compression would probably fit this task
17:12astoddardA amalloy suggested, there is a lot of repetition in genome sequence. Big runs of Ns being common in the reference assembly.
17:12chouserI don't know much about compression, but wouldn't it be hard to get good by-index performance with compression involved?
17:13amalloychouser: blahhhhh, of course it would. stupid math
17:13hiredmanit's a trade off, you can divy the sequence into chunks and compress chunks seperately
17:14hiredmantime (access speed) vs. space
17:14chouserpacking 2 nucleotides per byte could likely be done with ~15 lines of clojure
17:14chouserand relatively little impact on read or write performance
17:15amalloychouser: three nucleotides ought to fit in 7 bits, right?
17:15amalloywithout affecting indexability
17:16amalloy5^3 possibilities
17:16chouseryes, just stumbling on that :-)
17:16chousernot neatly bit-partitioned, but a lookup table or some math should make it work well enough
17:17amalloyyeah, just (rem n 5) a few times
17:18astoddardThanks for the suggestions.
17:19amalloy,(take 3 (map first (iterate (fn [[n d]] (rem n 5)) [112 0])))
17:19clojurebotjava.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer
17:19chouserbut again that should be an invibible implementation detail under the IPersistentVector interface
17:19astoddardI was intrigued by using vectors as persistence would let me store a lot of variant genomes very naturally and efficiently as "mutations" of the reference vector.
17:19amalloychouser: right
17:20chouserstart with a (vector-of :byte) because it's there already and replace with your own if it ever becomes worthwhile
17:20chouserhm, except we don't have literal byte syntax in Clojure.
17:20astoddardAnd that then lead to the thought, could I just but the whole reference in memory?
17:21amalloywhat's clojure's truncating division function? the complement of rem
17:21chouserquot
17:21amalloythanks
17:22chouserseriously. 15 lines of clojure could get you vector-of-nucleotides that could store/retreive :A :C :G :T or :N (or maybe nil)
17:23chouseramalloy: are you writing it?
17:23amalloyheh, sorta
17:23chouserlook at mk-am in gvec.clj
17:24amalloyi'm more interested by unpacking a byte into 3 nucleotides actually
17:24chouserI think you can write an ArrayManager for nucleotides and you'll be all set
17:24chouserput your packing code in aset and your unpacking in aget
17:24amalloyoh, no kidding? i didn't know that existed
17:24amalloy,(map first (take 3 (drop 1 (iterate (fn [[n d]] ((juxt quot rem) n 5)) [85 0]))))
17:24clojurebot(17 3 0)
17:25chouserit's not documented and therefore not really supported, but it sure would work today.
17:26amalloyhrm. that doesn't seem quite right, does it? i see
17:26amalloy,(map second (take 3 (drop 1 (iterate (fn [[n d]] ((juxt quot rem) n 5)) [85 0]))))
17:26clojurebot(0 2 3)
17:27amalloythere. 3*25 + 2*5 + 0*1
17:28chouseroh, a custom ArrayManager won't be enough
17:28chouseryou need to muck with the index earlier than that would allow
17:28chouserI think you would actually need a full vector adapter
17:28amalloychouser: now you're making me glad i didn't try to do that part first
17:29chouserheh
17:30amalloyhey, this could easily be turned into a generic bit-packer for encoding stuff in base N (here 5)
17:31chouserand since we don't yet have efficient partial implementations of the core clojure abstractions, a proper NucleotideVector deftype that handles equality, hashing, subseq, etc. will be quite a bit more than 15 lines.
17:31ohpauleezamalloy: that's almost an insult or a way to establish geekery rank
17:31ohpauleez"I'm an n-5 bit packer"
17:31ohpauleezor, "Quit being such a bit-packer and get it done"
17:31amalloyhaha
17:32amalloyyou should have seen the bit-packer that guy was carrying
17:32ossarehin england we use pack to mean "stop". i.e. "pack it in"
17:33amalloyossareh: we have that idiom, but don't use pack to mean stop in any other context i can think of
17:34ohpauleezin England, bit-packing is like "stop the presses" for the computer
17:34ohpauleez:)
17:34ossarehamalloy: right - I was just thinking that - an habitual packer is not a constant stopper =)
17:34ohpauleezhahaha
17:35ohpauleezIf there are ever Clojure Community awards, I really hope there's a category for, "most derailed conversations in IRC"
17:35amalloyhaha
17:36Adamantthey're just establishing a topic calculus. they can find the tangent to anything.
17:38astoddardThanks for the suggestions, folks. For now I'll start exploring vector-of :byte
17:43astoddardBut that does leave me asking how to assign to such a thing without a byte literal...
17:44astoddardHm, looks like I can just conj any integer that fits in a byte. Well that was easy.
17:47AWizzArdà propos, there is also a java.util.BitSet
17:48AWizzArdWith it you could do 3 bits per entry.
17:48amalloyAWizzArd: yeah, i always hated that class, though it might be useful for this application
17:48AWizzArdhttp://download.oracle.com/javase/7/docs/api/java/util/BitSet.html
17:48AWizzArdDon’t hate, learn to master it :)
17:48amalloythe must useful thing it could do is iterate over a collection of set-bits or unset-bits, but instead it will only iterate over all bits and return true/false
17:51AWizzArdThis BitSet class could store your 3 milliard entries à 3 bit in around one GB of RAM.
17:51amalloy3 milliard? i'm not sure what a milliard is, but he has 3 billion entries
17:51AWizzArdYes, milliard = billion ;)
17:52stainand billion = trillion!
17:52AWizzArdAn european milliard is an american billion
17:52amalloyman, is this a stupid english thing? i thought i knew all the stupid english things :)
17:52AWizzArdWhile a european billion is an american trillion
17:52stainthat's how the bankers managed to fool everyone in the credit crunch
17:52AWizzArd:)
17:52stainUK is using billion = 1 000 000 000 like the US - they changed it in the 70s or something
17:52AWizzArdAt least meters kilometers miles foot and inches have very distinct names.
17:53AWizzArdyes, amazing job
17:53AWizzArdThey should switch on a regular basis in every country
17:53stainperhaps at almost the same time as daylight savings
17:53AWizzArdyes *sigh*
17:53alsocaseylanguages will make fools of us all
17:58AWizzArdAnyway, the BitSet should be able to store your whole genome in around 1 GB of RAM.
17:58hiredmanbut BitSet is mutable and not threadsafe
18:00AWizzArdCould be okay for his use case.
18:02AWizzArdif he puts a :byte vector into a single ref then hammering that from multiple threads will totally kill the performance
18:08amalloyohpauleez: now look what you've made me do: http://github.com/amalloy/bit-packer
18:08ohpauleezhaha
18:09ohpauleezYES!
18:09amalloynow *everyone* will know that i am...a bit-packer
18:09AWizzArdFor example http://shootout.alioth.debian.org/u64q/performance.php?test=knucleotide :)
18:09ohpauleezsoon technomancy is going to be coming to me to name his projects
18:09amalloyyeah, just work your way up the scale of interesting people, from me all the way to technomancy
18:10AWizzArdsbcl eats 170 mb ram and runs only one of the 4 cores, takes 37 seconds. Clojure eats 1200 mb ram and runs all 4 cores at 100% and takes friendly 12 minutes ;)
18:14kmc,`(foo# bar ~`(foo# bar))
18:14clojurebot(foo__9899__auto__ sandbox/bar (foo__9898__auto__ sandbox/bar))
18:16amalloyhm. good question, kmc
18:16kmcheh i didn't ask the question yet but i guess it's obvious:
18:16kmchow do i refer to an auto-gensym from an outer quotation within an inner nested quotation
18:16kmc,`(foo# bar ~`(foo bar))
18:16clojurebot(foo__9902__auto__ sandbox/bar (sandbox/foo sandbox/bar))
18:17amalloy,`(foo# bar `(~foo# bar))
18:17clojurebot(foo__9905__auto__ sandbox/bar (clojure.core/seq (clojure.core/concat (clojure.core/list foo__9905__auto__) (clojure.core/list (quote sandbox/bar)))))
18:17kmcahh
18:17kmcmakes sense
18:17amalloymaybe? that has a different level of quoting on the outer form than you might want
18:18amalloybut i think in general it will be what you want
18:40KirinDaveMan, nested quote gensym hacking.
18:40KirinDavePrepare your butthole.
18:41amalloyKirinDave: a minute ago, this window was safe for work :)
18:41KirinDaveamalloy: Oh come on. They say butthole on the simpsons
18:42amalloy*chuckle* i kid, i kid
18:49duncanmdoes anyone know why http://liebke.github.com/incanter/ doesn't actually list anything?
18:50amalloyum, what do you mean? i see a list of namespaces; there's just nothing helpful in any given namespace
18:51amalloyhttp://liebke.github.com/incanter/api-index.html looks like the list of all the functions he's documented
18:52amalloyor if you want the github repo it's at http://github.com/liebke/incanter
18:53duncanmamalloy: the 'old' API docs are here: http://incanter.org/docs/api/
18:53duncanmamalloy: but all the links point to the new site
18:54duncanmoh, i can use this: http://liebke.github.com/incanter/branch-1.0.x/index.html
18:55amalloykmc: wuss
19:00kmcwhat's the standard way to have a function return a successful result or failure, when 'nil' is a possible successful result?
19:02amalloyummmm
19:03amalloyi don't know about standard, but you could return nil for failure, or [result] otherwise
19:04kmcyeah i can think of a lot of ways to do it
19:04kmcthough i didn't think of that one; i like that particularly
19:04kmcmaybe i should take a success continuation and a failure continuation ;P
19:08amalloykmc: you can take your filthy haskell habits out of this channel :)
19:08kmc:P
19:08kmcno, in Haskell i would just return a Maybe value
19:09jkkramerpeople use locals bound to (Object.) as a sentinel value sometimes, but i don't think i've seen it as a return value
19:09kmcah, that's odd
19:09hiredmanthere is clojure.contrib.monads
19:09amalloykmc: go whole-hog java and throw an exception!
19:09kmcamalloy, heh
19:25kmcso i can define a variatic function with (fn [x y & zs] ...)
19:25kmcbut i can't call it like (f x y & zs)?
19:25amalloy,(doc apply)
19:25clojurebot"([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."
19:25kmcis there a better way than (apply (partial f x y) zs) ?
19:25kmcoh, ok
19:26amalloy,(apply + 1 2 [3 4])
19:26clojurebot10
19:37ossarehapply is life.
20:42yayitsweiLauJensen: in your Compojure/Emacs intro, you have Compojure logging displayed in the inferior lisp buffer. I don't see that in my Emacs, did you have to do some special configuration?
20:42yayitsweiLauJensen: referring to the vimeo video, thanks for putting that up.
20:51defnis there a shortcut to get the most recent match from a regex
21:26_rata__hi
21:27_rata__how do I change the way an object is printed by the repl?
21:28dnolen_rata__: print-method
21:28dnolen,(doc print-method)
21:28clojurebot"; "
21:28dnolenheh
21:28amalloy~source print-method
21:29amalloynot quite doc, but might be helpful
21:30_rata__thanks :)
21:41KirinDaveMan, this webmachine design is bugging me.
21:41KirinDaveThe erlang version totally embraces mutability.
21:43TigerUppercuthow can i create a loop (like a for) in clojure, I would like to repeat a function 100 times passing as arguments to function ( myFunc(i) )
21:44KirinDaveTigerUppercut: (dotimes ...) is a good start
21:44KirinDave,(dotimes [n 3] (println n))
21:44clojurebot0 1 2
21:46amalloyor:
21:46amalloy,(map #(* 2 %) (take 3 (rest (range))))
21:46clojurebot(2 4 6)
21:46amalloydepending on, among other things, whether you want it to be lazy
21:50amalloy(and whether you want it to return a result or just produce side effects)
21:51KirinDaveamalloy: You know what's what. Can I bounce ideas off you for a moment?
21:51amalloysure
21:51KirinDaveI'm trying to think my way around a problem.
22:01TigerUppercut,(dotimes [n+1 5] (println n))
22:01clojurebotjava.lang.Exception: Unable to resolve symbol: n in this context
22:03TigerUppercuttk
22:07KirinDaveTigerUppercut: You need the index passed in?
22:12TigerUppercutI don't know what happen... (dotime [n 5] (myFunc n)) .. not yet
22:12amalloyTigerUppercut: that last form looks right
22:20amalloy,(let [[a b :as c] 1] [a b c])
22:20clojurebotjava.lang.UnsupportedOperationException: nth not supported on this type: Integer
22:20TigerUppercutI pasted here http://pastebin.com/MabThXYP ... when I call "test 5" it returns nil , if a remove dotimes and call direct, works correctly. Could you see?
22:20amalloy,(let [& [a b :as c] 1] [a b c])
22:20clojurebotjava.lang.IllegalArgumentException: let requires an even number of forms in binding vector
22:22amalloyTigerUppercut: dotimes doesn't collect its results into a list; it just evaluates them for side effects
22:22amalloyif you want it to print, then try wrapping a (print (if...)) around the if on line 11
22:25TigerUppercut:) it works. tks
22:29_rata__how do I create the symbol 'x_op' from the symbol 'x'? is there any function like Scheme's string->symbol and symbol->string?
22:29amalloy_rata__: symbol and str, respectively
22:29_rata__oh thanks :)
22:31bhenryTigerUppercut: dotimes is for side effects and will return nil every time.
22:31amalloy_rata__: http://github.com/amalloy/enum/blob/master/src/enum/core.clj is something i did a while ago that you might find useful
22:32amalloyspecifically lines 6-8
22:40_rata__yeah, thanks, I understand that part... but what does the 'key' function do?
22:41chouserkey returns the key part of a MapEntry
22:41chouser,(first {:a 1})
22:41clojurebot[:a 1]
22:41chouser,(key (first {:a 1}))
22:41clojurebot:a
22:41chouser,(avl (first {:a 1}))
22:41clojurebotjava.lang.Exception: Unable to resolve symbol: avl in this context
22:41chouser,(val (first {:a 1}))
22:41clojurebot1
22:42amalloyummm which part? chouser effectively explains (key), but i wonder if you mean what's key in my code for
22:42chousersorry, I should know better than to answer without context
22:43amalloyheh, well your answer might well be the right one
22:44amalloycause it's looking like my answer will be "i'm using key in a way that is totally unrelated to what you're trying to do, but i'm happy to explain it to you if that's what you actually mean"
22:44amalloy_rata__: i guess neither of us pinged you when we answered
22:45_rata__amalloy, no, I didn't know what the key function do in general... and the repl proved tricky at trying to understand it
22:45amalloychouser: see? right again :)
22:45chouserlucked out
22:50_rata__which pastebin do you guys use? which one has clojure syntax highlighting?
22:51amalloyhttp://gist.github.com is pretty good
22:53_rata__http://gist.github.com/623339
22:53amalloyyou get clojure highlighting iff you tell it the filename ends with .clj
22:54_rata__mmmm hahahaha ok
22:54_rata__ok, now it works :)
22:56TigerUppercut, (dotimes [m 4
22:56clojurebotEOF while reading
22:57TigerUppercut, (dotimes [m 4] (print m "-"))
22:57clojurebot0 -1 -2 -3 -
22:57amalloy,(for [x (range 4)] x)
22:57clojurebot(0 1 2 3)
22:59amalloyor for extra fun:
22:59amalloy,(clojure.string/join '- (for [x (range 4)] (* 2 x)))
22:59clojurebot"0-2-4-6"
23:04_rata__is there a way to say ` not to qualify a symbol?
23:05amalloy_rata__: ' works, but it's usually a bad idea in a macro, and often actually illegal in a macro
23:07amalloy,`(~'r)
23:07clojurebot(r)
23:07amalloy,'r
23:07clojurebotr
23:11_rata__thank you amalloy
23:12_rata__I have these two macros: http://gist.github.com/623360
23:12_rata__is it two bad to use the ' there?
23:13_rata__they seem to work correctly
23:13amalloywell...i mean, it's fine so long as you know that you're messing around with any variables named r the user happens to have
23:14amalloybut you probably want to use the automatic gensym# forms
23:14amalloy,`(let [r# 1] r#)
23:14clojurebot(clojure.core/let [r__10001__auto__ 1] r__10001__auto__)
23:15amalloy_rata__: the # magically creates a new variable name for you that it guarantees nobody else is using, so that you can't accidentally step on the user's variable named r
23:17_rata__oh yes, that was what I wanted... I couldn't remember how hygenie was done in clojure
23:17_rata__thanks
23:17amalloywelcome
23:18Lajla,(for [x '(\a \b \c)] (conj x "bla"))
23:18clojurebotjava.lang.ClassCastException: java.lang.Character cannot be cast to clojure.lang.IPersistentCollection
23:18Lajla,(for [x '("a" "b" "c")] (concat x "bla"))
23:18clojurebot((\a \b \l \a) (\b \b \l \a) (\c \b \l \a))
23:19amalloyLajla: conj takes its args in the other order
23:19amalloy,(conj "bla" \a)
23:19clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection
23:19Lajla,(for [x '(\a \b \c)] (conj "bla" x))
23:19clojurebotjava.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IPersistentCollection
23:19amalloyhm
23:19amalloyoh
23:19Lajlaamalloy, you liar.
23:19amalloy,(conj (seq "bla") \a)
23:19clojurebot(\a \b \l \a)
23:19Lajla,(seq 3)
23:19clojurebotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer
23:20Lajla,(seq '[vector I am])
23:20clojurebot(vector I am)
23:21amalloy,(str (conj (seq "ola") \h))
23:21clojurebot"(\\h \\o \\l \\a)"
23:21amalloylol, not quite right there
23:21amalloy,(apply str (conj (seq "ola") \h))
23:21clojurebot"hola"
23:21amalloyLajla: ^
23:22Lajla,(str '(this is a random list \a))
23:22clojurebot"(this is a random list \\a)"
23:22LajlaWeird
23:22LajlaWhy the double \ beore the char?
23:22amalloyso that if you copy/paste that back into the repl you get the same thing
23:22amalloy,"(this is a random list \\a)"
23:22clojurebot"(this is a random list \\a)"
23:22amalloy,"(this is a random list \a)"
23:22clojurebotUnsupported escape character: \a
23:22Lajlaahhhh
23:22Lajlaescape
23:22LajlaYeah, I get.
23:33amalloyis there a function that combines predicates like and, but returns a function instead of evaluating something? eg, something equivalent to
23:33amalloy(fn [& preds] (fn [& args] (every? identity (apply (apply juxt preds) args))))
23:38amalloyi had in mind using this like (multi-pred integer? pos?) to define a function that tests for positive integers, but my naive implementation has some problems, so i was hoping someone else has done this
23:41_rata__amalloy, what's the problem with the anonymous function you write before?
23:41amalloy,((fn [& preds] (fn [& args] (every? identity (apply (apply juxt preds) args)))) 'a)
23:41clojurebot#<sandbox$eval10078$fn__10079$fn__10080 sandbox$eval10078$fn__10079$fn__10080@4fdbd6>
23:41amalloyrgh
23:42amalloy_rata__: the problem is if you pass it "a" it tries to call pos? even if the test for integer? failed
23:42amalloyie, it's not lazy enough
23:43_rata__ah ok
23:43_rata__and #(and (integer? %) (pos? %))?
23:44amalloy_rata__: works, except i'm doing this in a function postcondition, which steals % from me
23:44amalloyi wrote it as a (fn [x] (and...)), which does work
23:44_rata__ok
23:44amalloybut that lends itself to copy/paste instead of code reuse
23:45amalloyso i was hoping someone had written a better version
23:45_rata__and you could write a macro multi-pred to write that function for you
23:45_rata__let me try
23:46amalloyhmmm, interesting suggestion. i don't think we need a macro, though: can't this be done with a function that's like my naive one but more careful/lazy?
23:46amalloymaybe the macro is easier, i dunno
23:47Lajla,[+ - * /]
23:47clojurebot[#<core$_PLUS_ clojure.core$_PLUS_@2dacc6> #<core$_ clojure.core$_@84d6c2> #<core$_STAR_ clojure.core$_STAR_@e5691e> #<core$_SLASH_ clojure.core$_SLASH_@736f7e>]
23:54_rata__amalloy, http://gist.github.com/623401
23:54TigerUppercuthow can i make a "new java.util.Date().getTime()" in clojure?
23:54amalloyif i (defn - [] 1), (defn _ [] 2), then both _ and - evaluate to #<user$_ user$_@xxxxxx - how can they have different code if they're the same class?
23:54amalloy,(.getTime (java.util.Date.))
23:54clojurebot1286942392870
23:56amalloy_rata__: args should be args#, but otherwise it looks pretty spiffy
23:56hiredmanhttp://gist.github.com/623413
23:57_rata__=)