#clojure log - Apr 12 2011

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

0:41 currentB: how to I get the first result of a strsplit

0:41 damn wrong room disregard

1:39 dnolen: hmm some interesting optimizations are possible with case, https://gist.github.com/914995

1:44 predicate dispatch could be > 5x faster than multimethods in some cases and much more general...

1:45 amalloy: dnolen: multimethods have to support isa/hierarchies

1:45 and i don't see anything "more general" about hardcoding a big long case statement?

1:46 dnolen: amalloy: yeah I'm not interested in supporting hierarchies with this at all, only thinking about defrecord/deftype

1:46 amalloy: it would be "hardcoded" each method would modify the dag, and the optimized case statement be emitted.

1:46 s/would/wouldn't

1:46 sexpbot: <dnolen> amalloy: it wouldn't be "hardcoded" each method wouldn't modify the dag, and the optimized case statement be emitted.

1:46 amalloy: haha good old sed

1:47 dnolen: incidentally, if you're optimizing you might as well turn (case foo true a, false b) into (if foo a b)

1:47 or do you want to specifically catch non-booleans and barf on them?

1:50 hiredman: case is faster than (if (= ...) ...)

1:51 maybe faster than if period, given that if has to do nil checks, etc

1:52 dnolen: anyways food for thought, night.

2:12 devn: what /is/ the idiom in clojure for using and requiring? I've seen 100 seemingly different ways. Heavy :requires with :as, lots of :uses with :only, when do you choose which?

2:13 amalloy: hiredman: he was doing (case (= x y) ...); surely that's not faster than (if (= x y))?

2:13 devn: Not trolling, just curious at what people see the "standard" being in that instance?

2:13 amalloy: devn: i do some of both

2:13 devn: amalloy: what is the motivating factor behind each decision?

2:13 amalloy: can't easily explain which when

2:13 devn: Does it require a survey of the library?

2:14 amalloy: no, i don't think so. more about how related the library is to the core function of the file i'm in

2:14 hiredman: amalloy: if has to do a null check on the value

2:14 devn: an example?

2:14 amalloy: hiredman: really?

2:14 hiredman: so that is two branches vs. one for case

2:14 devn: ^very interesting

2:14 hiredman: amalloy: nil and false are falsy

2:14 amalloy: oh, of course

2:15 devn: (:use [somnium.congomongo :only [fetch update!]]) (:require [clojure.string :as str])

2:15 in a file that mostly does database stuff with a little string manipulation

2:16 hiredman: I mean, I haven't read the part of the compiler that implements it, but it must call RT/booleanCast or similiar, which without inlining must be even slower then branching twice

2:16 amalloy: arguably it should be the other way around, devn, but this way feels more natural to me

2:16 hiredman: yes, you're quite right

2:17 hiredman: I smell 1.3, jira is getting cleared out, the auto promotion of earmuffed vars to dynamic is gone

2:55 amalloy: hiredman: did someone decide on 1.3 vs 2.0?

5:46 matthias__: hrm, im trying to install penumbra with leiningen, but i only get a bunch of errors which i dont understand :(

5:50 you guys know a good, up-to-date tutorial on how to set up clojure with emacs on ubuntu?

5:50 the last one i used turned out to be outdated in the middle and im afraid i may have made a mess here

5:51 ejackson: matthias the best and easiest way is to use elpa as detailed in Technomancy's blog

5:52 here: http://technomancy.us/126

5:52 this looks like the same thing: http://davidhilton.wordpress.com/2009/07/08/clojure-getting-started-in-5-simple-steps/

6:32 matthias__: thanks, ejackson

6:33 ejackson: good luck, it's a bit of a fight the first time.

6:34 matthias__: looks like the stuff in technomancy's blog is also outdated :|

6:39 * clgv knows why he doesnt try to use emacs ;)

6:41 matthias__: what are you using?

6:41 clgv: eclipse with counterclockwise

6:42 matthias__: gosh, the emacs-starter-kit removes the menu

6:42 oh igot errors

6:47 he says "you really don't need these; trust me" in the init.el

6:47 clgv: lol hihi, sounds funny

6:47 matthias__: i can sure do without scrollbars and the toolbar, but i think i might wanna keep the menu. but maybe he's right? hmm

8:12 raek: matthias__: if you use emacs-starter-kit, then the readme for swank-clojure explains the rest

8:20 markoman: how is internalization, common terms and text translations used to implement in clojure apps?

8:21 joodie: markoman: I use a map of language -> term -> string/function

8:21 clojurebot: map and the other sequence functions used to be lazy, but with the advent of chunked sequences, may or may not be lazy, consult your local ouija board

8:22 joodie: (def strings {:en {:bla "Bla text" :foo (fn [arg] (format...))}})

8:22 combined with a function to extract the translation given a keyword and language

8:23 markoman: somehow i would need to provide a path to the term because translation is often in some context

8:25 joodie: you can make the path part of the key, or nest more maps.

8:26 markoman: true, im thinking, if namespace could be part of the key

8:27 raek: ,(ns-name *ns*)

8:27 clojurebot: sandbox

8:27 raek: you can use that to get the name of the current namespace as a symbol

8:28 markoman: how about getting name of the function I am in?

8:29 joodie: generally, you can't get the name of the function you're in

8:29 and I'm pretty sure you don't want to

8:30 clgv: markoman: you can write a frontend/wrapper to defn which enables you to get the name of the function you are in

8:30 markoman: in PHP i have __CLASS__ and __FUNCTION__ constants I can use for such tricks

8:30 or __FILE__

8:30 joodie: markoman: yeah, but in clojure you can move function definitions around

8:31 markoman: oh yes, true

8:31 raek: functions are just values, and vars can contain any value

8:33 clgv: the defn wrapper would do something like (binding [*function-name* fname] (do ~@body))

8:33 markoman: namespace could help a little but im afraid i need to be more specific with the path. the reduced problem is {:en {:kuusi "fir" :kuusi "six"}}

8:35 so I think if i can pass more precise path / context i can get right term

8:35 without too much har coding of course, im lazy by nature, lol

8:36 Chousuke: you could also do {:en {:kuusi ["fir" "six"]}} if you don't need the extra information about which is which

8:36 though hm

8:37 looks like you do :/

8:38 markoman: sure, but its not practical as is not my example. if hard coded its better: {:en {:tree {:kuusi "fir"} :number {:kuusi "six"}}}

8:38 Chousuke: I suppose you could mark localisable strings with a macro that replaces them with a function call that fetches the correct string at runtime

8:39 markoman: clgv: i need to play with that idea, binding

8:41 most often translatable terms are inside of hiccup forms...

8:42 so one idea would be to get class or id path of the term and use it for translation

10:11 sritchie: does anyone have any suggestions on a cleaner way to write this function ?

10:11 https://gist.github.com/915542

10:12 I'm looking to generate identity matrices, where each nested vector represents a row

10:15 mduerksen: sritchie: ##(vec (map #(assoc (vec (repeat 10 0)) % 1) (range 10)))

10:15 sexpbot: ⟹ [[1 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0] [0 0 1 0 0 0 0 0 0 0] [0 0 0 1 0 0 0 0 0 0] [0 0 0 0 1 0 0 0 0 0] [0 0 0 0 0 1 0 0 0 0] [0 0 0 0 0 0 1 0 0 0] [0 0 0 0 0 0 0 1 0 0] [0 0 0 0 0 0 0 0 1 0] [0 0 0 0 0 0 0 0 0 1]]

10:17 sritchie: mduerksen: hey, that looks great, thanks

10:22 mduerksen: you're welcome :)

10:24 ejackson: mduerksen: slick !

10:24 sritchie: ##(vec (for [row (range 5)] (assoc (vec (repeat 5 0)) row 1)))

10:24 sexpbot: ⟹ [[1 0 0 0 0] [0 1 0 0 0] [0 0 1 0 0] [0 0 0 1 0] [0 0 0 0 1]]

10:25 sritchie: cool

11:10 hugod_: ##(take 5 (partition 5 (cycle (concat [1] (repeat 5 0)))))

