#clojure log - Feb 12 2011

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

0:00 cheezey: i already removed it.

0:00 bytecolor: anthony__: so in myscript.clj you have (ns myscript (:use my-utils)) ; not really sure if that's correct

0:01 I haven't loaded a clojure program the way you are attempting

0:01 anthony__: bytecolor: I've tried several things similar to that, none of them worked

0:03 Is there a function where I can pass it a .clj file and have it eval all of it? Maybe I need to eval the my-utils.clj from the JAR file before trying to use it.

0:06 tomoj: what does your myscript.clj actually do?

0:06 anthony__: Just some defs

0:06 bytecolor: hrm, I wonder if it's due to the hyphen in my-utils.clj

0:06 anthony__: Oh, sorry.

0:06 The myscript just calls some of the functions declared in my-utils.clj

0:07 tomoj: I mean, what does it _do_?

0:07 i.e. do you have a good reason for dealing with all this bullshit manually?

0:08 ideally you shouldn't have to worry about the classpath nor type "java" :)

0:08 anthony__: tomoj: Well, I'll have several (independent) scripts using the functions from my-utils. I could just make separate programs out of each of them, using my-utils as a library. I was just curious if it was possible to avoid that and just run them as scripts.

0:09 tomoj: hmm.. my suggestion leads to creating separate projects for each script which all depend on the utils

0:09 which could be a hassle

0:09 anthony__: I mean, I could probably throw them into one project, and just take a command-line arg for the script to run.

0:09 tomoj: oh, as you said

0:09 :)

0:09 anthony__: Which would be nicer.

0:10 I'll mess around with it some more. Maybe the hyphen is messing something up, like bytecolor said

0:10 bytecolor: wait, wait, I want to know *why* it wont work ;)

0:10 tomoj: well, you should never have hyphens in a .clj filename

0:11 anthony__: bytecolor: lol, me too. I need to grab something to eat, but I'll be back with some more messing around. I might be just doing something stupidly wrong.

0:11 tomoj: always replace with underscores

0:11 bytecolor: tomoj: nod, that bit me on the ares for a while until I figured it out

0:11 that's why I thought it may be a problem in anthony__'s example

0:12 tomoj: have we seen the error yet?

0:12 bytecolor: why no! we haven't

0:13 tomoj: blind men with an elephant, eh?

0:15 anthony__: Sorry, here's the error:

0:15 Exception in thread "main" java.lang.Exception: Unable to resolve symbol: myutils in this context (myscript.clj:1)

0:15 (I changed it to myutils)

0:15 tomoj: :D

0:15 that error looks rather mundane

0:16 anthony__: Exactly. That's why I'm worried I'm missing something trivial.

0:16 tomoj: perhaps you're missing a require or use in myscript.clj?

0:17 anthony__: tomoj: I wasn't missing it, but I think I had it typed wrong. Seems to be working now. Must've been the hyphen originally.

0:19 tomoj: (require 'foo.bar.baz-bang) will look for foo/bar/baz_bang.clj on the classpath

0:19 * tomoj shakes fist at java

0:25 anthony__: tomoj: Amen. The problem with Clojure is that it makes me hate writing Java more and more each day.

0:25 I was happy living in ignorance before.

0:26 tomoj: it's a strange situation

0:28 bytecolor: I think any time you start writing lisp, you have to step your game up. But, you'll be a much better programmer for having done so.

0:28 tomoj: I guess it helps if you were a java programmer already

0:28 then it just looks like you get to escape much of the madness

0:28 brehaut: bytecolor: that applies to any language that differs from the paradigms you know

0:31 anthony__: tomoj: Exactly. It's wonderful coming from Java.

0:31 bytecolor: brehaut: well, I don't know. I dont think any other language has made me re-evaluate my thought process more than lisp. Take clojure. The immutability has really tossed me a curve ball. But, I've never used a purely functional language such as haskell.

0:32 well, after typing that, yes I can agree with you

0:32 gregh: the "functional" thought process hit me when I did some nontrivial stuff in xslt (of all things) years ago

0:32 brehaut: heh :)

0:32 tomoj: bytecolor: in which other languages have you dabbled?

0:32 bytecolor: common lisp, scheme, python, c++

0:33 tomoj: so, lisps vs python and c++?

0:33 bytecolor: nod, I'll concede that my view is quite limited

0:34 tomoj: the "are we there yet?" talk by rich includes a part about how most popular languages are practically the same

0:35 brehaut: a logical language and haskell should be on everyones list to learn IMO

0:35 tomoj: and that the main differences are programmer sensibilites

0:35 if we're going to have religious wars, maybe programmer sensibilities aren't such a bad thing to war about

0:36 cheezey: so if a ns exists in (find-namespaces-on-classpath), how can i use one? for example clojure.core is in there..

0:36 i dunno i think im just being frustrated at this point ;_;

0:37 tomoj: but it's not awfully surprising to me for someone who's learned several popular languages very well to never have their head screwed around

0:39 brehaut: what would be your recommendation for a logical language?

0:39 brehaut: eeck kinda hard. prolog is very available and its hte canonical example

0:39 amalloy: tomoj: prolog is the canonical one

0:39 tomoj: my dabble there was probably not long enough for head-screwing

0:40 brehaut: but clause ordering and cuts require you to understand the procedural evaluation for even some simple programs

0:40 my dabble with miniKanren over summer was promising as a good first pass

0:40 bytecolor: tomoj: makes two of us, I've played around with it, but not written anything worth mention

0:41 although I'd still like to implement prolog in clojure, as in paip

0:41 brehaut: brain bending programs can be _very_ short in prolog ;)

0:41 bytecolor: brehaut: I have The Seasoned Schemer on my desk (collecting dust :/)

0:42 brehaut: ive only go the little schemer

0:42 ive pondered getting the seasoned and reasoned schemers

0:44 tomoj ask dnolen, hes neck deep in logical programming

0:46 bytecolor: I'd like to see hicky and co do a rewrite of paip in clojure. That would be one eye-opening book, imo. I tried doing a one-to-one port to clojure, but some of the functions just do so much mutating it's just not practical unless evertying is an atom, ref, etc.

0:46 tomoj: shoot, "clojure nomic"

0:46 has results now

0:47 the only result looks totally fucking bogus though

0:47 brehaut: 'nomic' ?

0:48 tomoj: er, talk of prolog reminded me of my attempts to write a code nomic in prolog. I've been yearning for a clojure one for quite a while

0:49 this appears to be the only clojure source file in the only so-called clojure nomic I can find: https://gist.github.com/1de0bec2aafc936d39b3 O_o

0:50 ignoring all the .clj files which appear to be dependencies checked in to the repo for some reason

0:51 amalloy: tomoj: funny you should mention nomics and xslts. i wrote a nomic that was mainly a couple xml files, and several xslts to render them in different ways

0:51 bytecolor: so is mutation in the let vector abuse, or good form?

0:52 brehaut: bytecolor: do you mean shadowing prior bindings?

0:52 (let [a 1 a 2 a 3] ...) frinstance?

0:52 bytecolor: using prior binding to *set* subsequent bindings

0:52 I guess *set* would be bind, as in local binding

0:53 brehaut: there are probably better tools for a lot of cases

0:53 tomoj: I accept it occasionally


0:53 bytecolor: clojure let is actually common lisp let*, no?

0:53 well, leaving destructing aside

0:54 tomoj: whether it's abuse really depends I guess

0:54 bytecolor: clojure destructuring is pretty cool, imo

0:54 brehaut: its not abuse; if it were it wouldnt be allowed

0:54 tomoj: it certainly can be abused

0:55 brehaut: i think its more of a code smell though

0:55 bytecolor: hey, I ran across a problem where I tried to destructure a binding form, but it crapped out. I found *old* post where someone had written a macro to do this, but has it not been implemented in the core?

0:57 something simple like (binding [[x y] [0 1]] [x y]), but (let ...) will work

0:58 tomoj: "binding form" :)

0:58 bytecolor: where x and y had been def'ed prior

0:59 tomoj: is it easy for you to explain why that would be useful?

0:59 I can't think of an example

1:00 bytecolor: well, actually I was converting koza's genetic programming kernel to clojure

1:00 tomoj: amalloy: hmm. so how do you play that nomic?

1:01 bytecolor: a map of 11 bits

1:01 amalloy: tomoj: email, and iirc manual editing of the xml files for new rules

1:01 it never really got off the ground

1:01 tomoj: unfortunately that seems to usually be the case

1:02 bytecolor: so, destructuring a binding is out

1:02 tomoj: map of 11 bits? like {0 true 1 false ... 10 true} ?

1:03 bytecolor: tomoj: basically, yes

1:03 tomoj: it was another one-to-one port, probably much better ways to do it in clojure

1:03 porting from common lisp code

