#clojure log - Apr 27 2010

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

0:02 defn: write code first, optimize later

0:07 pdk: no defn we gotta keep up the proud legacy of C

0:08 planning in advance whether every integer variable will be int or short

0:10 slyphon: i really like the name 'throwf' it kind of sounds like an exception "barfing"

0:33 man, the guys that write this Atomikos JTA lib are dicks

0:33 from the javadocs:

0:33 "All non-transient errors (i.e., those that happen each time a message is delivered) indicate problems at the application level and should be dealt with by writing better application code."

0:33 gee

0:33 thanks

0:41 remleduff_: technomancy: Best commit ever ;)

1:40 slyphon: ARGH

2:53 vegai: are there any active projects for bringing clojure to The Shootout?

3:39 LauJensen: vegai: Not to my knowledge

3:42 hircus: when using Leiningen, is there a way to specify a version number once and avoid repeating oneself?

3:44 ordnungswidrig: hircus: repeat where?

3:44 vegai: I guess you mean that you wanna get the version number of your app in project.clj to your app code

3:45 hircus: ordnungswidrig, vegai : I'm using several Incanter modules and I don't want to keep saying "1.2.3-SNAPSHOT"

3:46 vegai: ohhh

3:46 irfn: hircus project.clj is plain clojure code

3:46 vegai: cannot you just (def ver "1.2.3-SHAPSHOT")

3:46 irfn: so you should be able to def it

3:46 hircus: I tried (def *ver* "1.2.3-SNAPSHOT") and then :dependencies [[incanter/incanter-core *ver*] ...] but it fails, saying symbols can't be cast into strings

3:46 irfn: yeah

3:47 hircus: haven't used Clojure macros for a while, an dI forget my macro expansions

3:51 vegai: so after defining ver, how do I use it within defproject, given the problem I stated?

3:52 Borkdude: technomancy|away: I got leiningen working on XP now, just to let you know

3:53 Clojure is a seqsy language

3:54 vegai: hircus: odd

3:55 hircus: vegai: yeah. looking at the Leiningen source right now to see what's going on

3:56 Raynes: Borkdude: That was clever. I think sexpy is more clever though, hence the name of my bot.

4:04 hircus: vegai: so I guess the problem is that the arguments have to be quoted, because org.clojure/clojure etc. do not refer to anything in the namespace, but if they are quoted then the version numbers cannot be macro-expanded

4:04 vegai: the other solution, the Polyglot Maven syntax, requires you to quote the namespaces instead. gah.

5:24 stilkov: what would be the idiomatic way to do map over something that can either be a list of strings or a single string?

5:24 the 'if' I currently use somehow feels ugly

5:26 Borkdude: If you map over a single string, it maps the function over the characters of that string

5:27 Chousuke: stilkov: I don't think there's an idiomatic way to do that :P

5:27 stilkov: just use an if

5:28 stilkov: Borkdude: exactly my problem

5:28 Chousuke: but in general, why is your function accepting both a string and a list of strings?

5:28 stilkov: Chousuke: destructured command line args - can either be a single file or a list of files

5:29 Chousuke: usually in those cases you want a (fn foo [& strings] ...) so that you can call either (foo "string") or (apply foo list-of-strings)

5:30 try and see if you can change your code so that it always gives you a list of strings, even if there is only one

5:30 I think that would be the most idiomatic approach

5:31 in general if you have a function that works with sequences of something, special casing it for one of something is probably unidiomatic.

5:32 stilkov: Fair enough. Is there an idiomatic way to turn a single element into a list? Or can the let destructuring do this on its own?

5:32 Licenser: I'd go with (fn foo [string & strings] ...) so it forces at least one argument

5:34 stilkov: Licenser: and what would go in the body then? (map #() (conj string strings)) ?

5:34 Licenser: well that depends on what you want to do with it :P

5:34 but you've a point there

5:35 Chousuke: stilkov: (list element) :P

5:35 stilkov: Chousuke: that will turn a list into a list with an element that's a list

5:35 Chousuke: but I could help you better if I knew how you're doing your destructuring

5:36 stilkov: sure. but then why is your data at one time a list and other times a single element? Is there no way to fix that?

5:36 stilkov: (defn -main [& args]

5:36 (let [[pattern & files] args]

5:36 (great-function pattern files)))

5:37 Licenser: why not go with defn -main [pattern & files] ?

5:37 Chousuke: and what part of that will sometimes be a list and sometimes a single string?

5:38 stilkov: Chousuke: the "files" part, depending on how many arguments are passed on the cmd line

5:38 Chousuke: no, it'll always be a list.

5:38 or nil

5:38 but still, always a list

5:38 stilkov: hm

5:38 checking ...

5:38 * Licenser is still not sure why even do the destructing there

5:39 Chousuke: right, you could just (apply great-function args) :P

5:39 stilkov: Licenser: you're right, left-over from some earlier iteration

5:39 Licenser: *nods*

5:40 stilkov: Licenser: Ah, I remember: I had a check as to the number of arguments; but I can obviously do this with a nil check as well

5:40 Chousuke: ,(count nil)

5:40 clojurebot: 0

5:40 stilkov: Licenser, Chousuke: thanks for the help so far, I guess I'll play some more

5:40 Licenser: it gives the advantage (in my eyes) that the signature of -main already tells you what it wants (a pattern and files) and not just that it wasnts something :)

5:41 stilkov: have fun and you're welcome

6:21 kzar: Supposing you have a map and either another map or a list of maps and in either situation you need to return a list of maps how would you do it?

6:23 rhudson: Depends on how you get "either another map or a list of maps"

6:24 kzar: so either (list map1 map2) or (cons map1 list-of-maps) but I thought there might be a better way to write it

6:24 LauJensen: Any Linux Firefox users here who can help me out for 10 secs?

6:24 kzar: rhudson: Well I'm writing a function recursively that has a past-result parameter, usually it's just one map but sometimes it might be a list of a few maps.

6:25 rhudson: I thought of always wrapping the past-result map in a list but I thought that's a bit ugly

6:25 LauJensen: ,(flatten (cons [1 2 3] [[4 5 6] [7 8 9]]))

6:25 clojurebot: (1 2 3 4 5 6 7 8 9)

6:26 rhudson: kzar: you could define your function (defn whatever [ & maps ] ...)

6:27 LauJensen: kzar: that flatten demo was for you :)

6:28 rhudson: LauJensen: I run Firefox on Linux at work

6:28 LauJensen: rhudson: Are you at work ?

6:28 rhudson: thankfully no

6:29 not at this ET hour

6:29 Raynes: LauJensen: I run firefox on Linux.

6:31 kzar: Raynes: Cool idea, so maps would always be a list of the parameters given in that example?

6:31 oops sorry I meant rhudson

6:31 Raynes: It's okay. I love to hear my name.

6:32 rhudson: kzar: right

6:32 kzar: heh

6:32 rhudson: reins rains reigns

6:34 * eevar2 runs Shiretoko on Arch

6:35 stilkov: I'm trying to turn this into idiomatic clojure, I'm sadly pretty sure it's not: http://gist.github.com/380602

6:35 any comments appreciated

6:37 arbscht: stilkov: I think you can replace numbered-lines with indexed in clojure contrib

6:37 that will get rid of the atom too

6:38 LauJensen: Yea, zero need for mutability for that specific task

6:40 stilkov: thanks, neat use of map with two args

6:40 arbscht: stilkov: you can use destructuring inside print-matches to abbreviate binding stuff

6:42 Chousuke: stilkov: (if (or (nil? pattern) (empty? files)) ...) <- (if-not (and pattern files))

6:43 stilkov: arbscht: you mean something like (let [[fname matches] matches] ??

6:43 Chousuke: thanks

6:44 arbscht: stilkov: you can destructure within doseq itself

6:44 Chousuke: (doseq [[fname submatches] matches, match submatches] ...)

6:45 stilkov: er ? chewing on that for a second

6:45 Chousuke: or even (doseq [[fname submatches] matches, [first-part, second-part] submatches] ...)

6:46 stilkov: ah ? beautiful

6:47 Chousuke: it's similar to (for [row (rows matrix), element row] ...) except it's doseq :P

6:48 also you might want to use format instead of manually constructing the string with str

6:49 either is fine, but I think format strings are easier to read and modify

6:50 kzar: rhudson: I had a question about your idea to define the function using "& maps"; it works fine until I need to recur but then instead of passing the new map and all the old maps I end up passing back a new map and a list of all the old maps

6:51 patrkris: rhickey: Hey. Did you ever experiment with other contention mangement strategies than the one Clojure's STM currently employs?

6:51 stilkov: Chousuke, arbscht: thanks a lot, that surely looks a lot better

6:51 rhickey: patrkris: not much

6:52 patrkris: rhickey: so you don't have any idea how implementing e.g. karma would affect it?

6:53 rhudson: kzar: yes, that's what's wrong with my suggestion.

6:53 rhickey: patrkris: my guess is, not a lot. Clojure's STM is coarse-grained, so it's not going to be used on the inner bits of a concurrent collection, e.g. as in a lot of the STM literature

6:55 kzar: rhudson: Hey well macros let you expand a list, I could create a macro that took a list and just expanded it and then use that on the list of old maps?

6:55 patrkris: rhickey: ok, I believe you are right - but we'll try out a few different strategies and see how they work out. We're doing it as part of our studies.

6:57 rhickey: patrkris: If you are interested in doing something cool and new with Clojure's STM, and leveraging it being MVCC, one thing I have been thinking about is visible transaction timestamps

6:57 patrkris: rhickey: nice - I'll note that

6:57 rhickey: patrkris: so, rather than returning a value d-timestamped-sync would return a token representing the world at a point in time

6:58 rhudson: kzar: (defn f [m old-ms] (let [ms (cons m old-ms)] ... )

6:58 rhickey: the nyou could run a read transaction as of a point in time

6:58 patrkris: rhickey: you meant do-timestamped-sync?

6:59 rhickey: this matters when someone does something in a transaction and needs to communicate it to someone for use later. Given long enough histories, they can go back and see the same world

6:59 patrkris: yes, do-timestamped-sync or something

6:59 patrkris: rhickey: thanks man, cool suggestion

6:59 rhickey: another thing I am interested in is independent ref worlds

7:00 rhudson: kzar: then ms is always a list -- (cons x nil) => '(x)

7:00 rhickey: for some apps you might have small independent ref worlds of critical data for which you'd keep very large histories

7:00 patrkris: rhickey: so you'd have the ability to rewind?

7:01 rhickey: patrkris: not so much rewind as see the past

7:01 patrkris: rhickey: e.g. for undo operations?

7:01 rhickey: oh ok

7:02 rhickey: patrkris: consider event-driven systems where the event receiver adds the even to a collection transactionally, then notifies others. If they race to look at the collection something might have happened in the interim, wheras is the producer could communicate the world time, they could see his result

7:03 patrkris: rhickey: ok, got it

7:04 Licenser: ,(doc flatten)

7:04 clojurebot: "([x]); Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents as a single, flat sequence. (flatten nil) returns nil."

7:05 patrkris: rhickey: so your two suggestions are actually related somewhat, right?

7:06 rhickey: patrkris: not really, separate ref pools just let you get more concurrency when you have never-overlapping sets of data

7:06 Licenser: out of curiosity, why does flatten not take multiple lists, it is kind of what people use a lot

7:07 rhickey: patrkris: given that history length is per ref you don't need separate pools for that

7:08 patrkris: rhickey: Ok, I was just focusing on the history thing :)

7:08 rhickey: patrkris: timestamped transactions are something likely to make it into Clojure, ref pools probably not for a while

7:08 patrkris: ok

7:08 rhudson: ,(var flatten)

7:08 clojurebot: #'clojure.contrib.seq-utils/flatten

7:11 rhudson: ,*clojure-version*

7:11 clojurebot: {:interim true, :major 1, :minor 1, :incremental 0, :qualifier "master"}

7:12 patrkris: rhickey: so in independent ref worlds, you'd be able to see a consistent view of a pool of refs at a given point in the past, or am I misunderstanding?

7:14 rhickey: patrkris: sorry I confused you. Independent ref pools simply make it so one set of refs has no interaction at all with another, e.g. can't be part of the same transaction. At very high concurrency levels, that would ease the pressure on the single timestamp CAS inside the STM, since each pool would have its own

7:14 patrkris: really nothing to do with timestamped transactions

7:14 patrkris: rhickey: oh ok, thanks :)

7:15 rhickey: as long as you have sufficient history for any refs you need to see in the past, you can do timestamped reads

7:15 patrkris: yes, but clojure doesn't allow to look in the past as of now, right?

7:15 rhickey: talking about one just made me think of the other

7:16 patrkris: yes

7:16 rhickey: patrkris: right, that would be the enhancement - runs this read-only transaction as of this point in the past

7:16 as id

7:16 as if

7:16 * rhickey can't type

7:16 patrkris: :)

7:16 Raynes: rhickey: It's called too-early-in-the-morning syndrome.

7:17 rhickey: Raynes: it doesn't get better later :(

7:17 Raynes: It can't get any worse.

7:17 patrkris: start drinking coffee

7:17 * Licenser so is not commenting on the early-in-the-morning syndrome problem of the male population and rhickey capability to type

7:17 * rhickey tea in hand, maybe that's affecting my typing

7:21 Raynes: rhickey: What kind of tea?

7:21 I love me some tea.

7:21 * Raynes brews some Chai.

7:22 rhickey: Raynes: in the morning - an Assam, today it's Mangalam

7:22 Raynes: Never heard of either of those. My teafoo is weak, but I'm learning.

7:22 vu3rdd: rhickey: Indian Tea looks like?

7:23 Raynes: vu3rdd: You Indians sure are proud, aren't you? :p

7:23 rhickey: vu3rdd: right

7:23 Raynes: You should be, with such awesome teas.

7:23 vu3rdd: :)

7:23 We don't get as good coffees here as you have in Europe and the US.

7:24 I am sad that I am missing meeting all you great clojure hackers. You are all in the west. May be you can visit me and I will give you loads of Tea

7:25 Raynes: vu3rdd: I'd totally visit you. You're watching Irclj. One of the few. <3

7:25 Licenser: heh

7:26 vu3rdd: Raynes: Sure. I am quite interested in both sexpbot as well as irclj.

7:26 Licenser: vu3rdd: a colegue of mine was supposed to go to India the other weak but that silly vulcano thing keeped him in germny

7:26 vu3rdd: Oh..

7:26 Raynes: Volcanoes are so silly!!!