11:10 sexpbot: ⟹ ((1 0 0 0 0) (0 1 0 0 0) (0 0 1 0 0) (0 0 0 1 0) (0 0 0 0 1))

11:27 dnolen: fogus`: did you see my snippet idea of DAG -> case for predicate dispatching? I'm curious as to how you approached the problem. I've been reading over Efficient Predicate Dispatching and papers on how they do it in Standard ML.

11:43 TimMc: hugod_: Nice.

12:16 amalloy: hugod_: ##(cons 1 (repeat 5 0)) seems cleaner than concat

12:16 sexpbot: ⟹ (1 0 0 0 0 0)

12:18 hugod_: amalloy: indeed

12:47 cods: Is there a clojure mode for Emacs which is able to correctly indent case? (rather than aligning condition and expressions on the same column)

12:48 amalloy: cods: as far as i can tell that's the "right" way to indent case, bizarre as it seems to me

12:49 if you get the latest version of clojure-mode.el, i've added a variable you can customize that would indent this right: M-x customize-variable clojure-defun-indents, then add case to the list

12:49 mec: how do you save once you've done that?

12:50 amalloy: mec: save what? the customization?

12:50 mec: ya

12:50 cods: amalloy: ok, trying it. Sound interesting :)

12:50 amalloy: C-x C-s works fine, mec

12:50 the customization screen has Set and Save buttons if you prefer those

12:51 cods: thanks for bringing it up. i haven't used case since adding that feature, so mine still indents "wrong". nice to have it look more natural

12:51 cods: hmm, actually I meant cond, but case is similar.

12:52 amalloy: cods: if you don't like cond's indentation you're doing it wrong :P

12:52 should be (cond<RET>a b<RET>c d), which will indent fine

12:53 cods: sure if you don't break line between a and b :)

12:53 amalloy: mmm. that's harder. clojure's cond doesn't group pairs with parens, so emacs won't really be able to indent it (and there's no clearly "right" way)

12:54 i see people put a blank line, or a comma, after b in that case

12:54 cods: I get lost because I'm used to Common Lisp, where (cond (a b) (c d)) is less confusing

12:54 amalloy: cods: yeah. it's rather more cluttered; it's a compromise

12:55 i proposed at one point making (cond [a b] c d) equivalent to (cond a b c d) for just this reason

12:55 since a literal vector is always truthy, this doesn't seem to break any existing code

12:56 mec: you could always (defmacro my-cond [& body] (cons 'cond (apply concat body)))

12:56 amalloy: mec: no good

12:56 (cond a [b] c d)

12:57 or even (cond a (inc b)) - the list goes on

12:57 cods: mec: that what I was thinking, but I prefer conforming to the language, rather than trying to import my habits from another language

12:58 amalloy: well, i'll slop up a quick cond* and see if i like it

12:59 mec: Do i need to change anything else if i upgrade from clojure-mode 1.7.1 to 1.8.1 or just drop-in?

12:59 amalloy: mec: drop-in afaik

12:59 i did that when i was hacking it

13:09 cods: https://github.com/amalloy/amalloy-utils/blob/master/src/amalloy/utils/core.clj if you're interested

13:11 cods: amalloy: thanks :)

13:12 amalloy: cods: i've carefully engineered that to depend on my amalloy-utils: if you want to use cond* you have to either depend on my repo or look up lazy-loop and rewrite without it

13:28 fogus`: dnolen: I have not had time to look at it yet. I will do so ASAP

