#clojure logs

2010-10-17

00:17LauJensenGood morning guys
00:37amalloyhi LauJensen
04:05notsonerdysunnywhy should " (def (symbol "hello") 10) " work .. does anybody have an insight into this?
04:05notsonerdysunnywhy shouldn;t " (def (symbol "hello") 10) " work .. does anybody have an insight into this?
04:06amalloynotsonerdysunny: def requires a symbol literal
04:07amalloy,[(symbol "hello") 'hello]
04:07clojurebot[hello hello]
04:08amalloy(symbol "hello") is the same as 'hello, and it seems pretty reasonable that (def 'hello 10) shouldn't work, right?
04:10LauJensenuser> `(def (symbol "hello") 5)
04:10LauJensen(def (clojure.core/symbol "hello") 5)
04:10LauJensenuser> `(def 'hello 5)
04:10LauJensen(def (quote user/hello) 5)
04:10LauJensen
04:11amalloyyes?
04:11LauJensenIn either case its clear they wont work, since neither are a literal symbol
04:11notsonerdysunnyamalloy: hmm...
04:11notsonerdysunnyso we cannot programmatically generate the symbols..
04:12amalloyyou can, but you have to do it in a macro
04:13notsonerdysunnyamalloy: 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
04:13notsonerdysunnyhave you used it before?
04:15amalloyi 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
04:15notsonerdysunnyok sorry for misrepresenting you.. :)
04:15amalloyif you really want to create code based on the execution of code, why not just have your clojure program generate a new .clj file
04:15notsonerdysunnybut I was not able to figure out how to use it in any case ..
04:15amalloyand ship that to the user
04:17notsonerdysunny:) good point .. but was hoping I needn't have to do that ..
04:18notsonerdysunnyI think we are trying to make an argument like people using languages who don't have macros would .. :)
04:18amalloyif 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
04:18notsonerdysunnyI would do to Ahead Of Time compilation
04:19notsonerdysunnyso all the macros would be expanded in the resultant code ..
04:19notsonerdysunnywell atleast that was the theory based on which I was working ...
04:20amalloyright, i always forget AOT is an option
04:26amalloyokay. 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
04:27amalloynotsonerdysunny: http://gist.github.com/630662
04:29amalloyhere ask-mathematica is a function, which helps solve-pde generate code
04:31notsonerdysunnythanks amalloy .. Let me try to use your idea and come up with something..
04:31notsonerdysunny:)
04:32amalloythe 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
04:34amalloyfwiw, (solve-pde x y) really does macroexpand to (+ y (* x 10)) there - the reference to ask-mathematica has vanished
04:50notsonerdysunny:) ... 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 .. :)
04:57amalloynotsonerdysunny: well, for (def) you don't need such a macro
04:59amalloy(intern (symbol "test") 'size 10)
04:59amalloycan't do that in clojurebot obviously, but it should work at your repl
05:00amalloyanyway, i'm off to bed. good luck, i hope to see how it all turns out
05:36_ulisesmorning all
07:22serabehi
07:23raekhello
08:02serabejust released rinzelight, an image library for clojure, http://github.com/Serabe/rinzelight
09:58shanmuHi, What options would I have if I want to run a long running process/daemon in clojure (which has to do some periodic activity)?
09:59shanmumy thought is to have a compojure app, to which I do wget from cron...
10:00shanmuor another option is to write a quartz job but I am not sure how to integrate in clojure...
10:02shanmuor yet another option would be invoke the cljoure script/compiled class direct from shell script/cron but pay jvm startup cost everytime
10:13LauJensenshanmu: 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:15shanmuLauJensen: thanks for the suggestion - I had missed future... (i am still a n00b :))
10:28BahmanHi all!
10:53FUser,(range 1000)
10:53clojurebot(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:53FUser:)
11:16FUser,(counted? (seq [2 33]))
11:16clojurebotfalse
11:16FUser,(counted? (seq '(2 33)))
11:16clojurebottrue
11:17FUserwat?
11:17FUsermakes no sense
11:17jarpiain,(doc counted?)
11:17clojurebot"([coll]); Returns true if coll implements count in constant time"
11:17ChousukeFUser: they're different types
11:18FUserthey are both sequences
11:18Chousuke,(let [x '(2 3)] (identical? x (seq x)))
11:18clojurebottrue
11:18Chousukethat's the reason
11:18FUserlook
11:18FUser,(counted? [2 32])
11:18clojurebottrue
11:18FUser,(counted? '(23 2))
11:18clojurebottrue
11:19MayDaniel_,[(type (seq [1 2])) (type (seq '(1 2))]
11:19clojurebotUnmatched delimiter: ]
11:19FUser,(counted? (seq [2 23]))
11:19clojurebotfalse
11:19raekseqs are not guaranteed to be counted
11:19FUserthese are all expected
11:19FUseryeah
11:19raekbut PersistentLists are their own seqs
11:19FUserbut why are seqences made out lists counted
11:19raekso (seq a-list) happens to be counted
11:19FUseralso maps
11:19tensorpuddingwhere's a good place to get a tutorial to clojure?
11:19ChousukeFUser: because lists don't need to be made into sequences.
11:20ChousukeFUser: they are sequences already
11:20raek(let [l (list 1 2 3)] (identical? l (seq l)))
11:20raek,(let [l (list 1 2 3)] (identical? l (seq l)))
11:20clojurebottrue
11:20FUser,(counted? (seq {3 22}))
11:20clojurebottrue
11:20ChousukeI suppose it might be an oversight, though.
11:21FUserwhats the diff between seq function and sequence function?
11:22FUser,(seq nil)
11:22clojurebotnil
11:22FUser,(sequence nil)
11:22clojurebot()
11:22FUseroh
11:23raektensorpudding: this covers the basics http://en.wikibooks.org/wiki/Learning_Clojure
11:24FUsersequence is also faster it seems
11:25FUser(time (do (sequence (range 1000000000)) nil))
11:25raekI have seen 'sequence' before...
11:25FUser,(time (do (sequence (range 100000000)) nil))
11:25clojurebot"Elapsed time: 0.135 msecs"
11:26FUser,(time (do (seq (range 100000000)) nil))
11:26clojurebot"Elapsed time: 0.212 msecs"
11:26raekseq is the one that is usually used to turn a collection into a sequence
11:27_ulises,(doc sequence)
11:27clojurebot"([coll]); Coerces coll to a (possibly empty) sequence, if it is not already one. Will not force a lazy seq. (sequence nil) yields ()"
11:28tensorpuddingwhat does clojure call lambda?
11:28Kruppefn
11:28Kruppe(fn [] (print "hi"))
11:28tensorpuddingokay
11:29tensorpuddingclojure looks pretty good for being built on java, i suppose
11:30Kruppetensorpudding: It's pretty nice, id say its more built on the jvm than built on java though.
11:32raekthere are plans to reimplement the compiler (which is now written in Java) in Clojure
11:32FUser:D
11:33FUserthe only problem is that clojure uses a shitton of reflection and allocated billions of objects per second
11:34raekreflection is only used of java methods calls
11:35raekand can be avoided completely, if the type is known (e.g. through type hints)
11:35Raynestensorpudding: Ooh, you're the second prominent #haskell user in here in the last week.
11:35tensorpuddingheh
11:35Rayneskmc is here too. <3
11:36FUserraek: so if I am using clojure Fns, I am not using reflection?
11:36raekFUser: exactly.
11:37raekclojure fns are always take Objects and return Objects
11:37FUserallocations are still a problem though
11:37raekyes
11:37FUserthey did some testing
11:37Raynesraek: All your clojure fns are belong to us.
11:37raekbut the HotSpot JVM is pretty good at it
11:38FUsercompared 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:38raekbut having immutable data structures kinda requires much allocation
11:38FUserarray list still faster unless the list size is over a million
11:39FUsersimply the allocations for the linked list objects
11:39FUserare too much
11:39raekI guess that the mutable data structures are simpler and faster, but they still have the problems Clojure is trying to solve
11:39FUserand that's java mutable linked list, I can only imagine how badly the clojures quasiconstant time inserts must be
11:40ChousukeDon't imagine, measure :)
11:40FUserI'm just sayin'...O(n) notation doesn't say shit :P
11:40raekneither PersistentVector nor PersistentList is the correct data structure for doing fast inserts to the middle
11:40raekI have heard that chouser is working on some data structure that has good performance for that
11:41ChousukeFinger trees
11:41wakeupstickybest clojure tutorial for the non-java programmer (i'm familiar with lisp and haskell)?
11:42FUsertransient vectors are probably fast
11:43ChousukeThey'll still be slow for inserts in the middle
11:43FUserif they are actually java ArrayList then they are fast
11:43raekwakeupsticky: these were what I got started with. YMMV. http://clojure.blip.tv/posts?view=archive&amp;nsfw=dc
11:43Chousukethey aren't.
11:43Chousukethey can't be. :/
11:44Chousukebecause transient->non-transient and vice versa must be a constant time operation
11:44FUserok then I'll just use (.java.util.ArrayList) :P
11:45Chousukeif you're really doing lots of inserts, maybe :P
11:45FUserfastest access too
11:45Chousukebut realise that you're giving up safety and ease of use
11:45FUserI know
11:46FUserI can't cope with having 300 times slower apps
11:46ChousukeI'm not sure about that.
11:47ChousukeFor a whole bunch of apps Clojure's vectors won't be a bottleneck
11:47ChousukeDon't give up on them until you encounter a real performance problem.
11:48ChousukeFast programs are nice, but working ones are nicer :P
11:48FUserclojure has a bunch of weird performance issues
11:48ChousukeLike?
11:49FUser(if (> its 0)
11:49FUser
11:49FUsercompared to
11:49ChousukeI can't think of anything that's particularly weird. There is room for improvement though.
11:49FUser(if (> its (int 0)))
11:49FUserguess the speed difference
11:49ChousukeFUser: in the former case, there is boxing
11:49FUsernot only that
11:49Chousukeso of course it's slower
11:50FUserbut there's also lookup in > function
11:50FUserfor type
11:50Chousukeyeah, because it's polymorphic :p
11:50FUsersecond version runs 9 times faster
11:50Chousuke(numerical performance is kind of the focus of 1.3 btw)
11:51ChousukeSo expect things to improve
11:51FUserthat kind of performance differences for such a simple change in code is unacceptable
11:51ChousukeNo they are not
11:51Chousukeit's not a simple change,
11:51Chousukeit does a lot.
11:51FUserI'll spend time saved in development doing profiling afterwards
11:51FUserwell technically yes
11:52FUserbut I can't see why I'd have to cast a constant 0, why can't compiler do that for me
11:52ChousukeBecause the compiler is not very good yet.
11:52KruppeFUser: its a new language, 1.3 will improve that particular problem
11:52FUser:)
11:52ChousukeIt doesn't try to be, either; there are bigger things to do first.
11:52KruppeFUser: for now its not perfect, thats for sure.
11:54FUsersorry 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:55FUserit all becomes just a whole bunch of arcana
11:55FUserand code gets ugly fast
11:56KruppeFUser: I sympathize, I wrote a fairly complicated simulation in clojure and it was a real pain to work out all the performance kinks.
11:56KruppeFUser: the simulation was easy to write though.
11:59FUseryeah 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:00FUserand that simple query becomes ugly unreadable and ununderstandeable to any other programmer, unless they are in the know of these hacks
12:01KruppeFUser: Its performance definitely isn't a non issue, if its not good enough right now you could always use something else.
12:02KruppeFUser: Or write the bottlenecks in java since you're already on the jvm.
12:02FUserwell, I am not using it professionally so it's not much of an issue
12:02KruppeFUser: oh, well in that case. Readability isn't such a huuuuuuuge hit.
12:02ChousukeOr you could go and improve the compiler, and be everyone's hero :)
12:02FUser:D
12:02KruppeFUser: if you don't need concurrency semantics you could always use common lisp.
12:03KruppeFUser: I find it easier to write fast code in CL atm, but i suspect that will change soon enough.
12:03FUserCL?
12:03KruppeFUser: common lisp
12:03FUseroh
12:03FUsernever used lisp
12:03FUsermostly java
12:03ChousukeIn Clojure's case the compiler is destined to be rewritten in Clojure someday though.
12:04FUsermy main java issues are already solved by C#
12:04FUserso that would be my perfect language
12:04KruppeChousuke: yeah I have confidence that rich is very concerned with performance.
12:04FUserbut I have job requirement to use java so I'm stuck with it
12:04ChousukeYeah.
12:04FUserI'm taking up clojure purely for the learning experience
12:05FUsersince it's my first dynamically typed functional language
12:06FUserI'm fresh out of ideas what to make in it
12:06KruppeFUser: It's a general purpose language, could make anything you want in it.
12:06FUserthat'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:06KruppeFUser: performance issues aside I suppose.
12:07FUserI know :)
12:07KruppeFUser: could just pick an open source project and contribute
12:07FUserhm....
12:07FUsernot a bad idea
12:07KruppeFUser: dunno if there are any clojure open source projects you would want to contribute to. But you could look.
12:09FUserit's funny how I'm the only guy at the office who programs and reads about programming in his spare time
12:09FUserpeople call me an academic
12:11KruppeFUser: those people are probably just lazy and are surprised at your initiative
12:11KruppeFUser: probably burnt out on coding java
12:12FUserI'm amazed. They have no drive to better themselves at their chosen profession
12:12FUsereven though they are terrible at java
12:12FUserI don't need to improve my java, I'm one of the best in the firm
12:13KruppeFUser: working at large companies can ruin you desire for self improvement
12:13FUserI see shit daily that would bring tears to your eyes
12:13FUser40 employees
12:13KruppeFUser: oh
12:13FUserevery non-member function in the project is in a class named Utils
12:14FUserevery constant in the project is in a class named Constants
12:14FUsershit like that
12:14KruppeFUser: that sounds pretty tame, but this is also a little offtopic now
12:14FUserclass structure is 1 level deep at most, there are no interfaces defined
12:14FUserok
12:15FUserbasically cobol programmers trying to do OO
12:15FUserOOP
12:15KruppeFUser: it sounds like that structure was just decided by a manager
12:15FUsernope, by actual programmers with 10 year more experience than me
12:16KruppeFUser: I guess their minds have been somewhat tainted by working in cobol all the time.
12:16FUserno kidding :D
12:16KruppeFUser: teach em how it's done then, you then will really be the academic.
12:16FUserthat's why I'm learning clojure, not to get completely trapped in Java mindset
12:17KruppeFUser: 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:17KruppeFUser: don't get your heart set on writing haskell for money or anything though.
12:18FUsertrue
12:18KruppeFUser: clojure is a nice intermediate step though, you get to play around with macros and FP.
12:18FUseryeah
12:18KruppeFUser: not to mention really slick concurrency.
12:18FUserhell I'm hoping for C# someday
12:18FUserat least it has function pointers
12:19KruppeFUser: not a huge fan, but I don't enjoy programming for windows so.
12:19raekthere is Clojure CLR...
12:19FUserimplementing interfaces for a simple filter function in java is maddening
12:19FUserC# delegates neatly cover a lot of this
12:20FUserraek I'm not pining for CLR
12:20FUserjust 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:21KruppeFUser: I don't doubt it.
12:21FUserclojure has all of it also, of course
12:21FUserbut it's less commercially popular, so I'm not gonna get a job with it
12:21KruppeFUser: Hey boss, can I use this java library called clojure?
12:22FUserhehe, you know
12:22FUserI thought about it :D
12:22KruppeFUser: actually that would never fly.
12:22KruppeFUser: and it would be pretty irrisponsible of you to decieve your boss like that.
12:22FUserI know I know :D
12:22KruppeFUser: and your code would be unmaintainable by anyone else there sadly
12:22KruppeFUser: if only it were that easy
12:22FUseryes that is the main problem
12:23FUserI leave company now they can't fix anything in that code,because nobody else knows clojure
12:23KruppeFUser: I tried convincing my boss to use svn or git for our software projects
12:23FUsersvn ? version control system?
12:23KruppeFUser: even that was difficult
12:23KruppeFUser: yeah, we weren't using any version control for the longest time
12:23KruppeFUser: it was pretty depressing
12:23FUserwow
12:24FUserthat's pretty bad
12:24KruppeFUser: I don't work there anymore.
12:24FUserI'm trying to tell the boss that we need design documentation
12:25KruppeFUser: really? That I find really unusual.
12:25FUserwe are making none since the customers only pay for requirements documentation
12:25KruppeFUser: i need to practically document my bathroom schedule
12:25FUserso bascially each programmer is free to design his parts of the program however he wants
12:25FUseryou only have architectural restrictions
12:26FUseryou have to use this DB, that XML Serializer library, that web service etc
12:26FUserso project parts vary wildly in quality depending on who from our firm is working on them
12:27KruppeFUser: that's unfortunate.
12:27FUseronly for our customers :DDDDDD
12:27FUsersee this is how it kills you...I stopped giving a fuc
12:29KruppeFUser: Yeah, that will happen if you're not careful.
12:29FUserI 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:29FUsercan't be arsed to do it again
12:30KruppeFUser: that sucks.
12:31kryftC# templates? Are those anything like C++ templates?
12:32FUsernot sure
12:32FUserI just know that Java Generics are much like C# templates
12:32ChousukeNothing like C++ templates then :/
12:32FUserbut C# templates are proper and Java Generics are just stupid compiler hack with limited functionality due to havign to be backwards compatible
12:33KruppeFUser: they work alright though. It could be worse.
12:33FUserI've run into their limitations several times before
12:33KruppeFUser: language warts like that happen over time.
12:34KruppeFUser: yeahhhh. Sometimes java just makes things difficult.
12:34FUserIt could be better if Sun wasn't being so stubborn with their compatiblity
12:34raekI find it interesting that the C++ template system is Turing complete...
12:35FUseryou can't run java 5 classes on java 1.4 anyway so why bother
12:35KruppeFUser: its not stubbornness necessarily.
12:35KruppeFUser: They don't want to scare anyone away.
12:35KruppeFUser: in general they have done a real good job keeping java THE language for business.
12:36FUserhere an example: public void <E> someMethod(E param) {
12:36KruppeFUser: as a result it may not be the nicest language to work with but its still extremely popular.
12:36FUserE.class doesn't work, E.getClass() doesn't work
12:36KruppeFUser: yeah thats one of those warts right there.
12:36SergeyDHi, 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://clojure.org/cheatsheet)
12:37FUserhttp://clojuredocs.org/quickref/Clojure%20Core
12:40raekSergeyD: I have the .tex file. Can you compile that?
12:40SergeyDFUser: thanks for another source
12:41SergeyDraek: yes, I'll figure out
12:41FUserwhat's a monad
12:42raekSergeyD: http://raek.se/cheat-sheet/
12:42kryftFUser: http://intensivesystems.net/tutorials/monads_101.html
12:42kryftFUser: (I don't really know myself, but I plan to read that at some point and find out. ;)
12:43SergeyDraek: thanks!
12:43Kruppekryft: I've used haskell for a few personal projects, and I still can't really describe what monads are in words.
12:52raekcompiled PDFs are now up too http://raek.se/cheat-sheet/
12:53SergeyDraek: thanks :)
13:03_ulisescan anybody recommend a good library for performing 2d vector operations?
13:03_ulisesI've sort of handcrafted my own but I'm sure that there are better options out there (google wasn't my friend :(
13:04esj_ulises: I think Incanter wraps Colt
13:04_ulisesoh, right
13:04esjunsure how far they went
13:04_ulisesI am looking for something a bit more lightweight though :)
13:05_ulises,(doc max)
13:05clojurebot"([x] [x y] [x y & more]); Returns the greatest of the nums."
13:05KruppeAnyone else having trouble getting incanter and cake to work together?
13:05esj_ulises: oh, in that case the seq functions are your friend
13:06_ulisesseq? how? kind of like (apply map + points) where points is ([x y] [x y]...) ?
13:06raek,(merge-with + {:x 1, :y 2} {:x 0, :y -3})
13:06clojurebot{:x 1, :y -1}
13:06_ulisesooh
13:06_ulisesnice!
13:06raeknot a seq function, but...
13:06_ulisesno no, that is awesome
13:07dnolen_ulises: cantor is pretty good if you have simple needs, http://github.com/ztellman/cantor
13:07_ulisesnow I have to figure out how to use the same style for euclidean distance and the other fns...
13:08esjdnolen: thanks for the pointer - that looks pretty useful
13:08_ulisesdnolen: that looks good! thanks
13:08Kruppe(require '(incanter core stats charts)) gives me a java.lang.ExceptionInInitializerError using cake
13:08Kruppe
13:08raek,(map + [1 2] [0 -3])
13:08clojurebot(1 -1)
13:08dnolen_ulises: using maps or vectors is ridiculously slow if you're doing interactive grahis and the like
13:08_ulisesdnolen: indeed!
13:08dnolens/grahis/graphics
13:09dnolen_ulises: cantor has good perf, identical to using javax.vecmath in an immutable manner.
13:09_ulisesawesome, will give it a whirl
13:10_ulisesI can see how this is somewhat targeted to a physics engine
13:10dnolen_ulises: yeah it's integrated into penumbra, the clojure opengl library
13:10_ulisescool
14:10kmcwow a bunch of haskellers showed up :D
14:10rlbIs the best way to access a static nested java class to just import Foo$Bar?
14:13kmcChousuke, finger trees in Clojure? sweet
14:14raek#clojure - #haskell cross-pollination?
14:14kmcseems so
14:14kmcFUser, Kruppe, i can try to explain monads if you like, or at least give some relevant meta-advice
14:14tensorpuddingi had been meaning to try clojure for a little while
14:15_uliseskmc: I wouldn't mind that :)
14:15tensorpuddingit's not a lot like haskell so far as i can tell though
14:15kmcme too
14:15kmctensorpudding, i think it's philosophically close to Haskell, and technologically quite different
14:16kmcthe 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:17tensorpuddingi had tried setting it up before
14:17kmcso i had a couple false starts due to that
14:17kmcbut eventually i got lein set up ok
14:17tensorpuddingi was inspired to try again while cleaning up the mess that was my .emacs
14:17kmcand the actual clojure part of clojure is nice
14:18tensorpuddingclojure seems to have improved a lot on the packaging front
14:19tensorpuddingfor that matter, ELPA too
14:19raekClojure 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:20raekI remember the time before lein...
14:20tensorpuddinghaskell likes immutability, but also code segregation through typing, which clojure doesn't appear to have
14:20raekyes, Clojure tries to do as much as possible without types
14:21Kruppekmc: I wouldn't mind a nice description of monads. Thanks for the offer.
14:21raekdata representation, dynamic dispatch and hierarchies doesn't have to do anything with types
14:22_ulises+1 on the monads explanation :)
14:22kmcraek, well Haskell has mutable data structures too
14:22raekinc
14:22kmcand in fact there's some very popular haskell libs that use mutation behind the scenes, but present a pure interface
14:22_ulisess/+1/inc/
14:22kmcwriting such a thing is tricky
14:22raekreminds me of transients
14:22kmcyes
14:23kmcHaskell's ST monad is a lot like transients -- you get to use mutation locally, and expose the result as pure value
14:23kmcin Haskell the type system proves that your mutation doesn't leak out
14:23kmcand so there's no runtime overhead, compared to less safe approaches
14:23raekHaskell is very high on my to-learn list
14:24raekprobably #1
14:24tensorpuddingthe only way to get performance on some things is mutation behind the scenes
14:24Krupperaek: real world haskell did a good job for me. Pretty awesome book.
14:25FUserhow's performance of Haskell
14:25raekah, yes. I have borrowed that book from a friend. have barely started with it.
14:25KruppeFUser: very good.
14:26KruppeFUser: immutable data structures cause similar performance problems but you can use mutable data structures if necessary.
14:26raekever since I was introduced to SML in the Programming Theory course I'm attending, I have been incresingly interested in learning Haskell
14:26kmcGHC is one of the smartest native-code compilers i know of
14:26kmcfor any language
14:27Chousukekmc: 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:27Kruppekmc: I miss macros when im in haskell though, template haskell feels clunky :(
14:27kmcyes
14:27kmcTemplate Haskell is incredibly clunky
14:27kmcthat's one of my main complaints with Haskell these days, and it's one of my main reasons for learning Clojure
14:27FUserI miss types in clojure or even plain old C style structs
14:27tensorpuddingTH is an dark, dingy failed attempt masquerading as a code extension.
14:27kmcmetaprogramming is so powerful and so underappreciated, and Lisp is absolutely king there
14:28KruppeFUser: clojure has structs
14:28kmci 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:28Chousukerecords :P
14:28kmcanyway, monads!
14:28FUserif they are implemented as maps then they aren't stucts even if they are named as such
14:28Kruppekmc: rock on
14:28kmcmy advice on learning about monads
14:29ChousukeFUser: records are the closest you get to C-style structs
14:29KruppeFUser: they are quite fast as well
14:29kmcone thing to keep in mind is that "monad" is just the name of a generic API
14:29kmcpublic class List<T> implements Monad ...
14:29kmcand it's implemented by a lot of different unrelated things
14:29ChousukeThey provide a maplike interface for convenience and are immutable.
14:30kmcpeople often look for a deep intuitive connection between all the monad instances
14:30kmcwhen they wouldn't expect this of just any generic API
14:30Chousuke(deftype is there if you need custom behaviour, but that's not recommended)
14:31Chousukekmc: It helped me a lot to think of a monad as an "execution strategy" kind of thing :P
14:31kmcalso, before you read (or write!) a monad tutorial, you should read: http://byorgey.wordpress.com/2009/01/12/abstraction-intuition-and-the-monad-tutorial-fallacy/
14:31FUser(Kruppe if they are maps then they aren't fast TBH
14:31kmcthe Haskell community has moved pretty strongly against all these analogy-based tutorials
14:31KruppeFUser: i don't think they are maps under the hood.
14:31kmcthe common wisdom now is to get comfortable with a few concrete monad types
14:31raekFUser: (btw, transients in clojure, a way to temporarily use a data structure as a mutable one: http://clojure.org/transients)
14:31kmcyou don't have to care as much about what the generic API means, if you focus on one type at a time
14:32kmcand also, to learn some of the less powerful (meaning more general) APIs first
14:32kmcfunctor and applicative functor
14:32Kruppekmc: the one that really confuses me is ST, and the type errors i get when using it.
14:32kmcyeah, ST is pretty special
14:32kmcits specialness comes not from being a monad, but from the primitives that are provided for ST specifically
14:33kmcsame for IO, STM, etc.
14:33kmcit's a common fallacy to learn IO first and then generalize it to all monads
14:33kmcwhen really IO is a strange atypical monad
14:33kryftkmc: Right, familiarize yourself with a few concrete examples and then let your brain do the generalization from there.
14:33kmcKruppe, over in #haskell we'd be happy to help you with ST type errors
14:33Kruppekmc: yeah that seems to always be the first monad to be described, maybe because its used all the time
14:34kryftkmc: 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:34Kruppekmc: 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:34kmci 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:34kmcsome of the people who "don't get monads" are actually not getting the idea of building IO-descriptions for later execution
14:35kmcwhich is an orthogonal idea
14:36kryftkmc: I take it you use both clojure and haskell?
14:36kmcyup
14:36kmci've been using Haskell for about 5 years
14:36kmcjust learning Clojure
14:37awkoramawhat do you guys use closure for?
14:37Kruppeawkorama: closures? or clojure?
14:38awkoramasorry, i meant clojure
14:38awkoramathe language for jvm
14:38Kruppeawkorama: just making sure. I've used it for simulations mostly. Dunno about everyone else.
14:38tensorpuddinghmm, i have the clojure-contrib installed, but it seems (use 'clojure.contrib.monads) doesn't work
14:38Kruppeawkorama: its a general purpose language though
14:39awkoramaKruppe: sure, but what about traditional 3 layer enterprise web app?
14:39awkoramacan it handle these?
14:39tensorpuddingand now i've got it talking about classpaths
14:39awkoramawhat about annotations and stuff? i found no info on these in clojure
14:39Kruppeawkorama: I don't see why not, but I haven't tried it myself.
14:40Kruppeawkorama: you have access to all of javas libs and can basically write java in clojure if you want.
14:40zakwilsonClojure has the ability to talk to databases and render templates or generate HTML.
14:40raektensorpudding: how are you starting clojure? lein?
14:40awkoramazakwilson: including transaction management?
14:41tensorpuddingI installed clojure from the Ubuntu repositories
14:41tensorpudding /usr/bin/clojure -r
14:41rlbFUser: I belive records aren't "maps" at all, i.e. they're compiled classes where the members are fields.
14:41tensorpuddingit's a script
14:41rlb(and can have optional type annotations)
14:41FUserthat's cool
14:41tensorpuddingdoes some environment mashing
14:41FUserI'll use precompiled version then
14:41raektensorpudding: I wouldn't recommend starting clojure that way. it makes classpath management very hard.
14:42raektensorpudding: for just "give me a repl" use http://github.com/liebke/cljr
14:42FUserI use clojurebox
14:42tensorpuddingeeeenh
14:42zakwilsonawkorama: ClojureQL appears to handle transactions. I have not used it though.
14:42tensorpuddingi really was wanting to not have to use much in the way of hand-compiled stuff
14:42raektensorpudding: for projects (i.e. code in more than one source file) use http://github.com/technomancy/leiningen
14:44raekthe thee major clojure tools (lein, cake, irclj) have all been released since ~november 2009..
14:44tensorpuddinghmm
14:45kmci'm using leiningen even for tiny 1-file projects
14:45kmcit's pretty easy
14:45tensorpuddingleiningen is like cabal?
14:45kmctensorpudding, don't be that guy ;)
14:45tensorpuddingwhat do you mean?
14:45kmc"hi #haskell, please tell me which Haskell function is like GetXW3byF97() from PHP thanks"
14:45tensorpuddingi was asking you
14:46kmcthait said, leiningen is like cabal ;)
14:46djahandarieGetXW3byF97 only works in PHP kmc, Haskell isn't powerful enough to support it
14:46kmcbut it can also do stuff like launch a repl
14:46raekit manages dependencies and the class path, among other things
14:46SergeyDtensorpudding: ubuntu's clojure is quite old - version 1.0.*
14:46kmcand it can build a jar with all your clojure libs baked in, so you can distribute it to Java zombies
14:47tensorpuddingi've got 1.1.0 here
14:47raekbasic workflow for a new project: lein new foo; cd foo; <editor> project.clj; lein deps; lein repl
14:47tensorpuddingon maverick
14:47tensorpuddingit sounds like cabal but even better
14:47tensorpuddinghmm
14:47raekyou declare dependencies in project.clj, and leiningen takes care of downloading it and putting it on the classpath
14:48raekcljr is like lein, but with one global project
14:48tensorpuddinghow is the classpath handled? env mangling?
14:48raekit constructs it from what's in project.clj
14:49tensorpuddingokay
14:49tensorpuddingdoes lein work with clojure 1.1.0?
14:49raekevery project has its own lib/ directory with its versions of its dependencies
14:49tensorpuddingoh hey, it's named after that story about the ants
14:49raekyes, just change [clojure "1.2.0"] to [clojure "1.1.0"] in project.clj
14:49tensorpuddingi read that in middle school
14:49kmctensorpudding, when i set up lein i did it in a way that downloaded the newest clojure automatically
14:49rlbI'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:50tensorpuddingkmc: downloaded it where?
14:50kmctensorpudding, http://github.com/technomancy/leiningen
14:50raekinto ~/.m2
14:50kmcyeah
14:50tensorpuddingone of the things i strongly dislike about cabal is how it defaults to putting things in the home directory
14:50kmci had to apt-get install maven first
14:50raekit uses maven for the dependency stuff
14:50OnceIf anyone is familiar with fnparse please take a peek at http://paste.lisp.org/+2H88 Very simple example, and I'm not sure what the best solution is. Problem is exampled in the paste.
14:50tensorpuddingso i don't know where things are
14:50kmcwhich in turn downloaded about 80 MB of Apache Very Serious Enterprise Java libraries
14:51Onceproblem is explained*
14:51tensorpuddingthough i guess clojure basically is just a couple jarfiles isn't it?
14:51raekit is.
14:51kmctensorpudding, yep, there's a jar for clojure and another for clojure-contrib
14:51kmcand another for each 3rd-party lib you install
14:51tensorpuddingwhy ~/.m2?
14:51raekthat's why you basically have to start it with some tool
14:52raekmaven 2, I think
14:52tensorpuddingwhat's maven?
14:52tensorpuddingis that java's build tool?
14:52raeka java build tool
14:52raekyes.
14:52tensorpuddingokay
14:52raekleiningen uses the dependency parts of it
14:52tensorpuddingwhere are the scripts installed?
14:52raekwhich scripts?
14:53tensorpuddingdo i have to edit my $PATH?
14:53tensorpuddingthe lein script
14:53raekyes
14:53raekthe lein script is the only script
14:56ihodeshey all! it's been a while. anyone here familiar with Compojure?
14:59zakwilsonihodes: I am a little bit.
14:59amalloyzakwilson: if booleans said that they would be adorable
15:00ihodeszakwilson: 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:00zakwilsonInstead of loading the CSS, what does it do?
15:01ihodesthe raw HTML displays, as if unstyled
15:03LauJensenihodes: paste your app ?
15:03raekihodes: what happens if you enter the stylesheet url in the browser?
15:04tensorpuddingokay, so i have lein setup
15:04tensorpuddinghow do i get emacs to use it?
15:04raektensorpudding: install ELPA in emacs first
15:04raekif you don't already have it
15:04tensorpuddingi already did
15:05tensorpuddingto install clojure-mode
15:05raekok, then install packages slime, slime-repl and clojure-mode
15:05ihodes(html/deftemplate index "main.html" [] )
15:05ihodes(defroutes example
15:05ihodes (GET "/" [] (render (index)))
15:05raekslime is for interacting with the clojure process
15:05ihodes (route/not-found "Page not found"))
15:05LauJensenihodes: You also need to tell your app to serve sttic files
15:05LauJensenstatic
15:06ihodesLauJensen: what do you mean?
15:06ihodesLauJeson: it's serving the static HTML just fine; just without the CSS
15:06ihodesmain.html is in resources/
15:06tensorpuddingi've used slime before
15:06LauJensenihodes: 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:06tensorpuddingwith CL
15:06raekihodes: you need to tell your app that GETting /foo.css means serving the file resources/foo.clj
15:06LauJensenihodes: What it does, is read main.html from disk, and serve it via a template
15:07raektensorpudding: then add [swank-clojure "1.2.1"] to your project as a :dev-dependency
15:07LauJensenihodes: if all your static files are in resources/, try adding the middleware (wrap-file "resources")
15:07zakwilsonihodes: paste the whole thing to a pastebin?
15:07raekdo lein deps, and then lein swank
15:07ihodesLauJeson: do i need to include that middleware somewhere? that sounds like what I want to do
15:07ihodesLauJenson
15:08raekyou need both slime and slime-repl
15:08raektensorpudding: example project.clj http://gist.github.com/555485
15:09amalloyihodes: try LauJensen :)
15:09raeklein swank should start a swank server on port 4005, which you can connect to with emacs with M-x slime-connect
15:09LauJensenihodes: Yea you do. I havent used Compojure in a long time, but I think its (defroutes ex (wrap-file "resources") (GET "/" ....
15:10LauJensenAlso make sure you import it in your namespace declaration ring.middleware file
15:10LauJensen(thanks amalloy)
15:10tensorpuddingoh lame
15:11tensorpuddinggot an exception
15:11zakwilsonIs there a currently accepted "best" set of tools to use for web stuff in Clojure?
15:12tensorpuddingoh wait, right, need to change versions
15:12LauJensenzakwilson: 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:12tensorpuddingno, that didn't fix it
15:12LauJensenI also like Compojure. But not enough to use it
15:13ihodesLauJensen: what are the main differences? i'm just starting a project using Enlive; should I give Moustache a look first?
15:13raektensorpudding: swank-clojure 1.2.1 requires clojure 1.2 I think
15:13LauJensenihodes: I think you should yea. Its a very elegantly designed micro-webframework. Check out the readme on its github page.
15:13zakwilsonI have been using Compojure, though I haven't touched the web part of the app that uses it in a while.
15:13raekI'm currently very happy with the Ring + Moustache + Enlive combo
15:14tensorpuddingraek: i thought leiningen grabbed the right version of clojure for you?
15:14ihodesi'll give Moustache a go, then. do you know if Chris will be updating Enlive or Moustache anytime soon?
15:14tensorpuddingthe exception is related to ant, it seems
15:15raekleiningen picks the clojure version you tell it to
15:15tensorpuddingit's grabbing 1.2.0, supposedly
15:15LauJensenihodes: AFAIK I know there are no plans in the immediate future
15:15raektensorpudding: could you paste the stack trace?
15:16zakwilsonMoustache looks like it might be good. I hate the name though.
15:16raekif you mix [clojure "1.2.0"] with [clojure-contrib "1.1.0"] for example, it will not work
15:17raeksince clojure-contrib is ahead-of-time compiled for 1.1
15:17raekand clojure doesn't guarantee binary compatibility between verisons
15:17freakazoidI implemented base62 in Clojure - does anyone care if you have to convert, say, a sha1 hash to a BigInteger first?
15:18freakazoidthe semantics are slightly different than base64.
15:18tensorpuddinghttp://hpaste.org/40648/lein_dep_fails
15:18freakazoidI could make it the same as base64 by treating a byte stream as a base 256 number *after* the decimal point.
15:18tensorpuddingmy project.clj is the same as the one you gisted
15:18raektensorpudding: have you executed "lein self-install"?
15:19tensorpuddingyes
15:20raekwhich version of lein? the one linked on the project page?
15:20tensorpuddingfrom git
15:20tensorpudding1.4.0-SNAPSHOT, apparently
15:20raekah
15:20raekyou have to build the bleeding edge version with leiningen...
15:21tensorpuddingbleeding edge version of which?
15:21raekof leiningen itself
15:21raekhttp://github.com/technomancy/leiningen/raw/stable/bin/lein
15:22raekthat one is 1.3.1
15:22tensorpuddingis there a stable branch?
15:22raekyes
15:23raekthe installation instructions likns to that one
15:25tensorpuddingdammit, i hate git
15:26kryfttensorpudding: Why?
15:26tensorpuddingbecause it's like mercurial, but more confusing
15:26tensorpuddingbut everyone uses it, and no one uses mercurial
15:28tensorpuddingtrying to remember how to manage remote branches is one thing which i don't fully get
15:29raekgit has a steep learning curve
15:29tensorpuddingokay, there, i've checked out stable
15:30raekyou only need the file I linked
15:31raekeverything else is .jars that it downloads automatically when you do lein self-install
15:31tensorpuddingi know
15:32tensorpuddingbut 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:33tensorpuddingit's working now
15:34tensorpuddingugh, it even created a .gitignore
15:34tensorpuddingi suppose clojure is a heavy git community
15:35raekyes, I suppose so...
15:35tensorpuddingi'll have to edit the lein scripts to make an .hgignore instead
15:35raeksource on github and jars on clojars seems to be *very* common
15:37ihodesLauJensen: i'm having trouble rending my template using Moustache now; http://pastebin.org/263049
15:37ihodesmake that rendering
15:37rplevywhat is a reasonable test of pmap vs map that would demonstrate speedup on a 4 core machine?
15:39rlbI'm working with maildirs from clojure -- does anyone know if it's possible to get the filename from a javax maildir message?
15:40raek,(time (dorun (map (fn [_] (java.lang.Thread/sleep 20)) (range 100))))
15:40clojurebot"Elapsed time: 2127.817 msecs"
15:40raek,(time (dorun (pmap (fn [_] (java.lang.Thread/sleep 20)) (range 100))))
15:40clojurebot"Elapsed time: 90.17 msecs"
15:41raekpmap is useful when the computation to do for each element takes long time
15:41raekfor very small computations, it is not recommended
15:42rplevyraek: thanks!
15:43raeknp :)
15:44SergeyDrake: Nice clean example. But I can't figure out why the difference is 20x times on a 2-core processor :)
15:44ihodesanyone here know mucha botu Moustache?
15:45raekihodes: you might need to use wrap-file-info too
15:46SergeyDraek: oh, I got it.
15:46ihodesraek: i'm not even there yet haha — i'm having trouble getting moustache to render my template
15:46raekoh, please share!
15:47ihodeshttp://pastebin.org/263049
15:47raekthought the thread pool was 2 x no-of-processors
15:47raekihodes: you don't need to do the apply str step
15:48LauJensen[""] (response (templatename args))
15:48LauJensenihodes: ^^
15:48raekRing accepts sequences of strings (those that the templates return)
15:48raekah, yes. that makes sense.
15:48ihodesraek: just getting rid of "render" didnt work.
15:48ihodesLauJensen: response is in which ns?
15:50raekihodes: (defn ok [body] {:status 200, :headers {"Content-Type" "text/html; charset=UTF-8"}, :body body})
15:50raek^ this is what I use
15:50raek[""] (fn [_] (ok (index)))
15:50raekor, you could move that (fn ..) into ok
15:51ihodesraek: perfect!
15:51ihodesraek: that's awesome. thanks so much!
15:51raekthe rigth hand side of the route rule should eval to a ring handler
15:51raek:)
15:51ihodesraek: didn't realize i needed to be passing a map back
15:51ihodesraek: 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:52raekihodes: this is what you need to know: http://github.com/mmcgrana/ring/blob/master/SPEC
15:52SergeyDraek: Seems like the thread pool is about 30 on my computer
15:52raekbasically, what keys are in the request and response
15:53ihodesraek: awesome! anything i should know about Moustache beyond what's in the little doc cgrand has?
15:53raekwell, everything about moustache follows from syntax.html... if you know how to interpret it
15:54SergeyDraek: 32 actually, 16 for each core
15:54raekjust remember that things (app [..] <here>) are threaded differently fomr things (app <here>)
15:54RaynesMoustache is so dead simple, the docs he provides is amazingly sufficient.
15:54raek*treated
15:54RaynesIt's compojure that needs more documentation.
15:54raekeven though thosw two cases overlap somewhat
15:55raekwrapping the first case in [ ] always yields the second case
15:55ihodesraek: 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:55raekihodes: by looking at the example he provides, I think most of should be pretty clear
15:56raekthe grammar is nice if you want to be certain about the details
15:56ihodesraek: ah nevermind, this grammar makes perfect sense. and the docs look nice. i think i can handle this :)
15:56raekif you are familiar with grammars, then it should be pretty straight forward, I think
15:56ihodesraek: thanks again!
15:57ihodesraek: yeah it's not as bad as i was expecting; pretty much a cfg haha
15:57Raynes$seen cemerick
15:57sexpbotcemerick was last seen quitting 1019 minutes ago.
15:59Raynes-> (/ 1019.0 60)
15:59sexpbot⟹ 16.983333333333334
16:01amalloyRaynes: sexpbot is yours, right? if the minutes aren't helpful, why not get him to tell you hours as well?
16:01RaynesIf one more person asks me that, I'm going to make sexpbot timestamp intelligently.
16:02RaynesThat's at least 6 people in the last two months. :p
16:02amalloyheh. well, i don't mind the minutes myself, but since the *author* seems to find minutes inconvenient...
16:02raek,((juxt #(/ % 60) #(rem % 60)) 1019)
16:02clojurebot[1019/60 59]
16:02RaynesIt'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:04amalloy,((juxt quot rem) 1019 60) ; raek?
16:04clojurebot[16 59]
16:05amalloysexpbot: source?
16:05KirinDaveWait what?
16:05KirinDaveAh
16:05Raynes$whatis sexpbot
16:05sexpbotsexpbot = http://github.com/Raynes/sexpbot
16:06raek/facedesk
16:07amalloyraek: it's a good thing you're a founding member of the juxt fan club or we'd have to kick you out
16:07raek:-)
16:08ihodesRaynes: you should make sexpbot timestamp intelligently!
16:08ihodes;)
16:09RaynesHe's right, you know.
16:09RaynesJust 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:09amalloyRaynes: i'll fork and do it myself if you want. looks pretty easy in seen.clj
16:10RaynesI'd love you forever.
16:10LauJensenSuch an affectionate young man
16:12DeranderI'm trying to implement a file watcher daemon in clojure. Currently, I have a function like this: http://gist.github.com/63122 . In ruby, C, or other languages that I know, I'd slap that logic in a while loop and put a sleep of some reasonable amount of time in
16:13DeranderI have no idea how to do this idiomatically in clojure
16:13DeranderMost 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:13RaynesDerander: Sure that's the right gist?
16:13amalloy(loop [] (do-stuff) (Thread/sleep 1000)) ; would work, dunno if it's idiomatic
16:14amalloyer. and put a (recur) at the end, sorry
16:14DeranderRaynes: that is definitely not, weird
16:14Raynes(while true ..)
16:14Deranderhttp://gist.github.com/631226 is
16:14LauJensenamalloy: busywaiting... I think there is a FileWatcher class actually, or maybe Im thinking of C#
16:14LauJensenRaynes: (defn x [] (while true body (recur))) = (defn x [] (recur ...))
16:14DeranderLauJensen: When I was googling, I found some sort of FileWatcher mechanism in java 7
16:15RaynesLauJensen: I didn't tell him to recur in (while true ..)
16:15Deranderalright, I'll explore recur. Thanks for the info
16:15Raynesamalloy told him to recur at the end of the loop.
16:15Raynes:p
16:15LauJensenRaynes: Oh right, sorry for not being able to tell you two Americans apart
16:16DeranderLauJensen: I imagined that in a snotty british accent.
16:16Raynes:>
16:16RaynesNot quite.
16:16LauJensenHaha!
16:16KirinDaveDerander: Write (forever fn)
16:17KirinDaveDerander: Use the trampoline to recur, and make sure that it returns a future so the repl doesn't block.
16:17KirinDaveI'm not sure how you'd enable killing, but it's not like that's the intent, anyways. :)
16:17KirinDaveYou could probably put in a kill switch.
16:17DeranderKirinDave: 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:17KirinDaveThen you can write (forever #'alone)
16:17Deranderhaha.
16:19RaynesYou can use futures in places where you'd do (.start (Thread. (fn [] ..))) a lot of the time.
16:19LauJensenhaha
16:19DeranderRaynes: 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:20Deranderbut I'll read read read and figure it out
16:20RaynesGotta start somewhere.
16:20Derandermmhmm. it's more approachable than haskell at least
16:20LauJensenDerander: 62 lines is a very good start, it corresponds to 824 lines of Scala of 1400 lines of PHP
16:20LauJensenroughly...
16:20RaynesLauJensen: What about Ruby
16:20raek(def running? (atom true)) (future (loop [] (if @running? do-stuff clean-up)))
16:20KirinDaveLauJensen: That is math I want to see
16:20LauJensenRaynes: 74 ? :)
16:20DeranderRaynes: approximately equivalent
16:20KirinDaveRaynes: 62 lines as well, but only if you use eigenclasses.
16:21DeranderI've been writing ruby for 3 years and never really used eigenclasses
16:21LauJensenKirinDave: 62 lines, but behavior will be unpredictable
16:21RaynesDerander: With all due respect to Haskell (I adore the language), a brick wall is more approachable at high speeds.
16:21DeranderRaynes: yes
16:21LauJensenHaskell is fantastic.
16:21KirinDaveLauJensen: 62 lines, but it each line will take 1 year to execute, and won't run if you've required ActiveRecord.
16:21RaynesYes it is.
16:21LauJensenhehe
16:21Deranderbetter: 62 lines, and 120 lines of unit testing.
16:21KirinDaveHaskell is beautiful. There is a difference. ;)
16:21KirinDaveHaha, all written in advance
16:22LauJensenDerander: In Ruby, even unit tests wont save you
16:22KirinDaveWith a mock framework more complex and powerful than almost any other project in the language.
16:22DeranderLauJensen: I usually write integration tests for my ruby projects anyway
16:22Deranderbut that's because I am filled with hubris
16:23LauJensenI guess if you build commercial software in Ruby, you do deserve a bit of punishment
16:23KirinDaveLauJensen: If you need unit tests to successfully complete a project, ruby is a rough road.
16:23KirinDaveSome languages require champions to ride them.
16:23KirinDaveYou can quote me on that.
16:23Deranderthe biggest project that I've worked on in ruby is 15k lines of code
16:23LauJensenOuch!
16:23Deranderit's actually pretty nice
16:24Deranderif the templating was in haml life would be perfect
16:24LauJensenDerander: nice as in, you got rich from bugfixing it ?
16:24KirinDaveLauJensen: It's not a condemnation.
16:24LauJensenKirinDave: What is it then ?
16:24KirinDaveLauJensen: It's a compliment, actually. Ruby is a superbike.
16:24DeranderLauJensen: nah, nice as in it works pretty well and is easy to grok and work with
16:24KirinDaveLauJensen: The problem is you rev the throttle too fast and suddenly you're SuperDave.
16:24LauJensenDerander: impressive, I thought that was impossible with Ruby
16:24Deranderwhen I finish pushing it to 1.9.2 it'll be damn fast too
16:24KirinDaveHanging from your bike's handlebars, body horizontal with the acceleration.
16:25KirinDaveI have more metaphors, if you need them.
16:25Deranderruby was my first language after php. we've had a long and tender relationship
16:25tensorpuddingif you have a function which takes [& args], how can you mangle (arg arg) to make it work as input to the function?
16:27tensorpuddingwait, apply seems to be it
16:27aavtensorpudding: (applu myfunc args) - if i got your question right
16:27aavapply
16:28shanmuHi, I am trying to represent db records as clojure records - I am trying to do defrecord dynamically
16:28tensorpuddingexcept doh, it's a macro, not a function
16:28KirinDaveDerander: Same.
16:28KirinDaveExcept the PHP part.
16:28KirinDaveRuby was my first dynamic language that I loved.
16:28KirinDave:)
16:29shanmuI 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:30KirinDaveSo... I've been wondering.
16:30KirinDaveWhat's the right way to make something that responds to @deref correctly?
16:30tensorpuddingi'm really getting annoyed by how restrictive macros seem to be
16:31KirinDavetensorpudding: What in particular is bothering you?
16:31tensorpuddingwell, you can't apply them
16:32tensorpuddingor use them as functions
16:32Chousukeif you need to apply a macro you probably have a weird macro :/
16:32KirinDavetensorpudding: You have to understand, when you say (defmacro ...) what you're saying is (open up my compiler and add....)
16:32KirinDavetensorpudding: The very act of applying things is generally a runtime process.
16:32KirinDaveAnd as such the compiler has no place
16:32tensorpuddingi didn't decide to make or and and macros
16:32KirinDaveAh.
16:32KirinDaveThe Classic Complaint™
16:33KirinDaveand and or aren't actually macros.
16:34KirinDaveThey're special forms.
16:34Chousukewell, except that they are macros :P
16:34tensorpuddinghmm
16:34KirinDaveChousuke: Implementation detail ;)
16:34Chousukeand no they're not really special forms
16:34tensorpudding,(reduce or true [true false true])
16:34clojurebotjava.lang.Exception: Can't take value of a macro: #'clojure.core/or
16:34RaynesKirinDave: No, they seriously aren't special forms.
16:35Chousukeif is a special form, or and and are just macros
16:35Raynes-> (doc and)
16:35sexpbot⟹ "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:35KirinDaveRaynes: Ah, i'm thinking CL.
16:35RaynesNot a special form.
16:35tensorpudding,(reduce (fn [x y] (or x y)) true [true false true])
16:35KirinDaveSorry.
16:35clojurebottrue
16:35KirinDavetensorpudding: Yes
16:35Chousukebut the thing is that macros work with code
16:35tensorpuddingif you wrap it in a lambda, it works
16:35KirinDavetensorpudding: Right, because a function is generated.
16:35Chousukeapply works with runtime data.
16:35tensorpuddingi'm trying to translate something from haskell into clojure
16:35tensorpuddingto learn the former better
16:35Raynes-> (some false? [true false true])
16:35sexpbot⟹ true
16:36KirinDaveRaynes beat me to it.
16:36RaynesThat essentially accomplishes the same thing without any macros.
16:36amalloyRaynes: sent a pull request for sexpbot
16:36Raynesamalloy: Thank you, kind sir. Your work is appreciated.
16:37RaynesKirinDave: It must be Haskellers Try Clojure week. I've seen a ton of guys from #haskell in here lately. :D
16:38Chousukeheh.
16:38KirinDaveRaynes: Reaching for something. :)
16:38amalloyhmmm. does github have a "merge with upstream" function or do i have to figure out how to do it from git?
16:38Chousukeamalloy: pull from upstream, push into your fork? :/
16:39KirinDaveHum
16:40KirinDaveI'm working on asciidoc-ing my clojure & the web chapter for my book
16:40KirinDaveThis is the final code for a URL shortener. I know it works, but any failures to emulate idiomatic code would be appreciated.
16:40KirinDave(err, pointing them out, that is)
16:40KirinDavehttps://gist.github.com/f3509ac3fe7859fe527d
16:41KirinDaveAnd before you ask, the silly storage stubs are there so that couchdb can be hooked in later.
16:55shanmuHi, Can I dynamically declare a record?
16:57shanmuI get an error when trying (def name-list ["id" "name"]) (defrecord org name-list)
16:58shanmu,(do (def name-list ["id" "name"]) (defrecord org name-list))
16:58clojurebotDENIED
16:58chouseryou'll need to use eval or something
17:01amalloyor a macro. i think i gisted something like this a while back, let me find it
17:04amalloywell, 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:04kjeldahlhttp://stackoverflow.com/questions/678867/how-to-defn-a-function-from-string-in-clojure
17:10shanmuamalloy, kjeldahl: thanks!
17:23Raynes$seen cemerick
17:23sexpbotcemerick was last seen quitting 18 hours and 24 minutes ago.
17:23Raynesamalloy_: My love. <3
17:40amalloy_Raynes: woo!
17:40amalloy~seen cemerick
17:40clojurebotno, I have not seen cemerick
17:40amalloyheh. win for sexpbot
17:41RaynesMaybe he stores the info in memory. If so, a restart would wipe it (which is a possibility).
17:42KirinDaveOh I hope he doesn't have a data store for seen
17:42RaynesA seen database can get really huge.
17:43Raynessexpbot using mongodb for seen (among a lot of other things).
17:44amalloyclojurebot uses (ref {}) to store the seen list
17:44RaynesYeah, in memory. It probably just restarted since cemerick left.
17:44amalloyyeah
17:59shanmuI had to use (defmacro record-from-strings [fields] `(defrecord ~@(map symbol fields))) (record-from-strings ["org" "id" "name"]), does that look alright?
18:00shanmuoops! wrong paste
18:00shanmuI had to use (defmacro record-from-strings [rec-name fields] `(defrecord ~(symbol rec-name ) ~(map symbol fields))) (record-from-strings "org" ["id" "name"])
18:01shanmudoes that look alright?
18:01amalloyyeah, looks reasonable. i forgot it doesn't want the @ there
18:02shanmuamalloy: thanks a lot! this solves my problem nicely
18:03amalloyshanmu: just keep in mind it will only work with literals - you can't do like (def x ["foo"]) (record-from-strings "org" x)
18:04shanmuoh.. ok... I was planning to do defrecords for table columns in a db (obtained via c.c.sql)
18:05amalloymacros can't have access to runtime data. they happen before runtime
18:05amalloybut there is a way to do it if your db info will be known at compile time
18:05shanmuamalloy: thanks! is there any way to do it? the db info would be available during compile time...
18:06amalloyshanmu: see http://clojure-log.n01se.net/date/2010-10-17.html, especially the link to http://gist.github.com/630662
18:06shanmuamalloy: thanks! looking thorugh
18:17clojurebotThe Tao, considered as the Rabbit, began.
18:40amalloyshanmu: that help solve your problem?
18:42shanmuamalloy: no, not exactly... the problem is I donot know my macros... reading up on them now
18:42shanmuI tried (defmacro record-from-strings [fields] `(defrecord ~@(map symbol fields))) (record-from-strings ["org" "id" "name"])
18:42shanmuoops!
18:42shanmuI tried (defn create-record [rec-name fields] `(defrecord ~(symbol rec-name) ~(map symbol fields)))
18:42shanmuthen (defmacro make-record [rec-name fields] `(~(create-record rec-name fields)))
18:43shanmubut (let [n "recName" f ["f1" "f2"]] (make-record n f))
18:43shanmuerrors with Don't know how to create ISeq from: clojure.lang.Symbol
18:44amalloyshanmu: (let [blah] (stuff)): if stuff is a macro, it can't access the contents of blah because that's happening at runtime
18:45amalloythe 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:46amalloydefine-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:49shanmuamalloy|gone: thanks for the advice! will try something
18:51raekmaking some Active Record-like system?
19:07FUserwhat's the difference between :while and :when in macro "for"?
19:07FUser,(for [x (range 15) :when (> x 5)] x)
19:07clojurebot(6 7 8 9 10 11 12 13 14)
19:08FUser,(for [x (range 15) :while (> x 5)] x)
19:08clojurebot()
19:09FUser,(for [x (range 10) :when (> x 5) :while (> x 5)] x )
19:09clojurebot(6 7 8 9)
19:10FUser,(for [x (range 15) :when (even? x) :while (> x 5)] x)
19:10clojurebot()
19:10shanmuraek: not a full fledged activerecord like system
19:10FUserim confused
19:13LajlaFUser, obviously looking at this, while stops after the first false, and when continues.
19:13LajlaBut just doesn't put it into the list if it's false.
19:14FUserbut check this out
19:15FUser,(for [x (range 15) y (range 10) :when (even? x) :while (> x 5)] x)
19:15clojurebot(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:15FUseridentical case as when it returns empty list
19:15FUserexcept it has an additional variable that isn't used
19:15FUserand it suddenly behaves totally differently
19:16LajlaI have no idea how that works no.
19:16LajlaCould even be a bug.
19:16LajlaAsk raek, he is omnipotent.
19:17FUser:D
19:17FUseryou mean omniscient surely
19:19LajlaWell, if you can do all things, that includes knowing all things, or at least answering all quaestions.
19:27FUser:)
19:37chouser:when and :while control the previously specified loop
19:59shanmuamalloy: its working now!!
19:59shanmu(defmacro record-from-table [table-name]
19:59shanmu `(defrecord ~(symbol table-name) ~(map symbol (get-columns-map table-name))))
19:59shanmu(defn get-columns-map [table-name]
19:59shanmu (sql/with-connection db
19:59shanmu (map #(:column_name %1)
19:59shanmu (resultset-seq (-> (sql/connection)
19:59shanmu (.getMetaData)
19:59shanmu (.getColumns nil nil table-name nil))))))
19:59shanmusorry, pasting it
20:00amalloyshanmu: great! yeah, i was about to say paste
20:01shanmuhttp://pastebin.com/4ihxfMED
20:01shanmuamalloy: thanks for the guidance! just like you said, a macro which calls a function to get column list
20:05KirinDaveshanmu: #(:sym %1)
20:05KirinDaveshanmu: Or
20:05KirinDave,(map :col [{:col 1}])
20:05clojurebot(1)
20:05zakwilsonIf 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:05KirinDaveshanmu: Understand?
20:06duck1123I have a bunch of files I'm reading for my tests (lazytest) and
20:06duck1123previously I had them in the root of my application, but I want to
20:06duck1123move them to src/test/resources (using maven) is slurp the best way to
20:06duck1123contiue reading them, and if so, should I specify the path in the src
20:06duck1123directory, or is there a better way?
20:06duck1123ahh, sory about the multi-line
20:08dysingerduck you could find the files in your classpath if you put them in maven's src/test/resources dir
20:09shanmuKirinDave: sorry, didnot understand that...
20:10KirinDaveshanmu: You don't need the #().
20:11KirinDaveshanmu: :keywords are invokable.
20:11shanmuKirinDave: got it! sorry, bad habit of adding an anon func as soon as I type map!
20:11KirinDaveshanmu: Same. :)
20:12ninjuddzakwilson: [org.clojure.contrib/complete "1.3.0-SNAPSHOT"] should work
20:12shanmuKirinDave: thanks! will remember that keywords are invokable... :)
20:13zakwilsonninjudd: looks good so far. Thanks.
20:13duck1123dysinger: 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:13clojurebotAlice felt a violent blow underneath her chin - it had struck her foot! She was walking with nameless simplicity.
20:14duck1123I know there's an easy way to do it, but I can't remember it, and google is failing me
20:14ninjuddzakwilson: 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:16zakwilsonninjudd: I'll start with everything, and get specific if I decide by uberjar is too uber.
20:19ninjuddzakwilson: 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:20zakwilsonI am not writing a library, and I am not putting what I'm writing on clojars.
20:20zakwilsonSorry. Super proprietary. Going to make me a zillionare. Etc.
20:21ninjuddzakwilson: i see. well then you'll be able to afford all 61 jars ;)
20:21duck1123I need to go through my projects and go down to the specific contribs I need
20:23zakwilsonI'll even be able to afford sixty-TWO jars!
20:26shanmuthanks a lot people! #clojure rocks, as always....
20:26dysingerduck1123: (-> (Thread/currentThread) (.getContextClassLoader) (.getResourceAsStream "x/y/z.txt") (slurp))
20:27dysinger(slurps file from classpath)
20:29duck1123dysinger: ok, so maybe it wasn't as easy as I thought. Thanks a lot
20:30amalloydysinger: the parens aren't necessary for one-arg functions in ->, eg
20:30amalloy,(-> 1 inc inc inc)
20:30clojurebot4
20:30duck1123you wouldn't by any chance to know how to get lazytest failures to fail the build?
20:31amalloy(whether that makes things more readable is down to taste, of course)
20:34dysingerduck1123: it'd be pretty easy to make a fn to slurp-from-cp
20:34dysingerand just use that instead of plain slurp
20:35duck1123just did. looking for instances of slurp atm. :)
20:35dysingereasy peasy
20:39duck1123dysinger: what are you using for code coverage with maven atm?
20:58dysingerduck1123: I'm using lein mostly
21:25cemerickduck1123: code coverage is orthogonal to build tooling
21:25cemerickI 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:26cemerickPresumably there's some code coverage tools that have plugin architectures amenable to informing them about non-Java languages.
21:43jstirrell`hi
21:44jstirrell`what's the easiest way to get a new collection of, say, every third item from an old collection?
21:45cemerick,(take-nth 3 (range 20))
21:45clojurebot(0 3 6 9 12 15 18)
21:45cemerickjstirrell`: ^^
21:45jstirrell`sweet thanks!
22:04Raynescemerick: Evening.
22:05cemerickRaynes: howdy
22:05RaynesHow was your weekend?
22:05cemerickVery busy. Working on the book at the moment.
22:05RaynesOoh, goody.
22:06cemerickRewriting stuff this early on is surely a bad sign. :-/
22:06RaynesOnly means you're a perfectionist. When kept in check, that can be a very valuable asset.
22:06cemerickheh, indeed
22:06cemerickOtherwise, it was a perfect autumn day.
22:07RaynesIndeed. It's been a beautiful week here. Nice and cool.
22:07moogatronic+1 for perfect autumn day.
22:07cemerickWarmish but breezy, mostly sunny, tons of fantastic treescapes.
22:07cemerickBreakfast out, then a small hike, then a visit to Old Deerfield.
22:08RaynesWell, 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:08moogatronicwe'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:08cemerickRaynes: Figure after 8:30 anyway
22:08RaynesRight, I should be up or nearly up.
22:09RaynesGoodnight, fair #clojure.
22:09moogatronicgoodnight. =)
22:13clojurebot"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:14cemerickwow, that was random
22:14maravillasclojurebot must be reading lewis carroll lately
22:16maravillascurious...both that quote and the one at 8:12 are from http://twitter.com/#!/WonderTao
22:17maravillas"Text built by mashing up Alice's Adventures in Wonderland with the Tao Te Ching. Created with Python & Markov chains."
22:17cemerickvery random
22:36LajlaSo how are things going in noTCOland now?
22:38cemericksame as they always have; see recur
22:38cemerickor trampoline
22:38LajlaI know them.
22:39LajlaI'm just feeling like that remark.
22:39LajlaI am actually the second best clojure programmer in the world, second only to the microsoft Chief Software Architect.
22:40chousercemerick: hi
22:41cemerickchouser: bonsoir
22:41LajlaTerve
22:41chouserI feel like I've been gone
22:42cemerickThere was certainly a disturbance in the Force.
22:43chouserheh
22:48chouserwow, vars are suddenly in flux?
22:48cemerickindeed
22:51chousersomeone asked me at strangeloop, "what's next"
22:51cemerick"how much time do you have?"
22:52chouserwhich of course is a common question. and I'm always tempted to guess
22:53chouserI said "I don't know" and "maybe pods" ...not realizing dynamic binding and future/send had *already* *changed*
22:54cemerickmmm, the future/send change is pretty friggin' huge
22:54cemerickThat "fixes" vars and binding quite a lot.
22:59coldheadthanks clojurebot
23:02chouseryep
23:45cemerickThis seems like an unfortunate asymmetry:
23:45cemerick,(-> ::foo str keyword)
23:45clojurebot::sandbox/foo
23:45cemerickvs.
23:45cemerick,(-> 'foo str symbol)
23:45clojurebotfoo
23:47cemerickMeaning, namespaced keywords aren't trivially string round-trippable.
23:56chouser,(-> :foo str keyword)
23:56clojurebot::foo
23:56chouser,(-> `foo str symbol)
23:56clojurebotsandbox/foo
23:57chouser,(-> :foo name keyword)
23:57clojurebot:foo
23:57chousercemerick: I think I'm missing your point
23:57cemerickI'm tired; perhaps my point is foolish.
23:58cemerickI think one should be able to do (-> ::foo str keyword) and get the proper keyword out.
23:58cemerickAs things stand, you have to munge the string before keywordizing it.
23:58hiredman,(pr-str ::foo)
23:58clojurebot":sandbox/foo"
23:59cemericksure
23:59cemerickmy point was about asymmetry, not about not being able to do the thing
23:59chouserah, I see what you're saying
23:59chouserpr-str is the inverse of eval, though