#clojure log - Jan 20 2011

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

0:03 amalloy: gtech: i don't even know what jswat is, but have you thought about using george jahad's clojure debugging toolkit?

0:19 mabes: how can I tell if a lazy seq has been realized fully?

0:19 (this is for a test)

0:27 amalloy: mabes: haven't you been asking about this on the mailing list? make each element of the sequence have side effects, and test to see how many side effects have triggered

0:28 mabes: amalloy: no, I don't check the ML too often either so I will if there is some discussion on it

0:28 amalloy: mabes: yeah, i think someone's been asking about this in the last week or so

0:29 mabes: ah, I see the thread.. thanks amalloy

0:30 gtech: amalloy: cool that's a step in the right direction, thanks!

0:30 amalloy: welcome folks

2:40 TobiasRaeder: morning

2:40 Scriptor: morning TobiasRaeder

2:52 afekz: anyone here have much experience setting up enclojure on OSX? I can't see any "Libraries" node on my Project Properties and I'm starting to feel like I need to ask for a smack with a clue-by-four

3:44 Licenser: morning

3:46 LauJensen: Morning

3:49 raek: morning, europe

3:50 LauJensen: Good morning UGT

3:51 Licenser: yay UGT!

4:05 frank: (+ 1 1)

4:05 clojurebot: 2

4:05 Fossi: \o/

4:05 Licenser: (* 1 1)

4:05 clojurebot: 1

4:06 Licenser: (<3 "cookies")

4:13 pareidolia: Hi all

4:14 Does anyone know of a way to tell cake to use a specific version of swank? My emacs has an older slime installed

4:15 I could tell the clojure-maven-plugin which version of the protocol to use, but I'd like to try cake

4:15 Licenser: the cake is a lie!

4:15 octe: the cake is there, you'll see

4:16 i feel good for finally playing through portal and understanding the cake references

4:17 raek: pareidolia: from the swank-clojure docs "It may also warn you that your SLIME version doesn't match your Swank version; this should be OK."

4:18 pareidolia: is the warning all you get, or does something break?

4:21 Dranik: hello all! I'm playing with macros trying to generate a template function but has stuck with the symbols names. I have defined a parameter msg# but can't use it in the function body

4:21 could you please look at https://gist.github.com/787621#

4:27 raek: Dranik: 1) Close parens on the same line 2) You generally don't use string operations to generate code. use syntax-quote as you have done at the other places 3) an autogensymed symbol only spans the current syntax-quote

4:28 Dranik: raek, thanks, I'll give it a try

4:28 raek: 3) can be solved by (let [sym (gensym "msg")] `(foo ... ~msg ... ~(bar ... `(baz ... ~msg ...) ...) ...)

4:29 Dranik: oh wow!!

4:29 thanks!

4:30 raek: also, code using map + anon function is often more prettily written using 'for'

4:32 Dranik: raek, thanks for your advise, I'll check it out!

4:34 raek: Dranik: I reformatted it and applied 3): https://gist.github.com/787632

4:35 beware, I have not tested this

4:35 Dranik: raek, thank, I'll try to run it

4:36 raek: hrm, I already realized an error: you need a (apply concat ...) call around for, or you can use mapcat the way you used map before

4:36 every f needs to generate two forms, so all these pairs has to be concatenated somehow