13:30 dnolen: fogus`: seems like you get get a near 6X speed increase over multimethods and a with considerable amount of additional generality.

13:31 supporting ad-hoc hierarchies might be tricky, but I'm not a big fan of those these days.

13:32 jcromartie: what general naming convention would you use for functions that return predicates?

13:33 make-<predicate>?

13:34 like (defn make-shorter-than? [n] (fn [x] (<= (count x) n)))

13:39 mec_: ,(#('%))

13:39 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (0) passed to: sandbox$eval71$fn

14:06 mduerksen: is there an elegant way to convert a record into a normal map, e.g. for sending it over wire? instead of (into {} rec)

14:08 amalloy: mduerksen: that's not elegant?

14:08 mduerksen: well, not elegant enough ^^ ideally it should work with nested records

14:09 thanks a lot i'm asking for, i know ;)

14:10 *thats

14:10 amalloy: mduerksen: (postwalk (partial into {}) nested-records)

14:10 well, that's obviously rubbish

14:10 but you get the idea

14:12 if you want to copy transform-if from my utils library, you could write (postwalk (transform-if #(instance? clojure.lang.IPersistenMap %) (partial into {})) nested-records)

14:12 mduerksen: postwalk? that's not clojure.zip, where is that function in?

14:12 amalloy: clojure.walk

14:13 dnolen: warning; postwalk is horrendously slow.

14:13 mduerksen: ah, that's great, thanks. i think i know what transform-if means, i have an own version of that in my source (i called it change-when)

14:14 amalloy: heh

14:14 mine returns a function rather than actually doing the change, which is handy for postwalk

14:15 jcromartie: how does "lein run" work? it says "No :main namespace specified in project.clj."

14:15 I have a key for :main with a symbol for my namespace with a -main fn

14:17 mduerksen: amalloy, dnolen: thanks. i take it as yet another nudge to look further than clojure.core

14:18 amalloy: dnolen: i'm always surprised by the number of people who want to use records, which seem to be primarily for performance, and then do all kinds of slow things with them

14:19 using hash-maps all the way i usually wind up happier

14:20 mduerksen: in my case, i use records to add protocols to them, performance is but a nice side effect. where i don't use protocols, i usually just use hash-maps too

14:22 amalloy: mduerksen: protocols are mostly a high-performance, low-flexibility version of multimethods

14:23 technomancy: jcromartie: can you paste project.clj?

14:23 jcromartie: https://gist.github.com/d3e77832ace0e60462fa

14:23 llahna: hi, can partial be used to bind other args than the first one?

14:23 jcromartie: llahna: you want fnil

14:24 amalloy: jcromartie: i don't think that's true

14:24 technomancy: jcromartie: no need to quote symbols in project.clj

14:24 jcromartie: amalloy: ?

14:24 technomancy: ah, ok

14:24 amalloy: jcromartie: he wants to not pass the arg at all, not substitute something for nil

14:24 jcromartie: technomancy: you kids with your tricky macros

14:25 amalloy: llahna: anyway the answer is no. you can use #(some-fn %1 default-arg %2), for example

14:25 clojurebot: Roger.

14:25 amalloy: clojurebot: seriously? knock it off

14:25 clojurebot: Oh, I know the best knock-knock joke! It goes like this... OK, you go first:

14:25 technomancy: jcromartie: yeah, defproject would be a real pain to work with if you had to quote every symbol

14:25 jcromartie: Sorry I thought I had seen fnil used as a way to bind things other than the first arg

14:25 llahna: jcromartie: thanks

14:26 amalloy: oh ok

14:26 jcromartie: llahna: not so fast... amalloy says you want what he suggested

14:26 mduerksen: amalloy: true. still, a record provides me a type for dispatch. with a plain hashmap, i'd have to put an type identifier inside the map

14:26 jcromartie: technomancy: I un-quoted the namespace but still "No :main namespace specified in project.clj."

14:26 If I use -m findex.core it works

14:27 amalloy: llahna: i have a reorder function, which lets you reorder the arguments to a function and get out a new function. if you really wanted to, you could do like (partial (reorder subs) 2) to get a one-arg version of clojure.core/subs that has the second arg auto-filled in instead of the first

14:27 jcromartie: maybe I'll just update lein first :)

14:27 amalloy: but in practice i think that will lead to more confusion than enlightenment

14:27 dnolen: amalloy: personally I think multimethods are stop gap until we get something much better. the type dispatch function is a ball and chain.

14:28 I mean the dispatch fn.

14:28 amalloy: dnolen: like what?

14:28 dnolen: amalloy: matching multiple things means constructing a collection, downstream users of the multimethod are ball and chained to your dispatch fn.

14:29 technomancy: jcromartie: wfm on 1.5

14:29 jcromartie: technomancy: I am on 1.5.0

14:29 derp

14:29 derp derp derp

14:29 never mind

14:29 I had two project.clj in my Emacs

14:29 technomancy: it happens =)

14:30 jcromartie: now, next up: where did stdin go?

14:31 I'm piping the output of find to this program, and in -main I have (println (line-seq (BufferedReader. *in*))) which prints nil

14:32 technomancy: yeah, that's an ant bug

14:32

14:32 jcromartie: hm

14:32 technomancy: they have no plans to fix it

14:32 jcromartie: so...?

14:33 I see

14:33 technomancy: have to use java -cp `lein classpath` clojure.main

14:34 dnolen: amalloy: efficient predicate dispatch and Haskell pattern match + guards - order/exhaustiveness issues are more interested direction than what we currently have.

14:34 jcromartie: that works

14:34 or do I need genclass in that case?

14:35 sorry, using clojure to actually run standalone programs is new to me

14:35 technomancy: jcromartie: you can use clojure.main to get a repl or clojure.main -e "(some-form)"

14:35 or if you're on 1.3 you can do clojure.main -m my.ns

14:36 * technomancy grumbles that -m didn't make it into 1.2 =(

14:44 duncanm: amalloy: is choffstein someone who shows up here in #clojure?

14:44 amalloy: he just wrote a blog post about hacking clojure

14:45 amalloy: yes

14:46 duncanm: amalloy: is that his irc nick?

14:46 amalloy: yep

14:46 duncanm: ahh, i 'll keep an eye out for him then, i want to find more clojure users in the boston area

14:46 amalloy: duncanm: you can $mail him

14:46 $help mail

14:46 sexpbot: amalloy: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.

14:47 technomancy: duncanm: there should be a boston meetup announced soon for the first week of may

14:47 or so I've heard...

14:48 duncanm: technomancy: oh cool, there was a meeting a few months ago that i went to, but it went silent afterward

14:48 technomancy: yeah, my boss is attempting to revive it

14:48 amalloy: duncanm: oh cool, i read the first half of that blog post but then got interrupted. neat to see that i'm at the bottom, and it explains why you asked me specifically

14:48 duncanm: technomancy: oh? who's your boss?

14:57 dum de dum

14:57 mec_: is it better to make a simple macro that makes a bunch of nested ifs, or a more complex one that rips them all into one if

14:58 duncanm: magnet:

14:58 amalloy: mec_: better still to use cond?

14:58 duncanm: mec_: what about cond?

14:58 mec_: err sorry, not ifs, lets

14:58 amalloy: *shrug* let is free. do what you find most readable

14:59 duncanm: the reason why traditional Lisps have LET vs LET* is a performance trade-off, right?

14:59 amalloy: duncanm: i don't think so

14:59 duncanm: actually, space trade off?

14:59 i don't remember anymore, i think we talked about it in my PL class when i was in school

15:00 parallel bindings can be executed in parallel (but I don't know if any LISP systems actually do this)

15:00 parallel bindings create a single new environment (scope) for all the bindings. Sequential bindings create a new nested environment for every single binding. Parallel bindings use less memory and have faster variable lookup.

15:00 so i'm not totally wrong here....

15:00 mec_: so a big let vs a bunch of nested are more or less equal?

15:00 hiredman: if (let [x 1] ..) ~= ((fn [x] ..) 1), then (let [x 1 y x] ...) ~= ((fn [x y] ..) 1 x)

15:01 mec_: beyond the obvious that is

15:01 amalloy: duncanm: that's probably only relevant in interpreted code

15:01 technomancy: it may have to do with clojure's lack of reified environments

15:01 amalloy: certainly for "faster variable lookup" i can't see that being true in compiled code

15:01 matthias__: when i start swank with lein swank and then connect to it using M-x slime-connect, it always says "versions differ bla bla"

15:01 is that bad?

15:01 amalloy: matthias__: nothing you need to worry about

15:02 duncanm: mec_: this is a good explanation: http://stackoverflow.com/questions/554949/let-versus-let-in-common-lisp/587837#587837

15:02 Bronsa: matthias__: put this in your .emacs => (setq slime-protocol-version 'ignore)

15:02 duncanm: but it's more geared towards Common Lisp

15:02 Bronsa: and stop worring about it

15:02 amalloy: i have in my .emacs: (eval-after-load "slime" '(setq slime-protocol-version 'ignore))

15:02 mec_: duncanm: is this valid for clojure tho?

15:03 matthias__: hmm, swank just got an exception. "invalid token: swank::"

15:03 amalloy: it's an artifact of the poor version-control practiced by slime devs, as i understand it

15:03 technomancy: amalloy: that's correct.

15:03 well, poor release management.

15:03 duncanm: mec_: Clojure doesn't have LET*, its 'let' has the same semantics as LET* in older Lisps

15:03 technomancy: absent release management, rather

15:04 duncanm: mec_: so unless you really want to signify some difference in scope stylistically, (let [x 1] (let [y 2] ...)) is equivalent to (let [x 1, y 2] ...)

15:04 hiredman: well, clojure does have a let* but let and let* both behave like common lisp's let*

15:04 amalloy: technomancy: yes, i was being vague rather than trying to find the exactly-specific-enough term :P

15:04 duncanm: hiredman: oh really? let* is a synonym of let?

15:05 hiredman: no

15:05 let* lacks destructuring support

15:05 duncanm: oh

15:05 mec_: let* is the builtin compiler function that let uses

15:05 matthias__: http://pastebin.com/YEVnzDb3 thats the exception i got from swank

15:05 can you help me?

15:05 duncanm: i didn't know that

15:05 hiredman: let* is the real primitive, let is a macro on top

15:06 duncanm: oh, well, at least that doesn't quite invalidate what i said

15:06 amalloy: &(macro-expand '(let [[x :as all] (range)]))

15:06 sexpbot: java.lang.Exception: Unable to resolve symbol: macro-expand in this context

15:06 amalloy: &(macroexpand '(let [[x :as all] (range)]))

15:06 sexpbot: ⟹ (let* [vec__18069 (range) x (clojure.core/nth vec__18069 0 nil) all vec__18069])

15:06 Chousuke: clojure doesn't officially have let* anyway

15:07 it's just an implementation thingy

15:07 duncanm: Chousuke: the naming makes it particularly confusing

15:07 Chousuke: I suppose, if you know CL

15:07 hiredman: it's like fn and fn*

15:07 duncanm: since LET and LET* have well-defined meaning in CL and Scheme

15:07 hiredman: ~scheme

15:07 clojurebot: scheme is Scheme is like a ball of snow. You can add any amount of snow to it and it still looks like snow. Moreover, snow is cleaner than mud.

15:08 hiredman: hmm

15:08 duncanm: (i capitalize when i talk about scheme/lisp identifiers)

15:08 hiredman: ~scheme

15:08 clojurebot: scheme is Scheme is like a ball of snow. You can add any amount of snow to it and it still looks like snow. Moreover, snow is cleaner than mud.

15:08 hiredman: bleh

15:08 kotarak: ,map

15:08 clojurebot: #<core$map clojure.core$map@b36022>

15:08 kotarak: ,MAP

15:08 clojurebot: java.lang.Exception: Unable to resolve symbol: MAP in this context

15:08 kotarak: hmmm

15:08 amalloy: kotarak: clojure doesn't SHOUT like common-lisp

15:08 kotarak: amalloy: I KNOW.

15:09 hiredman: ~please tell us what the hyperspec says

15:09 clojurebot: hyperspec is not applicable

15:09 duncanm: i got used to seeing uppercase identifiers, it's kinda nice that it makes them standout more

15:09 TimMc: kotarak: Checking for case sensitivity?

15:09 hiredman: clojurebot: why doesn't clojure do like what I read in the hyperspec?

15:09 clojurebot: hyperspec is not applicable

15:10 duncanm: otherwise, you kinda resort to some quoting convention

15:10 kotarak: TimMc: not really

15:10 amalloy: duncanm: blech

15:10 clojure supports unicode symbol names. upcasing them would be a disaster for letters you don't recognize

15:11 kotarak: amalloy: clojure supports ascii symbols. Everything else is an implementation detail.

15:11 technomancy: elisp does fine with quoting in docstrings like so: "Pivots down to the `bargle' position."

