#clojure log - Mar 06 2009

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

0:12 Drakeson: what is elisp's mapconcat or python's join called in clojure?

0:14 hiredman: ,(doc mapcat)

0:14 clojurebot: "([f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection."

0:14 Drakeson: I want (join ", " ["a" "b" "c"]) -> "a, b, c"

0:15 ,(doc join)

0:15 clojurebot: java.lang.Exception: Unable to resolve var: join in this context

0:15 Drakeson: ,(doc string-join)

0:15 clojurebot: java.lang.Exception: Unable to resolve var: string-join in this context

0:15 arohner: there's a str-join in c.c.str-utils

0:16 Drakeson: arohner: oh, thanks. why is it in contrib? :(

0:16 arohner: ,(doc clojure.contrib.str-utils/str-join)

0:16 clojurebot: "([separator sequence]); Returns a string of all elements in 'sequence', separated by 'separator'. Like Perl's 'join'."

0:17 arohner: Drakeson: the simple but snarky answer is that it's there because it isn't in core

0:17 clojure is still young

0:19 Raynes: Is there a certain convention for writing functions like so (defn afunction ([] ..))

0:20 I tend to do it when the function contains documentation.

0:20 hiredman: that is for mult-arity functions

0:21 ~def max

0:21 like that

0:21 unless your function multi-arity like that, please don't write your functions that way

0:22 Raynes: Thanks ^_^

0:23 Drakeson: ,(filter 'identity [nil true])

0:23 clojurebot: ()

0:23 Drakeson: why?!

0:24 hiredman: ,(filter identity [nil true])

0:24 clojurebot: (true)

0:24 hiredman: 'identity is a symbol

0:25 Drakeson: habits ...

0:25 hiredman: identity is also a symbol that is resolved to a var that points to a function

0:25 Drakeson: hiredman: I know :)

0:26 hiredman: symbols can be called like funtions for hash look ups and the like

0:26 ,('identity {'identity 1})

0:26 clojurebot: 1

0:28 Drakeson: hiredman: thanks, My fingers tend to put a quote in those places to fill the common-lisp void!

0:29 replaca: Drakeson: I make the same mistake with identity all the time!

0:30 * Drakeson goes to grep for "'identity" in many files ...

0:40 Raynes: Could someone show me an example using comp?

0:44 hiredman: ,(map (comp inc first) (replicate 3 (range 3)))

0:44 clojurebot: (1 1 1)

0:44 Raynes: Thanks.

0:55 mrk1: In my slime repl, (read), (read-line) doesn't repond. is this normal?

1:29 durka42: wait, so are streams back under consideration?

1:31 slashus2: They look very interesting.

1:32 durka42: Why did they go out of consideration?

1:32 durka42: i was under the impression rich had banged on them for a while, thought they were kind of ugly, and went for full laziness instead

1:33 slashus2: Why not have both

1:33 ?

1:33 durka42: well, right

1:33 i guess they came back

1:34 slashus2: Looking at the examples, I wonder if some of the core functions will be rewritten with streams?

1:34 I guess it just shows that they can be.

1:35 lisppaste8: Rayne@acidrayne.net pasted "key value text reader" at http://paste.lisp.org/display/76568

1:35 hiredman: well, streams and seqs are a different abstraction

1:35 Raynes: Damn that bots fast.

1:35 It printed that before I even hit enter O_O

1:35 slashus2: I guess causality didn't apply?

1:36 durka42: it seems really fast because it posts to the channel before serving you the page

1:37 Raynes: durka42: Yeah, I noticed. O.O

1:38 durka42: Raynes: does what you posted work?

1:38 Raynes: Yes.

1:38 Surprisingly.

1:39 durka42: (well, on windows)

1:39 Raynes: Windows specific at the moment yes.

1:40 durka42: oh -- your config lines are specified as "foo = bar" not "foo=bar"

1:41 Raynes: Yup.

1:41 "foo=bar" was too easy.

1:42 durka42: heh

1:43 hmm monads for clojure programmers http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/

1:43 maybe i'll understand this one

1:43 Raynes: Oh cool.

1:43 hiredman: hot

1:43 * Raynes bookmarks to read later.

1:43 hiredman: onclojure, someone has set their sites high

1:43 Raynes: I need to go to sleep, but I want to read this.

1:43 :|

1:44 Meh, it will only take a minute.

1:45 * durka42 says the same thing and makes the opposite choice

1:49 Raynes: I only read half of it, too sleepy to comprehend it. Me go sleepy.

1:49 Also durka42: Thanks for not insulting my shitty code :) I know you were thinking it.

1:49 * Raynes goes to sleep.

2:20 dcnstrct: is there a way to check your classpath from the REPL ?

2:22 ayrnieu: ,(System/getProperty "java.class.path")

2:22 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission java.class.path read)

2:22 dcnstrct: thnx

3:22 xristos: i'm trying to setup swank-clojure but nothing seems work here

3:22 can anyone post his .el

3:54 AWizzArd: clojurebot: max people

3:54 clojurebot: max people is 156

3:54 AWizzArd: aha, new record :)

3:57 hiredman: I was begining to think it wasn't working correctly

4:09 AWizzArd: seems to work

4:15 Moin kotarak

4:15 kotarak: moin moin

4:16 AWizzArd: Alles Roger oder was? ;)

4:52 leafw: I just translated the nice make-a-derivative-fn-from-a-fn example, see http://pacific.mpi-cbg.de/wiki/index.php/Clojure_Scripting#Creating_a_derivative_of_a_function

4:57 AWizzArd: gut

5:59 aseeon: Could you recommend be a good editor/ide to write Clojure code in (i am not the vim kind of guy)?

6:01 kotarak: aseeon: geez. As maintainer of the vim mode, I would have recommended that... ;) There is a mode for emacs, enclojure for netbeans, clojure-dev for eclipse, waterfront (written in Clojure), a plugin for intelliJ ... pick one. :)

6:01 hoeck: aseeon: emacs :) (sorry, I'm an emacs guy)

6:10 AWizzArd: aseeon: you can try Enclojure: http://enclojure.org/

6:10 if you are used to modern looking IDEs then this would probably your best bet.

6:10 aseeon: AWizzArd: looks very promising

6:10 AWizzArd: absolutely

6:11 aseeon: yeah i am, Komodo Edit, Netbeans and Eclipse are my tools of the trade :D

6:11 AWizzArd: then you pretty much will need Enclojure, as this is a plugin for NetBeans.

6:12 I myself still use mostly Emacs, because I have a long Lisp background. But I closely look at Enclojure every time it gets updated. Soon it will be there where Emacs is.

6:13 aseeon: thanks kotarak and AWizzArd for telling me about enclojure, i will give it a spin :)

6:13 and hopefully will be back here ^_^

7:23 Hooke: hello

7:24 AWizzArd: Hi Hooke

7:25 Hooke: hello, AWizzArd, how are you

7:26 AWizzArd: fine thx, hope you too

8:38 jayfields: (doc compare)

8:38 clojurebot: Comparator. Returns 0 if x equals y, -1 if x is logically 'less than' y, else 1. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable; arglists ([x y])

9:42 candera: I'm sure this is a FAQ, but I've been unable to find the answer so far: I'm getting a ClassNotFoundException when trying to compile a lib. It's choking on :extends [javax.swing.JApplet] in my namespace's :genclass clause.

9:43 shoover: candera: try it without the []?

9:44 cemerick: candera: yeah, classes can have only one superclass -- can implement multiple interfaces, tho

9:45 candera: Yep, that worked. Thanks!

9:45 On to the next problem! :)

9:55 cgray: hi, I'm having trouble with require... I would like to name my files like foo-bar.clj , but when I do (require 'foo-bar) I get an error that there is no foo_bar.clj

9:56 Chouser: cgray: I would like to name my files like foo-bar.clj as well, but alas it doesn't work. You need to use foo_bar.clj

9:56 cgray: is there a good reason for that?

9:56 Chouser: well, it's a relatively good reason. :-)

9:57 'require' and 'use' deal in namespaces

9:57 Cark: i've been bitten by that too

9:57 cemerick: hrm, where oh where did cond-let go?

9:58 Cark: common lisp was more forgiving in that respect !