1:06 in the kernel, EVAL is used heavily in the fitness evaluation function, and it is god-all-mighty slow. I ended up progromatically writing the fitness funciton to c++, compiling, evaluating, and returing a clojure vector to shell-out/sh.

1:07 tomoj: wow

1:07 bytecolor: but I aint mad. I rockets through the population.

1:08 tomoj: that reminds me of my thoughts about macroexpanding a neural network topology into code that directly evaluates it. unfortunately that seems to be terribly evil and the class size limit makes it probably doomed

1:10 bytecolor: depending on the complexity of macro expansions, they can generate enormous amounts of code

1:10 tomoj: also unfortunately, I'm sure any sane neural network code I write in clojure will be _slow_

1:11 right, but too enormous and you just get an exception at compile time :(

1:11 bytecolor: I don't have a book on neural networks. I'll put that on the todo list ;)

1:20 Derander: bytecolor: I just got my second. I'm excited.

1:23 bytecolor: tomoj: are the exceptions due to a blown stack?

1:23 i.e. not being able to recur in the tail position?

1:23 tomoj: no, functions get compiled into classes. classes (or methods in classes?) have a size limit

1:24 bytecolor: hrm, so it's a java.lang limit?

1:24 tomoj: that is you will get the same error if you try to write an enormously long java method

1:24 right

1:24 amalloy: tomoj: the world would be a better place if that limit were about a hundred lines

1:26 tomoj: lines don't exist at this level

1:26 amalloy: i know

1:26 it's my fantasy, though, so i nominate them

1:26 brehaut: there is nothing like 1500 lines of VBS class initializer to bring one to tears

1:26 tomoj: but, yes, agreed :)

1:27 amalloy: on a related note, i love how easy it is to write short functions in clojure. in java, c, or php, it always seems so easy to just make the method ten lines longer than break it up

1:27 bytecolor: holy sheet, 1500 lines of vbs *anything* ;)

1:28 tomoj: there was a blog post a while back, something like "clojure is faster than assembly"

1:29 bytecolor: what I've found interesting about clojure is the lack of C/C++ continue and break. I just don't think like that any more.

1:29 tomoj: I didn't understand it but the idea stuck with me, macroexpanding into super-fast code

1:29 two hands: it sucks that the size limit cripples you here, but I guess you shouldn't be doing that anyway

1:30 brehaut: tomoj: theres some really intersting work in haskell supercompilers going on that can do some incredibly whole-program optimisations

1:31 tomoj: is a supercompiler something different than a really good compiler?

1:31 Scriptor: brehaut: like with jhc?

1:31 brehaut: dont know about jhc, yhc was the one i had heard most about

1:32 amalloy: macroexpanding into actual code is so passe. just expand into the desired output like with C++ template programming

1:32 brehaut: tomoj: basicly the compiler does graph transformations on the whole program

1:33 it is capable of finding hidden state machines that the programmer may not have been aware of

1:33 bytecolor: c++ template compilation times are just not that great. look at boost. compilations times are horrible, but run times are white-knuckle fast.

1:34 great for an end user, not so great for a programmer.

1:34 brehaut: i understand that if you run a supercompiler you have to suffer similar long compile time ;)

1:34 tomoj: at least you can run the subcompiler and still get a working program?

1:34 brehaut: yup

1:36 GHC has a pretty intereting local rewriting optimisation sub system too http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/rewrite-rules.html

1:37 bytecolor: brehaut: are you writing any clojure core or contrib code?

1:38 brehaut: bytecolor: hell no

1:38 you dont want that

1:39 bytecolor: ahahah, well I was thinking it wouldn't be a bad idea to have a haskell programmer's point of view

1:39 brehaut: it already does ;)

1:39 and im a dabbler, im not fluent

1:39 bytecolor: I just have to learn haskell to see that.

1:39 tomoj: if I ever understand anything conal says I guess I can die happy

1:40 bytecolor: haskell syntax just seems so chaotic to me and I can't figure out why.

1:41 brehaut: tomoj: hah yes indeed

1:41 replaca: bytecolor: haskell syntax is juat radically different from what you get in other languages. You have to immerse yourself in it and then it can be beautiful

1:41 though, tastes vary

1:42 brehaut: bytecolor: the answer is threefold a) you havent grasped its whitespace rules b) you havent grasped the effects of pervasive curried functions, c) the type system is wickedly expressive

1:42 tomoj: isn't there (here of all places) also something to be said for minimal syntax?

1:42 bytecolor: replaca: I will admit I'm curry ignorant

1:43 brehaut: aside from the type notations i think haskell is pretty minimal syntax wise

1:43 bytecolor: er brehaut

1:43 tomoj: haskell's may be minimal compared to blub, but compared to a lisp?

1:43 replaca: bytecolor: like lisp, you don't feel it until you've lived in it for a while (and really *tried* to live the way it wants you to live)

1:43 bytecolor: not compared to common lisp, it isn't

1:45 replaca: haskell's syntax isn't so minimal, but it feels very terse when you write it (and therefore un-blub-like)

1:45 bytecolor: parentheses -> the next atom may be a function, hallelujah!

1:45 tomoj: terse? really? :P

1:45 brehaut: replaca: all the weight in haskells syntax comes at the type system though

1:47 bytecolor: seems as though clojure tries to emulate haskell's functional notation, although clojure's is limited by arity

1:47 brehaut: really?

1:47 bytecolor: well, from my limited knowledge

1:48 amalloy: brehaut: (update-in foo [a b c] assoc-in :k 1 :j 2)

1:48 feels more like haskell than clojure

1:48 bytecolor: are a, b and c keys?

1:48 amalloy: yeah

1:48 replaca: brehaut: mostly. Haskell gets stuff that looks like syntax from funny named functions

1:49 tomoj: amalloy: that particular example has always felt rather strange to me

1:50 never thought much about why

1:50 amalloy: tomoj: same for swap!, alter, etc

1:51 bytecolor: I've been using the shite out of swap!, but only because I dont grok the higher mutators

1:51 tomoj: I guess I always feel like the flattening will break something

1:52 I imagine in haskell you could pretty easily nest that deeper

1:53 bytecolor: swap! is synchronous, correct? No other thread is running that will try to change the first arg to swap!

1:53 now when you get into refs, it get's umm... interesting.

1:53 brehaut: i think that would look something like updateIn foo [a b c] $ updateIn [(K, 1), (J, 2)]

1:55 bytecolor: tomoj: *why* is the greatest question ever asked ;)

1:55 tomoj: bytecolor: they might try, only one will succeed

1:55 amalloy: only one at a time, anyway

1:57 bytecolor: so, slap me if you will, but from a layman's point of view, clojure is a language that, to be of interest, requires many, many cores.

1:58 amalloy: bytecolor: or a desire to not have the zillions of programming errors mutation causes

1:58 tomoj: i

1:59 bytecolor: amalloy: nod, and that come from an individual writing the lock code that "knows what the hell he's doing", i.e. hickey

2:01 I've seen a couple other names that have a background in multi-core programming, joy of clojure comes to mind. Are cores going to follow memory?

2:01 brehaut: its not just knowing where to put the locks, but having done the work to determine good models to implement at all

2:02 bytecolor: brehaut: I'm such a n00b in multi-threading. I really am. But that *has* to be the next step.

2:02 brehaut: im confused

2:03 bytecolor: We have enourmous amount of memory, but it's all being piped through a bottle-neck.

2:03 a single processor, or 4, or 8

2:03 brehaut: i think messages got out of order

2:04 bytecolor: ahahaha

2:06 I saw a podcast. I found it through searching clojure. Steele's Fortress maybe? It was fantastic. No so much as how to divide a problem up into threads, but how to combine the results of those threads into a useable data structure.

2:08 amalloy: bytecolor: i think you are focusing too much on concurrency. it's nice, but it's not the only benefit of immutability, which in turn is not the only nice clojure feature'

2:09 bytecolor: amalloy: It's all new an shiny to me ;)

2:10 semperos_: it stays shiny

2:11 brehaut: the funny thing about immutability is it starts off seeming like its definately going to make life harder, where in reality there is a huge huge realm of problems where its the exact opposite

2:13 tomoj: personally I hardly ever use clojure's concurrency features and I still love it

2:13 brehaut: likewise

2:13 most common thing for me is to use pmap i think :P

2:14 its a lazy mans fork-join :P

2:14 semperos_: for me, having the concurrency semantics makes me think about state very critically

2:15 amalloy: brehaut: and for me the most common concurrency feature is "start a thread to do this expensive operation the user asked for, then get back to interacting"

2:15 brehaut: amalloy: i havent done any gui programinning in clj since 08

2:16 amalloy: brehaut: who said gui?

2:16 bytecolor: but the mind accepts parellel data. sound, sight, touch, etc. It processes that data and produces a thougt. It does *not* produce an output, it produces a thought. What is that thought? Is it a cache of ideas?

