#clojure log - Sep 03 2011

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

0:00 livingston: jblomo: that's a little wired but not that odd.. why not just switch on type or use dispatch

0:00 or just make your caller call list

0:01 jblomo: i usually like functions that are flexible and just do what i want

0:01 livingston: (it's not that odd because a recursive function might work like that)

0:01 jblomo: i'll do a sanity check to make sure i haven't written something wrong, thoguh :)

0:02 amalloy: that's a good point, livingston

0:02 clojurebot: please cancel my previous accusations of wrong-ness

0:02 clojurebot: Titim gan éirí ort.

0:02 livingston: but then you'd have a switch right at the top is this one things or many?...

0:03 amalloy: livingston: depending on the sort of recursive function, i'd make it a protocol

0:03 livingston: why does everyone want to shove everything in an object...

0:04 amalloy: livingston: who said? see https://github.com/clojure/data.xml/blob/master/modules/xml/src/main/clojure/clojure/data/xml.clj#L196

0:05 it's just polymorphism based on the type of the argument, without the gross/slow `switch` at the top

0:05 livingston: that's to make existing objects seq-able, that's fine. but if you just have lists of stuff that's perfectly fine

0:06 amalloy: often you're right, which is why i said "depending on the type of recursive function"

0:06 livingston: amalloy: some kind of recursing on item/list is still going through dispatch ... you're not saving anything (there's no way the compiler knows ahead of time how many are in your list etc.)

0:07 I'm just near to much java - the kingdom of nouns and all ;)

0:07 amalloy: livingston: that's not exactly true. the jvm can dispatch on type faster than you can do an if/else and dispatch yourself

0:08 maybe if there are only two types involved, seq/string, then that's not true

0:08 but in general if you're dispatching on type and you care about speed, you should let the jvm get involved

0:08 livingston: I'm inclined to say that's crazy how could that be, but everytime I've done that with clojure I'm likely to be wrong, so .. ok

0:09 amalloy: most of the time at least one of those statements is false, so i don't bother with protocols

0:09 livingston: oh sure if it can turn it into a jump-table maybe

0:09 amalloy: right

0:09 livingston: it can in fact do even better

0:10 livingston: then you pay for hashing. in some good CL implementations you could scan 30 items in a list before a hash got faster

0:10 amalloy: get the JIT involved and say "hm, this function has been called a thousand times, and EVERY TIME x was an instance of List. i'll just inline a jump to List.foo, and leave a note that if someone ever passes in a non-List i need to recompile"

0:11 it's all magic to me, of course, but i understand it does things like that regularly

0:12 livingston: compilers are smart

0:13 amalloy: yeah, and JIT compilation can optimized based on runtime information

0:33 solussd: If I want to extend array-map and hash-map, do I extend the java.util.map interface?

0:34 amalloy: i think the first thing you do is ask yourself what you mean by "extend"

0:34 livingston: ,(doc hash-map)

0:34 clojurebot: "([] [& keyvals]); keyval => key val Returns a new hash map with supplied mappings."

0:34 solussd: amalloy: with a protocol ?

0:35 amalloy: then no, extend it to clojure.lang.IPersistentMap

0:35 solussd: excellent. thanks!

0:35 amalloy: solussd: see ##(supers (class {}))

0:35 lazybot: ⇒ #{clojure.lang.APersistentMap clojure.lang.Associative clojure.lang.IObj clojure.lang.AFn java.lang.Iterable java.io.Serializable clojure.lang.IPersistentMap clojure.lang.MapEquivalence clojure.lang.Counted clojure.lang.IMeta java.util.concurrent.Callable java.lang... https://gist.github.com/1190567

0:35 amalloy: pick the one that most closely resembles what you want to extend, and go from there

0:36 solussd: makes sense

0:36 and wow, that's a lot of interfaces, etc

0:36 amalloy: clojure loves interfaces, yeah

0:39 gaze__: Hey, what would be the best way to do a sort of message queue thing in clojure?

0:40 a la erlang message passing

0:40 livingston: could you be more specific "a sort of message queue thing"

0:40 gaze__: yeah sorry that was pretty nonspecific, haha.

0:40 livingston: you could probably use an atom

0:42 solussd: what's the 'isa?' equivalent to check if an object implements an interface or protocol?

0:43 amalloy: solussd: turn that into two separate questions: interface, or protocol?

0:44 solussd: interface

0:44 amalloy: isa?

0:44 solussd: more generally, I want to know if something is a map or a list/vector/seq

0:44 amalloy: &(doc map?)

0:44 lazybot: ⇒ "([x]); Return true if x implements IPersistentMap"

0:44 solussd: ,(isa? [] clojure.lang.IPersistentCollection)

0:44 clojurebot: false

0:45 amalloy: &(isa? clojure.lang.IPersistentCollection [])

0:45 lazybot: ⇒ false

0:45 amalloy: oh right

0:45 instance?

0:46 solussd: isn't that just for classes?

0:46 ,(instance? clojure.lang.IPersistentCollection [])

0:46 clojurebot: true

0:46 amalloy: interfaces are classes

0:46 solussd: ;)

0:46 amalloy: &(class clojure.lang.IPersistentCollection)

0:46 lazybot: ⇒ java.lang.Class