7:26 vu3rdd: I am in Bangalore. If any of you are coming this way, please ping me at this handle @ gmail

7:26 Licenser: SOmeone from kuwait here?

7:31 Raynes: vu3rdd: Sexpbot is actually my biggest project ever. It started out as a little toy script to connect to IRC.

7:31 And then I got bored.

7:31 That's how all good projects start. "I got bored."

7:34 Licenser: Which would explain why I never have good projects :P I can't remember when I was boored the last time

7:34 patrkris: rhickey: in the software engineering podcast you talked about how STM couldn't be made to work correctly in certain other languages. One of the reasons, aside from MVCC and the persistent datastructures, would also be because of the "coarse grainedness" of Clojure's transactions? In C and Java STM implementations, the STM *has* to work at a finer granularity. Am I right in my understanding?

7:34 Raynes: clj-sandbox is great.

7:34 Licenser: Ever figure out what was up with StringWriter?

7:34 * Raynes moves discussion to #clojure-casual

7:35 patrkris: rhickey: sorry, 'correctly' is not the word here

7:36 rhickey: patrkris: right, my comment was directed at efforts to make ordinary mutating Java/C code safe by wrapping in transactions. The granularity would have to be at the field level, and most important, you'd need to be in a transaction to read. Clojure emphasizes programming with values, such values perfectly valid outside a transaction.

7:39 patrkris: rhickey: so how about haskell for instance? Could you hope to get MVCC working well in that language? Clojure's force with regard to MVCC is structural sharing and thus efficient 'copying', right? (I'm just sorting out the arguments we'll use when we write our paper.)

7:41 rhickey: patrkris: Haskell's STM is somewhat like Clojure's, sans MVCC. It is ref+value oriented, and can be used coarse grained, and of course the language emphasizes values

7:42 patrkris: and Haskell's data structures are similar. So, nothing to knock on Haskell here, we're on the same side of this I think

7:43 patrkris: rhickey: Ok, I better read up on Haskell :)

7:43 rhickey: Haskell has orElse (or something) which I considered but rejected

7:43 patrkris: yes orElse

7:44 rhickey: The big diff with Haskell's STM is that in order to do orElse you need to do read tracking. Clojure doesn't need to do that

7:44 Clojure is I think still unique in having commute

7:45 patrkris: and MVCC?

7:45 rhickey: there are other MVCC STMs I think

7:45 at least now there are

7:46 http://multiverse.codehaus.org/overview.html

7:46 sexpbot: "Multiverse - Java based Software Transactional Memory implementation"

7:46 patrkris: yeah you are probably right, but I can't see how you can get that to work as efficient as in clojure's case, unless the data structures have the same characteristics

7:46 rhickey: patrkris: exactly, the whole design works together

7:47 patrkris: rhickey: yes, and when I finally saw that, I was pretty amazed, rich :)

7:47 i've been wanting to ask you if these things was all one epiphany for you, or did things just follow each other naturally? :)

7:47 *were

7:48 rhickey: patrkris: took too long to be an epiphany :)

7:49 I do think it is a natural outcome of the reconciliation of a bunch of forces

7:50 looking backwards of course

7:50 patrkris: yes

7:50 rhickey: nothing about Clojure is really new

7:50 patrkris: but probably the combo is

7:51 wlangstroth: patrkris: beat me to it.

7:51 rhickey: first lisp I've liked, fwiw

7:51 patrkris: first lisp I did serious programming in :)

7:52 (for some definition of serious)

7:52 ^ that wasn't a lisp expression, in case you wondered

8:04 cemerick: rhickey: thank you for that last commit :-)

8:04 rhickey: cemerick: you're welcome!

8:04 protocol variadics will be harder

8:05 Raynes: patrkris: Looked more like python without the parens.

8:05 cemerick: ...and I was just about to (jokingly) suggest auto-hinting of % in fn literals in protocol fn maps :-P

8:07 rhickey: cemerick: extend-type auto-hints

8:07 cemerick: rhickey: yeah, I know :-)

8:07 rhickey: but extend doesn't look at the map at all

8:08 cemerick: so I figured. That's why it would have been a joke. :-)

8:08 rhickey: cemerick: but is there some real need?

8:08 cemerick: heh, no

8:21 wlangstroth: rhickey: I'm still catching up on your design ideals - Bagwell and Huet were new to me - any more required reading?

8:26 stilkov: rhickey: can I use the Clojure logo in a public presentation about the language?

8:27 rhickey: wlangstroth: tough to say, you learn from everything, even those things you reject

8:27 stilkov: sure

8:27 stilkov: rhickey: thanks

8:27 rhickey: stilkov: what are you talking about?

8:29 stilkov: rhickey: I'm doing an intro to Clojure's concurrency features at JAX 2010 in Germany

8:29 rhickey: stilkov: good luck!

8:30 stilkov: rhickey: thanks!

8:30 wlangstroth: rhickey: true enough - thanks

9:02 Licenser: hmm the protocll stuff is pretty neat

9:05 Raynes: technomancy|away: I need you. Wake up.

9:05 Licenser: So could the rule of thumb for when to use protocols and when to use multimethods be: If you don't need the crazy stuff you can do with multi methods you should do it in protocols?

9:05 * cemerick will miss ^ as meta just a little

9:06 Raynes: Deftypes can't implement a multimethod.

9:06 Chousuke: an easier way: try protocols first, if they don't work, use multimethods

9:06 Licenser: Chousuke: but that is so simple :P

9:07 Chousuke: ideally you'd keep the fact that there is a protocol or a multimethod an implementation detail

9:08 they're all functions, and if you don't advertise the protocol as part of your API, no-one's going to notice the difference :P

9:08 clojurebot: api examples is http://en.wikibooks.org/wiki/Clojure_Programming/Examples/API_Examples

9:08 Raynes: (start-repl 4005 :host "localhost") <-- Confusing.

9:08 start-repl takes any number of optional arguments, but doing that tosses a "Wrong number of arguments" error.

9:09 Licenser: Chousuke: muahaha

9:09 Raynes: I can't win for losing it seems.

9:11 _ato: Raynes: older version of swank-clojure didn't accept options

9:12 1.0 just takes a port, nothing else

9:12 looks like 1.1 is the same

9:12 http://github.com/technomancy/swank-clojure/blob/1.1.0/src/swank/swank.clj#L60

9:12 Licenser: hmm question: is every namespace in clojure a class in java?

9:13 Raynes: Oh.

9:13 That's the problem.

9:13 _ato: Thanks.

9:13 Didn't know my version was old.

9:15 _ato: Licenser: no, each namespace has many classes. Usually at least one for each function/lambda and one for __init

9:15 Licenser: ah sneaky

9:40 qbg: Did anyone come to Clojure without a Java background?

9:40 esj: me

9:41 qbg: Did Clojure's java based exceptions confuse you?

9:43 bytecoder: clojure's exception/error reporting is still evolving if i'm not wrong. not just exceptions; i've had difficulty comprehending other issues reported as well. it's not a turn off for me though.

9:43 Raynes: qbg: Yes. It irks everybody at first.

9:44 Eventually you get used to shitty error messages and start paying attention to the stack traces.

9:45 $sed #clojure i s/shitty/shoddy/

9:45 sexpbot: Eventually you get used to shoddy error messages and start paying attention to the stack traces.

9:45 * Raynes doesn't mean to make sailors blush. It comes naturally.

10:07 jwr7: Anybody know if clojure-jna (and JNA in general) places any limitations on multithreading? I tried to use pmap with a piece of code that uses JNA and it looks like something gets synchronized.

10:09 chouser: jwr7: clojure-jna doesn't sync anything, but I don't know about JNA itself.

10:11 jwr7: chouser: I searched the docs, but couldn't find anything. And yet YourKit clearly show me a checkerboard pattern — I get 16 threads or so, but only one seems to be running at a time.

10:17 chouser: jwr7: http://gist.github.com/380762

10:18 could the native lib you're calling be locking?

10:20 jwr7: chouser: it isn't — it's just one C function, reentrant and fairly simple. I'm looking at JNA source now, perhaps it's because I was using jna-invoke instead of deifning a jna-fn? (com.sun.jna.Function/getFunction might be blocking me)

10:21 chouser: you saw my gist? that uses jna-invoke without apparent blocking

10:22 jwr7: chouser: Right. That proves it, I guess. So why do I get blocking with pmap — it's the same mechanism, after all…

10:26 chouser: well, there are a few more variables there...

10:27 pmap uses a different thread pool. Is your input seq chunked? How are you forcing the pmap output seq?

10:28 jwr7: chouser: I forced the output with doall and the inputs were real lists by then. I'm trying to work out a test case right now.

10:29 chouser: ok

10:54 powr-toc: What's the best way of interacting with databases currently in clojure?

10:54 clojureql seems like it's a short way off being prime-time...

10:55 and c.c.sql has warts, but seems to be more stable... is this a fair assessment?

11:01 Raynes: Yeah, I have trouble writing small ones.

11:01 Check out defrecord's docstring in Clojure.

11:01 Oops.

11:01 Wrong channel.

11:10 AWizzArd: à propos defrecord... they they now have a print-dup representation. But there is no constructor which could rebuild them.

11:11 chouser: ,(condp = 99, 1 :a, 2 :b, #_else :unknown)

11:11 clojurebot: :unknown

11:11 chouser: is #_else helpful or confusing?

11:11 AWizzArd: confusing

11:12 Oh cool, defrecords are now serializable :)

11:13 rhickey: AWizzArd: it would be cooler if http://www.assembla.com/spaces/clojure/tickets/281-make-more-datastructures-serializable patch applied - I was al set to do this Serializable stuff this morning

11:13 stuartsierra: chouser: confusing

11:13 sexpbot: "#281 - Make more datastructures serializable (Test) | Clojure | Assembla"

11:15 fogus: chouser: confusing

11:15 chouser: wow

11:15 ok then

11:15 :-)

11:16 ,(condp = 99 1 :a 2 :b :unknown) ; it is then!

11:16 clojurebot: :unknown

11:18 stuartsierra: chouser: If your condp spans multiple lines, ";;else" before the last line would be helpful

11:18 rhickey: ick

11:18 chouser: hm.

11:19 rhickey: (if x

11:19 ;;then

11:19 y

11:19 ;;else

11:19 z

11:19 ) ;;endif

11:20 hiredman: you could also include the docstring for condp in a comment :P

11:22 * rhickey once suffered with someone who used a macro package to make C look like Pascal

11:25 moshisushi: rhickey: :D

11:25 chouser: I'm having far too much fun with :inline

11:25 but I need a better macroexpand

11:26 hiredman: mexpand-all?

11:26 chouser: hm, I don't trust it. But it doesn't do :inline's anyway, does it?

11:26 hiredman: no idea

11:26 ,mexpand-all

11:26 clojurebot: #<macro_utils$mexpand_all__4397 clojure.contrib.macro_utils$mexpand_all__4397@b0b955>