15:11 duncanm: i'm not saying it's great, but it's easy to follow that uppercase means it's some bounded identifier

15:11 technomancy: that's the elisp convention? `foo' like that?

15:11 fibeu: I have a quick qeustion: which IDE is best for doing GUI development in clojure?

15:11 technomancy: duncanm: yeah, erc even knows to highlight it

15:12 amalloy: duncanm: but it doesn't mean that! even in CL, if something returns the symbol A, you don't know if it's bound

15:12 hiredman: http://dev.clojure.org/display/design/Library+Coding+Standards

15:12 duncanm: fibeu: there's not a lot of support for GUI development in clojure - i do quite a bit of it, but i just use emacs, and i don't use any form designer

15:12 TimMc: fibeu: I don't think GUI dev is going to be much different from ordinary dev.

15:13 amalloy: &((juxt identity #(Character/toUpperCase %)) \u039b)

15:13 sexpbot: ⟹ [\Λ \Λ]

15:13 jweiss: is there a simpler way to write #(not (nil? %))

15:13 amalloy: (complement nil?)

15:13 longer, but simpler :)

15:13 fibeu: So I guess best approach is using java GUI builder to build classes and just call them from clojure?

15:13 kotarak: jweiss: % if you know it's not a boolean

15:14 amalloy: kotarak: ##(not (nil? 4))

15:14 sexpbot: ⟹ true

15:14 amalloy: he is effectively casting to a boolean, which yours doesn't

15:14 hiredman: ,(if 4 :x :y)

15:14 clojurebot: :x

15:14 TimMc: &(Character/toUpperCase \u131)

15:14 sexpbot: java.lang.IllegalArgumentException: Invalid unicode character: \u131

15:14 kotarak: ,(if 4 "o.O" "O.o")

15:14 clojurebot: "o.O"

15:14 hiredman: ,(if (not (nil? 4)) :x :y)

15:14 clojurebot: :x

15:14 jweiss: i just want to take-while from an infinite seq while it's not nil

15:15 TimMc: &(Character/toUpperCase \u0131)

15:15 sexpbot: ⟹ \I

15:15 jweiss: what pred to use

15:15 duncanm: fibeu: there's something nice about typing it all by hand, if you organize things

15:15 amalloy: &((juxt identity #(Character/toUpperCase %)) \u03bb)

15:15 sexpbot: ⟹ [\λ \Λ]

15:15 duncanm: fibeu: if you organize things just the right way, you can change the app while it's running

15:15 hiredman: if does an implicit boolean cast

15:15 kotarak: jweiss: (take-while identity ...) or (take-while (complement nil?) ...)

15:15 jweiss: the latter is more secure

15:15 jweiss: ah identity. that's it :)

15:15 kotarak: Ah

15:15 fibeu: duncam: yes, in the REPL, I tried some basic stuff with Swing, it is cool

15:15 amalloy: duncanm: ^ is the example i was looking for about why it would be evil to uppercase symbols

15:16 jweiss: it's iether going to be a string or nil, so i like identity

15:16 fibeu: reminds me of doing things in Smalltalk

15:16 TimMc: &(= (Character/toLowerCase (Character/toUpperCase \u0131)) \u0131)

15:16 sexpbot: ⟹ false

15:16 amalloy: &\0131

15:16 sexpbot: java.lang.Exception: Unsupported character: \0131

15:16 duncanm: amalloy: sure

15:16 amalloy: &\u0131

15:16 sexpbot: ⟹ \ı

15:16 TimMc: ^ This is why we don't do case-folding.

15:16 amalloy: TimMc: what dang character is that

15:16 TimMc: amalloy: Turkish dotless i.

15:16 duncanm: fibeu: yeah, but it takes a lot of care to do it right, often times, i just restart the app

15:16 amalloy: fun

15:17 duncanm: (well, kill the frame and start again)

15:17 amalloy: i guess i knew there were characters that didn't transition nicely, but i never would have found one. thanks

15:17 mec_: wow apparently there are limits on method length ;p

15:17 duncanm: fibeu: also, it's easy to accumulate too many dangling references in the REPL, and then you either can clear it out with (System/gc) or you have to restart your slime session (or you figure out some slime way to clean up....)

15:18 mec_: is that a JVM limitation?

15:18 amalloy: mec_: yeah, they're crazy large though. but you can't write your whole app in one big macro :P

15:18 mec_: I would assume so

15:18 amalloy: duncanm: yes

15:18 TimMc: amalloy: http://gizmodo.com/#!382026/a-cellphones-missing-dot-kills-two-people-puts-three-more-in-jail < Interesting case where lack of support for dotless i led to someone being killed. (Sorry for Gizmodo link.)

15:19 duncanm: dotless i? it's used in turkish or something?

15:19 fibeu: duncanm: hmm, never tried slime, I use IDEA

15:19 mec_: looks like the limit is 65536

15:19 duncanm: fibeu: oh, slime is what you'd use with emacs

15:19 i tried to like IDEA, but it just doesn't look very nice on the machines that I ran it on (mac and windows)

15:20 TimMc: duncanm: Turkish has both dotted and undotted upper and lowercase Is.

15:20 amalloy: mec_: 65536 of anything in particular? methods can't have more than 64k rubber ducks?

15:20 mec_: on the plus site nested let vs 1 big let doesnt seem to run any slower

15:20 TimMc: English has a dotted lower and an undotted upper. Localization hilarity ensues.

15:20 hiredman: k

15:21 mec_: i think it's characters but I cant be sure

15:21 hiredman: method size it bytes is limited to 64k I believe

15:22 fibeu: I think I will use netbeans to write some GUI classes in java, do the functional part in clojure and glui it together

15:22 duncanm: mec_: in Scheme, i think (let ((a 1)) (let ((b 2)) ....) is the same as (let* ((a 1) (b 2)) ....)

15:22 amalloy: TimMc: that's a pretty amazing localization story

15:22 duncanm: fibeu: i'd be interested to hear how that works out for you

15:23 fibeu: i write java code in NBs, but i neverg got around to using their form designer

15:23 fibeu: i wrote all the layout code by hand ;p

15:23 fibeu: oh, netbeans GUI designer is great I think

15:23 matthias__: hmm, according to something i found, my problem might be that i got the wrong version of slime, but i did install it with package.el

15:24 duncanm: fibeu: i just don't really like having generated code

15:24 but yeah, i should embrace it, it's a much easier/faster way to work

15:24 fibeu: Iyes, lot"s of boilerplate

15:26 amalloy: duncanm: write macros *you* understand to generate all the code, instead of letting a tool fill your program with code you don't understand

15:26 mec_: anyone know where let* is defined? all I can find is a reference in compiler of defining the symbol LET

15:27 wow dejavu

15:27 amalloy: mec_: it's in the compiler. the symbol LET is bound to Symbol.intern("let*")

15:27 mec_: but where from there?

15:27 duncanm: amalloy: yeah, that's why i want to write a define-action macro for Clojure+Swing

15:27 matthias__: swank keeps crashign with that unreadable message error :|

15:28 amalloy: LetExprParser, iirc

15:28 LetExpr.Parser

15:28 duncanm: amalloy: the idea is to kinda do SAM conversion, by making define-action return an AFn that also implements the given SAM interface

15:28 TimMc: It's in the Compiler.java file.

15:28 raek: matthias__: which slime version are you using? the one from emacs-starter-kit?

15:29 matthias__: yes

15:29 how can i check which version i have though?

15:30 raek: and you connect with M-x slime-connect?

15:30 matthias__: slime-20100404.1

15:30 yes

15:30 and then swank crashes

15:31 raek: I'm looking in my .emacs.d/ and I have that version too

15:31 matthias__: "unreadable message: (:emacs-rex (swank:autodoc (quote ("+" swank::%cursor-marker%)) :print-right-margin 80) "user" :repl-thread 4)"

15:31 raek: which version of swank-clojure?

15:31 matthias__: i got swank-clojure 1.3.0-SNAPSHOT

15:32 raek: same as the one I use too

15:32 matthias__: :(

15:32 raek: I'l try to update it

15:33 matthias__: swank crashed once i type more than a ( into slime

15:33 raek: ...and you don't have any old installation of slime lying around?

15:33 matthias__: *crashes

15:34 erm

15:34 raek: ok, this is strange...

15:34 matthias__: i dont know

15:34 i might have made a mess, i tried multiple different clojurei nstallation tutorials :D

15:34 but i removed the .emacs and .emacs.d and then installed the starter ki

15:34 t

15:34 raek: ok

15:34 that's good

15:35 matthias__: there's a slime package in ubuntu (assuming you are using some GNU/Linux variant). you don't have it installed?

15:36 matthias__: who knows B) ill look

15:36 i do

15:36 it actually seems to be a newer version

15:36 raek: try removing it

15:36 matthias__: on it

15:37 raek: newer versions are known to break compability with swank-clojure...

15:37 matthias__: yeah i heard

15:39 still doesnt work, but its different now

15:39 raek: did you install both slime and slime-repl with package.el?

15:39 matthias__: "exception in read loop

15:39 java.lang.Exception: Error reading swank message

15:39 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

15:40 yes

15:40 but who knows what else i had lieing around D:

15:41 raek: what does "java -version" say?

15:41 matthias__: java version "1.6.0_20"

15:41 OpenJDK Runtime Environment (IcedTea6 1.9.7) (6b20-1.9.7-0ubuntu1)

15:41 OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)

15:42 raek: matthias__: could you post the stacktrace somewhere?

15:43 matthias__: http://pastebin.com/53knb18c

15:45 raek: you could try switching the Java implementation to the Sun variant

15:46 matthias__: huh, i dont even get a repl anymore when i run slime-connect

15:46 is that normal?

15:46 used to see that fancy anymation right away

15:46 amalloy: no

15:47 matthias__: can i open one manually?

15:47 amalloy: that's a broken, there

15:47 matthias__: i got a *slime-events* buffer

15:47 so is openjdk known to cause issues or was that just a wild guess?

15:48 raek: I'm not sure, but getting an exception from sun.reflect.NativeConstructorAccessorImpl.newInstance feels suspicious :/

15:49 matthias__: hasnt crashed this time, but i cant try running code because i dont see a repl

15:49 i uninstalled cl-swank and something else. dont even know why i had cl stuff, never used it

15:50 hiredman: raek: that is just a reflective call to a constructor

15:53 raek: matthias__: anyway, here's some instructions on how to install the sun jvm: http://www.webupd8.org/2010/09/how-to-install-java-jre-and-java-plugin.html

15:54 matthias__: does the problem persist if you use swank-clojure 1.2.1?

15:55 matthias__: uh

15:56 how i do that?

15:56 raek: how do you start swank-clojure currently?

15:56 matthias__: lein swank

15:56 do i have to uninstall 1.3.0 and install 1.2.1?

15:57 raek: matthias__: did you add swank-clojure to you project.clj or did you do a lein plugin install?

15:57 in the latter case, yes

15:58 mec_: How could I do this? `(foo ~(rest (bar-macro ~@body))) I want to replace the head of the result from (bar-macro ~@body) with foo

15:58 matthias__: yeah, the latter

15:58 raek: lein plugin uninstall swank-clojure "1.3.0-SNAPSHOT" && lein plugin install swank-clojure "1.2.1"

15:59 matthias__: "Plugin "swank-clojure 1.3.0-SNAPSHOT" doesn't appear to be installed.

15:59 " what the hell :|

15:59 raek: mec_: you can't, since that subsitution will hapen after the foo macro is done

15:59 Chousuke: mec_: hmmh, that's a bit tricky

16:00 raek: or can you?

16:00 mec_: (cons `foo (rest (macroexpand-1 `(bar-macro ~@body)))) works but seems iffy

16:00 Chousuke: I was about to type something like that

16:01 it's not that bad :/ the macroexpansion still happens at macroexpansion time so it's not like you're using eval or something :)

16:02 tsdh: Why are there no nightly clojure builds since december last year?

16:02 amalloy: do you control bar-macro? it sounds like it would really rather be a function than a macro

16:02 tsdh: sun hasn't gone down yet, in antarctica?

16:02 mec_: amalloy: ya I was just thinking about pulling bar-macro out into a helper function that is referenced by both

16:02 matthias__: oh, there's lisp connection closed unexpectedly: connection broken by remote peer in *messages*

16:02 but swank doesnt seem to have crashed

16:03 tsdh: amalloy: ;-)

16:03 Chousuke: you could also use the macro function instead of the macro so you don't need macroexpand-1.

16:03 but that's maybe overkill :P

16:03 mec_: do what now?

16:04 Chousuke: ,(@(var defn) 'foo '[args] 'body 'here)

16:04 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol

16:04 Chousuke: hmm

16:04 oh right macros take the weird extra args too :/

16:04 amalloy: Chousuke: it wants some nils for &env and &body

16:04 Chousuke: never mind, best not try thtat then :D

16:05 matthias__: erm, i had something about 1.2.0 in my project.clj :|

16:05 amalloy: ,(#'and nil nil 'a)

16:05 clojurebot: a

16:05 matthias__: i dont even remember where i got that one

16:05 still not getting a repl in emacs

16:05 mec_: are &env and &body supposed to be anything besides nil?

16:05 matthias__: is there really no way to manually start a slime repl?

16:05 amalloy: mec_: the compiler sets them

16:05 matthias__: yes, you manually start it with slime-connect

16:05 that's it

16:06 matthias__: :(

16:06 how i find out why it doesnt work?

16:06 raek: matthias__: so you have put a more recent one in your project.clj and done lein deps?

16:06 amalloy: it can't start a repl with a swank server it can't connect to

16:06 matthias__: i didnt do line deps

16:07 got a bunch of artifact missing errors

16:07 it did say it connected

16:07 Connected. Lemonodor-fame is but a hack away!

16:08 perhaps i need to add some kind of repository for lein

16:08 hmm

16:08 raek: you have the latest version of lein?

16:09 you could remove lib/, add [swank-clojure "1.3.0-SNAPSHOT"] to project.clj and a lein deps again

16:09 swank-clojure is in clojars, so you shouldn't have to add any repo

16:10 what artifact is missing?

16:10 also, do you still have the global swank-clojure install (form lein plugin install)? if so, you don't need any in project.clj

16:11 matthias__: i cant tell which is missing

16:11 now it worked (after i removed it from project.clj)

16:12 the lein deps that is

16:12 raek: sounds like a typo

16:13 matthias__: "[leiningen/lein-swank "1.3.0-SNAPSHOT"]" iswhat is said before

16:13 raek: ooh, that's also old... :)

16:13 matthias__: slime still wont show me a repl, but is connected

16:13 raek: "lein swank" is in swank-clojure now

16:13 matthias__: as i said i tried a bunch of outdated tutorials on how to set up clojure and made a mess :(

16:13 raek: matthias__: replace that with [swank-clojure "1.3.0-SNAPSHOT"]

16:14 then you should be good to go :-)

16:15 matthias__: still getting no repl

16:16 raek: first, did the swank server start?

16:16 matthias__: all i get is some stuff in *Messages* and a *slime-events* buffer

16:16 oh i crashed again

16:16 didnt do that before

16:16 raek: i.e. do you get the #<ServerSocket ServerSocket[addr=localhost/127.0.0.1,port=0,localport=4005]> line?

16:16 matthias__: i did, but then it crashed

16:17 same as the last error i put on pastebin

16:17 raek: what does "ls ~/.lein/plugins/" say?

16:18 and could you paste your project.clj?

16:18 matthias__: swank-clojure-1.3.0.jar swank-clojure-1.3.0-SNAPSHOT.jar

16:18 http://pastebin.com/3S64NFRW

16:19 thanks a lot for helping me out, btw

16:19 now i'm wondering why i have two swanks

16:19 raek: ok, do a rm ~/.lein/plugins/* ~/.lein/bin/*

16:20 and then remove lib/ in your project and do a lein deps and lein swank

16:21 ...and before that, change version to "1.3.0" in project.clj

16:21 (didn't realize that one was released)

16:21 [swank-clojure "1.3.0"]

16:22 matthias__: gosh

16:22 can i also do that after? :p

16:22 raek: yes, just do a lein deps

16:23 it should remove the old stuff from lib/ too, I was just a bit paranoid before...

16:23 matthias__: i have a feeling the problem is actually with slime right now. maybe

16:23 i mean it says it connects

16:23 but doesnt give me a repl

16:23 the newer version of slime always did, but then crashed after

16:23 raek: is there any *slime-repl clojure* buffer anywhere?

16:23 matthias__: or made swank crash rather

16:24 no

16:24 only *slime-events*

16:25 raek: so you get "Connecting to Swank on port 4005.."

16:25 and then "Connected. Take this REPL, brother, and may it serve you well."? (or other random quote)

16:25 matthias__: yes

16:25 actually is said [2 times] after the connected

16:26 raek: but no repl? that's odd..

16:26 matthias__: and then it says byte-code: beginning of bugger [6 times]

16:26 *buffer

16:26 after the random quote

16:26 raek: and the "lein swank" terminal hasn't changed?

16:26 matthias__: nope

16:27 not this time anyways :|

16:28 raek: the only thing I can think of now is to remove .emacs.d and replace it with a fresh install of emacs-starter-kit, and then install clojure-mode, slime and slim-repl again

16:28 matthias__: hmm, i kinda only just installed emacs-starter-kit

16:28 raek: I'm not sure what happens if you try to install those while you have the system slime package installed

16:28 matthias__: but i guess i should try that :(

16:28 ah

16:28 maybe

16:29 huh, swank crashed after i closed emacs

16:29 raek: I get that at my setup too, if I exit emacs while the slime<->swank conenction is running

16:30 hrm, and then I get the same exception as you did...

16:30 matthias__: i think this is looking like slime is the problem

16:30 raek: probably means that swank-clojure got an EOF while reading or something

16:32 matthias__: reinstalled the starter kit

16:34 ihuh, slime-repl failed to install

16:34 Error: No setf-method known for slime-connection-output-buffer

16:35 raek: try installing one at a time, and with slime before slime-repl

16:35 matthias__: did have slime before slime repl

16:37 edw: Does ztellman of aleph fame hang here?

16:37 raek: matthias__: and you're not trying to install the "swank-clojure" package, right?

16:37 matthias__: no, i installed clojure-mode and slime and then tried slime-repl

16:38 i got the exact same error as the commenter on that: http://webcache.googleusercontent.com/search?q=cache:http://blog.clojurls.com/setting-up-clojure-with-emacs-and-leiningen

16:38 i'm too dumb to copy stuff out of emacs :D

16:39 raek: matthias__: M-w :-)

16:40 matthias__: slime-repl.el:122:39:Error: No setf-method known for slime-connection-output-buffer

16:40 haha

16:40 thanks

16:41 seems like slime-repl might actually be installed, but just not byte-compiled

16:41 according to 3. here http://groups.google.com/group/swank-clojure/tree/browse_frm/thread/20141a1e19c60339?_done=%2Fgroup%2Fswank-clojure%2Fbrowse_frm%2Fthread%2F20141a1e19c60339%3F&

16:42 i was actually going to install swank-clojure after slime-repl :>

16:42 * technomancy grumbles in the general direction of the slime maintainers

16:42 matthias__: i dont even know what it is, but some random part of the internet told me to

16:42 raek: heh, that package is from the time before lein

16:42 matthias__: technomancy, you're phil hagelberg, right?

16:42 technomancy: yeah

16:42 why slime-repl ever got separated out of slime.el I will never know. bunch of nonsense.

16:42 matthias__: i dont know how i knew that

16:43 raek: "When you perform the installation, you will see warnings related to the byte-compilation of the packages. This is normal; the packages will work just fine even if there are problems byte-compiling it upon installation."

16:43 matthias__: well this was an error, no warning

16:44 huh, got a repl and it seems to work 8)

16:44 raek: matthias__: is slime-connect available anyway?

16:44 matthias__: yeah

16:44 thanks again, raek

16:44 btw, what happens when i run just slime?

16:44 raek: matthias__: I can tell you, it's downhill from here ;-)

16:44 matthias__: better be :D

16:45 technomancy: what was the root cause? mostly just confusion due to the apt-get version of emacs?

16:45 matthias__: oh man

16:45 i didnt quite understand it all. but that was one of the problems

16:45 technomancy: I'm open for suggestions to make it clearer

16:45 matthias__: i didnt get a cool animationthis time though

16:46 technomancy: unfortunately I can't fix blogs with misleading info =\

16:46 raek: a combo of the slime debian package, [leiningen/lein-swank "1.3.0"] for [swank-clojure "1.3.0"], among other things

16:46 matthias__: your newest explanation is outdated. perhaps someone should make a tutorial on how to set it all up and actuallt keep is up to date

16:46 raek: ...coming from outdated blogs, I think

16:46 technomancy: matthias__: which one are you refering to as the newest?

16:46 matthias__: some random one i found

16:46 :D

16:47 raek: matthias__: this one? http://technomancy.us/126

16:48 matthias__: yeah

16:48 its not one of the problematic ones since its clear that its outdated

16:48 technomancy: that points to the official readme at least

16:48 matthias__: the link is also outdated and the official wiki thing explains some stuff about inferior lisp mode

16:48 which sounded wrong to me

16:49 raek: I should really make a screecast about how to do this...

16:49 technomancy: it's an alterante approach

16:49 not invalid, just more simplistic

16:49 matthias__: yeah, but it seems there was no current one about the swank-clojure + slime approach

16:50 that might have made it clearer 8)

16:50 raek: time to write that mail re. write access to the wiki

17:04 duncanm: la la la

17:07 amalloy: edw: i've seen him once or twice in here, but seems very rare

17:08 duncanm: i can never remember the arguments to the methods for JOptionPane

17:10 jcromartie: am I completely misunderstanding redis-clojure?

17:11 or is sadd broken... because doing (redis/sadd "key" "val") and then (redis/smembers "key") returns #{"3"}

17:17 it appears to be storing the length of the value instead of the value itself... must be a protocol mismatch

17:21 edw: amalloy: Thanks. I rooted through the source and found the answer to one of my questions.

17:22 amalloy: edw: i met him a month ago, though. i think there are lamina and/or aleph usergroups that he does follow if you want to get his attention

17:23 edw: amalloy: Thanks again. I'm curious about what sort of scalability benefits using aleph makes possible, as I've recently worked on a small but non-trivial Node.js project, and it got me getting very sick of the C-like syntax required for this very Lisp-like job.

17:28 lucian: edw: if you ever have to write JS, give CoffeeScript a try

17:28 raek: technomancy: do you think it would be resonable to present slime + swank-clojure as the primary / most common approach at Getting Started with Emacs in confluence?

17:29 edw: lucian: I feel like I'm at Hacker News right now! ;) I tried it, it's not compressing my code much, it requires too much thinking (do I NEED those parens?!) and it adds complexity to the development process.

17:30 technomancy: at least you don't have to think "did I get all my return statements in?"

17:30 lucian: edw: meh. i find the tradeoff worth it

17:30 technomancy: that's like a 50% bug reduction right there when it comes to the JS I write.

17:30 lucian: i get indentation-syntax, more expressions and nice function literals

17:30 edw: technomancy: Yeah, I hear you. And lucian, I'm not begruding anyone their coffeescript; it's just not for me.

17:31 lucian: edw: sure, never blamed you of anything

17:31 amalloy: explicit return statements are so sad

17:31 technomancy: raek: yes, but only if it's simple enough. I keep thinking it is, and people keep proving that false.

17:31 lucian: amalloy: to each his own. i think it's not the best of reasons for disliking JS :)

17:31 edw: I hate syntax. I love lisp.

17:31 raek: fair point.

17:32 amalloy: lucian: it's actually a reason for disliking php, for me :P. make a function to be an alias of another, and spend ages debugging to find i forgot the return

17:33 lucian: amalloy: i suppose that's down to familiarity. as a pythonista, i pretty much never do that

17:33 edw: And aleph, which someone on HN pointed me to, looks like it could let me write async threadless server apps in Clojure.

17:33 lucian: but there are plenty of things that are clearly wrong & stupid in both JS and especially PHP

17:34 edw: lucian: You spend much time in a lisp, where everything's an expression, you quickly forget the `return' ever existed. I stared at some of that Node.js code for ten minutes until I realized I needed a `return' in there.

17:34 lucian: edw: yeah, i realise that. i get the reverse when i write lisp, but not with returns

17:35 edw: btw, there's also ParenScript. it's a bit odd, you might hate it (i do)

17:35 edw: With pattern matching (destructuring assignment) and implicit returns and a banishment of assignment, Javascript would be *so* much nicer.

17:35 * lucian nods. CS has that btw :)

17:36 edw: Anything that's a prepocessor is going to be a drag.

17:36 lucian: well, still has assignments, but they're done right and less necessary

17:36 edw: lucian: CS has destructuring assignment?

17:36 lucian: edw: doesn't it? i might be wrong, but i thought it did

17:37 i treat CS as a compiler

17:37 or you can get it to compile in the browser if it's really a problem

17:38 edw: yeah, it has destr. assi.

17:38 edw: http://jashkenas.github.com/coffee-script/

17:38 works like in python or js1.7

17:39 edw: lucian: Thanks, I hadn't gotten that far down in the docs yet.

17:39 lucian: it might depend for your particular case, but i'm willing to jump some hoops to replace JS with CS

17:39 it's just that much nicer

17:39 edw: I'm using Joyent's Node.js Cloud, so the CS would interfere with the git push goodness.

17:40 lucian: well, you could run coffee -c -w and commit .coffee files

17:40 s/.coffee/.js/

17:40 sexpbot: <lucian> well, you could run.js -c -w and commit .js files

17:41 lucian: sexpbot: bad bot

17:41 brehaut: lucian: if you dont want sexpbot to do that, there is an exclude list

17:41 lucian: well, my regex is wrong

17:41 * amalloy was about to say the same things brehaut and lucian just did

17:42 lucian: brehaut: i should get my regexen right instead :)

18:45 raek: technomancy: what is the difference between the slime, slime-repl and clojure-mode packages when comparing ELPA and Marmalade

18:45 ?

18:46 technomancy: raek: clojure-mode is newer at marmalade. slime and slime-repl are probably the same.

18:48 raek: is it mentioned in the swank clojure readme beacuse it gets newer version more quickly?

18:49 technomancy: raek: elpa has basically stopped accepting new versions in hope that people will migrate to marmalade

18:51 raek: technomancy: ah, so maybe it's a good idea to mention it instead of elpa in Getting Started with Emacs? (since the packages mentioned at that page are all in marmalade anyway)

18:51 technomancy: raek: oh, for sure

18:52 raek: ok, thanks!

18:54 TimMc: marmalade... never heard of it

18:55 raek: just discovered it myself :-)

18:55 technomancy: it's spreadable elisp

18:55 * raek suddenly got the joke

19:54 raek: there. today's work is done: http://dev.clojure.org/display/doc/Getting+Started+with+Emacs

19:54 good night.

19:57 technomancy: raek: thanks!

19:59 does lein repl actually work for inf-lisp?

19:59 clojurebot: the repl is holding onto the head of sequences when printing them.

20:00 technomancy: clojurebot: nonsense

20:00 clojurebot: Pardon?

20:00 * technomancy is too used to rudybot being able to come up with witty retorts for things like that

20:02 znutar_: oh nice! I just started with clojure and emacs on saturday and the nebulous state of the documentation on what to actually use was a real drag

20:03 technomancy: well the old wiki docs were already halfway decent; the problem is more that people don't read them

20:04 and that everyone put lots of google juice into the assembla pages and now they're on confluence

20:06 znutar_: Yeah, it's a pain figuring out what docs are good out of context. Otoh it's usually a sign that people are actually doing something and not just blogging.

20:07 technomancy: more like people who don't know what they're doing are the ones doing the blogging

20:10 znutar_: That's almost always going to be the case, though. If you have everything running smoothly it's rarely interesting enough to warrant telling people about.

20:10 technomancy: quite true.

20:11 "Hey guys, check out the readme! It tells you how to use it. Shocking, I know." <= lemme go retweet that!

20:11 </rant>

20:24 znutar_: I wonder if the whole game console-like achievements angle for something like labrepl would do a good job of illustrating the most painless way to get yourself set up in some known state for newbies

21:10 sritchie: does anyone here know how to force stdout to print to the current emacs repl buffer, with SLIME?

21:10 cake currently directs it to .cake/cake.log, but I've seen a few screencasts where stdout shows up directly in emacs

21:59 MiggyX: Hi guys, if you need to write a program that goes through a CSV file to sequentially match rows (i.e. order is important) is there a standard way to maintain this 'state' in clojure ?

22:03 amalloy: sritchie: that's weird. it prints to the repl for me

22:04 (and i use cake)

22:04 sritchie: amalloy: hmm, odd! I've been running cake swank at the command line, then slime-connect in emacs

22:04 dnolen: sometimes things are so easy in Clojure it seems criminal, https://gist.github.com/916831

22:05 sritchie: the solution floating around the web is to put (setq SWANK:*GLOBALLY-REDIRECT-IO* t) in ~/.swank.lisp, but no luck there

22:05 amalloy: sritchie: same. maybe you have an old version of one of those?

22:06 sritchie: amalloy: I just updated everything off of ELPA, so it's not that --

22:06 amalloy: errr, cake isn't in elpa, is it?

22:07 sritchie: sorry, I meant slime, etc

22:07 cake is maybe a month old

22:07 amalloy: cake --version?

22:08 sritchie: just ran cake upgrade, so now it reads cake 0.6.2-20110221.082826-17-g4d002b1 -- let me test it now

22:11 brehaut: MiggyX: without knowing more details you probably want to look at reduce

22:12 sritchie: amalloy: no dice. normal side effects show up, and the results of function calls, just not anything that's meant to be piped to stdout

22:12 cascalog output, or pallet output, for instance

22:13 amalloy: oh. piped? i guess i don't understand the problem

22:14 but if i did understand it i still wouldn't have a solution, so probly not worth your effort to clarify

22:14 MiggyX: brehaut: Basically processing a huge csv file (30GB+) and matching rows together etc

22:14 brehaut: brb

22:16 sritchie: amalloy: no problem, thanks for taking a look. the clarification's short -- non-repl threads currently print to .cake/cake.log, so I was just looking for a way to get all threads, repl or non-repl, to send output to the repl buffer

22:18 brehaut: MiggyX: a) http://mywiki.wooledge.org/XyProblem b) thats still an extremely general description of a problem

22:21 MiggyX: brehaut: Well basically I have a CSV file that contains two feeds of data. We're talking more than 9 million rows combined. From the first feed (let's call it feed A) there should be a matching entry - or at least a similar entry - in feed B. The problem is that there are no global identifiers and so the file needs to be processed sequentially. Basically I want to match the two.

22:23 brehaut: MiggyX: how are they 'matched' ?

22:24 MiggyX: brehaut: There is a sequence number and various fields that should match up - it's unlikely that the same combination would appear within a few minutes of each other (though theoretically possible). However trying to load the file and match in one go won't work as you will have great trouble trying to isolate the correct one

22:25 brehaut: MiggyX: is this tallyman / TCRM data?

22:26 MiggyX: brehaut: forex price feed / trade

22:26 brehaut: close then. those formats are always miserable

22:27 MiggyX: brehaut: Tell me about it :/

22:27 amalloy: brehaut: i'm going to have to start prefacing all my questions with "I'm on Gentoo so I know what I'm doing"

22:27 brehaut: amalloy: golden eh :)