0:51 amalloy: livingston: btw, your remark that people want to put everything in an object reminded me of http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/aop/framework/AbstractSingletonProxyFactoryBean.html

0:53 livingston: amalloy: I don't know what that is but just reading the name of that thing makes me agitated if not angry

0:53 amalloy: i don't think anyone knows what it is, or they would never have written it

0:53 http://www.classnamer.com/ is a less-painful, more-fun take on the same thing

0:54 livingston: I like how the doc starts with "convenient..."

0:54 ok that thing is awesome...

0:59 thanks everyone, I'm out of here.

1:00 jblomo: is there a way to stick a primitive long into a map? I keep find it converted

1:00 boxed

1:00 amalloy: no

1:18 gaze__: is there any way to turn a quoted sexp into a string an vis-versa?

1:19 amalloy: &(doc pr-str)

1:19 lazybot: ⇒ "([& xs]); pr to a string, returning it"

1:19 amalloy: &(doc read-string)

1:19 lazybot: ⇒ "([s]); Reads one object from the string s"

1:20 gaze__: ahh, thanks a bunch :D

1:20 I'd like to try and come up with a way to have a really natural interface for storing that I want to call a function in a database, and then having it read that record out with all the arguments and actually call it

1:21 should be pretty simple, right?

1:38 actually wait... pr-str gives me some funky #<blah$something blah$blah@0xblah> which would seem to imply it cares about where that bit is loaded

1:38 so if I kill the vm, restart it, reload that function, that string won't actually get me back to the same function, will it?

1:38 amalloy: functions are not readably-printable

1:39 especially not closures

1:40 gaze__: I don't care so much that it's readable... I just want to store a blob somewhere that allows me to call that function again with say... no environment.

1:40 do I wanna write a macro like (defresumable name [args] contents) that defs the function as well as adds an entry to a table somewhere?

1:41 amalloy: closures already are what you want, except that they're not readable

1:43 gaze__: readable?

1:43 amalloy: from a string

1:44 closures are already "resumable" from within a single VM, and just writing some crap to a table somewhere isn't going to make your function "resumable" from a different VM

1:45 gaze__: sorry, I don't mean resumable... that was a really bad choice of words. Basically this is just a mechanism to ensure that if the VM dies in the middle of a function, when I start the program back up, that function will get started from the beginning again.

1:45 with the same set of arguments

1:46 that's what I meant to set out to do from the beginning

1:47 say I have a system designed to transcode videos or something. If a web user comes in, uploads a file, the raw file is sitting somewhere... and then the app calls (transcode "/path/to/video.avi"), that should start and complete. If there's a power outage, I want that transcoding to still happen.

1:49 so if there's a table somewhere with "transcode", "/path/to/video.avi" somewhere that gets scrubbed on startup, etc. etc.

1:52 amalloy: then don't store functions. just create a simple schema for "pending tasks"

1:53 pending.clj => {:tasks {1341 {:type :transcode :args "/path.avi"}}}

1:55 gaze__: it'd just be nice to have an interface where I can sorta (deftask transcode [args] (do stuff)), and then (invoketask transcode "/path.avi"), and all the bookkeeping is handled for me

1:56 I mean, isn't the lispy way to do it to create a ton of macros and make it all nice and transparent? :D

1:57 amalloy: so do that. but you still need a storage schema, and just storing functions or code isn't going to be a good one

1:58 gaze__: oh no no, the idea was never to store the function or code, just a way to get back to it.

1:58 what I wanted was to be able to do ((read-string "println") "hello")

1:59 only, instead of println, it'd be some stuff from that table, and instead of "hello", it'd be the stored args.

2:57 "java.lang.ArrayIndexOutOfBoundsException: 1 [Thrown class clojure.lang.LispReader$ReaderException]"

2:57 from the interpreter

2:57 would be a bug, yes?

3:02 hiredman: doubt it

3:02 (well, yes a bug in your code, sure)

3:14 amalloy: &(read-string "{x}")

3:14 lazybot: java.lang.ArrayIndexOutOfBoundsException: 1

3:16 amalloy: gaze__: ^

8:00 nizze: Hi!

8:00 Why clojure does not have [1..100] syntax for creating vectors?

8:03 Netpilgrim: nizze: Hi. I guess (range 1 101) does what you want. Not short enough?

8:03 nizze: Netpilgrim: thanks I know about (range 1 100)

8:03 I'm just curious

8:03 Netpilgrim: nizze: And if it has to be a vector: (vec (range 1 101))

8:03 nizze: :)

8:05 Could I write a macro to impelment [1..100]?

8:05 Or actually 1..100

8:06 Netpilgrim: nizze: The language designers probably wanted to keep the syntactic sugar to a minimum. And in this case it wouldn't really be a big improvement.

8:06 nizze: Netpilgrim: Okay, thanks :)

8:06 What I like about clojure compared to scheme is that it has sugar

8:06 Netpilgrim: nizze: I have no experience with macros but I think they have to be of the form (macro-name …) like function calls.

8:06 nizze: Easier to read.

8:07 Okay

8:07 Netpilgrim: nizze: I'm still very new to the language, and I've just fallen in love with -> and ->>. :)

8:07 nizze: Yeah, those are cool, you should check .. as well :D

8:09 Netpilgrim: Isn't it (.. o (m1) (m2)) the same as (-> o (.m1) (.m2))?

