#clojure log - May 25 2011

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:07 mefesto`: is there a function in core that does the equiv of 'call ? https://gist.github.com/990307

0:07 amalloy: mefesto: ((:do-this callbacks))?

0:07 mefesto`: or contrib for that matter...

0:08 amalloy: but handles the nil case

0:08 offby1: In traditional Lisp, it'd be called "apply"

0:08 amalloy: offby1: untrue. in CL it'd be called funcall

0:08 offby1: oh.

0:08 amalloy: apply, which exists in clojure, unrolls the last argument as a list

0:09 Raynes: (-?> callbacks :do-this) ; Doesn't that do something similar?

0:09 amalloy: Raynes: nah

0:09 Raynes: Well, if you wrap it in an outer layer of parethesuzes.

0:09 I know it does something with nil.

0:09 amalloy: if my patch to -> had been accepted, then (-?> callbacks :do-this ()) would work

0:10 mefesto`: working on some gui stuff so the usage would be like: (login-prompt :ok-clicked on-submit :cancel-clicked on-cancel)

0:11 amalloy: mefesto`: you can use .invoke, though

0:11 Raynes: mefesto`: If you're working on Swing stuff, check out http://github.com/daveray/seesaw

0:11 mefesto`: amalloy: refering to the invoke-later stuff?

0:11 amalloy: (-?> callbacks :do-this .invoke) ; using clojure.contrib.core/-?>

0:11 Raynes: I bet you it's a thousand times better than what you're already doing.

0:13 mefesto`: cool thanks guys

0:18 tomoj: anyone know how cljque is different from lamina?

0:20 amalloy: scores way better at scrabble

1:33 dnolen: erg 1.2.0 / 1.3.0 math differences seem unreconcilable, I guess there's just no way to do a conditional compilation?

1:34 irreconcilable I mean.

4:15 markoman: what is this error: java.lang.RuntimeException: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.Associative

4:17 Chousuke: markoman: looks like you're trying to use a keyword where a map should go

4:17 perhaps you've accidentally done something like (get :key map)

4:17 hiredman: that actually will not throw any exception

4:18 ,(assoc :foo :bar :baz)

4:18 clojurebot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.Associative

4:18 hiredman: ,(get :key {})

4:18 clojurebot: nil

4:18 Chousuke: hmm, yeah

4:18 forgot about that

4:19 markoman: im using several assoc and assoc-in functions so they could have the problem?

4:22 i made a big change on codebase and got some errors, but debugging is pain

4:30 danbell: hey, is there a function that would give the result of a value passed through a function n times?

4:31 as in (stacker f n val)

4:33 amalloy: danbell: ##(doc iterate)

4:33 sexpbot: ⟹ "([f x]); Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects"

4:33 danbell: ah, forgot about iterate

4:34 amalloy: then you can use nth on that if you want it called specifically n times

4:34 __name__: iterate is awesome.

4:35 danbell: it would be less memory-efficient than a loop, though

4:44 amalloy: danbell: why do you think that?

4:45 danbell: doesn't it have to store all index < n results?

4:45 whereas a loop discards them?

4:45 amalloy: no

4:45 it's lazy; it can immediately throw away the previous result when nth discards it

4:46 danbell: REALLY

4:46 amalloy: REALLY

4:46 danbell: ha

4:46 that's my interest

4:46 not sarcasm

4:46 amalloy: *laugh*

4:46 anyway, yes, it can

4:46 &(nth (iterate inc 0) 1e7)

4:46 sexpbot: ⟹ 10000000

4:47 amalloy: &(long-array 1e7)

4:47 sexpbot: ⟹ #<long[] [J@4d76db>

4:47 amalloy: well, apparently sexpbot has enough memory for 10 million longs. but if he didn't, the former would still work

4:47 danbell: ha

4:47 well

4:48 I need to go put in the effort to get accustomed to dealing w/laziness then

4:48 amalloy: danbell: it's hard to get much done in clojure if you're not lazy

4:52 Fossi: that's, um, so weird

4:54 amalloy: Fossi: laziness jokes abound if you put in the effort to look for them

5:00 danbell: anyway, have fun. i'm off to bed

5:01 danbell: thanks, sleep well

5:02 raek: good morning, #clojure

5:07 __name__: HEllo, raek

5:07 *Hello

5:31 clgv: may it cause a problem if I use a macro to generate a body of an fn like: (list 'fn (mymacro param)) within another macro?

5:32 some how I dont get it to work properly

5:33 it says "CompilerException java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol" on the line of the macrocall

5:35 raek: clgv: you probably don't want to run the macro inside the macro. instead generate code that uses it

5:36 clgv: but in this case `(fn (mymacro ~param)) wouldn't work very well, since the fn special form does not evaluate the first argument in the usual way

5:37 for a function of no arguments, this works: (defmacro wrap-in-fn [body] `(fn [] ~@body))

5:39 clgv: but, you can use ordinary functions in a macro to build the generated expression: `(fn [~param] ~(myfn param))

6:06 Jeffrey04: erm, i'm going through Labrepl, and found this (boolean (some #(divides? arg %) nums)) in one of the sample code

6:06 may i know where can i get more explanation on the #(function_name arg %) part?

6:08 ?

6:09 Dranik: this is a lambda-function

6:09 # -- abbreviation to

6:09 fn [] ...

6:10 % -- is the single argument provided to that function

6:12 Jeffrey04: @Dranik so the equivalent form would be (fn [] (function_name arg)) ?

6:17 Dranik: Jeffrey04: no

6:17 moment...

6:17 Jeffrey04: @Dranik sorry, i think the equivalent form for #(function_name arg %) should be (fn [foo] (function_name arg foo))

6:17 ?

6:17 Dranik: yep, I think so

6:17 clgv: thx, raek. I'll try to get the last suggestion running. as far as I can see it should be possible to make it a function

6:18 Dranik: just check it out int the repl

6:18 Jeffrey04: @Dranik thanks

6:21 clgv: raek: just a comprehension question: shouldnt `(fn ~@(mymacro param)) work?

6:25 Chousuke: clgv: that depends. What do you expect it to do?

6:26 clgv: it works, but it might not do what you think it does :P

6:26 clgv: raek: oh well, I found the real error. the "mymacro" does some evaluation that is needed to generate the code and this evaluation fails since in the above constellation only the symbol is passed

6:27 hoeck: Jeffrey04: reader macro characters are explained (a bit terse) here: http://clojure.org/reader

6:29 Jeffrey04: @hoeck @.@ thanks

6:52 raek: clgv: yes. both `(some-macro ...) and (some-macro ...) are valid and does something and you need to understand the difference in how they are evaluated (the evaluation rules are actually pretty simple)

6:52 clgv: raek: yeah, I totaly forgot to check evaluation time when I tried to find the error

6:59 raek: just remember that the body of a macro works like the body of a function. the macro "function" receives the unevaluated code of its attributes and returns new code that the macro form should be replaced with (and then macro expansion happens again for the generated code until no macros are encountered)

7:00 clgv: raek: I basically understand macros but sometimes when trying to do something new non-trivial I get caught in a "trap" ;)