2:16 brehaut: s/g// ?

2:16 amalloy: it happens to be sexpbot most of the time :P

2:16 brehaut: ah haha

2:16 im mostly doing web stuff

2:16 amalloy: "message just came in, get to work"

2:16 bytecolor: ahaha, havent't heard a bot muse in a while

2:17 tomoj: bytecolor: can you have a thought that has no effect whatsoever on your behavior?

2:17 amalloy: yeah i really need to learn ring. it sounds like it must be so easy to write webapps

2:17 bytecolor: tomoj: yes

2:17 brehaut: amalloy: do you know how to write a function that accepts a map and returns a map?

2:18 amalloy: brehaut: man, i almost didn't realize you were talking about ring

2:18 brehaut: hah

2:18 amalloy: i was like, yes, you write "identity"

2:18 bytecolor: tomoj: it's a state, but it's one of many

2:18 semperos_: I found moustache to be a nice place to start with ring

2:18 brehaut: classic

2:18 thats an illegal ringhandler btw ;)

2:18 tomoj: bytecolor: a thought is a state, you think?

2:18 bytecolor: wtf is moustache?

2:18 * tomoj forgets this isn't ##philosophy

2:18 brehaut: the only other thing for ring is (future (start-jetty {:port 8000}))

2:18 semperos_: micro web framework

2:18 bytecolor: tomoj: ahahaha

2:19 amalloy: bytecolor: we'll explains when you're older

2:19 semperos_: consists of one macro :)

2:19 it's a nice way to deal with Ring

2:19 and ring's features

2:19 and actually get something done

2:19 brehaut: semperos: thats unfair to both moustache and ring

2:19 amalloy: brehaut: (def handler (constantly {:response-code 500 :body "Not implemented yet"}))

2:19 semperos_: brehaut: how so?

2:19 brehaut: amalloy: perfect

2:19 semperos_: well you are still writing ring handlers and middleware even if you are using moustache

2:20 amalloy: out of curiosity how close was i on the keyword names?

2:20 bytecolor: tomoj: philosophy and programming are not disjoint

2:20 brehaut: :response-code is :status

2:20 semperos_: brehaut: right, that's why I like it

2:20 it provides a nice way to combine everything

2:20 but there's no "magic" over ring, you just get it with benefits

2:21 brehaut: semperos_: i agree; but i would personally encourage anyone starting out to start with ring first

2:21 tomoj: bytecolor: sure, which is one of the things that attracted me to clojure, I think. rich talking about whitehead and all

2:21 semperos_: brehaut: fair enough

2:21 tomoj: but my obsession for phil of mind doesn't belong here unfortunately :(

2:21 bytecolor: tomoj: I've been meaning to read whitehead, haven't gotten around to it yet, alas.

2:23 tomoj: start with ring then switch to aleph :P

2:25 bytecolor: philosophy *does* have a place in programming, it will become more apparent in subsequent generations.

2:26 tomoj: have you seen the "are we there yet" talk yet?

2:26 if not, do so

2:26 brehaut: i hate applescript

2:26 bytecolor: hrm, I think I have, there-fore I must have.

2:29 I tried to learn nurb surfaces from apple-script once. it was actually a really good description. I just didn't posses the brain cells to grok it.

2:31 brehaut: i am going to be social. ttyl

2:31 bytecolor: I wonder what egotistical bastard would use the name grok.

2:31 later brehaut

2:32 tomoj: what, you checked whether 'grok' was a registered nick?

2:33 bytecolor: na, just wondering. I'll bet there are some out there that would use it.

2:34 and the say part: they would not have a clue wtf grok means

2:35 tomoj: now I worry I don't have a clue either

2:36 bytecolor: didn't hickey used to idle in here?

2:37 tomoj: maybe too many people said clojure was awesome

2:38 bytecolor: then again, maybe his ego got too large, because clojure just isn't that awesome. Not when you look at users. I'm not knocking clojure, I'm knocking the creator.

2:40 gregh: wait, are you saying clojure users aren't awesome?

2:41 semperos_: I don't think you'll find any Rich Hickey worshippers in here, but Rich is a seriously intelligent individual who has created something of profound value and given it to the community

2:41 and from the many videos I've watched of him, he is surprisingly devoid of ego

2:43 tomoj: bytecolor: for context, I was referring to his disdain for the word "awesome"

2:45 s/referring/alluding/ ?

2:45 * tomoj kisses sexpbot

2:45 amalloy: lol

2:45 bytecolor: semperos_: I'm not questioning hickey's intelligence, I've watched enough vids to convince me that the man is quite intelligent. My only query... Why do the creators always leave? Simple question. I think it deserves a simple answer. And if money is a part of the answer, then I am dissapoint.

2:46 semperos_: bytecolor: in what way has he left?

2:46 tomoj: er, you deserve the kiss of course, but I imagine you don't want it :)

2:46 amalloy: tomoj: i think that wouldn't have triggered him anyway, before my change. if anything came after the trailing slash he didn't parse it

2:46 s/change/GENIUS IMPROVEMENT/ ?

2:46 tomoj: unfortunately I would've been too dumb to remember that

2:48 dunno about rich, but I wish I had the discipline not to type M-x freenode

2:49 semperos_: bytecolor: if you just mean the irc channel, then I agree with tomoj, wish I had the discipline :)

2:50 rata_: hi

2:51 semperos_: howdy

2:51 bytecolor: clojure?

2:51 clojurebot: clojure is not scheme

2:52 bytecolor: muahahaha, but it is, it uses ? as predicates, and that is a "good thing"

2:52 it uses ! for in-place mutators, an that is a good god damn thing

2:54 tomoj: doesn't ruby (with middling consistency) do both of those?

2:55 bytecolor: scheme did not survive to the next generation because it had big tits, it survivec because it produced the correct result.

2:55 fuck ruby

2:55 I mean really, fuck ruby

2:56 what the fuck has ruby done for me lately?

2:58 tomoj: did you buy AAPL?

2:58 Raynes: Stop with the f-bombs, man. You're offending the little old lady in all of us.

2:58 bytecolor: Raynes: ok, I can do that

2:58 tomoj: the little old lady in me is a vulgar cunt

2:59 amalloy: tomoj: swearing with style since 19...something

3:00 tomoj: damn less-than-111-year-old whippersnappers

3:00 bytecolor: raise your hand if scheme rawks

3:00 !

3:02 ok, so there are a lot of conservatives among us, and thats ok.

3:07 What really bugs the fuck out of me is syntax. simple syntax. Do you mutate? put a fucking ! on the end of your symbol. are you a predicate? put a fucking ? on the end of your symbol. These are scheme idea. They are not bad ideas. They are sound ideas. Adopt them. Clojure alomost does. Clojure almost has it right.

3:07 tomoj: almost?

3:08 bytecolor: ! and ? are epic in lisp programs.

3:11 rata_: bytecolor: I like scheme too and I find it's cool (but I don't know the subtleties of what the rocks expression means, so I don't know if it rocks)

3:13 bytecolor: fucking is an adjective, do you remember adjective from 6th grade?

3:13 rata_: the only thing I think they got wrong was to not make strings be sequences... the sequence abstraction is very powerful

3:14 tomoj: do you often seq strings?

3:14 rata_: tomoj: yes, why the question?

3:15 bytecolor: whom are you aiming that question?

3:16 bytecolor: if you'll look at, ok the string lib is a piece of shit. it really is. just try to find it.

3:16 rata_: the future

3:16 tomoj: rata_: just curious

3:16 that strings are seqable seems occasionally useful to me, not fundamental

3:19 rata_: for me it's a pity that in scheme you can't use map, reduce (fold*) and the whole sequence library on strings

3:19 anthony__: This is probably a really stupid question, but is print okay to use in a transaction? (will it only print to *out* if the transaction is successful?) I'm guessing it isn't, but I don't have a really good way to test it...

3:20 rata_: anthony__: the transaction can be retried many times, so the printing will be done many times too

3:20 if that doesn't annoy you, it's ok

3:21 anthony__: rata_: Thanks -- that's what I expected. I didn't know if maybe it was buffered until the end of the transaction (seems impossible), or if it went straight to *out*

3:21 bytecolor: anthony__: the repl will lie to you. try (count foo...))

3:22 anthony__: bytecolor: I'm not quite sure what you mean.

3:24 bytecolor: the repl shows the printed output in the result of a map

3:25 that's fucked up

3:25 map, print, return the output

3:26 anthony__: Oh, gotcha. Yeah.

3:27 bytecolor: it's not part of the output, but it *displays* as part of the output.

3:27 that's fucked up

3:28 fucked-up=invalid-output, for those that read too much of the bible

4:28 thorwil: hi! i'm trying out appengine-magic. "lein appengine-new" fails with "That's not a task".

4:28 any tips on troubleshooting that?