22:27 via raganwald's tweeter

22:28 MiggyX: Thing is, I can't see how I can do it without maintaining some sort of state - or sticking most of the code into a single function...

22:28 brehaut: MiggyX: are you fairly new to the functional programming thing?

22:29 MiggyX: brehaut: yeah - read a lot about it, but have yet to actual do anything useful with it.

22:30 brehaut: MiggyX: ok. theres a function called reduce (sometimes called 'fold' in other languages) that takes a function, some data and a sequence. The function it takes as an argument is given items from the sequence one at a time along with some data (sometimes called the accumulator/accumulation) and it returns a new accumulation

22:31 MiggyX: a simple example would be ##(reduce + 0 [1 2 3])

22:31 sexpbot: ⟹ 6

22:31 brehaut: MiggyX: the ## just tells sexpbot to evaluate it

22:32 amalloy: btw, you can see what the reduce is doing "under the hood" with ##(reduce (partial list '+) 0 [1 2 3])

22:32 sexpbot: ⟹ (+ (+ (+ 0 1) 2) 3)

22:32 brehaut: amalloy: ah yes good example

22:32 MiggyX: okay, with you so far :)

22:32 brehaut: MiggyX: so the data passed to reduce is the seed value for the accumulator, if its not present clojure will use the first argument in the sequence