11:26 hiredman: ,(mexpand-all '(+ 1 2))

11:26 clojurebot: (+ 1 2)

11:26 fogus: rhickey: What did "end." expand to?

11:26 The-Kenny: rhickey: There's a guy who wants to implement something very similar to lisp macros for c++. His syntax looks like @#wenn a ist 42 dann def b = a+@# ("wenn a ist 42 dann..." translates to "when a is 42 then ..."

11:26 hiredman: guess not

11:27 The-Kenny: He's writing a pre-processor for this

11:28 rhickey: fogus: nothing, it just made him happy to see it

11:32 stilkov: what's the point of most macros being defined with (defmacro [& body] ...) instead of (defmacro [body] ...) ?

11:32 LauJensen: powr-toc: correct assesment

11:33 bsteuber: stilkov: you can then offer implicit do for multiple statement (side effects)

11:33 chouser: if you want real macros on C++, this is interesting: http://voodoo-slide.blogspot.com/2010/01/amplifying-c.html

11:33 sexpbot: "voodoo slide: Amplifying C"

11:33 LauJensen: The problem with ClojureQL is, that at 0.9.7 we decided to rework the entire frontend. And when thats done it will be great, but we have to put in a lot of work and unfortunately we're all very busy atm

11:34 AWizzArd: When should I write a method for print-dup (vs. print-method)?

11:34 rhickey: stilkov: [body] can only take one form

11:35 often macros need to manipulate a variable number of forms

11:36 stilkov: rhickey: the reason then would be the one pointed out by bsteuber. is it idiomatic to expect macros do wrap the body in an implicit (do ...)?

11:36 s/do wrap/to wrap/

11:36 stuartsierra: chouser: try "wtf" from Halloway's circumspec

11:37 It's a macroexpansion, name is short for "what the form"

11:37 rhickey: stilkov: not necessarily, (defmacro add [& body] `(+ ~@body)) doesn't even emit a block

11:38 stilkov: macros like defrecord take variable forms, not related to statements/do

11:38 AWizzArd: btw, with print-method go away in 1.2 and get replaced by Protocols?

11:39 * joshua-choi is watching Stuart Halloway's protocols video; did not know about InternalReduce

11:39 stilkov: rhickey: I see; I may have been thinking of the wrong examples

11:40 rhickey: stilkov: there are plenty that just dump ~@body into something like a let or do as well

11:41 stilkov: rhickey: I was wondering about those that don't, yet use [& body] and ~@body anyway

11:41 rhickey: stilkov: searching for ~@ in core.clj can be instructive into the various uses

11:43 stilkov: rhickey: thanks

11:43 bsteuber: I've just been discussing the idea of having and/or being a function that just gets inlined to short-circuit evaluation

11:43 would that be a bad idea?

11:44 I'd love to write (map and boolean-seq1 boolean-seq2)

11:44 chouser: but it would *not* short circuit when used as a function

11:44 sounds confusing to me

11:45 bsteuber: chouser: I thought so, too, at first - but if you pass sth. as a function to apply etc., the arguments would get evaluated anyways

11:45 so you'd expect it to do so

11:46 chouser: (partial and foo) would be greedy on all args

11:46 stuartsierra: bsteuber: your example could be written (map #(and %1 %2) seq1 seq2)

11:47 bsteuber: stuartsierra: sure, the idea is just about simplifying this a little

11:48 AWizzArd: ,(every? boolean (concat [1 2 3] [4 5 6]))

11:48 clojurebot: true

11:48 joshua-choi: (doc boolean)

11:48 clojurebot: "([x]); Coerce to boolean"

11:48 joshua-choi: I did not know about that

11:48 stuartsierra: So (defn add* [& args] (every? identity args))

11:48 chouser: (map and boolean-seq1 boolean-seq2) used to return something, once upon a time.

11:48 stuartsierra: I mean defn and

11:49 and*

11:49 whatever

11:49 chouser: but ... it returned code.

11:49 bsteuber: :)

11:50 at least after I thought of it I found the idea less confusing than in the beginning :)

11:50 because in function-land you expect anything to be eager

11:51 hiredman: (map (comp eval #'and) bseq bseq2)

11:51 chouser: I'm not sure the boundary between function-land and inline-land is very clear to a lot of people

11:52 bsteuber: hmm, maybe

11:53 chouser: hiredman: have you tried that in a recent version of clojure?

11:53 calling macros manually is more complicated than it used to be.

11:53 hiredman: nope

11:53 bsteuber: chouser: btw, do you think it's ok to use images (with citation, of course) from JoyOfClojure in a talk I give at my university?

11:53 hiredman: why would I try such a silly thing?

11:54 bsteuber: not familiar with copyright on images in books

11:54 chouser: bsteuber: I'd think normal fair-use rules apply.

11:54 stuartsierra: just ask the author

11:54 who's not likely to sue you anyway

11:55 chouser: well, the publisher has a legal interest, for now anyway.

11:55 fogus: stuartsierra: Soeak for yourself! ;-)

11:55 Speak that is

11:56 stuartsierra: Seriously, no publisher is going to bother to sue you for using images in one talk.

11:56 bsteuber: ok, then I'll just do it :)

11:56 hiredman: it's a setup

11:56 stuartsierra: but it would be considerate to ask the author's permission

11:57 bsteuber: hm right, I just asked one of them so far :)

11:57 fogus: My plan is to make more money off of litigation than book sales.

11:57 hiredman: sierra talks you into giving the talk, and peddles his expert clojure legal opinions to the publishers law firm and you can turned into a smoking crater

11:57 bsteuber: chouser, fogus: so you personally wouldn't mind?

11:57 stuartsierra: hiredman: darn, you've figured out my secret plan!

11:58 bsteuber: haha

11:58 fogus: bsteuber: I do not. Which image(s)?

11:58 stuartsierra: IANALAIAPOTFETIWAALS

11:59 I Am Not A Lawyer And I Am Proud Of That Fact Even Though I Work At A Law School

11:59 hiredman: * see back of card for consulting rates

12:00 bsteuber: fogus: at least the mutable runner for now

12:01 fogus: and maybe the three circles from the start

12:01 chouser: bsteuber: yeah, as long as you credit the book, I don't mind in the least.

12:03 bsteuber: chouser: I will for sure :)

12:04 Luyt: Hmmm, I think I found a typo in Stuarts book, on page 39 it says "syntax for shorter anonymous function: (#body)" but I think that should be "#(body)"

12:04 ,(#(print "Yup"))

12:04 clojurebot: Yup

12:05 stuartsierra: Which Stuart?

12:06 bsteuber: stuartsierra: do you have a book, too?

12:06 stuartsierra: yes

12:06 not published yet

12:06 No one has ever heard of it.

12:06 Not even me.

12:06 bsteuber: haha

12:07 but it's great there's already at least two very good clojure books out there

12:07 (can't talk about Clojure in Action, yet)

12:07 stuartsierra: yse

12:07 Luyt: Stuart Holloway, "Programming in Clojure"

12:08 stuartsierra: 2010 will be the year Clojure goes mainstream.

12:08 Luyt: eh, "Programming Clojure"

12:08 stuartsierra: We'll all have to shop for ties.

12:08 Luyt: ISBN 101934356336

12:08 chouser: is clojureconj still on for this fall?

12:09 stuartsierra: chouser: what's this?

12:09 chouser: the conference

12:09 stuartsierra: I vaguely remember some talk about that

12:09 Then I heard it wasn't in New York, and I stopped paying attention. :)

12:09 chouser: heh

12:10 If I only paid attention to things around here, I'd have a lot more free time...

12:10 stuartsierra: But who knows where I'll be in the Fall.

12:10 Luyt: If I kept myself to C++, I'd also have more free time. What makes me interested in Clojure?

12:10 technomancy: supposedly it's still on, but with no call for talk proposals yet I have my doubts

12:15 maravillas: I'm trying to work with the change in c.c.str-utils* => c.c.string from 1.1 to 1.2, as well as the changed signature for c.c.str-utils2/drop and c.c.string/drop. There's something happening here that I don't understand...any thoughts? http://gist.github.com/380924

12:16 stuartsierra: don't do that

12:16 maravillas: Which part? :)

12:16 stuartsierra: the whole thing

12:16 just copy the old namespaces from 1.1

12:17 I got to make a ticket for that

12:17 maravillas: sorry, I'm not sure what you're suggesting

12:18 stuartsierra: If you want to use the 1.1 contrib functions, use 1.1. I'm nudging people toward copying the old 1.1 namespaces into 1.2 master, with a deprecation warning.

12:19 Don't try to support two different versions in one piece of code. That way lies madness.

12:22 maravillas: Hm, I see. Will 1.2 generally be considered a breaking upgrade? That is...should libraries not worry about supporting both? I'm not up to date on all the changes, but it seems silly for me to select one if this particular function is the only difference.

12:22 stuartsierra: Current trend is that 1.2 contrib will deprecate a bunch of namespaces, but will try not to break anything.

12:23 Current master branch breaks a lot.

12:23 That needs to change.

12:24 maravillas: Alright, fair enough. I'm still curious what's going on in that snippet, though...I can reference string/drop outside of the try, but I get the exception on the inside.

12:25 raek: maravillas: this might be useful: http://blog.licenser.net/2010/04/22/on-clojure-libs-and-versions

12:25 sexpbot: "lice! : On clojure libs and versions."

12:26 danlarkin: lol at contrib ticket #20

12:26 maravillas: I saw that, but it doesn't deal with my second issue, where the signature for the respective drop functions changes

12:28 raek: ah, ok...

12:29 digash: ,(byte 255)

12:29 clojurebot: -1

12:29 digash: ,(apply byte [255])

12:29 clojurebot: -1

12:29 digash: in the latest 1.2

12:29 user> (apply byte [255])

12:29 -1

12:29 user> (byte 255)

12:29 ; Evaluation aborted.


12:30 the second one throws an exception Value out of range for byte: 255

12:30 stuartsierra: https://www.assembla.com/spaces/clojure-contrib/tickets/79-forward-port-deprecated-1-1-namespaces

12:30 sexpbot: "#79 - Forward-port deprecated 1.1 namespaces (New) | Clojure Contrib | Assembla"

12:31 chouser: ,(.byteValue 255)

12:31 clojurebot: -1

12:31 * chouser just ran into this a few days ago

12:31 digash: cool, but i am still confused why the apply works?

12:32 stuartsierra: byte is actually a type cast to primitive byte.

12:32 chouser: it's the difference between function-land and inline-land

12:32 stuartsierra: It also happens to work as a function, in which case it coerces to byte. But they're different operations.

12:32 digash: feels like a bug to me

12:32 chouser: when used as a function (as with apply), it just does .byteValue on a boxed Number

12:33 stuartsierra: I kinda wish the primitive coercions looked more like type hints.

12:33 e.g. #^byte 127

12:33 only that wouldn't work in the current reader

12:33 chouser: when used inline-ably, it does a cast and thus works with primitives

12:34 stuartsierra: Could the reader support read-time metadata on non-Clojure types by wrapping them in a special "MetaFoo" object?

12:34 digash: maybe (^byte 127) vs (byte 127)

12:35 stuartsierra: ack no

12:35 that would expand to (127)

12:35 rhickey: digash: that is a bug, I didn't realize the fn defs weren't calling through RT

12:36 stuartsierra: rhickey: what do you think of #^byte 127 ?

12:37 rhickey: stuartsierra: #^ is so day-before-yesterday

12:37 stuartsierra: ok, fine, ^byte 127

12:37 one innovation at a time

12:37 rhickey: are we talking for literals only?

12:38 stuartsierra: yse

12:38 yes

12:38 chouser: oh, only literals?

12:38 rhickey: 127b ?

12:38 stuartsierra: hm, maybe

12:38 maravillas: Is there a set approach for dealing with deprecated symbols & namespaces? I appreciate that copying the old namespaces helps with 1.2, but when should we expect that we'll have to actually fix things to reference the new ones?

12:38 stuartsierra: actually, no, I was thinking for symbols too

12:38 oh, never mind

12:39 maravillas: what else could we expect?

12:39 chouser: I actually think it's pretty clever how primitive casts are built directly on interop support -- no explicit reader or compiler code needed.

12:40 maravillas: Of course they'll go away at some point, I'm just wondering if there's a guideline for how long deprecated stuff sticks around.

12:41 Licenser: maravillas: you can work around it with try catch

12:42 stuartsierra: Don't 'require' in try/catch!

12:42 That will drive you maaaaad.

12:42 Licenser: stuartsierra: ma ma ma maaaad

12:42 stuartsierra: If you want to use the new stuff, you've got to abandon some old stuff.

12:42 If you don't need the new stuff, you can stick around with an old version as long as you like.

12:45 rhickey: digash: fixed

12:46 dnolen: 127b and 1f would be cool for literals

12:47 rhickey: [b]yte, [s]hort, [i]nt, [l]ong, [f]loat [d]ouble ?

12:48 stuartsierra: l for long is hard to read, but it is consistent

12:48 chouser: that'll be the default eventually, right?

12:48 rhickey: BigDeci[M]al . BigInteger?

12:48 dnolen: rhickey: yes! graphics/audio code would benefit from less typing.

12:48 chouser: long will be the default eventually, right?

12:49 rhickey: chouser: I hope so

12:49 fogus: I think 131l will be tough to catch

12:49 digash: rhickey: so now it throw an exception always?

12:49 chouser: if the suffix letter is case-insensitive, 131L is a possible

12:49 rhickey: digash: yes

12:50 chouser: rhickey: If I understand your idea for default primitive literals, throwing on overflow, etc. I've grown to like it.

12:50 rhickey: digash: so now these are safe coercions. I'd take a patch for bit-casts

12:50 chouser: I really wish now I had done that up front

12:51 It's a big break with Lisp tradition, but much more practical

12:51 fogus: Why not make the suffix require caps?

12:51 rhickey: fogus: could do, but how would one as for Integer, Long etc?

12:51 ask for

12:51 chouser: combined with a syntax for literal non-defaults types (50i, etc.) a bunch of tricky problems become easier to handle

12:52 fogus: rhickey: L131 is long, 131L is Long... :( I got nothing

12:52 rhickey: fogus: also I becomes a problem then

12:53 stuartsierra: if primitives are the default, then there would rarely be a reason to ask for boxed literals

12:53 digash: (.byteValue n) is the way to get unsigned byte value then?

12:53 stuartsierra: And you could write (Integer. 127) when you need to.

12:53 chouser: digash: no such thing as unsigned byte on the JVM. :-/

12:54 somnium: maybe 123L <- primitive, 123<L> <- boxed ?

12:54 stuartsierra: ugh

12:54 fogus: 131L 131^L

12:55 stuartsierra: erg

12:55 fogus: Hmmm, nothing looks nice

12:55 stuartsierra: maybe we should stick with (long 131)

12:55 Licenser: stuartsierra: but not using require for namespaces would mean we can't make libraries and such that are version independant - that is kind of bad

12:56 stuartsierra: there is no such thing as a library that is version independent

12:56 Licenser: over certain version ranges, yes there is

12:56 stuartsierra: Then releases within those version ranges should aim for some backwards compatibility.

12:56 digash: chouser: i meant in java (byte)177, will "translate" int into byte

12:56 stuartsierra: In other words, the onus of library compatibility should never be on client code.

12:57 Licenser: and if I publish my lib for 1.1.0 and somene has a project in 1.2.0 he want's to use the lib for their thing they should be able to do so witout forking the project I think

12:57 stuartsierra: no

12:57 Licenser: yes

12:57 rhickey: stuartsierra: I agree (long 42) is both verbose and not really making it to the compiler

12:57 Licenser: not on client code stuartsierra but on library code

12:57 stuartsierra: If 1.2 contrib becomes supports backwards compatibility with 1.1, then that problem goes away.

12:57 Licenser: I would not make a app that uses require to work with 1.1 and 1.2. But I certenly made 2 libs arelday that do and they can nicely be included in any 1.1 or 1.2 project

12:58 stuartsierra: Then they should target 1.1.

12:58 rhickey: digash: wow, the spec for byteValue is really bad: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Number.html#byteValue()

12:58 sexpbot: "Number (Java 2 Platform SE 5.0)"

12:58 Licenser: they should 'just work' for most of the people :P

12:58 * digash reading spec

12:59 Licenser: if 1.2 c.c becomes backwards compatible, yes the problem goes away but will it?

12:59 stuartsierra: If I get my way.

12:59 Licenser: :P

12:59 stuartsierra: And I have commit access, so who's going to stop me?

12:59 Licenser: rhickey might

12:59 * stuartsierra laughs evilly

13:00 dnolen: for those that will be casting literals to primitive long often, 131l is fine I say, also seems like something that's not hard to highlight with syntax highlighting

13:00 Licenser: if I support your effort will you make a clojure.controb.silly namespace for me? where can go funtions like (defn rand [& _] 4) ;from xcdk or (defn cokkies [] (println "*nom nom nom*"))?

13:00 rhickey: 1.2 cc becoming backwards compatible is me getting my way too

13:01 Licenser: shush rhickey I was about to con stuartsierra in making a silly namespace!

13:01 don't backstab my efforts :P

13:01 digash: ,(.byteValue 1234)

13:01 clojurebot: -46

13:01 slyphon: so, in the repl (and only in the repl), is it possible to say, add 'pp' and 'pprint' to clojure.core so that it's available everywhere?

13:02 stuartsierra: Licenser: there's some pretty silly stuff in there already

13:02 Licenser: stuartsierra: you know if you do that and make 1.2 cc backwards compatible my only usefull blog post in the last 2 years will become meaningless *shakes fist*

13:02 stuartsierra: heh

13:02 The best code needs no blogs.

13:03 You can quote me.

13:03 chouser: in your blog

13:03 slyphon: that's the main problem with ruby

13:03 Licenser: heh

13:03 slyphon: everyone confuses blogging-about-code with code quality

13:03 Licenser: stuartsierra: well you can still use a blog to tell people nice things?

13:03 stuartsierra: sure

13:03 livingston: what's the correct way to shutdown the repl / swank / etc. from emacs swank-clojure-project ?

13:04 stuartsierra: But blog posts are no substitute for good documentation.

13:04 dnolen: livingston: I use slime-quit

13:04 stuartsierra: Licenser: you want silly, check out c.c.apply-macro

13:04 tomoj: livingston: at the repl, type ',', then type 'sayoonara'

13:04 Licenser: slyphon: no I don't confuse that but when I started my blog I decided not to make a whine girl dairy but write about things that matter (for me) IT wise so if I don't blog aobut code I blog about hardware and my little cluster of atom boards seemed not to be of interest :P

13:04 slyphon: hahaha

13:04 well, i salute your intentions

13:05 Licenser: thank you

13:05 so the atom cluster was pretty cool even so noone liked it

13:05 stuartsierra: I have a blog too. I hate myself for it.

13:05 livingston: dnolen: I don't have that defined? there's a slime-quit-lisp

13:05 dnolen: livingston: that's the one

13:06 slyphon: stuartsierra: yeah, i do too, i just never really update it

13:06 Licenser: about 95% of all blogs go along the line 'oh my god a bird pooped on my shoe, my life is so horrible meh meh meh'

13:06 stuartsierra: livingston: ,quit at the REPL also works

13:06 slyphon: unless i *really* get annoyed at ubuntu

13:06 stuartsierra: Licenser: heh :)

13:06 livingston: dnolen: that'll tear everything down, right?

13:06 dnolen: livingston: yes

13:06 tomoj: for some reason I always use ,sayoonara

13:06 Licenser: I could blog about cooking too but then I never can write down my recepies

13:06 ,sayoonara

13:06 clojurebot: java.lang.Exception: Unable to resolve symbol: sayoonara in this context

13:07 stuartsierra: It's a SLIME feature.

13:07 livingston: stuartsierra: I tried forms of that but you mean with the comma too? (I thought maybe (quit) or (exit) would be bound

13:07 stuartsierra: no

13:07 comma+command is a SLIME feature, there are several commands

13:07 Licenser: ,cookies

13:07 clojurebot: java.lang.Exception: Unable to resolve symbol: cookies in this context

13:07 kzar: Is there an easy way to "map" a tree?

13:08 stuartsierra: To kill a standard REPL, Ctrl-C or Ctrl-D usually does the trick.

13:08 kzar: (into {} (map (fn [key value] ...)) is the easy way

13:08 Licenser: kzar: I wrote some code for that

13:08 livingston: stuartsierra: yeah I'm in emacs - so that won't cut it

13:09 stuartsierra: kzar: (reduce (fn [result [key value]] (assoc result...)) {} ...) is the fun way

13:09 Licenser: http://github.com/Licenser/clj-sandbox/blob/master/src/net/licenser/sandbox.clj#L15

13:09 livingston: kzar: look at the "zip" routines

13:09 tomoj: livingston: get at the repl. type ','. now type 'quit' or 'sayoonara', your choice. now hit RET.

13:09 Licenser: if yo actually mean what I ment by that

13:09 stuartsierra: livingston: killing the *inferior-lisp* buffer also does it

13:10 tomoj: similarly ,i will let you change the namespace

13:10 rhickey: seq-contains? for sequential equality lookup?

13:11 stuartsierra: linear, right?

13:11 rhickey: yes

13:11 tomoj: wonder what pushd and popd do, they seem to be undocumented

13:11 stuartsierra: adding contains-key? or has-key? for associative would be clearer, I think

13:11 rhickey: then at least find-doc "contains" will find it, vs includes?

13:11 or apropos

13:12 stuartsierra: but can't break 'contains?' right now, so yeah

13:12 Licenser: well people I hop in the bath see you alter

13:13 kotarak: ,(doc tree-seq)

13:13 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

13:13 kotarak: kzar: maybe that is what you need?

13:14 * technomancy votes for adding a deprecation warning to contains? while making contains-key? be the Way of the Future.

13:14 livingston: kzar: there is a set of stuff in clojure.walk that will help you

13:14 stuartsierra: clojure.walk must die

13:14 I gave birth to a monster.

13:15 rhickey: technomancy: so the performant, often used one should get the long name and the inefficient use-at-your-own-risk one the short name?

13:15 chouser: has-key? is shorter than contains?

13:15 technomancy: rhickey: no, I think "contains?" should be dropped eventually

13:16 not that it should become seq-contains?

13:16 rhickey: technomancy: but it should become contains-key?

13:16 technomancy: actually yeah, has-key? is probably better than contains-key?

13:16 powr-toc: will has-key return the key if present?

13:17 rhickey: powr-toc: you have the key in hand when you ask, and what about nil?

13:17 kotarak: powr-toc: kind of like not-empty ?

13:17 stuartsierra: powr-toc: no, 'get' does that

13:17 no

13:17 ignore that

13:18 rhickey: ,(doc find)

13:18 clojurebot: "([map key]); Returns the map entry for key, or nil if key not present."

13:18 stuartsierra: right

13:18 powr-toc: stuartsierra: yes, fair point

13:19 stuartsierra: ,(contains? #{1 2 3} 2)

13:19 clojurebot: true

13:19 rhickey: well, the only thing on the table right now is the name for what c.c.seq/includes? does right now, moving into core

13:20 I don't like includes?

13:21 chouser: seq-contains? seems nice for that.

13:21 * kotarak doesn't need includes. (some #(= % x) ys) is fast to type and sufficiently ugly.

13:21 stuartsierra: yeah

13:21 chouser: can some remain idiomatic though?

13:21 rhickey: what about rand-nth for rand-elt?

13:21 kotarak: the problem with some is that few will think of that before they've been shown it

13:23 kotarak: Maybe there should be a Cookbook. "How to do FOO in Clojure..." "Chapter 21: Linear search: (some #(= % x) ys)"

13:23 powr-toc: rhickey: that happened to me today... It's been a while since I've been coding clojure, and it took a few minutes digging before I found 'some' again.

13:24 stuartsierra: seq-contains? is good enough

13:25 technomancy: seq-contains? is nice in that it highlights the fact that it's slow/sequential

13:25 kotarak: linear-search-which-is-slow-use-at-own-risk, but jokes aside: seq-contains? sounds ok to me, too

13:25 rhickey: technomancy: great! that's what I was going for

13:26 so, I have the same concern with readn-elt, thinking rand-nth. Then at least you know that if nth is fast, rand-nth is too

13:26 rand-elt

13:26 stuartsierra: Imagine if all fns were annotated with metadata describing their big-O performance: could useful metrics be devised from that information?

13:26 rhickey: a;so, we don't use elt anywhere else

13:27 livingston: some has always gone nice with every, etc.

13:27 chouser: I don't like "elt"

13:27 rhickey: chouser: does that mean you like rand-nth?

13:27 chouser: rand-nth seems nice, yeah

13:27 livingston: by the way is there a parallel some? (I know there is a parallel map) I could see myself looking for that in the very near future

13:27 technomancy: how about rand-from ?

13:27 stuartsierra: "elt" is good for situations like (rand-elk herd-of-bison)

13:28 rhickey: ouch

13:28 stuartsierra: heh

13:28 kotarak: maybe choose

13:28 no, rand-nth is better

13:28 stuartsierra: yes, joking aside

13:29 chouser: rand-nth will work on seqs, but force the whole thing and do O(n) lookup?

13:29 stuartsierra: that would be more or less consistent with nth

13:30 rhickey: chouser: whatever nth does, given some random n

13:30 in range

13:30 stuartsierra: but it's got to count first, so that's going to force a lazy seq

13:31 rhickey: stuartsierra: that doesn't change the big-O

13:31 stuartsierra: true

13:32 rhickey: people that use these things on large seqs are asking for trouble. Just want to make that clear to them

13:32 stuartsierra: Right, (rand-nth (range 100000000)) will blow heap unpredictably!

13:32 no, predictably

13:32 never mind

13:32 * stuartsierra goes back to his sandwich

13:32 rhickey: I can't help people that do that

13:34 chouser: well, ranges could be Indexed. :-)

13:34 stuartsierra: actually, having a real Range object might be useful someday

13:35 rhickey: we had one, and it implemented Counted

13:35 stuartsierra: oh, what happened?

13:36 rhickey: it became a testing ground for chunks

13:36 LauJensen: rhickey: chunks going away soon? :)

13:37 stuartsierra: oh, so it was cut up into chunks and sold?

13:37 rhickey: LauJensen: no

13:37 LauJensen: rhickey: Thats sad. I was hoping your new cell construct could eliminate the need for them

13:38 rhickey: LauJensen: only so many hours in a day here

13:38 stuartsierra: :)

13:39 LauJensen: rhickey: Yea we're all feeling it. My question didn't have an end-date, so I was just poking at whether or not it was in the pipe for 1.3 or 1.4 etc

13:39 rhickey: how much do people care about group-by returning a map that is sorted?

13:39 stuartsierra: never noticed it did

13:39 arohner: rhickey: I wrote my own unsorted group-by so I could use transients

13:39 rhickey: arohner: exactly

13:39 Licenser: well night people

13:41 kotarak: rhickey: never needed sorted group-by, got bitten by it once.

13:42 rhickey: kotarak: bitten how?

13:42 non-comparables?

13:42 kotarak: rhickey: I think so. IIRC. Was a while back.

14:06 slyphon: you know, the java interop stuff would be a little easier to use if calling it could be more dynamic

14:07 mefesto: hey everyone, i have a newbie style question. with the names invoice-inc, invoice-str... am i not using namespaces the way i should be? should names that match core function names be avoided? http://pastie.org/937655

14:07 slyphon: i.e. pulling the literal symbol as the method that . is going to call makes it kind of difficult for a non-lisp-master

14:08 mefesto: i guess i'm wondering if invoice/str is preferred to invoice-str ?

14:09 joshua-choi: mefesto: The answer is not clear-cut.

14:09 slyphon: well

14:09 shadowing core function names is probably a bad idea

14:09 chouser: slyphon: I don't quite know what you mean yet

14:09 not necessarily. nothing wrong with invoice/str

14:10 not really much wrong with invoice-str either. :-)

14:10 * kotarak happily shadows core functions in clojureql

14:10 joshua-choi: slyphon: Actually, shadowing core function names was actually preferred when possible, according to a draft of Clojure style people were making on clojure-dev.

14:10 slyphon: chouser: it's very difficult to do this: (. blah (some-method-name-that-i-constructed-elsewhere arg1 arg2))

14:10 joshua-choi: uh, wut?

14:10 chouser: mefesto: invoice-inc is (update-in inv [:num] inc)

14:11 slyphon: joshua-choi: seriously?

14:11 stuartsierra: slyphon: that's explicitly not allowed

14:11 slyphon: stuartsierra: but why?

14:11 joshua-choi: slyphon: Let me try to find it

14:11 stuartsierra: reflection

14:11 slyphon: i'm confused

14:11 there are legitimate reasons for wanting to do stuff like that

14:11 stuartsierra: (. object (method ...)) can become a bytecode method call, with appropriate type hints.

14:12 slyphon: ok, but what if you're willing to take the performance hit?

14:12 stuartsierra: Then use reflection.

14:12 RT/invokeMethod or something

14:12 slyphon: hrm

14:12 is that documented?

14:12 stuartsierra: no

14:12 joshua-choi: slyphon: http://groups.google.com/group/clojure-dev/browse_frm/thread/d090b5599909497

14:12 slyphon: ...

14:12 stuartsierra: but java.util.reflection is

14:13 slyphon: yeah, but that's a pain in the balls

14:13 joshua-choi: My language was too strong; it's not "preferred", but "don't be afraid to".

14:13 slyphon: stuartsierra: sorry, i know that's a poor argument

14:13 chouser: ,(clojure.lang.Reflector/invokeInstanceMethod 4 "toString" (to-array []))"4"

14:13 clojurebot: "4"

14:13 stuartsierra: sorry, that should be java.lang.reflect

14:13 slyphon: i don't mean to be a whiny bitch

14:14 chouser: slyphon: there are legitimate reasons to do that, but not as often as you might think, and doing it efficiently can be tricky

14:14 stuartsierra: The dot special form can't be dynamic and avoid the reflection at the same time.

14:14 chouser: it's a kind of meta-programming and should be approached with caution, or at least that appears to be Clojure's take. Other (slower) JVM languages may take other approaches.

14:15 on techinque I've used is to (eval `(fn ...)) and cache the resulting fn.

14:15 this is relatively succinct and quite fast after the initial eval

14:15 stuartsierra: huh

14:16 slyphon: so (eval `(fn [] (. ~thing ~@arglist)))

14:16 ?

14:16 chouser: yeah

14:16 ,(let [s (eval `(fn [n#] (. n# ~(symbol "toString"))))] (map s (range 4)))

14:16 clojurebot: DENIED

14:16 * slyphon laughs

14:17 chouser: :-( he hates my metaprogramming.

14:17 slyphon: hahaha

14:17 i'll try that in my repl

14:17 stuartsierra: It makes a kind of sense: you're generating thunks that contain compiled method calls.

14:17 kotarak: The lesson for using eval...

14:17 chouser: stuartsierra: exactly

14:17 stuartsierra: Actually similar to what the compiler itself does, I think.

14:17 slyphon: ah

14:17 * kotarak is obviously only a journeyman. Not a master.

14:18 slyphon: ok, well, that makes sense

14:18 cgrand: rhickey: (joining the party late) on group-by, I'd like it to take 4 args: [key-fn f seed coll], the 2-args case would then call (group-by key-fn conj |] coll)

14:18 chouser: well, not a thunk exactly, but yeah -- implementing IFn via eval :-)

14:18 stuartsierra: right

14:18 slyphon: stuartsierra: and the argument for performance is a compelling one

14:18 as long as there's "a way to do it" that doesn't require pulling out the "big gun" of Reflection

14:19 well, it's kind of a big gun to me

14:19 * slyphon is not a java master

14:19 chouser: slyphon: depending on the circumstances, a macro or :inline fn may work and be easier than caching eval results

14:19 slyphon: :inline ?

14:19 chouser: more undocumented compiler fun. :-)

14:19 slyphon: i've tried that above with a macro and didn't get far

14:20 cemerick: ouch; at some point Region lost its DEFAULT value, so the ebs wrapper is now broken; gotta get some AOT-compilation into the build process so that stuff gets caught...

14:20 kotarak: slyphon: macros only get you to compilation

14:20 cemerick: ugh, sorry, wrong channel

14:20 slyphon: mmarczyk and i tried that for a while

14:20 chouser: for both macros and :inline, it only works if you can compute the method name at compile-time.

14:20 slyphon: ahh

14:20 * kotarak finds macros compelling and almost never uses them.

14:20 slyphon: yeah, that's probably not gonna work here

14:20 chouser: where are you getting your method name from?

14:21 slyphon: in this case it's pretty static, but the number of args changes

14:21 in the case with mmarczyk, i was trying to write a complement to the 'bean' function that let you update a bean

14:21 (i wound up using reflection)

14:22 chouser: I've been doing some crazy/fun stuff along these lines with Google protobufs.

14:22 slyphon: oh yeah?

14:22 chouser: But it's for work, so I'll have to jump through some hoops to get it open-sourced.

14:22 slyphon: i've been meaning to look at those

14:23 it sounds really interesting

14:23 chouser: if you can get away with slinging clojure s-exprs around as text or something, I highly recommend that.

14:23 protobufs are all static and java-y

14:23 * slyphon nods

14:23 slyphon: i was gonna ask

14:23 stuartsierra: chouser: tried avro?

14:24 * slyphon prepares to ask a total lisp-n00b question

14:24 chouser: but if you need them (in my case for interop with other services that use protobufs) they can be made pretty fast and convenient in Clojure.

14:24 slyphon: if i wanted to serialize a clojure data structure and stick it in a javax.jms.TextMessage, how do i do that, then un-freeze-dry it

14:24 ?

14:24 stuartsierra: slyphon: prn-str, then read-string

14:25 lancepantz: we use protobufs

14:25 slyphon: ok, i kinda thought that was it

14:25 chouser: stuartsierra: no, I haven't. I wasn't involved in choosing protobufs, just using them.

14:25 stuartsierra: prn/read only works for simple cases, though

14:25 ah

14:25 lancepantz: they are really really fast, we use atomic appends as well

14:26 chouser: avro sounds interesting though

14:26 slyphon: oy, *another* apache project?

14:26 ;)

14:27 guys, give someone else a chance!

14:27 stuartsierra: I think Avro grew out of Hadoop, actually.

14:27 slyphon: yeah, looks like it

14:27 stuartsierra: Hadoop had its own binary serialization protocol that nobody used.

14:27 LauJensen: nobody used?

14:28 stuartsierra: Yeah, it was called Hadoop Records or something.

14:28 lancepantz: has hadoop switched to avro now?

14:28 stuartsierra: dunno

14:28 LauJensen: Oh that one. They had that Binary format where you could munge a bunch of files together which was quite useful

14:29 stuartsierra: no, that's still there

14:30 LauJensen: I should really blog more about Hadoop, so much cool data to be crunched

14:37 What is this ibm-jdk-clojure-build stuff on build.clojure.org?

14:37 dysinger: I added it

14:37 for stuart holloway

14:37 to test for bugs in clojure 1.2

14:37 LauJensen: its a test suite of sorts? Or just targeting a different jvm ?

14:38 dysinger: diff vm

14:38 LauJensen: ah ok, thanks

14:43 livingston_afk: i messed with protobufs for a while in common lisp, mostly because I wanted to make it into a tutorial on how you could hack the reader to read the format file - it was panning out to be pretty straightforward (only a few files of code), but I let it die

14:44 considering it was mostly thesis-avoidance it kinda had to go -- maybe I'll pick it up again someday

14:47 livingston: is there a convenient way to give struct-map a default map to extend?

14:48 i mean I can merge, I just thought there might be something else

14:54 stuartsierra: no

14:55 livingston: yeah now that I look at it, I kinda like the merge anyway

15:07 LauJensen: When you guys are running off the latest versions on github, which version of swank do you use with that ?

15:07 stuartsierra: 1.2.0-snapshot

15:08 LauJensen: stuartsierra: Do you pull everything via deps or build yourself?

15:08 stuartsierra: I use maven

15:08 LauJensen: How?

15:08 clojurebot: with style and grace

15:08 technomancy: LauJensen: you should be fine using the version on clojars

15:09 LauJensen: k

15:09 Chousuke: heh, sometimes clojurebot amuses me :P

15:09 technomancy: and there should be a new release soon

15:09 fingers crossed.

15:09 LauJensen: new release as in ?

15:09 technomancy: 1.2.0 stable

15:10 LauJensen: ah ok. How often are the snapshots pushed to clojars?

15:10 technomancy: it's not automated, but it happens often enough

15:11 * LauJensen frowns

15:11 technomancy: the swank-break stuff is in there, but not a lot has been committed since then

15:11 * technomancy is going to get a chance to go through and apply recent submissions soon, honest.

15:12 LauJensen: If not I'll email your employer explaining why he must fire you so that the opensource community can live on :)

15:12 technomancy: moar free time!

15:12 last time I lost my job I wrote the Clojure PeepCode screencast =)

15:14 LauJensen: hugod is also a committer on swank now, so if I am a bottleneck there is a workaround =)