4:40 nm, seems i'm reading impaired and mixed up :dependencies and :dev-dependencies :)

4:51 hiredman: k

6:52 Cozey: How can I replace some jar referenced in project.clj (i use cake) with my own version of this jar (I'm fixing a bug, and want to use my build until the issue is fixed upstream)

6:54 raek: Cozey: with leiningen, you can use the checkouts feature

6:55 Raynes: Cake has that feature as well, but that isn't what he looking for in this case.

6:55 raek: I guess it could also be possible to install an updated jar in your local maven repo (~/.m2) somehow

6:55 Cozey: I never figured out how to menage my own m2 repo

6:55 manage*

6:56 Raynes: Cozey: You can just build the jar and, if you aren't going to be putting your project into production, just do 'cake install' to install it in your local repository. Otherwise, you can modify the other project's project.clj to qualify the project name with your own clojars groupId and then push your own version to clojars and use that.

6:56 raek: well, you already have one. maybe it's called a "cache" rather than "repo"

6:57 Cozey: i now, it sits in ~/.m2, but i played with maven once trying to install something and got into a dependency hell of some kind

6:57 from that time i respect maven, but I don't fancy getting too much into it, if i can use it indirectly via cake or lein

6:58 clojars is a good idea - it would keep the setup almost as is

6:59 raek: cake/lein install should be like pushing to a "local clojars", if it works the way I think

7:00 Cozey: will try

7:01 is any of cake/lein getting better then the other?

7:01 or is it a religious question?

7:02 raek: this post helped me understand why there are two at all: http://blog.fogus.me/2010/11/30/take-6-justin-balthrop/

7:03 I currently use lein, but I have a very strong feeling that if someone would do a "alias lein=cake", I would not notice

7:04 (99% of the time, I only use the new, deps, repl and swank commands)

7:17 Cozey: cake chose me by luck.

7:30 fbru02: hey guys morning ! what is the key for bringing up slime buffer in emacs?

7:31 Cozey: I'm not sure if there is one by default. I had to bind slime-repl to ^c r

7:31 (add-hook 'clojure-mode-hook

7:31 '(lambda () (global-set-key (kbd "^c r") 'slime-repl)))

7:32 fbru02: Cozey: thanks I will try that

10:34 pdk: is there an apt repository with up to date clojure/clojure-contrib in it

11:20 pppaul: anyone know a site that explains how to use reduce?

11:20 fliebel: pppaul: More extensively than ##(doc reduce)?

11:20 sexpbot: ⟹ "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well... http://gist.github.com/823850

11:21 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

11:21 pppaul: i read that already

11:21 i want some examples, and the ones on clojuredocs suck

11:22 fliebel: hmmm...

11:22 Vinzent: pppaul, htdp.org

11:22 fliebel: https://github.com/search?type=Code&language=clojure&q=reduce&repo=&langOverride=&x=8&y=18&start_value=1

11:23 pdk: (reduce + 1 2 3 4) is equivalent to (+ (+ (+ 1 2) 3) 4)

11:23 pppaul: ok

11:23 that makes a bit more sense

11:23 pdk: in this case it assumes that + takes 2 arguments

11:23 it does (+ 1 2) first

11:24 then calls + with the result of the first addition and 3

11:24 then calls + with THAT result and 4

11:24 until reaching the end of the list

11:24 pppaul: (reduce (fn [i1 i2] (+ i1 i2)) 1 2 3 4 5) is the same?

11:24 pdk: naturally reduce expects the function you give it to take 2 arguments

11:25 should be

11:25 fliebel: reduce iterates over a list, calling the function with the previous result and the next item.

11:25 pppaul: so, my problem, i guess, was that i was giving reduce a seq

11:25 should i use apply in this case?

11:26 pdk: if the fn you're trying to apply to the seq only takes 2 args

11:26 fliebel: pppaul: As far as I know redce *does* take a seq, and nothing but a seq.

11:26 pppaul: oh

11:26 pdk: (doc reduce)

11:26 cmon bot

11:26 ##(doc reduce)

11:26 sexpbot: ⟹ "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well... http://gist.github.com/823855

11:26 pdk: yeah