9:58 leafw: why do I never get cond right? Somehow, it is not intuitive to me how to lay down the expressions.

9:58 Chouser: namespace names map to java class names

9:59 Cark: and the file names must be the same as file names ?

9:59 Chouser: java doesn't allow - in identifiers because it would mean subtraction in their infix notation.

9:59 Cark: err class names

9:59 Chouser: therefore the jvm doesn't allow - either (though this could theoretically change)

9:59 cgray: Chouser: okay, thanks I see now

9:59 Cark: in java is it forbidden to have a file name different from the class name it contains ?

10:00 i thought this was introduced with aot compilation

10:00 Chouser: Cark: java uses the filename to find the definition of a given package/class, so it needs to match.

10:00 cemerick: ah-ha, tricky -- my favorite documentation browser helpfully includes contrib stuff, but I didn't notice the contrib annotation on cond-let

10:00 Cark: ok i see

10:01 Chouser: basically it comes down to simply having one rule that - in a clojure name maps to _ in a java name or file is a simple rule that avoids a lot possibly more complicated rules and issues.

10:02 cemerick: ah, I didn't know there was a cond-let anywhere. nice.

10:02 cemerick: Chouser: Unfortunately, it doesn't seem to work.

10:02 Chouser: leafw: surely cond is easier to get right than condp, though!

10:02 leafw: Chouser: the docs are so incomplete on cond.

10:03 also, no indication of the "default". What is it, :else ?

10:03 Chouser: leafw: any true expression will do. :else is the common idiom.

10:03 leafw: ok. Thanks Chouser

10:05 * rhickey still needs naming convention for stream functions

10:05 Chouser: I thought the trailing ~ was cute

10:05 minor adjustment to the reader, I think...

10:06 rhickey: major overloading of ~ though

10:07 Chouser: no more major than, for example, #

10:08 Holcxjo: ,(find-doc "cond")

10:08 clojurebot: java.lang.NoClassDefFoundError: clojure/lang/IteratorSeq$State

10:08 Holcxjo: Is that meant to be the result?

10:08 Sandboxing issue?

10:09 Cark: rhikey : i liked the prepended s in your examples ... looks like 'S'tream and also like a verb

10:09 rhickey: Chouser: not sure about that, we don't put # on front and back of names

10:09 Chouser: #'foo means something completely different than foo#

10:09 completely unrelated, even.

10:09 Cark: meaning : this stream maps the sequence with that function

10:10 rhickey: what about =map=, =filter=, e.g. the pipe metaphor?

10:10 Chouser: cemerick: cond-let seems to work for me. What kind of failure are you seeing?

10:10 rhickey: Cark: that was the intent there, just not sure it will work well for fnctions that normally end in s

10:10 Cark: just follow the english grammar

10:10 what function do you think of ?

10:11 Chouser: reductionss

10:11 thickey: there's already pmap, would smap be following that 'convention'? (though, i wish both cases would just use the full word, but i know most would hate that)

10:11 Cark: abusing special character seems ugly

10:11 cemerick: Chouser: huh. (cond-let [a 5] (pos? a) (+ a 9) :else 3) => java.lang.Exception: Unable to resolve symbol: a in this context

10:12 Chouser: cemerick: yeah, is bound to the result of (pos? a)

10:12 rhickey: another possibility is map-1, filter-1, for the once-only nature of their use

10:12 Chouser: cemerick: so it's not bound to anything when (pos? a) itself is evaluated.

10:13 Cark: rhickey : painfull on a belgian keyboard !

10:13 leafw: Cark: programming on anything than querty english is painful.

10:13 rhickey: Cark: how so?

10:13 Cark: leafw : true

10:14 gnuvince: french canadian is not bad imo

10:14 Cark: well the - is already bad, but we have to in lisp (it's right beside backspace), then 1 is using the shift key

10:14 Chouser: =map= isn't too bad. It feels a bit heavy by itself, but doesn't look to bad with parens around it.

10:14 Cark: how about map> ?

10:14 Chouser: would =map, =filter, etc. be acceptible, or is that too much like equality?

10:15 too bad

10:15 rhickey: <=map, <=filter ?

10:15 Cark: why does it have to go left ?

10:15 gnuvince: (|map f xs)?

10:16 Cark: |map looks like some reader macro

10:17 rhickey: <-map, <-filter

10:17 cemerick: Chouser: the docs evade me, but I found an example that Stephen posted on the group. What it does is very surprising to me -- I was very much expecting just a mash of let and cond

10:17 rhickey: <<map <<filter

10:17 Chouser: cemerick: you wanted a single extra let around the outside?

10:18 Cark: any of those would be nice rhikey

10:18 cemerick: Chouser: yeah. I figured it would produce (let [a 5] (cond (pos? a) ....))

10:18 Cark: << being the easiest

10:18 gnuvince: Has anyone considered putting them in a different namespace and just using stream/map, stream/filter?

10:19 rhickey: gnuvince: where will you put your stream functions?

10:19 Holcxjo: Or make it hard for everybody and use non-ASCII �map

10:19 cemerick: I guess I just turned into one of those people that never read anything :-P

10:19 Cark: hoclxjo : haha

10:19 gnuvince: rhickey: ?

10:20 Chouser: cemerick: well, the behavior it has is the one I have wanted, where I've got a couple different complex test expressions, and have to repeat them inside the return exprs.

10:20 rhickey: gnuvince: using a namespace only solves the problems for core

10:21 Chouser: separate namespace doesn't help. then any code that does it a lot ends up using s/filter s/map etc. :-(

10:21 gnuvince: Chouser: that's better IMO than an arbitrarily selected symbol that means "stream"

10:22 cemerick: Chouser: yeah, I can definitely see that being useful. When I see 'let', I think of a vector of pairs, though.

10:22 rhickey: gnuvince: but you can't put your streams functions in the stream namespace, so everyone will have to pick a different prefix namespace

10:22 thickey: i'm with gnuvince, all these quirky charachters before/after things doesn't mean anything

10:22 Chouser: cemerick: hm. I think that may be part of why it's not in core.

10:23 rhickey: gnuvince: a naming convention lets you put both stream and seq versions in same namespace, and everyone will know what to pre/append to get the stream version

10:23 cemerick: I'll third gnuvince, thickey on this.

10:24 rhickey: thickey: yeah, they never inherently mean anything, but this is one case where frequently you'll have (map ... (filter ...) and want to make it faster by just adding a character to each call

10:24 cemerick: why not s-map, s-filter, etc? I just cringe at seeing more line noise (in the aggregate).

10:24 or smap, sfilter as suggested before

10:24 Chouser: I think <<map is my favorite so far (if map~ is off the table)

10:24 gnuvince: rhickey: I am thinking of something like Data.ByteStream in Haskell where it is a convention for users of the module to qualify import it (import qualify Data.ByteString as B) because it shares many names with Data.List, Data.Set, Data.Map, etc.

10:24 rhickey: Chouser: nothings off the table at this point except non-ascii

10:24 thickey: rhickey: makes sense

10:26 danlarkin: I'm with gnuvince, I think a separate namespace makes sense

10:26 rhickey: gnuvince: I don't think you are getting my point about there being many user namespaces with seq and stream versions of a function, you can't have a namespace-based naming convention

10:26 thickey: then i'm back to smap, sfilter... at least it in line with the decision to make the parallel functions named the way they are

10:27 rhickey: danlarkin: forcing all namespaces that have stream version to have a sub-namespace with a naming convention? ouch

10:27 Chouser: I like appending a modifier over prepending, because the algorithmic meaning of the stream ops is the same, it's just the data types involved that are different.

10:27 rhickey: Chouser: not exactly, due to the once-only use aspect

10:27 gnuvince: rhickey: that's the thing, why does there need to be a convention? You want to use regular seqs? Use the core functions. You want streams? Require stream (possibly aliasing it to a shorter name for your own convenience) and use that.

10:28 Chouser: rhickey is talking about user-created functions.

10:28 I think.

10:29 rhickey: gnuvince: so core has core and core.stream, and you have gnuvince and gnuvince.stream, and a user that wants to use both/all uses what aliases?

10:29 Chouser: If I write a fancy text-partitioning seq generators called clojure.contrib.regex.re-split, would my stream version have to have another whole namespace?

10:30 clojure.contrib.regex.stream.re-split?

10:30 rhickey: map$, filter$

10:30 Cark: smap ... the smapy version of a regular map

10:30 * rhickey ducks

10:31 cemerick: rhickey: indeed ;-)