15:14 LauJensen: lein new produces a bad :dependencies (old version?) and searching clojars for the clojure line is impossible

15:14 hugod: Its a privilegde watching hugo go, man that guy works fast :)

15:14 privilige

15:14 privilege

15:14 hmm, thats looks right

15:15 hugod: LauJensen: :), I built a time machine in my free time

15:15 LauJensen: sensible place to start

15:15 technomancy: LauJensen: interesting; could you submit an issue for that?

15:15 LauJensen: I could... :)

15:16 technomancy: can you drop the lines for lein, for the latest and great clojure, contrib and swank ?

15:17 dakrone: what's the best way to expand something like (my-func '(2 3 4)) into (my-func 2 3 4) ?

15:17 technomancy: sure: [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] [org.clojure/clojure-contrib "1.2.0-SNAPSHOT"] [leiningen/lein-swank "1.2.0-SNAPSHOT"]]

15:17 though you want lein-swank in dev-dependencies actually

15:17 kotarak: dakrone: apply

15:17 LauJensen: thanks

15:18 dakrone: kotarak: cool, thanks

15:19 LauJensen: technomancy: issue reported

15:19 technomancy: thanks

15:20 LauJensen: technomancy: btw - Loved that post you did on your pedantic requirements for contribs

15:25 chouser: technomancy: looks like you're using c.c.condition -- how's that going?

