#clojure log - May 06 2011

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

0:15 ymasory: what's the difference between STM and using H2/Derby in-memory?

0:17 amalloy: well, the stm won't be hideously slow

0:18 eg specifically, it never locks anything

0:18 so you can get as many cheap snapshots as you want

0:18 ymasory: ah. any major semantic difference?

0:19 amalloy: the stm understands clojure constructs in a way that i can't imagine derby ever would

0:20 ymasory: thanks

0:20 amalloy: i don't know anything about derby, but writing (alter num-customers inc) must be shorter than their equivalent

0:54 codedigestion: hey!

0:55 is there anybody out there?

0:55 symbole: Yes.

0:55 codedigestion: great! just wondering. First time in here. thanks for responding!

0:55 :)

0:56 symbole: I am a robot.

0:56 TheMoonMaster: Me too.

0:56 symbole: Beep! bop!

0:56 codedigestion: i eat robots for breakfast... What language are you programed in robot?

0:56 python???

0:56 clojurebot: python is ugly

0:56 codedigestion: you seem pretty sloow....

0:56 Belaf: :)

0:57 symbole: I am made with Befunge.

0:57 TheMoonMaster: Python really is ugly...

1:00 codedigestion: i would've been impressed if you were made in brainfuck

1:00 oh well...... can't win all the time...

1:01 TheMoonMaster: I think ZOMBIE would have been a better choice.

1:04 symbole: I thought Befunge would be arcane enough.

1:04 Apparently not.

1:05 TheMoonMaster: Well, "The language should allow the necromancer to animate dead bodies, summon and control spirits, and solve any computable problem. ", sounds awesome for a bot.

1:06 codedigestion: Zombie is an acceptable alternative to brainfuck. Perhaps, the core component was composed in brainfuck, and the remainder, zombie. This Befunge isn't impressive, though...

1:36 no_mind: If I instantiate a defrecord based record.How can I find the type of record ? Using 'type' returns Java.lang.Class

1:37 hiredman: you do (defcord Foo ...) in the namepsace bar.baz then the java type is bar.baz.Foo

1:39 amalloy: no_mind: Foo is in fact the class. (class Foo) returns Class, just like (class String) does

1:42 no_mind: amalloy: If I do (defrecord Foo ...) then do (def main (Foo. ...)) . I want to know if I can find main is of type Foo ?

1:43 amalloy: (instance? Foo main)

1:43 hiredman: (type main) will tell you

1:43 (the type)

1:44 amalloy: but i don't think you should want to do that. if you don't know the type of the record object already at compile time you don't usually get much benefit from using a record rather than a hashmap

2:37 Belaf: Hi

2:40 I'm trying (for curiosity/learning) to quickly get the color component values from an argb integer... I'm really surprised to see that

2:40 (.getRed (java.awt.Color. 0xff909030))

2:41 amalloy: &(java.awt.Color. 0xff909030)

2:41 sexpbot: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

2:41 Belaf: is much faster than

2:41 (bit-and 0xff (bit-shift-right 0xff909030 16))

2:41 Why is it so?

2:41 amalloy: Belaf: the bitops do runtime type checking to determine what size int they're dealing with, i suspect

2:42 Belaf: I see... I'd have thought that allocating an object would have taken more time...

2:43 amalloy: clojure is allocating objects all the time

2:44 it's working with java.lang.Long, not primitive long, most of the time

2:45 Belaf: Is there any option to avoid bit-and and bit-shift-right type checking? On the other side trying to use arithmetic operations (+ and *) doesn't get any faster...

2:46 amalloy: $findfn 0xff 0xf 0x0f