10:31 * cemerick flashes back: load "$", 8

10:31 Chouser: hm, is there some history to $ that I don't know.

10:31 rhickey: map*, filter*

10:31 Chouser: cemerick: nice.

10:31 rhickey: map1 filter1

10:32 Cark: i'll vote for the easy smap, sfilter, sreduce

10:32 rhickey: map-once, filter-once

10:32 cemerick: is there really a compelling reason to not use smap, etc?

10:32 rhickey: map-s filter-s

10:32 Chouser: I don't like the 1

10:32 gnuvince: rhickey: I guess I just don't see the problem with having the user explicitly require what he needs.

10:32 cemerick: using the p-prefix for parallel fns was a much bigger change, IMO

10:32 gnuvince: In any case, just my opinion, you're the dictator :)

10:33 cemerick: or, the parallelism of those fns represented a much bigger change in behaviour from the standard fns, I mean

10:33 rhickey: gnuvince: just answer the question, if I want to use the seq and stream version of clojure's map and the seq and stream version of gnuvince's foo, what will that look like?

10:33 4 namespaces and 2 aliases?

10:34 danlarkin: I realize why there are, but I kinda wish there didn't have to be different versions

10:34 gnuvince: (ns (:require [clojure.stream :as s] [gnuvince :as g] [gnuvince.stream :as gs]) (map f xs) (s/map f xs) (g/map f xs) (gs/map f xs))

10:34 thickey: wouldn't "the stream version of gnuvince's foo" just have some other name that gnuvince gave it?

10:35 cemerick: danlarkin: +1. I know I'm eventually going to have to write something like spmapcat or something. :-(

10:36 at some point, it would be nice to "decorate" the core fns with various characteristics (uses streams, uses parallel goodness, etc) (not that I have any concrete proposals about how to do that "decoration")

10:36 AWizzArd: could be as easy as providing an argument