15:26 technomancy: chouser: I like it quite a bit

15:26 dysinger: "LauJensen: If not I'll email your employer explaining why he must fire you so that the opensource community can live o" <- lol

15:26 no emails needed

15:26 :)

15:26 LauJensen: ok, phil is *poof* :)

15:27 dysinger: no we need phil

15:27 technomancy: oh noes!

15:27 chouser: technomancy: excellent. I've been hesitent to walk away from vanilla throw/catch

15:27 * danlarkin gasps

15:27 technomancy: chouser: with contrib ticket #80 you can catch vanilla Exceptions in handle-case forms

15:28 which makes them mesh fairly naturally

15:28 chouser: yeah, I saw that. looks good.

15:29 hugod: what's the distinction between condition and error-kit?

15:29 chouser: condition is might lighter-weight

15:29 -might +much

15:29 LauJensen: and condition is might heavier-weight

15:30 (sorry couldnt resist =)

15:30 technomancy: I like the idea behind error-kit, but it seems like it would be more useful if everyone else used it. it seems like it's subject to more of a chicken/egg dilemma

15:30 LauJensen: what dilemma? chicken came first

15:30 stuartsierra: dinosaurs had eggs

15:31 chouser: error-kit provides rarely-used features around outer dynamic scopes controlling the behavior of inner 'raises' and handlers.

15:31 and for free you also get a clumsy undocumented object system

15:32 ordnungswidrig: re

15:33 hugod: I miss CL restarts, very useful in slime

15:33 LauJensen: hugod: go implement, chop chop

15:34 chouser: you might be able to do something interesting with debug-repl + error-kit

15:34 hugod: well, patching condition/raise to call swank-break would be easy

15:34 chouser: but you'd probably be better off just using a Java debugger

15:34 LauJensen: chouser: only problem is, that they're hard to fit into Emacs

15:35 chouser: Java debuggers? Someone did it already.

15:35 * chouser digs through the log

15:35 cemerick: is JDEE still unpleasant?

15:35 chouser: all java is more pleasant from Clojure, even JDEE. :-)

15:36 algoriffic: hi all, how do i print out all nodes at a certain depth of an arbitrary tree structure?

15:36 hugod: LauJensen: haven't had time to do that yet...

15:37 LauJensen: k

15:40 digash: hmm, interesting message from defprotocol: Warning: protocol #'bar.foo/PacketHeaderReader is overwriting method foo of protocol MessageHeaderReader


15:40 chouser: technomancy: would there be any value in the Condition instance printing its values?

15:40 stuartsierra: digash: that's a bug with AOT-compiled protocols

15:41 I think

15:41 chouser: really?

15:41 stuartsierra: if the method names are the same

15:41 but that's not what digash posted

15:41 chouser: you can't have two protocol methods with the same name for two different protocols in the same namespace

15:41 AOT or not

15:42 digash: why is that?

15:42 chouser: they're namespaced to the namespace, not to the protocol.

15:42 digash: hmm, i am generating protocols in the macro, need to figure out how to do it then.

15:43 chouser: just think about how you'd call the protocol method and it should make sense.

15:44 (defprotocol Foo (bar ...) (baz ...)) (my.ns/bar ...) ; note no Foo in the method call

15:45 digash: ah, i see, it is different from deftype fields

15:46 i need to generate accessors to my generated deftypes

15:46 fields

15:48 chouser: hm... or have them implement ILookup so you can do (:my-field obj)

15:48 fogus: So for type (deftype Foo [a b])

15:48 and (def x (Foo. 1 2))

15:48 we can currently do (.a x)

15:49 But maybe that is not going to be true tomorrow?

15:51 chouser: fogus: That's documented and pretty well guaranteed I think

15:51 "The class will have the immutable fields named"

15:51 fogus: So accessor problem solved then?

15:53 digash: what about definterface, are the names of methods also namespaced?

15:53 also what is hms? hash-map-set?

15:54 chouser: definterface produces an interfaced ("namespaced" in a Java package) with Java methods ("namespaced" in the interface)

15:56 digash: maybe i need that, then the java api would make more sense

16:04 ,(definterface Dig (foo-bar []))

16:04 clojurebot: java.lang.Exception: Unable to resolve symbol: definterface in this context

16:05 digash: (show Dig)

16:05 === public abstract interface user.Dig ===

16:05 [ 0] foo-bar : Object ()

16:05 shouldn't it put _ in the name?

16:05 chouser: I think there's a ticket for that

16:06 digash: chouser: cool, thanks, just making sure my expectation is correct

16:07 chouser: though I'm not finding it now

16:08 digash: https://www.assembla.com/spaces/clojure/tickets/306

16:08 sexpbot: "#306 - definterface does not convert - to _ (Fixed) | Clojure | Assembla"

16:09 tcrayford: that's been fixed recently that one

16:09 just saw it when I was looking through the commit log for clojure

16:10 * digash updating my clojure 1.2 snapshot

16:11 tcrayford: ,(doc group-by)

16:11 clojurebot: "([f coll]); Returns a sorted map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll."

16:13 digash: hmm, it is still broken in clojure-contrib-1.2.0-20100427.200505-82.jar

16:15 chouser: well, turns out that patch only munges package names, not method names.

16:16 rhickey: digash: might I ask why you would have an interface with an invalid Java name?

16:16 do you really want to expose name munging to Java clients?

16:17 digash: i started with defprotocol but ran into issue of namespace methods

16:17 they i thought let me use interface

16:17 rhickey: the only reason we are supporting -/_ in packages is because people are already in my-ns...

16:17 digash: what was the namespace methods issue?

16:18 digash: and make it also available to java people

16:18 yes

16:19 rhickey: digash: what was the namespace methods issue?

16:19 digash: sorry, i misread you question

16:19 i would not call it an issue, more ignorance on my part of protocol

16:20 i though protocols are like interfaces

16:20 and will generate java interface classes

16:20 rhickey: they will

16:21 digash: then i am confused about the method names in the protocol being namespaced NOT including the protocol name

16:22 rhickey: my.ns/Protocol becomes my.ns.Protocol interface, protocol method foo becomes interface method foo

16:23 digash: my.ns/Protocol1, method foo gives me a warning

16:23 rhickey: you wanted my.ns.Protocol interface, Protocol_foo method?

16:23 what warning?

16:23 digash: <digash> hmm, interesting message from defprotocol: Warning: protocol

16:23 #'bar.foo/PacketHeaderReader is overwriting method foo of protocol

16:23 MessageHeaderReader [15:39]


16:24 rhickey: right, protocols put fns in the current namespace, so two protocols that define the same-named fn must be in different namespaces

16:25 you can think of protocols as a way to define a set of fns in your ns

16:26 still subject to the one def of name per ns

16:27 digash: the interface = protocol thing confused me, since it is possible in java to do it with interfaces

16:27 rhickey: to do what?

16:27 two interfaces in same package with same method name?

16:28 digash: my.ns/Interface1 (foo) and my.ns/Interface (foo)

16:28 yes

16:29 chouser: digash: depending on what you're trying to do, you could have your macro generate a whole namespace for your protocol.

16:30 digash: yes i guess i can do it, but I prefer it to be javaish

16:30 since people are going to use it from java

16:31 chouser: maybe you want to use definterface and munge the method names yourself. my-method -> myMethod

16:31 rhickey: chouser: this seems independent of the munging

16:32 digash: how would you use it from Clojure?

16:33 chouser: I haven't seen much pushback on the inability to share proto-method names in multiple protos of the same ns. digash seems to be running into it because of generating the names in a macro

16:34 digash: I would generate deftype or defrecord and the implementation for them

16:34 it is like a small compiler

16:35 the methods are very repetitive, it is a parser for the byte array and each method have offset and length and datatype

16:35 rhickey: chouser: I could see it coming from requirements that the Java side look like a.b.C and a.b.D interfaces, both with method foo. Couldn't deliver with protocols as it stands

16:36 chouser: sure, I can see that. Though it's an interop concern that definterface deals with already.

16:37 digash: chouser: i am implementing munging with definterfaces as we chat...

16:37 * rhickey still doesn't get the munging bit

16:38 chouser: digash: where are you getting these method names (with dashes in them) from?

16:38 digash: data dictionary based on the spec

16:39 chouser: is there a reason you don't want them to have javaCamelCase names in the spec?

16:40 digash: there are hundreds of them and i copied it from the spec with spaces and replaced spaces with -

16:40 so now i need to do camel-case on them

16:40 rhickey: Java devs wouldn't expect _s usually

16:41 chouser: so even from the clojure code you'll be using camelCase and java interop syntax?

16:43 rhickey: yes, that's what I'm missing, how do you intend to implement and consume on the Clojure side?