7:00 raek: ` (syntax-quote) is just a "template engine" for building nested lists (and other data strucutres) and resolving symbols, and can be used outside defmacros too

7:02 when writing a macro that consists of multiple parts, it can be more useful to define helper functions than helper macros

7:04 clgv: what is the easiest way to use the private clojure.core/assert-args?

7:04 or is there something similar somewhere?

7:07 I want some checking of the macro parameters like in clojure.core/let

7:10 raek: clgv: since it is private, you can't really assume that it will be there

7:10 clgv: it's probably safest to copy it to your own project

7:10 not very elegant...

7:10 clgv: yeah thats why I ask

7:10 raek: at least, that is how this guy did it: https://github.com/Kaali/pour

7:11 clgv: the macro seems nice to have in general.

7:12 raek: agreed :)

7:18 clgv: hmm it's still private in 1.3.0-alpha7

7:26 finally it works: ((juxt-map :plus + :minus -) 10 5) => {:minus 5, :plus 15}

7:26 :D

7:30 hmm I wonder if the order of the arguments is idiomatic...

7:32 symbole: Are there any resources on hacking the clojure compiler?

7:48 bpr: can someone help me understand recur a bit better? for example in http://paste.lisp.org/display/122247, why does map become (assoc map k v), (ie. it's not rebound to {}) but yet k and v pick up the new head of keys and values?

7:48 it seems like recur is evaluating [k & keys] keys

7:48 and [v & values] values

7:49 but not [map {}]

7:49 to me it seems that the map binding is being treated differently from the keys and values binding

7:50 bindings*

7:53 clgv: bpr: they use destructuring to get the first element and rebind the remaining ones to the same symbol

7:53 bpr: i know how k and v are updated

7:53 clgv: bpr: k = (first keys) and keys = (rest keys)

7:53 bpr: yes i know

7:54 clgv: well than what question remains?

7:54 bpr: the question is, if that's getting evaluated again, then why isn't [map {}]

7:54 clgv: oh the value on the right is only for initialization

7:54 bpr: oh!

7:54 clgv: it's only assigned the first time the loop is entered

7:55 bpr: cool, ty!

7:55 clgv: it's a bit tricky here because they use the same symbol names

7:55 bpr: yeah i'm working through labrepl, and i wrote that lol

7:56 now i see you can use :as when destructuring

7:56 clgv: yeah that as well. the full power of destructuring ;)

7:57 bpr: thanks for the help

7:57 clgv: writing the loop that way kinda reminds of prolog ;)

7:57 bpr: yeah it does lol

7:57 that thought struck me too

7:59 ejackson: is there a way to do (import com.foo.*) ?

8:01 clgv: ejackson: last time I checked there wasn't.

8:01 ejackson: this really is itchy now

8:01 but that's me being lazy i guess

8:01 bpr: according to labrepl it's use i think

8:01 let me double check

8:02 clgv: use is for clojure namespaces - import for java classes

8:02 bpr: oh

8:03 i missed that distinction

8:22 timvisher: hey all

8:22 i'm trying to use clojure-jack-in

8:22 and i'm confused as to the behavior i'm seeing

8:23 i'm on "GNU Emacs 23.2.1 (i386-apple-darwin10.6.0, NS apple-appkit-1038.35)

8:23 of 2011-02-25 on ssm-macbook.local"

8:23 I have clojure-mode 1.9.1 installed through elpa

8:24 and when I run clojure-jack-in from my project I get a long buffer about bootstrapping slime and then I get that a server was started but I can't connect to it in any way and I don't get a repl.

8:26 bpr: do you have slime-repl installed?

8:26 timvisher: nope

8:26 bpr: try installing that

8:26 raek: slime-repl comes with swank-clojure, if you use the clojure-jack-in approach

8:26 so you shouldn't need that

8:26 bpr: oh

8:26 raek: timvisher: did you install the snapshot version of swank-clojure?

8:27 like in this tutorial: http://technomancy.us/149

8:27 symbole: Make sure there's one version of swank-clojure inside .leiningen/plugins. I had an issue where two different versions caused it to fail.

8:29 timvisher: raek: indeed I did not.

8:29 i didn't know about that tutorial

8:29 i'll go follow that before i bother you guys any more. :)

8:34 thanks so much, kids! that fixed it.

8:34 as always you've been a magnanimous group of devs.

9:06 markoman: how do I make (unique [31 32 32]) -> [31 32]

9:07 it was some trick with set ...

9:08 clgv: markoman: its called distinct ##(distinct [31 32 32])

9:08 sexpbot: ⟹ (31 32)

9:08 raek: markoman: if you don't need to maintain order, use a set instead of a vector to keep the elements

9:09 markoman: can I use merge to add item to the set?

9:09 raek: markoman: you use conj

9:10 ,(conj #{1 2 3} 3 4 5)

9:10 clojurebot: #{1 2 3 4 5}

9:10 markoman: ok, thanks for both

9:40 lpetit: Hi there

9:41 Somebody willing to review some macro code I did ?

9:41 raek: lpetit: sure :)

9:41 lpetit: https://gist.github.com/990975

9:42 Should pretty self-explanatory given the examples

9:42 Now I'm not sure the macro impl is safe from pitfalls

9:45 raek: lpetit: I've been looking for something like this :)

9:47 lpetit: What 'bout the macro impl.?

9:47 (I'm no macro expert)

9:51 raek: do whatever you want with it

9:51 raek: lpetit: I think the implementation is clear. I have no objections :)

9:51 lpetit: raek: feww ;)

9:54 raek: maybe I would have used (if (empty? bindings) ...) instead of (if-not result ...), but since result will never be nil in any legitimate use case, I guess it doesn't really matter

9:54 lpetit: this macro would be nice to have in core.

9:54 lpetit: argh no, there's a problem. I'm trying to cheat with assert-args but it's not handled as expected, I suspect it's not used as a macro but as a fn, in my current impl.

9:55 For what usage have you been looking for it ?

9:56 raek: to be able to do error handling, but with the simplicity of -> or let

9:56 lpetit: ah, yes. you can't use the var quote trick for macros. you end up calling the underlying macro function as a function

9:57 (def ^{:macro true} assert-args clojure.core/assert-args) is another workaround

9:57 lpetit: raek: exactly what I've just added :)

9:57 tho #'clojure.core/assert-args

9:58 raek: lpetit: I would call "result" and "call" something like "binding-form" and "expr", I think

9:58 lpetit: indeed

9:59 imade: let's say I have a function last-but-one, which way is more idiomatic to implement it (last (butlast coll)) or (-> coll butlast last) ?

9:59 I have many implementations, but I am wondering if I should use -> more often

9:59 raek: lpetit: I was thinking of a small variation to your let-unless where handler-fn does is passed 'result' instead of the value returned from error-fn

10:00 imade: personally I find (last (butlast coll)) more readable

10:00 raek: imade: if the collection is a vector, you can do ##(nth (rseq [1 2 3 4]) 1)

10:00 sexpbot: ⟹ 3

10:01 lpetit: raek: mmm, you're right, it's an artifact of past versions where error-fn was used in client code to re-check the result of the let

10:01 raek: ,(fnext (rseq [1 2 3 4])) ; or even this

10:01 clojurebot: 3

10:01 imade: I think nth is dangerous, (nth [] 1) gives IOB

10:02 raek: lpetit: I think it is more general if you don't need some value to both convey thruthiness and a value

10:02 lpetit: yes, removing that right now

10:04 raek: this is why I sometimes miss algebraic data types in Clojure...

10:05 imade: in what situations would you use -> if at all?

10:05 lpetit: argh, assert-args causes some pain ... expanding into a call to itself which then expands to clojure.core/assert-args which then fails

10:05 clgv: imade: I love it for trying stuff in repl incrementally ;)

10:05 lpetit: will cheat with it and call it twice ;)

10:06 clgv: imade in some cases you can avoid using let to improve readability

10:06 imade: well, I think -> might also help sometimes to reduce lots of nested parentheses

10:07 raek: it's funny. this is the second time today that the problem of assert-args being private has been discussed

10:07 imade: clgv, how do you use -> to avoid let?

10:08 raek: lpetit: if wonder if copypasting in this case might be the most convenient solution...

10:08 lpetit: well ...

10:09 imade: clgv, I guess I misread, I think you meant that avoiding let in general helps to improve readability?

10:10 clgv: imade: (let [bla (+ x 2), blubb (/ bla 10)] x) => (-> x (+ 2) (/ 10))

10:10 imade: clgv, thanks, that's a good example

10:12 clgv: imade: in a repl scenario you could now easily add another function call on the result at the end easily

10:21 lenw: Hi all

10:21 if I have a list and i want to expand it into a map calling a fn for each entry to get the value what is a neat way to do that ?

10:23 opqdonut: there really isn't anything "neat", but you can do something like (into {} (for [val list] [val (f val)]))

10:24 or if you're feeling tricky, (into {} (map (juxt identity f) list))

10:24 imade: maybe zipmap can help too?

10:24 lenw: opqdonut: thanks thats a refreshing way to look at it - i was stuck

10:25 opqdonut: imade: I don't like zipmap

10:25 lenw: imade: i cant see that zipmap allows a fn for the val ?

10:25 opqdonut: especially I don't like (zipmap something (map f something))

10:25 but maybe I'm weird

10:26 lpetit: raek: new version https://gist.github.com/990975

10:26 imade: I'm a beginner, but if you want some specific keys for the map you created, then zipmap could be useful?

10:27 lenw: imade: yes that example from opqdonut would work for that

10:28 imade: yes, opqdonut example is neat

10:29 opqdonut: which one?-)

10:29 imade: the first one is more readable for me

10:30 I mean the (into {} (for [val list] [val (f val)]))

10:30 opqdonut: yeah

10:30 raek: lpetit: I just realized that there could be a probel with destructuring

10:30 *problem

10:30 opqdonut: I like that one too

10:30 lpetit: raek: listening

10:30 opqdonut: one can always abstract that out as a function that takes f and list

10:31 raek: maybe it would be better to replace [... ~binding-form ~expr] with [... value# ~expr, ~binding-form value#]

10:31 and then send value# to handler-fn

10:32 'cause it probably gets weird if you try to pass the expression {:keys [a b]} to handler-fn...

10:33 example: (let-unless nil? error-fn [[_ as bs] (re-find #"(a+)(b+)" s)] (success as bs))

10:34 in this case, [_ as bs] happens to be valid syntax for both a destructuring form and an expression

10:35 lpetit: raek: you're totally right

10:36 raek: that's what happens when one tries to be smart #autobashing

10:37 thanks for all these catches !

10:37 raek: your welcome :-)

10:37 're

10:37 faust45: 3

10:41 lpetit: raek: corrected version:https://gist.github.com/990975/6d5f6bde57e3bae9db24ae5c59c6c385afd547ce

10:43 raek: lpetit: I guess error# is not needed anymore, so the if-let could be changed into a if

10:43 lpetit: lpetit => going to bed

10:43 ;)

10:43 raek: right again

10:45 raek: cleaned up : https://gist.github.com/990975/cc31874d45256ad184c824997ee2a2b9d0679957

10:47 raek: lpetit: the last do form is redundant, and maybe the examples need to be adapted to the new usage of handler-fn

10:47 lpetit: raek: will not have the time to work more on this today

10:48 raek: something like etherpad, but with clojure syntax highlighting would be nice

10:48 lpetit: raek: indeed

10:50 raek: corrected: https://gist.github.com/990975/595209332e2e4583208b5b39bd696cdf911af1c7 (but examples not updated)

10:57 aav: lpetit: hi!

11:00 cemerick: aav: I think he had a meeting starting @ the hour. :-)

11:04 aav: cemerick: yep. he already told me :)

11:25 lonstein: damn I want this... http://cgi.ebay.com/ebaymotors/2008-Honda-XR-650L-MANY-UPGRADES-/320696339261

11:25 ww

11:58 Jeffrey04: sigh, I am still doing labrepl, is currently doing the mini_browser tutorial, and is getting this error

11:58 ompilerException java.lang.Exception: Unable to resolve symbol: code* in this context, compiling:(NO_SOURCE_PATH:557)

11:59 I tried this but it doesn't work (use 'labrepl.util :only (code*))

12:03 symbole: Jeffrey04: I never used labrepl, but is it in your classpath?

12:05 Jeffrey04: @symbole it should be, i tried this (use 'labrepl.util)

12:05 raek: Jeffrey04: you are missing the vector needed for options: (use '[labrepl.util :only (code*)])

12:05 Jeffrey04: and get

12:05 IllegalStateException source already refers to: #'clojure.repl/source in namespace: user clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)

12:06 raek: Jeffrey04: i think sertain vars are already referred in the user namespace (like clojure.repl/source). you could try to enter another namespace than user first: (ns user2)

12:06 Jeffrey04: @raek thanks @.@ i probably need to sleep now (0006 at my place here)

12:07 raek: in that namespace, only the vars in clojure.core should be referred

12:07 Jeffrey04: ok. good luck or good night then :)

12:09 Jeffrey04: @raek thanks, i will probably finish up the remaining things first, still have 3 steps to go :)

12:20 dnolen: OK core.logic compat with 1.2.X and 1.3.X for real now thanks to Clojure/core.

12:24 ejackson: impressive !

12:24 the big guns

13:52 amalloy: imade: i like (comp last butlast)

13:54 gfrlog: is there a convenience method for the (first (filter p coll)) pattern?

13:54 $findfn even? [1 2 3 4] 2

13:54 sexpbot: []

13:54 gfrlog: $findfn [1 2 3 4] even? 2

13:54 sexpbot: []

13:55 gfrlog: I guess that's as good an answer as any. :-/

13:55 sexpbot: thanks

13:57 cemerick: gfrlog: depending on what your predicate returns, some can work; otherwise, (first (filter …)) is idiomatic

13:58 gfrlog: cemerick: good point.

14:07 amalloy: dnolen: (if @cache @cache (other stuff)) is easier to write as (or @cache (other stuff)) if that's your actual code

14:07 dnolen: amalloy: true, lots of little things like that to fix in core.logic.

14:12 ataggart: dnolen: unchecked-multiply-int is a horrifically named fn

14:13 I put up a suggestion to create a separate namespace for those to shadow the regular fns

14:13 hiredman: namespaces? crazy

14:14 ataggart: dnolen: btw, why did you use the -int versions?

14:14 hiredman: PHP leads by example

14:15 S11001001: gfrlog: contrib has find-first

14:15 guess how it's implemented

14:16 dnolen: ataggart: because it's faster. idea lifted from gvec implementation.

14:17 ataggart: well crap, I guess that's why those fns are in core.

14:18 hiredman: ?

14:19 dnolen: ataggart: last I recall, rhickey wasn't against what you're suggesting.

14:21 gfrlog: S11001001: I guess I should remove my implementation of find-first (which is exactly what I called it) and just refer to that one.

14:26 amalloy: gfrlog: i try to avoid using contrib at all these days, with the apparent difficulty of moving from 1.2.x w/contrib to 1.3 with a bunch of libraries representing a subset of what exists in contrib

14:32 technomancy: well "contrib" as a library is straight up deprecated

14:32 amalloy: indeed

14:32 but on 1.2.x it's hard to use the modular-contrib libraries

14:33 and not all of them have been promoted. eg, my app depends on prxml, which simply doesn't exist in modular contrib afaict, so i'm stuck on 1.2

14:38 ataggart: amalloy: data.xml is sitting there waiting to be populated

14:41 amalloy: ataggart: yeah, i saw that

14:44 fliebel: ataggart: What does that mean?

14:44 ataggart: fliebel: what does what mean?

14:45 fliebel: ataggart: that data.xml is sitting around empty.

14:45 amalloy: fliebel: data.xml is the new-contrib place for prxml, but nobody's put any code there yet

14:45 fliebel: Uhm, so is prxml jst going to be copied there, or is it waiting for someone to come around and make something awesome?

14:46 amalloy: fliebel: prxml needs at least some minor fixes to work on 1.3

14:46 fliebel: oh, okay.

14:46 amalloy: eg, the vars it rebinds need to be marked as ^:dynamic

14:46 * fliebel remembers https://github.com/pepijndevos/ArmageDOM

14:47 amalloy: huh. i had to read that several times before pronouncing it right. it just *looks* french with only one G

14:48 the ar-maj-DOM

14:48 and i'm aware that there's only one G in armageddon; there are two Ds. thanks for the correction, google

14:48 fliebel: amalloy: Wait, you mean it's.. ah

14:48 * technomancy prefers armagetron

14:54 no_mind: raek: there ?

14:55 amalloy: technomancy: arrrrr, mage-tron! combining pirates, wizards, and technobabble, this movie has something for everyone

14:59 edw: technomancy: You around? Curious how one idiomatically connects to a remote, already-running swank server under the new clojure-mode regime.

15:02 technomancy: edw: here's what I use: http://p.hagelb.org/remote-slime.html

15:02 orthogonal to the new clojure-mode

15:02 I should package it up though

15:04 edw: Ah. So it obviates the need for the (insecure) '... :host ""' in your START-REPL form... Nice.

15:06 raek: no_mind: yeah

15:07 no_mind: there are a lot of other people in this channel that knows enlive, so you could just ask the question :-)

15:07 no_mind: raek: ever used enlive to generate html ?

15:07 raek: ohk

15:07 edw: technomancy: I'm getting a "Symbol's value as variable is void: safe-tunnel-process" error.

15:08 raek: no_mind: by transforming a template document, yes

15:08 edw: Sould I just setq it to nil?

15:09 no_mind: I need to generate a form dynamically and wrote some code. Was wondering if someone can review it

15:09 technomancy: edw: yeah, incomplete paste, sorry. also set safe-tunnel-port to a number

15:10 edw: Ah, like 4005, fer example?

15:10 technomancy: aye

15:11 edw: Woot. Thanks!

15:11 no_mind: here is the code for generating a html input element http://pastebin.com/M3b8jLs3 Someone please review it

15:11 technomancy: edw: definitely need to get that into durendal or something

15:13 edw: technomancy: Whoa, that's some crazy shit in there.

15:20 technomancy: edw: what specifically?

15:25 edw: Crazy-awesome. I'd like font-lock in the REPL. Got a little enthusiastic there.

15:27 technomancy: there's a way to do that.... I forget how, but it's in durendal.

15:27 edw: Yeah, that's what I mean. Good stuff in there. Durendal, was that the ship's computer's name in Marathon?

15:28 technomancy: edw: yup!

15:28 actually it was Durandal, Durendal is an archaic spelling used in order to avoid MS trademark violations. =)

15:28 edw: Ah. I spent a lot of freshman or sophmore year being freaked out by that on my Mac IIsi.

15:29 technomancy: ah yes, the halcyon days when making a player read actual text in a video game wasn't frowned upon.

15:30 amalloy: i spent a lot of my high school and jr-high immersed in a MUD. probably wouldn't have learned to touch-type otherwise

15:30 edw: I really enjoyed reading Durandal's musings.

15:32 technomancy: everything I know about Latin I learned from Marathon.

15:32 always appreciated the shakespeare references too.

15:33 edw: Marathon prepared me to be freaked out by Event Horizon.

15:40 raek: no_mind: another approach is to make a element with a map: {:tag :input, :attrs {:type "...", :id "...", ...}, :content ()}

15:42 edw: Grr. How do I tell Emacs which SLIME I want a buffer associated with?

15:42 technomancy: edw: there's no good answer for that

15:42 I keep separate insntances

15:42 you can only have one active slime connection at a time.

15:42 edw: Of Emacs?

15:42 raek: no_mind: (at <tree> <selector for containing node> (append {:tag :input, :attrs {:type "...", :id "...", ...}, :content ()}

15:42 technomancy: yeah, separate emacs instances

15:42 I'm crazy like that

15:43 multiple slime connections can be open, but you have to manually switch between them

15:43 edw: I'm typing into Emacs on my linode box for IRC, through Emacs. Then I have my Cocoa Emacs, and an 'emacs -nw' going...

15:44 technomancy: I'm using VNC to type into the Emacs running ERC... I don't like restarting Emacsen.

15:45 technomancy: hah; dude... emacs -nw inside tmux.

15:49 edw: That's how I do my swank servers on my degenerate cluster of one...using screen(1).

15:49 * technomancy is using ERC inside tmux on an ec2 node

15:49 technomancy: M-x emacs-uptime => 142 days, 1 hour, 18 minutes, 51 seconds

15:49 edw: Nice. How do you clean out your ERC buffers?

15:50 technomancy: there's an erc-truncate module

15:50 amalloy: technomancy: that's like...almost half as long as i've known how to use emacs

15:50 technomancy: amalloy: hah; awesome.

15:50 edw: (I'm only at six days with my VNC Linode Emacs ERC connection.)

15:51 I had Emacs running SLIME48 with my consulting firm's web site running inside it for over a year.

15:52 Using screen, of course...

15:52 fliebel: What do Mac people in here use for IRC?

15:52 edw: Emacs.

15:53 cemerick: Colloquy is pretty common

15:53 I'd love to have a better option, but I don't think I could bring myself to pay for an irc client.

15:53 edw: Colloquy feels like it was made for warez traders.

15:54 cemerick: huh

15:54 jneira: i am learning emacs through typos

15:54 technomancy: limechat and irissi are also somewhat popular

15:55 dakrone: some people use adium also

15:55 cemerick: adium is pretty painful for irc IMO

15:55 fliebel: I did...

15:55 jneira: today i have learned c-c i

15:55 edw: Best just to stick with ERC in Emacs.

15:56 cemerick: technomancy: Hadn't seen limechat before, thanks.

15:56 amalloy: hey jneira, nice to meet you in here

15:56 fliebel: I'm trying it move everything to separate apps, so I can maintain some productivity.

15:56 edw: fliebel: M-x new-frame is your friend.

15:56 jneira: hi! a typo has guided me here ;-)

15:57 amalloy: jneira: what is C-c i? it isn't bound to anything for me

15:57 jneira: (lambda nil (interactive) (switch-or-start

15:57 (lambda nil (rcirc-connect "irc.freenode.net"))

15:57 "*irc.freenode.net*"))

15:58 ops

16:01 fliebel_: Hm, talking from a lemon now.

16:02 raek: I'm using irssi

16:05 * dnolen likes Colloquy

16:06 fliebel_: dnolen: my colloquy does weird stuff to growl :(

16:07 * raek still can't get over the fact that there is a JavaScript implementation in javax.script

16:07 fliebel: raek: Why not?

16:08 ordnungswidrig: how do I preserve the type of an associative structure?

16:08 ,(update-in [1 2 3] [0] inc)

16:08 clojurebot: [2 2 3]

16:08 raek: I really thought that Java and JavaScript had nothing in common except for their names...

16:09 amalloy: ordnungswidrig: looks right to me. what's the problem?

16:09 ordnungswidrig: raek: but?

16:09 raek: I'm just astonished

16:09 fliebel: raek: What did you expect? Lua? Or just nothing at all?

16:10 ordnungswidrig: amalloy: typical case of rubber ducking :-) The structure I tried to update and which I expected to be a vector after updating was a sequence all the time...

16:10 jneira: or groovy

16:10 raek: didn't expect the JVM to contain an implementation of another language

16:12 ordnungswidrig: amalloy: so my question is:

16:12 ,(map inc [1 2 3])

16:12 clojurebot: (2 3 4)

16:12 ordnungswidrig: ,(apply vector (map inc [1 2 3]))

16:12 clojurebot: [2 3 4]

16:12 imade: when calculating collection length I guess I would have to use only the long version of anonymous function, I can't do it with the #() macro like so (reduce #(inc %1) 0 coll))

16:13 amalloy: ordnungswidrig: clojure.walk/walk works but isn't very high-performance. converting a vector to a seq and then back to a vector can't be performant anyway

16:13 ordnungswidrig: amalloy: btw. I don't care about vector but about associativines for get-in / update-in

16:14 amalloy: which seqs do not have. After all I do some matrix updates.

16:14 ,(update-in [[0 1 2] [1 2 3] [2 3 0]] [1 2] inc)

16:14 clojurebot: [[0 1 2] [1 2 4] [2 3 0]]

16:14 amalloy: sure

16:15 do you care about performance?

16:15 ordnungswidrig: yes and no

16:20 I mean, at some point I think I will

16:21 amalloy: ordnungswidrig: you can't really use map on a vector and get out a vector: map converts its argument to a seq for maximum generality

16:22 (and for laziness)

16:23 if you have a vector, and want out a vector, you can use reduce: ##(let [v [1 2 3]](reduce #(update-in %1 [%2] inc) v (range (count v))))

16:23 sexpbot: ⟹ [2 3 4]

16:25 raek: if all elements should be updated, then could it be a good idea to simply build a new vector?

16:26 hugod: I thought this would trap the compile error, but it doesn't … (try (defn x [] (String. 1 2 3 4 5)) (catch IllegalArgumentException _))

16:27 amalloy: raek: i suspect that update-in*N will be faster than seq+map+vec, because it won't have to reconstruct the tree structure, but i could be wrong

16:28 hugod: the error is being thrown in the compiler, because there's no constructor for String that takes that many args: it can't convert that expression into bytecode

16:28 hugod: right, which is why it is in a try block

16:28 amalloy: hugod: the *execution* of that expression is in a try block. the compilation isn't

16:31 hugod: I thought top level forms were executed at compile time

16:33 raek: hugod: when a file is loaded, each top-level expression is compiled and then evaluated

16:33 "compile time" is a bit relative in Clojure

16:33 hugod: so there is no way of making that work without resort to reflection, mm

16:34 * hugod puts up his hand for eval-when

16:34 raek: hugod: the compiler would have emitted code that uses reflection if it could not determine which constructor you wanted to use

16:34 hugod: but in this case, there are no constructors with that signature

16:35 so the compiler won't even try to emit reflective code, since it knows it will always fail

16:35 hugod: right, I need to support two versions of an external dependency, and thought I could do that at compile time

16:36 hiredman: macros

16:37 hugod: hiredman: I guess so

16:38 dnolen: hugod: that's what I had to do to deal with supporting core.logic on 1.2 and 1.3, doing a top level thing just won't work. Macro lets you get around the problem.

16:38 raek: hiredman: something like this? (defmacro foo-constructor [args] (case api-version :old `(OldClass. ~@args) :new `(NewClass. ~@args)))

16:39 dnolen: hugod: w/ a macro, the compiler never gets a chance to see the wrong thing.

16:39 hiredman: raek: something like that

16:40 hugod: I don't think I have a constant available, so I'll have to use reflection to pick the correct code

16:40 dnolen: hugod: reflection in a macro isn't such a big deal tho right?, cache the result and all that.

16:40 raek: hugod: that's okay. macros have the whole Clojure language available to figure out what code to generate :-)

16:45 hugod: sure, just more work than "eval-when" would have been

16:51 manutter: heh, I thought I was a bit more advanced than that, until I started doing the 4clojure problems

16:52 "Heck, everybody knows how to write a fibonacci series in clojure, right?" Yeah, try it without the book in front of you.

16:56 amalloy: manutter: ##(take 10 (iterate (fn [[a b]] [b (+ a b)]) [0 1]))

16:56 sexpbot: ⟹ ([0 1] [1 1] [1 2] [2 3] [3 5] [5 8] [8 13] [13 21] [21 34] [34 55])

16:56 amalloy: er, ##(map first (take 10 (iterate (fn [[a b]] [b (+ a b)]) [0 1])))

16:56 sexpbot: ⟹ (0 1 1 2 3 5 8 13 21 34)

16:56 manutter: Nice

16:57 I got a slightly different one, but it passed

16:57 It was still humbling :)

16:58 amalloy: manutter: i found that one on rosettacode when i was still new enough that it astonished me. added a bunch of comments to the rosettacode entry, which was a tremendous help in understanding and remembering it

16:59 manutter: My favorite on 4clojure so far is "Implement reverse from scratch"

17:00 I had some big complicated thing in mind with loop/recur, and then all of a sudden I though of using reduce, and it frickin worked

17:00 amalloy: manutter: wanna see the shortest possible solution?

17:00 manutter: shortest fib? Sure

17:00 amalloy: no, for reverse

17:00 manutter: oh yea

17:00 amalloy: into ()

17:00 manutter: lol

17:00 jneira: hehe

17:00 manutter: That is shorter than mine

17:01 dnolen: hugod: might be worth searching the IRC logs for rhickey's thoughts on eval-when, I see he mentioned it around the time he devised AOT. I assuming there are other thing that need to be in place for eval-when to happen.

17:03 amalloy: manutter: i think Reverse Interleave is my favorite, because when i proposed it my implementation was "tricky", and i saw several people tweet a simple, elegant solution

17:05 jneira: i liked implement triangle-minimal-path

17:08 amalloy: jneira: i don't really like problems where there's a well-known algorithm for doing it, and the problem boils down to looking up the algorithm and implementing it in clojure

17:09 jneira: mmm is there a well-known algorithm to triangle? :-P

17:11 * offby1 stares blankly

17:12 jneira: i try to not google the answer or see #4clojure tl ones

17:14 with powerset i had to translate wikipedia algorithm, yours is more idiomatic

17:18 amalloy: jneira: i'm sure i've seen an algo for triangle path at some point, but i can't find it now

17:20 jneira: hah, here it is in scheme: http://community.schemewiki.org/?max-sum-triangle-path

17:21 jneira: amalloy: sure, but if you dont get it by yourself it is not so funny

17:23 my take https://gist.github.com/992016

17:24 i love map recursion

18:00 danlarkin: so it's possible to deliver on a promise that's inside a ref without being in a transaction

18:00 how do people feel about this

18:00 technomancy: you put anything but a value in a ref and all bets are off

18:00 danlarkin: or, even worse -- if you're in a transaction and it fails you could've prematurely delivered

18:01 offby1: then the value needs to be in an incubator for months until it's healthy?

18:01 technomancy: ,(instance? clojure.lang.IDeref (promise))

18:01 clojurebot: true

18:03 amalloy: danlarkin: it's also possible to swap! an atom that's inside a ref when you're not in a transaction. refs only manage one level of mutability for you; promises and atoms are another level

18:03 danlarkin: indeed

18:03 ok, problem solved -- I'll dispatch to an agent and have THAT deliver to the promise

18:04 then it won't happen unless the transaction commits

18:05 amalloy: yes. if you consider delivering to a promise as i/o, that's pretty normal

18:18 stirfoo: ls

18:26 symuyn: Hey, I'd like to take two vectors and get a pair of sets of indices of shared elements: [[5 3 1 2] [1 6 7 3]] → [#{1 2} #{0 3}]. What's the best way?

18:30 amalloy: symuyn: fwiw i don't see how your inputs relate to your outputs at all

18:31 ataggart: took ema while too. the first set is the indices from the first vector, etc.

18:31 symuyn: #{1 2} means that the first vector's elements at indices 1 and 2 (i.e. 3 and 1) are also inside the second vector.

18:31 Vice versa for the second vector.

18:31 Sorry about the example.

18:32 [['a 'b 'c 'd 'e] ['f 'd 'a 'z 'b]] → [#{0 1 3} #{1 2 4}].

18:34 ataggart: (filter (into #{} a) b) will give you the intersection

18:34 then you just need to pull the indices for each coll

18:35 amalloy: i mean, it's going to be an N^2 operation, and there are usually no one-liner ways to do such ugly stuff

18:35 ataggart: a set won't work if there are any duplicates, no?

18:36 ataggart: that depends on what problem he's trying to solve

18:36 amalloy: i guess

18:36 gfrlog: I don't imagine there's any way to generate all possible ways of matching a regular expression, is there? (re-seq) is not what I mean.

18:36 symuyn: Hmm, yes, it is pretty ugly in of itself

18:36 Thanks for the help

18:42 amalloy: gfrlog: to match against a given input string? or "tell me all input strings that would match this regex"?

18:42 gfrlog: a given input string; so:

18:43 given #"(.*)xx(.*)" and "abxxxbca" I want [_ "ab" "xbca"] and [_ "abx" "bca"]

18:43 amalloy: gfrlog: there is never more than one way, because the regex language has precedence rules built in: you will always get abc bca

18:43 er, abx bca

18:44 gfrlog: okay. so regular expressions themselves do not like this idea.

18:44 amalloy: no. it would lead to horrible amount of backtracking

18:44 imagine the re-seq like (a*)* matched against "aaaaaaaaaaaaaa"

18:45 gfrlog: well that would be an appropriate amount of backtracking

18:45 because if I'm asking for all ways to match that, clearly I'm asking for a pretty long seq back

18:47 you may as well say that the subsets function is worthless because it also does a lot of work when passed "aaaaaaaaaaaaaa"

18:57 stirfoo: you'd have to make the first kleene star non-greedy on one pass and greedy on the next, but that's only for the case given.

19:02 amalloy: stirfoo: i don't really follow. how would you use that technique to return ["aaaa" "a" "aaa" ...]?

19:03 stirfoo: amalloy: I meant it would only work for gfrlog's given example

19:03 definitely not a fix-all

19:04 amalloy: ah

19:10 scottj: wondering about alternate names for this macro: (if-pred string? cf/parse time) => (if (string? time) (cf/parse time) time)

19:11 amalloy: scottj: i called it transform-if

19:11 and made it a function rather than a macro

19:12 https://github.com/amalloy/amalloy-utils/blob/master/src/amalloy/utils/transform.clj#L4

19:12 scottj: how often do you use the f-not arity?

19:13 amalloy: mmmm, less often than the other

19:13 scottj: but making it a HOF is a win imo. i can do stuff like (postwalk-replace (transform-if float? int) some-data-structure)

19:15 scottj: amalloy: agreed, thanks

19:15 amalloy: scottj: feel free to just depend on amalloy/utils instead of writing it yourself, if that's more convenient for you

19:39 Null-A: Is there an emacs/slime feature where I can evaluate let bindings as var bindings

19:40 so with (let [foo 3] foo), I want to move my cursor to foo, type C-c C-?? and now (def foo 3) is executed

19:43 scottj: nope

19:44 Null-A: it's probably an easy elisp hack, but I don't know elisp very well

19:44 amalloy: Null-A: i doubt it's easy

19:44 technomancy: usually let bindings depend upon lexical scope, so that would only work in very limited cases

19:44 amalloy: what about (let [[foo] [10]])? what should that do?

19:44 technomancy: better to put a swank.core/break in there an inspect it live

19:44 Null-A: amalloy: I just want something for the common case

19:45 I would just eval the first 2 s-expressions that the cursor is on

19:45 in slime

19:45 wrap it with def

19:45 (def "foo 3")

19:45 (def <<foo 3>>)

19:51 scottj: (defun blah () (interactive) (save-excursion (slime-eval `(swank:eval-and-grab-output ,(concat "(def " (symbol-at-point) (progn (forward-sexp) (symbol-at-point)) ")"))))) figure out how to get symbol-at-point to be string and that might work