10:36 (map :stream #(+ 4 %) coll)

10:36 rhickey: gnuvince: ok, looks tedious, also, as a reader I have no idea what the implications of gs/ and s/ are to the evaluation - they could just as easily be fred/ and ethel/, even in two parts of the same program. The behavioral difference is critical to call out here in a consistent way - you don't want to be aliasing these things

10:36 cemerick: (map +sp #() coll)

10:36 Chouser: cemerick: metadata! (#^{:use-stream true, :use-parallel true} mapcat func coll)

10:37 cemerick: Chouser: you just pegged my verbosity meter! :-P

10:37 Chouser: AWizzArd: that already means something else

10:37 cemerick: :-)

10:37 AWizzArd: yes, plus I don't like that idea.

10:37 rhickey: using args means a lot of partial-ing for HOF use

10:38 AWizzArd: something like smap, sfilter would be ok I guess

10:38 RadioApeShot: Hi #clojure - I am looking for a way to launch a clojure function in a separate thread from the REPL. For instance, if I wanted a rendering loop to be running in the background but still have access to the REPL to add, remove, or change things about it via dosync blocks.

10:38 Cark: forth style : (streaming (map #(+ 4 %) coll))

10:38 cemerick: yeah, maybe some more concise metadata representation could be fielded for stuff like this (analogous to #^Classname)

10:38 rhickey: It is critical to note that while there is an algorithmic similarity, streams have very circumscribed usage compared to persistent seqs, they are one-pass and ephemeral

10:39 RadioApeShot: I already tried creating a fn and then calling its run method via (. f run)

10:39 rhickey: I am partial to Chouser's argument for appending, especially as then the two versions will sort together

10:40 cemerick: rhickey: Definitely. However, if just one more 'axis' of functionality is introduced, then the various combinations of streams, parallelism, and XX will become very difficult to keep straight.

10:40 Chouser: RadioApeShot: (.run (Thread. #(prn "hi!")))

10:40 rhickey: cemerick: you want less functionality? :)

10:40 RadioApeShot: Chouser: Thanks.

10:40 Chouser: RadioApeShot: or look into agents or futures, depending on how you intend to use the thread.

10:40 cemerick: rhickey: surely, no. But I do want a way to compose various features around a core operation (map, filter, etc)

10:41 rhickey: cemerick: in the ends these aren't 'properties' of the same function - they're different functions with different albeit similar semantics

10:41 cemerick: ...without having an explosion of variants of those core operations (spmapcat, etc)

10:41 rhickey: cemerick: that's a theoretical argument

10:41 Cark: would it make sense to have a parallel stream function anyways ?

10:42 AWizzArd: I thought streams are serial?

10:42 gnuvince: rhickey: is there a reason not to have both? Put them in a different namespace and dictate a naming convention to make their behavior explicit to the reader? There are already over 450 symbols in the core namespace; if set operations were put in a different namespace, why not streams?

10:42 Chouser: = has parallel lines, thus clearly means parallel multithreaded operation. ~ looks like a little river, so clearly means stream. thus mapcat=~

10:42 cemerick: lol

10:43 RadioApeShot: (.run (Thread. f)) still causes my REPL to hang while the thread does its work

10:43 gnuvince: Chouser: I proposed ~ yesterday, but the reader doesn't like that :-/

10:43 cemerick: Chouser was egyptian in a previous life

10:43 Cark: haha

10:43 rhickey: = looks like a pipe and ~ a tail, so streaming and lazy :)

10:43 Chouser: gnuvince: the reader can be fixed.

10:43 rhickey: :-P

10:44 cemerick: ~ really can't be in the running. One would get dizzy while writing macros.

10:44 clojurebot: Holy Crap.

10:44 AWizzArd: What are the contras for a prefix letter, such as "s"?

10:44 Chouser: gnuvince: but yes, I know you thought of it. It's not my idea, I'm simply defending it. :-)

10:44 rhickey: cemerick: I agree

10:44 danlarkin: AWizzArd: doesn't sort together

10:44 Chouser: AWizzArd: reductionss

10:44 oh, prefix, sorry.

10:44 cemerick: danlarkin: bah, the p* fns don't sort with their single-threaded counterparts

10:45 Cark: i don't buy the sorting argument, docs are searchable by other means

10:45 rhickey: cemerick: where are these many p* fns?

10:45 Chouser: nah, we already can have `(let [foo# #'foo, bar# ~#{#'baz #'qux}] ...) in a macro

10:46 rhickey: Chouser: but not ~foo~

10:46 Chouser: ooh, pretty!

10:47 rhickey: that's foo swimming in a sea of confusion

10:47 Cark: looks like foo is about to drown ... more like a pond than a stream

10:47 Chouser: heh. ok, fine.

10:47 * Chouser is greatly amused.

10:48 gnuvince: rhickey: any thoughts on the namespace+naming convention idea or is it just bad?

10:48 rhickey: map<<, filter<<

10:48 Chouser: mapS map$ map=

10:48 was the map$ suggesting entirely a joke?

10:49 rhickey: gnuvince: I didn't see the naming convention in there

10:49 gnuvince: [10:43:56] < gnuvince> rhickey: is there a reason not to have both? Put them in a different namespace and dictate a naming convention to make their behavior explicit to the reader? There are already over 450 symbols in the core namespace; if set operations were put in a different namespace, why not streams?

10:49 rhickey: Chouser: no, but $ is totally unused and could thus be used for something really special down the line

10:49 AWizzArd: I don't like too many conventions. More than enough people will not stick to it.

10:49 cemerick: rhickey, danlarkin: sorry, my bad. There's pmap of course, but we have a pfilter here, too. I thought the latter was in core. :-(

10:49 rhickey: gnuvince: what's the naming convention then?

10:50 gnuvince: rhickey: well that's to be decided, but would you opposed to putting "conventially-named" functions for streams in a separate namespace?

10:51 Chouser: map<< is my new favorite

10:51 rhickey: gnuvince: yes, because all the seq functions will likely be defined in terms of the stream ones, creating a lot of organizational hassle for people

10:51 gnuvince: ah

10:51 Didn't know that.

10:52 rhickey: gnuvince: there might even be a single macro that defines both a stream and seq version in one shot

10:52 Cark: if smap is rejected i'd go for map<< too

10:52 gnuvince: So the seq functions are going to lose their nice functional, recursive definition in favor of something more iterative?

10:52 jayfields: (doc var)

10:52 clojurebot: No entiendo

10:52 cemerick: rhickey: looking at clojure.org/streams, your original thought of map*, etc. looks really good.

10:53 rhickey: (def map #(sequence (map-stream %1 %2)))

10:53 Chouser: jayfields: var is a special form: http://clojure.org/special_forms#var

10:54 jayfields: Chouser: thanks.

10:54 rhickey: map*, map+, map= or map<< ?

10:54 map1 map-1 maps

10:54 Chouser: map* says nothing, and the * suffix is occasionally used elsewhere

10:54 gnuvince: Any reason for <<?

10:55 rhickey: gnuvince: implies piping

10:55 cemerick: huh, map+ is nice

10:55 Chouser: map= looks too much like it's related to equality, I'm afraid.

10:55 gnuvince: rhickey: piping the elements into f?

10:55 cemerick: isn't +name+ used as some kind of convention in CL?

10:55 (not that that would be a reason to not use map+, etc)

10:55 rhickey: gnuvince: just being part of a pipeline, that really is the analogy, there is also tap now

10:56 Chouser: the 1 suffixs I dislike because they might imply taking only the first rather than taking each thing only once.

10:57 gnuvince: Has any other Lisp (or another language like Forth or Factor) implemented something like this and decided on a convention?

10:57 Chouser: so of those, I think map+ and map<< rise to the top.

10:57 rhickey: Chouser: you might read it 'once', works like macroexpand-1

10:57 people coming from other langs might not see foo<< as one symbol

10:58 Cark: you don't have to put a warning in the name of your function, that's what docs are for

10:59 tashafa: how do i make a thread sleep in clojure

10:59 ?

10:59 cemerick: map+ and map* are my preferences, FWIW

10:59 tashafa: (java.lang.Thread/sleep n) doesnt seem to work for me

10:59 thickey: my brain seems to like map* because verbalizing "map-star" at least shares some commonality with "map-stream" so the "oh right, that's the stream version" moment of realization is there

11:00 Chouser: I wouldn't worry too much about foo<< looking like two symbols. At that level of understanding, they might see it as a separate modifier or something, but you pretty quickly get used to looking for spaces to break up symbols.

11:00 thickey: not loving map<<

11:00 rhickey: map<-s, filter<-s

11:00 map-s, filter-s

11:00 cemerick: tashafa: that's the right function....

11:01 rhickey: map*s, filter*s

11:01 Cark: chouser : yes at that rate someone looking at read-file would think we're doing a substraction

11:01 cemerick: (* "ugh" 6)

11:02 Chouser: tashafa: that takes milliseconds, so (Thread/sleep 1000) should be noticable.

11:02 tashafa: cemrick: hmm, it doesnt throw any errors, but would using it in a doseq change teh behaviour?

11:03 Chouser: thickey: any particular reason?

11:04 leafw: rhickey: map<-s or map-s read best to me; map*s does't convey the meaning to my eyes (looks to much like global var, or like the product of something)

11:04 cemerick: tashafa: like any side-effecting method, if you call Thread/sleep in a lazy context, then you're likely not going to get what you want

11:04 thickey: Chouser: they share a lot of letters

11:04 RadioApeShot: So (.run (Thread. th)) - am I wrong in thinking this should run th (a clojure function which loops forever and sometimes sets a value inside a ref) in a new thread and immediately return to the REPL? When I call this my REPL freezes just as if I had called (th)

11:04 thickey: Chouser: oh, did you mean for not liking << ?

11:05 Chouser: thickey: yes

11:05 cemerick: RadioApeShot: you want .start, not .run

11:05 tashafa: ok my bad...it does work

11:05 Chouser: ah! my fault, sorry.

11:06 RadioApeShot: cemerick: Thanks.

11:06 tashafa: thanks all

11:06 RadioApeShot: My java is rusty

11:06 thickey: Chouser: just don't like the way it looks. and i'm in preference of the "s" variants myself, and thought that at least * had some way i could connect the two, as opposed to << which just leaves me wondering

11:06 leafw: thickey: << is a c++ thinguie, really.

11:07 which has meaning around the concept of streams.

11:07 Cark: great let's plunder c++ ...was good for java, might be good for clojure as well =P

11:07 cemerick: << is a bit shift to me *shrug*

11:07 Chouser: but not in clojure

11:07 leafw: cemerick: that too xD

11:07 rhickey: doesn't << imply piping to anyone?

11:08 leafw: rhickey: to me. But map<< reads funny

11:08 cemerick: rhickey: not really

11:08 rhickey: ok

11:08 cemerick: <- perhaps

11:08 but that's bad for other reasons

11:08 rhickey: <-map, <-filter

11:08 Chouser: sure, << implies a direction of flow. I like filter<<

11:09 AWizzArd: smap, sfilter, sreductions

11:09 cemerick: rhickey: if those are options, why not just use smap, sfilter

11:09 leafw: how about map$ where $ is for stream. Or is the $ used for something else?

11:09 * cemerick still prefers map* or map+

11:09 leafw: also, it makes it stand out a lot.

11:10 Chouser: leafw: "< rhickey> Chouser: no, but $ is totally unused and could thus b

11:10 leafw: map* read like a pointer. map+ reads like "something more than map"

11:10 Chouser: e used for something really special down the line"

11:10 AWizzArd: rhickey: every few weeks you come up with a new naming challenge. Why don't you write a small poll (in Clojure) for the website? ;)

11:10 rhickey: Just as an FYI, whatever it ends up being, you're going to use it a lot as it can be 3-4x as fast

11:10 Chouser: ew. sorry.

11:10 leafw: pointer!?

11:10 leafw: Chouser: sorry, started with C long ago.

11:10 cemerick: heh, I didn't think about the pointer interpretation at all

11:11 Chouser: leafw: me too, but it's not a syntax I come close to thinking about here. :-)

11:11 cemerick: fn* is pretty standard for a slightly modified version of fn in various lisps, which makes sense

11:11 leafw: Chouser: well, just an impression :)

11:11 Chouser: my main argument against * is that it's used several other places to mean non-stream things.

11:11 leafw: cemerick: but is map* a modified map in the same way that fn* is a modified fn? Or an altogether different modification?

11:12 Chouser: altogether different, which is my argument

11:12 leafw: I agree Chouser

11:12 AWizzArd: can we already foresea if the stream version will be used more often than the one we currently have? In that case one could maybe even think of having the stream versions named map, reduce and filter, and find a new name for the existing stuff.

11:12 Chouser: a + suffix is equally unmeaningful, but at least unique within clojure.

11:12 cemerick: AWizzArd: oh, no, please, no

11:13 Chouser: AWizzArd: huge breaking change!

11:13 AWizzArd: of course

11:13 cemerick: Chouser: in that case, smap and sfilter should be it, sort order be damned.

11:13 thickey: Chouser: good argument against *

11:13 AWizzArd: cemerick: yes, I like these prefixes also more

11:13 leafw: map-s reads most natural, but honestlym it would already break some of my code: I have vars named like that

11:14 smap would do it for me too -- reads like "stream map", and it's an unlikely name for a var.

11:30 achim_p: hmm, what about putting the stream variants in a separate namespace. people could alias it to their liking, even (require '[clojure.streams :as <-])

11:31 AWizzArd: that was what gnuvince suggested

11:31 scroll up to see rhickeys questions regarding that

11:31 achim_p: oops, sorry

11:32 gnuvince: achim_p: it'd be alright if it wasn't for the fact that the core seq functions will be defined in terms of streams

11:35 Chouser: and that you can only alias one namespace to <- even if you want stream functions from several different libs

11:35 achim_p: i see

12:24 hiredman: ~latest

12:24 clojurebot: latest is 1326

12:29 hiredman: hmmm

12:44 r1006

12:47 ~latest?

12:47 clojurebot: latest is 1326

12:48 rhickey: I'm currently partial to map* and filter*, I don't see the prior usage of blah* as being part of the public interface

12:50 could just as easily be fn-special-op, let-special-op

12:50 no one uses them directly

12:58 cemerick: rhickey: I actually didn't realize that fn* et al. existed until I started spelunking with macroexpand

12:58 but yeah, changing those forms to something without the trailing asterisk would make sense

12:58 I actually use the * convention for a couple of "alternative" fn implementations already.

13:01 jayfields: is there a function that lets me verify if an argument is in a seq, e.g. (any? [1 2 3] 1)

13:02 achim_p: jayfields: (some #{1} '(1 2 3))

13:02 jayfields: thanks

13:02 achim_p: jayfields: contains? is faster for vectors and sets, doesn't work on lists

13:02 hiredman: ,(.contains '(1 2 3) 1)

13:02 clojurebot: true

13:02 cemerick: jayfields: to be clear #{1} creates a set that contains a single member (1) -- and sets are fns of their contents

13:03 ,(#{1 2 3} 3)

13:03 jayfields: where is contains? defined?

13:03 clojurebot: 3

13:03 hiredman: might be in contrib

13:03 jayfields: cool. thanks.

13:04 achim_p: contains? is in core ...

13:04 hiredman: oh

13:04 ~def contains?

13:04 I guess that is where it is defined

13:04 achim_p: argh, contains doesn't work for vectors, forgot that

13:05 danlarkin: achim_p: it does! but not how you thought

13:05 achim_p: yeah

13:05 contains? is "contains key?"

13:05 danlarkin: ya

13:06 hiredman: so clojurebot has brand spanking new svn polling code, and https://twitter.com/clojurebot, so I am just waiting for rhickey to commit something so I can see if it works

13:06 danlarkin: achim_p: you probably want (some #{k} coll)

13:09 achim_p: danlarkin: yeah, i was replying to myself replying to jayfields ;)

13:10 danlarkin: :-o

13:10 I have a bad habit of not reading my whole irc buffer

13:15 shoover: cemerick: true, as long as you don't have nil as a value in the set

13:18 even then it's true, I suppose, but hard to distinguish

13:18 (to mince words with myself)

13:30 sohail: hey anyone here know how to pass -Xlint:deprecation through maven?

13:49 cp2: anyone here have experience with couchdb? im wondering how it is, if you like it, etc

13:50 eevar__: ,(use 'clojure.contrib.lazy-seqs)

13:50 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/lazy_seqs__init.class or clojure/contrib/lazy_seqs.clj on classpath:

13:50 eevar__: (doc primes)

13:50 clojurebot: Excuse me?

13:50 eevar__: m(doc primes)

13:50 ,(doc primes)

13:50 clojurebot: java.lang.Exception: Unable to resolve var: primes in this context

13:51 digash``: cp2: i'v heard from not unbiased developers for mongodb that couchdb is very slow.

13:51 cp2: heh

13:52 ok, ill change the question then

13:52 any "clojure-friendly" database api/whatever

13:52 Chouser: Rich was talking about the state of mongodb recently.

13:52 * Chouser offers the only information he has.

13:53 cp2: heh

13:53 thanks

13:53 digash``: mongodb guys have couple of different java apis

13:53 cp2: i may end up using clojureql in the end

13:53 but im open to other options

13:53 digash``: and they are willing to cooperate to make it much more clojure friendly when i've talked to them.

13:56 eevar__: how hard is using plain jdbc from clojure?

13:57 digash`: pretty straight forward, i've wrote number of scripts to "massage" databases.

13:57 Chouser: not bad, plus there's clojure.contrib.sql for a fairly thin wrapper, or clojureql for a bit more abstraction.

13:58 cp2: does contrib.sql / clojueql have support for more than just mysql? (as in sqlite, mysqli, etc)

13:59 Chouser: I believe contrib.sql will work with whatever, but doesn't hide the differences in SQL syntax.

13:59 eevar__: database independence is a pipe dream anyway

13:59 Chouser: clojureql attempts to hide those differences as well, and supports a couple databases.

14:00 cp2: yeah, im not too worried about being database independent

14:00 i just dont want to _have_ to use mysql

14:00 Chouser: eevar__: 100%, sure, but even independence for 80% of your db interaction can be a big win.

14:00 cp2: Chouser: thanks for the info

14:00 eevar__: dunno. I'd rather pick one db and marry it ;)

14:00 Chouser: hm.

14:01 * Chouser has been through several db-porting projects on codebases that thought they had married one db.

14:01 digash`: i think jdbc does abstract quite a bit compare to libmysql.so

14:02 eevar__: should I ever come across somethign postgres can't handle, i'm sure there's plenty of $$ floating around for oracle/db2 porting

14:03 i do use embedded db's a times, tho

14:04 but only for small hackish things that are easily ported to pg if neccessary

14:11 hiredman: ~latest contrib?

14:11 clojurebot: latest contrib is 334

14:11 hiredman: clojurebot: latest contrib is 570

14:11 clojurebot: 'Sea, mhuise.

14:23 dcnstrct: has anyone here had any success using CouchDb4J ?

14:24 for some reason I can't get it to execute views although it works fine for CRUD on individual documents

14:27 nvm I just found jcouchdb a different library.. and it works

14:36 tashafa: look into clj-record

14:36 http://github.com/duelinmarkers/clj-record/tree/master

14:52 cemerick: hrm, using delays in maps makes determining equality a little tricky

14:53 dcnstrct: clj_record looks badass, maybe I can augment it to add couchdb support

14:55 * dcnstrct is no looking to go back to using the relational database any time soon

15:04 danlarkin: dcnstrct: some sort of ORM-ish type thing with couchdb backing is on my (ever growing) todo list

15:05 maybe you could strike it off for me!

15:06 dcnstrct: sounds like a plan, but don't hold your breath ;)

15:12 gnuvince: Was anything decided for streams?

15:16 ls

15:18 cemerick: gnuvince: I think map* is in the lead, last I saw

15:22 gnuvince: ok

15:29 StartsWithK: i have in one file (gen-class :name net.ksojat.neman.swing.Wrapper ..) (defmethod patch [net.ksojat.neman.swing.Wrapper ..] ...)

15:29 but i get a error that net.ksojat.neman.swing.Wrapper dosn't exist

15:30 kotarak: Did you compile the containing namespace?

15:30 StartsWithK: what should i do to make it work?

15:30 yes

15:30 hiredman: is it in your classpath?

15:30 StartsWithK: yes

15:31 that part is ok im sure

15:31 hiredman: lets see the stack trace

15:32 StartsWithK: it says that when i try to run example from repl, not when i compile the code

15:34 hiredman: (.printStackTrace e*)

15:34 oe *e

15:34 r

15:34 whatever it's named

15:35 StartsWithK: http://paste.pocoo.org/show/106759/

15:36 hiredman: how do you know the compiled class is in your classpath?

15:37 StartsWithK: build generates my repl script to reflect any changes i made to classpath

15:37 hiredman: so your *compile-path* is in your CLASSPATH?

15:37 StartsWithK: yes

15:37 hiredman: really?

15:38 Chouser: you should be able to say net.ksojat.neman.swing.Wrapper at the repl before you 'load' anything

15:38 StartsWithK: yes

15:38 hiredman: what does (System/getProperty "java.class.path") say?

15:39 StartsWithK: Chouser: that fails too

15:39 Chouser: StartsWithK: then that class is not in your classpath. Either it wasn't generated, or the place where it was generated is not in your classpath.

15:41 StartsWithK: hiredman: http://paste.pocoo.org/show/106762/

15:42 hmm, but java.class.path says it is, and swing/target/classes has that class

15:45 hiredman: StartsWithK: was it generate before or after you started your repl?

15:46 StartsWithK: hiredman: before

15:46 and just in case i regenerated repl script

15:47 hiredman: are all your namespace declarations correct?

15:48 StartsWithK: yes

15:48 kotarak: @rhickey: AOT compilation uses metadata of namespaces.

15:48 s/uses/looses

15:49 StartsWithK: only thing that is not compiled is test file

15:50 Chouser: (let [p #(.getAbsolutePath (java.io.File. %))] (filter #{(p *compile-path*)} (map p (.split (System/getProperty "java.class.path") ":"))))

15:51 StartsWithK: what does that return? ^^^

15:51 kotarak: Stupid question: How do I use *warn-on-reflection*?

15:51 Chouser: kotarak: not stupid! set it true before you evaluate some (defn ...) forms.

15:52 StartsWithK: Chouser: from repl? (), but i don't have *compile-path* for repl, only for compile target

15:52 Chouser: hm, ok.

15:52 kotarak: So must it be source file or do compiled files also work? (read: (set! ...) (require 'foo.bar) ?

15:53 Chouser: kotarak: the warnings are generated at compile time, not at runtime

15:53 so in that example, if foo.bar is not compiled, it should work.

15:53 but if foo.bar is loaded from a .class file, you'll get no warnings.

15:54 kotarak: Ah ok. I need gen-class, though. Can I set the warn flag also when compiling? Some -Dclojure.warn-on-reflection=true magic?

15:55 Chouser: as far as I know there's no property you can set, but you should be able to use (set! ...) and then compile.

15:57 kotarak: Chouser: Ok. Simply compiling the gen-class stuff and then using load-file give the warnings. set!-ing and then compiling does not give the warnings, though. Hmm... Ominuous.

15:57 Chouser: thanks. :)

15:58 Chouser: hmph

15:59 StartsWithK: this is the file http://paste.pocoo.org/show/106763/ loaded from (ns :load "swing/wrapper"), compiles ok, i see all generated classes, but now i see that even require on swing namespace generates the same erro

16:02 ah, and line 24 is line 16 in the paste, didn't include the header..

16:05 kotarak: Can I somehow tag the :state part of gen-class?

16:06 StartsWithK: tag how?

16:07 it 'works' now, but i included generated jar in classpath, and not directory with generated .class files

16:07 why should that make any difference?

16:11 kotarak: StartsWithK: I always have a IPersistentMap in there. But all calls to .theMap return something, which I have to tag with IPersistentMap to avoid reflection. :(

16:11 But maybe I just the "usual" functions instead of the methods directly...

16:13 Chouser: ah, interesting. If you provide an accessor that has a tagged return value, then you should be able to use that accessor everywhere and not have to tag each usage.

16:19 fanda: hello!

16:19 i have a question about "contains?"

16:19 how does it work with lists?

16:19 ,(contains? '(1 2 3) 1)

16:20 clojurebot: false

16:20 fanda: is this a bug?

16:20 hiredman: ,(doc contains?)

16:20 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

16:20 hiredman: "it will not perform a linear search for a value"

16:20 fanda: oh, I see

16:21 hiredman: Chouser: could you commit something to contrib?

16:27 fanda: hiredman: are you testing some functionality?

16:27 I could commit something too

16:28 hiredman: that would be cool

16:28 Yes

16:30 kotarak: cool. one can also tag %1 in a #() :)

16:31 fanda: new test for "find" commited

16:31 * hiredman waits

16:31 hiredman: *tada*

16:31 Chouser: nice

16:32 fanda: yes, looks nice

16:37 Raynes: To iterate is human. To recurse is divine

16:37 fanda: :-)

16:38 hiredman: ah, well, the recurse in instant space is divine

16:38 to

16:38 constant

16:38 ugh

16:52 fanda: :-)

16:53 hiredman: I think I fail at twitter

16:54 fanda: why is that?

16:55 hiredman: fanda: it seems simple, but for some reason clojurebot's tweets are not working correctly

16:56 I blaim that fact that I am shelling out to curl, so I think I'll go find some java code

16:57 fanda: hiredman: it's always good to have more options :-)

16:59 rhickey, Chouser: I believe that Clojure issues 55 and 76 could be solved now.

16:59 http://code.google.com/p/clojure/issues/list

16:59 They were waiting for Timothy Pratley to sign and send his CA, but that looks done:

16:59 http://clojure.org/contributing

17:01 Chouser: 55 is already fixed, but the issue needs to be marked, I guess.

17:02 ,(repeat 5 9)

17:02 clojurebot: (9 9 9 9 9)

17:03 fanda: replicate hasn't been removed, though

17:04 * Chouser nods, shrugs.

17:29 Drakeson: is there a shortcut for replacing subtrees matching a certain criteria with a function of the subtree? (e.g. DFS). tree=[:a [:b 1] [:b 2 3]] pattern=[:b x] --> [:a (f [:b 1]) [:b 2 3]]

17:30 Chouser: you might find something useful in clojure.contrib.walk, but I'm not sure.

17:32 dcnstrct: could anyone give me a suggestion of what I might be doing wrong ? I'm trying to use jcouchdb to create a document, and exactly what like what is showin the first example on this page: http://code.google.com/p/jcouchdb/wiki/Tutorial

17:33 (. *db* createDocument {:foo "bar"}) returns this: java.lang.UnsupportedOperationException (NO_SOURCE_FILE:0)

17:33 I can't figure out how to trace into this to figure out what the problem is. Do I need to use a java debugger ?

17:34 if so what debugger would you recommend (I'm on OSX)

17:34 Drakeson: Chouser: thanks, that's like what I was looking for.

17:35 dcnstrct: forget the jcouchdb part of the question... I just want to know the name of a good java debuger (I'm new to java)

17:36 hiredman: dcnstrct: the db must be trying to mutate the imutable clojure hash

17:36 dcnstrct: hiredman, ah ha!

17:37 hiredman, yes it is.. it's trying to add a couple properties to it

17:37 hiredman: :(

17:37 how unfortunate

17:37 dcnstrct: hiredman, is there a way I can turn the clojure hash into something more maleable before I pass it in ?

17:37 hiredman: sure

17:39 ,(java.util.HashMap. {:a 1})

17:39 clojurebot: #<HashMap {:a=1}>

17:40 dcnstrct: it works!!! thank you you saved the day

17:45 hiredman: ugh

17:45 silly sun, not including Base64 encode/decode in the jdk

17:47 Chouser: so now after starting up a plain repl, you can run (add-break-thread!)

17:48 after that, Ctrl-C should break you out of any infinite loop and return you to the repl.

17:48 I don't know what it'll do in slime/swank or any other unusual repl

17:48 and even in a plain repl there may be odd consequences, since it's using Thread.stop()

17:49 * hiredman uses add-classpath and dies a little inside

17:49 Chouser: ...but it may get you out of a sticky situation. I'd be curious to know if anyone finds it useful, or if it makes bad things happen for anyone.

19:20 keithb: Is there a way to write a function that returns something that it lazily initializes

19:20 ?

19:21 I'm finding that I need some objects to be available in various parts of a program. Is it better to use def?

19:23 mrsolo: hm how come there is not-any? but not any?

19:24 keithb: mrsolo: some?

19:24 durka42: what he said

19:24 mrsolo: ah

19:24 hiredman: mrsolo: because there was 'some' and someone wanted 'not-any' and bitched until they got it

19:25 mrsolo: ..

19:25 keithb: I withdraw my previous question...

19:25 hiredman: ~def not-any?

19:26 Raynes: (doc not-any?)

19:26 clojurebot: Returns false if (pred x) is logical true for any x in coll, else true.; arglists ([pred coll])

19:26 Raynes: (doc some)

19:26 clojurebot: Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return true if :fred is in the sequence, otherwise nil: (some #{:fred} coll); arglists ([pred coll])

19:26 Raynes: Well...

19:26 hiredman: not-any? is literally the composition of not and some

19:27 Raynes: Tsk.

19:28 keithb: I have a def that calls a function with a fn, that is: (def foo (myfunc (fn [] ...))). I refer to a variable in the fn. At the time the def is read by the interpreter, that variable in the fn has not yet been initialized. So will it always refer to nil, even though when it is called the var has a non-nil value?

19:28 mrsolo: oddity that's all since there are empty and every?

19:28 hiredman: keithb: pastbin

19:29 Raynes: paste.pocoo.org or paste.lisp.org O.O

19:29 durka42: ~paste

19:29 clojurebot: lisppaste8, url

19:29 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

19:29 Raynes: durka42: Thanks for not insulting my code, I know you wanted too :p.

19:30 durka42: Raynes: i was just puzzled while i was trying to reverse-engineer your input format from the code :)

19:31 Raynes: I know the code sucks though anyways :|

19:31 durka42: i did find it strange that you had two replace-xxx fns that both took strings, but one was the actual string and the other took a filename

19:32 Raynes: That was a break-code-up-into-smaller-functions-and-dont-format accident.

19:32 durka42: hmm, someone should write a clojure refactoring tool :p

19:32 lisppaste8: keithb pasted "Entire Program" at http://paste.lisp.org/display/76599

19:33 keithb: That's the whole thing; I'll try to pare it down now...

19:33 lisppaste8: Rayne@acidrayne.net pasted "new keyvalue reader" at http://paste.lisp.org/display/76600

19:34 Raynes: I also realized that if I cut one of the spaces beside the '=' then I don't need to replace the double spaces with single spaces before splitting :D

19:34 durka42: "Hi there, it looks like you're writing iterative, stateful code with loop/recur. Would you like to: -change the loop into tail recursion -transform the loop into an elegant lazy fold -write the goddamn loop in peace"

19:34 * Raynes is going to start writing a parser tonight.

19:35 durka42: keithb: it's clear-action on line 114 you're asking about?

19:38 keithb: durka42: yes

19:39 lisppaste8: keithb annotated #76599 "untitled" at http://paste.lisp.org/display/76599#1

19:42 durka42: keithb: it's true that fahr-text-field isn't bound until you call create-text-fields

19:43 keithb: durka42: Yes, I know. My question is about the timing of the access to fahr-text-field in the fn.

19:43 duncanm: i have a list of names (let [name "x" names `(name ~name)] (for [n names] (println n))) --> this prints (nil nil)

19:43 shouldn't it print "name x"

19:43 ?

19:44 durka42: keithb: i think it should be okay to globally def fahr-text-field to nil, since the fn you pass to create-action can't be called until the frame is on the screen, which happens after create-text-fields is called

19:44 keithb: durka42: I thought that it would access fahr-text-field and get its value *when it is called*, but it appears to hold on to the value (nil) it had when the function was *defined*.

19:44 durka42: Oh..

19:45 durka42: duncanm: for is lazy. for me it prints:

19:46 Clojure=> (let [name "x" names `(name ~name)] (for [n names] (println n)))

19:46 (clojure.core/name

19:46 x

19:46 nil nil)

19:46 use doseq if you want a more "traditional" for loop

19:46 for is not a "for loop", it is more of a list comprehension

19:46 duncanm: hmm

19:46 all i'm looking for is something like FOR-EACH in Scheme

19:47 keithb: durka42: I just tried that. No joy. I now get a NullPointerException. I remember in my Ruby study that a code block retains its bindings from when it was created. I think that's what's happening here.

19:47 gnuvince_: duncanm: doseq

19:47 (doseq [element sequence-of-things] (println element))

19:48 lisppaste8: durka42 pasted "keithb" at http://paste.lisp.org/display/76601

19:50 keithb: durka42: Thanks. Great job of reducing the problem...so it looks like I have to include an accessor method.

19:50 That's why I was wondering before about lazily initializing the thing within that accessor method. Possible?

19:50 durka42: i'm not sure what you mean by lazily

19:51 keithb: durka42: Lazily in that the object would not be created until the function's first time called. Subsequent times it would return the same value.

19:52 durka42: oh, i suppose you could do that

19:52 but isn't this an event handler function?

19:52 so you would want the text fields to be created before that

19:52 keithb: durka42: It doesn't really matter when they're created...they don't rely on any context.

19:54 durka42: but you will need them to be created so they can be shown onscreen...

19:56 lisppaste8: keithb annotated #76599 "Java lazy initialization method" at http://paste.lisp.org/display/76599#2

19:56 keithb: durka42: This is what I would like to do in Clojure.

19:56 durka42: that looks doable

19:57 (if fahr-text-field fahr-text-field (create-text-field))

19:57 keithb: durka42: I think I just figured it out... def it to nil in the beginning, and then, what you said. ;)

19:57 durka42: (or fahr-text-field (create-text-field))

19:58 keithb: durka42: ...except you want to hold onto the newly created thing in the variable, so you only ever create one of them.

19:58 durka42: well, that's what the (if) or the (or) does

19:59 * durka42 finds it hard to talk about functions whose names are basic grammatical units

19:59 keithb: ok, I'll write something up and run it by you. THanks much.

20:01 AWizzArd: gnuvince_: is there a descision about the streams now?

20:02 gnuvince_: AWizzArd: I don't know, I've been away most of the afternoon and evening

20:19 lisppaste8: keithb annotated #76599 "untitled" at http://paste.lisp.org/display/76599#3

20:20 keithb: Got it... it was an extra set of parens!!!!

20:26 durka42: oh, i see

20:26 nice work

20:30 lisppaste8: keithb annotated #76599 "untitled" at http://paste.lisp.org/display/76599#4

20:31 keithb: Given the repetition in the pastie, and the simplicity of the function, is there a macro somewhere that would do this for me with a simple definition of name and initialization strategy? Where does one look for these things?

20:33 Chouser: (if foo foo bar) is the same as (or foo bar)

20:33 oh, wait.

20:33 what are you doing?

20:34 keithb: Chouser: I'm writing accessors that lazily initialize the thing they access.

20:34 They're not really self contained; they require a def outside of the function. If there's a better way I'm totally open to it...

20:35 Chouser: hm, there are a few options...

20:35 Cark: def inside a function ...that's ugly

20:37 hiredman: keithb: sounds like you want futures

20:38 keithb: The use case I'm trying to address is that I want to pass a fn that has access to a var whose value will be initialized in the future. YES!

20:38 hiredman: (doc future)

20:38 clojurebot: Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block.; arglists ([& body])

20:38 Chouser: delay is probably closer to what you want, unles I'm misunderstanding.

20:40 hiredman: ~def delay

20:40 keithb: Chouser: Thanks! I think delay is what I want; an additional thread is overkill.

20:40 lisppaste8: Chouser annotated #76599 "close over a delay" at http://paste.lisp.org/display/76599#5

20:44 keithb: Chouser: That's great, it works. Now, to be a pain about it...couldn't a macro hide the let and force mechanics from me so that my functions could be even simpler?

20:45 lisppaste8: keithb annotated #76599 "untitled" at http://paste.lisp.org/display/76599#6

20:45 keithb: ...something like the thing I pasted, which could maybe be expanded to your delay/force code, which would in turn be expanded?

20:45 I haven't learned macros yet...

20:45 Chouser: yep, sure could

20:46 looks like a great one to start with.

20:46 keithb: :)

20:46 Ok, for another day...thanks for all your help.

20:46 Chouser: I'm not kidding. I'm guessing you haven't bought Halloway's book?

20:46 oh, ok. you're welcome.

20:47 keithb: Yes, I have...I've been using it.

20:47 But only read some chapters so far.

20:48 I know you're not kidding...I will try that...but first I want to finish this program...I hope to post an article about it on my blog at http://krbtech.wordpress.com.

20:50 Chouser: ah, great. The chapter on macros should be just right for this example.

20:50 keithb: Chouser: So where is the cached value stored?

20:50 Metadata?

20:50 Chouser: nope, it's cached inside the delay object, which is held by x

20:51 keithb: Ah, it's a Java object?

20:51 Chouser: x is held inside the function (a.k.a. closure) created by #()

20:51 ,(class (delay))

20:51 clojurebot: clojure.lang.Delay

20:51 hiredman: http://twitter.com/clojurebot/status/1291166090 <-- so this kind of works

20:53 keithb: Chouser: and a function can hold data because code is data? This is hard for me to wrap my head around, coming from C/C++/Java/Ruby.

20:53 te: hello all

20:53 Chouser: keithb: no, it's independent of that. I'm pretty sure Ruby has closures...

20:53 te: Is it possible to create a function that renames itself?

20:54 keithb: Chouser: I believe in Ruby any code block, lambda, or proc is a closure.

20:54 Oh, I think I get it...

20:54 te: keithb: im not sure if that's true

20:54 lambda and proc behave differently

20:54 hiredman: te: that sounds like mutation

20:54 keithb: te, do tell...

20:54 Chouser: my ruby is really rusty...

20:55 te: iif you use lambda inside a block it will not continue past the point in the block that it occurs

20:55 proc will return the value of the block it exists inside

20:57 hiredman: that is really weird

20:57 te: i cant remember for sure if its like that or vice versa

20:57 hiredman: http://samdanielson.com/2007/3/19/proc-new-vs-lambda-in-ruby

20:57 te: this may h ave changed in 1.9 also

20:59 keithb: From the pickaxe book, it sounds like both code blocks and Procs are closures: Associated with a block (and hence a Proc object)

20:59 is all the context in which the block was defined: the value of self and the methods,

20:59 variables, and constants in scope. Part of the magic of Ruby is that the block can still

20:59 use all this original scope information even if the environment in which it was defined

20:59 would otherwise have disappeared. In other languages, this facility is called a closure.

21:00 * te thinks

21:00 te: oh yeah im sorry

21:00 i forgot that lambdas are basically procs

21:00 Chouser: f = lambda{ x = 5; lambda { x = x + 1 } }.call

21:00 te: they literally are procs

21:00 (lambdas are)

21:00 Chouser: ok, it's a bit like that

21:01 f.call returns the value of x (it also mutates it, but that's not my point)

21:01 lisppaste8: slashus2 annotated #76599 "lazy-init" at http://paste.lisp.org/display/76599#7

21:01 keithb: ok, I'll leave it at that...my head's exploding... ;)

21:01 te: if you define f = lambda{ puts "hello" }

21:01 and do f.type

21:01 it's type Proc

21:01 slashus2: keithb: Does that work?

21:01 Chouser: where is the int stored? inside the x that is held by the inner lambda

21:02 te: Chouser: what that a question and answer

21:02 or a question?

21:02 keithb: slashus2: You mean the delay strategy? Yes.

21:02 slashus2: keithb: That macro?

21:02 Chouser: keithb: congrats, it's a macro! :-)

21:02 keithb: slashus2: Sorry, I didn't see your pastie. Tyring it now. Chouser, that wasn't me. ;(

21:02 Chouser: te: sorry, rhetorical device. yes, question and answer.

21:03 te: ah cool just checking

21:03 Chouser: oh

21:03 sorry

21:04 slashus2: you've got a few more args than you need.

21:04 man, irb really hates it when I paste in clojure code

21:04 te: Can you create a function that renames itself?

21:04 Is that possible?

21:04 Chouser: haha

21:05 hiredman: te: that sounds like mutation

21:05 te: hiredman: could you elaborate please:?

21:05 Chouser: te: functions don't really have external names

21:05 te: external in reference to what?

21:05 Chouser: external to itself

21:06 te: hmmm thats hard to understand

21:06 could you explain what you mean

21:06 hiredman: te: you would have to mutate the symbol that names the var that resolves to the fn

21:06 Chouser: you could say that (fn foo [] ...) is called foo inside (where the ... is), but that form returns an anonymous function.

21:06 hiredman: and symbols are not mutatable

21:06 keithb: slashus2: Can you tell me how I would call lazy-init?

21:07 Chouser: you can have multiple Vars or locals pointing to the same function

21:07 te: could that become dirty if i did it too many times?

21:07 slashus2: keithb: exactly how yous specified

21:07 hiredman: dirty?

21:07 Chouser: keithb: the opportunity to justifiably write a macro is pretty rare. I'd ignore solutions posted by others and do it yourself. :-)

21:07 te: hiredman: could it impact performance?

21:08 keithb: Chouser: I hear you. Thanks, everyone. I'm going to call it a night. Beer and karaoke for me. Woohoo!!! ;)

21:08 te: hiredman: sorry im just poking around -- i dont mean to ask 10,000 questions

21:08 hiredman: I dunno about perf, but it would impact "does this program make sense"

21:08 slashus2: keithb: You could ignore mine, but mine does (lazy-init create-a-text-field)

21:09 keithb: slashus2: So: (def fahr-text-field (lazy-init create-a-text-field))?

21:09 slashus2: keithb: yeah

21:09 te: hiredman: im interested in renaming functions according to metadata inside the function

21:09 keithb: slashus2: Cool.

21:10 hiredman: te: without hearing and explanation I am going to tell you: that makes no sense

21:10 an

21:10 besides

21:10 functions cannot currently have metadata

21:11 te: im sorry man maybe im using the complete wrong way to explain this

21:11 Chouser: but Vars can, and you could make a new Var pointing to the same fn based on the metadata of the old Var.

21:11 keithb: slashus2: It works. Well done! Chouser, I'll look into reimplementing it myself later when I learn macros. Thanks everyone!

21:11 Chouser: Not sure why you'd do that, though.

21:12 te: where would the metadata come from?

21:12 te: It would change based on the input

21:12 for the function

21:12 hiredman: :(

21:14 te: i really dont know how to approach this, but basically i want to give the ability to "tag" functions according to whether or not their meta data matches a string the best

21:14 so "Red house dog cat" would match functions whose meta includes house and cat

21:14 Chouser: maybe you want a hash-map with strings as keys and fns for the values?

21:14 hiredman: why?

21:15 te: im interested in toying with evolution of code

21:16 Raynes: Chouser: hash-map is my newest favorite function.

21:16 te: the idea is to age tags that satisfy the combination of functions to give a correct answer

21:16 or an interesting one, at least

21:16 hiredman: te: why would you even name those funtions?

21:16 (name in the sense of symbol->var->fn)

21:17 te: i suppose it isn't necessary, but it would be nice to glimpse into the pool of possibilities and see what has become of the original pool of fns

21:17 hiredman: consider "design space"

21:17 Raynes: (apply hash-map ..) <3

21:18 te: where design space is this space that contains every single possibility for design

21:18 hiredman: te: I refuse to consider something so broad

21:18 te: from a toaster to soil to a ferarri

21:18 hiredman: and it's dinner time

21:19 te: hiredman: im just trying to start with a number of possible designs that are necessary to create new designs

21:19 and then evolve them to see what i can come up with

21:25 slashus2: Chouser: I don't think that a macro was needed for that lazy-init. I rewrote it as a function, and it works correctly.

21:26 Chouser: slashus2: it would have to be a macro if you wanted to provide arbitrary expression rather than a fn.

21:27 like his example: (lazy-init (create-a-text-field))

21:27 slashus2: oh, okay

21:28 ~expr in the place.

21:28 clojurebot: It's greek to me.

21:28 slashus2: woops

21:30 rlb: Does anyone know if the output of pr (or prn) is likely to be identical for a given data structure (at least the core structures) across clojure releases?

21:30 slashus2: Chouser: Thank you, I didn't see the potential for entering an expression.

21:31 Chouser: slashus2: sure, np.

21:31 slashus2: It was actually easier to write that way.

21:35 rlb: More spefically, I'm wonding what the chance is that you can use pr (or prn) to write a bunch of data to a file and have a sha-1 of that file match the output of the same data by a future version of clojure.

21:36 ouch s/spefically/specifically/ s/wonding/wondering/

21:36 Chouser: hard to say for sure. you don't need print-dup i hope?

21:37 rlb: print-dup?

21:38 Chouser: ,(binding [*print-dup* true] (pr-str [1 2] #{3 4} (sorted-set 5 6))

21:38 clojurebot: EOF while reading

21:38 rlb: Actually, hmm, I should look -- ISTR something about clojure serialization, but the same question would apply there, i.e. is the output likely to be bit-for-bit identical across releases? I just want to know if it's likely that I could depend on that. I would guess not, but I thought I'd ask.

21:39 Chouser: ,(binding [*print-dup* true] (pr-str [1 2] #{3 4} (sorted-set 5 6)))

21:39 clojurebot: "[1 2] #{3 4} #=(clojure.lang.PersistentTreeSet/create [5 6])"

21:40 rlb: Basically I want to be able to reliably write at least simple lists or vectors of at least numbers and strings quickly in a way that always results in a byte-wise identical file.

21:41 Chouser: that's unlikely to change, I would think, but you'd want some way to recover if strings get escaped slightly differently or something.

21:41 rlb: And I need to be able to read it back in. Obviously I can write code to do that (i.e. rigid-read rigid-write or whatever, I just wondered if clojure might obviate the need.

21:42 Chouser: I suspect I'll just need to do it myself, though I might use clojure's read/write for now (as the implementation), and plan to just switch to custom routines if/when clojure breaks anything.

21:42 Chouser: that might work.

21:42 rlb: (where "breaks" means changes output format)

21:42 Chouser: right

21:42 rlb: Chouser: anyway, that seems like a fast way to get started -- thanks for the help.

21:43 I'll just add "make check" tests to look for variations.

Logging service provided by n01se.net