16:44 digash: i made it a macro, so i can bounce off the client, the names of methods

16:45 the consumption would be to call a constructor with byte buffer

16:45 rhickey: and the method calls via interop?

16:45 digash: and then call any accessor and get a field value back

16:46 ah, i see, another ignorance on my part

16:46 rhickey: digash: not necessarily, it could be some missing feature

16:47 chouser: heh, I guess you could generate one protocol per namespace (with dashed-names), and extend it to all the generated interfaces (calling camelCase methods)

16:47 digash: the methods on the defrecord are not available in java ?

16:47 rhickey: e.g. it would be easy to let defprotocol specify the name of the interface type

16:47 digash: the only methods you can have in defrecord are those in interfaces, and thus consumable in Java via those interfaces

16:48 digash: not the ones on the protocol

16:48 rhickey: digash: yes, those too via its interface

16:49 chouser: if it feels like magic, that's because it is.

16:49 rhickey: all methods of a deftype/record are available from Java

16:50 not extends of course

16:50 digash: ok, let me restate my understanding of protocols

16:51 defprotocol will give me java interface

16:51 chouser: digash: if I understand what you're implementing now, you'll have an interface with camelCase accessors, and you'll be able to call those on an record that implements it from both java and clojure

16:51 mtm: before I roll my own, does anyone know of a GML (Graph Modeling Language, not Geography Markup Language) parser for Clojure (or, barring that, one for java)?

16:51 chouser: but from clojure, it'll look like java interop: (.foo myrecord)

16:51 rhickey: digash: yes, with interface type name my.ns.Protocol

16:52 digash: defrecord "implments" that protocol and gives me class

16:52 then i can call the methods on the class through the interface

16:53 rhickey: digash: when you implement the protocol inline, the resulting record isA my.ns.Protocol. You never leverage that from the Clojure side explicitly

16:53 digash: you'd call them that way from Java, but use my.ns/foo from Clojure usually

16:54 doing so does away with all of the interop cruft and need for type hints, (foo x) is the same as (.foo ^my.ns.Protocol x)

16:56 digash: now, i see where the requirement for the namespace coming from

16:56 clojurebot: namespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

16:58 slyphon: with .. do you have to wrap thunks in () ?

16:58 chouser: we haven't deprecated .. yet?

16:58 * chouser ducks

16:58 slyphon: :(

16:58 uh

16:59 should i use -> then?

16:59 stuartsierra: slyphon: to answer your question, no

16:59 chouser: I always recommend it, but I've been shot down on that point by Important People, so take it for what it's worth.

16:59 digash: i think i am going to stick with interfaces for now, since one of my goals is a java api and create names to look like java accessors getField, etc.

16:59 * slyphon nods

16:59 slyphon: i like ->

17:00 digash: rhickey: thank you for clarifications

17:00 chouser: what do you mean by thunks in .. ?

17:00 digash: chouser: thank you for suggestion

17:00 slyphon: (.. thing getSomething (add blah))

17:00 being thing.getSomething.add(blah)

17:01 er

17:01 being thing.getSomething().add(blah)

17:01 chouser: ah. right, what stuartsierra said. no need for parens if you only have the method's name there

17:01 slyphon: kk

17:01 Borkdude: -> is like a spear which forces your objects to accumulate through functional spheres

17:01 slyphon: Borkdude: :D

17:01 ->> is that but harder

17:01 blasts them clear to the other side of the parens

17:07 ataggart: I liked the notion that -> is for banging on an object and ->> is for banging on a stream

17:08 inferred from something Rich wrote once

17:08 Chousuke: hm, why does that sounds painful to me?

17:08 like, you're mutating an object by banging it with a hammer or something

17:08 Borkdude: slyphon, how does Clojure's -> behave in comparison with C's --> operator? http://www.guyrutenberg.com/2007/11/19/c-goes-to-operator/ ;-)

17:08 sexpbot: " C’s “Goes To” Operator by Guy Rutenberg"

17:08 chouser: I always thought it was about how many open-mouthed people were trying to eat the cookie on the left.

17:09 no, actually, I didn't.

17:09 slyphon: hahahhaa

17:09 where is the -?> hiding?

17:10 Borkdude: wow, nothing like that

17:10 Borkdude: that's kind of cool, though

17:10 Borkdude: in a "Oh my god C syntax is totally retarded" kind of way

17:10 Borkdude: haha

17:10 slyphon: "Please stop doing that, it's going to fall off eventually"

17:16 Borkdude: "Most programmers know Lisp for its parentheses. Few programmers know their power."

17:18 I was thinking, while reading The Joy of Clojure about vectors being so ubiquitous in Clojure, if Lists to present code is still the right choice? Probably, because you always start with the head of a program and then the rest?

17:20 stuartsierra: In general, Clojure uses lists for things that will get evaluated somehow.

17:20 And vectors for things that won't.

17:24 Borkdude: stuartsierra: things that will get evaluated... I can think of one example: code

17:24 stuartsierra: yeah

17:24 I think I misunderstood your question.

17:25 Borkdude: I'm just checking if you had other things than code in mind

17:27 putting code into vectors instead would be back to GW-Basic: goto 10 ;P

17:29 stuartsierra: it isn't entirely true btw, Clojure uses vectors for argument 'lists

17:29 ', those will get evaluated first

17:30 But I'm just thinking out loud while being very tired, I better not do that

17:36 rich_holygoat: hi folks

17:36 I just ran into an annoying impedance mismatch; thought I'd run it past the IRC brains before hitting the list

17:37 deftype generates final classes; JAX-WS mandates that its classes be non-final. Is there any way to force deftype's classes to be non-final?

17:38 chouser: and an interface won't do?

17:39 rich_holygoat: chouser: it's the implementing class that gets annotated as a WebService, not its interface

17:39 "implementing class must not be declared final and must not be abstract... must have a default public constructor... must not define a finalize method..."

17:40 I don't know why, but there it is

17:44 Borkdude: Cool, Clojure in Action MEAP update

17:48 rich_holygoat: ah, reading the compiler source it looks like individual fields can have final removed by marking them as mutable, but the class as a whole is always emitted as final (and public, for that matter)

17:50 chouser: rich_holygoat: you might have to use gen-class to meet such specific requirements.

17:50 rich_holygoat: falling between two stools -- gen-class doesn't yet have annotations (though I see the patch in Assembla)

17:51 I do wonder precisely why the generated class is final -- it might just be that all other classes generated by Clojure using this mechanism are final, so it's this way by default

17:52 perhaps I'll ping Rich and see if he has a reason; I'm not averse to doing the patch work.

17:53 chouser: Clojure doesn't like implementation inheritence.

17:53 pure virtual abstract interfaces or concrete final implementations -- take your pick. :-)

17:54 rich_holygoat: and neither do I -- but it does allow volatile and mutable fields in deftype to allow "rolling up the sleeves". In this case it wouldn't be used for inheritance; merely to satisfy JAX-WS's demands

17:54 it would be a shame to have to add another layer of passthrough

18:05 livingston: I'm assuming alter-var-root is thread safe and will alter for all threads like this: (def foo 5) (binding [foo 2] (pr foo)) ;some other thread alters foo with inc (pr foo) -- I expect to see 2 and 6 printed right?

18:05 rhickey: rich_holygoat: what are JAX-WS's demands?

18:05 livingston: as long as I'm not under the scope of a binding form I always get the current root value, right?

18:05 Borkdude: I made a foolish little program that runs things like this: (def ops ['(goto 2) '(goto 4) '(println "two") '(goto 1) '(println "end")])


18:06 rhickey: livingston: yes

18:06 technomancy: livingston: yes, but in general if you've already got multiple threads running I would say it's too late to be thinking about alter-var-root

18:06 it's a matter of taste, but that's my take on it

18:06 rhickey: technomancy: not really, with no bindings it still makes sense

18:07 technomancy: rhickey: ok, maaaaybe, but it still needs big caution signs all over =)

18:09 livingston: I've got this problem where RDF databases can communicate with an abbreviated URI, using an identifier for the namespace instead... I can query the server for the current mappings - constantly. but since my code is creating them, it'd be nice instead to juse cache them as they are created

18:09 as long as the mapping is cached before it's used, that seems like it'll be ok

18:12 the problem I'm worried about is one thread stores with a piece of short-hand, and later another thread gets it back, either the mappings have to be cached somewhere, or the threads have to ask every time they talk for the mappings in case new ones were added -- I think

18:12 rich_holygoat: rhickey: just sending you an email; saves spamming the channel. In short: non-final classes and a bunch of other things.

18:15 livingston: I'm also assuming binding something to itself is relatively benign?

18:49 sattvik: rich_holygoat: I am guessing that once the gen-class annotation patch is in, that should solve your problems. It gen-class generates non-final, public classes. It should also allow you to have some state and a default constructor.

18:50 vin: How can I find out if "hell" is in "hello world"

18:51 dakrone: vin: (re-find #"hell" "hello world")

18:51 rich_holygoat: sattvik: yes, that's one option; but if non-final deftypes are simply an omission, I'll take that route.

18:52 wooby: Chousuke, thanks for the tip on that futures macro gist

18:54 sattvik: rich_holygoat: deftype certainly is nice. The other problem is that if you want to have fields with a deftype, you cannot have a no-arg constructor.

18:55 rich_holygoat: sattvik: yup. fortunately I don't need fields (servlets etc. typically use a session for that -- they're stateless). deftype is really nice by comparison to gen-class for my purposes.

18:56 sattvik: rich_holygoat: That's good. I ran into the no-arg issue when trying to extend my EJB example with a stateful EJB.

18:58 rich_holygoat: ah, tricky :)

18:58 slyphon: woah, it never occurred to me, you can put a start-fn in a struct

18:58 ~ wacky! ~

18:58 clojurebot: Excuse me?

18:58 slyphon: :)

18:58 clojurebot: botsnack

18:58 clojurebot: thanks; that was delicious. (nom nom nom)

19:00 * a_strange_guy hates the Exception hierarchy

19:07 raek: vin: a non-regex version (not= (.indexOf "hello world" "hell") -1)

19:36 livingston: is there a reason this is giving me a NullPointerException? (def *kb* nil) (alter-var-root *kb* #(if *kb* *kb* a-kb))

19:37 can I not refer to something in it's alter form? (I guess I could call defonce, but this may get called a lot, I thought the alter seemed "cleaner")

19:47 zakwilson_: Is there a built-in (or in contrib) more performant way to persist built-in data-structures to disk than (spit (str foo))?

19:47 technomancy: livingston: your function needs accept one argument, the current root value of the var

19:48 not sure if that would cause a NPE

19:50 livingston: technomancy: that just dawned on me but... there still seems to be an issue:

19:50 ataggart: (alter-var-root #'*kb* #(if-not % "something"))

19:50 livingston: oooooh I have to #' the var?

19:50 ataggart: ya

19:51 cuz *kb* isn't a var

19:51 or rather, it doesnt resolve to a var

19:51 if I jave my lingo correct

19:51 rhudson: livingston: is there a reason you're not doing something like (def abbrevs (ref {})) -- I mean, using a ref or atom for your URI abbrev data?

19:52 livingston: there's no reason for it to be a ref, that I can tell

19:52 rhudson: atom then?

19:52 livingston: a var does the same thing, right? just no transaction support, right?

19:53 rhudson: Seems like atoms are designed for what you're trying to do.

19:55 livingston: I guess atoms would work, but if I wanted to cover the values up with a binding I would then need to bind over it with a new atom etc. I just don't see what it buys me?

19:56 an atom would allow the threads to stay in sync, but I don't think that's really needed in my case

20:04 _rata_: how do I get the minibuffer information that clojure-swank gives while at the REPL buffer in the other buffers as well?

20:05 livingston: _rata_: you mean the function call signatures and things?

20:07 _rata_: livingston: yes

20:08 livingston: my buffers are in mode: (Clojure Slime[clojure]) and seems to work fine for me (w/ AquaMax) it's autodetected on .clj files you might have to add hooks in your .emacs

20:08 (add-hook 'lisp-mode-hook (lambda () (slime-mode t))) (add-hook 'inferior-lisp-mode-hook (lambda () (inferior-slime-mode t)))

20:09 that's pretty standard though, nothing special

20:15 _rata_: oh thanks, livingston :)

20:16 livingston: np, did that work?

20:17 _rata_: I did work before, but I had to press the spacebar after defn for it to show the help... I was standing over a piece of code already written

20:38 livingston: if I have (defmulti clj-ify type) is there a way to then define a defmethod that will accept any of a list of types? or do I defmethod for each type?

20:41 mmarczyk: (map #(defmethod clj-ify % [_] :foo) [String Integer])

20:41 also, how about calling it clojurify? :-)

20:42 (just checked that map at the repl -- seems to work; perhaps it would be best to wrap it in a dorun, though)

20:42 Blkt: sounds like a World of Warcraft spell

20:43 mmarczyk: it *is* a World of Warcraft spell! cast clojurify on your sword and it becomes imbued with a spirit, which you can programme in Clojure

20:43 Blkt: Perl monk style?

20:43 casting spells with Clojure

20:43 omg

20:43 mmarczyk: :-)

20:44 livingston: yeah, I'm not sure that's worth doing .. it's just one liners, I'll think about it though if I get annoyed with this though

20:44 Blkt: (is it forbidden here to to use acronyms?)

20:44 mmarczyk: livingston: the proper way would probably be to derive a new relationship

20:44 from the types to, say, ::MyGroupOfTypes

20:44 and than use that as the dispatch value

20:46 livingston: yes I could isa them together... might do that

20:46 mmarczyk: (Blkt: forbidding acronyms!? doesn't that get one lynched in the IT community?)

20:47 livingston: that buys you one more thing, namely you only have the one implementation of the multimethod

20:48 if you change that, the change will work for all the types involved

20:48 and there's always underive to kick out a type from the club

20:51 livingston: yeah I think I will create a pseudo class for this

20:52 it's kinda cool, in java there are like 10 classes but they all implement the same 3 functions, and clojure doesn't care when it comes time to call those 3 functions what it's being passed, it'll find the right thing

20:52 so I can treat the 10 or whatever things as if they are the same

20:56 mmarczyk: :-)

21:02 * slyphon hates on jndi

21:05 slyphon: man, i just suck at recursion

21:09 livingston: where there are multiple java methods with call signatures that maybe could be ambiguous to clojure, how can I make sure the right one is being called

21:10 e.g. this method has signatures Object Object Object Object and boolean Object Object Object and I think it may be calling the first instead of the second is there anyway to verify / force it