22:33 amalloy: brehaut: you missed my stroke of genius to explain the difference between apply and reduce: ##((juxt apply reduce) (partial list '+) (range 4))

22:33 sexpbot: ⟹ [(+ 0 1 2 3) (+ (+ (+ 0 1) 2) 3)]

22:33 TimMc: We don't have foldl and foldr, do we?

22:33 brehaut: amalloy: nice :)

22:34 TimMc: nope

22:34 amalloy: TimMc: no

22:34 * amalloy needs to add foldr to amalloy-utils

22:34 brehaut: MiggyX: so in your case you might have something like (reduce match-csv (match-acc) csv-data)

22:35 where match-csv is a function that operates record at a time on csv-data and (match-acc) is a function that returns an empty accumulator

22:36 MiggyX: can the csv-data see the contents of match-acc ?

22:36 brehaut: no

22:36 csv-data needs to be a sequence of csv records from your csv file

22:37 MiggyX: if I understand correctly, each row (assuming I set it up that way) will be passed to the match-csv function which will be called uniquely (i.e no side effects) for each row.

22:37 brehaut: also because im a muppet, it should probably just be empty-match-acc or something; no need for it to be a function call

22:37 MiggyX: From that I'm not sure how I could match saw row one with row ten

22:38 brehaut: MiggyX: match-csv can return anything it likes. whatever it returns is used as the accumulator argument for the next call to match-csv