4:38 Dranik: seems like (apply concat didn't help....

4:38 raek: Dranik: you can test the macro using (macroexpand-1 '(create-object ...))

4:39 that way you will se what the code expand too

4:39 *to

4:39 Dranik: yep, doiing that

4:39 raek: gotta go, good luck.

4:40 Dranik: thanks!

4:51 Licenser: out of curiosity how is the status of clojure and databases?

4:51 LauJensen: ?

4:51 Licenser: as in what solutions exist, how 'good

4:51 ' are they compared to each other

4:52 LauJensen: Well, ClojureQL is the way to go if its relational databases. For non-relational I've only really looked at FleetDB which I really didn't like.

4:54 Licenser: I was also wonderinger about mongodb and hadoop but I am entirely not sure

4:55 since I am at the position of a fresh start I have the freedome to choose weather I go for a relational or document based DB

5:01 actualy couchdb not hadoop

5:03 pareidolia: raek: Thanks

5:03 raek: I remembery trying it once, and encountering exotic looking errors and unpredictable behaviour

5:04 raek: Or am I fooling myself? Does setting the protocol version actually do anything with clojure-maven-plugin ?

5:07 I hope I don't offend anyone with this noob question... Is it possible to define a function that takes a map, and implicitly all map keys are available as variables which evaluate to the keys' values ?

5:09 raek: it would be possible to do with a macro. if enumerating the keys is acceptable, then (let [{:keys [a b c d]} m] ...) should be sufficient

5:11 clgv: pareidolia: raek's proposal seems to be the easiest way

5:13 raek: code with "magic symbols" (i.e. variables whose binding forms are hidden) tends to be hard to read anyway

5:14 pareidolia: also, it would only be possible if the map was known at compile time.

5:15 (it = the idea in your question)

5:15 pareidolia: Ah, it's a large map

5:16 I'm comfortable with (:keyword themap), but I always wonder if there is a "better" way

5:16 clgv: yes it's the one raek showed you ;)

5:16 but you have to know the keys on compile time

5:19 pareidolia: I'm customizing the example at http://www.learningclojure.com/2010/10/generating-xml-to-make-svg-vector.html for my use

5:26 clgv: how do I include resources, like images, into my clojure project? where do I have to put them? how do I tell leiningen to include them?

5:27 raek: clgv: resources/

5:27 leiningen includes that dir by default (if present)

5:28 clgv: ok. and it's top level directory within the created jar?

5:28 raek: that dir will be on the classpath and the contents will be included in produced jar files

5:28 yes

5:28 clgv: ok thanks.

5:29 raek: if you meant that resource/foo/bar.txt will end up in <jarfile>/foo/bar.txt

5:30 it behaves as src/

5:33 pareidolia: Are spaces allowed in :keywords ?

5:38 clgv: pareidolia: I dont think so. but you can use "-"

5:40 pareidolia: I vaguely remember reading something about a special escaping notation... ah well, if anyone knows...

5:48 clgv: why would you want to make it that complicated?

5:56 pareidolia: clgv: I'm exploring borders haha

5:57 clgv: lol. you should have a look at borders of symbol names ;)

7:11 is there some version of "get" that can be used within nested maps like update-in?

7:11 e.g. (get mymap [key1 key2] default-value)

7:17 rrc7cz: if I (defmacro defn' [name params & body] `(defn ~name ~params (binding [*foo* this] ~@body))), "this" seems to bind to a var in the local namespace. What if "this" is actually a paramater in params (gen-class fns)? How do you prevent it from trying to resolve to #'somens/this and instead capture the local parameter?

7:17 mduerksen: clgv: get-in

7:18 clgv: mduerksen: thx. that seems so easy to guess, but I didnt :P

7:19 _na_ka_na_: where's clj-time repo, github gives a 404

7:21 mduerksen: rrc7cz: i'm not sure i get what you want, but havin local params in macros lets me think of mylocalvar#. example: (defmacro test [coll] `(let [f# (first coll)] (println f#)))

7:21 in that case, for f# a local symbol is generated

7:23 rrc7cz: mduerksen: but that generates a unique local symbol. I need to instead capture an existing one

7:24 mduerksen: here is the problem: I have a large number of fns that look like this (defn one [this] (binding [*api-key* (.apiKey this)] (do something)))

7:24 mduerksen: rrc7cz: ok, then i didn't understand your goal correctly, sorry

7:24 rrc7cz: mduerksen: I'd like to make a def+key macro that just wraps all the bodys in that binding form to reduce duplication

7:26 mduerksen: rcc7cz: and you need 'this' in the bodies, right?

7:28 rrc7cz: mduerksen: maybe, maybe not. These are gen-class fns, so "this" is the required first param. It can be used to pull the object's state, like @(.state this)...

7:28 mduerksen: I definitely need 'this' for the binding form to work correctly, because it pulls the object's state (.apiKey) and binds it to *api-key*

7:29 mduerksen: it all expands correctly, except 'this' is bound to #'myns/this, which doesn't exist, instead of leaving it as a symbol 'this' which captures the fn param at runtime

7:30 clgv: if "this" is visible just use "~this" and you should capture the right one, dont you?

7:30 mduerksen: rrc7cz: i'm not sure it will work, but maybe just put a ' in front?

7:31 in front of 'this, i mean

7:32 clgv: rrc7cz: try that one: (defmacro defn' [name params & body] `(defn ~name ~params (binding [*api-key* (.apiKey ~'this)] ~@body)))

