0:17 LauJensen: Good morning guys
0:37 amalloy: hi LauJensen
4:05 notsonerdysunny: why should " (def (symbol "hello") 10) " work .. does anybody have an insight into this?
4:05 why shouldn;t " (def (symbol "hello") 10) " work .. does anybody have an insight into this?
4:06 amalloy: notsonerdysunny: def requires a symbol literal
4:07 ,[(symbol "hello") 'hello]
4:07 clojurebot: [hello hello]
4:08 amalloy: (symbol "hello") is the same as 'hello, and it seems pretty reasonable that (def 'hello 10) shouldn't work, right?
4:10 LauJensen: user> `(def (symbol "hello") 5)
4:10 (def (clojure.core/symbol "hello") 5)
4:10 user> `(def 'hello 5)
4:10 (def (quote user/hello) 5)
4:11 amalloy: yes?
4:11 LauJensen: In either case its clear they wont work, since neither are a literal symbol
4:11 notsonerdysunny: amalloy: hmm...
4:11 so we cannot programmatically generate the symbols..
4:12 amalloy: you can, but you have to do it in a macro
4:13 notsonerdysunny: amalloy: the other day you had suggested that I use apply-macro to make sure that the arguments of a macro get evaluatated before the macro expansion .. but I couldn't figure out how to use it
4:13 have you used it before?
4:15 amalloy: i wouldn't go so far as to say i *suggested* it...i think you are trying to do things at compile time that you can't do until runtime, and apply-macro lets you get close to that sometimes
4:15 notsonerdysunny: ok sorry for misrepresenting you.. :)
4:15 amalloy: if you really want to create code based on the execution of code, why not just have your clojure program generate a new .clj file
4:15 notsonerdysunny: but I was not able to figure out how to use it in any case ..
4:15 amalloy: and ship that to the user
4:17 notsonerdysunny: :) good point .. but was hoping I needn't have to do that ..
4:18 I think we are trying to make an argument like people using languages who don't have macros would .. :)
4:18 amalloy: if you want the user to be able to run the same program that you do, unmodified, then you have to ship them mathematica. i don't know how it can possibly work otherwise
4:18 notsonerdysunny: I would do to Ahead Of Time compilation
4:19 so all the macros would be expanded in the resultant code ..
4:19 well atleast that was the theory based on which I was working ...
4:20 amalloy: right, i always forget AOT is an option
4:26 okay. here is an idea that i think i have tried a few times but i don't think i've really communicated it to you. one sec while i put together a gist
4:27 notsonerdysunny: http://
4:29 here ask-mathematica is a function, which helps solve-pde generate code
4:31 notsonerdysunny: thanks amalloy .. Let me try to use your idea and come up with something..
4:31 :)
4:32 amalloy: the general point here is you very rarely want to define a macro that uses another macro you define - the second level and below usually want to be functions
4:34 fwiw, (solve-pde x y) really does macroexpand to (+ y (* x 10)) there - the reference to ask-mathematica has vanished
4:50 notsonerdysunny: :) ... but as a side-note.. It would be nice if we had a set of macros which would wrap the special forms and be able to handle non-literal values.. be it macro or just regular code .. just wishfull thinking .. I don't know enough even to evaluate the feasibility of such macros .. :)
4:57 amalloy: notsonerdysunny: well, for (def) you don't need such a macro
4:59 (intern (symbol "test") 'size 10)
4:59 can't do that in clojurebot obviously, but it should work at your repl
5:00 anyway, i'm off to bed. good luck, i hope to see how it all turns out
5:36 _ulises: morning all
7:22 serabe: hi
7:23 raek: hello
8:02 serabe: just released rinzelight, an image library for clojure, http://
9:58 shanmu: Hi, What options would I have if I want to run a long running process/daemon in clojure (which has to do some periodic activity)?
9:59 my thought is to have a compojure app, to which I do wget from cron...
10:00 or another option is to write a quartz job but I am not sure how to integrate in clojure...
10:02 or yet another option would be invoke the cljoure script/compiled class direct from shell script/cron but pay jvm startup cost everytime
10:13 LauJensen: shanmu: jvm startup cost is typically < 1 second with the -client option. It would be trivial to write a program which ran a future every x seconds though. Its a tradeoff between startup time and memory consumption, weigh it thinking about the frequency of the activity
10:15 shanmu: LauJensen: thanks for the suggestion - I had missed future... (i am still a n00b :))
10:28 Bahman: Hi all!
10:53 FUser: ,(range 1000)
10:53 clojurebot: (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
10:53 FUser: :)
11:16 ,(counted? (seq [2 33]))
11:16 clojurebot: false
11:16 FUser: ,(counted? (seq '(2 33)))
11:16 clojurebot: true
11:17 FUser: wat?
11:17 makes no sense
11:17 jarpiain: ,(doc counted?)
11:17 clojurebot: "([coll]); Returns true if coll implements count in constant time"
11:17 Chousuke: FUser: they're different types
11:18 FUser: they are both sequences
11:18 Chousuke: ,(let [x '(2 3)] (identical? x (seq x)))
11:18 clojurebot: true
11:18 Chousuke: that's the reason
11:18 FUser: look
11:18 ,(counted? [2 32])
11:18 clojurebot: true
11:18 FUser: ,(counted? '(23 2))
11:18 clojurebot: true
11:19 MayDaniel_: ,[(type (seq [1 2])) (type (seq '(1 2))]
11:19 clojurebot: Unmatched delimiter: ]
11:19 FUser: ,(counted? (seq [2 23]))
11:19 clojurebot: false
11:19 raek: seqs are not guaranteed to be counted
11:19 FUser: these are all expected
11:19 yeah
11:19 raek: but PersistentLists are their own seqs
11:19 FUser: but why are seqences made out lists counted
11:19 raek: so (seq a-list) happens to be counted
11:19 FUser: also maps
11:19 tensorpudding: where's a good place to get a tutorial to clojure?
11:19 Chousuke: FUser: because lists don't need to be made into sequences.
11:20 FUser: they are sequences already
11:20 raek: (let [l (list 1 2 3)] (identical? l (seq l)))
11:20 ,(let [l (list 1 2 3)] (identical? l (seq l)))
11:20 clojurebot: true
11:20 FUser: ,(counted? (seq {3 22}))
11:20 clojurebot: true
11:20 Chousuke: I suppose it might be an oversight, though.
11:21 FUser: whats the diff between seq function and sequence function?
11:22 ,(seq nil)
11:22 clojurebot: nil
11:22 FUser: ,(sequence nil)
11:22 clojurebot: ()
11:22 FUser: oh
11:23 raek: tensorpudding: this covers the basics http://
11:24 FUser: sequence is also faster it seems
11:25 (time (do (sequence (range 1000000000)) nil))
11:25 raek: I have seen 'sequence' before...
11:25 FUser: ,(time (do (sequence (range 100000000)) nil))
11:25 clojurebot: "Elapsed time: 0.135 msecs"
11:26 FUser: ,(time (do (seq (range 100000000)) nil))
11:26 clojurebot: "Elapsed time: 0.212 msecs"
11:26 raek: seq is the one that is usually used to turn a collection into a sequence
11:27 _ulises: ,(doc sequence)
11:27 clojurebot: "([coll]); Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. (sequence nil) yields ()"
11:28 tensorpudding: what does clojure call lambda?
11:28 Kruppe: fn
11:28 (fn [] (print "hi"))
11:28 tensorpudding: okay
11:29 clojure looks pretty good for being built on java, i suppose
11:30 Kruppe: tensorpudding: It's pretty nice, id say its more built on the jvm than built on java though.
11:32 raek: there are plans to reimplement the compiler (which is now written in Java) in Clojure
11:32 FUser: :D
11:33 the only problem is that clojure uses a shitton of reflection and allocated billions of objects per second
11:34 raek: reflection is only used of java methods calls
11:35 and can be avoided completely, if the type is known (e.g. through type hints)
11:35 Raynes: tensorpudding: Ooh, you're the second prominent #haskell user in here in the last week.
11:35 tensorpudding: heh
11:35 Raynes: kmc is here too. <3
11:36 FUser: raek: so if I am using clojure Fns, I am not using reflection?
11:36 raek: FUser: exactly.
11:37 clojure fns are always take Objects and return Objects
11:37 FUser: allocations are still a problem though
11:37 raek: yes
11:37 FUser: they did some testing
11:37 Raynes: raek: All your clojure fns are belong to us.
11:37 raek: but the HotSpot JVM is pretty good at it
11:38 FUser: compared ArrayList and LinkedList in java, inserting in the middle of the list, which is O(n) for array list and O(1) for linked list
11:38 raek: but having immutable data structures kinda requires much allocation
11:38 FUser: array list still faster unless the list size is over a million
11:39 simply the allocations for the linked list objects
11:39 are too much
11:39 raek: I guess that the mutable data structures are simpler and faster, but they still have the problems Clojure is trying to solve
11:39 FUser: and that's java mutable linked list, I can only imagine how badly the clojures quasiconstant time inserts must be
11:40 Chousuke: Don't imagine, measure :)
11:40 FUser: I'm just sayin'...O(n) notation doesn't say shit :P
11:40 raek: neither PersistentVector nor PersistentList is the correct data structure for doing fast inserts to the middle
11:40 I have heard that chouser is working on some data structure that has good performance for that
11:41 Chousuke: Finger trees
11:41 wakeupsticky: best clojure tutorial for the non-java programmer (i'm familiar with lisp and haskell)?
11:42 FUser: transient vectors are probably fast
11:43 Chousuke: They'll still be slow for inserts in the middle
11:43 FUser: if they are actually java ArrayList then they are fast
11:43 raek: wakeupsticky: these were what I got started with. YMMV. http://
11:43 Chousuke: they aren't.
11:43 they can't be. :/
11:44 because transient->non-transient and vice versa must be a constant time operation
11:44 FUser: ok then I'll just use (.java.util.ArrayList) :P
11:45 Chousuke: if you're really doing lots of inserts, maybe :P
11:45 FUser: fastest access too
11:45 Chousuke: but realise that you're giving up safety and ease of use
11:45 FUser: I know
11:46 I can't cope with having 300 times slower apps
11:46 Chousuke: I'm not sure about that.
11:47 For a whole bunch of apps Clojure's vectors won't be a bottleneck
11:47 Don't give up on them until you encounter a real performance problem.
11:48 Fast programs are nice, but working ones are nicer :P
11:48 FUser: clojure has a bunch of weird performance issues
11:48 Chousuke: Like?
11:49 FUser: (if (> its 0)
11:49 compared to
11:49 Chousuke: I can't think of anything that's particularly weird. There is room for improvement though.
11:49 FUser: (if (> its (int 0)))
11:49 guess the speed difference
11:49 Chousuke: FUser: in the former case, there is boxing
11:49 FUser: not only that
11:49 Chousuke: so of course it's slower
11:50 FUser: but there's also lookup in > function
11:50 for type
11:50 Chousuke: yeah, because it's polymorphic :p
11:50 FUser: second version runs 9 times faster
11:50 Chousuke: (numerical performance is kind of the focus of 1.3 btw)
11:51 So expect things to improve
11:51 FUser: that kind of performance differences for such a simple change in code is unacceptable
11:51 Chousuke: No they are not
11:51 it's not a simple change,
11:51 it does a lot.
11:51 FUser: I'll spend time saved in development doing profiling afterwards
11:51 well technically yes
11:52 but I can't see why I'd have to cast a constant 0, why can't compiler do that for me
11:52 Chousuke: Because the compiler is not very good yet.
11:52 Kruppe: FUser: its a new language, 1.3 will improve that particular problem
11:52 FUser: :)
11:52 Chousuke: It doesn't try to be, either; there are bigger things to do first.
11:52 Kruppe: FUser: for now its not perfect, thats for sure.
11:54 FUser: sorry I'm mad, but after doing SQL optimizations, where there's a bunch of hidden rules how things get evaluated and slightly changed but semantically same sentences produce vastly different performance I'm really disgusted by these kinds of things
11:55 it all becomes just a whole bunch of arcana
11:55 and code gets ugly fast
11:56 Kruppe: FUser: I sympathize, I wrote a fairly complicated simulation in clojure and it was a real pain to work out all the performance kinks.
11:56 FUser: the simulation was easy to write though.
11:59 FUser: yeah but you see what I mean....you write a simple sql query, optimizer screws it up in ways you know nothing of, then you scour the forums for ages to find some kind of hack (adding dumb shit like "or false" to queries, that makes the optimizer do things differently)
12:00 and that simple query becomes ugly unreadable and ununderstandeable to any other programmer, unless they are in the know of these hacks
12:01 Kruppe: FUser: Its performance definitely isn't a non issue, if its not good enough right now you could always use something else.
12:02 FUser: Or write the bottlenecks in java since you're already on the jvm.
12:02 FUser: well, I am not using it professionally so it's not much of an issue
12:02 Kruppe: FUser: oh, well in that case. Readability isn't such a huuuuuuuge hit.
12:02 Chousuke: Or you could go and improve the compiler, and be everyone's hero :)
12:02 FUser: :D
12:02 Kruppe: FUser: if you don't need concurrency semantics you could always use common lisp.
12:03 FUser: I find it easier to write fast code in CL atm, but i suspect that will change soon enough.
12:03 FUser: CL?
12:03 Kruppe: FUser: common lisp
12:03 FUser: oh
12:03 never used lisp
12:03 mostly java
12:03 Chousuke: In Clojure's case the compiler is destined to be rewritten in Clojure someday though.
12:04 FUser: my main java issues are already solved by C#
12:04 so that would be my perfect language
12:04 Kruppe: Chousuke: yeah I have confidence that rich is very concerned with performance.
12:04 FUser: but I have job requirement to use java so I'm stuck with it
12:04 Chousuke: Yeah.
12:04 FUser: I'm taking up clojure purely for the learning experience
12:05 since it's my first dynamically typed functional language
12:06 I'm fresh out of ideas what to make in it
12:06 Kruppe: FUser: It's a general purpose language, could make anything you want in it.
12:06 FUser: that's my main problem, I was learning Android, J2Me, Clojure, but I have no inspiration about what to make in them so I end up not practicing enough
12:06 Kruppe: FUser: performance issues aside I suppose.
12:07 FUser: I know :)
12:07 Kruppe: FUser: could just pick an open source project and contribute
12:07 FUser: hm....
12:07 not a bad idea
12:07 Kruppe: FUser: dunno if there are any clojure open source projects you would want to contribute to. But you could look.
12:09 FUser: it's funny how I'm the only guy at the office who programs and reads about programming in his spare time
12:09 people call me an academic
12:11 Kruppe: FUser: those people are probably just lazy and are surprised at your initiative
12:11 FUser: probably burnt out on coding java
12:12 FUser: I'm amazed. They have no drive to better themselves at their chosen profession
12:12 even though they are terrible at java
12:12 I don't need to improve my java, I'm one of the best in the firm
12:13 Kruppe: FUser: working at large companies can ruin you desire for self improvement
12:13 FUser: I see shit daily that would bring tears to your eyes
12:13 40 employees
12:13 Kruppe: FUser: oh
12:13 FUser: every non-member function in the project is in a class named Utils
12:14 every constant in the project is in a class named Constants
12:14 shit like that
12:14 Kruppe: FUser: that sounds pretty tame, but this is also a little offtopic now
12:14 FUser: class structure is 1 level deep at most, there are no interfaces defined
12:14 ok
12:15 basically cobol programmers trying to do OO
12:15 OOP
12:15 Kruppe: FUser: it sounds like that structure was just decided by a manager
12:15 FUser: nope, by actual programmers with 10 year more experience than me
12:16 Kruppe: FUser: I guess their minds have been somewhat tainted by working in cobol all the time.
12:16 FUser: no kidding :D
12:16 Kruppe: FUser: teach em how it's done then, you then will really be the academic.
12:16 FUser: that's why I'm learning clojure, not to get completely trapped in Java mindset
12:17 Kruppe: FUser: if learning is your goal i recommend haskell as well. Lots of interesting programming language concepts are available in it to play around with.
12:17 FUser: don't get your heart set on writing haskell for money or anything though.
12:18 FUser: true
12:18 Kruppe: FUser: clojure is a nice intermediate step though, you get to play around with macros and FP.
12:18 FUser: yeah
12:18 Kruppe: FUser: not to mention really slick concurrency.
12:18 FUser: hell I'm hoping for C# someday
12:18 at least it has function pointers
12:19 Kruppe: FUser: not a huge fan, but I don't enjoy programming for windows so.
12:19 raek: there is Clojure CLR...
12:19 FUser: implementing interfaces for a simple filter function in java is maddening
12:19 C# delegates neatly cover a lot of this
12:20 raek I'm not pining for CLR
12:20 just having delegates (function pointers actually) and proper templates (C# ones not java ones) would solve a lot of my day to day work problems with java
12:21 Kruppe: FUser: I don't doubt it.
12:21 FUser: clojure has all of it also, of course
12:21 but it's less commercially popular, so I'm not gonna get a job with it
12:21 Kruppe: FUser: Hey boss, can I use this java library called clojure?
12:22 FUser: hehe, you know
12:22 I thought about it :D
12:22 Kruppe: FUser: actually that would never fly.
12:22 FUser: and it would be pretty irrisponsible of you to decieve your boss like that.
12:22 FUser: I know I know :D
12:22 Kruppe: FUser: and your code would be unmaintainable by anyone else there sadly
12:22 FUser: if only it were that easy
12:22 FUser: yes that is the main problem
12:23 I leave company now they can't fix anything in that code,because nobody else knows clojure
12:23 Kruppe: FUser: I tried convincing my boss to use svn or git for our software projects
12:23 FUser: svn ? version control system?
12:23 Kruppe: FUser: even that was difficult
12:23 FUser: yeah, we weren't using any version control for the longest time
12:23 FUser: it was pretty depressing
12:23 FUser: wow
12:24 that's pretty bad
12:24 Kruppe: FUser: I don't work there anymore.
12:24 FUser: I'm trying to tell the boss that we need design documentation
12:25 Kruppe: FUser: really? That I find really unusual.
12:25 FUser: we are making none since the customers only pay for requirements documentation
12:25 Kruppe: FUser: i need to practically document my bathroom schedule
12:25 FUser: so bascially each programmer is free to design his parts of the program however he wants
12:25 you only have architectural restrictions
12:26 you have to use this DB, that XML Serializer library, that web service etc
12:26 so project parts vary wildly in quality depending on who from our firm is working on them
12:27 Kruppe: FUser: that's unfortunate.
12:27 FUser: only for our customers :DDDDDD
12:27 see this is how it kills you...I stopped giving a fuc
12:29 Kruppe: FUser: Yeah, that will happen if you're not careful.
12:29 FUser: I told my boss multiple times that better programmers should be doing class design for whole project and worse programmers should be implementing closely specified indivdual methods
12:29 can't be arsed to do it again
12:30 Kruppe: FUser: that sucks.
12:31 kryft: C# templates? Are those anything like C++ templates?
12:32 FUser: not sure
12:32 I just know that Java Generics are much like C# templates
12:32 Chousuke: Nothing like C++ templates then :/
12:32 FUser: but C# templates are proper and Java Generics are just stupid compiler hack with limited functionality due to havign to be backwards compatible
12:33 Kruppe: FUser: they work alright though. It could be worse.
12:33 FUser: I've run into their limitations several times before
12:33 Kruppe: FUser: language warts like that happen over time.
12:34 FUser: yeahhhh. Sometimes java just makes things difficult.
12:34 FUser: It could be better if Sun wasn't being so stubborn with their compatiblity
12:34 raek: I find it interesting that the C++ template system is Turing complete...
12:35 FUser: you can't run java 5 classes on java 1.4 anyway so why bother
12:35 Kruppe: FUser: its not stubbornness necessarily.
12:35 FUser: They don't want to scare anyone away.
12:35 FUser: in general they have done a real good job keeping java THE language for business.
12:36 FUser: here an example: public void <E> someMethod(E param) {
12:36 Kruppe: FUser: as a result it may not be the nicest language to work with but its still extremely popular.
12:36 FUser: E.class doesn't work, E.getClass() doesn't work
12:36 Kruppe: FUser: yeah thats one of those warts right there.
12:36 SergeyD: Hi, is there a way to get colorful Clojure cheat sheet? It was in the zip a year ago, but now that link is broken. (In the bottom of http://
12:37 FUser: http://
12:40 raek: SergeyD: I have the .tex file. Can you compile that?
12:40 SergeyD: FUser: thanks for another source
12:41 raek: yes, I'll figure out
12:41 FUser: what's a monad
12:42 raek: SergeyD: http://
12:42 kryft: FUser: http://
12:42 FUser: (I don't really know myself, but I plan to read that at some point and find out. ;)
12:43 SergeyD: raek: thanks!
12:43 Kruppe: kryft: I've used haskell for a few personal projects, and I still can't really describe what monads are in words.
12:52 raek: compiled PDFs are now up too http://
12:53 SergeyD: raek: thanks :)
13:03 _ulises: can anybody recommend a good library for performing 2d vector operations?
13:03 I've sort of handcrafted my own but I'm sure that there are better options out there (google wasn't my friend :(
13:04 esj: _ulises: I think Incanter wraps Colt
13:04 _ulises: oh, right
13:04 esj: unsure how far they went
13:04 _ulises: I am looking for something a bit more lightweight though :)
13:05 ,(doc max)
13:05 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."
13:05 Kruppe: Anyone else having trouble getting incanter and cake to work together?
13:05 esj: _ulises: oh, in that case the seq functions are your friend
13:06 _ulises: seq? how? kind of like (apply map + points) where points is ([x y] [x y]...) ?
13:06 raek: ,(merge-with + {:x 1, :y 2} {:x 0, :y -3})
13:06 clojurebot: {:x 1, :y -1}
13:06 _ulises: ooh
13:06 nice!
13:06 raek: not a seq function, but...
13:06 _ulises: no no, that is awesome
13:07 dnolen: _ulises: cantor is pretty good if you have simple needs, http://
13:07 _ulises: now I have to figure out how to use the same style for euclidean distance and the other fns...
13:08 esj: dnolen: thanks for the pointer - that looks pretty useful
13:08 _ulises: dnolen: that looks good! thanks
13:08 Kruppe: (require '(incanter core stats charts)) gives me a java.lang.ExceptionInInitializerError using cake
13:08 raek: ,(map + [1 2] [0 -3])
13:08 clojurebot: (1 -1)
13:08 dnolen: _ulises: using maps or vectors is ridiculously slow if you're doing interactive grahis and the like
13:08 _ulises: dnolen: indeed!
13:08 dnolen: s/grahis/graphics
13:09 _ulises: cantor has good perf, identical to using javax.vecmath in an immutable manner.
13:09 _ulises: awesome, will give it a whirl
13:10 I can see how this is somewhat targeted to a physics engine
13:10 dnolen: _ulises: yeah it's integrated into penumbra, the clojure opengl library
13:10 _ulises: cool
14:10 kmc: wow a bunch of haskellers showed up :D
14:10 rlb: Is the best way to access a static nested java class to just import Foo$Bar?
14:13 kmc: Chousuke, finger trees in Clojure? sweet
14:14 raek: #clojure - #haskell cross-pollination?
14:14 kmc: seems so
14:14 FUser, Kruppe, i can try to explain monads if you like, or at least give some relevant meta-advice
14:14 tensorpudding: i had been meaning to try clojure for a little while
14:15 _ulises: kmc: I wouldn't mind that :)
14:15 tensorpudding: it's not a lot like haskell so far as i can tell though
14:15 kmc: me too
14:15 tensorpudding, i think it's philosophically close to Haskell, and technologically quite different
14:16 the barrier to me getting started was setting up all the java classpath apache maven 80 mb of code to do nothing jvm that tries to take down your whole system bs
14:17 tensorpudding: i had tried setting it up before
14:17 kmc: so i had a couple false starts due to that
14:17 but eventually i got lein set up ok
14:17 tensorpudding: i was inspired to try again while cleaning up the mess that was my .emacs
14:17 kmc: and the actual clojure part of clojure is nice
14:18 tensorpudding: clojure seems to have improved a lot on the packaging front
14:19 for that matter, ELPA too
14:19 raek: Clojure and Haskell seems to have the preference for immutability in common.. (well, maybe preference is a bit of an understatement in the case of Haskell :) )
14:20 I remember the time before lein...
14:20 tensorpudding: haskell likes immutability, but also code segregation through typing, which clojure doesn't appear to have
14:20 raek: yes, Clojure tries to do as much as possible without types
14:21 Kruppe: kmc: I wouldn't mind a nice description of monads. Thanks for the offer.
14:21 raek: data representation, dynamic dispatch and hierarchies doesn't have to do anything with types
14:22 _ulises: +1 on the monads explanation :)
14:22 kmc: raek, well Haskell has mutable data structures too
14:22 raek: inc
14:22 kmc: and in fact there's some very popular haskell libs that use mutation behind the scenes, but present a pure interface
14:22 _ulises: s/+1/inc/
14:22 kmc: writing such a thing is tricky
14:22 raek: reminds me of transients
14:22 kmc: yes
14:23 Haskell's ST monad is a lot like transients -- you get to use mutation locally, and expose the result as pure value
14:23 in Haskell the type system proves that your mutation doesn't leak out
14:23 and so there's no runtime overhead, compared to less safe approaches
14:23 raek: Haskell is very high on my to-learn list
14:24 probably #1
14:24 tensorpudding: the only way to get performance on some things is mutation behind the scenes
14:24 Kruppe: raek: real world haskell did a good job for me. Pretty awesome book.
14:25 FUser: how's performance of Haskell
14:25 raek: ah, yes. I have borrowed that book from a friend. have barely started with it.
14:25 Kruppe: FUser: very good.
14:26 FUser: immutable data structures cause similar performance problems but you can use mutable data structures if necessary.
14:26 raek: ever since I was introduced to SML in the Programming Theory course I'm attending, I have been incresingly interested in learning Haskell
14:26 kmc: GHC is one of the smartest native-code compilers i know of
14:26 for any language
14:27 Chousuke: kmc: I don't know the status of Chouser's finger tree implementation though. It seemed sort of half-ready the last time I checked.
14:27 Kruppe: kmc: I miss macros when im in haskell though, template haskell feels clunky :(
14:27 kmc: yes
14:27 Template Haskell is incredibly clunky
14:27 that's one of my main complaints with Haskell these days, and it's one of my main reasons for learning Clojure
14:27 FUser: I miss types in clojure or even plain old C style structs
14:27 tensorpudding: TH is an dark, dingy failed attempt masquerading as a code extension.
14:27 kmc: metaprogramming is so powerful and so underappreciated, and Lisp is absolutely king there
14:28 Kruppe: FUser: clojure has structs
14:28 kmc: i wouldn't say TH is "failed" -- it is used in an essential role by a wide variety of useful projects. it's just a lot more pain than necessary
14:28 Chousuke: records :P
14:28 kmc: anyway, monads!
14:28 FUser: if they are implemented as maps then they aren't stucts even if they are named as such
14:28 Kruppe: kmc: rock on
14:28 kmc: my advice on learning about monads
14:29 Chousuke: FUser: records are the closest you get to C-style structs
14:29 Kruppe: FUser: they are quite fast as well
14:29 kmc: one thing to keep in mind is that "monad" is just the name of a generic API
14:29 public class List<T> implements Monad ...
14:29 and it's implemented by a lot of different unrelated things
14:29 Chousuke: They provide a maplike interface for convenience and are immutable.
14:30 kmc: people often look for a deep intuitive connection between all the monad instances
14:30 when they wouldn't expect this of just any generic API
14:30 Chousuke: (deftype is there if you need custom behaviour, but that's not recommended)
14:31 kmc: It helped me a lot to think of a monad as an "execution strategy" kind of thing :P
14:31 kmc: also, before you read (or write!) a monad tutorial, you should read: http://
14:31 FUser: (Kruppe if they are maps then they aren't fast TBH
14:31 kmc: the Haskell community has moved pretty strongly against all these analogy-based tutorials
14:31 Kruppe: FUser: i don't think they are maps under the hood.
14:31 kmc: the common wisdom now is to get comfortable with a few concrete monad types
14:31 raek: FUser: (btw, transients in clojure, a way to temporarily use a data structure as a mutable one: http://
14:31 kmc: you don't have to care as much about what the generic API means, if you focus on one type at a time
14:32 and also, to learn some of the less powerful (meaning more general) APIs first
14:32 functor and applicative functor
14:32 Kruppe: kmc: the one that really confuses me is ST, and the type errors i get when using it.
14:32 kmc: yeah, ST is pretty special
14:32 its specialness comes not from being a monad, but from the primitives that are provided for ST specifically
14:33 same for IO, STM, etc.
14:33 it's a common fallacy to learn IO first and then generalize it to all monads
14:33 when really IO is a strange atypical monad
14:33 kryft: kmc: Right, familiarize yourself with a few concrete examples and then let your brain do the generalization from there.
14:33 kmc: Kruppe, over in #haskell we'd be happy to help you with ST type errors
14:33 Kruppe: kmc: yeah that seems to always be the first monad to be described, maybe because its used all the time
14:34 kryft: kmc: I have a tendency to want to understand everything as generally as possible from the get-go, and that usually doesn't turn out so well. :)
14:34 Kruppe: kmc: thanks hehe, but its been a while since my last use of the ST monad. My projects right now are tied with C libs and python.
14:34 kmc: i like the approach of some materials (LYAH?) where they present IO early on, but give you the concrete explanation and avoid the m-word until much later
14:34 some of the people who "don't get monads" are actually not getting the idea of building IO-descriptions for later execution
14:35 which is an orthogonal idea
14:36 kryft: kmc: I take it you use both clojure and haskell?
14:36 kmc: yup
14:36 * djahandarie giggles
14:36 kmc: i've been using Haskell for about 5 years
14:36 just learning Clojure
14:37 awkorama: what do you guys use closure for?
14:37 Kruppe: awkorama: closures? or clojure?
14:38 awkorama: sorry, i meant clojure
14:38 the language for jvm
14:38 Kruppe: awkorama: just making sure. I've used it for simulations mostly. Dunno about everyone else.
14:38 tensorpudding: hmm, i have the clojure-contrib installed, but it seems (use 'clojure.contrib.monads) doesn't work
14:38 Kruppe: awkorama: its a general purpose language though
14:39 awkorama: Kruppe: sure, but what about traditional 3 layer enterprise web app?
14:39 can it handle these?
14:39 tensorpudding: and now i've got it talking about classpaths
14:39 awkorama: what about annotations and stuff? i found no info on these in clojure
14:39 Kruppe: awkorama: I don't see why not, but I haven't tried it myself.
14:40 awkorama: you have access to all of javas libs and can basically write java in clojure if you want.
14:40 zakwilson: Clojure has the ability to talk to databases and render templates or generate HTML.
14:40 raek: tensorpudding: how are you starting clojure? lein?
14:40 awkorama: zakwilson: including transaction management?
14:41 tensorpudding: I installed clojure from the Ubuntu repositories
14:41 /usr/bin/clojure -r
14:41 rlb: FUser: I belive records aren't "maps" at all, i.e. they're compiled classes where the members are fields.
14:41 tensorpudding: it's a script
14:41 rlb: (and can have optional type annotations)
14:41 FUser: that's cool
14:41 tensorpudding: does some environment mashing
14:41 FUser: I'll use precompiled version then
14:41 raek: tensorpudding: I wouldn't recommend starting clojure that way. it makes classpath management very hard.
14:42 tensorpudding: for just "give me a repl" use http://
14:42 FUser: I use clojurebox
14:42 tensorpudding: eeeenh
14:42 zakwilson: awkorama: ClojureQL appears to handle transactions. I have not used it though.
14:42 tensorpudding: i really was wanting to not have to use much in the way of hand-compiled stuff
14:42 raek: tensorpudding: for projects (i.e. code in more than one source file) use http://
14:44 the thee major clojure tools (lein, cake, irclj) have all been released since ~november 2009..
14:44 tensorpudding: hmm
14:45 kmc: i'm using leiningen even for tiny 1-file projects
14:45 it's pretty easy
14:45 tensorpudding: leiningen is like cabal?
14:45 kmc: tensorpudding, don't be that guy ;)
14:45 tensorpudding: what do you mean?
14:45 kmc: "hi #haskell, please tell me which Haskell function is like GetXW3byF97() from PHP thanks"
14:45 tensorpudding: i was asking you
14:46 kmc: thait said, leiningen is like cabal ;)
14:46 djahandarie: GetXW3byF97 only works in PHP kmc, Haskell isn't powerful enough to support it
14:46 kmc: but it can also do stuff like launch a repl
14:46 raek: it manages dependencies and the class path, among other things
14:46 SergeyD: tensorpudding: ubuntu's clojure is quite old - version 1.0.*
14:46 kmc: and it can build a jar with all your clojure libs baked in, so you can distribute it to Java zombies
14:47 tensorpudding: i've got 1.1.0 here
14:47 raek: basic workflow for a new project: lein new foo; cd foo; <editor> project.clj; lein deps; lein repl
14:47 tensorpudding: on maverick
14:47 it sounds like cabal but even better
14:47 hmm
14:47 raek: you declare dependencies in project.clj, and leiningen takes care of downloading it and putting it on the classpath
14:48 cljr is like lein, but with one global project
14:48 tensorpudding: how is the classpath handled? env mangling?
14:48 raek: it constructs it from what's in project.clj
14:49 tensorpudding: okay
14:49 does lein work with clojure 1.1.0?
14:49 raek: every project has its own lib/ directory with its versions of its dependencies
14:49 tensorpudding: oh hey, it's named after that story about the ants
14:49 raek: yes, just change [clojure "1.2.0"] to [clojure "1.1.0"] in project.clj
14:49 tensorpudding: i read that in middle school
14:49 kmc: tensorpudding, when i set up lein i did it in a way that downloaded the newest clojure automatically
14:49 rlb: I'm still not happy with what appears to be the java (and apparently inherited in clojure) practice of "just run this cmd and don't worry about where all the code comes from, who wrote it, or whether or not it's been vetted". I hope eventually that changes (i.e. wrt maven, clojars, etc.).
14:50 tensorpudding: kmc: downloaded it where?
14:50 kmc: tensorpudding, http://
14:50 raek: into ~/.m2
14:50 kmc: yeah
14:50 tensorpudding: one of the things i strongly dislike about cabal is how it defaults to putting things in the home directory
14:50 kmc: i had to apt-get install maven first
14:50 raek: it uses maven for the dependency stuff
14:50 Once: If anyone is familiar with fnparse please take a peek at http://
14:50 tensorpudding: so i don't know where things are
14:50 kmc: which in turn downloaded about 80 MB of Apache Very Serious Enterprise Java libraries
14:51 Once: problem is explained*
14:51 tensorpudding: though i guess clojure basically is just a couple jarfiles isn't it?
14:51 raek: it is.
14:51 kmc: tensorpudding, yep, there's a jar for clojure and another for clojure-contrib
14:51 and another for each 3rd-party lib you install
14:51 tensorpudding: why ~/.m2?
14:51 raek: that's why you basically have to start it with some tool
14:52 maven 2, I think
14:52 tensorpudding: what's maven?
14:52 is that java's build tool?
14:52 raek: a java build tool
14:52 yes.
14:52 tensorpudding: okay
14:52 raek: leiningen uses the dependency parts of it
14:52 tensorpudding: where are the scripts installed?
14:52 raek: which scripts?
14:53 tensorpudding: do i have to edit my $PATH?
14:53 the lein script
14:53 raek: yes
14:53 the lein script is the only script
14:56 ihodes: hey all! it's been a while. anyone here familiar with Compojure?
14:59 zakwilson: ihodes: I am a little bit.
14:59 amalloy: zakwilson: if booleans said that they would be adorable
15:00 ihodes: zakwilson: well i'm using it and Enlive to serve up some static pages on my local machine. problem is, the CSS will not load. I've tried relative and absolute paths, and opening the page myself (with the relative path) as a static file in safari displays the CSS just fine. any ideas?
15:00 zakwilson: Instead of loading the CSS, what does it do?
15:01 ihodes: the raw HTML displays, as if unstyled
15:03 LauJensen: ihodes: paste your app ?
15:03 raek: ihodes: what happens if you enter the stylesheet url in the browser?
15:04 tensorpudding: okay, so i have lein setup
15:04 how do i get emacs to use it?
15:04 raek: tensorpudding: install ELPA in emacs first
15:04 if you don't already have it
15:04 tensorpudding: i already did
15:05 to install clojure-mode
15:05 raek: ok, then install packages slime, slime-repl and clojure-mode
15:05 ihodes: (html/deftemplate index "main.html" [] )
15:05 (defroutes example
15:05 (GET "/" [] (render (index)))
15:05 raek: slime is for interacting with the clojure process
15:05 ihodes: (route/not-found "Page not found"))
15:05 LauJensen: ihodes: You also need to tell your app to serve sttic files
15:05 static
15:06 ihodes: LauJensen: what do you mean?
15:06 LauJeson: it's serving the static HTML just fine; just without the CSS
15:06 main.html is in resources/
15:06 tensorpudding: i've used slime before
15:06 LauJensen: ihodes: Nothing in what you pasted is telling Compojure to serve CSS files right? So when you template looks for /css/main.css, it wont find anything
15:06 tensorpudding: with CL
15:06 raek: ihodes: you need to tell your app that GETting /foo.css means serving the file resources/foo.clj
15:06 LauJensen: ihodes: What it does, is read main.html from disk, and serve it via a template
15:07 raek: tensorpudding: then add [swank-clojure "1.2.1"] to your project as a :dev-dependency
15:07 LauJensen: ihodes: if all your static files are in resources/, try adding the middleware (wrap-file "resources")
15:07 zakwilson: ihodes: paste the whole thing to a pastebin?
15:07 raek: do lein deps, and then lein swank
15:07 ihodes: LauJeson: do i need to include that middleware somewhere? that sounds like what I want to do
15:07 LauJenson
15:08 raek: you need both slime and slime-repl
15:08 tensorpudding: example project.clj http://
15:09 amalloy: ihodes: try LauJensen :)
15:09 raek: lein swank should start a swank server on port 4005, which you can connect to with emacs with M-x slime-connect
15:09 LauJensen: ihodes: Yea you do. I havent used Compojure in a long time, but I think its (defroutes ex (wrap-file "resources") (GET "/" ....
15:10 Also make sure you import it in your namespace declaration ring.middleware file
15:10 (thanks amalloy)
15:10 tensorpudding: oh lame
15:11 got an exception
15:11 zakwilson: Is there a currently accepted "best" set of tools to use for web stuff in Clojure?
15:12 tensorpudding: oh wait, right, need to change versions
15:12 LauJensen: zakwilson: Depends on who you ask. There's primarily Moustache and Compojure. I like Moustache a lot and its very similar to Enlive (by the same author).
15:12 tensorpudding: no, that didn't fix it
15:12 LauJensen: I also like Compojure. But not enough to use it
15:13 ihodes: LauJensen: what are the main differences? i'm just starting a project using Enlive; should I give Moustache a look first?
15:13 raek: tensorpudding: swank-clojure 1.2.1 requires clojure 1.2 I think
15:13 LauJensen: ihodes: I think you should yea. Its a very elegantly designed micro-webframework. Check out the readme on its github page.
15:13 zakwilson: I have been using Compojure, though I haven't touched the web part of the app that uses it in a while.
15:13 raek: I'm currently very happy with the Ring + Moustache + Enlive combo
15:14 tensorpudding: raek: i thought leiningen grabbed the right version of clojure for you?
15:14 ihodes: i'll give Moustache a go, then. do you know if Chris will be updating Enlive or Moustache anytime soon?
15:14 tensorpudding: the exception is related to ant, it seems
15:15 raek: leiningen picks the clojure version you tell it to
15:15 tensorpudding: it's grabbing 1.2.0, supposedly
15:15 LauJensen: ihodes: AFAIK I know there are no plans in the immediate future
15:15 raek: tensorpudding: could you paste the stack trace?
15:16 zakwilson: Moustache looks like it might be good. I hate the name though.
15:16 raek: if you mix [clojure "1.2.0"] with [clojure-contrib "1.1.0"] for example, it will not work
15:17 since clojure-contrib is ahead-of-time compiled for 1.1
15:17 and clojure doesn't guarantee binary compatibility between verisons
15:17 freakazoid: I implemented base62 in Clojure - does anyone care if you have to convert, say, a sha1 hash to a BigInteger first?
15:18 the semantics are slightly different than base64.
15:18 tensorpudding: http://
15:18 freakazoid: I could make it the same as base64 by treating a byte stream as a base 256 number *after* the decimal point.
15:18 tensorpudding: my project.clj is the same as the one you gisted
15:18 raek: tensorpudding: have you executed "lein self-install"?
15:19 tensorpudding: yes
15:20 raek: which version of lein? the one linked on the project page?
15:20 tensorpudding: from git
15:20 1.4.0-SNAPSHOT, apparently
15:20 raek: ah
15:20 you have to build the bleeding edge version with leiningen...
15:21 tensorpudding: bleeding edge version of which?
15:21 raek: of leiningen itself
15:21 http://
15:22 that one is 1.3.1
15:22 tensorpudding: is there a stable branch?
15:22 raek: yes
15:23 the installation instructions likns to that one
15:25 tensorpudding: dammit, i hate git
15:26 kryft: tensorpudding: Why?
15:26 tensorpudding: because it's like mercurial, but more confusing
15:26 but everyone uses it, and no one uses mercurial
15:28 trying to remember how to manage remote branches is one thing which i don't fully get
15:29 raek: git has a steep learning curve
15:29 tensorpudding: okay, there, i've checked out stable
15:30 raek: you only need the file I linked
15:31 everything else is .jars that it downloads automatically when you do lein self-install
15:31 tensorpudding: i know
15:32 but since i bothered checking out the lein source, and made a /usr/local/bin symlink from it for the lein script, i didn't want to hardcode my lein script
15:33 it's working now
15:34 ugh, it even created a .gitignore
15:34 i suppose clojure is a heavy git community
15:35 raek: yes, I suppose so...
15:35 tensorpudding: i'll have to edit the lein scripts to make an .hgignore instead
15:35 raek: source on github and jars on clojars seems to be *very* common
15:37 ihodes: LauJensen: i'm having trouble rending my template using Moustache now; http://
15:37 make that rendering
15:37 rplevy: what is a reasonable test of pmap vs map that would demonstrate speedup on a 4 core machine?
15:39 rlb: I'm working with maildirs from clojure -- does anyone know if it's possible to get the filename from a javax maildir message?
15:40 raek: ,(time (dorun (map (fn [_] (java.lang.Thread/sleep 20)) (range 100))))
15:40 clojurebot: "Elapsed time: 2127.817 msecs"
15:40 raek: ,(time (dorun (pmap (fn [_] (java.lang.Thread/sleep 20)) (range 100))))
15:40 clojurebot: "Elapsed time: 90.17 msecs"
15:41 raek: pmap is useful when the computation to do for each element takes long time
15:41 for very small computations, it is not recommended
15:42 rplevy: raek: thanks!
15:43 raek: np :)
15:44 SergeyD: rake: Nice clean example. But I can't figure out why the difference is 20x times on a 2-core processor :)
15:44 ihodes: anyone here know mucha botu Moustache?
15:45 raek: ihodes: you might need to use wrap-file-info too
15:46 SergeyD: raek: oh, I got it.
15:46 ihodes: raek: i'm not even there yet haha — i'm having trouble getting moustache to render my template
15:46 raek: oh, please share!
15:47 ihodes: http://
15:47 raek: thought the thread pool was 2 x no-of-processors
15:47 ihodes: you don't need to do the apply str step
15:48 LauJensen: [""] (response (templatename args))
15:48 ihodes: ^^
15:48 raek: Ring accepts sequences of strings (those that the templates return)
15:48 ah, yes. that makes sense.
15:48 ihodes: raek: just getting rid of "render" didnt work.
15:48 LauJensen: response is in which ns?
15:50 raek: ihodes: (defn ok [body] {:status 200, :headers {"Content-Type" "text/html; charset=UTF-8"}, :body body})
15:50 ^ this is what I use
15:50 [""] (fn [_] (ok (index)))
15:50 or, you could move that (fn ..) into ok
15:51 ihodes: raek: perfect!
15:51 raek: that's awesome. thanks so much!
15:51 raek: the rigth hand side of the route rule should eval to a ring handler
15:51 :)
15:51 ihodes: raek: didn't realize i needed to be passing a map back
15:51 raek: i'll read more about ring. i just started using this about 20 mins ago :\ time for some real reading now. thanks so much
15:52 raek: ihodes: this is what you need to know: http://
15:52 SergeyD: raek: Seems like the thread pool is about 30 on my computer
15:52 raek: basically, what keys are in the request and response
15:53 ihodes: raek: awesome! anything i should know about Moustache beyond what's in the little doc cgrand has?
15:53 raek: well, everything about moustache follows from syntax.html... if you know how to interpret it
15:54 SergeyD: raek: 32 actually, 16 for each core
15:54 raek: just remember that things (app [..] <here>) are threaded differently fomr things (app <here>)
15:54 Raynes: Moustache is so dead simple, the docs he provides is amazingly sufficient.
15:54 raek: *treated
15:54 Raynes: It's compojure that needs more documentation.
15:54 raek: even though thosw two cases overlap somewhat
15:55 wrapping the first case in [ ] always yields the second case
15:55 ihodes: raek: i don't know how; what should i read in order to interpret that haha—i'm familiar with grammars etc, so maybe a guide eists somewhere to introduce this to me? would be useful for my continuing to work with enlive as well
15:55 raek: ihodes: by looking at the example he provides, I think most of should be pretty clear
15:56 the grammar is nice if you want to be certain about the details
15:56 ihodes: raek: ah nevermind, this grammar makes perfect sense. and the docs look nice. i think i can handle this :)
15:56 raek: if you are familiar with grammars, then it should be pretty straight forward, I think
15:56 ihodes: raek: thanks again!
15:57 raek: yeah it's not as bad as i was expecting; pretty much a cfg haha
15:57 Raynes: $seen cemerick
15:57 sexpbot: cemerick was last seen quitting 1019 minutes ago.
15:59 Raynes: -> (/ 1019.0 60)
15:59 sexpbot: ⟹ 16.983333333333334
16:01 amalloy: Raynes: sexpbot is yours, right? if the minutes aren't helpful, why not get him to tell you hours as well?
16:01 Raynes: If one more person asks me that, I'm going to make sexpbot timestamp intelligently.
16:02 That's at least 6 people in the last two months. :p
16:02 amalloy: heh. well, i don't mind the minutes myself, but since the *author* seems to find minutes inconvenient...
16:02 raek: ,((juxt #(/ % 60) #(rem % 60)) 1019)
16:02 clojurebot: [1019/60 59]
16:02 Raynes: It's been in my invisible TODO list forever. I just haven't gotten around to it. I haven't been getting around to much lately.
16:04 amalloy: ,((juxt quot rem) 1019 60) ; raek?
16:04 clojurebot: [16 59]
16:05 amalloy: sexpbot: source?
16:05 KirinDave: Wait what?
16:05 Ah
16:05 Raynes: $whatis sexpbot
16:05 sexpbot: sexpbot = http://
16:06 raek: /facedesk
16:07 amalloy: raek: it's a good thing you're a founding member of the juxt fan club or we'd have to kick you out
16:07 raek: :-)
16:08 ihodes: Raynes: you should make sexpbot timestamp intelligently!
16:08 ;)
16:09 Raynes: He's right, you know.
16:09 Just as soon as I get a good night's sleep rather than the 4 hour increments I've been getting over the last two days.
16:09 amalloy: Raynes: i'll fork and do it myself if you want. looks pretty easy in seen.clj
16:10 Raynes: I'd love you forever.
16:10 LauJensen: Such an affectionate young man
16:12 Derander: I'm trying to implement a file watcher daemon in clojure. Currently, I have a function like this: http://
16:13 I have no idea how to do this idiomatically in clojure
16:13 Most clojure programs that I read are more of the "compute this thing" or "listen for this event", not the "do this thing indefinitely" variety
16:13 Raynes: Derander: Sure that's the right gist?
16:13 amalloy: (loop [] (do-stuff) (Thread/sleep 1000)) ; would work, dunno if it's idiomatic
16:14 er. and put a (recur) at the end, sorry
16:14 Derander: Raynes: that is definitely not, weird
16:14 Raynes: (while true ..)
16:14 Derander: http://
16:14 LauJensen: amalloy: busywaiting... I think there is a FileWatcher class actually, or maybe Im thinking of C#
16:14 Raynes: (defn x [] (while true body (recur))) = (defn x [] (recur ...))
16:14 Derander: LauJensen: When I was googling, I found some sort of FileWatcher mechanism in java 7
16:15 Raynes: LauJensen: I didn't tell him to recur in (while true ..)
16:15 Derander: alright, I'll explore recur. Thanks for the info
16:15 Raynes: amalloy told him to recur at the end of the loop.
16:15 :p
16:15 LauJensen: Raynes: Oh right, sorry for not being able to tell you two Americans apart
16:16 Derander: LauJensen: I imagined that in a snotty british accent.
16:16 Raynes: :>
16:16 Not quite.
16:16 LauJensen: Haha!
16:16 KirinDave: Derander: Write (forever fn)
16:17 Derander: Use the trampoline to recur, and make sure that it returns a future so the repl doesn't block.
16:17 I'm not sure how you'd enable killing, but it's not like that's the intent, anyways. :)
16:17 You could probably put in a kill switch.
16:17 Derander: KirinDave: I've never heard of a trampoline, I've read about futures but have no idea how to use them. I'll do some reading.
16:17 KirinDave: Then you can write (forever #'alone)
16:17 Derander: haha.
16:19 Raynes: You can use futures in places where you'd do (.start (Thread. (fn [] ..))) a lot of the time.
16:19 LauJensen: haha
16:19 Derander: Raynes: I must confess that I've never done threaded programming in clojure either. I've written a total of 62 lines in the language. This is my first project
16:20 but I'll read read read and figure it out
16:20 Raynes: Gotta start somewhere.
16:20 Derander: mmhmm. it's more approachable than haskell at least
16:20 LauJensen: Derander: 62 lines is a very good start, it corresponds to 824 lines of Scala of 1400 lines of PHP
16:20 roughly...
16:20 Raynes: LauJensen: What about Ruby
16:20 raek: (def running? (atom true)) (future (loop [] (if @running? do-stuff clean-up)))
16:20 KirinDave: LauJensen: That is math I want to see
16:20 LauJensen: Raynes: 74 ? :)
16:20 Derander: Raynes: approximately equivalent
16:20 KirinDave: Raynes: 62 lines as well, but only if you use eigenclasses.
16:21 Derander: I've been writing ruby for 3 years and never really used eigenclasses
16:21 LauJensen: KirinDave: 62 lines, but behavior will be unpredictable
16:21 Raynes: Derander: With all due respect to Haskell (I adore the language), a brick wall is more approachable at high speeds.
16:21 Derander: Raynes: yes
16:21 LauJensen: Haskell is fantastic.
16:21 KirinDave: LauJensen: 62 lines, but it each line will take 1 year to execute, and won't run if you've required ActiveRecord.
16:21 Raynes: Yes it is.
16:21 LauJensen: hehe
16:21 Derander: better: 62 lines, and 120 lines of unit testing.
16:21 KirinDave: Haskell is beautiful. There is a difference. ;)
16:21 Haha, all written in advance
16:22 LauJensen: Derander: In Ruby, even unit tests wont save you
16:22 KirinDave: With a mock framework more complex and powerful than almost any other project in the language.
16:22 Derander: LauJensen: I usually write integration tests for my ruby projects anyway
16:22 but that's because I am filled with hubris
16:23 LauJensen: I guess if you build commercial software in Ruby, you do deserve a bit of punishment
16:23 KirinDave: LauJensen: If you need unit tests to successfully complete a project, ruby is a rough road.
16:23 Some languages require champions to ride them.
16:23 You can quote me on that.
16:23 Derander: the biggest project that I've worked on in ruby is 15k lines of code
16:23 LauJensen: Ouch!
16:23 Derander: it's actually pretty nice
16:24 if the templating was in haml life would be perfect
16:24 LauJensen: Derander: nice as in, you got rich from bugfixing it ?
16:24 KirinDave: LauJensen: It's not a condemnation.
16:24 LauJensen: KirinDave: What is it then ?
16:24 KirinDave: LauJensen: It's a compliment, actually. Ruby is a superbike.
16:24 Derander: LauJensen: nah, nice as in it works pretty well and is easy to grok and work with
16:24 KirinDave: LauJensen: The problem is you rev the throttle too fast and suddenly you're SuperDave.
16:24 LauJensen: Derander: impressive, I thought that was impossible with Ruby
16:24 Derander: when I finish pushing it to 1.9.2 it'll be damn fast too
16:24 KirinDave: Hanging from your bike's handlebars, body horizontal with the acceleration.
16:25 I have more metaphors, if you need them.
16:25 Derander: ruby was my first language after php. we've had a long and tender relationship
16:25 tensorpudding: if you have a function which takes [& args], how can you mangle (arg arg) to make it work as input to the function?
16:27 wait, apply seems to be it
16:27 aav: tensorpudding: (applu myfunc args) - if i got your question right
16:27 apply
16:28 shanmu: Hi, I am trying to represent db records as clojure records - I am trying to do defrecord dynamically
16:28 tensorpudding: except doh, it's a macro, not a function
16:28 KirinDave: Derander: Same.
16:28 Except the PHP part.
16:28 Ruby was my first dynamic language that I loved.
16:28 :)
16:29 shanmu: I am using metadata to get column names as a map of string, and when I try to defrecord using them, hitting a classcastexception unable to cast String to IObj
16:30 KirinDave: So... I've been wondering.
16:30 What's the right way to make something that responds to @deref correctly?
16:30 tensorpudding: i'm really getting annoyed by how restrictive macros seem to be
16:31 KirinDave: tensorpudding: What in particular is bothering you?
16:31 tensorpudding: well, you can't apply them
16:32 or use them as functions
16:32 Chousuke: if you need to apply a macro you probably have a weird macro :/
16:32 KirinDave: tensorpudding: You have to understand, when you say (defmacro ...) what you're saying is (open up my compiler and add....)
16:32 tensorpudding: The very act of applying things is generally a runtime process.
16:32 And as such the compiler has no place
16:32 tensorpudding: i didn't decide to make or and and macros
16:32 KirinDave: Ah.
16:32 The Classic Complaint™
16:33 and and or aren't actually macros.
16:34 They're special forms.
16:34 Chousuke: well, except that they are macros :P
16:34 tensorpudding: hmm
16:34 KirinDave: Chousuke: Implementation detail ;)
16:34 Chousuke: and no they're not really special forms
16:34 tensorpudding: ,(reduce or true [true false true])
16:34 clojurebot: java.lang.Exception: Can't take value of a macro: #'clojure.core/or
16:34 Raynes: KirinDave: No, they seriously aren't special forms.
16:35 Chousuke: if is a special form, or and and are just macros
16:35 Raynes: -> (doc and)
16:35 sexpbot: ⟹ "Macro ([] [x] [x & next]); Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true."
16:35 KirinDave: Raynes: Ah, i'm thinking CL.
16:35 Raynes: Not a special form.
16:35 tensorpudding: ,(reduce (fn [x y] (or x y)) true [true false true])
16:35 KirinDave: Sorry.
16:35 clojurebot: true
16:35 KirinDave: tensorpudding: Yes
16:35 Chousuke: but the thing is that macros work with code
16:35 tensorpudding: if you wrap it in a lambda, it works
16:35 KirinDave: tensorpudding: Right, because a function is generated.
16:35 Chousuke: apply works with runtime data.
16:35 tensorpudding: i'm trying to translate something from haskell into clojure
16:35 to learn the former better
16:35 Raynes: -> (some false? [true false true])
16:35 sexpbot: ⟹ true
16:36 KirinDave: Raynes beat me to it.
16:36 Raynes: That essentially accomplishes the same thing without any macros.
16:36 amalloy: Raynes: sent a pull request for sexpbot
16:36 Raynes: amalloy: Thank you, kind sir. Your work is appreciated.
16:37 KirinDave: It must be Haskellers Try Clojure week. I've seen a ton of guys from #haskell in here lately. :D
16:38 Chousuke: heh.
16:38 KirinDave: Raynes: Reaching for something. :)
16:38 amalloy: hmmm. does github have a "merge with upstream" function or do i have to figure out how to do it from git?
16:38 Chousuke: amalloy: pull from upstream, push into your fork? :/
16:39 KirinDave: Hum
16:40 I'm working on asciidoc-ing my clojure & the web chapter for my book
16:40 This is the final code for a URL shortener. I know it works, but any failures to emulate idiomatic code would be appreciated.
16:40 (err, pointing them out, that is)
16:40 https://
16:41 And before you ask, the silly storage stubs are there so that couchdb can be hooked in later.
16:55 shanmu: Hi, Can I dynamically declare a record?
16:57 I get an error when trying (def name-list ["id" "name"]) (defrecord org name-list)
16:58 ,(do (def name-list ["id" "name"]) (defrecord org name-list))
16:58 clojurebot: DENIED
16:58 chouser: you'll need to use eval or something
17:01 amalloy: or a macro. i think i gisted something like this a while back, let me find it
17:04 well, i guess it's not that close. but the general idea is (defmacro record-from-strings [fields] `(defrecord ~@(map symbol fields))) (record-from-strings ["org" "id" "name"])
17:04 kjeldahl: http://
17:10 shanmu: amalloy, kjeldahl: thanks!
17:23 Raynes: $seen cemerick
17:23 sexpbot: cemerick was last seen quitting 18 hours and 24 minutes ago.
17:23 Raynes: amalloy_: My love. <3
17:40 amalloy_: Raynes: woo!
17:40 amalloy: ~seen cemerick
17:40 clojurebot: no, I have not seen cemerick
17:40 amalloy: heh. win for sexpbot
17:41 Raynes: Maybe he stores the info in memory. If so, a restart would wipe it (which is a possibility).
17:42 KirinDave: Oh I hope he doesn't have a data store for seen
17:42 Raynes: A seen database can get really huge.
17:43 sexpbot using mongodb for seen (among a lot of other things).
17:44 amalloy: clojurebot uses (ref {}) to store the seen list
17:44 Raynes: Yeah, in memory. It probably just restarted since cemerick left.
17:44 amalloy: yeah
17:59 shanmu: I had to use (defmacro record-from-strings [fields] `(defrecord ~@(map symbol fields))) (record-from-strings ["org" "id" "name"]), does that look alright?
18:00 oops! wrong paste
18:00 I had to use (defmacro record-from-strings [rec-name fields] `(defrecord ~(symbol rec-name ) ~(map symbol fields))) (record-from-strings "org" ["id" "name"])
18:01 does that look alright?
18:01 amalloy: yeah, looks reasonable. i forgot it doesn't want the @ there
18:02 shanmu: amalloy: thanks a lot! this solves my problem nicely
18:03 amalloy: shanmu: just keep in mind it will only work with literals - you can't do like (def x ["foo"]) (record-from-strings "org" x)
18:04 shanmu: oh.. ok... I was planning to do defrecords for table columns in a db (obtained via c.c.sql)
18:05 amalloy: macros can't have access to runtime data. they happen before runtime
18:05 but there is a way to do it if your db info will be known at compile time
18:05 shanmu: amalloy: thanks! is there any way to do it? the db info would be available during compile time...
18:06 amalloy: shanmu: see http://
18:06 shanmu: amalloy: thanks! looking thorugh
18:17 clojurebot: The Tao, considered as the Rabbit, began.
18:40 amalloy: shanmu: that help solve your problem?
18:42 shanmu: amalloy: no, not exactly... the problem is I donot know my macros... reading up on them now
18:42 I tried (defmacro record-from-strings [fields] `(defrecord ~@(map symbol fields))) (record-from-strings ["org" "id" "name"])
18:42 oops!
18:42 I tried (defn create-record [rec-name fields] `(defrecord ~(symbol rec-name) ~(map symbol fields)))
18:42 then (defmacro make-record [rec-name fields] `(~(create-record rec-name fields)))
18:43 but (let [n "recName" f ["f1" "f2"]] (make-record n f))
18:43 errors with Don't know how to create ISeq from: clojure.lang.Symbol
18:44 amalloy: shanmu: (let [blah] (stuff)): if stuff is a macro, it can't access the contents of blah because that's happening at runtime
18:45 the way i would solve a problem like yours is to define (define-sql-records) as a macro, which calls (lookup-sql-tables), a function
18:46 define-sql-records takes no arguments, or maybe one that's the name of the db to use or something; lookup-sql-tables queries the database and returns some code, which define-sql-records splices into its return value so that it's available at compile time
18:49 shanmu: amalloy|gone: thanks for the advice! will try something
18:51 raek: making some Active Record-like system?
19:07 FUser: what's the difference between :while and :when in macro "for"?
19:07 ,(for [x (range 15) :when (> x 5)] x)
19:07 clojurebot: (6 7 8 9 10 11 12 13 14)
19:08 FUser: ,(for [x (range 15) :while (> x 5)] x)
19:08 clojurebot: ()
19:09 FUser: ,(for [x (range 10) :when (> x 5) :while (> x 5)] x )
19:09 clojurebot: (6 7 8 9)
19:10 FUser: ,(for [x (range 15) :when (even? x) :while (> x 5)] x)
19:10 clojurebot: ()
19:10 shanmu: raek: not a full fledged activerecord like system
19:10 FUser: im confused
19:13 Lajla: FUser, obviously looking at this, while stops after the first false, and when continues.
19:13 But just doesn't put it into the list if it's false.
19:14 FUser: but check this out
19:15 ,(for [x (range 15) y (range 10) :when (even? x) :while (> x 5)] x)
19:15 clojurebot: (6 6 6 6 6 6 6 6 6 6 8 8 8 8 8 8 8 8 8 8 10 10 10 10 10 10 10 10 10 10 12 12 12 12 12 12 12 12 12 12 14 14 14 14 14 14 14 14 14 14)
19:15 FUser: identical case as when it returns empty list
19:15 except it has an additional variable that isn't used
19:15 and it suddenly behaves totally differently
19:16 Lajla: I have no idea how that works no.
19:16 Could even be a bug.
19:16 Ask raek, he is omnipotent.
19:17 FUser: :D
19:17 you mean omniscient surely
19:19 Lajla: Well, if you can do all things, that includes knowing all things, or at least answering all quaestions.
19:27 FUser: :)
19:37 chouser: :when and :while control the previously specified loop
19:59 shanmu: amalloy: its working now!!
19:59 (defmacro record-from-table [table-name]
19:59 `(defrecord ~(symbol table-name) ~(map symbol (get-columns-map table-name))))
19:59 (defn get-columns-map [table-name]
19:59 (sql/with-connection db
19:59 (map #(:column_name %1)
19:59 (resultset-seq (-> (sql/connection)
19:59 (.getMetaData)
19:59 (.getColumns nil nil table-name nil))))))
19:59 sorry, pasting it
20:00 amalloy: shanmu: great! yeah, i was about to say paste
20:01 shanmu: http://
20:01 amalloy: thanks for the guidance! just like you said, a macro which calls a function to get column list
20:05 KirinDave: shanmu: #(:sym %1)
20:05 shanmu: Or
20:05 ,(map :col [{:col 1}])
20:05 clojurebot: (1)
20:05 zakwilson: If I want clojure-contrib 1.3 from Leiningen, where do I find appropriate version strings? I see that it has been split in to core and [other stuff] but [org.clojure/clojure/contrib/core "1.3.0-alpha1"] seems like it should work (and doesn't)
20:05 KirinDave: shanmu: Understand?
20:06 duck1123: I have a bunch of files I'm reading for my tests (lazytest) and
20:06 previously I had them in the root of my application, but I want to
20:06 move them to src/test/resources (using maven) is slurp the best way to
20:06 contiue reading them, and if so, should I specify the path in the src
20:06 directory, or is there a better way?
20:06 ahh, sory about the multi-line
20:08 dysinger: duck you could find the files in your classpath if you put them in maven's src/test/resources dir
20:09 shanmu: KirinDave: sorry, didnot understand that...
20:10 KirinDave: shanmu: You don't need the #().
20:11 shanmu: :keywords are invokable.
20:11 shanmu: KirinDave: got it! sorry, bad habit of adding an anon func as soon as I type map!
20:11 KirinDave: shanmu: Same. :)
20:12 ninjudd: zakwilson: [org.clojure.contrib/complete "1.3.0-SNAPSHOT"] should work
20:12 shanmu: KirinDave: thanks! will remember that keywords are invokable... :)
20:13 zakwilson: ninjudd: looks good so far. Thanks.
20:13 duck1123: dysinger: right, my question was what is the best way to now read those files from the classpath. (slurp "entry.xml") is no longer working.
20:13 clojurebot: Alice felt a violent blow underneath her chin - it had struck her foot! She was walking with nameless simplicity.
20:14 duck1123: I know there's an easy way to do it, but I can't remember it, and google is failing me
20:14 ninjudd: zakwilson: no problem. or you can just add the specific libs from contrib you want. e.g. [org.clojure.contrib/find-namespaces "1.3.0-SNAPSHOT"]
20:16 zakwilson: ninjudd: I'll start with everything, and get specific if I decide by uberjar is too uber.
20:19 ninjudd: zakwilson: that works. though if you are writing a library that you're going to put on clojars, it is probably best to have specific deps. looks like complete pulls in 61 jars!
20:20 zakwilson: I am not writing a library, and I am not putting what I'm writing on clojars.
20:20 Sorry. Super proprietary. Going to make me a zillionare. Etc.
20:21 ninjudd: zakwilson: i see. well then you'll be able to afford all 61 jars ;)
20:21 duck1123: I need to go through my projects and go down to the specific contribs I need
20:23 zakwilson: I'll even be able to afford sixty-TWO jars!
20:26 shanmu: thanks a lot people! #clojure rocks, as always....
20:26 dysinger: duck1123: (-> (Thread/currentThread) (.getContextClassLoader) (.getResourceAsStream "x/y/z.txt") (slurp))
20:27 (slurps file from classpath)
20:29 duck1123: dysinger: ok, so maybe it wasn't as easy as I thought. Thanks a lot
20:30 amalloy: dysinger: the parens aren't necessary for one-arg functions in ->, eg
20:30 ,(-> 1 inc inc inc)
20:30 clojurebot: 4
20:30 duck1123: you wouldn't by any chance to know how to get lazytest failures to fail the build?
20:31 amalloy: (whether that makes things more readable is down to taste, of course)
20:34 dysinger: duck1123: it'd be pretty easy to make a fn to slurp-from-cp
20:34 and just use that instead of plain slurp
20:35 duck1123: just did. looking for instances of slurp atm. :)
20:35 dysinger: easy peasy
20:39 duck1123: dysinger: what are you using for code coverage with maven atm?
20:58 dysinger: duck1123: I'm using lein mostly
21:25 cemerick: duck1123: code coverage is orthogonal to build tooling
21:25 I presume something like Clover would get the job done, though it'd be a bit of a mess insofar as it's not clojure-aware.
21:26 Presumably there's some code coverage tools that have plugin architectures amenable to informing them about non-Java languages.
21:43 jstirrell`: hi
21:44 what's the easiest way to get a new collection of, say, every third item from an old collection?
21:45 cemerick: ,(take-nth 3 (range 20))
21:45 clojurebot: (0 3 6 9 12 15 18)
21:45 cemerick: jstirrell`: ^^
21:45 jstirrell`: sweet thanks!
22:04 Raynes: cemerick: Evening.
22:05 cemerick: Raynes: howdy
22:05 Raynes: How was your weekend?
22:05 cemerick: Very busy. Working on the book at the moment.
22:05 Raynes: Ooh, goody.
22:06 cemerick: Rewriting stuff this early on is surely a bad sign. :-/
22:06 Raynes: Only means you're a perfectionist. When kept in check, that can be a very valuable asset.
22:06 cemerick: heh, indeed
22:06 Otherwise, it was a perfect autumn day.
22:07 Raynes: Indeed. It's been a beautiful week here. Nice and cool.
22:07 moogatronic: +1 for perfect autumn day.
22:07 cemerick: Warmish but breezy, mostly sunny, tons of fantastic treescapes.
22:07 Breakfast out, then a small hike, then a visit to Old Deerfield.
22:08 * cemerick is New England-y.
22:08 Raynes: Well, I'm off to bed. I'll talk to you in the morning. I should be up, so just ping me whenever you get around to calling expedia (DOT COOOOOOOOM).
22:08 moogatronic: we're a little moisture starved in mid-southern indiana , burn ban in effect for most counties, going to impact my up-coming backpacking trip
22:08 cemerick: Raynes: Figure after 8:30 anyway
22:08 Raynes: Right, I should be up or nearly up.
22:09 Goodnight, fair #clojure.
22:09 moogatronic: goodnight. =)
22:13 clojurebot: "You're nothing but a pack of cards, after all? Can you play croquet with the bitterest grief; and soldiers under sentence of execution?"
22:14 cemerick: wow, that was random
22:14 maravillas: clojurebot must be reading lewis carroll lately
22:16 curious...both that quote and the one at 8:12 are from http://
22:17 "Text built by mashing up Alice's Adventures in Wonderland with the Tao Te Ching. Created with Python & Markov chains."
22:17 cemerick: very random
22:36 Lajla: So how are things going in noTCOland now?
22:38 cemerick: same as they always have; see recur
22:38 or trampoline
22:38 Lajla: I know them.
22:39 I'm just feeling like that remark.
22:39 I am actually the second best clojure programmer in the world, second only to the microsoft Chief Software Architect.
22:40 chouser: cemerick: hi
22:41 cemerick: chouser: bonsoir
22:41 Lajla: Terve
22:41 chouser: I feel like I've been gone
22:42 cemerick: There was certainly a disturbance in the Force.
22:43 chouser: heh
22:48 wow, vars are suddenly in flux?
22:48 cemerick: indeed
22:51 chouser: someone asked me at strangeloop, "what's next"
22:51 cemerick: "how much time do you have?"
22:52 chouser: which of course is a common question. and I'm always tempted to guess
22:53 I said "I don't know" and "maybe pods" ...not realizing dynamic binding and future/send had *already* *changed*
22:54 cemerick: mmm, the future/send change is pretty friggin' huge
22:54 That "fixes" vars and binding quite a lot.
22:59 coldhead: thanks clojurebot
23:02 chouser: yep
23:45 cemerick: This seems like an unfortunate asymmetry:
23:45 ,(-> ::foo str keyword)
23:45 clojurebot: ::sandbox/foo
23:45 cemerick: vs.
23:45 ,(-> 'foo str symbol)
23:45 clojurebot: foo
23:47 cemerick: Meaning, namespaced keywords aren't trivially string round-trippable.
23:56 chouser: ,(-> :foo str keyword)
23:56 clojurebot: ::foo
23:56 chouser: ,(-> `foo str symbol)
23:56 clojurebot: sandbox/foo
23:57 chouser: ,(-> :foo name keyword)
23:57 clojurebot: :foo
23:57 chouser: cemerick: I think I'm missing your point
23:57 cemerick: I'm tired; perhaps my point is foolish.
23:58 I think one should be able to do (-> ::foo str keyword) and get the proper keyword out.
23:58 As things stand, you have to munge the string before keywordizing it.
23:58 hiredman: ,(pr-str ::foo)
23:58 clojurebot: ":sandbox/foo"
23:59 cemerick: sure
23:59 my point was about asymmetry, not about not being able to do the thing
23:59 chouser: ah, I see what you're saying
23:59 pr-str is the inverse of eval, though