21:10 slyphon: i would imagine reflection is one way

21:10 somnium: livingston: you can use type hints

21:11 slyphon: yeah, that'd probably be easier

21:11 Boolean/TRUE

21:11 mmarczyk: (boolean first-argument) instead of first-argument

21:12 ,(boolean 1)

21:12 clojurebot: true

21:12 mmarczyk: ,(boolean true)

21:12 clojurebot: true

21:12 slyphon: ,(boolean 0)

21:12 clojurebot: true

21:12 slyphon: hah!

21:12 suck it, C!

21:12 livingston: somnium: could you give me an example I tried (.method obj #^boolean true ... and it says Metadata can only be applied to IMetas

21:12 mmarczyk: yeah

21:12 chouser: that's not a type hint, but might help at runtime

21:12 mmarczyk: livingston: use (boolean true)

21:13 slyphon: really? there's nothing built-in that converts an Enumeration to a seq?

21:13 chouser: (doc enumeration-seq)

21:13 clojurebot: "([e]); Returns a seq on a java.util.Enumeration"

21:13 slyphon: oh ffs

21:13 really?

21:13 chouser: :-)

21:13 * slyphon goes and sits in the corner

21:13 mmarczyk: also see

21:13 (doc iterator-seq)

21:13 clojurebot: "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly."

21:15 slyphon: ok, i need some functional-fu here, i want to walk a NamingContext and print out, recursively, the tree

21:15 livingston: hmmm... ok looks like I have yet more problems then oh but wait, (boolean true) gives me a big-B Boolean

21:15 slyphon: for some reason this is stumping the hell out of me

21:15 livingston: the call signature seems to want an little-b boolean

21:15 mmarczyk: (doc tree-seq

21:15 clojurebot: EOF while reading

21:15 mmarczyk: (doc tree-seq)

21:15 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

21:15 livingston: (at least that's what show is telling me)

21:15 slyphon: hrm

21:16 mmarczyk: also see clojure.zip

21:16 slyphon: see, now you guys are just makin me feel dumb

21:16 :)

21:16 mmarczyk: livingston: when you pass (boolean true) to a method which expects a primitive Boolean

21:16 it gets a primitive Boolean

21:16 but when you do (class (boolean true))

21:16 slyphon: mmarczyk: thanks

21:17 mmarczyk: then that (boolean true) gets boxed before being passed to the class function

21:17 livingston: yeah but there is also a method signature for that slot being an Object

21:17 and I think that instance of the method then becomes preferred

21:17 mmarczyk: livingston: I don't think so

21:17 livingston: (or at least that's what I'm trying to figure out - not my library)

21:18 mmarczyk: in fact

21:18 http://stackoverflow.com/questions/2722856/how-do-i-call-overloaded-java-methods-in-clojure

21:18 sexpbot: "How do I call overloaded Java methods in Clojure. - Stack Overflow"

21:21 anair_84: how do i do an import *

21:21 in clojure

21:22 Raynes: You can't import all the classes from a package.

21:22 anair_84: :(

21:22 livingston: I'm reasonably confident because it's producing a Boolean instead of a boolean it's calling the the method with the Object signature and not the one with the boolean (little b) signature

21:22 anair_84: Raynes: any thing close ?

21:22 can i list all classes in package and then import those ?

21:22 Raynes: You can do (:import [java.package Class1 Class2 Class3])

21:24 It's better to be explicit, even if it does require quite a bit of typing. Others don't have to guess where a class that you use comes from, and you always know which classes you have imported.

21:24 At least, I assume that's the rationale for not being able to do what you want.

21:24 Anyone, correct me if I'm wrong. :)

21:24 anair_84: Raynes: yeah i understad the reasoning but in the repl importing explictly can be painful

21:25 extremely painful

21:25 Raynes: :\

21:27 mmarczyk: livingston: have you visited that SO link?

21:27 there is an example of a method overloaded on int vs. Object being called with 10 first, then with (int 10)

21:28 livingston: yes I looked

21:28 mmarczyk: right

21:28 livingston: I don't know - I'm just saying what I think I'm seeing on my machine

21:29 mmarczyk: that's consistent with everything else I've read on the issue

21:30 livingston: it's not my library so I can't get in there and muck with it and know for sure, but it's giving me an error that's consistent with it trying to do some object like stuff to my poor Boolean

21:30 slyphon: get a Method object through reflection and call it explicitly?

21:30 livingston: I have some workarounds for now, I think

21:30 slyphon: i think wall-hack will let you list the explicit signature

21:31 mmarczyk: (inc slyphon)

21:31 slyphon: :)

21:32 mmarczyk: hope it feels good to be incremented ;-)

21:32 slyphon: indeed :D

21:32 i'm one more now!

21:32 mmarczyk: yeah; in time, one can grow by a thousand!

21:32 slyphon: hahaha

21:36 livingston: if I have the instance of a java object how do I get the member field foo (not the method foo, but a member variable?)

21:36 chouser: (.foo obj), and hope there's not also a method of no args named foo

21:37 livingston: no... but that's just great, it's not set

21:38 thanks

21:41 chouser: livingston: http://gist.github.com/381625

21:42 slyphon: when you call a variadic method in java, do you have to terminate the array you pass in with a nil?

21:43 livingston: chouser: cool thanks for checking that. just for the sake of argument can you change that to be 4 objects and 1 boolean and 3 objects.

21:43 I'm sure it won't matter but that's the situation I'm in

21:44 actually there's like 10 methods signatures with excruciatingly minor variations (I hate this api already)

21:46 rhudson: chouser: lines 11-16 in that gist disturb me. Do you know why it behaves that way?

21:46 hiredman: slyphon: uh, no

21:47 * slyphon forgets where he saw that

21:47 livingston: rhudson: why? those lines seem fine?

21:48 rhudson: line 13 in particular

21:49 livingston: 13 is output? 11 creates an instance and sets it to u and 12 calls a method on that instance

21:50 rhudson: Right. It seems like u being dynamically typed in 12 is losing the conversion of the argumen to a primitive type.

21:50 chouser: without a hint on the target, the clojure compiler can't generate a single method call and has to generate reflection code instead

21:51 rhudson: I think that's right.

21:51 rhudson: But in the process converting back to boolean

21:51 i mean Boolean -- missed the shift key

21:52 livingston: OH wait I read that wrong 11-13 are *exactly* my problem

21:53 it didn't work in those lines

21:53 mmarczyk: ohhh

21:53 that's good to know

21:54 would (.foo (cast mypkg.Ugly u) (boolean true)) work?

21:54 chouser: mmarczyk: no

21:55 you need a type hint

21:55 livingston: and line 15 is the fix

21:55 wow that's ugly

21:55 mmarczyk: ok, thanks

21:56 chouser: you can hint u

21:56 livingston: that's really unfortuante, so it's because it's using reflection to figure it out? and it's doing so at compile time?

21:56 mmarczyk: chouser: would you care to add this to this SO question: http://stackoverflow.com/questions/2722856/how-do-i-call-overloaded-java-methods-in-clojure ?

21:56 sexpbot: "How do I call overloaded Java methods in Clojure. - Stack Overflow"

21:56 chouser: (def #^mypkg.Ugly u (mypkg.Ugly.))

21:57 livingston: not quite

21:58 livingston: yeah I seem to be back to rhudson 's question because yeah, that certainly doesn't seem right

21:58 slyphon: wow, java, you complete me

21:58 livingston: or at least doesn't seem like something that should confuse clojure

21:59 chouser: at compile time when it can't figure out exactly one correct method to call, it generates code to do reflection at runtime, and by then it seems to have lost track of the fact that the arg is a primitive.

22:00 mmarczyk: chouser: that's if you do SO, of course, otherwise I could post a link to your gist myself -- seems directly relevant to that question

22:02 livingston: why doesn't it know that the arg is primitive? - i mean it makes sense that it didn't know, that was my problem BUT ... even with the type hint that only tells it the class the method is attached to not the method signature which still must wait until runtime I would think?

22:03 mmarczyk: that would make sense if you could compile the code without having the class on your classpath

22:03 slyphon: or, you could be explicit and use wall-hack-method...?

22:03 livingston: it seems like if it can compute any method signatures at all, it should be able to get past this particular problem without much trouble at all?

22:03 slyphon: and Boolean/TYPE

22:04 wrapped in a parital...?

22:04 hiredman: livingston: the method signature definitely does not have to wait until runtime

22:04 mmarczyk: livingston: well actually this isn't at all different from what happens when you compile Java code

22:04 chouser: mmarczyk: eh, go ahead.

22:05 I started an answer, but I should be doing other things.

22:06 mmarczyk: chouser: if it's a certain book you have in mind, I'm definitely interested in removing any distractions you might face :-)

22:07 livingston: hiredman: it doesn't have to, but it sometimes it must right? if it doesn't know and and has to dispatch

22:07 rhudson: At this point I'd be tempted to wrap the pesky overloaded methods, in Java or Clojure, give them distinct names (f-yes-I-mean-the-one-with-little-b-boolean-first-arg-dammit) & use those

22:08 hiredman: livingston: what do you want?

22:08 livingston: mmarczyk: I suspect not, but one of the most unattractive things about java is how about 50% of your code is type information (hell even Ada wasn't that bad)

22:09 pdk: couldve been haskell :p

22:09 livingston: hiredman: I'm just confused as to how this is confusing to the compiler

22:09 mmarczyk: livingston: well that (.foo ^TypeHint stuff more-stuff) business hardly seems to suffer from this problem

22:09 it's just one hint, you know :-)

22:11 livingston: if the compiler can't figure it out at compile time and has to generate some reflection code to dispatch at run time, and it gets the arguments bool I would expect it to quite easily call the bool one, I mean why should that change if it knows the base class or not?

22:11 that's what's weird about this

22:12 chouser: it's actually already some pretty gnarly code. dynamic method invocation on the jvm is a bit of a mess.

22:13 But I'm only suggesting why it doesn't, not that it couldn't or shouldn't handle this.

22:15 livingston: so is this just a limitation of the clj compiler? or of the jvm or something else in general?

22:15 mmarczyk: does the unhinted code generate a reflection warning?

22:17 livingston: mmarczyk: it just breaks at runtime (from what I can tell) at the repl - I didn't try compiling it any other way

22:17 rhudson: ,*warn-on-reflection*

22:17 clojurebot: false

22:17 rhudson: (doc *warn-on-reflection*)

22:17 clojurebot: "; When set to true, the compiler will emit warnings when reflection is needed to resolve Java method calls or field accesses. Defaults to false."

22:17 defn: for someone with very limited java experience is reading effective java worth the time, or should i start with a more introductory text first?

22:17 chouser: mmarczyk: yes, you get reflection warnings

22:18 defn: ,(set! *warn-on-reflection* true)

22:18 clojurebot: java.lang.IllegalStateException: Can't change/establish root binding of: *warn-on-reflection* with set

22:20 mmarczyk: ok, thanks

22:20 in that case it's fairly easy to catch

22:21 I'd expect the compiler to become more sophisticated when it transitions to Clojure, no?

22:21 chouser: it will certainly become less painful to change.

22:21 mmarczyk: should be more pleasant adding stuff in Clojure than in Java

22:24 ok, posted that SO answer, hope it's accurate

22:27 rhudson: defn: I'd say start with something else besides Effective Java. (I think the best way to write effective Java is to write Clojure :) )

22:27 chouser: ok, it looks like when it generates reflection code, it just stuffs the args into an array (Object[]), and that's all it uses to find the correct method at runtime.

22:29 livingston: this is the clojure compiler? so it just gets the class'es then and the big-B Boolean wins as an Object?

22:30 OH wait I see so it need to use reflection when it doesn't know the object's type, BUT when it does it just hands it off to the jvm for normal dispatch?

22:31 chouser: http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#LID1278

22:32 no, not quite.

22:33 if it knows the type of the target and the types of enough of the args *at compile time* (which it does by using reflection at compile time), then it generates a normal java method call which at runtime is handled by the normal jvm dispatch stuff.

22:34 defn: rhudson: any recommendations?

22:34 rhudson: i dont wanna learn java so much as i want to learn enough java to use it properly in clojure

22:35 livingston: I hate the API that lead me to this even more now ... for one class they have .getNameSpace and another is .getNamespace - so I can't just use one simple clojure function that doesn't care which class it gets - blech

22:35 chouser: ok that's starting to make sense

22:35 chouser: if it doesn't know enough at compile time, it stuffs the args into an Object[] and generates code that at runtime will do reflection to find the right method and call it via refleciton

22:35 defn: livingston: i think you can do that with a multimethod

22:36 livingston: are you talking about inheritance?

22:36 rhudson: The intro stuff in Java in a Nutshell is pretty good, then you have a good reference to the standard library as well

22:36 livingston: chouser: ok that also makes sense

22:36 defn: rhudson: cool! thanks

22:36 chouser: but since all its got is an Object[], primitives have gotten autoboxed and so the Object,Object,Object signature matches

22:36 livingston: defn: I know i can but it'd be nice not to have to

22:37 chouser: ok good, at least this is telling a sane story as to why this works this way

22:38 defn: livingston: idk, i think the control over polymorphism is pretty cool -- i like having that fine grain control

22:38 id almost prefer clojure *not* do that for me

22:40 slyphon: defn: it's easy to make it do "dumb polymorphism" too, just dispatch off the class or (obj :type) of the first arg

22:41 livingston: chouser: this is odd though, because getParameterTypes must return something where primitives are discernible? because clojure.contrib.repl-utils/show knows the difference between big-B and little-b boolean

22:41 slyphon: i remember that kind of blew my mind the first time i played around with CLOS

22:41 livingston: (unless it's just calling toString or something)

22:43 mmarczyk: livingston: sure, but if the compiler postpones reflection until runtime and then at runtime all you've got is Object[], then the fact that reflection could find a (boolean, Object, Object) method is irrelevant by that point

22:43 you'd have to not stuff everything into Object[], basically

22:44 incidentally, the new ^foo syntax for reader meta data is Really Pretty :-)

22:44 chouser: right. or include flags indicating which args were primitives and should unboxed again.

22:44 livingston: or route it through the regular dispatch code?

22:45 couldn't you just scan for things that could be primitive?

22:45 chouser: livingston: The jvm doesn't have "regular dispatch code" that's dynamic

22:45 you have to name a specific method of a specific class or interface at compile time

22:46 livingston: although that presumes it's illegal to have a Boolean and a different little-b boolean - because you couldn't tell between those...

22:46 chouser: I meant the clojure dispatch code, basically dynamically build a multi-method

22:46 mmarczyk: http://blogs.sun.com/jrose/entry/dynamic_invocation_in_the_vm

22:46 sexpbot: "dynamic invocation in the VM - John Rose @ Sun"

22:47 mmarczyk: I am under the impression that invokedynamic will make all of this easier

22:47 is this correct?

22:47 livingston: interesting

22:48 well there's still a problem though if you can have two signatures one with a little b and one big B because you won't know to unbox or not, right?

22:49 chouser: livingston: that's why I was suggesting a separate set of info about which args were primitives before being stuffing into the Objectp[

22:49 Object[]

22:49 dnolen: is contrib being continuously rebuilt as well?

22:49 that is, how can I get the latest in my lein project?

22:50 mmarczyk: clojure-contrib-1.2.0-SNAPSHOT

22:50 I believe

22:50 livingston: chouser: yeah, I think that is the right thing. clojure could do that today and get around this problem

22:50 dnolen: mmarczyk: is that coming from hudson as well?

22:50 mmarczyk: it is, afaik

22:50 I mean it must be, since there's no c-c in maven central or clojars to the best of my knowledge

22:51 dnolen: i see, somewhat confusing the lack of master in the name when clojure has it.

22:51 mmarczyk: true

22:51 chouser: livingston: I pasted a link to the code. feel free to write a patch and try to get it in.

22:51 :-)