7:37 rrc7cz: mduerksen: the form is already syntax quoted with a backtick `

7:38 clgv: let me try that..

7:38 clgv: rrc7cz: you should rename the macro. it causes problems in clojure 1.2 ;)

7:39 rrc7cz: clgv: really? why? they're depricating symbols in identifiers or somethign? no +?

7:39 clgv: no I took the version with defn'

7:39 that wont work here

7:39 rrc7cz: I read that as clojure 1.3, not sure why

7:39 clgv: oh, ha, yeah I know ' isn't valid. It's a haskell convention. i was just writing it as an example

7:39 clgv: I am still on stable 1.2 ;)

7:40 for: (defmacro defn-api [name params & body] `(defn ~name ~params (binding [*api-key* (.apiKey ~'this)] ~@body)))

7:41 I get:

7:41 user=> (macroexpand-1 '(defn-api one [this] (do something)))

7:41 (clojure.core/defn one [this] (clojure.core/binding [user/*api-key* (.apiKey this)] (do something)))

7:41 rrc7cz: clgv: your version works! I don't understand why though..

7:41 I thought the backtick ` quoted everything unless it was explicitly unquoted with ~

7:42 so you're quoting this... then unquoting it?

7:42 clgv: its a bit tricky. I asked that some weeks ago ;)

7:42 symbols get resolved during macroexpansion afaik

7:42 rrc7cz: clgv: well thank you, I don't think I would have figured out that trickery myself

7:43 clgv: I guess the issue is around the actual code that resolves.. for some reason it's resolving not to the local fn param, but to the ns var

7:44 clgv: you should reread what the templating syntax with the syntax-quote means

7:44 rrc7cz: okay

7:45 clgv: I got my head twisted around that too... ;)

7:45 there are actually cases where you would write something like: '~this

7:45 ;)

7:46 rrc7cz: now I feel stupid. I found this in Practical Clojure in the Code Templating section, "Also, symbols directly referenced within a syntax quote are assumed to be top level, namespacequalified

7:46 symbols and will be expanded as such."

7:46 although it doesn't mention your trick

7:47 clgv: only quoting doesnt work since it's then still part of the template-body

7:47 and gets resolved too

7:47 so you have to get it out of the template body with ~ and then quote it so that it isnt resolved.

7:49 rrc7cz: clgv: interesting. And your oposite, '~ is expanded, but then quoted so it isn't evaluated?

7:49 clgv: right. I did it for code rewriting

7:50 it was a list of clojure statements like you would put in the body of a defn

7:50 rrc7cz: okay

7:51 clgv: I learned one lesson from it: develop complicated macros step by step and macroexpand is your best friend ;)

7:52 rrc7cz: makes sense. I'm hoping I can keep this defn macro simple, skipping the optional docstring, attr-map, different artiy+bodies, etc

7:53 clgv: oh thats not that complicated since you have the clojure source ;)

7:54 you can have a look at the implementation of defn ;) I did that. but I am not supporting attributes at the moment

7:55 rrc7cz: right now I think the only fn *with extras* is multiple artify+body

7:55 so it'll need it to generate a binding wrapper for each body

7:55 so we'll see. Lot's of macroexpand for sure

7:55 I'm definitely planning on looking at the defn impl as you suggested. should make it easy

7:57 clgv: they just check the body for being a vector and then they know that there is only one paramter+body ;)

7:58 I meant they check the first element of body for being a vector...

9:34 chouser: Anyone up for a pop quiz? You can read docs now, but not after I ask the question!

9:36 tonyl: mmm.. too early for me, but shoot

9:37 chouser: heh, ok

9:37 re-find looks for a regex match in a string. What does find do?

9:38 * chouser hums the Final Jeopardy tune

9:38 dnolen: get the map entry (kv pair) out of a map by key, return nil if not found :)

9:39 tonyl: i was going to say kinda like contains?, but that was my guess

9:39 chouser: dnolen: hmph. very good.

9:39 tonyl: haven't use that function

9:41 chouser: I've used it in the past, but just now when wanting a write a function named 'find' I was suprised it was already there and couldn't remember what it did.

9:41 tonyl: hehe it happens

9:42 * tonyl needs to make a cheatsheet of all functions in clojure, then again, there is doc and find-doc

9:43 tonyl: need to hit clojure-quiz sometime this weekend

9:45 clgv: how can I extract only few KeyValuePairs from a bigger map into a standalone map?

9:45 Chousuke: (doc select-keys)

9:45 clojurebot: "([map keyseq]); Returns a map containing only those entries in map whose key is in keys"

9:46 clgv: oh thx. I was stuck on "project" which only works for sets

9:59 lpetit: morning/afternoon/evening

10:00 chouser: lpetit: indeed!

10:01 lpetit: maybe we could invent a new term for that : mae, or morafe

10:01 :)

10:01 morafev, I meant

10:02 tonyl: morafev haha

10:02 chouser: how about "greetings!"

10:03 and of course the symmetric "partings!" :-P

10:04 lpetit: chouser: yea, greetings, of course. I'll go with this for now on

10:04 chouser: :-)

10:04 well, that's solved then!

10:04 * chouser dusts his hands together and wanders off

10:05 clgv: hm if I guess right, I might get an answer to the following question: when will the next stable update for CCW be released? ;)

10:09 lpetit: clgv: actually 0.2.0.RC04 is quite stable. But it introduces features which may change/be refined, "semantically speaking" (though not so much, the last "hard work" on it will be a refinement of details of the repl UI)

10:09 clgv: so I'd say it's not "temerary" at all to install it.

10:09 clgv: but I did not answer your question :)

10:10 clgv: lpetit: I adopted the habit to install software, I depend on, only if the authors consider their release as stable ;)

10:10 lpetit: clgv: expect a new release candidate this week. Mostly correcting stuff. Then another release candidate with a new bunch of repl UI enhancements from Chas. Then maybe another RC if what Chas introduced needs to be polished a little bit more. Then we'll say "good enough" and release it

10:11 So the "merge" of the branch repl-ui into the branch "master" of ccw will probably happen during february. I hope closer to the beginning than to the end, but who knows.

10:12 clgv: lpetit: thx. that are much more detailed infos than those communicated about clojure 1.3 ;)

10:14 february sounds fine - not too long to wait ;)

10:58 digash: l

11:20 fliebel: Morning

11:21 markskilbeck: Guten morgen.

11:35 fliebel: Are there any functions for dealing with chunks directly?

11:36 jcromartie: as in chunked seqs?

11:36 fliebel: yes

11:37 Having things like first, rest, conj and map for chunks would be very nice in some cases.

11:38 jcromartie: You want to inspect the chunk itself, eh?

11:39 fliebel: yes :)

11:39 jcromartie: I don't see any "chunk" here http://clojure.github.com/clojure/

11:39 hm

11:39 interesting question though

11:39 why do you want to do this?

11:40 tomoj: (doc chunk-first)

11:40 clojurebot: "([s]); "

11:40 fliebel: Just playing around. I was wondering if it would make sense to turn some binary tree into a 32tree, sortof. In fact i could just do (take 32), but what fun is that.

11:41 jcromartie: that sounds fine to me :)

11:41 using undocumented API means it could break later

11:42 fliebel: It's not like this will end up in mission critical applications ;)

11:48 But I don wonder what type of stuff implements IChunkedSeq.

11:48 *do

11:49 tonyl: &(filter (fn [[k v]] (if (re-find #"chunk" (str k)) true false)) (ns-publics 'clojure.core))

11:49 sexpbot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

11:55 tomoj: &(map chunked-seq? ((juxt identity next) (range)))

11:55 sexpbot: ⟹ (false true)

11:57 fliebel: :)

12:05 So, if I need to take subseqs of any length from a long list real fast, is it wise to use chunks? Either directly, or by 'aligning' your data to them, and trust core functions to handle the chunks?

12:07 So, either (chunk-first), (take 32) or (take 10)

13:34 lenw: hi all

13:36 tonyl: hello

13:36 fliebel: hi

13:36 lenw: any prefs re nosql backends for clojure :)

13:37 ohpauleez: leafw: I'd use whatever backend fits your problem space. All of the major ones have at least one wrapper, interface, or library

13:37 I've used both Cassandra and MongoDB with Clojure to great success

13:38 lenw: any prefereed wrappers over couchdb ?

13:38 yeah mongo seems easy hey

13:38 fliebel: lenw: clutch

13:38 It has a Clojure view server ;)

13:38 ohpauleez: lenw: Yeah clutch is what you'll want to use

13:39 lenw: brilliant - knew i should ask you guys - thanks !

13:40 ohpauleez: np, good luck!

13:55 jweiss_: can someone point me to a github project where src/ and test/ are laid out in a "standard" way? trying to set up my own project

13:55 ohpauleez: jweiss: if you use lein or cake, you'll get the structure for free

13:56 typically it's src/project-name/file.clj and test/project-name/file.clj

13:56 technomancy: no, you can't have the same ns in src/ and test/

13:56 ohpauleez: yes, you're right

13:57 test/project-name/test/file.clj

13:57 my b

14:06 kencausey: perhaps wrongly I downloaded the 'master version' of lein and am trying to use it but even self-install chokes because it can't find leiningen-1.5.0-SNAPSHOT-standalone.jar

14:07 technomancy: kencausey: check the bottom of the readme like it says in the error message; it explains that

14:07 kencausey: Related are maven and ant pre-installation requirements? The instructions could really be clearer on what you are expected to have installed versus what lein gets for you

14:07 technomancy: which is where I found self-install, but I will read again more closely

14:07 jweiss_: is this convention of creating a file "core.clj" in the src something i should use? my lib will probably always be just a single file

14:08 it's an error handling lib, was thinking just src/error/handler.clj

14:08 fliebel: I am bothered by the same question as jweiss_

14:09 I even did just src/my_file.clj sometime.

14:10 technomancy: kencausey: it's best to keep a lein-stable or lein-1.4 around to sourdough-bootstrap development versions

14:11 ohpauleez: jweiss: In the case you have a single file, you can also do this:

14:12 src/project-name.clj

14:12 sometimes it's helpful to do this:

14:12 src/project-name/file.clj and make a src/project-name.clj

14:12 that has all the active endpoints/actions/functions that the user actually needs

14:13 it is convention to have a core.clj, but if it doesn't fit the project, don't do it

14:13 core is for the underlying functions and operations... the core to your app or lib

14:13 kencausey: technomancy: OK, doing as suggested

14:13 ohpauleez: sometimes projects have many "cores," in that case, it doesn't make sense and you can do something like this:

14:14 src/project-name/backend/core.clj ... src/project-name/middleware/thismiddleware.clj etc

14:15 melipone: hello

14:15 technomancy: kencausey: cool; suggestions for clearer wording are welcome

14:15 ohpauleez: jweiss_: fliebel ^

14:15 does that make sense?

14:16 lpetit: ohpauleez: of course, it would be src/project_name/file.clj, not src/project-name/file.clj

14:16 ohpauleez: right right

14:18 kencausey: technomancy: ok, first, did I get this right?: downloaded standard lein, put at ~/bin/lein-old, cloned lein github repo and ran lein-old deps in it. Got to intended location for new project and type lein (symlink to leiningen/bin/lein) new project, etc Exception '...*jure names no longer allowed'

14:18 s/etc/got/

14:18 sexpbot: <kencausey> technomancy: ok, first, did I get this right?: downloaded standard lein, put at ~/bin/lein-old, cloned lein github repo and ran lein-old deps in it. Got to intended location for new project and type lein (symlink to leiningen/bin/lein) new project, got Exception '...*jure names no longer allowed'

14:19 kencausey: hmm, I guess I should clarify that the actual name of the project was ClojureInAction as I'm going through the book

14:19 perhaps I should believe the error message even if I wonder why

14:19 lein new cia seems fine

14:21 technomancy: oh... the *jure regex needs to be case-insensitive; doh

14:24 having "clojure" in the name is fine, but the regex is just twitchy there wrt case.

14:24 anyway, you have the right idea for lein-old

14:25 kencausey: technomancy: Regarding the wording it might be clearer if you clearly stated that lein can install everything other than Java (if that is true) and maybe clarify what version of Java is required for Clojure/Lein

14:25 technomancy: been using Clojure for years and I don't think I'll ever remember case-insensitive regex syntax =(

14:25 /foo/i is so much nicer

14:25 Raynes: (?i)

14:25 technomancy: thanks

14:25 kencausey: glad found a corner case then I guess ;)

14:29 jweiss_: ohpauleez: good info, thanks

14:29 ohpauleez: jweiss_: np, happy to help

14:30 fliebel: What is the fastest way to take 32-ish items from a seq? subvec and chunks seem to be able to do this, but take and partition are all cons-based(so one-by-one recursion?)

14:44 Can anyone give me a useful example of rsubseq?

14:49 lpetit: ,(doc rsubseq)

14:49 clojurebot: "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a reverse seq of those entries with keys ek for which (test (.. sc ...

14:50 lpetit: fliebel: if the only assumption you can make on the object you have is that it's a seq ...

14:53 kencausey: technomancy: is http://groups.google.com/group/clojure/browse_thread/thread/c178bed30fd9d704# still valid?

14:53 technomancy: I'm trying the trunk version of package.el in 23.2

14:55 I tried to perhaps install too many things as it doesn't appear to get past slime, there is a message "url-http-parse-response: Trying to parse HTTP response code in odd buffer: *http repo.technomancy.us:80*"

14:57 * kencausey tries to install them one by one

14:57 technomancy: yeah, there are still a few bugs in package.el when the HTTP connections are shaky

14:57 you could also try marmalade as the source: http://technomancy.us/144

14:58 kencausey: seems like it is working this way

14:58 technomancy: yeah, stabilizing that is on my list =\

15:32 kencausey: What have I done wrong if lein is missing swank?

15:32 mefesto: kencausey: did you add a dependency for it in your project.clj?

15:32 kencausey: this being dev lein

15:33 oh, yeah

15:33 * kencausey self-slaps

15:36 mefesto: Is there a preferred set of tools for piecing together a restful json server? Right now I'm messing with (ring, ring-json-params, compojure, ring-jetty-adapter) but also saw moustache and aleph as another possible route.

15:44 melipone: help with enlive/lein

15:44 ohpauleez: melipone: What are you specifically having an issue with?

15:45 melipone: I'm trying up enlive with lein repl and I get this message: Var *classpath* not marked :dynamic true, setting to :dynamic. You should fix this before next release!


15:45 not sure if it's an enlive or lein message

15:45 how do I set variables like that?

15:46 ohpauleez: it has to do with you using Clojure 1.3, which changed the def behavior

15:46 it's just a warning

15:47 if you use Clojure 1.2 the warning will go away

15:49 melipone: okay thanks!

15:49 is it the right place to ask newbie questions?

15:49 ohpauleez: melipone: totally!

15:49 pdk: any type of questions roll here, i don't think there's a separate beginners channel

15:50 melipone: great!

15:50 fliebel: Even non-Clojure questions, sometimes *hides*

15:53 ohpauleez: fliebel: Do we need to talk about window managers again?

15:53 haha :)

15:54 tonyl: or politics... :P

15:54 fliebel: ohpauleez: I don't think OS X does window managers… I was thinking algortithms.

16:03 melipone: clojure-contrib was missing from enlive's project.clj ...

16:04 fliebel: melipone: If you are using 1.3, there is no such ting ;)

16:05 clojure-contrib has been split up into separate projects.

16:05 melipone: I replaced clojure 1.3 with 1.2

16:06 Scriptor: wait, there's no clojure-contrib in 1.3?

16:07 fliebel: Scriptor: Not in the classical sense. There is a package that contains all the new projects, and you can get all the parts separately.

16:08 melipone: fliebel: isn't it like that already?

16:08 fliebel: I mean you can specify :only to get what you want

16:09 amalloy: melipone: :only is part of (require) - fliebel is talking about adding it as a project dependency in maven or project.clj

16:10 fliebel: amalloy: Ah, thanks, I was thinking I had missed something in Leiningen ;)

16:14 lazy1: Can someone explain why I get NullPointerException when running iterdir (https://gist.github.com/788685) on an empty directory?

16:16 S11001001: (branch? nil) => NPE

16:18 lazy1: Thanks!

16:27 melipone: what's good for parsing html in clojure? enlive might be overkill ...

16:27 ohpauleez: melipone: enlive is the best in my opinion

16:27 are you scraping for something?

16:27 melipone: yes, web scraping

16:28 ohpauleez: I think enlive is the best clojure solution for web scraping, but there are wrappers for tagsoup in clojure

16:28 you can also use any java library

16:29 lazy1: melipone: https://github.com/antoniogarrote/apricot-soup

16:38 brehaut: melipone: re ohpauleez's comment about using any java library, enlive uses tagsoup under the hood i believe

16:39 melipone: so even if you dont use enlive itself, it may prove a useful resource for just using tagsoup from clojure

16:40 melipone: okay, I'll give enlive another try. I found another tutorial on the enlive wiki

16:40 brehaut: melipone: dont be put off by the somewhat imposing first impression enlive gives off; its actually really easy to use. david nolen's tutorial is a great starting point

16:41 LauJensen: melipone: There is no reasonable alternative to Enlive and Enlive is in fact fantastic

16:43 ohpauleez: these are all facts

16:43 :)

16:43 melipone: the problem is that I'm learning clojure as I go along

16:44 amalloy: melipone: if learning clojure is a "problem" you live a pretty good life

16:44 brehaut: melipone: just start small. dnolen's tutorial starts with scrapping anyway.

16:45 LauJensen: melipone: You can check out my blog, my most recent post is about Enlive, but I use it in a couple of other posts as well, http://www.bestinclass.dk/blog.html

16:45 I always try to explain everything so carefully that even amalloy can understan

16:45 d

16:46 tonyl: even me

16:46 amalloy: LauJensen: i'm home sick from work today and actually reading your blog right now. there are too many damn entries though

16:46 LauJensen: amalloy: hehe, oh, sorry about that - from which end should I start deleting? :)

16:46 melipone: for example, the "->" macro just threw me

16:47 Raynes: melipone: Did the comp function catch you?

16:48 melipone: okay, comp is not so bad

16:49 LauJensen: -> ->> -?> -?>> -=@?> and comp are all easy once you see a couple of examples

16:49 brehaut: Lau, -=@?> ?

16:49 tonyl: juxt still blows me in how weird it looks but the many uses you can have for it

16:50 LauJensen: yea juxt is pretty cool

16:50 brehaut: juxt is great :)

16:50 melipone: yeah, it's weird

16:50 LauJensen: brehaut: -=@?> is just a speeding fish or something

16:50 brehaut: haha

16:50 Raynes: tonyl: juxt blows you, eh? ;)

16:50 tonyl: indeed haha, that is why i keep using it

16:51 * tonyl meant blows my mind

16:52 amalloy: &'-=@?>

16:52 sexpbot: ⟹ -=

16:52 brehaut: fnil boggles my brain. amalloy showed me some examples of it in use, but its not gotten wedged into my head enough for me to actually have usecases

16:53 amalloy: LauJensen: sadly that's not a legal symbol. if it were i'd love for you to write a useful function with that name, then write a blog post about it

16:53 LauJensen: amalloy: Did you see my implementation of factorial 5? I might actually have used that symbol in there

16:53 ,(letfn [(!-?>[&$ &!](if(>,&!,1)(!-?>@(->>,&$,(*,&!)ref)(->,&!,dec))&$))](!-?>,1,5))

16:53 clojurebot: 120

16:54 LauJensen: So Clojure is quite easy once you get the hang of it

16:54 brehaut: Lau, this is #clojure, not #apl

16:54 amalloy: LauJensen: lol

16:54 LauJensen: brehaut: I was inspired by J actually :)

16:54 (I love J)

16:54 brehaut: haha

16:54 amalloy: i don't see that one in your factorial article

16:54 LauJensen: amalloy: It was something I posted on twitter a while ago

16:54 brehaut: amalloy, link please

16:55 amalloy: brehaut: http://www.bestinclass.dk/index.clj/2009/09/scala-vs-clojure-lets-get-down-to-business.html

16:55 brehaut: cheers

16:55 amalloy: LauJensen: we should start a business cross-pimping blogs

16:55 LauJensen: If you're interested in J, check out this article where I explain some funky J code

16:55 http://bestinclass.dk/index.clj/2009/11/mind-games-ascension.html

16:55 And then this one, where I show how it inspires concise Clojure code

16:55 http://bestinclass.dk/index.clj/2009/11/life1d-in-clojur.html

16:55 amalloy: Im in! :)

16:56 brehaut: i feel that i need to write another clojure blog post, but im currently lacking ideas

16:56 LauJensen: brehaut: You should definitely write about ClojureQL and how it has improved your quality of life

16:56 I'd read that

16:56 brehaut: LauJensen: hah yes :) i'll be doing that once i have my site ported over properly

16:56 LauJensen: brehaut: Im fine with that ... if your site is up and running by monday :)

16:56 brehaut: haha

16:57 its up and running now!

16:57 just not with clojureql

16:57 LauJensen: :(

16:57 I've seen it already. Pretty layout, hard to read

16:57 brehaut: hah yeah, hacker news hates me

16:57 LauJensen: Like to opposite of amalloy who's easy to read but hard to look at :)

16:57 brehaut: haha

16:57 LauJensen: s/to/the

16:57 sexpbot: <LauJensen> Like the opposite of amalloy who's easy the read but hard the look at :)

16:58 brehaut: ive discovered its really monitor sensitive

16:58 amalloy: LauJensen: that actually made your sentence less readable :P

16:58 LauJensen: brehaut: Its not though, its because you have the same background as your text color :)

16:58 Quite moronic when you stop and think about it :D

16:59 brehaut: LauJensen: black on white is the same background color as text color :P just happens to have a larger difference in lumiance

16:59 (1 rather than 0.45 for reference)

17:00 LauJensen: brehaut: Im beginning to understand where you're going wrong with this whole design thing

17:00 jweiss_: anyone ever get this error in the clojars UI? "Thundering typhoons! I think we lost it. Sorry!"

17:01 i scp'd my pom and jar to it, and the ssh output shows that it appeared to work. but i get the above error if i try to click on it on the clojars webpage

17:02 brehaut: in any case, monitor does have a huge effect; the effective contrast that a given monitor can produce becomes reallly significant when the contrast between text and background is small. some cheap panels also make yellows quite vicious

17:04 LauJensen: brehaut: Thats true. Ive had some awful experiences with that

17:04 brehaut: LauJensen: yeah. i checked out my site on my former coworkers cheap ass dell panels

17:04 result is eye bleeding

17:08 LauJensen: i am trying to make the design more readable though. but i want to keep the visual identity at the same time

17:09 LauJensen: brehaut: Okay, so I say keep the URL and change the design completely :)

17:09 brehaut: hahaha

17:10 its more likely that i'll eventually change to not-yellow

17:10 but leave the rest of the design

17:11 LauJensen: That sounds perfect since its the yellow thats causing the problems

17:12 clizzin_: soooo often during development i'll do some refactoring that involves breaking some function f out from ns1 into ns2 and having ns1 use ns2, and that results in namespace conflicts because f has already been defined in ns1. the only solution i know of is to restart the jvm. does anyone out there have a better solution?

17:13 S11001001: clizzin_: ns-unmap

17:14 clizzin_: S11001001: is there a way to unmap all bindings in a given ns?

17:15 S11001001: another common problem is that i forgot to set up the proper use/requires, and so some code is still referring to the old functions that i've deleted/moved and i just don't realise it until something goes wrong. being able to clear the namespace wholesale and recompile would be nice.

17:15 as opposed to manually remembering each function i've deleted/moved

17:17 amalloy: clizzin_: (doseq [[f _] (ns-publics *ns*)] (ns-unmap *ns* f)) feels about right

17:18 and hey look at that, i just tried it and it's exactly right

17:19 clizzin_: amalloy: awesome, didn't know about ns-publics. tahnks!

17:19 thanks*

17:21 mreynolds: Newb question : I'm seeing a defmethod without finding the defmulti in the same file. What's the best way to find the defmulti associated with the defmethod? (I'm using emacs/swank, if that helps)

17:21 technomancy: mreynolds: M-. should do it

17:21 amalloy: mreynolds: M-. on the multimethod's name might work?

17:22 mreynolds: It's asking for a tags table, which I don't think I have setup

17:22 amalloy: mreynolds: you'll have to compile the file

17:22 mreynolds: Or, the defaults aren't working, since it can't find the tags file

17:22 ahhh, k, I'll start from there

17:22 technomancy: you must not have slime connected

17:22 amalloy: that is, have slime connected, then C-c C-k the file; then M-.

17:23 mreynolds: technomancy: I don't, not in this one. I'm debugging the library at the same time that I'm working on my code (fixing docs mostly)

17:23 K, I'll setup another instance

17:24 thanks all

17:34 melipone: okay, I'm getting the hang of it, slowly ... more tomorrow, bye

17:39 hiredman: ,(.replaceAll "foo\bar" "\\\\" "/")

17:39 clojurebot: "foo\bar"

17:39 hiredman: ,(.replaceAll "foo\bar" "\\" "/")

17:39 clojurebot: java.util.regex.PatternSyntaxException: Unexpected internal error near index 1

17:39 \

17:39 ^

17:39 hiredman: clojurebot: thanks dude

17:39 clojurebot: No entiendo

17:39 amalloy: hiredman: "foo\\bar"?

17:40 technomancy: hiredman: this is how you do it, bro: https://github.com/technomancy/lein-tar/commit/bfef514ff36542a6c036fceb5f6471da7f9587ac

17:40 hiredman: cool story

17:56 frank`: good night

18:01 kcl: who

18:01 whois

18:06 S11001001: I too am a member of the secret society of those who have written \\\\\\\\ in earnest for production code

18:06 oops

18:08 keithl: Does anyone know if the moustache micro-framework is dead? Seems no checkins since May.

18:10 dnolen: keithl: I think the feature set was always meant to be quite minimal. but cgrand has been quite busy of late, when he has a free moment I think he tends to work on parsley.

18:10 keithl: the only thing I'd like to see added to moustache is reverse lookup.

18:10 keithl: dnolen: It has all the features I need - was wondering if it had issues with 1.2.

18:11 dnolen: What is parsley if I may ask?

18:11 dnolen: keithl: I don't think so.

18:11 a Clojure parser

18:11 ohpauleez: keithl: I haven't had any issues using it with 1.2

18:12 keithl: ohpauleez: Thanks. I just need to build a small web service, and it seemed like a good approach.

18:12 ohpauleez: and yes, moustache's feature set is pretty small and quite solid, so besides some nice-to-haves, it's a pretty complete package that doesn't really need continual work

18:12 keithl: It's my favorite for most clojure web development, I even wrap it occasionally to use with aleph

18:14 keithl: Hmm - had not looked at aleph. Looks interesting.

18:14 I used compojure for a small project, but its changing quite fast and I find that I struggle a bit knowing how to approach some things.

18:14 Newbie to clojure - and not a java person generally.

19:17 zakwilson: Is Moustache displacing Compojure in new projects?

19:20 keithl: zakwilson: It is for me, but maybe just for this small project. Compojure is quite nice, but as I mentioned, it is changing pretty rapidly and the docs are not up to date.

19:20 zakwilson: As I understand it, both mainly serve to map URLs to handlers.

19:21 keithl: zakwilson: I think that's right. Just more capabilities in Compojure - more sophisticated route handling, etc.

19:22 zakwilson: I see. I think I'll try sticking with Compojure and only investigate switching if I have problems.

19:22 keithl: Makes sense I think - but I am no expert :-)

19:23 The one thing that bugged me - again related to changes - was that I ended up doing a lot of googling because the api changed so much.

19:23 That really was the only issue I had with it.

19:26 zakwilson: To be expected with a small somewhat experimental thing.

19:26 keithl: yup

19:26 bleeding edge, as it were.

19:27 Went through the same things w/rails - first project was on 0.13

19:27 zakwilson: On that subject... I wonder if everything I need works with 1.3 now.

20:18 currentB: if I have an ordered sequence of dates (longs) from varying time intervals (ie there might be 10 one day then three the next) is there an easy way to partition them by a given time interval?

20:18 hiredman: group-by?

20:20 currentB: hmmm just trying to wrap my brain around what the grouping function would have to be

20:22 it could return what nth item the date would belong to, ok I think that could work, thanks!

20:24 amalloy: currentB: like you want to group them by day of week regardless of day of month?

20:25 currentB: grouping by 24hr period is all that really matters, actually if possible I'd like to keep it general, for example allowing the function to take as parameters the sequence of longs and the amount of milliseconds to do the grouping by

20:26 amalloy: currentB: then it sounds like you just want div

20:28 &(group-by #(div % 86400000) (repeatedly 20 #(rand-int (* 10 86400000))))

20:28 sexpbot: java.lang.Exception: Unable to resolve symbol: div in this context

20:29 amalloy: &(group-by #(rem % 86400000) (repeatedly 20 #(rand-int (* 10 86400000))))

20:29 sexpbot: ⟹ {43091328 [43091328], 85823489 [777023489], 19147458 [710347458], 48212099 [134612099], 34379782 [725579782], 29852840 [461852840], 36766920 [641566920], 37551370 [555951370], 4857802 [4857802], 41098220 [386698220], 64125390 [841725390], 47243887 [306443887], 752616... http://gist.github.com/789091

20:29 currentB: ok sweet that's similar to what I was messing with, thanks!

20:29 amalloy: er, damn it, quot

20:29 &(group-by #(quot % 86400000) (repeatedly 20 #(rand-int (* 10 86400000))))

20:29 sexpbot: ⟹ {0 [60216224], 1 [115823748], 2 [245325431 205820251 188400044 185196259 196982624], 3 [266483468], 4 [411494513 379197832], 5 [470114010 470576693], 6 [588959862], 7 [649107250 633158285], 8 [744349997 776718958], 9 [818622453 835503570 790813983]}

20:30 currentB: yes, even better thanks!

20:31 amalloy: lol, "even better" in the sense that it works instead of the complete nonsense i said earlier

20:31 currentB: haha exactly

20:50 zakwilson: I just tried updating my version of hiccup.core and I'm getting "as-str does not exist" when I try to use it in my namespace.

21:02 pdk: (doc :>>)

21:02 clojurebot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to clojure.lang.Symbol

21:03 amalloy: &(doc ->>)?

21:03 sexpbot: ⟹ "Macro ([x form] [x form & more]); Threads the expr through the forms. Inserts x as the last item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the last item in second form, etc."

21:08 amalloy: zakwilson: that function is in clojure.contrib.string, right? perhaps hiccup is old and expecting it somewhere else?

21:08 pdk: say

21:08 if you use recur outside of a loop form

21:09 will it still be tco'd

21:09 amalloy: pdk: yes, it recurs to the innermost containing loop or function

21:09 zakwilson: amalloy: actually, hiccup is new and expects it in clojure.contrib.java-utils. I just reverted to the old version.

21:09 pdk: so loop is pretty much optional

21:09 and even if i'm recurring on a function defined at toplevel with defn it'll still tco it

21:09 amalloy: pdk: um. yes to your second statement; your first is pretty confus{ed,ing}

21:10 i mean, loop is never "necessary" because you could use a new anonymous function instead, but the same could be said of let

21:10 pdk: i.e. if i'm defining a function with defn and use recur within that function

21:11 there's no arbitrarily limits on which cases it'll tco the function it's called within as long as it's a proper tail call

21:11 amalloy: pdk: as long as it's a *self-recursive* tail call. there's no provision for tail-calling some other function

21:13 (fn [x] (when-not (= x 10) (recur (dec x))) will work fine, yes

21:13 but if you want to recur to some level other than the top one you need to declare either a new function or a new loop marker

21:14 pdk: hmm ok

21:19 amalloy: pdk: here's an example of loop being used because it would be inconvenient otherwise: https://github.com/liebke/incanter/blob/master/modules/incanter-core/src/incanter/distributions.clj#L195

21:20 hope it helps; i'm afk a while

21:52 qbg: Hmm... Cliff Click thinks languages on the JVM should expose primitives.

21:55 brehaut: qbg: link?

21:55 qbg: http://www.infoq.com/interviews/click-gc-azul

21:55 He has also mentioned it in the past

21:56 That link also has a ton of awesome in it

21:56 brehaut: cheers

22:08 dnolen: qpg: are you skeptical of exposing primitives?

22:08 qbg: I've grown to love them

22:09 They aren't a hard concept at all; a ton of other languages do the same thing, only worse

22:09 e.g. Java

22:10 dnolen: qbg: ?, who think primitives are a hard concept ?

22:10 qbg: My main problem is with the current implementation of primitive function support (it is broken in a few ways)

22:10 dnolen: That is the feeling I get when I read messages on the group freaking out about it

22:11 The limit of 4 args is somewhat disappointing

22:11 Also, I think there is a bug if you type hint the return of the function to be a subtype of Object

22:12 hiredman: ugh

22:13 blogure? who did that?

22:13 qbg: hiredman: At least it isn't blojure

22:14 danlarkin: hotdogsladies: This is pretty cool.

22:14 In Vi?

22:14 pardon me

22:15 dnolen: qbg: haven't seen that bug. I have no problem w/ the 4 arg limitation tho. Beats bleeding your eyes with type coercions or writing crazy macros to tag symbols everywhere pre 1.3.0 .

22:16 qbg: dnolen: It existed a while back at least; it only appears if the return type is a subtype of Object and one of the positional arguments is a primitive

22:17 I remember getting an AbstractMethodError when I tried to evaluate the defined function

22:22 Try this: (defn foo ^List [^long x] (doto (ArrayList.) (.add x)))

22:23 (foo 5) gives me AbstractMethodError user$foo.invokePrim(J)Ljava/lang/Object; user/eval7

22:24 dnolen: qbg: ah yeah that makes sense, not a bug, there's no interface that can match that.

22:24 to discard ^List would be a lie.

22:25 hiredman: I'd try (defn ^List foo …

22:26 qbg: defn should at least give an exception, or the compiler returns Object and at the call sites it is cast/whatever appropriately

22:29 dnolen: qbg: what hiredman said.

22:29 type hints before the arg list are only for hinting primitive fns.

22:30 hiredman: basically the primitive type hint way and the non-primitive type hint mechanism haven't been unified yet

22:30 dnolen: or that's what I recall anyhow.

22:32 qbg: Hmm... If I put the ^List on foo, the type information isn't propagated to the users of foo

22:33 Also (.add ^List (foo 5) 4) generates a reflection warning, but (let [^List x (foo 5)] (.add x 4)) doesn't

22:35 dnolen: qbg: huh, I don't see a reflection warning.

22:35 qbg: Do you have *warn-on-reflection* on?

22:36 dnolen: qbg: yes

22:36 qbg: I get it on the latest master

22:36 dnolen: (do (set! *warn-on-reflection* true) (.add ^java.util.List (foo 5) 4))

22:36 qbg: Don't do it in a do

22:39 dnolen: there's nothing wrong with the do. Definitely an issue with the way primitive fn's get compiled.

22:40 still question how much of a legitimate issue that is, the example is questionable. More likely you'd be returning a gvec, which doesn't need a type-hint anyway.

22:41 brehaut: how on earth did i achieve things before multimethods

22:58 pdk: would binding be an appropriate alternative to letfn if i want to define things other than exclusively functions within the binding form

22:59 say if i wanted to define some recursive functions locally a la letfn but i also wanted to define some objects in the same let/binding form that weren't functions

23:00 amalloy: pdk: no binding is crazy there

23:00 you just want let

23:01 pdk: hmm

23:01 amalloy: &(let [x 1 f (fn [arg] (+ arg x))] (f 10))

23:01 sexpbot: ⟹ 11

23:01 pdk: in this case i'd want f in that example to be recursive

23:01 that's the rub

23:01 qbg: Self recursive only?

23:01 pdk: yep

23:02 qbg: (fn f [arg] ...)

23:02 f will be the name of the fn it the fn's body

23:02 pdk: oh cool beans

23:02 didn't know you could name a fn from within

23:03 amalloy: &(let [! (fn ! [num] (if-not (pos? num) 1 (* num (! (dec num)))))] (! 10))

23:03 sexpbot: ⟹ 3628800

23:03 a_strange_guy: &((fn self [x] (if (<= 1 x) x (self (- x 1) (- x 2)))) 6)

23:03 sexpbot: ⟹ 6

23:03 a_strange_guy: &((fn self [x] (if (<= x 1) x (self (- x 1) (- x 2)))) 6)

23:03 sexpbot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: sandbox9236$eval11185$self

23:04 a_strange_guy: &((fn self [x] (if (<= x 1) x (self (+ (- x 1) (- x 2))))) 6)

23:04 sexpbot: java.lang.StackOverflowError

23:04 qbg: &((fn self [x] (if (<= x 1) x (+ (self (- x 1)) (self (- x 2))))) 6)

23:04 sexpbot: ⟹ 8

23:04 a_strange_guy: bleh, that happens at 5 in the morning...

23:21 amalloy: LauJensen: you around? http://www.bestinclass.dk/index.clj/2009/10/python-vs-clojure-reloaded.html looks really wonky. i can't read the code examples

23:21 or maybe i can, in which case i need to stab my eyes out; tell me or="or" log10="log10" isn't an actual code snippet

Logging service provided by n01se.net