22:38 MiggyX: think of it as simple recursive over a list but without you needing write the recursive logic and tests

22:39 MiggyX: okay, so match-csv is called with the result of the accumulator and the next row from the file?

22:39 brehaut: the result _is_ the accumulator

22:40 amalloy: brehaut: haskell teaches us that everything should be a function call

22:40 TimMc: Oh, that's right... nullary functions for constants.

22:40 brehaut: amalloy: this is indeed what tripped me up

22:40 amalloy: haha

22:41 i didn't even know that, TimMc

22:41 i just figure, if brehaut says something crazy, blame haskell

22:41 TimMc: Well, don't take it as gospel.

22:42 brehaut: amalloy: if you cant have any side effects due to the type system, and the funcall syntax doesnt require parens, then there is no difference between a function of no argumnts and a constant value

22:42 TimMc: brehaut: Can you confirm my assertion?

22:42 * amalloy is already converting indigenous peoples to the Way of TimMc

22:42 TimMc: heh

22:42 brehaut: TimMc: yes. although its probably elided back to just constant values by the compiler

22:43 TimMc: brehaut: Also, where do you live? I'm wondering about your use of the word "muppet".

22:43 brehaut: TimMc: New Zealand

22:43 TimMc: It's a Brtish thing, yeah?

22:43 mec: amalloy: do you have an example of using your lazy-recur in a non tail position?