22:52 mmarczyk: the last c-c build is from ~7 hrs ago

22:52 livingston: although I'm still a bit confused, why there isn't a simpler solution? since somewhere somehow with an array of objects show is able to show me the difference between a Boolean and a boolean

22:52 chouser: I suspect rhickey won't want this kind of change so close to 1.2 release, but I could be wrong.

22:52 mmarczyk: livingston: I'm not sure what you mean

22:52 livingston: http://github.com/richhickey/clojure-contrib/blob/4f9a78d13217a8de4c29221d74aca0a67cec8c1a/src/main/clojure/clojure/contrib/repl_utils.clj#L59

22:52 mmarczyk: i.e. what use of show you have in mind

22:52 chouser: livingston: there's two different things that have to be matched up. Clojure's got to find the declared method that matches the actual args.

22:53 livingston: right

22:53 mmarczyk: yeah, I use show all the time, but that's at the REPL to find out what methods a class has

22:53 chouser: 'show' and the Clojure compiler and the Clojure runtime reflection code all have no problem finding which declared methods have primitive args.

22:53 mmarczyk: which has nothing to do with matching the correct method with a given set of arguments

22:53 chouser: the problem is knowning what the actual args being passed in are.

22:54 livingston: right and show can tell me the difference between little and big B, but I'm looking at the code and they seem to use an array of objects, which suggests there's a way to pass the little b boolean around without losing it's type...

22:54 chouser: Once the actual args have been put in an Object[], clojure.lang.Reflector/invokeInstanceMethod looks at the type of each actual object there to see if it can find a matching declared method

22:55 livingston: oh wait I see where I went wrong, the object coming out of getParameters aren't objects, duh

22:55 they're something else Parameters or something (probably)

22:56 no yeah I get it - I was just over generalizing or something about how show worked

22:56 blech

22:57 yeah your vector of what was / wasn't boxed is good, also meta type hints on the parameters themselves to suggest a call signature to force it would be fine too

22:58 I would have liked (.foo (mypkg.Ugly.) #^boolean true)

22:58 but your can't type hint there currently

22:59 although, the auto un/re boxing should really fix this up (that's something I like about lisps, is not having to crud up my code with types)

23:01 mmarczyk: livingston: actually (boolean true) does ensure that the true is unboxed -- and it will be used unboxed if non-reflective code can be generated

23:02 so the key hint becomes the one on the object you're calling the method on

23:03 livingston: although one would think the literal true would be sufficient for that

23:03 mmarczyk: hm? why would you think that?

23:03 chouser: all literals in Clojure are currently boxed

23:03 slyphon: wah-wah

23:03 mmarczyk: with both little-b and Big-B Booleans around

23:04 incidentally, having both little-b and Big-B Booleans seems crazy to me

23:04 livingston: well the first problem is that booleans and other types need two forms

23:04 mmarczyk: I'm not saying it doesn't make sense

23:04 chouser: ,(expression-info true)

23:04 clojurebot: {:class java.lang.Boolean, :primitive? false}

23:04 chouser: ,(expression-info 5)

23:04 clojurebot: {:class java.lang.Integer, :primitive? false}

23:04 chouser: ,(expression-info (long 5))

23:04 clojurebot: {:class java.lang.Long, :primitive? false}

23:04 chouser: heh

23:04 mmarczyk: I'm perfectly prepared to believe that it makes sense in a very deep way due to performance considerations or whatever

23:04 or just history

23:04 chouser: ,(expression-info '(long 5))

23:04 clojurebot: {:class long, :primitive? true}

23:04 mmarczyk: but it makes it no less crazy

23:04 livingston: the second is even needing boolean at all, common lisp has gotten along just fine with nil being false and everything else is true

23:05 mmarczyk: why expect straightforward literal behaviour in this situation :-)

23:05 livingston: the Java world is doing reasonably well despite the ridiculous decision to have a separate notion of Booleans ;-)

23:05 livingston: all this boxing only makes sense when you live in the Kingdom of Nouns

23:05 slyphon: hah

23:06 mmarczyk: incidentally, coming from Scheme, I still find it somewhat surprising that we have two false objects :-)

23:06 or should I say falsey

23:06 slyphon: it makes sense when your design has made tradeoffs for performance reasons

23:06 mmarczyk: coming from ruby it's very natural

23:07 mmarczyk: although, i must say, i'm very happy that '{} and nil aren't equivalent

23:07 er '()

23:07 mmarczyk: slyphon: I'm actually trying to learn a bit of Ruby now

23:07 slyphon: mmarczyk: ruby is fun

23:07 mmarczyk: slyphon: just because so many Clojurians seem to have strong Ruby backgrounds

23:07 slyphon: :)

23:07 livingston: the only reason there's a performance issue is that java decided that everything needed to be objects and that numbers et. al can't play where everything else is allowed to play without a big brother object to hold it's hand

23:07 mmarczyk: makes me curious :-)

23:07 slyphon: yeah, i've been a ruby developer for about 4 years

23:07 mmarczyk: but it does look *really weird* to me :-)

23:07 slyphon: (primarily)

23:08 hahahaha

23:08 dnolen: livingston: that's not the problem at all, IMO. fns should accept and return anything, that means boxing.

23:08 the only time you don't want that behavior is truly performance critical code.

23:09 mmarczyk: livingston: if you're proposing to have a Java-bashing session, I'm at one with that :-)

23:09 livingston: mmarczyk: no I do that enough at work (we're a java shop)

23:10 mmarczyk: livingston: yeah, I guess your Java must be thouroughly bashed then

23:10 that must be some really atrocious api you're trying to use, btw

23:10 livingston: dnolen: only if you assume that an object is somehow different from a number - common lisp doesn't have this issue, it has a type hierarchy with numbers in it - things work just fine

23:11 mmarczyk: somehow the .getNamespace vs. .getNameSpace thing really gets to me

23:11 livingston: mmarczyk: it's Jena and AllegroGraph's bastardization of Jena

23:11 mmarczyk: filed under "try not to need to use"

23:11 slyphon: livingston: it's different when you're referring to an Object and when you're referring to a location in memory

23:12 livingston: it makes me want to gouge my eyeballs out that it takes about 4-9 method calls (and a lot of objects) to do the equivalent of '(ex/a rdf/type ex/b)

23:12 I'm working on that though

23:14 livingston_: awesome - web client died

23:15 not sure what I missed but I was going to say:

23:15 slyphon: livingston_: what client are you using?

23:15 livingston_: I don't have to worry about when I call this method I get Triples back but when I call that one I get Statements back they are exactly the same, except completely different

23:15 http://webchat.freenode.net/

23:15 sexpbot: "freenode Web IRC (qwebirc)"

23:15 slyphon: oh, nice

23:15 livingston_: port 6667 is blocked here

23:15 * slyphon nods

23:15 slyphon: my buddy has the same situation

23:15 "hackers use irc"

23:16 (schmucks)

23:17 livingston_: I wonder if I'm still here

23:17 rhudson: yep

23:17 livingston: (it just told me I timed out so I was confused - that was the old client I guess)

23:18 defn: slyphon: are you ming slyphon?

23:19 slyphon: defn: hahahahaha

23:19 defn: i haven't heard that in ages

23:19 mmarczyk: "hackers use irc and we *certainly don't* want to employ hackers, do we"

23:19 defn: slyphon: im not even sure why it's funny! i just realized i have you on my google talk contact list

23:19 mmarczyk: makes perfect sense for an it shop

23:20 slyphon: defn: orly!?

23:20 defn: slyphon: we talked in ruby-lang ages ago

23:20 slyphon: defn: ahhh

23:20 defn: i used to go by mingus also

23:20 in #twisted

23:20 defn: ahhh

23:20 a fan of charles?

23:20 slyphon: indeed!

23:21 livingston: 99% of the people here don't program - so it doesn't kinda make sense and a good preventative measure against worms - I can't say I don't understand why

23:21 slyphon: unless someone decides to run their CNC server on port, say, 6668

23:21 or 80

23:21 or 53 :D

23:21 * slyphon 's buddy used to run openvpn on 53 to get through firewalls

23:22 slyphon: EVIL

23:22 dnolen: livingston: I see, I suppose that's what rhickey means when he says breaking with Lisp tradition. I do note that that even Common Lisp requires you to declare types in fns that use them. Clojure's deftype does avoid that. always tradeoffs I suppose.

23:22 livingston: I haven't checked but my guess is that everything that isn't http or ssh related is blocked - even skype's blocked

23:22 slyphon: woah, skype is hard to block

23:23 they go out port 80 if necessary

23:23 livingston: dnolen: you don't have to put types in function signatures in CL

23:23 slyphon: is deftype in 1.2?

23:23 livingston: you do if you want to dispatch but then...

23:23 dnolen: not in signatures, but inside the fn to hint the compiler no?

23:24 livingston: some CL compilers will generate unsafe code with type info and (speed 3) (safety 0) set

23:24 dnolen: like SBCL i imagine.

23:25 livingston: dnolen: no no types unless you need the compiler to be more efficient (rare) - in fact it's genearally advisable to avoid them - then you can reuse and maintain code easier

23:25 ditto with clojure

23:28 dnolen: livingston: but that's more of an issue with CL, with so many compilers with different capabilities. In Clojure I only ever want type hints on arithmetic.

23:30 livingston: dnolen: it's the same thing - only hint when a bottleneck is found otherwise don't worry about it and don't waste your time - that's what the profiler is for

23:32 dnolen: livingston: except un-type hinted arithmetic is dog slow. I've seen it enough times first hand (doing graphics stuff) that I never want to do arithmetic with boxed numbers.

23:33 you also never want to add non-binary arithmetic. the slowness is horrifying

23:33 livingston: ,(+ 3 4 5 )

23:33 clojurebot: 12

23:33 dnolen: that won't be inlined

23:34 mmarczyk: ,(+ (+ (int 3) (int 4)) (int 5))

23:34 clojurebot: 12

23:34 mmarczyk: oh, but so ugly

23:34 ,(unchecked-add (unchecked-add (int 3) (int 4)) (int 5))

23:34 clojurebot: 12

23:34 dnolen: that's what macros are for

23:34 livingston: How do you know what + creates?

23:34 mmarczyk: oh, but even more ugly

23:34 hiredman: there is some possibility that the reduce protocol stuff will make reducing over an array of ints the fastest way to add

23:34 mmarczyk: true

23:35 dnolen: (prim float (+ 1 2 3 4 5 6 7 8 9 10))

23:35 is one macro I wrote to do the right thing

23:35 mmarczyk: hiredman: oh, that's a cool idea

23:35 livingston: most functions like that have multiple dispatch for 1 2 3 and many parameters to optimize for the common cases

23:35 mikem: ~def int

23:36 slyphon: chouser: where do inline functions live?

23:36 hiredman: + has one inline, which calls the binary add in Numbers

23:36 ,(:inline (meta #'+))

23:36 clojurebot: #<core$_PLUS___4516 clojure.core$_PLUS___4516@183ccdb>

23:36 hiredman: ,(:inline-arities (meta #'+))

23:36 clojurebot: #{2}

23:36 livingston: I don't do enough math in code where it's ever been the case that I could get significant speed by altering my numbers my run-time goes to other things

23:37 slyphon: wow, ok

23:37 dnolen: livingston: as rhickey has said, if Clojure get's unboxed arithmetic everybody's code is going to get way faster, not just math code.

23:37 billions of operations per second, instead of tens of millions

23:38 slyphon: dnolen: pfft, how often do computers have to "add things"?

23:38 c'mon

23:38 dnolen: slyphon: heh, a good joke if you meant it :D

23:39 slyphon: :D

23:39 * slyphon needs to work on his EybrowsOverIP protocol

23:39 slyphon: eyebrows, even

23:39 mmarczyk: well now

23:39 livingston: in my world not that often only for bookkeeping (like how long did this take) - I do symbolic AI - it's all lists and symbols

23:40 mmarczyk: chouser: livingston: it appears that locals don't need type hints

23:40 http://gist.github.com/381686

23:41 when their type can be inferred, that is

23:42 (let [t u] ...) would still use the Object method

23:42 livingston: mmarczyk: wait what how the hell is that possible?

23:42 right ok

23:43 presumably code that wasn't the constructor in that let would also wreck some havoc

23:43 mmarczyk: (.foo (foo.TestInterop2.) true) uses the bool method too

23:43 so apparently the compiler checks whether it's actually just emitted the code to construct the object in question (in which case it knows all about it)

23:43 in addition to using type hints

23:48 livingston: well this has been fun everyone

23:48 mmarczyk: right

23:48 one more thing

23:48 (see my gist)

23:48 livingston: I'm going to go get some food and cuss about Triples not be the same as Statements

23:48 mmarczyk: you can also type-hint a Var

23:48 then wherever you use this Var

23:48 livingston: *looking

23:48 mmarczyk: the type hint will be taken into account

23:49 from what I gathered from experimenting at the repl, anyway

23:50 livingston: oh huh

23:50 most of my things are coming out of maps, but there might be a way to hint those too

23:51 but like i said, things are a little fluid now so I'd like to avoid having to lock things down too soon

23:51 mmarczyk: sure

23:51 livingston: thanks again everyone

Logging service provided by n01se.net