#clojure logs

2009-08-03

01:31mebaran151I'd like to have a version of concat that stops concatting at nil
01:33mebaran151something like concat while
01:33carksometing like (apply concat (take-while ...
01:34mebaran151will take-while respect laziness?
01:34hiredman,(doc take-while)
01:34clojurebot"([pred coll]); Returns a lazy sequence of successive items from coll while (pred item) returns true. pred must be free of side-effects."
01:34cark,(apply concat (take-while identity [[1 2 3] [:a :b :c] nil]))
01:34clojurebot(1 2 3 :a :b :c)
01:35mebaran151thanks you all
01:36mebaran151that did the trick nicely
01:36mebaran151I now have lazy cursors over berkeleydb which is pretty sweet
01:36carknice =)
01:38mebaran151is there any reason why iterate always pulls the first iterations of its series?
01:39mebaran151,(take 2 (iterate #(prn %1) "no"))
01:39clojurebot("no" nil)
01:39mebaran151first three iterations?
01:40mebaran151that example didn't show it, but it all seems to prefetch the first three chunks
01:40carkhum it used to be like that i think, but not anymore
01:41carkwhat version of clojure are you using ?
01:43mebaran151the 1.0 that comes with enclojure
01:44mebaran151I think it's from may
01:44mebaran151I don't mind the behavior, because for this application, a little prefectching is actually a pretty good idea
01:45cark1.0 should not show this behaviour
01:45carkmy guess is that your code is to blame =)
01:45mebaran151mine too
01:45mebaran151but it's exactly three
01:46mebaran151I'll lisp paste the relevant functions
01:46carki'm using an even older version, and i can't reproduce that
01:46mebaran151~lisppaste
01:46clojurebotTitim gan éirí ort.
01:46carkclojurebot: paste?
01:46clojurebotlisppaste8, url
01:46lisppaste8To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.
01:47lisppaste8mebaran151 pasted "iterate likes to pull" at http://paste.lisp.org/display/84653
01:48mebaran151db-list always pull the first three mores, as verified by my juvenile prn statement
01:49mebaran151these statements are not recomputed, and the laziness works as before
01:50jonase,(for [x (range 1 10) y (range 1 10) :while (= y 2)] [x y])
01:50clojurebot()
01:50jonase,(for [x (range 1 10) y (range 1 10) :while (= x 2)] [x y])
01:50clojurebot([2 1] [2 2] [2 3] [2 4] [2 5] [2 6] [2 7] [2 8] [2 9])
01:50jonase:while confuses me.
01:53carkmebaran151: sorry i can't help you on this
01:53mebaran151no problem
01:53mebaran151so it's nothing super obvious?
01:55carki think you're looking at the wrong place ...
01:55carkyou have these loops in fetch and more
01:55mebaran151(def ts (apply concat (iterate (fn [x] (prn "MOAR")) 2)))
01:55clojurebotx is y
01:55mebaran151that function displays the exact same behavior
01:56mebaran151,(def ts (apply concat (iterate (fn [x] (prn "MOAR")) 2)))
01:56clojurebotDENIED
01:56mebaran151printed 3 times to my screen
01:57mebaran151I think it must be in the application of concat, as concat works through its 3 overloaded forms
01:58carkthat makes sense
01:58mebaran151,(apply concat (iterate (fn [x] (prn "MOAR")) 2)))
01:58clojurebotjava.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer
01:59mebaran151,(apply concat (iterate (fn [x] (prn "MOAR")) 2))
01:59clojurebotjava.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: Integer
01:59mebaran151,(apply concat (iterate 2 (fn [x] (prn "MOAR")))
01:59clojurebotEOF while reading
01:59cark~def concat
01:59mebaran151anyway to get a concat that doesn't do this
01:59mebaran151?
02:00mebaran151,(apply concat (iterate 2 (fn [x] (prn "MOAR"))))
02:00clojurebotjava.lang.RuntimeException: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn
02:00carkuse lazyseq
02:00carkmake a function forit
02:01mebaran151so I'd just recursively hit that function or something?
02:01cark~doc mapcat
02:01clojurebotIt's greek to me.
02:02cark~def mapcat
02:02carkmhh nope
02:03mebaran151it isn't that big deal: in fact it's downright useful for use in db-list (where I'd probably write some prefetching logic anyhow)
02:04carki'm pretty sure you can do this with lazy-seq ...but yes if it's usefull why bother =)
02:06mebaran151my other option is just to pad it with nils
02:07carkthat's ugly =/
02:08mebaran151then it only hits me once
02:11mebaran151yep
02:11mebaran151padding with three nils makes it all work out okay
02:13mebaran151(apply concat (concat [nil nil nil] (iterate (fn [n] (prn "MOAR") n) [2]))))
02:13mebaran151nasty looking but functional
02:17mebaran151,(apply concat (concat [nil nil nil] (iterate (fn [n] (prn "MOAR") n) [2]))))
02:17clojurebotEval-in-box threw an exception:java.lang.OutOfMemoryError: Java heap space
02:18mebaran151I didn't see that one coming.....
03:00LauJensenTop of the morning gents
06:01cgrandHi LauJensen!
06:01LauJensenMr. Grand! Good to see you
07:32JimiDiniHi
07:33JimiDinisopi: I got your question about status of data. Unfortunately I don't have access to verify the status. X-Fade does
07:41Fossiis the only way to get a float[] (make-array (. Float TYPE) ) and putting stuff in there? or is there a way to use into-array or such?
07:42ChousukeFossi: (into-array Float/TYPE your-seq)?
07:43Chousuke(You should really avoid using . directly. it's so ugly :()
07:43FossiChousuke: i got the (. from the docs ;p
07:44Chousukewell, Float/TYPE does expand to (. Float TYPE)
07:44Chousuke... hmm
07:44Fossiah. great http://clojure.org/java_interop#toc27 doesn't mention the type variant
07:45ChousukeActually, I wonder what Clojure does if a class had a static field identical to an instance field in Class
07:45Chousukebecause then (. FooClass fieldName) would be ambiguous
07:48Chousukehmm, looks like it will choose the static field for that form.
07:48Fossiah, even better: (float-array 10)
08:24angermanyep, :)
08:38rhickeygit question: we have both a tag and a branch 1.0 in the clojure repo, whenever I do anything with git with 1.0 I get a "warning: refname '1.0' is ambiguous.", but it seems to proceed. What does it use by default, the branch or tag?
08:43Chouser#git says: see man git-rev-parse. The tag takes precendence.
08:43rhickeyso, git checkout 1.0 pulls the tag
08:43rhickeyhow do we apply patches to 1.0?
08:44opqdonutcheckout, git-apply, commit?
08:44rhickeyopqdonut: the question is about disambiguating the tag from the branch
08:45opqdonuthave you tried "git checkout branches/1.0"
08:45opqdonuterr, "heads/1.0" that should be
08:46opqdonutIf you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell git which one you mean.
08:46opqdonutsays git-rev-parse
08:47rhickeyso anyone who says checkout 1.0 will always get the tag snapshot and everything else we need to do with the branch needs to be qualified?
08:47opqdonutbasically, yes
08:47rhickeyugh
08:47angermanrhickey: did you ask in #git already?
08:48rhickeyangerman: no
08:48angermanfound them helpful the last time I asked ;)
08:48rhickeywe need to make a policy decision as to whether we want to work that way, no patches applied to 1.0 yet afaik
08:49rhickeythis is just what we got be default from the svn import
08:49ChouserI think that's right. can we rename the tag to 1.0.0 ?
08:49rhickeyby default
08:50opqdonutrelease-1.0.0 or something might be a better tag name
08:50rhickeyChouser: I don't think you can rename tags once people have seen them
08:50Chouserugh
08:54Chouserbleh. maybe rename the branch (or create a new one) 1.0.x
09:07angermanhow does clojure handle the keyword arguments?
09:07Chouserit doesn't.
09:07Chouseror put another way, what keyword arguements?
09:08angermanlike in (gen-class :extends )
09:09angermanI'm wondering how I could rewrite my database abstraction layer to be lisp agnostic... I like clojureql's approach, but maye (query "MyKind" :where (and (= ...)) :order-by xyz)
09:09angermanbut if clojure does not support keyworded arguments by default, I guess I'll just not use them
09:12durka42not by default, but you could construct something with hash-map
09:12Chouseryou could use clojure.contrib.def/defnk
09:18angermanohh dang. I need naturally sorted results. hmm.
09:20angermanhow would I sort a vector in clojure if my vectore looks someting like [{:pos 0 :name "x"} ... {:pos 20 :name "x"}] ... obviously not sorted beforehand
09:24Neronusangerman (sort-by #(% :pos) vector) ?
09:25angermanNeronus: thanks, will try.
09:26rhickeyso I'm pretty happy with the thread safety now for mutable vectors, as well as the API
09:26rhickeybasically mutable vectors enforce use in a single thread
09:26rhickeyall mutating ops have ! appended
09:27rhickeybut count/get/nth/invoke all work with normal API, yet check thread also
09:27rhickeyno use after immutable! call
09:27rhickeyso, no fast and safe
09:27rhickeynow fast and safe
09:29rhickeyI'm amazed, but thread check was practically free perf-wise. Apparently HotSpot caches Thread/currentThread in a register or something
09:30Chouserwhat does "no use after immutable! call" mean?
09:30rhickeyChouser: throws an exception
09:31Chousera mutating ! op after an immutable! call throws?
09:31rhickeyChouser: all calls throw after immutable!
09:32Chouseroh! on the old mutable thing. immutable! returns what you want to use.
09:34rhickeythe idea is to support single flow usage, just like functional style but with no persistence, trying to avoid bash-in-place use
09:34rhickeyso you can take normal (but non-persistent, non-aliasing) functional use and add mutable at front, some !'s and immutable! at end for a batch editing session
09:34rhickeynew is the protection against use in other Threads
09:34angermanwhee, sorting works. it's dead stupid but it does work. Hmm.
09:34rhickeythrows if used in thread other than the one that called mutable
09:35rhickeyChouser: exactly
09:36rhickeyoriginally I had supported calling immutable! then continuing editing, but there's no perf advantage over calling mutable again, and it is much clearer
09:37Chousersounds really good.
09:37rhickeypv -> (mutable pv) -> mv -> edits! -> (immutable! mv) -> pv
09:37Chouserwith structural sharing throughout
09:38rhickeythe thread protection takes it to a whole new level, as such use, even with multiple collections is truly safe and a lot more flexible than either all-methods-synchronized (like j.u.Vector) or, shudder, locking
09:39rhickeythe fact that this works, as does parallel vector map, with the exact same data structure set is incredibly powerful
09:45Chousukeangerman, Neronus: (sort-by :pos vector) is enough :)
09:51Chousukerhickey: Maybe you just need to merge them to master to get people to test :P
09:51rhickeyChousuke: yup
09:51ChousukeI wonder if undoing a merge is as easy as reverting the merge commit, though.
09:53AWizzArdAs clojure.lang.RT.conj() returns an IPersistentCollection it means I have to cast every time (in Java) when I want to conj something on my vector, right?
09:54Chousercasting doesn't have runtime cost, afaik
09:56AWizzArdNo, that's not a problem. I was just curious if there is a trick to go around that need for casting :-)
09:56cemerickJomyoot: perst is the most likely candidate, IMO. I've enjoyed working with it so far.
09:57angermanohh no. clojures json seems to choke on utf-8 :/
09:57ChouserAWizzArd: you could call PersistentVector.cons() instead.
09:57danlarkinangerman: clojure-json? what input
09:58cemerickwriting something like that in clojure would make the API a whole lot cleaner, but reinventing proper transactionality, etc., is not something I'm qualified to do (or interested in tackling)
09:58angermandanlarkin: using clojures contrib json module
09:58angermanbut it seems to encode it correctly
09:58angermannow I need to find out where the issue resided
09:59cemerickAWizzArd: What Chouser said. Polymorphism is nifty :-)
10:00rhickeycemerick: covariant returns re nifty, were missing in C#
10:00angermanhmm jtable ... hmmm
10:01cemerickrhickey: When I left the shores of scala, I promised myself I'd forget everything I knew about covariance, contravariance, etc etc :-)
10:07AWizzArdChouser and cemerick: yeah, good trick, that saves a few keystrokes, good.
10:12angermananyone any idea how to tackle unicode from jtable -(json)-> server -(json)-> jtable?
10:17danlarkinangerman: what's the step that fails?
10:36NeronusIs there an intelligent way to check if (map fn o) can be used with object o (other than the exception way)?
10:46LauJensenNeronus: Generally if (seq? o) is true, then map should work
10:47Neronusyeah, but map works for arrays too, and (seq? (int-array 10)) == false
10:47stuartsierraNo, seq? tests if o is already a sequence.
10:48Chouserthere's a 'seqable?' in clojure.contrib.core, but I'd wonder if it's thr right solution.
10:49rhickeyNeronus: in what situation would you be calling map speculatively?
10:49ChouserNeronus: you really want *anything* that map can work on? And how will you handle the failure?
10:54rhickeymutable vectors and latest ensure code now in master
10:55Chouserexciting!!
10:55stuartsierraWhat's the purpose of mutable vectors in this case?
10:55cemerickvery good news :-)
10:55cemericknext week (hopefully!) we're going to set up our build system to always build against clojure's head automatically
10:56Chouserstuartsierra: chest-crushing, wind-whipping speed.
10:56stuartsierraoh my
10:56Chouser:-)
10:56stuartsierraIn a single-threaded context?
10:56Chousukestuartsierra: it's supposed to be a way to do a "batch update" I guess.
10:57Chousukea good example is into, I guess.
10:57Chousuke... I guess too many things.
10:57Chousuke:P
10:57NeronusChouser, rhickey: I want to do something to all the keys of all maps contained in a collection, recursively. i.e. if a map is found in a collection which is contained in another map, I want to do that for the keys of the innermost map, too. Anything that is not mappable is just left as it is
10:57rhickeystuartsierra: if you have a pure function returning a vector, but building that vector takes a lot of steps, you can get a thread safe mutable version of a vector in O(1), make changes to it in a functional style, just using assoc!, conj! etc, then get an immutable persistent vector to return in O(1)
10:58stuartsierragot it
10:58stuartsierrasmart
10:58ChouserNeronus: you probably just want 'coll?' then. Remember that Java arrays, Strings, etc. are mappable
10:58cemerickrhickey: the same thing is coming for all data structures, right?
10:59NeronusChouser: Again, not true for e.g. arrays
11:00ChouserNeronus: what's not true for arrays?
11:00Chousuke,(coll? (float-array 1))
11:00clojurebotfalse
11:00rhickeycemerick: sure, patches welcome :)
11:00cemerickah, I thought you had already started work on maps :-)
11:01rhickeycemerick: I haven't, but I think same the mechanism will apply
11:01cemerickI must have transformed a similar comment of yours in my head into ("...and I'm going to apply it to them forthwith!" :-P )
11:02lisppaste8rhickey pasted "hest-crushing, wind-whipping speed" at http://paste.lisp.org/display/84670
11:02stuartsierrawoah!
11:02rhickeynote how you don't even change the structure of your functional code
11:03cemerick*drool*
11:04NeronusChousuke: Chousuke demonstrated what I mean
11:05Chousuke:P
11:06stuartsierraThat actually answers a question someone brought up on the group -- what if the compiler could substitute mutable structures for immutable when it's safe to do so. It's not automatic, but that's what you've done here.
11:07Neronusgrr
11:07ChouserNeronus: you're okay with all such things becoming lazy seqs?
11:07cemericksometime last week, someone was talking about decorating fns with metadata indicating that they're pure, so that the compiler could do just that.
11:08NeronusChouser: Yupp
11:08Chouserwell, maybe contrib core sequable? is what you want
11:10lisppaste8rhickey pasted "safe at every speed" at http://paste.lisp.org/display/84672
11:10stuartsierraAh, but careful, (seqable? "string") is true.
11:10danlarkin*cough* bad pun
11:13LauJensenIs it just me, or this idea of a mutable vector a little icky and scary?
11:13clojurebotthis is not a bug
11:14rhickeyLauJensen: don't use them
11:14LauJensenrhickey: dont pout, I just meant generally, in a language which so fully defaults to immutable datatypes, isnt there a better way to handle this?
11:14stuartsierrarhickey: I think it's the scripting folks who want to write APIs that take either a single object or a collection.
11:15rhickeywhat happens when we define seq on non-collection objects to enumerate their JavaBean properties?
11:15stuartsierrai.e., a Thing and a collection of Things should be "the same." I don't agree, but I get it.
11:15stuartsierraRight, seq is more general than just collections.
11:16cemerickLauJensen: it's perfectly proper when used in conjunction with pure fns
11:16rhickeyLauJensen: better way to handle what?
11:16stuartsierraI think a universal "aggregate?" predicate might be useful.
11:16LauJensenrhickey: The fact that you want a mutable object
11:16rhickeystuartsierra: I guess I see seqable? as perpetually ready to break
11:16LauJensencemerick: How so ?
11:17rhickeyLauJensen: I don't want a mutable object, I want the fastest speed in a known, linear, isolated context
11:17stuartsierrarhickey: I agree. What people really want is a single predicate that asks "is this a single thing or a collection of things?"
11:17cemerickLauJensen: because you really don't care what happens to intermediate representations within a pure fn, you only care about the result value
11:17cemerickresulting*
11:17rhickeystuartsierra: exactly, and they will need to option to include strings or not in that logic
11:18LauJensenOk
11:18stuartsierraI think most people don't think of strings as collections, unless they grew up on C. :)
11:19LauJensencemerick: I follow that logic actually :) I just had the notion that all things mutable are evil.
11:19jdzworld is not black and white
11:19rhickeyLauJensen: the beautiful thing is, you write your app as always and only when you have a bottleneck need you tap into this capability, without restructuring your code. Also some library things will do this by default, like "into"
11:19stuartsierraLauJensen: I think *shared* mutable things are evil.
11:20rhickeystuartsierra: right and these things are unshareable
11:20LauJensenrhickey: Sounds good. So only when I have a vector operation which is taking too long will I use this. Got it
11:20LauJensenstuartsierra: Agreed
11:21rhickeyThey also don't support the persistent modification interface, so assoc/conj etc fail, so you can't accidentally leak them into code expecting persistent data structures
11:21LauJensenPerfect!
11:22LauJensenThat type of thinking really makes me love clojure - It protects me against me :)
11:22stuartsierraWithout preventing you from doing what you want to do when you know what you're doing. :)
11:23LauJensenI think this calls for a T-Shirt
11:23rhickeystuartsierra: well, they do in some sense, since for example you might be able to share mutable things between threads if you knew what you were doing, these prevent it
11:24rhickeyI think thread-local assurance is a huge deal, another safe model other than locks
11:24Chousermost languages attempt to protect you from yourself in some cases and to some extent, while letting you do "dangerous" things in other cases.
11:24stuartsierraOk, fair enough, but you can always create Java collections if you want to be really sneaky.
11:25LauJensenhehe
11:25rhickeywith a lot of power since it supports both composite work on one data structure and work involving multiple data structures
11:25Chouserthe question is how well does a particular language fit with your own experience of what is dangerous vs. what is necessary
11:25rhickeystuartsierra: true, I'm trying to make it so you'd never be tempted by that
11:25Chouserthis drives some people to enjoy coding in C, because they're unwilling to give up direct pointer manipulation.
11:26cemerickthe answer to that question is probably directly corollated with the quality/type of programmers you have around you
11:26stuartsierraCode us not into temptation, but dissociate us from mutability.
11:27rhickey:)
11:28LauJensenrhickey: Could you define what you mean when you say 'thread-local assurance' ?
11:29rhickeyLauJensen: rhickey pasted "safe at every speed" at http://paste.lisp.org/display/84672
11:29rhickeyIf you try to use one of these mutable things from other than the thread on which they were created it will throw an exception
11:30LauJensenThats awesome!
11:31rhickeyIt when coupled with O(1) to/from immutable+persistent, this is, IMO, game-changing
11:32stuartsierrayes, yes
11:33LauJensenrhickey: You should get a blog going and sell subscriptions :) I dont want to be the one to tell you to charge, but I think you could :)
11:34stuartsierraActually, sounds like a good topic for one of the functional programming conferences.
11:34stuartsierraIFL 2009 is coming up.
11:34stuartsierraRight across the Hudson. :)
11:34Chousermaybe it'd be easier to sell a writeup as an article to a magazine that already has a compensation model.
11:36cemerickdo authors get paid for magazine articles anymore? (outside of the mainstream press?)
11:37stuartsierraa little, not much
11:43angermanso with all this parrallelism of clojure can we have some math libs that serioulsy use the parrellism and show that clojure is fast?
11:45stuartsierraGo for it. :)
11:46rhickeyangerman: there's a third leg to to this Clojure perf work - parallelism, safe mutability, and finally primitives in Clojure's vectors and fns, the latter is still to come, and will be 'limited' to longs and doubles
11:46stuartsierrawhy longs & doubles?
11:55LauJensenstuartsierra: ints are too small, doubles have similar speed to floats? :)
11:56cemerickLauJensen: I've been advised by people who would know that doubles *should* be faster than floats in general.
11:57LauJensenCool - I wasnt quite sure so I took the safe route: theyre similar :)
11:58cemerickI've yet to benchmark the difference in our case, but the rationale I heard made sense to me at the time. :-)
11:58stuartsierraok, just curious
11:59NeronusChouser: yeah, thanks, sequable? works for me
11:59clojurebotWhy are you asking *him*
11:59cemerickparallelizable primitive arrays! I never thought I'd see the day :-P
12:02hiredman~botsnack
12:02clojurebotthanks; that was delicious. (nom nom nom)
12:02rhickeystuartsierra: because longs and doubles can accommodate the smaller primitives without loss
12:03stuartsierraOk, but what if you had a huge array of 'short's?
12:03rhickeyfloat->double byte->short->char->int->long
12:03cemerickstuartsierra: RAM is cheap?
12:03stuartsierraAnd they wouldn't fit in memory as an array of longs?
12:04stuartsierraI'm thinking search engines, where you might have a billion-element array.
12:04rhickeystuartsierra: oh well, memory is getting cheaper and bigger
12:04cemerickyou can always start packing bits
12:05cemerick(if you care that much)
12:06stuartsierraOk, I guess. Won't affect me personally. But I know people who never have enough RAM.
12:06rhickeybut each supported type is a multiplier, i.e. supporting n arg types means n^num-args variations, I'm thinking 3 (Object/long/double) with support for up to 4 args
12:06stuartsierraI understand the problem.
12:07stuartsierraCode generation!
12:08rhickeythere may be some flex in the data structures vs fn calling, I'm mostly fixed on long/double for fns, it might be possible to have vectors of shorts going in/out as longs
12:09rhickeystuartsierra: it's not a code generation problem (FWIW, I generated the original IFn overloads in CL), it's a vtable size thing, I'm concerned about that getting out of hand
12:09rhickeyoh, yes, fourth leg of perf tuning is new new, in progress
12:10stuartsierraah, ok
12:11hiredman,(import 'clojure.lang.AFn)
12:11clojurebotclojure.lang.AFn
12:12rhickeyone thing's for sure, drawing conclusions about Clojure perf now is very premature, when all of these are in place it will be stunning
12:12hiredman,((new [AFn] (invoke [] "foo")))
12:12clojurebot"foo"
12:14rhickeyhas anyone tried new new's signature inference? (other than that ^^) :)
12:14rhickeynew new is now the only branch not merged into master
12:15Chouserrhickey: I started going through contrib again, but haven't had the time to finish
12:15Chouser...little time though it should take.
12:16rhickeyI swapped out future and promise, where else do we have proxy? xml I guess
12:16cemerickrhickey: I'll probably start beating on it next week.
12:17rhickeynew new docs in progress: https://www.assembla.com/wiki/show/clojure/New_new
12:17rhickeyvolatile now works
12:17rhickeyonly missing non-reflective self calls
12:17Chousukehmm
12:17rhickeyand stable names during AOT
12:18Chousukeparallel, inspector and xml have proxy calls.
12:18Chousukeand core_proxy of course :P
12:18cemerickrhickey: how are captured locals stored? It'd be great if they were actual fields, with nice (identical, when possible?) names...
12:18rhickeyparallel is going to be deprecated
12:19Chousukeheh
12:19Chousukewell, that's where most of the proxy calls are
12:19rhickeycemerick: they are but I am loathe to promise that. The semantics of this are simpler than classes with fields etc
12:20cemerickrhickey: for goodness' sake, think of the tools...! ;-)
12:20Jomyootwhat is the best editor for clojure these days?
12:20Jomyootstill Emacs?
12:21technomancysome things never change. =)
12:21rhickeycemerick: what I am trying to do is some up with a story I could explain without reference to Java/C# etc. Then and only then, there could be a description of the intended (non-portable) mapping to host constructs
12:21rhickeycemerick: think of Chouser, writing ClojureScript!
12:22cemerickheh
12:22rhickeycemerick: targeting Javascript is a big deal, and only going to become bigger IMO
12:23cemerickclojurescript is pretty crazily wonderful -- but still crazy :-)
12:23rhickeycemerick: Is GWT crazy, IYO?
12:24rhickeyJS engines *are* the VMs of the browsers
12:24ChouserGWT is crazier. Given the choice between writing in Java and Javascript, I choose Java.
12:24cemerickrhickey: in concept, no -- and neither is clojurescript. But I'm guessing the latter will always have a footprint issue.
12:24stuartsierraAnd these days they do JIT compilation, just like the JVM.
12:24hiredmanhuh, assembla turns ascii smilies into images
12:24JomyootDoes ECB work well with clojrue?
12:24Chousergah!
12:25ChouserJavascript! I choose Javascript!
12:25Chousersheesh
12:25technomancyJomyoot: ECB is kind of pointless for Clojure IIRC
12:25cemerickbut then, it's all in what you're doing, too. For the web stuff I care to bother with, I'd much rather have a very thin remoting layer so I can touch clojure fns running on the server super-easy.
12:25technomancyit's for Complicated Languages
12:25Jomyoothow come?
12:25Jomyoottechnomancy: what if i need project browser like in textmate?
12:26Jomyootshowing folder trees
12:26technomancyJomyoot: (a) you probably don't; you just think you do and (b) you can use speedbar by itself without ECB. =)
12:26cemerickI really dislike web development, which explains a lot of my preferences :-)
12:27rhickeycemerick: me too, ClojureScript is my best hope :)
12:31stuartsierraI always worry about *-to-JavaScript translators because you have to think about three layers at once -- the source language, the translator, and JavaScript. All three have quirks.
12:33alrex021How do I, if possible, use :gen-class and run compile in REPL? I am following the http://clojure.org/compilation hello example and get the following exception in my REPL: "Could not locate clojure/examples/hello__init.class or clojure/examples/hello.clj on classpath"
12:33Jomyoothow good is vimclojure?
12:34kotarakJomyoot: good (shameless advertisement)
12:34kotarakJomyoot: but has its quirks
12:34Jomyootkotarak: you made it?
12:34Jomyootwhat are the quirks?
12:34kotarakyes
12:34Jomyoothttp://kotka.de/projects/clojure/vimclojure.html it looks very good for formating though
12:34Jomyootlining up the columns
12:34cemerickstuartsierra: js is the new bytecode? *shudder*
12:35Chousercemerick: so clearly it needs a way to embed source filename and linenumbers
12:35Chouser:-)
12:35stuartsierracemerick: it's true though, look at Chrome, Gmail, iPhones, Palm's Web OS...
12:36kotarakJomyoot: it uses the introspection of clojure to provide dynamic things. That means, that it tries to load the file you are editing. => it executes code, must not contain syntax errors... hiredman doesn't like that, for such cases you can turn off dynamic features and just use the static things vim provides.
12:36kotarakJomyoot: I used to this style and it works perfectly for me.
12:37kotarakJomyoot: the static things like formatting, syntax highlighting, static completion, are on par with emacs, enclojure, ... you name it.
12:38Jomyootso typically does emacs or vim wins?
12:38stuartsierraThat's been going on for decades.
12:38kotarakJomyoot: neither, a matter taste I guess
12:38rhickeycinc->js ftw!
12:39Jomyootcan emacs line up columns like in vimclojure?
12:39Jomyoothttp://kotka.de/projects/clojure/vimclojure.html
12:39technomancysure; M-x align-regexp
12:39kotarakIt would be surprised if not...
12:39kotaraks/It/I/
12:42cemerickstuartsierra: all that heat just makes me want to dive under the bed until the market makes some real decisions. I don't want to go platform-hopping every 6 months because Google, Apple, Palm, and 500 spinning VC-backed pre-revenue "companies" collectively sneeze.
12:43ChouserI would guess the safe-mutable collections will be an even bigger win for JS VMs than it is for JVM.
12:43cemerickyeah, I'd presume the VMs' GCs are relatively primitive.
12:43stuartsierracemerick: In general, though, everyone's coalescing around HTML + CSS + JS as a user interface standard, for better or for worse.
12:45cemerickstuartsierra: oh, don't get me wrong, I think it's for the better! What I really dislike is getting led around by the nose by platform vendors, which is inevitable in any immature tech market.
12:45Chousercemerick: so quit whining and just use sliverlight already.
12:45rhickeyouch!
12:45stuartsierraSure, the mobile world is going to be hairy for the next couple of years. But hey, three years ago we couldn't even write mobile apps.
12:46cemerickChouser: better throw out that wink really fast! :-P
12:46rhickeyI don't think js in browsers is going away
12:46Chouser;-)
12:46cemerick:-D
12:50JomyootIs Rich Hickey still using Aquamac?
12:54technomancyJomyoot: yeah, but he doesn't use slime
12:55technomancypresumably because he knows what the code will do before it executes. =)
12:55Jomyootwhy aquamacs and not carbon or cocoa emacs?
12:55Jomyootu know?
12:55LauJensenAnd he doesnt use a keyboard either.. he just stays at the compiler until it obeys
12:55LauJensenstares...
12:56technomancyJomyoot: I don't know. I have heard of a number of weird edge-casey bugs with aquamacs so I don't recommend it myself.
12:56technomancyalso since it's not portable it's hard for people to test on it.
12:56stuartsierraI use it, no problem.
12:56clojurebot"There is no problem in computer programming which cannot be solved by an added level of indirection." -- Dr Maurice Wilkes
13:02rhickeyso, I need a term for these single-threaded mutable collections that can share structure with the persistent collections. "Mutable" doesn't seem to do them justice, and has bad implications
13:02stuartsierra"fast"
13:02rhickeyheh
13:02rhickeyeditable views?
13:03rhickeybatch structures?
13:03stuartsierrathat implies some separate, concrete backing object
13:03stuartsierrabatch structures is ok
13:03rhickeystuartsierra: yeah, view is scary, since the source is inviolate
13:04stuartsierra"protean"
13:04stuartsierra"mercurial"
13:05stuartsierra"builder structures"
13:06stuartsierra"growth structure"
13:07stuartsierra"fillable container"
13:08Chousukefillable container sounds redundant :P
13:08stuartsierra"agglomerator"
13:08rhickeybreeder/composer/producer
13:09stuartsierra"accumulator"
13:09rhickeyinteresting
13:10rhickeycached
13:10rhickeyvery overloaded I know
13:10stuartsierrayeah, "cached" makes me think memoization
13:10stuartsierra"collector"
13:11rhickeyassembler, maker
13:11rhickeyooh, collector
13:12kotarakdrain
13:12rhickeyput your data in the drain? :)
13:12rhickeyhrm
13:12durka42can you flush the drain?
13:13stuartsierracollector/accumulator because they're like accumulator functions in Common Lisp loops.
13:13Chousukehoard :P
13:14stuartsierraThat's actually not bad, you're hoarding a collection. :)
13:14rhickeystuartsierra: hmm, that analogy isn;t helping me. but I like collector. Whatever name wins could replace (mutable coll) and needs a counterpart for yielding the immutable result
13:14stuartsierra"finalize"
13:15rhickeyurk
13:15kotarak(flush (drain coll)) :P ;)
13:15stuartsierra:)
13:15stuartsierra"realize"
13:15stuartsierra"conclude"
13:15rottcoddthaw/freeze
13:15Chousuke"seal"
13:15rhickeyalso, one of the things you can do with these is only remove things, in which case you aren't collecting items, but changes
13:15Chousukeand unseal
13:16rhickeyIf it could incorporate some sense of the linearity/single-threadedness that would be good too
13:17stuartsierraisolate / share
13:17rhickeyexcept (isolate x) doesn't
13:17stuartsierraok
13:17stuartsierratap / untap
13:18stuartsierracrack / seal
13:19stuartsierraimmediate / persistent
13:20Chousuketether/unleash
13:20rhickey(foo immutable-thing) -> threaded-mutable-thing -> (bar threaded-mutable-thing) -> immutable-thing, none of which affects or hinders immutable-thing
13:21stuartsierrathreadify / unthreadify :P
13:21danlarkinI like mutable/persistent, not sure why you don't like mutable though
13:21Chouserit's cute that immutable! has a ! but mutable does not.
13:22stuartsierratransient / persistent
13:22rhickeydanlarkin: well, and ArrayList is mutable too, but much less powerful
13:22rhickeyan ArrayList
13:22rhickeyand less safe
13:23rhickeyso there are two notions in my view, one is the data structure, and the other is the 'editing session'
13:23Chouserpersistent! is nice, then you just need a noun for the safe-mutable thing itself which can also be used as the "factory" fn name.
13:23kotarakeditor / save
13:25rhickeytransient, ephemeral?
13:25Chousukethread-bound?
13:25Chousukehmm
13:26rhickeytransient/persistent!
13:27Chouserchameleon
13:28rhickeyI like transient, any objections?
13:30Chouser"bum" is shorter and less PC
13:30rhickeyhah
13:30opqdonuthow about apple/orange
13:30ChouserI guess their transience is no less defining than their other features.
13:31danlarkinit's too bad there's no word that means exactly "locally mutable"
13:31hiredmanlocutable
13:31cgrandin-flux/solid
13:32rhickeyI think the term is kind of open when applied to data structures, so this method can define it. It is a great counterpart to persistent
13:33Chouserinconstans propinquus
13:35rhickeytransient data structures "move" through various states, in a single-threaded manner
13:35rhickeythey are not memory holes subject to poking from multiple threads
13:35rhickeyand calling persistent! stops them
13:36danlarkinget-a-job!
13:36rhickeyChouser: is that a kind of bird or something?
13:37rhickeyvery funny that transient makes you guys think of drifters
13:38Chouserrhickey: that's a lame attempt at a latin phrase for locally mutable
13:38ChouserI just find it interesting that when other sciences need to name things, they string together latin words until it's unique and then apparently truncate to one or two syllables
13:39rhickeyI like the sense of motion and the implied short-livedness in transient
13:39rhickeyChouser: :)
13:39Chousukerhickey: plus it sounds cool and mysterious
13:39Chousukewhich is good for catching people's attention
13:39rhickeyChousuke: there you go!
13:40Chouserwhile comp. sci. hunts around for related english thing and then overloads it to death, "tree" being the classic example.
13:40rhickeyat least they'll have to consider what it means, with mutable they'll presume they know
13:41rhickeyok, well the bum objection notwithstanding, any other objections to transient?
13:43Chouserconclusive silence.
13:44rhickeyok, seems no one else likes it, but no one objects - transient it is - thanks for the help!
13:44Chouserha!
13:44rhickeywill be (transient pv) -> tv -> edit! tv -> (persistent! tv) -> pv
13:45Chouserand we can call the thing transients
13:45Chouserthe things
13:45rhickeyor bums
13:45Chousuke:P
13:46Chousertransient vectors -- that's indeed better than mutable vectors
13:46Chousukealso implies that you're not supposed to keep them around for long.
13:46rhickeyit's a great fit - sparked by your call for (persistent! x)
13:47Chouser"persistent" was stuartsierra
13:48rhickeyok, creds/blame to him when he gets back from lunch
13:52rhickeyand a persistent collection capable of producing a transient version? not all will be
13:53rhickeycurrently "editable"
13:55Chousertransable
13:57Chouseroverpaid
13:57rhickeyoh boy
13:58ChouserThe state prior to becoming a bum might be "lazy", but I guess that won't work.
13:58Fossi;D
14:01rhickeytransient == bum completely doesn't click with me, didn't even consider it
14:02Chousuketransient is apparently a PC way of saying it :P
14:02ChouserI didn't think of it 'til very late. Wasn't a particularly natuarl association.
14:03ChouserI think it was the plural form "transients" that made it click.
14:04rhickeyit's a Java keyword, wonder if that will be a problem
14:05rhickeySun's JVM seem pretty tolerant of names, but IBM's isn't
14:05jwhitlarkWhat's the best way to suggest a minor update to the docs?
14:06Chouserha! even in Java transient means not persistent.
14:06ChousukeI wasn
14:06Chouserjust different meanings of both. :-)
14:06rhickeyChouser: for another definition of persistent
14:06ChousukeI wasn't even aware of transient. :/
14:06Chousukethe keyword that is.
14:08jwhitlarkIt would be helpful if the http://clojure.org/java_interop page had a quick note on the requirement to import java inner classes; it took me quite a while to find out.
14:08jwhitlarkfinally found it here: http://bradfordcross.blogspot.com/2009/05/using-inner-classes-from-clojure.html
14:08jwhitlarkso it appears I'm not the only one.
14:09ChousukeI think it is mentioned there.
14:09Chouser"Note that nested classes are named EnclosingClass$NestedClass, per the JVM spec"
14:09Chousukejust not very noticeable. :/
14:09rhickeyjwhitlark: it's in the second paragraph in the explanation of the Dot form
14:09Chousukehm, looking through the list of java keywords, strictfp seems to be the only other keyword new to me.
14:10ChouserI wonder if a FAQ would be more scannable for some of these issues
14:10jwhitlarkyea, I got the $ part of it, it was having to import it that wasn't obvious.
14:10jwhitlarkunless I'm still missing something.
14:11Chouserwell, the class name itself has the $ in it.
14:11rhickeythe transients have moved in: http://github.com/richhickey/clojure/commits/master
14:11technomancyjwhitlark: me too; I thought importing the outer class would let you access the nested class
14:11jwhitlarkI'd import the parent class, and try calling it with the $ syntax. I didn't expect that I'd have to import the inner class.
14:12ChouserIf named Foo$Bar, Foo is a class but Bar is not -- must use Foo$Bar
14:12Chouseralso the #1 example for class name aliases.
14:12jwhitlarktechnomancy: that's it. It wasn't the naming that was confusing, it was the deliberate import.
14:13ChouserYou imported Foo and then tried to use Foo$Bar?
14:14jwhitlarkSomething along the lines of: "Inner classes must be specifically imported with the $ syntax" would have saved me a lot of puzzlement.
14:14jwhitlarkyea.
14:14jwhitlarkcoming from Python, so perhaps it's a leftover from that.
14:14Chouserbut they don't have to be imported at all, any more than other classes. :-/
14:15Fossiit's also non-obvious coming from java
14:15Chouseryou can say com.company.Foo$Bar with no import
14:17jwhitlarktrue, but when you do (import '(com.company Foo)) a portion of population is going to expect Foo$bar to work.
14:17jwhitlarknot saying it's right, just saying a single sentence addition would remove a stumbling block for some people.
14:18Chouserjwhitlark: I'm not arguing against a sentence, just not sure of the right wording.
14:19Chouser"must be imported" seems misleading
14:20stuartsierra"Note that nested Java classes are named OuterClass$InnerClass and must be imported as such."
14:20Chouserthe thing is, each unqualified class name used must be specifically named in an import
14:20Chouserstuartsierra: you saw you won?
14:21stuartsierrayes. :-D
14:21stuartsierraNot that it matters.
14:21jwhitlarknot sure what the wording should be.
14:21Chouserso whether it's a.b.Foo or a.b.Foo$Bar, you can't get away with only mentioning a.b to get to Foo or a.b.Foo to get to Foo$Bar
14:23jwhitlarkso what would be the best way to express that inner classes aren't a special case?
14:23jwhitlarkI think that's the assumption that got me into trouble. Thinking of the inner classes more as a member of field.
14:23jwhitlarks/of/or/g
14:24jwhitlarkdamn, got that wrong twice.
14:25jwhitlarkperhaps: Note that inner classes are not a special case, and must either be explicitly imported or fully qualified.
14:28jwhitlarka little redundant with the docs that are already there, but makes a potential pitfall clear.
14:44jwhitlarkChouser: what do you think? Is that closer?
14:45Chouserjwhitlark: yeah. any suggestion on where to put it?
14:47jwhitlarkwell, the second paragraph of the dot special form discussion seems reasonable, but where it would have really helped me is in api/import
14:48jwhitlarkI think either would do. I read them both several times when I was struggling with it.
14:49ChouserI think the import docstring is best. An example of Inner$Outer might be helpful there too.
14:49jwhitlarkinteresting aside: this is the first time I've had this type of problem with clojure. I'm *really* liking lisp and clojure in particular.
14:50jwhitlarkI think that would do very nicely.
14:51Chouser"Note that inner classes (such as Inner$Outer) are not a special case, and must be fully qualified (mypackge.myname.Outer$Inner) or explicitly imported.
14:51Chouser"
14:51rhickeyaren't they normally nested, not inner, classes?
14:52Chouserthis is where my knowledge of Java breaks down.
14:53Chouserlooks like both
14:53Chouserhttp://java.sun.com/docs/books/tutorial/java/javaOO/innerclasses.html
14:53Chouserhttp://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
14:53jwhitlarkhmm.. I think nested is more proper, but the one time I took a java course, the instructor called them inner.
14:53rhickeyinner classes have a relationship to their enclosing instance, nested are more generally just lexically nested, and are the ones you're most likely to use from outside the class
14:54jwhitlark"Note that nested or inner classes ..."
14:54jwhitlark?
14:54Chouser"Note that nested or inner classes (such as Outer$Nested) are not a special case, and must be fully qualified (mypackge.myname.Outer$Nested) or explicitly imported.
14:55jwhitlarkThat would have done it for me.
14:59jwhitlarkrhickey: I don't normally gush, but I wanted to thank you; even as inexperienced with clojure as I am, it feels like the most clean and powerful language I've ever used.
15:00rhickeyjwhitlark: great! thanks
15:19cemerickis it safe to say that clojure is "more dependent" on jit than typical javac'd java? e.g. a particular clojure operation/fn/program requires more "runs" before it's performance settles into a minima?
15:19cemerickthat's the impression I get, and I wonder if there's any basis to it.
15:21stuartsierradon't know, maybe the bytecode is less "efficient" on the first pass
15:39lizphello, shouldn't this expression return 5 - ((first '(+ 2 3)) 2 3) ?
15:39lizpit returns 3
15:39hiredman,(first '(+ 2 3))
15:39clojurebot+
15:39hiredman,((first '(+ 2 3)) 2 3)
15:39clojurebot3
15:39hiredman,((first '(+ 2 3)) 2)
15:39clojurebotnil
15:40Chousukelizp: that's because (first '(+ 3 2)) returns the symbol +, not the function
15:40hiredmanoh
15:40hiredmanduh
15:40hiredman,((first (list + 2 3)) 2)
15:40clojurebot2
15:40Chousuke('+ 3 2)
15:40Chousuke,('+ 3 2)
15:40clojurebot2
15:40hiredman,((first (list + 2 3)) 2 3)
15:40clojurebot5
15:40Chousukelizp: symbols have an interesting property: they look themselves up in things when used as functions
15:41Chousukelizp: but 3 is not associative, so you get nil; however, if there are two arguments, the latter gets used instead of nil
15:41Chousuke,('foo '{foo bar})
15:41clojurebotbar
15:41Chousuke,('fooz '{foo bar} 'default)
15:41clojurebotdefault
15:42lizpwhere can i read about the semantics of symbols/functions in clojure?
15:44Chousukelizp: keywords are also functions. as are maps, sets and vectors
15:44hiredmanwell
15:44hiredmanlizp: http://clojure.org/data_structures#toc10
15:45avital,'(+ 1 2)
15:45clojurebot(+ 1 2)
15:45avital,(list + 1 2)
15:45clojurebot(#<core$_PLUS___4094 clojure.core$_PLUS___4094@e5d622> 1 2)
15:45hiredmanlizp: http://clojure.org/vars
15:45hiredmanetc
15:45avitalso what is ' exactly?
15:45avitalisn't it the same as (list ...)?
15:45hiredmanquote
15:46hiredmannope
15:46hiredman,'a
15:46clojurebota
15:46Chousukeavital: it's "this is an unevaluated code literal"
15:46kotarak,a
15:46clojurebotjava.lang.Exception: Unable to resolve symbol: a in this context
15:46hiredmanit keeps the quoted symbol from being evaluated
15:46kotarak,(list a)
15:46clojurebotjava.lang.Exception: Unable to resolve symbol: a in this context
15:46kotarak,'(a)
15:46clojurebot(a)
15:46hiredman' is a reader macro for (quote …)
15:46kotarak,(quote a)
15:46clojurebota
15:47Chousukeavital: so while in clojure (+ 1 2) gets evaluated and produces 3, '(+ 1 2) produces the list that when evaluated as code would produce 3
15:47hiredmansomething quoted is what is read, without any evaluation
15:48avital,(eval 2)
15:48clojurebotDENIED
15:48avitaloh what
15:48Chousukeeval is not allowed :)
15:48avitalhehe
15:48avitalso i see that (eval +) returns the + function and (eval 2) returns 2
15:48Chousukeavital: but remember that clojure code is not text. it's made of symbols, lists, vectors, keywords, maps and sets.
15:49avitalis there another way to get the + function other than eval?
15:49Chousuke,+
15:49clojurebot#<core$_PLUS___4094 clojure.core$_PLUS___4094@e5d622>
15:49Chousukeof course, that has an implicit eval
15:49Chousuke:P
15:49hiredman,(find-var '+)
15:49clojurebotjava.lang.IllegalArgumentException: Symbol must be namespace-qualified
15:49hiredman,(find-var *ns* '+)
15:49clojurebotjava.lang.IllegalArgumentException: Wrong number of args passed to: core$find-var
15:49hiredmanbah
15:49lizphehe
15:49Chousukesince the symbol +, when evaled, produces the + function
15:50hiredman,(find-var (symbol (str *ns*) (name '+)))
15:50clojurebotnil
15:50avitalbut is there a more direct way?
15:50Chousukedirect?
15:50Chousukewhat could be more direct than +?
15:50hiredmanavital: what are you trying to do?
15:50hiredmanthe symbol + evaluates to the function +
15:51hiredmanso as long as the you don't quote it (stop evaluation) you will get the function
15:52hiredman
15:52avital_sorry lost the last few messages, so is there a simple way to get the + function?
15:52Chousuke:P
15:52Chousuke,+
15:52clojurebot#<core$_PLUS___4094 clojure.core$_PLUS___4094@e5d622>
15:52Chousukethere
15:52Chousukethe simplest possible way :9
15:53cark,(type +)
15:53clojurebotclojure.core$_PLUS___4094
15:53hiredmanthe symbol + evaluates to the function +, so if you don't quote + (stop the evaluation) you will get the function
15:53cark,(type '+)
15:53clojurebotclojure.lang.Symbol
15:53cark,(type (find-var 'clojure.core/+))
15:53clojurebotclojure.lang.Var
15:53avital_no but wait
15:53hiredman,(resolve '+)
15:53clojurebot#'clojure.core/+
15:54hiredman,(deref (resolve '+))
15:54clojurebot#<core$_PLUS___4094 clojure.core$_PLUS___4094@e5d622>
15:54avital_so can we make the ((first '(+ 2 3)) 4 5) example work with minor modifications?
15:54avital_,((first '(,+ 2 3)) 4 5)
15:54clojurebot5
15:54avital_doesn't work
15:54carkah nice hiredman =)
15:54hiredman((first `(~+ 2 3)) 4 5)
15:54hiredman,((first `(~+ 2 3)) 4 5)
15:54clojurebot9
15:54avital_wow ok what just happened there? :)
15:54Fossiwhat do you expect to get?
15:54hiredmanavital_: ~ is unquote
15:55hiredman,((first '(~+ 2 3)) 4 5)
15:55clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
15:55Chousukeavital_: ` is a special kind of quote, and ~ unquotes :)
15:55avital_oh right
15:55Chousukefo you get a list of a function, 2 and 3
15:55avital_ok great thanks"!
15:55Chousukealternatively, you could just use a vector :P
15:55hiredmanor a list
15:55carkavital_ : fossi's question might be worth answering
15:55Chousukethat IS a list
15:56hiredman,((first (list + 2 3)) 4 5)
15:56clojurebot9
15:56avital_cark
15:56avital_yeah sorry
15:56Chousukehiredman: the syntax-quoted thing is almost teh same.
15:56carkthis strikes me as a very strange way to do things
15:56avital_Fossi: I wanted to get 9, and hiredman's solution gives me 9.
15:56avital_I was just experimenting
15:56Chousuke,((first [+ - /]) 3 4) ; no need for quoting stuff
15:56clojurebot7
15:56carkoh ok
15:56piggyboxthis channel makes me feel like in #haskell...
15:56carkwell that's not idiomatic at all
15:56Chousuke(the things in a vector are always evaluated)
15:56Chouseroh dear
15:56Chousukeunless the vector is quoted, of course :P
15:56avital_DISCLAIMER: THIS IS JUST EXPERIMENTATION TO UNDERSTAND CLOJURE'S LIST SEMANTICS
15:57Fossiomg, now i get it
15:57Chouserpiggybox: what can we do to fix that?
15:57hiredmanfoo :: x -> a -> b
15:57hiredmannow it is just like #haskell
15:57Chousukehiredman: quick, do something cryptic with pl!
15:57hiredmanclojurebot: numbers!
15:57clojurebot(pl reverse $ (↕reduce range $ 10 () λxy (↕conj inc $ y x)))
15:57Chousukeexcellent!
15:57hiredmanactually I don't think I reloaded pl
15:57danlarkincult of lambda
15:58hiredman,(pl reverse $ (↕reduce range $ 10 () λxy (↕conj inc $ y x)))
15:58clojurebot(1 2 3 4 5 6 7 8 9 10)
15:59piggyboxlOlrz
16:04cemerickhah
16:04avital_so why would i ever use ' and not `?
16:04cemerickwhat's pl, anyway?
16:05hiredmanpl is a toy
16:05Chouseravital_: ` qualifies symbols into var names and class names
16:05hiredman,~a
16:05clojurebotjava.lang.Exception: Unable to resolve symbol: a in this context
16:05hiredmaner
16:05hiredman,`a
16:05clojurebotsandbox/a
16:05Chouser,[`foo `map `Integer 'foo 'map 'Integer]
16:05clojurebot[sandbox/foo clojure.core/map java.lang.Integer foo map Integer]
16:05hiredman,'a
16:05clojurebota
16:06avital_Chouser: my question was: if ` is a stronger form of ' that allow to use ~ inside, why would i ever use vanilla '?
16:06avital_oh
16:06avital_wht
16:06avital_hired just answered
16:06avital_sorry
16:06avital_hiredman: and what is sandbox/a... ?
16:07hiredmanit is a namespace qualified symbol
16:07avital_and why is it that 'a and `a are diferent?
16:07hiredmansymbols quoted with syntax-quote (`) are turned into full qualified symbols
16:07hiredmanmostly
16:08hiredman' is the traditional simpler quoting
16:08hiredman` and ~ and ~@ are used alot for writing macros
16:09avital_hiredman: what is ~@?
16:10hiredmanunquote splice
16:10avital_oh right
16:10Quiark,'a
16:10clojurebota
16:10hiredman,`(1 2 ~@(list 3 4 5))
16:10clojurebot(1 2 3 4 5)
16:10Quiark,`a
16:10clojurebotsandbox/a
16:11Quiark,`a#
16:11clojurebota__2992__auto__
16:11hiredmanoh, right
16:11tomojautogensyming is awesome
16:11hiredmangensyms working in syntax quote too
16:21lizpthanks btw!
16:58JAS415,a#
16:58clojurebotjava.lang.Exception: Unable to resolve symbol: a# in this context
16:59rhickeyfirst cut at transient docs - feedback welcome: http://clojure.org/transients
16:59Chousukefoo# is a special feature of syntax-quote
17:02technomancyrhickey: I love the notion that there shouldn't be any "we do this in clojure's internal implementation, but you shouldn't do this in your own code" moments.
17:02technomancyvery democratic
17:05Chousukelisp is (or claims to be!) all about that, isn't it :)
17:05angermanthickey: not bad, I was able to understand it, eh >:)
17:08Fossirhickey: good read
17:08JAS415I like using clojure as a java compiler
17:10angermanJAS415: isn't that what we all use clojure for? :)
17:11stuartsierrarhickey: good explanation of transients
17:11JAS415i guess i mean like pretending that java is the assembly language and then writing functions and macros that arrange the java into the right forms
17:11JAS415like clojure is the compiler
17:11mebaran151what version of clojure has transients?
17:12rhickeymebaran151: master
17:12mebaran151ah so it's bleeding edge stuff
17:12angermanJAS415: well, that's all Suns fault. If they hand's alised java with the jvm and java bytecode ...
17:14ChousukeJAS415: fortunately Clojure does not compile down to Java, but JVM bytecode.
17:14rhickeymebaran151: yes, I added that info on the page
17:15ChousukeI suppose as far as Clojure is concerned, Java is "just another JVM language" (also the implementation language, but...)
17:17jwhitlarkJAS415: That's exactly how I think of java, the new assembly language.
17:17mebaran151it's the new COBOL
17:17mebaran151or FORTRAN
17:17mebaran151which ever old school, excessively verbose, down to the metal language floats your fancy
17:18JAS415right, java is just another jvm language, except clojure has really good support for calling it
17:18JAS415so you can write a macro that programmatically arranges java into the right clojure code to suite your puroses
17:18ChousukeClojure doesn't call *java* code per se. it calls *JVM* code
17:18JAS415its like having a really really large amount of leverage over a language with a ton of libraries
17:19JAS415doesn't matter really
17:19JAS415concept is the same
17:19ChousukeI suppose the host interop matches best with java.
17:19mebaran151anyway are transients like tag types, only supposed to be used in dire emergencies?
17:19JAS415java just has most libraries
17:19JAS415fastest libraries too, which counts
17:20mebaran151eh, C has the most fast libraries, but I've never seen an ffi in which I really would invest a lot of faith
17:20jwhitlarkI used to be really down on java programmers, then I realized who I needed to be down on were people who *only* wrote java.
17:20ChousukeJAS415: Well, the libraries could be written in Scala or Groovy too
17:21jwhitlarkor jython, I suppose.
17:21Chousukemebaran151: transients look like they can be used pretty safely anywhere, but I doubt it's worth the trouble unless you have a code path that is a bottleneck
17:21JAS415hmm, do we have (.. macro or proxy or genclass for scala or groovy?
17:21mebaran151don't forget JRuby, you could have Clojure on Cleets
17:21mebaran151*Cleats
17:21jwhitlarkWhich is actually an interesting idea for me; I could use my knowledge of the python standard library form clojure. hmmmm....
17:22ChousukeJAS415: how do you call a Scala method from java?
17:22ChousukeJAS415: do that, then translate to clojure interop. That is your scala interop.
17:22mebaran151Scala builds things that look very similar to Java classes
17:22mebaran151languages like JRuby and Groovy probably require a bit more dancing
17:22Chousukenot to mention clojure itself.
17:22stuartsierraJRuby's not hard, I use it.
17:23ChousukeCalling clojure stuff through the java interop would probably look a bit ugly... :P
17:23mebaran151that's what I meant
17:23mebaran151it would be nasty to write a ruby on rails app in clojure, even though it's technically possible
17:23jwhitlarkwhat we need are reverse macros ;-)
17:24jwhitlarkassuming that doesn't have a meaning that I'm unaware of.
17:24stuartsierraWell, if you use Java calling conventions as your common denominator, all the JVM languages create Java classes/methods.
17:25headiusnot necessarily
17:26JAS415sorry didn't mean to be rude and dissapear, had to keep dinner from burning...
17:26mebaran151couldn't some languages make some sort of nasty bytecode that might violate the nice neat modle of JVM classes and methods
17:26stuartsierraNot if they want the JVM to run it.
17:26headiusjruby by default interprets code at first, so there's no classes or methods for "java" to call
17:26Chousuke,(.invoke (clojure.lang.Var/find (clojure.lang.Symbol/intern "clojure.core" "+")) 1 2) ; calling clojure through java interop...
17:26clojurebotDENIED
17:26Chousukedamn
17:27headiusstuartsierra: I think you're making some assumptions about what the JVM expects...it's extremely liberal
17:27headiusin scala, for example, you can't create a static Java method
17:27headiusit's simply not possible
17:28headiuson the other hand, a lot of scala's constructs can't easily be called directly from normal Java code because they've got mangled names or singleton abstractions or whatever
17:28headiusscala does some really wild and scary things with bytecode and class/method structures
17:28stuartsierraah, ok
17:28JAS415i was thinking about stuart, so for example let and def are private/public variables, defn- and def are functional equivalent (sort of)
17:28stuartsierraThat's scala's fault, then. :)
17:28hiredman~scala
17:28clojurebot{((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}
17:28headiusclojure does too, really... a class per function immediately makes it harder to interop because you have a million little classes to link against
17:29jwhitlarkThe transients docs look very good. I went in to it on one end having never heard of it, and came out with a good understanding of when and why I'd use it. In one pass.
17:29stuartsierraBut in Clojure you can generate nice normal-looking Java classes.
17:29headiuswhich are just a shim around a million little classes
17:29mebaran151jwhitlark, agreed
17:29Chousukeheadius: but, perversely, that's a requirement for smooth interop :P
17:29headiusbut yes, it's better for java
17:29mebaran151Clojure has really good conceptual documentation compared to most languages
17:29headiusjruby's various java interop options do the same thing, as does groovy's
17:29Fossino wonder
17:29Chousukeheadius: since it's the only way for every function to sanely implement Callable and Runnable
17:29jwhitlarkmebaran151: the best I've ever seen, actually.
17:30headiusin almost every case where a language needs to present a "normal" looking Java type, they go above and beyond their own data structures and usually produce something artificial
17:30headiusChousuke: jruby does something similar, but all in memory
17:30headiuswhen you compile a .rb it produces exactly one .class file
17:30headiusthat .class file generates method stubs on boot
17:30Chousukemebaran151: Rich does a good job at explaining the concepts, but the actual API docs have much room for improvement.
17:31mebaran151totally agreed
17:31mebaran151there is much room for something that's more navigable
17:31headiusso jruby doesn't have any easier time of interop...we still need to generate a synthetic Java type that is made up of our Ruby structures behind the scenes
17:32hiredmanhmmm
17:32mebaran151maybe even something like the noobkit docs for ruby, that present a hierarchy for documentation
17:32Chousukemebaran151: at least there are the "related functions" sections in the reference nowadays...
17:33JAS415it would have been cleaner if java had been implemented in clojure
17:33technomancyheadius: I submitted a talk for RubyConf on using Clojure's STM and data structures from JRuby, so hopefully we'll see some JRuby love there. =)
17:33headiustechnomancy: neat
17:34technomancyI love the way JRuby procs implement Callable; made it really easy to use them with Clojure.
17:35mebaran151I wonder if there would be a seamless way adapt multimethods to operate on a ruby class hierarchy
17:37mebaran151the clojure api could actually use a comments section
17:37headiustechnomancy: we could improve that consistency a lot...but where we have it it's nice
17:38headiusjruby's got a lot of baggage still
17:39mebaran151and maybe even quick notes as to what is lazy and what isn't
17:39headiusI'm obviously very interested in language interop in general
17:39headiusthere's a lot of people who will never use clojure and prefer jruby, but getting access to clojure's structures would be great for them
17:40headiusand lots of people who will never want to write ruby but use clojure, and then want to be able to interop with ruby apps or libraries
17:40JAS415clojure on ruby on rails
17:40headiusit's unfortunate there hasn't been more interest among other language implementers in building a common interop protocol
17:40mebaran151as I said, Clojure on Cleats
17:40headiusthe only people who've ever worked on one, as far as I know, are me and Attila
17:41headiusand mostly Attila
17:41JAS415the only thing i would worry about would be programs that use clojure/ruby/python/java/scala/groovy, where you have to have a huge breadth of knowledge to understand the entire codebase
17:42headiuswell, other than scala, those are all pretty easy to grasp at a glance
17:42mebaran151wouldn't the ffi stuff be a good conceptual starting point? it seems nasty, but I don't see any more common basis
17:42headiusmixing scala into any codebase scares me, but I'm still of the opinion that scala is like programming gymnastics
17:42mebaran151I've seen ruby C++ C projects before, so it can't be THAT bad
17:42JAS415haha
17:43JAS415yeah i just worry about getting the reputationi CL has for maintnence difficulty
17:43Chousukeheadius: every example of Scala I've seen thus far has been rather off-putting :P
17:43headiusthat will always be clojure's cross to bear
17:43headiusChousuke: I've seen some great examples of Scala...unfortunately I wrote all of them myself
17:44headiusdon't get me wrong, I like scala...but I fear it at the same time
17:44ChousukeI don't have a real opinion of Scala
17:45ChousukeAll the times I've tried to learn more about it I've been scared away by cryptic code.
17:45headiusme too
17:45Chousukesomething about the syntax just doesn't agree with me.
17:45headiusalex's book (pragprog) is pretty good, though I've only seen early drafts
17:45headiushe teaches scala from a rubyist's perspective
17:45mebaran151it seems to be weird to try to combine functional techniques with OOP
17:45mebaran151OOP is all about state
17:46JAS415its is pretty good in CL actually
17:46headiusyeah, it's a weird combination
17:46mebaran151I bought the scala book: it's a confusing hydra of a language
17:46headiusat least it feels weird in scala
17:46mebaran151well you have to do it differently: you can't use Java style oop
17:46headiusI still would rather write something like Duby for my static-typed code
17:46piggyboxwell, Scala isn't the first one to do that. OCAML comes into my mind
17:46mebaran151you probably want something akin to the multimethods or what not
17:46JAS415you use functional for certain things and oop for other things
17:46headiusif I ever got Duby finished
17:46ChousukeCL OOP is actually method-oriented programming :P
17:47mebaran151I don't think OCaml is modula one
17:47mebaran151* Simula style oop
17:47JAS415i mean, i find the java oop x-treme methodology to be kind of perverse
17:47Fossiwhat's a binary or in clojure?
17:47mebaran151where you have fields that you set
17:47ChousukeFossi: bit-or I think
17:47JAS415everything is an object? even abstract stuff? really?
17:47FossiChousuke: great. thanks.
17:48ChousukeJAS415: the thing with java is that it doesn't even adhere to the "Everything is an object" thing :P
17:49ChousukeSmalltalk does it right. Even code is objects :)
17:50mebaran151I remembering reading somewhere you can either represent objects as hashtables or closures conceptually
17:50JAS415yeah that's the idea behind scheme i think
17:50mebaran151the hashtable methdology with fields and such, just isn't such a good fit for functional languages, where as closures are a natural way to carry state in real functional languages
17:51JAS415they had factorial and actorial and it turned out to be the same thing :-)
17:51JAS415same code*
17:52mebaran151I don't know much about clos, but I've heard it's filled with Dragos
17:52mebaran151*Dragons
17:52mebaran151and Cruft
17:54JAS415dragons?
17:55mebaran151as in, it's a convoluted system
17:55mebaran151with lots of ways to do the wrong thing
17:55JAS415lisp in general is kind of like that
17:55JAS415enough rope to hang yourself
17:56mebaran151I found clojure a lot less crufty than most lisps: it enjoys a sensible design
18:00jwhitlarkheh. I'm certainly enjoying clojure more than I did elisp. Although I think I'm getting better at the later from my exposure to the former.
18:02JAS415i dunno, i guess it depends on what the definition of cruft is
18:03JAS415there are things in CL that are very very nice, but i never really touch, simply because i don't think to use them
18:05mebaran151it's nice to break with the past though
18:05mebaran151try reading an mp3 file in common lisp or anything like that
18:06mebaran151I can think of 10 Java libraries I can choose from with sane api's
18:06JAS415yeah definitely
18:06JAS415try even installing CL without already knowing how to do it
18:06JAS415i think it took me the better part of a week the first time i did SBCL, and I didn't even have it setup right
18:09ChousukeI think one huge benefit over CL that Clojure has are first-class hashmaps and vectors (and sets).
18:10Chousukepoor sets, always mentioned in parenthesis
18:10JAS415you can write some pretty macros with that stuff :-)
18:10Chousukeyes. and you don't need four sets of functions, one for each data type.
18:11mebaran151also found macro writing in clojure more approachable
18:12JAS415the helper macros being built in... helps :-P
18:12Chousukehelper macros?
18:12JAS415off the top of my head the `var# macro
18:12Chousukeahh, autogensyms
18:12Chousukeyes.
18:12JAS415i think there are others but that is the big one
18:13Chousukethe namespace-qualifying property of syntax-quote is almost as big, if not bigger :)
18:13JAS415yeah that's true, the trick there is figuring out how to circumvent it
18:14Chousukewhich is relatively easy.
18:14JAS415yeah :-)
18:14jwhitlarkI love sets. I had an interview question, where they changed the requirements to keep a unique list of items instead of all items, took me one second to change my code. Got the job.
18:16Chousukeheh
18:24mebaran151sets are an important data structure
18:24mebaran151very useful for the current project I'm working on which essentially does a little relational calculus
18:24mebaran151it's also nice that they are lazy (I think)
18:25technomancysets can't be lazy.
18:25technomancysince you'd have to realize the whole thing to determine membership.
18:25mebaran151that does make sense
18:25mebaran151but luckily I can map over them lazily
18:26technomancyif you're producing a list, yes.
18:26mebaran151which is where it matters (I don't hit the db, until I need the return value)
18:26mebaran151working with laziness has turned out to be a lot of fun
18:31ChousukeLaziness can sometimes surprise you though.
18:31ChousukeYou may not get what you think you should get :)
19:05cemerickrhickey: the transients document is very good
19:15lizphi! lets say i want to write the following macro: (defmacro aif [x y] `(let [it ~x] (if it ~y))) and have y be an expression that uses 'it'. my problem is that upon expansion ` makes 'it' become 'user/it' and 'it' doesnt exist..
19:16carkuse this form : ~'it
19:18lizpno, it is still user/it
19:19lizpfor example: (aif (+ 2 3) (print it))
19:19carkmhh there is something like it though ...let me check
19:19lizpok
19:19lizpok
19:19lizpsorry
19:20tomoj(let [it# ~x] (if it# ~y)) ?
19:21lizpthank you cark, it works
19:22lizpthis works: (defmacro aif [x y] `(let [~'it ~x] (if ~'it ~y)))
19:22carkoh great i was wondering how it was working here and not to your place !
19:22tomojisn't that a really bad thing to do, though?
19:22carkno it isn't
19:22carkbut i beleive it was made hard to do so that you don't do it by mistake
19:22lizpso ~' is basically unquote then quote?
19:23lizpotherwayaround
19:23carknot the same kind of quotes
19:23tomojindeed, but... why does lizp want to do it?
19:23carkthe aif macro is pretty standard lisp stuff
19:23avitallizp yes why do you want to do it?
19:23tomojit was made hard for a reason :)
19:23cark"a" stands for ...take a seat .. anamorphic
19:23avitalanaphoric
19:24carkoh
19:24lizpwhy do i want to do the macro or the ~' thing?
19:24tomojmaybe I don't understand what the macro is supposed to do
19:24avitallizp the whole macro
19:24carkavital:indeed =/
19:25carkyou could (if (retreive-customer customer-id) (print it))
19:25carkyou could (aif (retreive-customer customer-id) (print it))
19:25cark=)
19:26lizpyeah
19:26lizp:)
19:26avitalits a quite common scenario - you want to act if something is not nil
19:26avitalon that thing
19:26avitalinstead of writing a let each time
19:26tomojok, but suppose I have a variable "it" already
19:26avitalthis both saves space and makes the code more readable imho
19:26tomojthat macro clobbers it
19:26carkthough the macro you wrote won't work that way
19:26avitaltomoj: sure you have to take care
19:26carkand they can't be nested
19:27avitalyes if you want to nest such things you have to think of a different scheme
19:27carkso we have in clojure : when-let if-let
19:27tomojoh, gensyms don't work in this case, I see
19:28cemerickjeez, I pop into #haskell for a sec just for the hell of it, and this is the first thing I see: data G = G (G -> a -> b); f :: G -> a -> b; f (G g) a = g a; g (G f) h = f h; h = g (G f) (G f)
19:31avital,(source if-let)
19:31clojurebotjava.lang.Exception: Unable to resolve symbol: source in this context
19:31avitaloh
19:31cark~def if-let
19:32avitalcark thanks :)
19:36Chousukecemerick: what is that supposed to mean?
19:36cemerickabsolutely no idea
19:37cemerickI thought of popping in after hiredman got clojurebot to drop some scala :-)
19:37tomojlooks vaguely similar to the Y combinator to me
19:37Chousukeas far as I can tell it's some kind of recursively defined type and then a bunch of functions
19:37cemerick~scala
19:37clojurebotScala often gets in the way when trying to write neat code -- seen in #scala
19:37cemerick~scala
19:37clojurebot{((x: Any, y: Any) => (f: Function2[Any, Any, Any]) => f(x, y))(1, 2)((x: Any, y: Any) => x)}
19:37cemerickthere we go :-)
19:37hiredmanevaluates to 1, btw
19:38tomojthere apparently is a G combinator
19:38tomojapparently having something to do with "anaphoric" something or other, interestingly
21:42JAS415swing feels inelegant, this is kind of frustrating
21:43quidnuncAnyone know how to specify a DNS server when using pppoe client?
21:47quidnunc`Sorry, wrong chan
21:50slaneyare these sanctioned? ...like do proceeds help the dev effort? http://www.zazzle.com/clojure+tshirts
21:51hiredmanI think Chouser created the store
21:51slaneyok
21:51slaneycoolio
21:53hiredman2009:Feb:16:20:48:26 Chouser : blbrown: you should. I've currently got the keys to that account, but since the ideas are mostly not my own I've already said I'll give the proceeds (if any) over to Rich.
21:54slaneydanke
21:57Carkhquestion : is there a way to detect we're compiling during AOT compilation ?
21:58hiredman,(doc *compile-files*)
21:58clojurebot"; Set to true when compiling files, false otherwise."
21:58Carkhthanks !
22:04cemerickBrief/helpful comparison of transients to haskell's SP monad here: http://www.reddit.com/r/programming/comments/977mq
22:04cemerickor, actually: http://www.reddit.com/r/programming/comments/977mq/think_persistent_data_structures_and_functional/c0bo4md
22:13hiredman~max users
22:13clojurebotTitim gan éirí ort.
22:13hiredman~max people
22:13clojurebotmax people is 149
22:44cemerickhuh, that should be 164
22:48durka42does it not count often enough?
22:49hiredmannah
22:49hiredmanI reset it to 5 a while back to see if it was working
22:50hiredman~max people is 164
22:50clojurebotRoger.
22:50onats1question guys
22:50onats1when is clojure useful?
22:50hiredmanalways
22:51onats1im just curious about it.. as i've read the label..
22:51hiredmanclojurebot: rationale
22:51clojurebotrationale is http://clojure.org/rationale
22:51onats1hiredman, can you give me a scenario? like, and end-application that was done using clojure?
22:51hiredmanclojurebot
22:52hiredmanI have used clojure and htmlunit to do screenscraping with clojure
22:52hiredmanclojure and SuperCSV to do CSV processing
22:53hiredmanpeople are using clojure for hadoop jobs
22:53hiredmansome people are even using it for writing android apps
22:58onats1this is a fairly new concept to me
22:58onats1is it similar to haskell?
22:59hiredman~blip.tv
22:59clojurebotblip.tv is http://clojure.blip.tv/
22:59hiredmanI would check out the videos
23:00onats1alright
23:07arohneronats_: I'm making a website using it
23:07onats_arohner, deployed on what?
23:07arohnercompojure & apache on AWS
23:08arohneroh, and jetty
23:08arohnercompojure is a clojure web framework
23:47tomojto me compojure looks more like a tool for building web frameworks
23:48tomojI guess I'm just used to heavily opinionated frameworks
23:51arohnertomoj: you're not wrong, it is low level, but that's what we have right now. it hasn't been much of a hinderance though
23:52Carkhdid they manage to make expiring sessions yet ?
23:52tomojyeah, I think that's awesome
23:52tomojI have been pondering writing my own framework based on compojure
23:52tomojneed to learn clojure better first I suppose
23:53tomojactually I want to go learn seaside first since if I tried now it would just be a clone of rails
23:53arohnerCarkh: I haven't heard of anything, though I haven't been following the group closely
23:53Carkharohner: me neither ...
23:53Carkhthough i 'm almost done with an app
23:54Carkhand that's one of those things i still need to look into =/
23:54gkoWhat's the minimum JDK version to compile Clojure?
23:54Carkh1.5
23:54gkoArgh...
23:55gkoNo 1.4 ?
23:55Carkhnope =(
23:55gkoToo bad :(
23:55hiredmanwhy dod you need 1.4?
23:55hiredmando
23:56gkoOld machines
23:56gkoDEC OSF1
23:56hiredmanOh
23:56gkoCan find only 1.4.2
23:56hiredmanouch
23:57gkoyeah
23:57mebaran151so I've got a bunch of sets and I'd like to lazily combine them
23:57mebaran151#{0} #{0 6} #{0 6} #{0 6 12} #{0 6 12 18}
23:58mebaran151essentially I'd like this to look like a lazy list that would go 0 6 12 18 etc
23:58mebaran151how can I do this?
23:58hiredmansets are not lazy
23:59mebaran151no I know
23:59mebaran151but I'd like to lazily combine them