22:43 brehaut: TimMc: probably

22:44 dnolen: hmm are strings reliable unique identifiers for classes on JVM? I wondering the what's the most stable thing considering redef'ing types/records is common.

22:44 amalloy: mec: https://github.com/amalloy/amalloy-utils/blob/master/src/amalloy/utils/core.clj, but pretty much every use of lazy-recur isn't in tail position

22:44 dnolen: no

22:45 two classes with the same package and name can be loaded by different classloaders and not conflict

22:45 mec: amalloy: err right

22:45 TimMc: amalloy: "not conflict" is an interesting phrase

22:46 It can be problematic if you accidentally try to cast one to the other.

22:46 amalloy: TimMc: feel free to propose more-accurate statement

22:46 TimMc: nuh-uh

22:46 MiggyX: stupid question - I don't suppose reduce runs in paralllel :)

22:46 brehaut: MiggyX: nope

22:46 TimMc: MiggyX: preduce

22:46 dnolen: amalloy: huh ... how does the JVM differentiate them? If I load some other jar that references one of those classes, which will get instantiated ?

22:46 TimMc: Wait, how would that even work?

22:46 MiggyX: TimMC: I assume that would screw up the accumulator though

22:47 amalloy: dnolen: suppose class A1 and A2 are loaded by classloader L1 and L2

22:47 if someone in class B refers to class A, they get the class named A which was loaded by the same classloader as B

22:47 iirc

22:49 TimMc: MiggyX: There's something called preduce, but I think it parallelizes operations on different key-value pairs of maps.

22:49 dnolen: amalloy: if classes can't cross class loader boundaries then how can using string as an identifier be problem?

22:50 brehaut: MiggyX: thres no such thing as magic parallization; you need to know your domain well enough to device reasonable partitioning, operations on those partitions, and reconstitutions for instance

22:50 MiggyX: TimMc: I always seem to pick hard tasks :)

22:50 amalloy: dnolen: you can find references to other classloaders, and ask them to load a class for you, or return it if it already exists

22:50 brehaut: MiggyX: and your strong ordering requirement may cause you a lot of grief

22:50 amalloy: MiggyX: you pick vaguely-defined tasks

22:50 all such tasks are hard :)

22:51 http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ClassLoader.html#getSystemClassLoader()

22:51 MiggyX: brehaut: If I was doing it in say Python, I would split the file into say 1GB chunks and then start the matching process. any rows that aren't match are passed back, put in an ordered list and then processed as a final job. I think that should work

22:51 but I was hoping to have a good excuse to spend a few days doing it in clojure :D

22:51 brehaut: MiggyX: you would do the same in clojure then

22:52 phenom_: hey, in my code I create a lot of vectors which i pass around to single argument functions which in turn deconstruct the vector ... YourKit is showing me that alot of my space is taken up by clojure.lang.PersistentVectors ... any idea why?

22:52 shouldn't they be garbage collected? I dont hold on to them at all

22:53 brehaut: MiggyX: but you will have a potentially very large post-parallel bottleneck which is going to seriously impede your performance gains

22:53 phenom_: the collector runs in its own time

22:53 amalloy: phenom_: they get gced eventually, but in the meantime you're creating a lot of them. what else can you expect but that they take up space meanwhile?

22:54 MiggyX: brehaut: I wouldn't expect it to be that bad. If I slice the CSV file, only a few rows would be affected either side of it... there shouldn't be much left to process after the main chunks I'd have thought

22:54 phenom_: amalloy, brehaut: but i eventually get an OOM exception :S with -Xmx1G

22:54 amalloy: then something is wrong; fix it :P

22:55 TimMc: phenom_: Are you holding onto the head of seq you shouldn't be?

Logging service provided by n01se.net