2:46 sexpbot: [clojure.core/max-key clojure.core/cond clojure.core/dosync clojure.core/sync clojure.core/char-escape-string clojure.core/with-loading-context clojure.core/bit-and clojure.core/*clojure-version* clojure.core/with-precision clojure.core/case clojure.core/min-key cloj... http://gist.github.com/958529

2:46 amalloy: hmph

2:47 Belaf: there's unchecked-add and friends

2:48 Belaf: oh, I'll look at them. Thanks!

3:07 amalloy: no luck, they get no faster. Actually every unchecked_XXX functions seem to allocate a clojure.lang.Numbers instance, so I guess I should stay with the java.awt.Color solution... maybe there's too much C in my memories :)

3:08 amalloy: ~source unchecked-inc

3:09 Belaf: they're not allocating c.l.Numbers. it's a class with several static methods

3:10 the closest you can get in java to a plain, isolated function

3:11 killa: hello

3:12 guys

3:12 anyone home?

3:14 Belaf: Ops, I misread (or better misunderstood it)... I need to give a better look... the speed didn't improve, though.

3:18 no_mind: is there a package/library in clojure for Publisher-Subscriber model ?

3:18 Belaf: amalloy: what I'm surprised to see is that "(.getRed (java.awt.Color. 0xff909030))" is faster than "(unchecked-divide 0xff909030 (long 65536))"

3:19 amalloy: &(time (dotimes [_ 1e7] (/ 0xff909030 65536)))

3:19 sexpbot: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

3:19 amalloy: seriously? i guess sexpbot is broken

3:19 ,(time (dotimes [_ 1e7] (/ 0xff909030 65536)))

3:19 clojurebot: java.lang.ExceptionInInitializerError

3:20 amalloy: or maybe not

3:20 Belaf: anyway, i'm going to bed. good luck, i guess

3:20 Belaf: Allright, thanks! Have a good night!

3:21 killa: I would like to ask some questions to experienced clojure developer

3:21 if there is one here

3:21 :)

3:21 Belaf: Erm... don't look at me ;-)

3:22 no_mind: killa: this is a n00bies channel :P

3:22 Fossi: killa: never ask to ask

3:23 unless you want payed consultant hours that is ;)

3:23 killa: nah questions are rather basic

3:23 just trying to figure out if clojure is right yo me

3:23 shouldnt be that hard

3:23 right?

3:25 anyway I have rather ambitious project in mind. I want to create very flexible RPG game. Since I am looking for runtime flexibility C++/Java and so on are out of the question (unless mixed with Lua or something).

3:26 some concepts of lisp make sense to me

3:26 and so does JVM

3:26 the problem is this functional programming thing

3:26 immutable datatupes seem like bad idea when game state changes 24 times a second

3:27 so Clojure sounds like bad idea, except that I like syntax (or rather lack thereof) and macros

3:28 so what do you think people

3:28 ?

3:29 seancorfield: killa: well, clojure has very well controlled mutable state too

3:29 atom, ref and other types support software transactional memory

3:29 which would allow you to manage a mutable game state without worrying about concurrency problems

3:33 killa: how does that work? I mean compared to classic mutable variables?

3:34 I never saw someone make real time game in clojure (I saw turn based game but that's it)

3:34 thanks for answering, btw

3:36 sorry but I still just don't see it as viable option

4:33 seancorfield: killa: sorry, got distracted with work... well, try it and see how well it works :) then someone will have made a real time game in clojure

4:33 killa: lol, thank you

4:33 seancorfield: if you don't think it's viable, i'm probably not going to persuade you...

4:34 killa: well, I've been googling a bit and I have found one RPG

4:34 that seems real time

4:34 but I guess that the problem I really have with the whole thing is that Clojure HAS some good ideas

4:34 fliebel: killa: Writing a game in Clojure?

4:35 killa: researching how viable is writting game in Clojure

4:35 at the moment

4:35 not writing anything yet

4:35 fliebel: killa: 3 or 2D?

4:35 Fossi: there are lots of functionally written games

4:36 killa: for now it's 2d, but it's real time

4:36 fliebel: killa: https://github.com/pepijndevos/Begame/tree/master/src/examples

4:37 Fossi: in my little toy thing i just applied the state every frame at the top of the game loop

4:38 killa: but the point is that I don't like cargo cult programming. And every damn language in the universe seems cargo cult. In python they won't give you optional static typing. In java no dynamic typing. And you NEVER, EVER get macros anywhere. And Clojure has no mutable typing. How about supporting most stuff that's usefull and letting ME decide?

4:38 Fossi: basically events in, commands out atd then applying them to the state

4:38 killa: sorry for ranting

4:38 eevar: mutable typing?

4:39 killa: I mean mutable types

4:39 I mistyped

4:39 Fossi: you really can't have all the features there are

4:39 killa: no need for all

4:39 just all most common

4:39 fliebel: Well, in Common Lisp you can :P

4:39 Fossi: because some of them are mutully exclusive

4:39 clgv: killa: you should check atoms and refs

4:39 killa: well you can have both dynamic and static typing for example

4:40 some are mutually exclusive, but most aren't

4:40 it seems it's mostly ego thing: everyone want's to get you to program his way

4:40 but sorry for ranting

4:40 :)

4:41 fliebel: killa: https://github.com/graydon/rust/wiki/Language-FAQ "I like the language but it really needs $somefeature."

4:42 killa: Fossi: you wrote Begame?

4:43 fliebel: killa: I did :)

4:43 killa: okay

4:44 so is it realisticaly possible to get decent performance (comparable to, say, Java) for real time game using Clojure?

4:44 Fossi: using the jvm i'd say yes

4:44 killa: thanks for comments so far, folks :)

4:45 fliebel: killa: I'd say so. I have not written anything big with it, but I had 1000 ducks moving around randomly ina smooth way.

4:45 Fossi: then again a lot depends on the graphics there ;)

4:46 fliebel: killa: I have an optional option for automating transitions between key frames, so sometimes you can get away with doing logic a dozen times per frame and then just drawing.

4:47 killa: another thing I worry about is the fact that my game is going to be vey complex and very interconnected. That's kind of the point. I want extremely extensible game with scripting and stuff. (That's why I am seeking best language for the job, instead of settling for, say, Java)

4:47 I have some game developer experience (mostly smaller flash games) and one unfinished RTS in c++

4:48 fliebel: killa: You are likely to run into code organization then. Clojure is a single pass compiler, so you need to avoid circular deps and rometimes resort to forward declarations.

4:48 killa: but now I am truing to make something much larger (I mean conceptually larger, not fancier graphic)

4:48 jamesswift: hey all. I'm developing in emacs/slime and when i reload a file/namespace on the repl using (require .... :reload-all) and I get the exception "Unable to resolve symbol: blabla in this context" I see no way to find out on which line the offending symbol occurs. The stack trace is in clojure core code. Is there some way to get this that I'm unaware of?

4:48 killa: and Java is too damn staic

4:49 I've heard about Steve Yegge bitching about single pass thing too

4:49 on mailing list or somewhere

4:50 fliebel: I need to run now, but you can question me about Begame later today :)

4:50 killa: thanks for trying to help

4:50 basically the point is that I really need something that helps me write complex code

4:50 raek: jamesswift: if you press C-c C-k in the source code buffer, the rows with errors will be underlined

4:51 killa: see ya later, fliebel

4:52 raek: (C-c C-k is like (require .... :reload), but with slime integration)

4:52 ttmrichter: killa: I'm curious here: why not just use Common Lisp?

4:53 killa: ttmrichter:I like JVM, and Common Lisp sounds very ancient (unless you are aware of some good implementation)

4:54 ttmrichter: There are good commercial implementations. The open stuff tends to suck, though, yeah.

4:54 clgv: killa: since clojure and java interop quite nice, you might also divide your development between the two, e.g. high performance graphics and stuff in java and complex rules of the logic game engine in clojure...

4:54 jamesswift: raek: thanks a million. perfect.

4:56 killa: clgv: that's sort of what I have in mind. This assumes that Clojure is good at complex interconected logic. In theory it should be, since it's lisp. But functional-only and single pass compliling scares the me.

4:57 clgv: killa: functional-only? there are great language concepts for coordinated mutable state as well

4:57 killa: clgv: I guess I will have to look a litle more thoroughly, then

4:57 clgv: killa: the importance of the limitation to single pass compiling isnt quite obvious to me as well

4:58 killa: clgv: it creates problems when you have pices of code that are mutually dependent, does it not?

4:59 clgv: killa: if you are referring to some kind of circular dependencies then afaik you also should avoid these in java, c# or c++ as well ;)

4:59 raek: I've heard that clojure actually has two pass compilation. however, the compilation unit is not the namespace, but the top-level form

4:59 seancorfield: killa: you can write mutually recursive functions in clojure just fine

4:59 raek: this makes macros possible

5:00 killa: clgv: I am sorta trying to TRANSCENT java and such :)

5:01 clgv: to clarify: I didn't refer to mutually recursive functions with the previous comment ;)

5:02 killa: but yeah folks, I am not quite sure what I really need. This stuff is still rather alien to me.

5:02 completely different way of thinking

5:02 seancorfield: clgv: i know - but i'm trying to see why killa is concerned about single pass compilation affecting mutually dependent code :)

5:03 killa: but it does seem more flexible than standard OOP model

5:03 don't laugh at me, I am still warping my head about stuff

5:03 around

5:03 clgv: killa: I started with clojur last october. I did only imperative OO languages before that

5:04 except from some prolog while studying ;)

5:04 killa: and, in your opinion, is this model more flexible? More expressive?

5:04 frankly OO is too damn verbose

5:04 seancorfield: you can write OO in clojure if you want... i think java is too verbose

5:05 killa: and not enough runtime flexibility

5:05 because I want to create custom objects at runtime

5:05 you know about universal design pattern by Steve Yegge

5:06 there is blog post about that

5:06 seancorfield: steve has lots of interesting rants

5:06 killa: I know

5:06 I agree about lot's of stuff

5:06 clgv: you get custom objects with hash-maps ;)

5:06 killa: he recomended clojure

5:06 that's why I am here

5:06 seancorfield: i think you should just try and build something with clojure and see how it goes

5:07 clgv: if you need common "interfaces" you can define a protocol and implement records for it.

5:07 seancorfield: it's very hard to reason about a language until you've used it to build real systems, imo

5:08 killa: agreed

5:08 clgv: well, you get a feeling for it if you read an introductory book

5:08 killa: clgv: yeah I am also thinking about custom objects with hashmaps. That's very Javascript-like

5:08 clgv: and try the examples along reading and doing a little project after that

5:09 killa: clgv: Me and Steve Yegge came to similar conclusions about the same thing independently

5:11 one moment, brb

5:36 I am back

5:36 I guess you are right folks

5:36 I will have to create something first

5:36 then rant about stuff.

6:12 clgv: lol that guy is funny ^^ http://steve-yegge.blogspot.com/2010/07/wikileaks-to-leak-5000-open-source-java.html

6:15 * clgv throws something after lenstr

6:16 killa: clgv: yeah he is. Make sure to read his stuff about 'universal design pattern' and 'pinnochio problem'

6:17 clgv: me and him are on same wavelength there

6:17 clgv: that will explain to you why I got into clojure in the first place

6:17 clgv: and it is great read, too

6:18 clgv: :D

6:18 killa: basically I am interested in system that are extensible at runtime

6:19 where you can swap functions inject new code and stuff

6:20 living systems

6:21 clgv: >>The Wikileaks founder said: "Today the Eclipse Foundation put out a private briefing calling me a 'non-thread-safe AbstractKeywordRemovalInitiatorFactory'"<< :D

6:21 killa: and I have heared lisp is supremely very expressive. Read some stuff and was impressed. Never really did anything, thought. That's why I got interested into Clojure (that and the fact that Steve recommended it).

6:22 but I don't really know how good is clojure at any of that

6:22 clgv: I heard and tried some lisp in a lecture on Aspect-Oriented Programming. in CLOS this worked out of the box ;)

6:23 killa: clgv: and what about clojure?

6:24 clgv: I would have to find the old slides and examples to be able to compare that.

6:25 killa: I don't have problem with creating my own object system, as long as it can be made to work well

6:25 clgv: I know that project named robert.hooke has some wrapping around functions which was the technical side of aop runtime

6:26 so it seems possible to develop a more elaborate AOP framework

6:26 killa: yeah aspec oriented programming is part of what I want

6:26 aspect

6:26 I might end up developing it myself

6:26 I am rather motivated

6:26 althought I might not be motivated to do that in Clojure

6:27 depends on many things

6:27 clgv: in java you already have aspectj for it ;)

6:27 that was the second part of the before-mentioned lecture ...

6:28 killa: it is quite a pain. Or at least it was last time I checked

6:28 clgv: I can't tell. Last time I saw it is about 3 years ago ;)

6:29 killa: basically the point is that Java is quite verbose and too damn static and I don't trust it at all

6:29 so I am looking for alternative

6:29 but functional seems a bit too radical

6:30 also I love idea of macros

6:30 creating my own language construct

6:30 clgv: read that "programming clojure" or one of the others to get you started and build a small project meanwhile or when you are done reading ;)

6:31 killa: yeah, probably

6:31 clgv: that should help to decide. I think I read it in 2-3 days

6:33 killa: thanks for having patience with me

6:34 clgv: np. it's only about 7 months ago that I started using clojure ;)

6:35 killa: anothe issue is JVM itself

6:35 now that Oracle has it

6:36 ejackson: killa: ain't nothing perfect in this world - you just have to work with what is available.

6:36 killa: yeah I guess

6:46 reading Programming Clojure now.

6:46 thanks for advice

7:10 cemerick: killa: "Oracle has it"?

7:10 it's GPL'ed

7:17 clgv: hey cemerick, you know of lisp conferences for the remaining year?

7:18 cemerick: clgv: http://clojure-conj.org/

7:18 Apparently there won't be an ILC in 2011 http://www.international-lisp-conference.org/2011/index :-O

7:19 That's bizarre.

7:19 clgv: hm true

7:20 killa: cemerick: I don't know the details but I know there where some court battles over JVM implementations. Google vs Oracle

7:20 clgv: do you know of any journals in the lisp and functional programming topic?

7:21 cemerick: killa: None of which matters a hoot unless you're an Android developer, or want to build your own "clean-room" JVM impl. Just sayin'

7:22 clgv: There's a couple of FP journals. I don't know them off the top of my head.

7:22 killa: it doesn't matter much to me, I agree. But if someone wants to make program accesible on computers without JVM and distributes it as .exe with JVM bundled in?

7:22 cemerick: clgv: There's also http://cufp.org

7:22 killa: what happens with that?

7:22 clgv: cemerick: hmok I try to persuade google to tell me ;)

7:23 cemerick: killa: Commercial redistribution of an unmodified JVM is still allowed, just as it was under Sun.

7:23 killa: so only modifying is no no ?

7:23 I can live with that

7:23 cemerick: Yeah, if you wanted to distribute a modified version, you'd have to use OpenJDK. But then you'd be subject to GPL.

7:24 killa: how large is JVM, btw ?

7:24 in megabytes

7:24 clgv: killa: nothing is decided on that. you will have to wait for the outcome of that court battle ;)

7:31 cemerick: killa: FYI: http://www.oracle.com/technetwork/java/javase/readme-142177.html#redistribution

8:37 no_mind: if defining a new record using defrecord, can I force an attribute of record to be a ref ?

9:13 chouser: no, but you can of course put a ref in any field you want

10:14 mrbombastic: how come i have to use seq to use basic operations on my sets, vectors etc? why don't these types implement the seq interface automatically? is there a performance reason?

10:16 stuarthalloway: mrbombastic: example?

10:16 mrbombastic: why doesn't set implement nth, but (seq set) does

10:16 raek: mrbombastic: I don't understand. many of the operations work directly on the data strucures (conj, disj, peek, pop, assoc, dissoc), and when you use sequence functions, they will call seq on the data structres automatically

10:17 manutter: ,(doc nth)

10:17 clojurebot: "([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."

10:17 mrbombastic: i can't (rand-nth #{1 2}), but i can (rand-nth (seq #{1 2})) - why the need for the seq

10:17 yeah, i've read the docs thanks

10:17 manutter: ,(nth #{1 2 3} 2)

10:17 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet

10:17 manutter: no, I was just checking, I couldn't remember the order of the args :)

10:18 ,(nth (seq #{1 2 3}) 2)

10:18 clojurebot: 3

10:18 raek: mrbombastic: in this case, it's because hash sets do not have any "native" way of looking up the nth element

10:18 mrbombastic: but they do when you wrap them as a seq

10:19 why not have the code that implements nth for a set inside the definition of set in the first place, since it's possible

10:19 raek: to find element 3, you need to traverse the three and stop at the fourth observed leaf

10:19 bartj: my 2c, there is no ordering required for hash sets

10:19 raek: *the tree

10:19 seq is that traversal

10:19 mrbombastic: and in my case, i'm using rand-nth, so i don't care about ordering

10:19 so rand-nth makes sense on a set

10:20 manutter: well, I think you want rand-element in general, not rand-nth

10:20 mrbombastic: ,(doc rand-element)

10:20 clojurebot: Cool story bro.

10:20 manutter: depends if you make a distinction between "set" and "ordered set"

10:21 sorry, that was pseudo code

10:21 raek: I see you point. one reason that rand-nth requires a sequential collection could perhaps be that there is no convenient api in clojure for fetching a random element of any data structure

10:21 manutter: I'm talking conceptually

10:21 mrbombastic: ok

10:21 but it does all work, and the code is all there, you just have to wrap it in a seq which is counter-intuitive

10:21 manutter: I dunno, it seems intuitive to me

10:22 rand-nth assumes each element has an index/position, because nth refers to that position to retrieve the element

10:22 if sets in general do not index the position of their elements, nth would be meaningless

10:23 mrbombastic: it's not meanginless if n is random

10:23 which it is when you use rand-nth

10:23 raek: mrbombastic: it would be convenient of rand-nth would have called seq on its argument in this case, but that would not have been god for vectors

10:23 manutter: if you had an ordered set, then the indexes would exist, nth would make sense, and rand-nth would be meaningful

10:23 Yeah, I'm quibbling I know

10:23 raek: mrbombastic: with a vector, you have constant time lookup, but for a vector seq, you have linear time lookup

10:24 manutter: My point is that rand-nth is 2 steps: (1) pick a random n, (2) give me the element at position n

10:24 That's slightly different from a 1 step give-me-any-element-from-the-set

10:24 mattmitchell: i have a co worker who is trying to implement an java interface in clojure, which has a method that needs to throw a particular exception class. anyone know of a resource we can look at to find out how to do that?

10:25 manutter: mattmitchell: you mean just how to throw an arbitrary exception?

10:25 raek: mattmitchell: you can use the throw special form: (if (some-condition ...) (f ...) (throw (AParticularExceptionClass. ...args...)))

10:26 manutter: yeah, what he said

10:27 mattmitchell: ok awesome. we'll play with that. thanks!

10:27 manutter: ,(rand-elt #{1 2 3} 2)

10:27 clojurebot: java.lang.Exception: Unable to resolve symbol: rand-elt in this context

10:27 manutter: oh, I see

10:28 ,(clojure.contrib.seq/rand-elt #{1 2 3} 2)

10:28 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: seq$rand-elt

10:28 manutter: doh, me stoopid

10:28 ,(clojure.contrib.seq/rand-elt #{1 2 3})

10:28 clojurebot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet

10:28 manutter: boo yeah

10:29 no wonder it's deprecated :)

10:30 ,(let [any (fn [s] (rand-nth (seq s)))] (any #{1 2 3}))

10:30 clojurebot: 2

10:30 manutter: That's what I'd do: define a function called "any" (or something similar) and then use that instead of rand-nth

10:30 it's just syntactic sugar, but it makes me happy :)

10:38 raek: ,(let [v (vec (range 1e6))] (time (nth v (dec 1e6))))

10:38 clojurebot: "Elapsed time: 0.148 msecs"

10:38 raek: ,(let [v (vec (range 1e6))] (time (nth (seq v) (dec 1e6))))

10:38 clojurebot: 999999

10:38 "Elapsed time: 71.822 msecs"

10:38 999999

10:39 manutter: That's interesting

10:56 has defstruct been superceded by defrecord, or is there still a use case for it?

11:01 I was just reading a cool blog post and noticed he was using defstruct

11:01 http://inclojurewetrust.blogspot.com/2009/11/tail-recursion-and-function-composition.html

11:03 using comp in a tail-recursion to "instantly" unwind a bunch of stack calls -- how awesome is that?

11:06 stuartsierra: defrecord replaces defstruct in all cases, I believe

11:07 manutter: I thought I'd heard that

11:07 stuartsierra: And soon you'll be able to print & read them! http://dev.clojure.org/display/design/defrecord+improvements

11:11 manutter: Cool!

11:15 cemerick: stuartsierra: now if we can just get the struct-related vars marked as deprecated…

11:16 stuartsierra: cemerick: make a patch

11:16 cemerick: stuartsierra: ok; I was waved off of doing so a while back

11:16 stuartsierra: oh?

11:17 stuarthalloway: cemerick, stuartsierra: there was something about struct that was still needed for e.g. resultset-seq

11:17 but since that itself will be deprecated....

11:17 cemerick: stuartsierra: key enumeration in the basis is unique to it, IIRC

11:18 stuartsierra: ah

11:18 cemerick: stuarthalloway: depends on the relative release timings of jdbc and 1.3, then, I presume?

11:18 deprecation meta, that is

11:18 stuarthalloway: cemerick: it will be deprecated, but possibly never removed

11:18 so the meta could happen now

11:19 stuartsierra: Old code never dies, it just deprecates.

11:19 cemerick: oh good, so we have our java.util.Date now :-/

11:22 stuartsierra: it's not quite that bad

11:23 timvisher: hey all

11:23 is it possible to easily create a seq on an Iterator?

11:23 cemerick: stuartsierra: don't mind me, I'm just being grumpy :-P

11:24 timvisher: I'm trying to deal with the javax.imageio.* libraries

11:24 stuartsierra: timvisher: yes, use `iterator-seq`

11:24 timvisher: and getting the understood image format requires dealing with an Iterator as far as I can tell

11:24 stuartsierra: and be careful: iterators are allowed to change

11:25 timvisher: stuartsierra: j00 rock brother. ;)

11:26 stuartsierra: thx

11:37 timvisher: I have a seq with duplicate values in it and I want to remove them.

11:37 I tried simply applying hash-set to the whole seq

11:37 but it says that there are duplicate keys

11:37 is there a simpler way to do it?

11:38 semperos: ,(doc distinct)

11:38 clojurebot: "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed"

11:39 semperos: timvisher: ^^ that what you're looking for?

11:39 timvisher: semperos: exactly

11:39 thx so much

11:39 semperos: np

11:39 you can always do a broad documenation search with "find-doc"

11:40 ,(find-doc "duplicates")

11:40 clojurebot: -------------------------

11:40 clojure.core/distinct

11:40 ([coll])

11:40 Returns a lazy sequence of the elements of coll with duplicates removed

11:40 timvisher: yeah

11:40 i had erc open so i got lazy

11:40 i usually do that :)

11:40 semperos: :) no worries

11:40 timvisher: but hey, you guys are so helpful!

11:40 manutter: plus us lurkers get to add to our clojure knowledge... :)

11:42 fliebel: killa: How are the game plans going?

11:45 zippy314_: Is there a way to do the equivalent of unquote splicing (~@) in regular functions (i.e. not in the context of syntax quoting) for parameters that have been collected into a list with &?

11:47 manutter: hrm, apply?

11:47 what do you need to do with them once you've "unquote spliced" them?

11:48 ataggart: ,(apply + [1 2 3])

11:48 clojurebot: 6

11:51 no_mind: Can I define a new exception in clojure ?

11:53 zippy314_: actually I just used a macro to do it. I wanted to create a function which just looks like a call to a different function with the first two parameters reversed where there's a variable number of params.

11:53 raek: no_mind: you need to use genclass to define Java exceptions. for error handling in clojure, consider clojure.contrib.error-kit or clojure.contrib.condition

11:53 zippy314_: So it was easier just to actually use defmacro and the unquote-splicing.

11:53 raek: ~error-kit

11:53 clojurebot: error-kit is http://pragprog.com/magazines/2009-07/when-things-go-wrong

11:55 dnolen: zippy314_: except now you have a macro, macros don't compose w/ functions.

11:56 manutter: zippy314: a function would also work without too much trouble: (defn foo [a b & others] (apply bar (seq b a others))) should do it, I think

11:57 zippy314_: ok so say i have (defn a [x y &z]) and I want to create a function b that's the same as a except you call it like (b y x foo bar).

11:58 my solution was (defmacro b [y x & z] `(a ~y ~x ~@z))

11:58 raek: (defn flip-first-two-args [f] (fn [x y & args] (apply f y x args)))

11:58 zippy314_: How do you do this with plain functions

11:59 raek: (def bar (flip-first-two-args foo))

11:59 zippy314_: ^^

11:59 (hrm, to match your example, foo and bar should be swapped)

12:00 manutter: cool, it does work without the (seq), I wasn't sure it would

12:00 raek: manutter: do you mean 'list*' instead of 'seq'?

12:01 manutter: raek: I said "seq" in my (untested) code example because I didn't think you could just pass an unadorned list of symbols to apply

12:02 I thought I needed to wrap it in a (seq a b c etc)

12:02 raek: (apply f a b c args) is the same as (apply f (list* a b c args)) which in turns is the same as (apply f (cons a (cons b (cons c args))))

12:02 manutter: seq only takes one argument

12:02 manutter: See, now that's why I hang out in this channel :)

12:03 that's right, I remember now

12:03 so, um, yeah, I did mean list*

12:03 :D

12:03 raek: apply calls seq on the last argument to convert it from whatever it is (e.g. a vector) to a seq (if it wasn't one already)

12:04 (since it's an ordinary function, it cannot know what the code of the expression looks like. all it cares about is that it's seqable)

12:05 so, nothing magic there... :)

12:06 zippy314_: So, this means that at the regular function level theres no way to substitute the values from a list as parameters? i.e. because apply assumes you have a function to call as in my example?

12:08 raek: zippy314_: sorry, I don't follow. what do you mean by "substitute the values from a list as parameters"?

12:09 what I meant was that a function cannot tell if it called like (f 123) or (let [a 123] (f a))

12:10 in response to what manutter said before: "I didn't think you could just pass an unadorned list of symbols to apply"

12:10 zippy314_: yah, I know I'm not using the right words. So to my (newbie) understanding, unquote splicing has the effect of substituting the values of the list in, instead of the list itself. I was wondering if there's a way to do that not in the context of a syntax quoting.

12:10 raek: but I probably misunderstood that, I see now.

12:11 zippy314_: yes, that's what apply does. it's analogous to "splats" in python and ruby

12:12 zippy314_: zippy314 is reading the docs for apply

12:12 raek: if you have a list of arguments l = [1 2 3], and you want to call the function with those elements as separate arguments like (f 1 2 3), you use apply: (apply f [1 2 3])

12:12 or (apply f l)

12:13 manutter: ,(let [some-list [1 2 3 4]] (+ some-list)

12:13 clojurebot: EOF while reading

12:13 manutter: ,(let [some-list [1 2 3 4]] (+ some-list))

12:13 clojurebot: java.lang.ClassCastException

12:13 raek: any arguments to apply that comes between "f" and "l" will be prepended to "l"

12:13 manutter: there we go: my code failed because I used a list as the argument to +

12:14 raek: this is a convenience feature so that you don't need to append them manually

12:14 manutter: what I want to do is add up the numbers IN the list, like with unquote splicing

12:14 for that I can use "apply"

12:14 ,(let [some-list [1 2 3 4]] (apply + some-list))

12:14 clojurebot: 10

12:15 ataggart: stuarthalloway: anything need to be worked on?

12:15 manutter: so in my code, the apply function "unrolls" my list, and clojure effectively does (+ 1 2 3 4)

12:15 zippy314_: I get it. Thanks. What's hard for me is that apply always takes a function, and I think about doing this in the middle of a list or elsewhere without a particular function in mind.

12:15 stuarthalloway: ataggart: review of fogus' work on defrecord would be welcome

12:16 http://dev.clojure.org/jira/browse/CLJ-374

12:16 ataggart: k, reviewing

12:16 manutter: zippy314_: I think if you need to make changes in the middle of the list you can just process the list first, and then pass it to some other function

12:16 stuarthalloway: ataggar: also http://dev.clojure.org/display/design/defrecord+improvements

12:17 please post comments on the ticket

12:17 manutter: apply is only necessary when you go to pass your list as arguments to some function

12:17 zippy314_: Yah, makes sense. It's all part of shifting my thinking to the clojure way. I love it, but it's just been too long since I've been really coding in lisp.

12:18 raek: having functions as values really changes how you think

12:26 zippy314_: What's the clojure ideomatic way to remove duplicates from a seq, i.e. like ruby;s #uniq ?

12:28 manutter: ,(doc distinct)

12:28 clojurebot: "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed"

12:29 zippy314_: thanks. I was searching for at filter, unique, etc.

12:30 manutter: somebody was just asking for the same thing earlier today

12:30 that's how I found out about it

12:30 someone else also did this:

12:30 zippy314_: :-)

12:30 manutter: ,(find-doc duplicates)

12:30 clojurebot: java.lang.Exception: Unable to resolve symbol: duplicates in this context

12:30 manutter: doh

12:30 ,(find-doc 'duplicates)

12:30 clojurebot: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.String

12:31 manutter: sigh, one more time

12:31 ,(find-doc "duplicates")

12:31 clojurebot: -------------------------

12:31 clojure.core/distinct

12:31 ([coll])

12:31 Returns a lazy sequence of the elements of coll with duplicates removed

12:31 manutter: there, I learn eventually...

12:31 clsmith: 'distinct' does seem a strange name for that function

12:31 zippy314_: nice. where's the clojurebot docs?

12:32 manutter: I think they're on Google ;)

12:32 ^ ^ in other words I don't know

12:33 timvisher: wow

12:33 this must be in the water today

12:33 no_mind: is there a package which implements Observer pattern ?

12:34 zippy314_: (-D)

12:34 fliebel: no_mind: What is that again? Let me google...

12:34 raek: zippy314_: you can also use set, but then the order is not maintained (distinct is lazy and carries a set with previously seen elements with it to skip those)

12:34 ,(set [1 2 3 1 2])

12:34 manutter: zippy314_: https://github.com/hiredman/clojurebot

12:34 clojurebot: #{1 2 3}

12:34 fliebel: maybe https://github.com/stuartsierra/cljque

12:35 zippy314_: ,(into [] (set [1 2 3 1 2]))

12:35 clojurebot: [1 2 3]

12:36 zippy314_: raek: cool. thanks.

12:38 raek: (also, unless you need constant time random access you can keep it as a set)

12:38 Raynes: Wow. Linode went down for the first time since we got it.

12:38 Somewhere around 150 days of uptime.

12:40 dpritchett: Is it a linode problem or something to do with your apps?

12:40 no_mind: clique is unstable...

12:41 fliebel: no_mind: Whatever that means… The interface is really simple, and works, as far as I know.

12:43 Raynes: dpritchett: I imagine it was scheduled maintenance. They pretty much never go down unless it's scheduled, and even that is very rare.

12:52 no_mind: fliebel: this is closest to what I want http://dev.clojure.org/display/design/Asynchronous+Events but cant find any schedule for development

13:13 mec: How might I transform ((apply comp fs) x) to use trampoline?

13:13 fliebel: mec: Just prepend a hash sign.

13:15 mec: fliebel: to what?

13:16 fliebel: mec: oh, wait, what is that snippet doing? Looks a lot like iterate to me. I need to run now, sorry.

13:17 mec: (f1 (f2 (f3 (f4 (f5 ... x)))))

13:17 fliebel: I;d say (reduce #(%2 %1) x fs)

13:18 maybe switch the arguments… really need torun now

13:18 mec: ok, thanks

13:20 raek: ,(reduce #(%2 %1) 0 (repeat 1e6 inc))

13:20 clojurebot: 1000000

13:21 raek: ,((apply comp (repeat 1e6 inc)) 0)

13:21 clojurebot: 1000000

13:21 raek: hrm

13:21 mec: im surprised that actually didnt blow the stack, so I'm oversimplifying my problem

13:21 raek: ~source comp

13:23 the vararg version actually does some trampolining...

13:23 https://github.com/clojure/clojure/blob/f128af9d36dfcb268b6e9ea63676cf254c0f1c40/src/clj/clojure/core.clj#L1957

13:24 ,((reduce comp (repeat 1e6 inc)) 0)

13:24 clojurebot: Execution Timed Out

13:25 raek: ,((reduce comp (repeat 1e4 inc)) 0)

13:25 clojurebot: java.lang.StackOverflowError

13:25 raek: there we have it!

13:25 you learn something every day :D

13:27 manutter: so apply is lazy and reduce isn't? Is that what those results mean?

13:28 mec: yes

13:28 stuartsierra: apply realizes the entire sequence before invoking the function. reduce only realizes 2 elements at a time

13:29 (apply + [1 2 3]) evaluates to (+ 1 2 3) but (reduce + [1 2 3]) evaluates to (+ (+ 1 2) 3)

13:29 mec: There was an example I remember of giving an infinite seq to apply

13:29 manutter: That's what I'd have expected, but it looks like reduce blows stack and apply doesn't, in raek's examples

13:29 mec: manutter: comp is blowing the stack, facilitated by reduce

13:30 manutter: ah, wait, I see, it's ((reduce... not (reduce

13:30 so the outer parens are effectively holding onto a head of some kind

13:32 I think.... Hmm.

13:32 Curse my PHP day job!

13:32 I'm burning out my brain clutch shifting gears too much :0

13:33 chouser: reduce isn't lazy. If fully consumes whatever seq you give it

13:33 s/If/It/

13:34 comp in this case is given two fns, and comp always returns an object that holds onto its args

13:34 manutter: Yes, that's it!

13:34 Thanks, it clicks now.

13:34 chouser: great! :-)

13:35 manutter: So I guess "apply" failed to blow stack because the stack isn't exhausted by an arg list of 1000000 integers, or something?

13:36 Yeah, it's not stacking, it's just making one big list

13:36 which is heap not stack

13:36 chouser: it's not even doing that

13:36 manutter: I'll get this all some day. :)

13:37 chouser: apply really is lazy, so it's not making one big list, it's just passing along the lazy sequence to comp

13:37 manutter: cool, so I started off on the right foot even if I wandered a bit between here and there.

13:38 chouser: :-)

13:44 mec: ,(rseq (seq "!23"))

13:44 clojurebot: java.lang.ClassCastException: clojure.lang.StringSeq cannot be cast to clojure.lang.Reversible

13:44 mec: you'd think that would be possible

13:46 ataggart: ,(apply (fn [x & more] x) (repeat 1))

13:46 clojurebot: 1

13:47 ataggart: apply only resolves the required fixed arity elements. it's very lazy

13:48 chouser: ,(reverse "!123")

13:48 clojurebot: (\3 \2 \1 \!)

13:48 chouser: mec: oh, I see your point. Yeah, does seem like it could be added.

13:51 bartj: Raynes, you mean try clojure is down ?

13:51 Raynes: bartj: It shouldn't be anymore. It would have been for several hours this morning.

13:51 timvisher: is it possible to use the {:keys ...} destructuring syntax in let statements?

13:52 ataggart: timvisher: yes

13:52 mec: timvisher: of course ##(let [{:keys [a b c]} {:a 1 :b 2 :c 3}] [a b c])

13:52 bartj: Raynes, it seems down for me

13:52 mec: omg wheres sexybot

13:52 Raynes: bartj: I guess so.

13:52 mec: ,(let [{:keys [a b c]} {:a 1 :b 2 :c 3}] [a b c])

13:52 clojurebot: [1 2 3]

13:53 timvisher: nice

13:53 i was missing where the source would come from

13:53 not sure why

13:53 thx guys

13:53 and gals :\

13:53 Raynes: $kill

13:53 Wow, even sexpbot isn't working properly. Sigh.

13:53 mec: ,(let [{:keys [a b] d :c :as e} {:a 1 :b 2 :c 3}] [a b e f])

13:53 clojurebot: java.lang.Exception: Unable to resolve symbol: f in this context

13:54 mec: ,(let [{:keys [a b] d :c :as e} {:a 1 :b 2 :c 3}] [a b d e])

13:54 clojurebot: [1 2 3 {:a 1, :b 2, :c 3}]

13:55 mec: chouser: clojure.string/reverse uses stringbuilder.reverse which, while not constant time, maintains combined characters

13:55 so I guess rseq is no good after all

13:58 chouser: ,(rseq "123")

13:58 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.Reversible

13:59 chouser: ,(rseq (into-array [1 2 3]))

13:59 clojurebot: java.lang.ClassCastException: [Ljava.lang.Integer; cannot be cast to clojure.lang.Reversible

13:59 chouser: ,(rseq (seq (into-array [1 2 3])))

13:59 clojurebot: java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to clojure.lang.Reversible

13:59 chouser: hm

13:59 ,(rseq [1 2 3])

13:59 clojurebot: (3 2 1)

13:59 chouser: ,(rseq (seq [1 2 3]))

13:59 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector$ChunkedSeq cannot be cast to clojure.lang.Reversible

14:00 raek: ,(rseq (sorted-set 1 2 3))

14:00 clojurebot: (3 2 1)

14:06 Raynes: I didn't start mongodb properly, which is why sexpbot is all stubborn and quiet. I'll have that fixed in a moment.

14:12 sexpbot is back in action.

14:12 technomancy: http://p.hagelb.org/try-defn.clj.html <= interesting mystery

14:13 Derander: Raynes: does sexpbot use congomongo?

14:14 ejackson: $botstnack

14:14 Raynes: Derander: Yup.

14:14 ejackson: $botsnack

14:14 sexpbot: ejackson: Thanks! Om nom nom!!

14:14 ejackson: welcome back sexp

14:15 Derander: Raynes: have you ever run into something like "db message size too big (1958167) max is (1821679)" from the java driver?

14:15 Raynes: those numbers are made up, but the first is always larger than the second. it occurs on trying to fetch a fairly large document

14:16 (9991339) max is (8389632) <-- those are the actual numbers. it's an IllegalArgumentException that gets thrown.

14:20 S11001001: Is this guaranteed? ##(let [[_ & r] '(1)] (nil? r)) for all colls/sequences in place of '(1)

14:20 sexpbot: ⟹ true

14:20 chouser: you mean collections of length 1

14:20 ?

14:21 S11001001: yeah

14:21 chouser: yes

14:21 S11001001: great

14:21 thanks chouser

14:21 chouser: The & uses 'next', which promises nil when you reach the end of the collections.

14:30 S11001001: yeah, I've been seqing those, guess I'll stop

14:43 fliebel: technomancy: Solved the mystery yet?

14:44 technomancy: fliebel: not in the slightest

14:45 fliebel: technomancy: I've experienced more weird things with try. I wonder how it's implemented.

14:46 For example, you cannot recur across a try, and locking is also doing weird stuff.

14:48 technomancy: recurring across try I can sorta understand

14:48 fliebel: I can't, what could go wrong?

14:49 hiredman: try/catch is dynamic scope

14:49 technomancy: http://dev.clojure.org/jira/browse/CLJ-31

14:49 fliebel: Where are special forms defined again?

14:49 hiredman: (infact binding, actually expands to a try/finally

14:49 )

14:50 fliebel: hiredman: What does that mean?

14:50 hiredman: fliebel: it meeans you end up with odd behaviour when you allow recur (jumps) across dynamic scopes

14:51 dnolen: fliebel: recur is not a function call, so recur across a try doesn't make sense, there is no scope to protect.

14:52 technomancy: defn inside try, on the other hand... that one stumps me.

14:52 hiredman: technomancy: huh?

14:53 fliebel: technomancy: Well, if the scope is dynamic, maybe it just thorws it away? I never used dynamic scope enough to understand it well

14:53 technomancy: hiredman: http://p.hagelb.org/try-defn.clj.html

14:53 fliebel: hiredman: Would recurring mean that you get the scope of the previous iteration?

14:53 manutter: Ah, that's an interesting idea

14:54 technomancy: the first line defines user/hi

14:54 manutter: technomancy: does the namespace exist at all outside of the try?

14:54 hiredman: technomancy: you got gilardi scenarioed

14:54 technomancy: manutter: doesn't seem to matter

14:54 hiredman: the defn is happening in the scope of the namespace you started in, not the scope of the in-ns'ed namespace

14:54 manutter: No, I mean: you start with a clean repl, run the code, it's done. Did the namespace disappear when the try ended, or did it persist

14:55 technomancy: hiredman: oh snap. I thought I tried it multiple times, apparently not.

14:55 fliebel: http://technomancy.us/143

14:55 technomancy: the do is special-cased by the compiler; of course.

14:55 hiredman: fliebel: you would loose the finally that pops the dynamic scope

14:56 indeed

14:59 fliebel: Can anyone show me some magic try clause that shows the dynamic scope?

14:59 manutter: technomancy: jark gives some interesting feedback:

14:59 user=> (try (ns foo.bar) (defn hi []))

14:59 #'user/hi

15:00 hiredman: fliebel: if you do (try .. (recur ...) (catch Exception e ...)) the recur is a jump, so if you jump outside of the try, you jump outside of the exception handling, so if the recur thows an exception, it won't be caught

15:00 technomancy: manutter: yeah as hiredman mentioned, the problem is the defn is compiled before foo.bar exists as a namespace

15:01 see the technomancy.us link above

15:01 manutter: I knew I'd seen that phrase before

15:01 hiredman: a.k.a. The Gilardi Scenario

15:02 technomancy: devious

15:02 manutter: indeed

15:02 But shouldn't that make the do fail as well?

15:02 o wait, do is a special form

15:02 fliebel: and a special case

15:02 manutter: yup yup, I didn't see the relevance of the conversation above, but I do now

15:03 I'm kicking myself for not tuning in to this channel sooner, I'm learning tons here.

15:05 fliebel: aaah! A lot of stuff starts to make more sense now, like binding + threads, and the other recur weirdness.

15:06 technomancy: recent blind testing has shown that consumers prefer the taste of Freenode's #clojure channel 4 out of 5 times

15:06 cheater_: hi

15:06 is what clojure calls m-result the same as what haskell calls "return"? (for monads)

15:06 fliebel: (try (future (throw))) will also not work of course :)

15:08 hiredman: basically, because of the lack of tco, you need recur as a functional loop construct, but it is a jump, not a proper function call, so to make it act sanely you have to restrict the use

15:09 it does make me wonder how the tco patches for openjdk deal with exceptions and finally, etc

15:09 manutter: cheater_: are you talking about m-result as used in clojure.contrib.monads?

15:10 ,(doc m-result)

15:10 clojurebot: Gabh mo leithscéal?

15:10 manutter: ,(find-doc "m-result")

15:10 clojurebot: -------------------------

15:10 clojure.contrib.monads/defmonad

15:10 ([name doc-string operations] [name operations])

15:10 Macro

15:10 Define a named monad by defining the monad operations. The definitions

15:10 are written like bindings to the monad operations m-bind and

15:10 m-result (required) and m-zero and m-plus (optional).

15:10 -------------------------

15:10 clojure.contrib.monads/m-reduce

15:10 nil

15:10 Return the reduction of (m-...

15:11 Raynes: Wow.

15:11 __name__: Why do you not teach this bot to use a pastebin?

15:11 It is very bad-mannered.

15:12 technomancy: ~botsmack

15:12 clojurebot: clojurebot evades successfully!

15:12 manutter: I'll have to be careful how I use that function from now on.

15:12 cheater_: manutter: yes

15:12 __name__: ~botsmack

15:12 clojurebot: clojurebot evades successfully!

15:12 __name__: What's that do?

15:12 cheater_: manutter: is that the same as haskell's return?

15:13 manutter: cheater_: I want to say yes, but I'm a total noob wrt haskell and monads

15:13 I'm trying to wrap my brain around it/them, but they elude me still

15:14 cheater_: have you been able to figure out monads in clojure?

15:14 i have just watched this series of tutorials, it's very good. http://vimeo.com/20717301

15:14 manutter: I've got a rough handle on at least the maybe monad in clojure

15:15 cheater_: aha

15:15 but not on defining your own monads?

15:15 manutter: Oh yeah, the brian Marick series, I started that but he hadn't finished it yet

15:15 I've been meaning to get back to that.

15:15 Yeah, defining my own monads is way beyond me atm

15:16 cheater_: i did it in one go

15:16 manutter: Hey, the weekend is near :)

15:16 Maybe by Monday I'll understand it better.

15:24 cheater_: dude

15:24 it's just an hour and a half

15:24 lol

15:29 watch it during lunch ;-)

15:29 i'm off

15:29 thanks for the help!

15:31 thorwil: the following code cannot work, but should shed light on my intention: http://paste.pocoo.org/show/384213/

15:33 that fn shall play the role of an enlive transformation. en/do-> allows to combine several such transformations into one. unsurprisingly, it does not like a when with a false condition

15:35 this is for a page navigation "Previous Next", both in <span>s in the template

15:37 4 cases: #1: there is only 1 page, nothing to navigate, no need for a transformation. #2: on the first page, only Next needs to be turned into a link. #3 somewhere in the middle: transform both. #4 on the last page, only transform Previous

15:38 what i'm struggling with is that i have zero, 1 or 2 transformations to do, so i may or may not need to use en/do->

15:54 is there something like a `when` that produces nothing if false, instead of a nil?

15:55 raek: thorwil: what value is nothing?

15:55 fliebel: Even a comment returns nil :)

15:56 thorwil: ah right, everything does at least that

15:56 dumb me, i have to assemble a list by concatenating

15:56 fliebel: &(cons 1 nil)

15:56 sexpbot: ⟹ (1)

15:57 fliebel: &(concat [1 2 3] nil [ 4 5 6] nil)

15:57 sexpbot: ⟹ (1 2 3 4 5 6)

16:10 ordnungswidrig: does (alter r identity) ensure a ref?

16:11 hiredman: ,(doc ensure)

16:11 ordnungswidrig: or does is hurt concurrency?

16:11 clojurebot: "([ref]); Must be called in a transaction. Protects the ref from modification by other transactions. Returns the in-transaction-value of ref. Allows for more concurrency than (ref-set ref @ref)"

16:13 raek: ordnungswidrig: I don't think it does

16:14 bhenry: is there a function for (apply list [1 2 3]) or do i have to apply list?

16:14 raek: ordnungswidrig: hrm. ignore that.

16:14 ordnungswidrig: have you seen this? http://java.ociweb.com/mark/stm/article.html#write-skew

16:14 stuartsierra: bhenry: list*

16:15 bhenry: stuartsierra: thanks

16:15 stuartsierra: 'welcome

16:16 ordnungswidrig: raek: ah, I lost that link

16:16 I remember to have read the article

16:18 however, it did not worry about write skew.

16:19 I have a datastructure like (ref (:users (ref { 1 (ref { :name "alice"}), 2 (ref { :name "bob"})}))), i.e. a nested map of refs of maps and so on. I want to have some values as refs to improve write concurrency

16:19 I write a function update-in-ref which works like update-in but wich will insert a call to "alter" where necessary.

16:20 with the above example you can do (update-in-ref m [:users 1] assoc :name alice) or (update-in-ref [:users 2 :bob :age] inc)

16:20 raek: if you alter a ref and the transaction succeeds, then the ref will note have been altered by another succeeding transaction in between

16:21 ordnungswidrig: raek: you mean the changes by the in-between-transaction would have been lost?

16:21 raek: ordnungswidrig: ...or what did you mean by "ensure"?

16:22 no, simply that they are atomic

16:22 s/note/not/

16:23 ordnungswidrig: raek: I meant I'm perfectly aware of write skew and ensure, I think. I was not sure if (ref-set r @r) would hurt concurrency.

16:24 raek: from the docs I read that (ref-set r@) has the same effect as ensure but at a higher cost

16:24 raek: ok, sorry. I missed the "identity" part.

16:24 that is probably true

16:26 ordnungswidrig: so my proposed function update-in-ref should make sure that only the innermost ref would be altered

16:27 raek: that sounds very reasonable, since the outer refs need not be changed at all

16:29 ordnungswidrig: hmm, that will be a lot of conditionals hackery then :-)

16:29 raek: ordnungswidrig: in this case, you could also do (-> x deref :users deref (get 1) (alter assoc :name "eve"))

16:29 ataggart: unless intermediate maps need to be created, which is the advantage of update-in. otherwise, just deref/get the ref/map you want to modify and alter it

16:30 raek: i.e. first "get-in" to the ref, and then an ordinary alter

16:34 ordnungswidrig: raek: not so bad.

16:35 I wanted to have get-in-ref and update-in-ref which handle references transparently where occuring.

16:35 (get-in-ref {:users (ref {123 (ref {:name "Al"})})} [:users 123 :name]) -> "Al"

16:46 scottj: bury-buffer is such a nice function, I can't believe I only recently learned about it

16:46 opps, wrong chan :)

16:46 Ramblurr: i'm having issues displaying utf8 chars with enlive and compojure.. i think it is because compojure isnt returning the content-type with the charset as utf8

16:48 scottj: Ramblurr: search compojure mailing list thread "Problems with compojure 0.4 + Enlive and UTF-8"

16:48 Ramblurr: scottj: yea, i just found that middleware..

16:49 scottj: since wrap! is deprecated, what is the proper way to use that with (-> ..) ?

16:49 scottj: yeah

16:49 raek: Ramblurr: ring (which compojure uses) does not set the charset parameter of the Content-Type header and the servlet spec says that if it is missing, ISO 8859-1 should be filled in

16:49 scottj: (-> app (wrap-charset ..))

16:50 ataggart: ISO8859-1 is for text/html, utf-8 is for xhtml

16:50 ordnungswidrig: cu all.

16:50 raek: Ramblurr: (assuming your files are in UTF-8) try setting the following header in the response: "Content-Type" "text/html; charset=UTF-8"

16:51 servlet containers add "; charset=ISO-8859-1" to all "text/*" types, IIRC

16:51 which is kinda sad

16:52 symbole: raek: Are you sure?

16:52 raek: Ramblurr: if you use firefox, you can see that header by right clicking and choosing show page info

16:52 Ramblurr: by default i'm not getting the content-type header at all

16:55 raek: Ramblurr: are you sure? the content-type header should always be present

16:56 Ramblurr: raek: yup -- http://i.imgur.com/wbC31.png

16:56 interestingly, the content-type is set for the GET requests to .css and .js files, but not the html responses

16:57 i wonder if i'm doing something incorrect with enlive

16:58 raek: enlive only affects the response body

16:59 symbole: fairly. I'm trying to find a mail list thread...

16:59 here's one related: http://groups.google.com/group/compojure/browse_thread/thread/44a25e10c37f3b1b/d4a17cb99f84814f?lnk=gst&q=utf8#d4a17cb99f84814f

17:01 ah, here's the thread where I saw this the first time: http://groups.google.com/group/clojure/browse_thread/thread/a7e74645baede508/7df98e3ceab51a96

17:02 symbole: http://download.oracle.com/docs/cd/E17802_01/products/products/servlet/2.5/docs/servlet-2_5-mr2/javax/servlet/ServletResponse.html#getCharacterEncoding%28%29

17:03 "If no character encoding has been specified, ISO-8859-1 is returned."

17:06 miwillhite: Hey, new to clojure…I have an app built with Leiningen, and I want to add a libraray from github…whats the best way to go about that?

17:07 do I need to clone the repo into my lib directory and just reference the namespace in the dependencies?

17:07 technomancy: miwillhite: check clojars.org for it

17:07 miwillhite: okay thanks

17:07 ah cool

17:07 technomancy: also read "lein help tutorial" if you haven't

17:07 miwillhite: I wasn't aware of this site

17:07 hiredman: or any maven repo

17:07 miwillhite: cool thanks a lot

17:08 Ramblurr: raek: herm, essentially i am passing the result of enlive/content as the handler for the route

17:08 looking at some examples, it looks i should at least be calling (apply str ..) on it

17:09 raek: Ramblurr: from the handler, try returning {:status 200, :headers {"Content-Type" "text/html; charset=utf-8"}, :body result-from-enlive-here}

17:10 Ramblurr: why? ring accepts seqs of strings as bodies

17:10 it's all here https://github.com/mmcgrana/ring/blob/master/SPEC

17:10 Ramblurr: raek: huzzah, that worked

17:11 i had just assumed the status code and headers were handled automatically..shouldn't there be a middleware for that?

17:12 raek: the status code and the content-length header are added automatically by ring

17:13 Ramblurr: and there's also these: http://clojuredocs.org/ring/ring.util.response

17:15 but as for the content-type: I think "text/html; charset=utf-8" would be resonable as a default, but you would still need to set that header when serving anything else than html

17:59 miwillhite: the lib I want to use is version 1.6 on clojars, but the current version on github is 2.3…is there anyway I can grab the github version and bring it into my app?

18:00 TheMoonMaster: miwillhite: You could push the new version to clojars, https://github.com/ato/clojars-web/wiki/tutorial

18:02 raek: miwillhite: are you saying that none of 2.3, 2.2, 2.1 or 2.0 are on clojars? one option could be to use checkouts if you use leiningen (see the readme)

18:02 miwillhite: btw, which library is it?

18:08 miwillhite: raek: I'm new to clojars, but I only see the 1.6.1-SNAPSHOT as an option

18:08 raek: It is the "store" library

18:08 I'm trying to integrate S3

18:08 raek: miwillhite: github url?

18:09 miwillhite: https://github.com/getwoven/store

18:09 btw, if you know of a better one (with better docs) I'd like to hear it

18:09 I'm brand new to clojure

18:09 this is the first library I've tried to add besides contrib

18:09 technomancy: somebody really needs to sit the woven people down and explain how releases work

18:11 miwillhite: I was a release off in my versions, its actually 0.1.6 and 0.2.3

18:11 but STILL!

18:11 raek: miwillhite: those that end in -SNAPSHOT are not releases

18:11 they are snapshots

18:11 miwillhite: yeah

18:11 I know…but thats all I see

18:11 raek: the author of the lib should really do a proper release

18:12 since he has even stepped up the snapshot versions

18:12 snapshots are supposed to go between releases

18:12 miwillhite: right…as a sort of "edge" version right?

18:12 raek: yeah

18:13 if you have people depending on your lib, then you're not in alpha anymore and 1.0.0 should be available

18:13 miwillhite: good point

18:13 I just found this one: https://github.com/ndimiduk/s3-edge

18:13 they actually have tags and its 1.0

18:14 not sure if its what I need though…

18:15 basically, I just want to pull down a bunch of files from S3

18:17 hm, I'm finding more results with the query 'aws', I think I need to dig around a bit more

18:17 raek: miwillhite: to try out a new version, you can clone a project from github and run "lein install" in the project directory to build and install that version into you local maven repo. (and if you like it, bug the author about making a release... :) )

18:17 miwillhite: sounds like the woven stuff isn't in a good place right now

18:18 raek, perfect thank you

18:18 raek: you should then be able to specify that version in your project.clj

18:18 miwillhite: awesome

18:30 stevenlawren: hello. i've installed clojure from mac-ports. when i run clj and try to run (use 'clojure.contrib.seq-utils) at the repl it says it can't find it. am i using 'use' wrong, or is there some drama with my classpath? what could it be?

18:31 technomancy: stevenlawren: clojure is pretty different from most languages in that it's not that useful when installed in a package manager.

18:32 you generally want to use something like Leiningen to get started

18:33 stevenlawren: even to run a basic script at the command line?

18:33 raek: stevenlawren: the usual way to do it, is to use a clojure environment tool like Leiningen or Cake to handle the classpath (as well as dependency resolution and fetching)

18:33 technomancy: yeah, I strongly suggest not using macports from Clojure

18:34 raek: stevenlawren: there is no official clojure launched (except for starting with the 'java' command)

18:34 *launcher

18:35 stevenlawren: is clj written by the mac ports people then?

18:35 dysinger: stevenlawren: y

18:35 stevenlawren: if you just want a taste you can try https://github.com/liebke/cljr#readme

18:35 gives you a python idle like gui to mess with

18:36 stevenlawren: i don't want all the guff of a gui, i just want to get a repl on the screen, and to be able to run a script at the command line

18:37 raek: cake is probably a better fit for the "script" style of development (which to me does not seem to be what clojure was designed for)

18:38 technomancy: clojurebot: how about jark?

18:38 clojurebot: Titim gan éirí ort.

18:38 technomancy: ...

18:39 clojurebot: jark is a clojure daemon for scripting: http://icylisper.in/jark/

18:39 clojurebot: c'est bon!

18:40 dysinger: stevenlawren: curl -O https://maven.atlassian.com/content/groups/public/org/clojure/clojure/1.2.1/clojure-1.2.1.jar ; java -jar clojure-1.2.1.jar

18:41 raek: stevenlawren: if you just want to learn the language, I recommend keeping a clojure repl session open rather than starting clojure each time you want to try something

18:41 stevenlawren: there does seem to be a dislike of scripting, or anything else related to posix from the clojure community. is that fair? is there any literature on why this is

18:41 raek: stevenlawren: you can still use load-file to "execute a script"

18:42 technomancy: stevenlawren: it's fair. it comes from some fundamental shortcomings of the JVM. we don't like it, but we live with it because zomg the GC and JIT are wow.

18:43 dysinger: stevenlawren: it's pretty easy

18:43 java -jar clojure-1.2.1.jar -e "(println 'hello)"

18:43 > "hello"

18:43 hsbot: "hello"

18:44 stevenlawren: almost all other major programming environments have gc and jit but also work well with scripting

18:45 or do you mean that the java gc and jit are particularly good, which they are

18:45 technomancy: stevenlawren: right; other cross-platform VMs are simply not in the same league when it comes to performance

18:46 jlf``: technomancy: is there any existing clojure analog of emacsclient, such that you could have a long-lived image and do something like clojureclient -e "(println 'hello)" ?

18:46 technomancy: jlf``: that's basically what jark is, linked above

18:46 I haven't used it myself

18:47 stevenlawren: that's probably an issue for oracle to fix as well, for all of java

18:47 technomancy: jlf``: or you could argue the slime/swank duo is kinda like that; that's what I use

18:47 jlf``: heh, backlog reading fail :)

18:53 dysinger: so leiningen, cljr, et al are super easy to install - I don't see what the problem is

18:54 hiredman: indeed

18:55 technomancy: well we'd all be thrilled if the JVM had a quick boot time and no classpath issues, but given that it's unlikely to ever be fixed we make ourselves comfortable.

18:56 raek: are there any fundamental reasons code has to be loaded from the classpath in clojure, btw?

18:57 hiredman: what we need is a jvm that does images

18:57 essential preload the jdk classes into ram then dump that disk and reuse it

18:57 raek: it's how you load code into a jvm

18:58 well, classloaders are how you load code, and the jvm starts with a classloader that loads from the classpath

19:00 raek: couldn't the language load source files like ordinary files, compile them to byte arrays containing JVM bytecode and then load them with java.lanng.ClassLoader/defineClass?

19:01 hiredman: http://blog.headius.com/2010/03/jruby-startup-time-tips.html

19:01 raek: "load like ordinary files"

19:01 what does that mean?

19:01 http://download.oracle.com/javase/1.5.0/docs/guide/vm/class-data-sharing.html neat

19:02 dysinger: % java -jar clojure-1.2.1.jar -e "(defn hello[] (println 'hello))" -r

19:02 #'user/hello

19:02 user=> (hello)

19:02 hiredman: "Dumping a shared archive is not supported on the Server JVM.

19:02 "

19:02 :(

19:07 hguy: does clojure have it's own name for zip? i can't find it anywhere. not zip as in that zipper library whatever it is, the standard functional zip function

19:08 hiredman: ,(find-ns 'clojure.zipper)

19:08 clojurebot: nil

19:08 hiredman: grr

19:08 ,(find-ns 'clojure.zip)

19:08 clojurebot: #<Namespace clojure.zip>

19:09 hiredman: oh, zipmap? or map?

19:09 ,(zipmap (range 10) (range 10))

19:09 clojurebot: {0 0, 1 1, 2 2, 3 3, 4 4, 5 5, 6 6, 7 7, 8 8, 9 9}

19:09 hguy: is that really what i want? i want the really basic zip function

19:09 hiredman: ,(map vector (range 10) (range 10))

19:09 clojurebot: ([0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9])

19:09 hiredman: basic zip function?

19:10 hguy: the same zip function that haskell and all other funcitonal languages have

19:10 hiredman: why don't you just explain what you want?

19:11 hguy: (zip [1 2 3] [4 5 6]) to [[1 4] [2 5] [3 6]]

19:11 any other functional language in the world has that function

19:11 even python does!

19:12 hiredman: I jsut showed it to you

19:12 ataggart: a function to create a list of tuples from lists seems kinda limited

19:12 hguy: zipmap? it has nothing to do with maps

19:13 dnolen: ,(map vector [1 2 3] [4 5 6])

19:13 clojurebot: ([1 4] [2 5] [3 6])

19:13 dnolen: hguy: ^

19:13 hiredman: hguy: I showed you three things, one of them does exactly what you want

19:13 ataggart: just what hiredman showed

19:13 hguy: i'm starting to think that clojure developers don't really understand functional programming when very basic functions such as zip are missing. if it's not required why does haskell have it

19:13 dnolen: hguy: contrary to popular belief, Haskell is not in fact the world's first functional programming language.

19:14 hguy: no but it is the academic and industry standard

19:14 ataggart: there are only so many good words, not all of them mean the same thing in every language

19:14 dnolen: hguy: depends on who you ask, some people prefer SML or OCaml

19:14 ataggart: anyway, if you want to create a list of tuples, (map vector ...) is your answer

19:15 hguy: it's a very basic computer science concept - there's even a wikipedia page on it http://en.wikipedia.org/wiki/Convolution_(computer_science)

19:15 hiredman: hguy: I'm going to go ahead and ignore you now, but please continue

19:15 ataggart: have a nice day

19:17 * technomancy golf claps

19:17 raek: one reason for the lack of a zip function could be the lack of a tuple type

19:17 dysinger: heh that hiredman is rude! :)

19:17 technomancy: A++ excellent time; would be trolled again.

19:17 ataggart: yes hiredman is rude, but sometimes it's appropriate

19:17 dnolen: hguy: if you'd rather have the zip you're familiar with, you can always (def zip (partial map vector))

19:18 hguy: every time you ask a question about clojure it's very quickly apparent that the community doesn't really understand computer science at all

19:18 * ataggart yawns

19:18 dnolen: hguy: wow just wow.

19:18 hguy: never heard of the zip operation, that's wow

19:19 ataggart: so, waffles or pancakes?

19:19 I prefer waffles

19:19 hguy: waffles? don't you mean carrots ha ha ha

19:19 technomancy: definitely waffles

19:19 my secret is to stick some brown sugar in the batter

19:19 ataggart: I'm not sure if the need for specialized equipment should count as a pro or a con

19:20 dysinger: I like dolphins

19:20 hiredman: technomancy makes great german pancakes

19:20 delicious

19:20 ataggart: porpoises > dolphins

19:21 hiredman: but I am more of a pancake anyway

19:21 dysinger: clojurebot: pancakes

19:21 clojurebot: Titim gan éirí ort.

19:21 dysinger: there's work to be done!

19:23 ataggart: (binding [*print-dup* true] (pr-str 2))

19:43 seancorfield: if someone thinks haskell is the be-all and end-all of FP, why do they even bother coming in here criticizing clojure?

19:43 * seancorfield is puzzled

19:44 technomancy: for amusement?

19:46 dysinger: I kinda like haskell

19:46 I like dolphins & pancakes too

20:43 SergioTapia: Hi

20:43 Check out this wallpaper I made :P

20:43 Derander: http://cl.ly/2H2w353f2P1J3L0P2a2m <-- is that the normal google look? it looks more pastel.

20:43 SergioTapia: http://i.imgur.com/cZj1N.png

20:43 Yeah, it looks weird for me too.

20:43 I think they changed it.

20:44 Derander: bizarre

20:44 SergioTapia: I don't know, I think it looks better

20:44 easier to scan the information you need

20:44 Derander: it looks completely alien :-)

20:44 the whitespace between results is appreciated

22:24 miwillhite: Hi, I'm trying to include the jets3t library. Lein found the dependency with [net.java.dev.jets3t/jets3t "0.8.1"], but I can't figure out how to require it in my clj file…trying this:

22:24 (:require net.java.dev.jets3t)

22:25 but the compile fails

22:25 Could not locate ... on classpath:

22:25 (very much a beginner here)

22:27 tomoj: require and use are for clojure namespaces only, for java deps you need to import the classes you want

22:27 ..or just refer to them fully-qualified

22:27 miwillhite: I'll paste some code, I thought that was what I am doing…

22:28 tomoj: (:require foo.bar) will only work if foo.bar is a clojure namespace

22:28 I don't think net.java.dev.jets3t is

22:29 miwillhite: http://pastebin.com/naLNFuHi

22:29 I guess the real question is…how do I know which namespace to include?

22:30 semperos: miwillhite: don't use :require

22:30 use :import

22:30 so if jets3t is an actual class you want to use

22:30 you can do (:import net.java.dev.jets3t)

22:30 if you're importing multiple classes in the same "depth"

22:30 you can do

22:31 (:import [net.java.dev jets3t foo bar])

22:31 then you can reference the class with just it's name

22:31 miwillhite: okay, that makes sense

22:31 tomoj: you need to look for the jets3t javadocs or documentation to find which classes you want

22:31 miwillhite: right, thats what I'm missing

22:31 semperos: yep

22:31 miwillhite: its starting to come together ;)

22:31 thanks for your help

22:32 tomoj: you could poke through the jar and take some guesses.. but..

22:32 semperos: http://jets3t.s3.amazonaws.com/api/index.html

22:32 miwillhite: ah perfect

22:32 thank you so much

22:32 semperos: no problemo

22:32 so I'm trying out JGit, writing a Clojure wrapper for it

22:33 when I do a git clone with the library, it clones the .git folder of the repo, but doesn't actually copy over the files

22:33 and I'm not making "bare" repo, it's supposed to be a normal repo

22:33 anybody have any experience with JGit, or any thoughts?

22:35 dlh: I'm not familiar w/ JGit, but you most likely need to manually do a checkout.

22:35 semperos: it's been a few hours, I'll double-check if that does it

22:35 dlh: thanks for the thought

23:21 trptcolin: gcj

23:22 technomancy: ~guards

23:22 clojurebot: SIEZE HIM!

23:23 technomancy: using gcj in a clojure channel... honestly.

23:23 trptcolin: what's gotten into you? =)

23:23 trptcolin: :) whoopsie

23:24 technomancy: trptcolin: how did that training program go?

23:24 trptcolin: wowsa - didn't realize gcj was a java compiler

23:25 it went great, thanks!

23:25 people seemed to get a lot out of it

23:25 technomancy: how many attendees wer there?

23:25 trptcolin: 10ish

23:26 technomancy: mostly local?

23:26 trptcolin: yeah. a few from out of town, but mostly chicago-area

23:27 so the other day i was thinking of looking into a way to extend radagast to work w/ other test frameworks - specifically speclj

23:28 any thoughts? just took a quick look, seems like it wouldn't be too bad

23:28 technomancy: clojurebot: forget guards |is| <reply>SIEZE HIM!

23:28 clojurebot: I forgot that guards is <reply>SIEZE HIM!

23:28 technomancy: clojurebot: guards |is| <reply>SEIZE HIM!

23:28 clojurebot: Ok.

23:28 technomancy: that's better

23:28 hmmm...

23:28 yeah, I don't think there's much to it.

23:29 the coverage is pretty orthogonal; it just sees if stuff has run at all.

23:30 ataggart: read is the corollary to print-dup, right?

23:31 trptcolin: looks like just 1 line to kick off the runner (applying clojure.test/run-tests over the nses)

23:31 technomancy: zactly

23:59 seancorfield: why is print-dup called that?

23:59 we seem to have a lot of print functions...

Logging service provided by n01se.net