11:26 pppaul: (reduce (fn [i1 i2] (+ i1 i2)) '(1 2 3 4 5)) then?

11:26 pdk: so that example above shouldve been (reduce + [1 2 3 4])

11:27 fliebel: &(reduce (fn [i1 i2] (+ i1 i2)) '(1 2 3 4 5))

11:27 sexpbot: ⟹ 15

11:27 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the re

11:28 pppaul: i'm trying to reduce a hash-map to a string

11:28 (reduce #(str (:name %2) "\n" %1) myhashmap)

11:28 fliebel: pppaul: Almost!

11:29 pppaul: (reduce #(str (:name %2) "\n" (:name %1)) myhashmap) makes a string of 1 item

11:29 fliebel: &(reduce irc://irc.freenode.net:6667/#(str (:name (key %)) "\n"  (val %)) {:a 1 :b 2)

11:29 sexpbot: java.lang.Exception: Unmatched delimiter: )

11:29 pppaul: so, i'm not sure what i'm doing wrong

11:30 hmm

11:30 jkrueger: pppaul: your version assumes that the reduce fn takes two arguments, while it only takes one

11:30 pppaul: &(reduce (str (:name (key %)) "\n"  (val %)) {:a 1 :b 2})

11:30 sexpbot: java.lang.Exception: Unable to resolve symbol: str� in this context

11:30 pdk: when you use % within a #() function

11:30 fliebel: &(reduce #(str %1 (:name (key %2)) "\n" (val %2)) "" {:a 1 :b 2})

11:30 sexpbot: ⟹ "\n1\n2"

11:30 pdk: every time you use % it refers to the same first argument

11:31 pppaul: ...

11:31 jkrueger: pppaul: forget what i said. it was rubish...

11:31 pppaul: i'm using %1 and %2

11:31 gah! reduce!

11:32 &(reduce (str (:name (key %)) "\n"  (val %)) {:a 1 :b 2})

11:32 sexpbot: java.lang.Exception: Unable to resolve symbol: str� in this context

11:32 pppaul: &(reduce #(str (:name (key %)) "\n"  (val %)) {:a 1 :b 2})

11:32 sexpbot: java.lang.Exception: Unable to resolve symbol: str� in this context

11:32 pdk: %(reduce str {1 2 3 4 5 6})

11:32 &(reduce str {1 2 3 4 5 6})

11:32 sexpbot: ⟹ "[1 2][3 4][5 6]"

11:32 pppaul: ...

11:33 fliebel: &(reduce (fn [i [k v]] (str i k \newline v)) "" {:a 1 :b 2})

11:33 sexpbot: ⟹ ":a\n1:b\n2"

11:33 pppaul: hmmm

11:33 pdk: we're just pulling stuff out our asses now :p

11:33 pppaul: lol

11:33 jkrueger: fliebel: that's more obvious :)

11:33 pppaul: maybe i should just use map and string/join

11:34 fliebel: pppaul: If you know how destructuring works, you can see that I str the previous/initial value i to the k and v of the map. Iterating over a map returns pairs.

11:34 pppaul: i really want to know how to use reduce, though

11:34 i'm iterating over a seq

11:34 a seq of maps

11:35 (:name %) works

11:35 pdk: keyword args can be used as functions themselves if their argument is a map

11:35 pppaul: ok, how about this, i'll write the code using map + string/join, and then maybe you guys can tell me how to make it a reduce

11:35 pdk: so instead of #(:name %) you could just stick name in there

11:35 er :name

11:35 pppaul: cool

11:36 fliebel: pppaul: In that case, you where almost there, just add the initial value to the str.

11:37 pppaul: (->> *s360accounts-salutation-errors*

11:37 (map :name ,,,)

11:37 (string/join "\n")

11:37 println)

11:38 mfex: hi all, any ideas why I can't do a Thread/sleep in a lein repl?

11:38 pppaul: use swank?

11:38 companion_cube: ,(reduce (comp (partial str "\n") (partial :name)) {1 2 3 4})

11:38 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (1) passed to: core$partial

11:39 companion_cube: ,(reduce (comp (partial str "\n") :name) {1 2 3 4})

11:39 clojurebot: "\n[3 4]"

11:39 companion_cube: err

11:39 pppaul: ,(reduce (comp (partial str "\n") :a) ({:a 1} {:a 2}))

11:39 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :a

11:39 pppaul: :(

11:40 ,(reduce (comp (partial str "\n") :a) '({:a 1} {:a 2}))

11:40 clojurebot: "\n1"

11:40 clgv: lol. can't you describe in words what you want to do?

11:40 fliebel: pppaul: Try juxt

11:40 pppaul: ,(reduce (juxt (partial str "\n") :a) '({:a 1} {:a 2}))

11:40 clojurebot: ["\n{:a 1}{:a 2}" 1]

11:40 companion_cube: the seek of the holy one-liner...

11:40 pppaul: i thought my above code was pretty clear, though

11:40 is it not?

11:41 get a list of names from a list of hash-maps, interleave with newlines, make into a string

11:41 fliebel: &(reduce #(str %1 "\n" (:a %2)) "" [{:a 1} {:a 2}])

11:41 sexpbot: ⟹ "\n1\n2"

11:41 pppaul: :D

11:41 success!

11:42 thanks a lot

11:42 clgv: lol k ;)

11:43 pppaul: &(reduce #(str %1 "\n" (:a %2)) "" [{:a 1} {:a 2}{:a 2}{:a 2}])

11:43 sexpbot: ⟹ "\n1\n2\n2\n2"

11:44 fliebel: &(apply str (interpose \newline (map :a [{:a 2} {:a 5} {:a 2} {:a 5} {:a 2} {:a 5}])))

11:44 sexpbot: ⟹ "2\n5\n2\n5\n2\n5"

11:45 fliebel: I think str was one of the few things where using apply in a case like this makes sense. + does reduce internally anyway, for example.

11:46 But then string/join makes even more sense.

11:46 incandenza: &(reduce #(str %1 (name (key %2)) " " (val %2) "\n") "" {:a 1 :b 2})

11:46 sexpbot: ⟹ "a 1\nb 2\n"

11:49 clgv: &(str-join \newline (map :a [{:a 2} {:a 5} {:a 2} {:a 5} {:a 2} {:a 5}]))

11:49 sexpbot: java.lang.Exception: Unable to resolve symbol: str-join in this context

11:50 clgv: &(clojure.contrib.str-utils/str-join \newline (map :a [{:a 2} {:a 5} {:a 2} {:a 5} {:a 2} {:a 5}]))

11:50 sexpbot: ⟹ "2\n5\n2\n5\n2\n5"

11:50 clgv: fliebel: thats even shorter ;)

11:51 fliebel: clgv: See the solution pppaul provided using clojure.string/join

11:51 clgv: ah kk ;)

11:57 pppaul: :)

12:08 pdk: i love you ubuntu

12:08 >gem install cake

12:08 >cake

12:08 fliebel: php?

12:09 pdk: "cake isn't installed, do sudo apt-get cakephp-scripts

12:09 yeah that's the rub

12:09 clojurebot: make a note of http://scienceblogs.com/goodmath/2006/11/the_c_is_efficient_language_fa.php it is yet another article about picking c or c++ for performance being naive

12:09 pdk: clojurebot's developed sentience

12:09 and he's got a robo axe to grind in the languages world

12:10 fliebel: pdk: You can create a custom alias I guess.

12:10 Or use the full path, like real man :P

12:10 pdk: i don't really know where gem and apt put their packages so :p

12:11 pppaul: why would you use cake over lein?

12:11 fliebel: pdk: Have you tried $which cake?

12:11 pppaul: persistent vm, tasks, and other goodies.

12:11 pdk: same thing as running cake

12:11 i managed to get lein installed

12:11 though when i got clojure through apt it was 1.1

12:12 and i recall reading something about installing clojure through cake or lein, forget which

12:12 pppaul: persistent vm, as in when you turn it off and boot it up again it's the same?

12:12 pdk: so i figured i could update it that way since i don't know where apt stuck the jars

12:12 let alone if contrib installed alright

12:12 pppaul: what's a task?

12:12 fliebel: pppaul: No, it just stays up inbetween repl sessions.

12:12 pppaul: lein does that

12:12 via swank

12:12 it's how i'm coding right now

12:13 command: lein swank

12:13 what's a task?

12:13 fliebel: pppaul: Read the readme ;) https://github.com/ninjudd/cake#readme

12:13 pppaul: pff

12:13 i did read the cake stuff

12:14 fliebel: pdk: My cake lives in /opt/local/bin/cake

12:14 pdk: hell if i could just figure out where it put clojure and then update it id be happy then i'd fuss with lein/cake wars

12:14 i tried putting it in /bin/cake

12:14 then adding that to $PATH

12:14 still does it

12:14 sudo chmod +x cake aftward doesn't fix it

12:15 fliebel: pdk: Hm, so either name it clj-cake, so that it doesn;t tigger the msg, or installke cake-php, and make sure that your cake is on the path first.

12:17 pdk: hm

12:17 do i just change the name of the folder with cake in it to clj-cake

12:25 fliebel: pdk: No, the binary.

12:26 pdk: something tells me i ended up with the cake source in /bin/cake

12:26 a folder with project.clj and everything

12:26 let's see if i xcopy the lein install approach like the docs say

12:27 fliebel: pdk: In that case, the actual binary is in /bin/cake/bin/cake, of bin/cake is where the project.clj lives.

12:27 pdk: love that shit

12:28 there we go

12:28 ghetto lein style install seems to work

12:28 pppaul: if i want to print out a string, and save it to a file, is #(comp println (parital spit "file") %) the way to do that?

12:28 fliebel: ghe, if I remember correctly, I settled on using ~/git/cake/bin/cake all the time.

12:28 pdk: at least now it doesn't piss and moan about missing a server jvm install like it did on 7

12:29 i dunno what the hell was up with that

12:29 fliebel: pppaul: juxt

12:29 pdk: but apparently i was mising a /server/jvm.dll in the java install dir

12:29 when there wasn't even a /server subfolder there MY OH MY

12:29 pppaul: when would i use juxt over comp?

12:29 fliebel: well...

12:29 pdk: (doc bindings)

12:29 clojurebot: Excuse me?

12:30 fliebel: &((juxt + *) 2 5)

12:30 sexpbot: ⟹ [7 10]

12:30 pdk: could always do something like (binding [*out* (java.io.FileWriter. "file")] (println "foo"))

12:30 fliebel: &((comp println +) 4 5)

12:30 sexpbot: ⟹ 9 nil

12:30 pppaul: hmm

12:31 (comp f g) = f(g())?

12:31 pdk: yes

12:31 pppaul: (juxt f g) = f()g()

12:31 pdk: rather

12:31 fliebel: yes

12:32 pdk: (comp f g) = (fn [% args] (f (apply g args)))

12:32 if you call the function produced by (comp f g) with any args

12:32 all the args get passed to g

12:32 then the return value of g is passed to f etc

12:32 so all but the last function you pass to comp should take 1 argument

12:32 pppaul: i understand that

12:33 i just want a function that will let me fork a thread (->>

12:33 so, juxt it is

12:33 fliebel: Hm, I'm thinking about some sort of function tree, or function spreader…

12:34 pdk: (doc juxt)

12:34 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Alpha - name subject to change. Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

12:35 pppaul: yup

12:36 fliebel: &(map #(%1 %2) [reverse inc dec] ["hi" 4 5])

12:36 sexpbot: ⟹ ((\i \h) 5 4)

12:37 chouser: lazy trees are hard for my poor brain

12:37 pppaul: i get a NPE :(

12:37 ((juxt

12:37 (println)

12:37 (partial spit "accounts with salutation fixes to be uploaded.txt")

12:37 ),,,)

12:38 this is part of a thread (_>>

12:38 (->>

12:39 fliebel: chouser: What does a lazy tree do?

12:39 chouser: well, specifically I mean a lazy tree of a lazy seq

12:40 trying to turn a series of events like [a :down b :down c d :up :down e f :up :up] into (a (b (c d) (e f))

12:40 ...but lazily

12:41 * chouser goes off to ponder some more

12:42 fliebel: So, taking c consumes a :down b :down c...

12:46 kgrad5_: Hello, I am having trouble including clojure-contrib with my repl. I am launching the repl with java -cp path/to/clojure-contrib.jar -jar path/to/clojure.jar however when i try to (use 'clojure.contrib.str-utils) I get a FileNotFoundException. I have tried printing out my ClassPath and clojure-contrib is not on it.

12:46 If it matters, I am using clojure 1.2.0 and contrib 1.1.0

12:47 TimMc: kgrad5_: I highly recommend using lein or cake to interact with clojure.

12:47 kgrad5_: TimMc: thanks, I will go look at those, I am a first timer.

12:47 TimMc: With Leiningen, I just run `lein repl` and it Does the Right Thing.

12:47 (lein and cake are both build tools for Clojure)

12:50 incandenza: for future reference, though, I think the -jar option overrides all other classpaths (everything is supposed to be in the .jar)

12:50 kgrad5_: incandenza: ah ok, so what would the proper way be to launch from the cmdline with contrib on the classpath?

12:51 TimMc: kgrad5_: Oh yeah, that's right -- I think for -cp you need a colon-delimited set of directories and jars.

12:51 incandenza: you put both in the -cp and then give the name of the class with the repl to run... forgot the exact syntax

12:51 kgrad5_: clojure.lang.Repl?

12:51 clojurebot: you mean clojure.main

12:51 raek: java -cp clojure.jar:clojure-contrib.jar:something-else.jar:source-directory/ clojure.main

12:52 kgrad5_: great! thanks everyone :D

12:52 incandenza: right, there you go

12:58 TimMc: kgrad5_: But definitely check out lein/cake.

13:00 kgrad5_: thanks TimMc, checking out lein right now, still useful to know how to do it properly from the commandline too.

13:00 TimMc: indeed

13:23 chouser: woo! got it. now to make it usable...

13:26 fliebel: chouser: Can you paste? Or is it private?

13:27 chouser: not private, but raw

13:27 it'll end up in lazy-xml eventually.

13:27 fliebel: chouser: Neat!

13:28 How does lazy-xml currently work?

13:28 chouser: https://gist.github.com/823958

13:28 lazy-xml currently returns a lazy tree, but someone found that it's a little too eager

13:29 it forces the parsing of one sibling beyond what you need, at every level of the tree.

13:29 fliebel: oh, interesting...

13:30 chouser: since parsing the next sibling requires parsing the full content of the current node, it makes the laziness essentially useless when there's one node with a very large number of children

13:31 fliebel: chouser: Isn;t all xml one root node with a lot of children?

13:32 hm, if you'd provide predicates for up and down, it'd be like the inverse of tree-seq.

13:32 chouser: fliebel: inverse, yes, that's the idea

13:34 fliebel: And you do (rest coll) in a lot of places, why not destructure that? (i know you said this was raw)

13:35 oh, right, *when*-ket

13:37 No, that would work, right?

13:37 (when-let [[event & nodes] (seq coll)]

13:38 * fliebel looks at the source of when-let

13:44 chouser: destructing & uses 'next' not 'rest', so it forces another step

13:52 fliebel: chouser: oh

14:15 TimMc: amalloy_: I did end up using meta for something: https://github.com/timmc/CS4300-HW3/blob/master/src/timmcHW3/core.clj#L112

14:16 clojurebot: #<RuntimeException java.lang.RuntimeException: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated>

14:16 fliebel: hiredman: Clojurebot is doing funny things.

14:17 TimMc: amalloy_: See the usage on line 271 and the processing code in act! around line 160. Basically, the function specifies some details of how it is to be used.

14:28 markskilbeck: Hi, all. I'd like to pause/sleep for every iteration of a loop, but Thread/sleep doesn't seem to do the job.

14:29 Any ideas?

14:33 Oh. Sleep takes milliseconds.

14:33 2 milliseconds ain't a long time :P

14:38 ,(some zero? [1 2 3])

14:38 clojurebot: nil

15:01 jaskirat: markskilbeck: (doseq [x (range 10)] (Thread/sleep

15:01 1000)(println x)) doesnt work?

15:04 julian-: bunnies

15:06 pppaul: i agree, but, rabbits

15:06 julian-: pppaul: Yeah, but we can face those.

15:07 I mean, there's nothing we can't face, except for the aforementioned member of the Leporidae family.

15:08 pppaul: because he has no face?

15:08 julian-: pppaul: http://www.youtube.com/watch?v=cW20AlC0IbA

15:11 pppaul: it won't play

15:11 the others will, though

15:11 * julian- should wander back to the IRC client support channel from where he came

15:12 pppaul: add block killed it

15:13 sorta funny, the singing is soooooooo bad

15:14 well, i just missed my bus

15:36 * thorwil is puzzled about java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup)

16:08 rata_: hi

16:09 Scriptor: hey rata_

16:09 rata_: hi Scriptor

16:14 kjeldahl: So, I'm giving up on enlive, about to test fleet. Anybody else have any nice hints for modern supported template solutions for clojure?

16:15 rata_: kjeldahl: what's the problem with enlive?

16:16 when you vec a lazy-seq, does it copy it?

16:16 kjeldahl: rata_: It caches to agressively. Sometimes (or always) the template I pull in with deftemplate simply refuse to reload. There's a ticket for it pending for more than one year. I do not feel up to the task of solving it myself yet.

16:17 rata_: Plus looking at the commit log doesn't exactly scream of being well supported (considering the tickets).

16:18 rata_: oh ok

16:25 chouser: kjeldahl: the author has recently become a father. That may or may not be related to support lag. :-)

16:27 kjeldahl: chouser: He he, I can imagine (I've got two myself, 4 and 6 years old). Thanks for letting me know anyway; maybe I'll try to fix it myself after all...

16:30 chouser: kjeldahl: well, I'm not suggesting that means you shouldn't find another lib that works better out-of-the-box for you.

16:32 LauJensen: kjeldahl: Typically when working with Enlive, I just add a wrap-reload middleware to my stack and the templates update on every view

16:34 rata_: is there a short article (like a cheatsheet) about doing common things with swing?

16:34 kjeldahl: LauJensen: You stick the templates files themselves in wrap-reload? I already have the clj file where the deftemplate macros gets set up wrapped with wrap-reload, but it still fails to reload my template html files.

16:35 LauJensen: kjeldahl: (wrap-reload '[myapp.templates]), then keep all templates in that file/namespace. It will suceed unless there's an error in that file in which case it will fail silently

16:36 kjeldahl: LauJensen: That's what I do also. Either it doesn't work, or somehow stops working over time.

16:36 LauJensen: And you're certain its not an error on your part?

16:37 kjeldahl: Absolutely not. But it always work when I restart the server.

16:38 LauJensen: Ah ok. Are you on the latest versions of ring/moustache and enlive?

16:39 kjeldahl: I do not use moustache. Enlive tag is 1.0.0-SNAPSHOT, and since enlive hasn't been updated for a long time, I guess that's the latest.

16:39 anthony__: I'm stuck on some java interop. I've created a proxy for j.u.Comparator and implemented the compare method. But, I need to create a field and constructor for it. How do I do that in proxy? (can I?)

16:40 Chousuke: Why do you need a proxy for comparator?

16:40 (doc comparator)

16:40 clojurebot: "([pred]); Returns an implementation of java.util.Comparator based upon pred."

16:41 anthony__: Chousuke: Ah man, awesome. Thanks so much

16:42 Chousuke: (actually any function returning bool should work as is)

16:46 kjeldahl: Wrapping in wrap-reload definitively does not work, this is what I'm doing though: (deftemplate index_t "www/index_t.html" ... ) Whenever I modify index_t.html I have to restart the server. Get's kind of tedious...

16:47 LauJensen: kjeldahl: I understand. Completely the problem wrap-reload should solve. What if you manually reload the templates namespace/file?

16:48 kjeldahl: Reloading in repl works.

16:49 LauJensen: So it sounds like you need to take a closer look at wrap-reload

16:50 kjeldahl: You mean you think ring isn't working like it should?

16:50 LauJensen: If manual reloading works, then I cant think of another possible point of failure

16:51 kjeldahl: Ok, thanks for the hint.

16:59 LauJensen: kjeldahl: np. I haven't seen the implementation, but if you make your own middleware as a really naive call to :reload-all, that might work

17:01 kjeldahl: I believe my problem is some wierd combination of running a server inside repl, reloading inside repl and wrap-reload and family. Sometimes the server also simply stops after I use a :reload-all (which doesn't autostart any server and such). So things _sometimes_ fails, and _sometimes_ work. That's the frustrating part.

17:03 LauJensen: Sounds very frustrating. Would be great if you could exactly pinpoint the problem. I recall it happening to me once, but 9/10 times it just works. I also do webdev with ring/moustache/enlive/clojureql

17:04 kjeldahl: Thanks for the info. I'll share whatever I'm able to figure out.

17:04 LauJensen: Great, looking forward to it

17:21 kjeldahl: Ok, I at least found a repeatable failure pattern. 1. load the "core" clj file. 2. call "boot" method (which starts the server using defonce). 3. modify "core" clj file (inside comment is enough). 4. reload "core" clj file with :reload-all. 5. attempting to load page gives an endless 301 redirect loop to /. I may be able to create a minimal testcase and solve it later unless somebody beats me to it.

17:23 Oh, and the "core" file was also wrapped in wrap-reload...

17:48 LauJensen: kjeldahl: tried writing a naive reload middleware?

17:59 chouser: does contrib standalone fail to build for anyone else?

18:37 arohner: is there a library that adds higher level navigation to XML docs parsed by clojure.xml?

18:38 with fns like "give me the tag with this name"?

18:39 brehaut: arohner: the zip library has xml zipping

18:40 and a fantastic xml-> fun

18:40 arohner: brehaut: oh right. I forgot about that, thanks

18:46 brehaut: arohner: clojure.contrib.zip-filter is what i was thinking of

18:47 as well as zip

19:28 _Vi: My program have 2 parts: GUI (Swing) and backend. When user performs action in GUI, it does "(send backend-agent qqq)". What do to if backend wants to callback to GUI (to ask a password, for example)? Block inside qqq while waiting for some reaction from GUI?

19:29 brehaut: _Vi swing provides a run queue

19:30 i think its called Invoke soemthing

19:31 _Vi: brehaut, What should backend do? Currently there is "(defprotocol BackendInterface ...)" that contains the interface of backend exposed to GUI. What should I add to make backend call back to GUI? (The backend itself should not know about Swing)

19:32 brehaut: the backend calls SwingUtilities/invokeLater with a Callable or Runnable

19:33 an example of a callable or runnable in clojure is anything that implements ifn, eg a function

19:33 http://download.oracle.com/javase/6/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable)

19:33 _Vi: brehaut, Backend wants information (the password) that needs to be returned to library function.

19:34 brehaut: you make the function you pass to invoke pass that to the agent or thread that is doing the work

19:34 _Vi: brehaut, GUI -(connect)-> backend. Backend connects to server. Connection procedure (external library) callbacks with "askPassword" inside backend. Backend should callback to GUI.

19:35 brehaut: _Vi i dont have a magic bullet for you. you have to get the backend to pass a function to the UI thread via InvokeLater to request the password fro mthe user and pass that back to the background thread

19:35 _Vi: OK, trying Invoke and waiting when it completes.

19:35 brehaut: you certainly can try that

19:44 _Vi you might also want to look at promise and deliver

19:45 promise is a reference type; deliver lets you assign a value to a promise. any time a promise dereferenced before it is delivered it blocks; after delivery it returns the delivered result.

19:45 _Vi: brehaut, Promise and immediately deliver - looks like no use. The answer is probably just using a modal window: Backend -> Backend-to-GUI-interface -> GUI -> Modal window.

19:46 brehaut: _Vi you UI implimentations concerns are completely seperate you your foreground/background communication concerns

19:46 a modal window is not going to block your background thread

19:47 _Vi: brehaut, The modal window is going to be called from a background thread.

19:47 brehaut: (unless you use InvokeAndWait i guess)

19:47 _Vi expect your program to crash then

19:47 Swing does not like UI activity occuring on any thread but the AWT event thread

19:48 _Vi http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#single_thread_rule

19:48 _Vi: Main window sends connect request to backend. (using "send"). Agent starts connecting and requests GUI to show password entry window. It shows modal window (blocking that thread).

19:51 Yes, actually it will probably be invoke and then wait inside.

19:53 brehaut: _Vi that wont the password back to the background thread though

19:53 gfrlog: I just bet myself five dollars that there's an easier way to do this:

19:53 (eval (list (symbol "clojure.core" "go")))

19:53 aw crap

19:54 no wait, I think I can't just do (clojure.core/go) because the actual namespace I'm referring to isn't loaded until runtime

19:54 so the compiler would complain

19:54 so I have to use eval...

19:55 but I bet (eval #'clojure.core/go) would work, or some similar syntax. thus my question

19:55 ,#'clojure.core/map

19:55 clojurebot: #'clojure.core/map

19:55 gfrlog: ,(eval #'clojure.core/+)

19:55 clojurebot: DENIED

19:56 hiredman: gfrlog: you don't have to use eval

19:56 gfrlog: even if it's not loaded until runtime?

19:57 hiredman: correct

19:57 gfrlog: hmm

19:57 I guess the compiler doesn't complain if it's fully qualified?

19:57 hiredman: nope

19:58 gfrlog: that makes sense -- hadn't thought of that; thanks

19:58 _Vi: brehaut, Looks like promise/deliver is the answer here. We can invokeLater an object with a promise. When it that delivers, the background thread unblocks.

19:58 brehaut: yes

19:59 _Vi instead of an object, just use a closure

20:00 _Vi: brehaut, closure is also an object. (Here object means "a thing").

20:01 brehaut: _Vi its always worth being precise.

20:04 gfrlog: hiredman: got a ClassNotFoundException :-/

20:06 switching to (eval '(my.namespace/go)) makes it work

20:07 hiredman: you don't need eval

20:07 gfrlog: I'm not sure how to do it then; (my.namespace/go) produces the classnotfoundexception

20:08 hiredman: so obviously you cannot do it that way

20:08 gfrlog: okay; so you're saying there is some other way to call the function and it is not eval?

20:11 ,(#'clojure.core/+)

20:11 clojurebot: 0

20:12 gfrlog: that one doesn't work either ("Unable to resolve var")

20:16 rata_: gfrlog: what's the problem?

20:19 gfrlog: not really a problem anymore. I originally had some ugly code that I've simplified to (eval '(my.namespace/go))

20:19 hiredman was saying that I don't need to use eval, but hasn't said anything further, so I'm not sure what he meant

20:19 I was just trying other things

20:20 raek: gfrlog: what would the eval do?

20:20 or, what do you want to simplify

20:20 gfrlog: eval calls the function

20:21 which does not get loaded until runtime

20:21 so simply using (my.namespace/go) causes a classnotfoundexception at compile or load time

20:21 raek: and you are doing something at compiletime?

20:21 gfrlog: well I have the code there and it is being compiled, I think

20:21 raek: then you are missing a (:require my.namespace) in your ns form

20:21 gfrlog: but the namespace would not be found

20:22 it is loaded via (load-string)

20:22 raek: oh

20:22 gfrlog: after the program starts

20:22 raek: but before you want to call a function from it?

20:22 gfrlog: right

20:23 raek: it don't see why eval would make it work if it didn't work without it...

20:23 if the namespace has been loaded, you should be able to use it

20:23 gfrlog: I assume it means that the compiler or loader or whatever it is that checks for those things when the code gets loaded would pass over it

20:24 rata_: what do you load-string?

20:24 raek: loading happens when you evaluate load-* require and use

20:25 gfrlog: I load the my.namespace code

20:25 raek: why do you load it from a string?

20:25 gfrlog: it's not local -- it's obtained via HTTP

20:25 rata_: that sounds dangerous

20:26 gfrlog: like security or like code maintainability?

20:26 rata_: anyway, do you have a (require '...) after load-string? (I'm not sure it's required)

20:26 like security

20:26 gfrlog: ah -- that doesn't really bother me, it's just personal

20:26 no, no require after load-string

20:26 raek: gfrlog: does the code work when you replace the load-string call with a require with a local file?

20:27 and how much experience do you have with namespaces, ns, require, etc?

20:28 gfrlog: I use them all the time, so I think I know them enough for 98% of use cases. Have a hard time describing the plumbing of it though

20:28 I'll try adding a require at the top

20:29 raek: I think the problem lies in how you custom loading code works

20:29 rata_: I'm reading require and it needs the file to be there in the classpath, so that's probably not the solution

20:29 gfrlog: you mean I shouldn't use load-string?

20:30 raek: I don't know how you load-over-http code works, but I'm very sure that wrapping a call using it in an eval shouldn't make something work

20:31 gfrlog: adding require gets me a totally unrelated error, so I don't think I can conclusively say what that does

20:31 raek: the distiction between compile-time and runtime is very blurred in clojure

20:31 require looks for the file on the classpath, so that's not what you'd want for loading code over http

20:31 gfrlog: so I have a typical source file for the namespace, with a (ns my.namespace) expression at the top

20:32 I'm just passing it to (load-string) instead of having it in the classpath

20:32 (after getting it over http of course)

20:32 raek: so if you have (ns my.namespace) (def x "hello") in that file

20:33 evaling my.namespace/x after having evaled (load-string the-string) returns "hello"?

20:33 gfrlog: depends on what you mean by your first "evaling"

20:34 if you mean calling eval explicitely, then yes

20:34 raek: i mean in the repl, or at the top level of a file you are running

20:35 gfrlog: I haven't tried the repl -- I've been trying this with "lein test"

20:35 I think I can do repl though

20:36 okay, so before loading the code, I get a classnotfoundexception of course

20:36 hiredman: gfrlog: what is the relationship between symbols, the compiler, and vars?

20:37 gfrlog: I would think that the compiler associates a symbol with a var

20:37 but I am fuzzy on these things

20:37 it resolves a symbol to a var?

20:37 based on the context?

20:38 rata_: gfrlog: and after loading the code?

20:38 hiredman: so if you do (clojure.core/+ 1 2), clojure.core/+ is a symbol and the compiler resolves it to a var?

20:39 gfrlog: rata_: that's a good question, I'm not very well set up to try that...

20:39 rata_: why? you don't have the code string at the repl?

20:40 gfrlog: rata_: I can get it, but there's actually a number of namespaces and I'd have to make sure they're loaded in the right order

20:40 hiredman: I think that's how I would explain it

20:40 ,(symbol "clojure.core" "+")

20:41 clojurebot: clojure.core/+

20:41 hiredman: gfrlog: and the compiler would fail to resolve clojure.core/+ to a var if the var didn't exist (the file that created it hadn't been loaded)

20:41 rata_: gfrlog: but then try with the string example raek gave you

20:42 gfrlog: hiredman: that sounds right

20:42 hiredman: gfrlog: but you know a var exists at runtime but not compile time, so you cannot rely on the compiler to resolve it for you

20:43 gfrlog: hiredman: right

20:43 hiredman: so you ned to _ the var yourself

20:43 gfrlog: "resolve"

20:44 so I need a way to refer to a var without a symbol?

20:44 hiredman: why?

20:44 clojurebot: http://clojure.org/rationale

20:44 hiredman: clojurebot: stick a sock in it

20:44 clojurebot: Excuse me?

20:44 hiredman: clojurebot: you heard me

20:44 clojurebot: hiredman: I'm just giving you a second chance

20:45 hiredman: clojurebot: watch it

20:45 clojurebot: I don't understand.

20:45 gfrlog: hiredman: should I have filled in the blank with "refer to"?

20:45 "reference"?

20:45 hiredman: no, you were doing fine

20:46 gfrlog: I guess I just figure if I have a symbol, and I want to resolve it to a var, I use (eval)

20:46 hiredman: gfrlog: how does the compiler resolve a var?

20:46 gfrlog: but I suppose there must be a more specific function for doing that

20:46 hmmm

20:47 well it'd have to muck about with all the requires/uses, but since I'm fully qualifying I assume I can skip that part

20:47 so it would go to the namespace object and ask for it?

20:47 this is something I haven't done before, but I've seen the functions for examining the contents of a namespace

20:48 so it would be in that arena?

20:48 hiredman: have you looked at the docs on vars?

20:48 gfrlog: resolve the namespace name, get a map of its contents and look up my function?

20:48 (er, var)

20:48 hiredman: not recently

20:49 hiredman: perhaps they would be useful here

20:49 brehaut: the clojure.org/vars page only mentions the appropriate fun in briefly i think

20:49 gfrlog: hiredman: reading now

20:53 on first pass I have only learned that I don't know what set! does

20:55 brehaut: has the implications of interning sunk in yet?

20:56 gfrlog: brehaut: interning I understood to mean that successive "def"s of the same symbol will refer to the same var

20:56 so I suppose not, because I'm not sure how that relates

20:56 brehaut: if i understand where hiredman is going with his socratic method, i think thats important?

20:57 gfrlog: the (find-var) method listed in related functions...

20:57 seems like a way to get a var

20:58 so I would have to do... ((var-get (find-var 'my.namespace/go)))

20:59 and that in fact passes my tests

20:59 whether or not it's what hiredman was getting at, it sounds like is still uncertain

21:00 brehaut: i could just tell you what my guess is, but that might ruin the larning

21:01 rata_: yes, I'm trying not to say it too

21:01 gfrlog: oh my golly

21:01 okay

21:01 so I should keep thinking about interning you think?

21:03 brehaut: based on the text of that page, yes i think so

21:03 gfrlog: looks like the intern function will do something similar to find-var

21:04 that doesn't give us any new functionality though

21:05 the interning section of the var page seems straightforward to me

21:05 I can't see anything hiding there

21:06 brehaut: reread the whole page with what you've understood from there then

21:08 may i also suggest you examine clojure.repl/apropos and clojure.core/find-doc at some point too

21:10 gfrlog: the bit before set! seems straightforward too... set! itself is confusing. And I think I have made sense of the non interned vars as well.

21:10 will look at the two functions you recommended

21:12 ,(doc mapcat)

21:12 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."

21:13 gfrlog: ,(all-ns)

21:13 clojurebot: (#<Namespace swank.core.threadmap> #<Namespace swank.rpc> #<Namespace dk.bestinclass.clojureql.util> #<Namespace clojure.set> #<Namespace clojure.contrib.seq> #<Namespace clojure.contrib.sql.internal...

21:14 gfrlog: ,(ns-publics (first (all-ns)))

21:14 clojurebot: {find-thread #'swank.core.threadmap/find-thread, *thread-map-next-id* #'swank.core.threadmap/*thread-map-next-id*, *thread-map* #'swank.core.threadmap/*thread-map*, thread-map-id #'swank.core.threadm...

21:14 gfrlog: so that is a map of symbols to vars

21:15 so that's how apropos works

21:15 brehaut: yeah. you can also dir a namespace

21:15 which gives a seq of all the symbols

21:15 gfrlog: right; that's what I expected

21:16 I think these would be the namespacy functions I referred to earlier

21:17 brehaut: im assuming you havent pulled out any more information from the vars page?

21:17 oh, dir is also in clojure.repl

21:17 gfrlog: this is quite a mysterious process to me

21:18 ,(ns-interns (first (all-ns)))

21:18 clojurebot: {find-thread #'swank.core.threadmap/find-thread, get-thread-id #'swank.core.threadmap/get-thread-id, *thread-map-next-id* #'swank.core.threadmap/*thread-map-next-id*, *thread-map* #'swank.core.thread...

21:18 brehaut: gfrlog: you are aware that each doc page on clojure.org has prose about the topic, and then at the end a summary of related functions?

21:18 gfrlog: brehaut: yes, I believe so...

21:18 on the var page I read prose about the topic, and at the end I perused the related functions

21:20 source code for find-doc is straightforward

21:21 as clojure.repl/dir

21:21 brehaut: gfrlog: i mentioned those because they are useful tools for crosscutting the all the functions rather than having to dig through api pages

21:23 gfrlog: this all seems to conform to my understanding that a namespace maps symbols to vars

21:24 brehaut: so what happens if you try to reference a symbol that isnt in the namespace?

21:25 gfrlog: what does "reference a symbol" mean?

21:25 you mean use a free symbol?

21:25 like eval it?

21:25 brehaut: not eval it

21:25 you can safely leave eval out of this

21:26 if you type

21:26 foo

21:26 into a repl

21:26 without quoting it

21:26 what happens?

21:26 gfrlog: I've always thought that means the repl calls (eval (read-string "foo"))

21:26 ,(read-string "foo")

21:26 clojurebot: foo

21:27 brehaut: those mechanics are unimportant

21:27 gfrlog: ,(eval (read-string "foo"))

21:27 clojurebot: DENIED

21:27 gfrlog: okay

21:27 so then

21:27 it notes that the symbol is free

21:27 and looks it up in the current namespace

21:27 brehaut: how does it note that?

21:27 gfrlog: oh, well at the repl I guess all symbols are free unless they are letted within the current expression

21:28 since we just typed "foo", that's irrelevant

21:28 no letting going on

21:29 so it's free, it looks in the current namespace, doesn't find it, and so throws an error

21:30 brehaut: ok

21:30 so what needs to happen for it to not throw that error

21:37 anthony__: Why would you use #' for a send-off command instead of just the function name? I'm looking through the ants demo source, and there's code like (send-off *agent* #'evaporation) in several places. Why not (send-off *agent* evaporation) ?

21:37 brehaut: anthony__: it passes the var itself rather than dereferencing the var

21:38 anthony__: brehaut: Yeah, but I don't understand why it needs to do that. Is it because it's being called within the evaporation function, so evaporation isn't a var yet?

21:38 brehaut: #' is 'var quote' according to http://clojure.org/reader

21:38 anthony__: i recall some of those vars being forward declared

21:39 gfrlog: brehaut: I would think either the symbol needs to be bound locally through let, or else exist in the namespace already

21:39 brehaut: gfrlog: correct

21:39 so you want it to be in the namespace?

21:40 gfrlog: well I don't mind fully qualifying it...

21:40 I guess we haven't been addressing that point

21:40 brehaut: qualifying it just tells it to look in another namespace right?

21:40 gfrlog: yes

21:42 incandenza: anthony__: for what it's worth, my copy does in fact have just "evaporation" without the #'

21:42 gfrlog: are we suggesting that I should (def my.namespace/go) before that namespace has been load-stringed?

21:42 anthony__: incandenza: Ok, cool. Thanks for that. I was just worried that my agent code might be wrong, since I never use that macro.

21:43 brehaut: gfrlog: can you find a way that does declares that a symbol will be bound, before its actually defined?

21:43 gfrlog: that's what def does right?

21:43 so (in-ns my.namespace (def go)) is what I want?

21:44 brehaut: i dont think so

21:44 although it might still work

21:45 gfrlog: well the namespace shouldn't exist yet, right?

21:45 so I have to at least implicitly create it?

21:46 brehaut: hmm pass

21:47 i need to head off anyway.

21:47 gfrlog: :-P

21:47 brehaut: hiredman may say im completely off base, but look at delcare

21:48 gfrlog: ah yes, I've used that before

21:48 not across namespaces though

21:48 brehaut: good luck anyways

21:48 gfrlog: ,(declare hiredman.brehaut/x)

21:48 clojurebot: DENIED

21:49 gfrlog: ah well. at least I tried.

22:43 ossareh: evening all

Logging service provided by n01se.net