19:52 Null-A: oOo

19:53 amalloy: scottj: symbol-at-point won't work; it needs to be sexps

19:53 Null-A: forward-sexp brings the cursor to the end of the current sexp

19:54 http://www.emacswiki.org/emacs/ThingAtPoint

19:54 no_mindu: raek: could you please example code of generating html element using enlive based on the mapp method you suggested earlier. I am not been able to figure out how to use map to generate element

20:07 Null-A: scottj: do you know how to unquote in elisp?

20:07 its not ~

20:08 technomancy: Null-A: ,

20:21 Null-A: I've almost got this working in elisp, but there's something wrong with `(swank:eval-and-grab-output call

20:21 my function works fine in *scratch* but not in a clojure file

20:22 https://gist.github.com/992291

20:22 scottj:

20:37 how do I change the root binding of a var?

20:37 I think that's the problem I'm having

20:37 ataggart: ,(doc alter-var-root)

20:37 clojurebot: DENIED

20:38 ataggart: well damn

20:38 Null-A: heh

20:38 jedi: lol

20:38 Null-A: good enough

21:04 carllerche: I'm trying to tweak clojure-mode indentation for a 'defupstream' form, it works, but if I use a namespace (like foo/defupstream) the indentation tweak doesn't work anymore Is there a way around it? https://gist.github.com/1493b7c155f424b9c93b

21:05 amalloy: carllerche: clojure-mode includes a customizable var, clojure-defun-indents, as of like 1.8 or so

21:06 but i don't think that will fix the issue of (foo/defupstream)

21:06 carllerche: amalloy: so it seems it indents def* as a defun right now

21:06 amalloy: *nod*

21:07 carllerche: i guess i could use the namespace instead of require :P

21:08 amalloy: carllerche: i don't think anyone (technomancy?) really knows how the clojure indenter works anymore. i only added a few surface things, and i don't know how hard it would be to make */def* indent right

22:05 scottj: I added some def* thing to clojure-mode that actually doesn't work, can't remember if it was indenting or highlighting

22:20 arohner: I don't suppose anyone has a clever solution for the "lazy-seqs that require side effects, and need to clean up when they're done" problem yet?

22:23 amalloy: arohner: that's a pretty vague and general problem, isn't it? i don't think a single solution can fit all classes of the issue

22:25 arohner: amalloy: "all I need" is for some cleanup code to be called when the lazy seq is consumed or GC'd

22:25 hiredman: at work have a closeable seq, you just have to consume it inside a with-open

22:27 arohner: hiredman: oh, a protocol that extends c.l.LazySeq to have a .close method?

22:27 hiredman: yes

22:50 arohner: hiredman: is there a clever way to just add a .close method to an instance? I'm seeing several messy ways to do this, and no clean ones

22:52 mefesto: arohner: would a try/finally work? (try (consume seq) (finally (cleanup)))

22:53 arohner: also, it seems like there's room for a clojure fn to override an instance. (inherit inst (foo [x]...) (bar [x]). returns an instance of a new class, that inherits from inst. reflects all method calls to inst, unless overridden.

22:54 mefesto: conceptually, I really like the idea of making this integrate with with-open. "all you have to do" is return something that implements c.l.LazySeq, and also has a .close method

22:55 mefesto: arohner: oic, how is your lazy-seq implemented, just with (lazy-seq ...) ?

22:56 arohner: mefesto: I'm not sure how to implement it yet :-)

22:56 mefesto: since you want to use it with 'with-open im guessing it's some sort of io?

22:57 arohner: not io, but I do need to clean up when I'm done

22:58 mefesto: not sure if this helps but there is java.io.Closeable which you might be able to use in combination with proxy, deftype/record ...

22:58 Closeable is an interface with a close method that will be called by with-open

22:59 afaik, with-open doesn't require you to implement that ... just as long as whatever object it binds responds to (.close x)

23:03 arohner: is there something specific you are trying to do or just experimenting with clojure features?

23:03 arohner: mefesto: I'm using webdriver to scrape some pages. I want to generate a lazy-seq of urls from scraping. I want to close the webdriver instance when the seq is consumed/goes out of scope

23:06 mefesto: arohner: from what i've seen the lazy-seq is separate from the closeable resource. for example: https://gist.github.com/992465

23:06 arohner: notice how line-seq doesn't handle the opening/closing of the file from which it reads

23:10 arohner: mefesto: that's annoying. This is an experiment, we'll see how it goes

23:16 mefesto: arohner: why is that so annoying? :)

23:17 here's a comparison if line-seq was also closeable: https://gist.github.com/992465

23:29 tomoj: &(->> #(rand-int 2) (repeatedly 5) (fn []) (repeatedly 10))

23:29 sexpbot: ⟹ ((1 0 0 1 0) (0 1 0 1 0) (1 0 0 1 1) (1 0 1 0 1) (1 0 1 1 0) (0 1 0 1 1) (0 0 0 1 0) (1 1 0 0 1) (0 0 0 1 0) (1 0 0 0 0))

23:30 tomoj: what's a pretty and non-crazy way to do that?

23:30 suppose you could just partition

23:38 arohner: tomoj: yeah, I would cycle rand-int and then partition

23:38 err, repeatedly, not cycle

23:38 I always get those confused

23:40 &(->> #(rand-int 2) (repeatedly 50) (partition 5))

23:40 sexpbot: ⟹ ((0 1 0 1 0) (0 1 0 1 1) (1 0 1 1 0) (0 0 0 0 1) (0 1 0 1 1) (1 0 0 1 1) (0 1 0 0 0) (0 0 0 0 1) (0 1 0 1 0) (0 0 1 0 0))

23:48 tomoj: much better

Logging service provided by n01se.net