8:10 s/it //

8:13 Apparently you can call static methods with .. but not with ->.

8:21 Is there a limit on how many function calls I can chain together with ->? I suddenly get a ClassCastException after a few almost identical calls in this code: https://gist.github.com/1191098

8:28 raek: Netpilgrim: which function is the exception thrown from?

8:29 Netpilgrim: raek: Apparently set-edge on the marked line.

8:30 raek: It's curious because on the two lines above it I call the exact same function.

8:30 raek: but no, there shouldn't be any limit on the number of forms

8:31 if you get an exception at runtime, it's not ->'s fault, since it's gone then

8:31 (because it is a macro)

8:32 Netpilgrim: raek: Ah, ok. It seems the exception is thrown the third time set-edge is called, no matter what order the calls are in.

8:33 raek: I would recomment to look the stacktrace to see which line of the set-edge function it is thrown from

8:34 Netpilgrim: raek: Do you know how I can get a full stacktrace in slime-repl?

8:34 raek: you should get one

8:34 maybe you need to click on the cause lines

8:35 khaliG: Netpilgrim, try (.printStackTrace *e) (i've been reading Joy :P)

8:35 raek: but the whole exception chain should be available in the buffer that pops up

8:36 Netpilgrim: raek: The compilation buffer only contains this one line I've quoted in the gist.

8:37 khaliG: (.printStackTrace *e) returns nil.

8:38 raek: Netpilgrim: do you get the exception when you compile or when you run it?

8:38 Netpilgrim: raek: When I compile it.

8:39 raek: try calling (require 'yout-ns :reload) in the repl

8:42 seems like you don't get good stack traces when you don't use the repl

8:42 anyway, I think this line is the problem: (conj (em from) to)

8:42 and that em is a list thre

8:43 Netpilgrim: raek: "Could not locate yout_ns__init.class or yout_ns.clj on classpath"

8:43 raek: you coult also try to comment out the test-graph form from the file, copmile it, and the run that code in the repl

8:44 Netpilgrim: raek: Ah, you probably meant 'your-ns. :)

8:44 raek: or replace (def test-graph ...) with (defn test-graph [] ...) and call (test-graph) in the repl

8:44 Netpilgrim: I meant whatever your namespace is called

8:44 Netpilgrim: raek: I got that now.

8:45 raek: require leads to the same ClassCastException. I'll try running the -> form in the repl.

8:46 raek: Netpilgrim: make the test thing a function. then you will have compile-time and run-time separate

8:51 Netpilgrim: raek: Wow, that's strange. I have made it a function (https://gist.github.com/1191098) and now it compiles and runs ok.

8:52 raek: It smells like a bug in the compiler.

8:54 hugod: shouldn't that be update-in rather than conj in set-edge?

8:55 raek: Netpilgrim: when I take your original code and turn test-graph into a function, I still get the exception when I run it

8:56 same thing with your second gist

8:57 Caused by: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

8:57 at user.DirectedGraph.set_edge(NO_SOURCE_FILE:175)

8:58 if you compile it in emacs, rather than typing it in in the repl as I did now, you should get a line number too

8:58 Netpilgrim: raek: Keeps getting stranger. I can't reproduce the problem, now that it's a function.

8:58 raek: Netpilgrim: which namespace is the repl in?

8:59 Netpilgrim: and you run (test-graph) in the repl?

8:59 Netpilgrim: raek: You can see the line number here: https://gist.github.com/1191098/5191de8a71d2f1c579c6171d1b553da5ccf47306

8:59 raek: is this gist the whole file? if so, you're missing a namespace declaration

9:00 Netpilgrim: raek: Yes, I run the test-graph in the repl and it's in the same namespace as the function.

9:00 raek: I've left out the namespace declaration (and some other stuff) in the gist.

9:00 raek: what happens when you run (test-graph)?

9:00 I get an sception there

9:00 *exception

9:01 anyway, I have to go. good luck!

9:01 Netpilgrim: raek: Damn, when I remove everything but what I've posted in the gist and call the function in the namespace "user" I get the exception again.

9:02 raek: how do you compile the file?

9:04 Netpilgrim: raek: slime-compile-and-load-file

9:04 raek: anyway, it's easier for others to debug if you post the whole file as it is

9:05 but now I really have to go.

9:05 hugod: (update-in em [from] conj to)

9:06 Netpilgrim: hugod: Sorry, I wanted to get back to you on that. I'm not familiar with update-in. Is it just nicer or do you think my code is (semantically) wrong?

9:07 hugod: O, now I see the problem. Thanks for the hint.

9:08 hugod: Wow, this gets rid of the compilation problem. I just don't see how.

9:09 raek: Thanks for your help.

9:11 hugod: the original call to conj was returning a list, which was used as the value of em in the next set-edge call, giving rise to the exception you were seeing

9:13 Netpilgrim: hugod: Now there's just the mystery why compilation and run did work with one specific namespace.

9:14 hugod: But as long as something like this doesn't come up again, I can live with that.

9:14 khaliG: is scheme a better choice for making android apps than clojure?

9:40 bsteuber: khaliG: I'd stick to ClojureScript

9:40 but to be fair, I don't know anything about scheme android dev

9:40 zilti: Why would you compile Clojure to JavaScript if it has to run on a JVM anyway on Android?

9:41 bsteuber: why should javascript run on a jvm?

9:41 khaliG: bsteuber, I dont know anything about it either - but reading about how kawa scheme has full support for android and it runs fast without the problems clojure seems to have on the same platform

9:42 bsteuber: the thing is, if you use clojurescript, things run in any browser, so you even got iPhone in the boat

9:42 but of course it might depend on the type of your app

11:58 gaze__: hey, what would be the nicest way to go about composing a list over the duration of a function... kinda like with the list monad in haskell, but without clojure's funky monad syntax

11:58 is there anything better than a let-bound mutable vector?

12:51 chouser: gaze__: yes, there is something better.

12:51 by definition. a let-bound mutable is to avoided if at all possible.

12:52 what about conjing onto a vector, passing it forward from one step in the function to the next.

12:59 solussd: I usually just don't, but what is the preferred way to enforce arg types to a function?

12:59 e.g. I want a function to throw an exception if not called with a keyword

13:00 pre/post conditions?

13:06 robermann: if I'd want to double a number, which whould be better / more idiomatic: using a partial as (defn pdouble [x] ((partial * 2) x)) or using a closure as (def times-two (let [x 2] (fn [y] (* y x)))) ?

13:14 gaze__: chouser: I'm afraid I don't understand

13:16 what would that look like?

13:19 solussd: robermann: what's wrong with (defn [x] (* 2 x)) ?

13:19 *function-name

13:23 robermann: mmm I was tr

13:23 ying to find when to use a partial and when to use a closure

13:24 these are new concepts for me, and I'm going to study them

13:25 isn't a closure a partial function?

13:25 gaze__: a closure is a function tied with it's environment.

13:26 solussd: a closure is a function that 'closes over' its environment

13:28 robermann: but here the partial isn't closing over the two? (def two 2) (defn pdouble [x] ((partial * two) x))

13:28 or maybe this example is too simple to be interesting

13:29 solussd: the function partial takes a function and any number of args and returns a function that calls the original function with the args it was created with plus any args passed to it

13:31 gaze__: I guess I don't understand how you'd write a DSL in closure... how do you go about threading state through a series of functions?

13:31 solussd: define state as the application of functions? :D

13:34 moving a data structure from one state to the next is modeled functionally as (def next-state (move-to-next-state original-state))

13:34 gaze__: let's put it this way... I wanna be able to do (foo [x] (add-to-list 3) (add-to-list 4) (if x > 8 (add-to-list 5))) (foo 3) => (3 4) ; (foo 9) => (3 4 5)

13:35 solussd: there be side-effects

13:36 gaze__: sure! but haskell seems to handle this sorta thing fine

13:36 I mean... there's a ton of desugaring

13:36 I was just hoping there'd be something similar

13:37 basically I want to build up a transaction over the lifetime of my function, and before the function returns I'd like to commit it atomically.

13:38 michaelr525: heyo

13:38 !

13:47 solussd: gaze__: (defn foo [x] (let [add-5? (fn [y] (if (> x 8) (conj y 5) y))] (-> [3] (conj 4) add-5?)))

13:48 use the threading macro to thread your list (in this case, a vector) through each step

13:50 more concisely, (defn foo [x] (let [add-5? #(if (> x 8) (conj % 5) %))] (-> [3] (conj 4) add-5?)))

13:56 ShereKahn: Hi, I am writing a tool to extract values from the output of commands of a system (in this case a router). The approach I have taken is to write a "parser" that is actually matching the output based on templates.

13:57 but the problem I have is that I have some sub-structure in the show, so I thought that I could use some recursive function to go through the templates and the actual tokens

13:58 so the issue I have is that I would need to have something that would do (while tokens (parse ...)) where the parse would send back the result and the remaining tokens if any

13:58 but I am not sure how this is possible

13:59 e.g. passing a ref to change the state of the remaining tokens for the while ?

14:00 or is there anything more idiomatic in clojure to do that ?

14:04 otherwhise put, say I have a (let [token ...] (while token (do-something (token))), is there a way for the do something to change the bindings for 'token' from inside the 'while' or the 'do-something' ?

14:06 similar to what CL '(setf token new-value) ' would do ?

14:07 Netpilgrim: Can someone explain to me why the pre conditions at https://gist.github.com/1191537 are ignored?

14:12 Chousuke: ShereKahn: if you want something stateful you will need an atom or something

14:13 ShereKahn: however it should be entirely possible to make a stateless parser

14:14 actually I might have a gist somewhere that implements a simple one

14:15 ShereKahn: Chosuke : thanks I would be grateful to see it.

14:23 Chousuke: ShereKahn: https://gist.github.com/141085 I did it as a monad exercise but maybe it will give you an idea or two :)

14:24 ShereKahn: Chousuke: thanks a lot for that! I hope it'll give me enough ideas to get me unstuck

14:24 Chousuke: ShereKahn: there's also a clojure parser combinator library that you might be able to use

14:25 fparse or something? I don't remember exactly

14:49 rindolf: Hi all. How do I run labrepl?

14:52 https://github.com/relevance/labrepl/wiki/Maven - I see.

15:16 scode: Would the with-private-fns macros as descibed at http://nakkaya.com/2009/11/18/unit-testing-in-clojure/ still be idiomatic for unit testing private functions in a namespace?

15:21 amalloy: Chousuke, ShereKahn: fnparse

15:31 arohner: scode: if you're not calling the fns too often , you can just ((var your-private-fn) foo)

15:32 sigh, anyone gotten a ring app to run on heroku? I'm getting Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch, and no other helpful information

15:34 scode: arohner: Interesting work-around, thanks!

15:34 michaelr525: what work-around?!

15:47 icey: arohner: I have a ring app up there, but didn't run into any errors like that

15:48 arohner: it's a tiny app, it barely does anything: https://github.com/pmn/peeranoia

15:51 arohner: icey: thanks

15:52 icey: arohner: do you have a Procfile defined? It sucks that the error message is so ambiguous. I have a noir app deployed out there that does a little more (but not much more) and it's working alright too (just checked on them to make sure they were still running)

15:53 arohner: icey: yes, I have a procfile, just 'lein run -m my-ns.server'

15:53 it's a noir app, with very few changes

15:54 I'm thinking there's an exception on startup that's not getting logged

15:55 icey: arohner: the procfile for my noir app just says "web: lein run", but having the -m <ns> shouldn't make a difference, right?

15:55 arohner: icey: yeah, I've tried it both ways

15:56 icey: hmmm. this is what my server.clj looks like: https://gist.github.com/1191690

15:56 (for the noir app)

15:57 arohner: icey: yeah, mine looks almost identical

15:57 icey: arohner: do you connect to a database or anything like that?

15:57 arohner: icey: nope

15:58 I have some static files I serve out of /resources, but that's about it

15:59 icey: have you tried deleting the heroku app and creating a new one? the only thing i can find on google about the R10 error appear to be database related - either a bad database.yaml was included, or the correct database was defined and is unreachable

15:59 arohner: sigh. Now it's working, and I don't know why

15:59 icey: thanks for your help

16:00 icey: arohner: chalk it up to random sunspot activity or something ;)

18:10 sirn: Anyone knows if Compojure still requires the (assoc-in response [:headers "Content-Type"] "whatever; charset=utf-8") middleware stuff for UTF-8 support?

18:11 jblomo: it looks like the current version adds it already

18:11 https://github.com/weavejester/compojure/blob/master/src/compojure/response.clj

18:12 sirn: jblomo: awesome, thanks!

18:23 jblomo: what is the scope of extend-protocol? if you extend a protocol in (ns user (:require foo)) will the extension be in effect inside foo?

18:28 akhudek: is there a way to get a java iterator for a clojure seq? This is for interop purposes.

18:28 amalloy: sim: that's only setting utf-8 when you tell compojure to render a string. if you render anything else, it looks like it doesn't necessarily add utf-8 (and it shouldn't, since it doesn't know what content encoding, say, a file on the local hard disk is)

18:28 &(doc seq-iterator)

18:28 lazybot: java.lang.Exception: Unable to resolve var: seq-iterator in this context

18:28 amalloy: &(doc iterator-seq)

18:28 lazybot: ⇒ "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly."

18:28 akhudek: I mean the other way :)

18:28 amalloy: &(supers (class (clojure.lang.SeqIterator. (seq [1 2]))))

18:28 lazybot: ⇒ #{java.util.Iterator java.lang.Object}

18:29 akhudek: that will work? hm thanks

18:29 amalloy: akhudek: but seqs are already Iterable

18:29 if java wants an Iterator instead of an Iterable, that's not very pleasant

18:29 akhudek: this function wants: Iterator<List<String>>

18:30 I think the inner type can be an iterator too

18:30 amalloy: akhudek: right, my point is that's a dumb thing to want as of java 1.5, which is like a decade old. if you can get them to accept an Iterable instead...

18:31 akhudek: the code is part of mahout, I may try to submit a request, but I imagine it's unlikely to be changed any time soon

18:31 https://builds.apache.org/job/Mahout-Quality/javadoc/org/apache/mahout/fpm/pfpgrowth/fpgrowth/FPGrowth.html

18:38 chouser: I think just (.iterator your-seq) should work

18:39 akhudek: ^^^

18:41 akhudek: yep, that seems to work, thanks chouser

18:52 mudge: how do I make Clojure fully evaluate this map call: (map #(str project-path %) ["lib/*:" "src/:" "resources/"])

18:52 akhudek: doseq

18:52 amalloy: uhhhh. you can stick a doall in front, but since this operation has no side effects that really won't do anything interesting

18:53 akhudek: or doall rather

18:53 mudge: I tried (doall (str (map #(str project-path %) ["lib/*:" "src/:" "resources/"]))), but it doesn't work

18:53 amalloy: clojurebot: bug report?

18:53 clojurebot: A bug report has three parts: What you did; what you expected to happen; what happened instead. If any of those three are missing, it is awfully hard to help you.

18:54 amalloy: maybe i should get him to reword that so it's clear it applies to "this doesn't work"

18:57 but mudge, it sounds like you're trying to implement (System/getProperty "java.class.path"). aside from the fact that your implementation doesn't work, is there a reason not to use the builtin?

18:57 mudge: amalloy, i'm trying to setup a classpath for calling java

18:58 amalloy: i found a way, so I am good

18:59 amalloy: mudge: just call lein classpath

18:59 or cake classpath

18:59 mudge: amalloy: i don't have lein on the remote server where the production server is

19:01 is there a takeall function for taking all the elements from a lazy seq?

19:02 amalloy: mudge: this is exactly as crazy as crazy as "fully evaluate this map call". a lazy seq already contains all of its elements; taking them all doesn't mean anything. you need to be more clear about what your goal is, rather than asking a solution to a sub-problem you think you need to solve

19:04 mudge: amalloy: yes, makes sense

19:05 amalloy: i am trying to append a string to each of three strings

19:05 amalloy: actually preprend a string to each of three strings

19:05 amalloy: your originally-posted code already does that

19:06 mudge: amalloy: then I want to put the three strings inside (apply str )

19:07 amalloy: great. wrap (apply str) around your original code, and you've done it

19:08 that said, i'd prefer to write: ##(let [path "foo"] (clojure.string/join ":" (for [suffix ["lib/*" "src" "resources"]] (str path "/" suffix))))

19:08 lazybot: ⇒ "foo/lib/*:foo/src:foo/resources"

19:10 mudge: amalloy: so I have this: (apply str "java -cp " (map #(str "/home/nick") ["lib/*:","src/:" "resources/"]))

19:10 amalloy: &(#(str "/home/nick") "src:/")

19:10 lazybot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: sandbox17398$eval20592$fn

19:11 mudge: i mean this: (apply str "java -cp " (map #(str "/home/nick/" %) ["lib/*:","src/:" "resources/"]))

19:13 amalloy: &(apply str "java -cp " (map #(str "/home/nick/" %) ["lib/*:","src/:" "resources/"]))

19:13 lazybot: ⇒ "java -cp /home/nick/lib/*:/home/nick/src/:/home/nick/resources/"

19:13 amalloy: so what's the problem?

19:14 mudge: amalloy: yea, that works, but actually I have more strings after the map, so like this: (apply str "java -cp " (map #(str "/home/nick/" %) ["lib/*:","src/:" "resources/"]) " clojure.main")

19:15 amalloy: well that doesn't work

19:15 mudge: amalloy: yea, it doesn't

19:15 amalloy: i guess only the sequence can be at the end?

19:16 amalloy: i think this is what I was having trouble with and that I didn't understand before

19:17 amalloy: i hope you've got what you need, because tbh i'm tired of solving problems you're not actually having

19:17 mudge: amalloy: yes, i understand now, the function signature for apply is: apply f args* argseq)

19:17 amalloy: so the sequence has to be at the end and that's why i was having trouble

19:19 amalloy: so this works: (apply str "java -cp " (join "" (map #(str "/home/nick/" %) ["lib/*:","src/:" "resources/"])) " clojure.main")

19:20 amalloy: i join together the sequence into a single string so it isn't a sequence in apply

19:20 cemerick: redinger: Not wanting to clutter two lists up with it, but: consider the ongoing clojure-dev thread my input re: 1.3. "showstoppers". Especially given CLJ-736 (rightly) going into -beta3.

19:21 mudge: amalloy: i also don't need apply now, i can just use str

19:48 jblomo: is there a way in lein to run something without have test-resources in the classpath?

19:49 kof4001: hello

19:49 where could I get information on how to get clojure-mode to work in emacs?

19:50 amcnamar1: kof4001: elpa or marmelade (emacs package managers) will let you install it easily

19:51 kof4001: I tried first with http://riddell.us method

19:51 and then with elpa

19:51 amcnamar1: what problem are you seeing?

19:51 kof4001: I might be missing something here

19:52 this appears in debug mode:

19:52 Debugger entered--Lisp error: (file-error "Cannot open load file" "clojure-mode")

19:52 require(clojure-mode)

19:52 amcnamara: (require 'clojure-mode)

19:52 emacs is a lisp

19:53 kof4001: in my init.el I have:

19:54 amcnamara: also, usually elpa handles the loading for you behind the scenes

19:54 so you can drop that, restart emacs, and hit M-x clojure-mode

19:54 kof4001: (add-to-list 'load-path "~/emacs.d/clojure-mode")

19:54 (require 'clojure-mode)

19:55 i have installed clojure mode inside .emacs.d

19:55 instead ~/opt

19:56 amcnamara: you may still need to load it

19:56 try (load "clojure-mode.el") or something equivalent off the load-path path you have above

19:57 (before the require call)

19:57 lobotomy_: ugh, how do i easily print a LazySeq

19:58 (println (str "seq is " my-lazy-seq)) doesn't work so hmm

19:58 is there a way to force the lazy seq to be evaluated? or a print-for-real function?

19:58 kof4001: that load did the trick

19:58 thanks

19:59 amcnamara: kof4001: np.

19:59 lobotomy_: try (apply str lazy-seq), that should pull all the values out

19:59 amalloy: &((juxt print-str pr-str) (range 3))

19:59 lazybot: ⇒ ["(0 1 2)" "(0 1 2)"]

20:00 amalloy: &((juxt str pr-str) (range 3))

20:00 lazybot: ⇒ ["clojure.lang.LazySeq@7480" "(0 1 2)"]

20:00 amalloy: there we go. that's the point i was making

20:01 amcnamara: &(apply str (range 3))

20:01 lazybot: ⇒ "012"

20:01 lobotomy_: (println (str "my-seq is " (apply str my-seq))) ;; still doesn't work, just prints "my-seq is clojure.lang.LazySeq@0clojure.lang.LazySeq@0"

20:01 amcnamara: everyone's a winner.

20:01 lobotomy_: hmm, or is that a thing that contains other lazyseqs...

20:01 isn't there a force-print-dammit function? :)

20:02 maybe i'll use flatten!

20:02 amcnamara: try what amalloy posted

20:02 lobotomy_: ooh, right

20:02 amcnamara: but yeah, looks like you've got lazies all the way down.

20:03 amalloy: &(pr-str (for [x [10]] (range x)))

20:03 lazybot: ⇒ "((0 1 2 3 4 5 6 7 8 9))"

20:03 lobotomy_: yep, pr-str works fine

20:03 cheers

20:06 mudge: how to add to the lein classpath?

20:12 anybody ever added to the lein classpath of their project?

20:12 lobotomy_: grr, now i just need to figure out how to view the print results in the slime repl... apparently scrolling with that is impossible

20:12 there's say 100 lines, it shows either the first 5 or the last 10

20:12 clojurebot: Huh?

20:17 amcnamara: mudge: I've never needed to, lein is supposed to track and manage dependencies for you -- you tell it what to get instead of where to get it.

20:17 what are you tring to do?

20:17 kof4001: i'm sorry to be bothering again, but the (load "clojure-mode.el") in emacs, only works if i loaded it from emacs, not from init.el

20:18 amcnamara: lobotomy_: M-x scroll-up ?

20:18 kof4001: probably has something to do with the order that those scripts are loaded, I dump most of those things into a .emacs file on ~

20:19 kof4001: i think the 23 version does not use .emacs anymore

20:19 amcnamara: I believe .emacs is run last (after elpa, which may be causing your problem)

20:19 kof4001: i do not see a .emacs file in my home

20:19 amcnamara: you have to make it

20:19 kof4001: i'll try

20:19 mudge: I'm using Clojure for a shell script type of command line program that starts/stops/restarts my jetty server. I have an extra directory in my project called scripts which i want to add to leiningens classpath

20:20 amcnamara: mudge: if you want them to be visable to your project but not managed by lein, dump them in myproject/lib

20:21 mudge: amcnamara: thanks

20:21 amcnamara: you may also wish to set :disable-implicit-clean to true in project.clj

20:22 or else whenever you run lein deps it will kill your lib

20:22 kof4001: the .emacs did not work

20:23 the same problem with init.el

20:23 mudge: amcnamara: yes, thanks

20:23 amcnamara: kof4001: dump/gist the error

20:24 kof4001: i Debugger entered--Lisp error: (file-error "Cannot open load file" "~/emacs.d/clojure-mode/clojure-mode.el")

20:24 load("~/emacs.d/clojure-mode/clojure-mode.el")

20:24 eval-buffer(#<buffer *load*> nil "/home/nonelse/.emacs" nil t) ; Reading at buffer position 64

20:24 load-with-code-conversion("/home/nonelse/.emacs" "/home/nonelse/.emacs" t t)

20:24 load("~/.emacs" t t)

20:24 #[nil "\205\264

20:25 mudge: amcnamara: I could also use the load-file function and refer to include my file that isn't in the classpath

20:27 amcnamara: kof4001: odd...

20:29 kof4001: lets go back to elpa, what went wrong on your install from there?

20:30 kof4001: i installed elpa from the site http://tromey.com/elpa/install.html

20:30 should i do it again?

20:30 amcnamara: did you do package-install?

20:31 icey: kof4001: what OS are you using? Are you sure your idea of ~ is the same as emacs'?

20:31 kof4001: of emacs?

20:31 lubuntu

20:31 amcnamara: in emacs

20:31 elpa is a program to fetch emacs plugins

20:32 M-x package-list-packages

20:32 will show all of the available ones

20:32 M-x package-install clojure-mode

20:32 will install clojure-mode using elpa

20:32 kof4001: well the package install is not working

20:33 i guess elpa did not installed correctly

20:34 amcnamara: rerun the script from tromley, and remove the require/load clojure mode stuff you added to init.el

20:36 kof4001: i managed to install elpa

20:36 lobotomy_: hmm, apparently one of the sets i'm giving to clojure.set/difference isn't always a set, but sometimes a lazyseq

20:36 this looks like it might be annoying to debug

20:37 kof4001: but clojure-mode is not detected as a package

20:37 lobotomy_: does clojure.set/intersection or /union sometimes generate lazyseqs?

20:38 kof4001: i had to list it first

20:39 amcnamara: kof4001: is it showing up now?

20:39 kof4001: after i did a package-list yes

20:39 amcnamara: &(doc clojure.set/union)

20:39 lazybot: ⇒ "([] [s1] [s1 s2] [s1 s2 & sets]); Return a set that is the union of the input sets"

20:39 amcnamara: &(doc clojure.set/intersection)

20:39 lazybot: ⇒ "([s1] [s1 s2] [s1 s2 & sets]); Return a set that is the intersection of the input sets"

20:40 amcnamara: nope.

20:40 kof4001: i guess that was it

20:40 i installed paredit while i was at it

20:40 thanks a bunch

20:40 amcnamara: paredit comes in very handy

20:40 np.

20:41 kof4001: keep up

20:50 lobotomy_: argh, i can't seem to print the stupid things before they end up in clojure.set/difference and cause that explosion

20:51 (do (println ...) (into {} (for [... :let (...)] (do (println ...) (let ... (clojure.set/difference foo bar) ;; and the println's all say everything is a hashset, and immediately after java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IPersistentSet

20:52 wonder if debug printing stuff is actually this difficult in clojure or whether i just suck, heh

20:53 amcnamara: gist your code

21:11 amalloy: jira is such a damn pain. i can't even close issues i reported? they were informally marked as "not interested" by clojure/core, but jira still thinks they're "Unresolved, open, unassigned"

21:21 lobotomy_: here's my code: http://pastebin.com/dMB14FKb

21:22 any ideas appreciated :)

21:25 ah damn, that seems to be incomplete. need to fix

21:25 ibdknox: unusual question: does anyone happen to know what font the Clojure logo uses?

21:27 lobotomy_: added the pretty print stuff so it should compile: http://pastebin.com/C96NNcMu

21:45 cemerick: amalloy: Those damn fine-grained ACLs. :-P You don't have a 'close issue' button at the top of the issue?

21:47 jkkramer: lobotomy_: it looks like you're passing hash maps, not hash sets, to clojure.set/difference

22:01 mudge: what is a an ear muff?

22:01 ctran: *var*'

22:02 http://stackoverflow.com/questions/3579063/conventions-style-and-usage-for-clojure-constants

22:14 jkkramer: lobotomy_: i was mistaken. it's like 88; remove-threatening-squares ought to return a set

22:15 lobotomy_: it may help in the future to break your code into smaller, more testable pieces. the code flow is a bit hard to follow

22:53 amalloy: cemerick: no. or if i do it's awfully well-hidden

22:53 cemerick: amalloy: which issue? Maybe I can close it?

22:54 amalloy: 714, 707, and probably 709 also

22:56 thinker341: hi

22:57 amalloy: cemerick: i have to step out for a while; if you need anything more from me to get those closed, just leave a message

23:05 cemerick: amalloy_: Issues closed.

23:07 ambrosebs: what do I need to do to request commit access to core.match?

23:07 cemerick: ambrosebs: find someone with admin rights in the 'clojure' github organization.

23:07 msg to clojure-dev should do it, presumably

23:08 ambrosebs: will do, thanks chas

23:10 seancorfield: there has to be a better way...

23:11 so, i have a vector of maps... i want to do (map (juxt :id :name) data) which gives me ((id1 name1) (id2 name2) ...)

23:11 but i want that as a map {id1 name1, id2 name2, ...}

23:12 i can do (into {} (map vec *1)) but that seems ugly

23:12 is there a nicer way to turn ((a b) (c d) ...) into a map?

23:18 cemerick: seancorfield: juxt produces vectors here (-beta1)

23:20 Otherwise, (reduce #(apply assoc % %2) {} (map (juxt :id :name) …)) ?

23:20 Not nicer, but maybe (probably not) more efficient?

23:26 seancorfield: ,((juxt :id :name) {:id 1, :name "Sean"})

23:26 clojurebot: [1 "Sean"]

23:26 seancorfield: how about that... *facepalm*

23:27 cemerick: It's in the docs, FWIW. I don't have 1.2.0 handy, maybe that's a change.

23:27 seancorfield: so i can lose the map vec at least... no idea why i had convinced myself i got sequences instead :(

23:27 thanx!

23:27 cemerick: :-)

23:28 seancorfield: now i can clean up my code quite a bit...

23:30 technomancy: jblomo: set the LEIN_NO_DEV environment variable

23:38 seancorfield: yeah, nice... much cleaner code... comp and juxt FTW :)

23:38 thanx cemerick !!

23:39 cemerick: seancorfield: np, glad it worked out :-)

23:39 user317: is there a transpose function somewhere?

23:42 davekong: I tried running clojure on jnode and got this error: http://pastie.org/2478994 just wondering if anyone might have an idea how I would go about fixing this error

23:46 user317: is there a good source on list manipulation in clojure for someone from a haskell background? like zip zipWith transpose etc...

23:47 technomancy: zip?

23:47 clojurebot: zip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c))

23:48 user317: ah, so thats transpose

23:48 i dont have my head wrapped around the variable arg part of clojure

23:48 makes sense

23:49 does that work over infinite lists?

23:49 technomancy: yep

23:50 user317: cool, seems to do the right thing when they are different sizes as well

23:51 technomancy: I think it truncates to the shortest seq arg

23:51 cemerick: it does

23:51 ,(map list [1 2 3] [1 2 3 4])

23:51 clojurebot: ((1 1) (2 2) (3 3))

23:52 user317: yep

23:53 so, if i pass a record constructor as the function to map, that should apply each value from the list as arguments to the constructor, right?

23:54 cemerick: ctors are not first-class; you can't apply them to a seq of args, etc.

23:54 However, (defrecord Foo …) creates a ->Foo factory function that will do what you want

23:55 user317: Foo is that function, right?

23:55 cemerick: No, `->Foo` is the function's name, if your record class is named Foo.

23:55 user317: (map ->Foo (1 2 3) (4 5 6))

23:55 like that?

23:56 cemerick: yup

Logging service provided by n01se.net