#clojure log - Jun 01 2012

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

0:03 wei_: what's the idiomatic way to include something in a hash only if it's not nil? e.g. {:a a :b b} but if b is nil, then the map should just be {:a <value of a>}

0:08 ^ nevermind, this helped: http://stackoverflow.com/questions/3937661/remove-nil-values-from-a-map

0:15 irc2samus: hmm the shutdown hook fires on normal program exit but does not when receiving SIGINT (which was my original goal) :/

0:16 technomancy: your version works too and it's prettier, thanks

0:18 technomancy: irc2samus: you may be able to catch an InterruptedException or something

0:26 irc2samus: nope, even with try/catch it just aborts

0:27 I'm running with "lein run" and Clojure 1.2 would that matter?

0:28 technomancy: shouldn't

0:33 irc2samus: it doesn't work on te repl, neither 1.2 nor 1.3

0:34 weird, the whole internet agrees on that solution regarding specifically SIGINT (they talk Java but should apply here as well)

1:04 amalloy: well mostly you can't 100% rely on anything that happens after a SIGINT

1:05 though the usually-works solution for java should also mostly-work for clojure

1:06 useful.java has a signal-handler function, which is not portable across all JVMs

1:06 https://github.com/flatland/useful/blob/develop/src/useful/java.clj#L10

1:08 estebann: i am almost completely ignorant about functional programming, and am suffering a failure of imagination

1:08 how are large scale projects organized in a functional scheme

1:09 ?

1:09 devn: is it evil to use &(resolve ((comp symbol str) "ns/my-fn-prefix-" "ends-like-this"))

1:09 will that break across namespaces?

1:11 for instance: in x.core I have (:require [x.abc :as abc]) -- later on I use the above to get a fn out

1:12 in x.def I (:require [x.core :as core]), then I go to use core/fn-which-uses-resolve-in-its-body

1:12 will it still resolve properly in this scope?

1:18 brainproxy: estebann: are you asking in general or you're specifically interested in how clojure addresses the issue?

1:18 amalloy: seems like that would be faster to try out than to ask about, devn

1:23 estebann: brainproxy: a bit of both. I've come from an OO and messy procedural background and I cant really imagine how to organize code better in clojure than I did in C

1:25 if you could point me to some sort of overview of functional design principals I would be grateful

1:27 brainproxy: estebann: first of all, don't worry, you'll catch on ... I'm only a few weeks in myself, coming from a mostly javascript background

1:28 estebann: in clojure, code is organized using namespaces; namespace members can be used in the context of other namespaces with the help of `require`, `use`, and so on

1:29 gfrederi`: you don't even have to instatiate them!

1:29 brainproxy: in other words, namespaces allow groups of related values to be organized, "modularized"

1:30 also, a dependency management framework as provided by the "leiningen" tool which is popular in the clojure community

1:31 allows authors to declaratively indicate what their packages will need in place in order to work properly

1:32 this allows rather efficient organization, modularization of code

1:33 devn: amalloy: come on man, do you see any obvious deficiency with it? I ran into an issue earlier while I was hacking around with it, but I'm not sure if that is the reason.

1:33 estebann: brainproxy: ok, I believe I will be able to get to the code I need when I need it.

1:33 brainproxy: estebann: yep, and w/ leiningen it's really easy

1:33 amalloy: *shrug* i don't think it will work, but i dunno

1:33 instead you probably want (ns-resolve (the-ns ns) (str "prefix-" fn-name))

1:34 brainproxy: estebann: I've had a great experience with the Clojure Programming book from O'Reilly; readint it with clojuredocs.org and clojureatlas.com close at hand

1:34 *reading

1:34 devn: yeah, probably right on that one. i used resolve because when i was mucking around i didnt care about passing in the ns if i could get away with "foo/bar"

1:34 amalloy: thanks

1:34 estebann: brainproxy: my problem is that I'm not really sure how to think about complex systems without agency.

1:35 brainproxy: I tend to think of things doing verbs.

1:35 devn: estebann: for what it's worth, don't get focused on organization

1:35 estebann: it seems a lot harder to think just in terms of nested verbs

1:35 devn: let organization *fall out*

1:36 estebann: hmm... I'm willing...

1:36 devn: estebann: i was used to tens of files when i came to clojure and spent time thinking about how id split up all of the fns by file and so on, and found it to be a headache, not because it is "hard" so much as I think it's just fundamentally wrong

1:37 brainproxy: estebann: honestly, I think if you work through the (sometimes super challenging!) examples in a book like http://www.clojurebook.com/ you'll be able to decide wether this func prog stuff is for you or for the birdss :D

1:37 estebann: btw, I'm not one of the authors, nor trying to sell you on it, just had a super good experience with it, and it seems like you need something that will "show you the ropes"

1:37 devn: estebann: one last thing on organization. use clojure, but just follow the rules and only use one file.

1:38 use one file until you hit about 1000 lines. at that point the fns which can be in their own file(s) will be obvious

1:38 that's how it has worked out for me anyway

1:39 excess code organization leads to headaches if you overdo it early on. im stealing from rich or stu or someone recently

1:39 but it's a bit like pouring concrete on your code

1:39 you will have less freedom if you over-organize early in the process

1:39 estebann: devn: i can totally see that

1:40 devn: the same is true for other languages, but i think we ignore it because it's "how things are done"

1:40 in clojure you feel the pain of it

1:40 it hurts, but i think it produces more manageable code in general

1:40 brainproxy: devn: in NodeJS, the modules system encourages breaking things up into ~100 - 250 LOC files

1:41 estebann: devn: on the other hand when I'm confronted with a complex process that I need to design all at once functions alone seem rather a sparse vocabulary for doing that.

1:41 brainproxy: devn: and by encourages, I mean that doing so is pain free and seems to help individual pieces from turning into giant hairballs

1:41 devn: brainproxy: yes, this is not a surprise, right? this happens all over the place. big files can become cesspools. In Clojure I don't feel this way. I am comfortable reading a clojure file that is a few thousand lines because the ordering of fn declarations and so on makes it straightforward, story-like

1:42 in other languages that lack the same functional properties of clojure i find this to be unnerving and painful

1:42 gfrederi`: estebann: not only functions but also data!

1:42 brainproxy: estebann: clojure gives you protocols and types also

1:43 devn: estebann: functions are verbs. what other vocabulary do you need?

1:43 estebann: devn: subject and object

1:43 devn: (defn embiggen ...) (defn make-party-hat ...) (defn retrieve-headers ...) and so on

1:43 estebann: think in terms of data, not abstractions that hide data

1:44 estebann: devn: I come ultimately from a philosophy background so maybe I am suffering under a disadvantage

1:44 brainproxy: estebann: what I've learned so far is that you can go a *long* way using the built-in collections for data structures

1:44 devn: i found it helpful to think to myself: "I have [1 2 3]. I want [3 2 1]. How do I get from [3 2 1] to [1 2 3]?"

1:44 abp_: I would even say that it's not very likely to get many LOC's with Clojure while learning anyway. The language is just to terse and especially so while learning with little pet problems and projects.

1:45 devn: estebann: i almost wrote a macro yesterday. i almost wrote a multimethod the day before. i didnt need either of them.

1:45 functions win. you just need to live with them in harmony for awhile and they will become your faithful servants

1:45 abp_: Just reiterate and improve your code while learning. Will shrink everything to nearly nothing.

1:45 estebann: all: I believe, help thou my unbelief

1:46 brainproxy: :)

1:46 devn: estebann: nothing helps like *knowing*

1:46 :)

1:46 i think it honestly took me 3-4 months before i started to go "ah-ha"

1:46 and that was just the beginning

1:47 this is the beauty of learning a functional language. you keep saying ah-ha. it feels better and better as time goes on. it's like learning to play a violin instead of feeding a player piano.

1:47 or at least i have...

1:48 ruby is a tremendous bore compared to clojure and its community.

1:48 that should be reason enough to feel like awkward for awhile. :)

1:48 like the awkward kid*

1:48 estebann: ok I'm hoping to re-implement some existing code in clojure (mostly be because I want to give it a try) is the best way to go about converting from oo to functional to just go one step at a time from entry point onward

1:48 ?

1:49 that was pretty incoherent

1:49 devn: estebann: nono, i know where you're coming from

1:49 it's a vague question with a vague answer

1:49 the question id ask of you is: what is your problem? what do you want as a solution? talk about input and output in here.

1:50 it's helpful to say: "I have [1 2 3]. I want to get [3 2 1]. How do I do that?"

1:50 Small steps.

1:50 that lets you start building tiny functions, and then you can start composing them and see how things build up.

1:52 estebann: if you can legally post the code you're interested in reimplementing in clojure, that might be a start, for instance.

1:52 estebann: ok, maybe I'm being too ambitious. I have an execution path that esentially turns a large number of numbers into a simplified cumulative distribution function

1:52 it seems like an ideal target for a functional approach

1:53 but there are a lot of steps between the first set of numbers and the final result

1:53 devn: estebann: it's okay to have an ambitious goal, but i felt like i got a bit monk-like when i started to grok clojure. id take a deep breath, think about the values i had in my hand at the repl, and think about the transformation id need

1:53 the first step. that is the important one. it's hard to go wrong with pure functions.

1:54 ,(map Integer/parseInt ["1" "2" "3"])

1:54 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer, compiling:(NO_SOURCE_PATH:0)>

1:55 devn: ,(map #(Integer/parseInt %) ["1" "2" "3"])

1:55 clojurebot: (1 2 3)

1:56 devn: "I have '(1 2 3). I want to sum them."

1:56 AimHere: ,(map read-string ["1" "2" "3"])

1:56 clojurebot: (1 2 3)

1:56 brainproxy: estebann: it's probably helpful to learn a little bit about the basic containers that clojure provides you, and the facilities they afford you

1:56 devn: ,(reduce + '(1 2 3))

1:56 clojurebot: 6

1:56 devn: AimHere: lol. why?

1:57 AimHere: it's an inbuilt first-class function that does roughly what your parseInt example does; though perhaps more flexible and slower

1:57 brainproxy: in other words, knowing about lists, hash maps, vectors and sequences, and the kinds of things you can do with them and expect from them

1:57 devn: more flexible to a fault. i guess if you're damned sure of your inputs it's fair, but it just feels... i dont know... filthy.

1:57 like eating pizza in a sewer ;)

1:58 estebann: devn: AimHere = NinjaTurtle?

1:58 devn: hahaha

1:58 donatello? is that you?

1:59 AimHere: Caravaggio. I'm the fifth Ninja Turtle

1:59 devn: estebann: you need to know about str, map, filter, reduce, apply, [], '(), #{}, {}, and a handful of other fns, and you should be able to start hacking stuff together

1:59 estebann: also, (use 'clojure.repl)

1:59 ,(doc filter)

1:59 clojurebot: "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects."

1:59 brainproxy: i would say that coming to some terms with regard to laziness is quite important also

2:00 devn: ,(apropos "map")

2:00 clojurebot: (sorted-map ns-unmap zipmap mapv map ...)

2:00 devn: that will let you explore a bit

2:00 brainproxy: i think you can defer that

2:00 fwiw

2:00 gfrederi`: devn: aw you don't need #{} to hack things together

2:00 devn: gfrederi`: you dont, but man it's cool if you're not used to a set literal

2:00 riley526: Hello all, complete noob here. Quick question: How do I switch from clojure 1.2.1 to 1.3 in the Leiningen 1.7.1 REPL?

2:00 brainproxy: devn: i dunno, seems like otherwise, you might shy away from things that are super nice

2:00 like ranges and what not

2:01 which in non-lazy langs could be prohibitive if they're large

2:01 devn: brainproxy: yes, but you have to do it wrong to know how to do it right!

2:01 this is what good math professors teach us

2:01 gfrederi`: (alter-var-root *clojure-version* (constantly {:major 1 :minor 3 :incremental 0}))

2:01 brainproxy: iow, if you assume eager evaluation, like with most other languages

2:01 devn: CS skirts this discipline in the classroom all the time

2:01 do it the hard way. then realize you have real ultimate power.

2:01 brainproxy: you're perspective on what's possible would have a much narrower horizon

2:02 devn: brainproxy: yes, but narrow makes you focus.

2:02 and for beginners there is so much already, narrow is good

2:02 gfrederi`: riley526: you want to change the version of clojure in the project.clj file and restart the repl

2:02 AimHere: Well this guy is going to be converting oo code to clojure to 'try it out'; he might end up with that narrow focus just by the way he's starting otu

2:02 estebann: don't worry if you have hegel or kant questions come to me. pure cs questions... I learn on the job

2:03 * brainproxy throws a copy of the summa at estebann

2:03 estebann: the summa was kind of awesome, imho

2:03 devn: estebann: dialectic. explain it.

2:04 the hegelian ones i mean

2:04 * devn likes the three-valued logic stuff

2:04 estebann: dialectic is process by which multiple oposing ideas are able to

2:04 ...

2:04 brainproxy: estebann: i think so too, but have a philo prof who is a thomist and cringes at the very mention of kant

2:04 devn: alfred north whitehead?

2:05 anyone actually take up rich's suggestion to read it from Are We There Yet?

2:05 that book is...jesus.

2:05 incredible ideas. but it took me 30 minutes per page in some cases.

2:05 estebann: that's how you know it's the good stuff

2:07 devn: he makes a cool argument about how all arguments are flawed because they presuppose the existence of the universe

2:07 which makes you head into thought loop territory

2:07 riley526: gfrederi`: do I need to create a project before I run `lein repl` then? there is no existing project.clj that I can find.

2:08 estebann: i've never read "are we there yet" but I enjoyed meditations on first philosophy. in a popcorn sort of way

2:08 antares_: riley526: you can run lein repl without generating a project

2:09 riley526: antares_: right, but gfrederi` says I need to edit project.clj in order to change the clojure version.

2:09 estebann: it seems embarissingly obvious that descartes wanted someone to solve the problem of mortality before he died

2:09 brainproxy: estebann: and a friend and I set out to read Copleston's series, but I only got through the 1st volume before getting too weighed down with work to properly commit the time to it everyday

2:10 estebann: brainproxy: you are a better man than I

2:10 all: thanks! i'm encouraged

2:10 brainproxy: estebann: good luck, ask questions any time

2:11 antares_: riley526: that is correct. if you want to run lein repl with a particular version outside of a project, you need a version of leiningen that is compiled against that Clojure version

2:11 riley526: so, clojure version is specified per-project. Globally you can only change it with leiningen 2 via profiles.

2:11 devn: estebann: yeah. seriously. i hope ive been helpful. this is a great group of people who genuinely want to help, so dont be shy.

2:11 cheers

2:12 estebann: devn: super helpful.. gnight

2:12 devn: ciao

2:13 riley526: antares_: ok, so it's a lein 2 thing then. I wonder if I'd be better off just upgrading to a 2.0.0 preview now.

2:14 antares_: riley526: it's not hard, I think most of active Clojure projects are on lein2 by now

2:15 riley526: antares_: yeah, I'm really just starting out anyway, so I don't need *everything* to be supported.

2:15 antares_: riley526: it is not a lein2 thing per se, it's just for lein repl, Clojure is a library that's loaded. It can be managed like other dependencies but outside of projects, there is no "list of dependencies" in lein1. Lein 2 has :user profile that is always loaded.

2:16 riley526: https://github.com/technomancy/leiningen/wiki/Upgrading, download 1 script, put it on PATH, run lein self-install

2:17 interesting, I haven't tried to force a particular Clojure version outside of a project

2:37 riley526: there seems to be a regression in lein2 preview5 (just released) that breaks lein2 repl. I suggest putting together a small project and using either 1.7 or 2.0 preview 4 for now.

2:38 riley526: antares_: thanks for the heads up. I decided to stick with 1.7.1 for now, and just work out of a generic project.

2:38 antares_: good idea

2:39 PeregrinePDX: Ok I've thought myself in circles three times. I have a list of anonymous functions. I want to execute each function in the list passing into each of them an arguement.

2:39 I think I need one of the do functions but I've confused myself.

2:41 antares_: PeregrinePDX: doseq + (apply f arg)

2:41 PeregrinePDX: that's if you want to invoke them for side effects. If you care about returned values, use map + apply

2:42 PeregrinePDX: Yeah, I care about the returned values. Thanks

2:59 antares_: PeregrinePDX: something like (map #(apply % [10]) [(fn [x] (* 5 x)) (fn [x] (* 2 x))])

2:59 hiredman: what a waste

3:00 antares_: justify your use of apply

3:00 antares_: hiredman: it just an example

3:01 (map #(% 10) [(fn [x] (* 5 x)) (fn [x] (* 2 x))]) can work just as well

3:01 emezeske: &(doc juxt)

3:01 lazybot: ⇒ "([f] [f g] [f g h] [f g h & fs]); 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)]"

3:01 muhoo: ((juxt (fn [x] ...) (fn [y] ..) (fn [z] ...)) somearg) ?

3:02 antares_: yeah, yeah. juxt is exactly what you don't show people who are only getting started.

3:02 emezeske: PeregrinePDX: juxt is what you want

3:02 antares_: because it takes them 5 minutes to just read through that docstring

3:02 emezeske: antares_: I for one, am always happy to be introduced to a function that does exactly what I want, rather than writing it myself...

3:02 antares_: And have been since day one.

3:03 antares_: emezeske: when you study a language, do you first learn words or sophisticated idiomatic expressions that involve not-so-standard use of tenses and so on?

3:03 juxt is exactly that kind of thing for functional programming

3:04 emezeske: That's a ridiculous comparison

3:04 antares_: it's ridiculous to feed newcomers juxt and call one extra "apply" call a waste

3:05 emezeske: The apply call was a waste though, with no purpose

3:07 Anyway, it's nothing personal if someone corrects your code in here, it happens to me all the time, and I learn from it

3:08 I actually am happy when I see a hiredman or an amalloy calling me out on stupid code, it's like a code review for free :)

3:08 antares_: I don't mind if my code is corrected. For whom it was pasted, it does not matter if there's a direct call or via apply or juxt. The person wants to get a feel of what it's like to pass function as values, starting with a simple example of iteration.

3:09 emezeske: So there's no problem with me answering the question "how do I print hello world" with this code snippet?

3:09 &(apply apply apply str (list (list (list "hello " "world"))))

3:09 lazybot: ⇒ "hello world"

3:10 antares_: emezeske: dude, go to some fucking haskell mailing list and show yourself off there

3:10 together with all "what a waste" and other comments

3:10 emezeske: antares_: Okay, I'll exit this conversation at least, before I get cursed at again. Happy coding.

3:11 antares_: instead of provisioning lein2 preview 5 on travis-ci.org I have to listen to nonsensical comparisons of Clojure elitists

3:13 abp_: emezeske:

3:14 emezeske: abp_: Did you send me a message? I don't see anything.

3:15 abp_: emezeske: sorry, were about to and hit return to early..

3:15 emezeske: abp_: ^_^

3:15 abp_: I thought maybe my IRC client couldn't display it or something.

3:33 clojure-newcomer: hey guys, I'm having trouble working with JTidy (or adding as dependency to lein). I've got '[org.clojars.jmeeks/jtidy "r938"]' in project.clj, but I can't resolve Tidy in the REPL

3:33 any ideas ?

3:36 antares_: clojure-newcomer: what does the exception message say?

3:36 clojure-newcomer: antares: if I use '(use '(org.w3c.tidy)) ' and then (new Tidy) I get 'Unable to resolve classname: Tidy'

3:37 antares_: clojure-newcomer: when you run lein repl (or lein deps), are there any exceptions?

3:37 clojure-newcomer: plus, is it '(use …) or (use …) ?

3:37 the former isn't evaluated (executed)

3:38 clojure-newcomer: hmm… its (use...

3:38 sorry was quoting in here...

3:38 antares_: clojure-newcomer: no problem. Can you please gist your project.clj?

3:38 I see that jtidy is available from oss.sonatype.org

3:39 that repo is not on the default leiningen list

3:39 clojure-newcomer: sure

3:39 antares_: so you may need to add it like so: https://gist.github.com/29f6942b7a1ec5e2bd45

3:39 but if REPL starts, it probably means that the jar was resolved and downloaded

3:40 clojure-newcomer: antares: http://pastebin.com/FYABxJtp

3:40 yes, I spotted it had resolved

3:40 antares_: clojure-newcomer: wait, I think I get it. you need (import org.w3c.tidy.Tidy), then (Tidy.) and (new Tidy) should work

3:41 use is for clojure namespaces

3:41 clojure-newcomer: I'll try it now

3:41 antares_: while you want to use a Java class

3:41 clojure-newcomer: antares: thanks

3:41 sorry newb here

3:41 not really worked with java classes yet within clojure

3:41 antares_: clojure-newcomer: no problem, that's what this channel is for

3:46 kral: namaste

3:46 bobry: a question about CA: is it possible to email a scan? or postal mail is the only option?

3:49 antares_: bobry: 4 months ago I was told that postal mail is the only option

3:53 bobry: oh, okay

4:21 ro_st: technomancy: i want to use clojure-swank's buffer <-> repl keybinding actions across frames (instead of across windows)

4:21 is this possible?

4:22 i already have the repl up in a separate frame on a new monitor, but the keybindings open up the repl in the active frame in a new window instead

5:24 anyone using monger, in here?

5:25 i want to know how to refer to nested fields in the find function

5:26 usual mongo says use "item.field". monger uses :field to refer to fields. does this mean use :item.field? "item.field"?

5:55 clojure-newcomer: hey guys… how do I access the content of byte[] maybe iterating over a collection contained in it ?

5:57 in this case its coming back from clojure.java.jdbc

6:04 digcon9: clojure-newcomer: you can call seq on that array and use any functions on sequences

6:05 clojure-newcomer: digcon9: oh, cool

6:05 thx

6:18 Drakeson: Imagine that I need to define an object that needs to be evaluated just when it being consumed (a bit similar to lazy sequences; this one needs to interact with a bunch of caches and filesystem). Can I implement it without resorting to java?

6:20 borkdude: Drakeson http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/delay maybe?

6:20 lazybot: Nooooo, that's so out of date! Please see instead http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/delay and try to stop linking to rich's repo.

6:25 Drakeson: Thanks. not exactly what I need, but close enough.

6:27 borkdude: Drakeson maybe you can find more helpful things using Clojure Atlast ;) http://www.clojureatlas.com/org.clojure:clojure:1.4.0?guest=t#concept/delay

6:27 Drakeson: What would it take to get clojure.repl/doc to print documentation for java classes, methods, fields, packages, etc.?

6:28 ro_st: i believe doc is simply a metadata reader shortcut

6:28 borkdude: Drakeson currently in reply you can just type (javadoc String) and it will point your browser to the javadoc online

6:29 Drakeson: Note: Opening javadoc in a browser does not count as *print*ing documenation

6:29 ro_st: that's handy!!

6:29 borkdude: Drakeson you can also get members, etc

6:30 Drakeson: I have used reflection to augment clojure.repl/doc to print members, fields, and constructors of a class, but haven't found a way to get at javadoc in a clean way.

6:32 borkdude: Drakeson I guess you can take a look at https://github.com/clojure/clojure/blob/master/src/clj/clojure/reflect/java.clj

6:33 Drakeson ok yes, reflection is about as far as it goes I think

6:34 Drakeson: borkdude: That is interesting. Thanks.

6:34 Is there a clean way to get at javadoc, at all? In a related matter, is it possible to automatically rebuild [many] jars, but with javadoc enabled?

6:36 borkdude: I wouldn't know, sorry

7:41 zomg: Hm the doto macro is pretty nice :)

7:42 Kvaks: What's the best way to install Clojure on Ubuntu? I suspect using the Ubuntu apt repos won't get me the freshest version. I believe I can also get Clojure with git or through leiningen (get leiningen first)? Which is the preferred way?

7:43 florianover: use leiningen

7:44 Kvaks: A'ight.

7:49 antares_: Kvaks: installing leiningen is all you need typically. For production env, JDK is sufficient (apps are commonly packaged as "fat jars" with all the dependencies included, Clojure, too)

7:50 Kvaks: Thanks.

8:09 bordatoue: hello

8:10 I have got a problem with clojure setup on emacs, everytime when i restart emacs i need to reinitalise the marmalade package

8:11 so on restarting emacs i lose clojure-mode

8:17 vijaykiran: bordatoue: what do you mean by reinitializing package ? load ?

8:19 clojure-newcomer: hey guys, I've got a clojure.java.jdbc result coming back as a byte[] its from a GROUP_CONCAT on an int(10) field. In the mysql client the result is '1,2,4,6,7,19,24,32,54,152'. I am unsure how to extract this result properly in clojure… (println (seq (samovar))) gives me an unexpected result

8:22 antares_: clojure-newcomer: that should be handled by the driver. Post more details to the mailing list?

8:23 clojure-newcomer: antares: ok, will do

8:23 for '1,2,4,6,7,19,24,32,54,152' I get (49 44 50 44 52 44 54 44 55 44 49 57 44 50 52 44 51 50 44 53 52 44 49 53 50)

8:23 pretty confused

8:32 Kototama: hi, when using emacs+slime is there a way to have the exception during executions being displayed just like the errors during compilation?

8:32 ie, in the slime debugger

8:32 and not just in the *swank* buffer for instance?

8:40 bordatoue: everytime when i restart emacs, I am having to reinitialise package manually and install clojure mode. For some reason it is not saving package references installed . My current configuration is http://hastebin.com/menodiputi.lisp

8:41 vijaykiran: which version of Emacs are you using ?

8:42 bordatoue: vijaykiran: emacs 23.1

8:42 vijaykiran: bordatoue: do you have elpa folder with clojure-mode in your .emacs.d ?

8:42 bordatoue: vijaykiran: yes

8:43 vijaykiran: elpa also contains archives

8:43 vijaykiran: bordatoue: I just have (load "~/.emacs.d/els/package.el") in my config

8:44 bordatoue: may be you can try loading/requiring clojure-mode

8:44 hoeck: clojure-newcomer: that looks like the bytes of a string

8:44 bordatoue: vijaykiran: that is what i am speculating ,is it necessary to have package.el under a subdirectory

8:45 clojure-newcomer: hoeck: yeah, I figured, unfortunately being a clojure newb I can't do much with them yet

8:45 hoeck: clojure-newcomer: mysql group concat produces a string, the driver probably fails to convert it to a java string

8:46 clojure-newcomer: hock… there is a mysql issue where if I also use a group_by it produces a binary result

8:46 vijaykiran: bordatoue: does M-x list-pacakges list the clojure-mode as installed ?

8:47 clojure-newcomer: hoeck: sorry, just had a typing incident unsure where the hock… came from

8:48 hoeck: clojure-newcomer: if you know the encoding you are using (probably utf-8, but for comma-separated numbers it doesn't matter), (String. <the-bytes>) should work

8:49 clojure-newcomer: hoeck: I'll try it thanks

8:49 hoeck: clojure-newcomer: by binary result you mean an array of bytes?

8:49 clojure-newcomer: hoeck: yes

8:50 hoeck: and its a group-by over a stringy column?

8:50 clojure-newcomer: hoeck: over an int(10) column

8:51 hoeck: mysql or the java driver probably mess up type information then, which type has the column in the resultset?

8:51 clojure-newcomer: hoeck: String. <the bytes> is getting me there

8:52 hoeck: I get (\1 \, \2 \, \4 \, \6 \, \7 \, \1 \9 \, \2 \4 \, \3 \2 \, \5 \4 \, \1 \5 \2), which is almost there

8:52 hoeck: I'd rather not mess with manually building integers from byte seqs, who knows what the driver will return in the next minor release :/

8:53 clojure-newcomer: huh? are you calling seq on the created string?

8:53 clojure-newcomer: hoeck: yeah, forgot to remove that, had just fixed it while chatting in here

8:53 hoeck: do you need the string or the list of ints?

8:54 clojure-newcomer: hoeck: your earlier fixed things for me, String. <the-bytes>, thanks for your help

8:55 hoeck: clojure-newcomer: your're welcome

8:55 clojure-newcomer: hoeck: java interop is still like magic with me :-)

8:59 clgv: clojure-newcomer: it's just java with different syntax ;)

8:59 clojure-newcomer: clgv: I am getting there very slowly :-)

8:59 clgv: it's my first Lisp too, and I'm new to Emacs, so its a big deal all at once

9:00 bordatoue: vijaykiran: yes,

9:00 clgv: clojure-newcomer: oh, then you are one step ahead of me. I am foreign to emacs ;)

9:00 bordatoue: vijaykiran: I tried everyting i can

9:01 clgv: you are not alone, I am new to clojure and emacs

9:01 clgv: bordatoue: oh well, I program clojure for 2 years now ;)

9:02 bordatoue: clgv: well done

9:06 clgv: $findfn [nil nil nil 70 79] [111 83 78 nil nil 59] [111 83 78 70 79 59]

9:06 lazybot: []

9:06 clgv: :(

9:07 $findfn [111 83 78 nil nil 59] [nil nil nil 70 79] [111 83 78 70 79 59]

9:07 $findfn [111 83 78 nil nil 59] [nil nil nil 70 79] [111 83 78 70 79 59]

9:07 lazybot: []

9:07 clgv: (map or [111 83 78 nil nil 59] [nil nil nil 70 79]) doesnt work since `or` is a macro^^

9:08 ivan: map is also tricky because it'll run out on the shortest sequence

9:08 Bronsa: ,(mapv #(or % %2) [1 2 nil 4] [nil nil 3 nil])

9:08 clojurebot: [1 2 3 4]

9:08 ivan: ,(mapv #(or % %2) [1 2 nil 4 5] [nil nil 3 nil])

9:08 clojurebot: [1 2 3 4]

9:09 clgv: yeah as function it works ;)

9:09 it's a pity there is no function or ^^

9:09 definline would do, I guess

9:09 ivan:oh right^^

9:11 ivan: but I have a version for that one ^^

9:24 dnolen: PersistentVector construction now 10x faster in CLJS master.

9:25 KIMAvcrp: I have to start exploring clojure-script

9:32 clgv: dnolen: how did that happen?

9:33 dnolen: clgv: just better construction, in particular JS engines that are not V8 seems to poorly with many object instantiations - this happens when we convert a PV to a transient.

9:34 clgv: if the vector being constructed is less than 32 we can just set the tail and cnt, no need to bother transients.

9:34 "seem to perform poorly"

9:34 clgv: dnolen: ah ok. interesting.

9:36 dnolen: clgv: makes PV construction under V8 competitive with the times under the JVM

9:36 clgv: I suspected PV construction time was a problem after some perf issues lynaghk mentioned.

9:36 clgv: dnolen: wow, thats awesome

9:37 dnolen: mmarczyk: ping

9:37 mmarczyk: dnolen: pong

9:37 dnolen: mmarczyk: PV construction got 10X faster :)

9:39 mmarczyk: dnolen: I've noticed the commit, yeah -- I guess most vector literals are <= 32 elements, so that should be very cool :-)

9:40 dnolen: mmarczyk: should address the slowness of the various fns that return small vectors - which is a lot of code out there :)

9:40 mmarczyk: dnolen: exactly :-)

9:40 dnolen: mmarczyk: including lynaghk issues with the regex fns

9:40 mmarczyk: dnolen: did you notice CLJS-290 ?

9:40 dnolen: right

9:41 dnolen: mmarczyk: looking

9:44 mmarczyk: you'll need to redo the patch, was too close to my PV optimizations

9:44 mmarczyk: dnolen: ah, sure; just a sec

9:47 dnolen: done

9:47 dnolen: ah, wait

9:52 dnolen: ok, working patch attached

9:54 dnolen: mmarczyk: started working on source-map support

9:56 mmarczyk: dnolen: marvellous! with source maps, cljs just might have a better debugging/profiling story than Clojure :-)

9:57 dnolen: mmarczyk: yeah, profiling is already ok, browsers make it easy.

9:57 mmarczyk: source-map support require some kind of merging which will be interesting.

9:57 requires

9:59 mmarczyk: dnolen: merging? you mean cljs-to-js with js-to-adv-comp-js ?

10:00 dnolen: mmarczyk: cljs-to-js with js-to-any-comp-mode-js

10:00 mmarczyk: hm, right

10:01 dnolen: mmarczyk: one big perf issue I'm very unhappy with is update perf of small maps - so slow.

10:03 mmarczyk: dnolen: well, PHM is faster for updates, so making the conversion thresholds smaller would help here

10:04 dnolen: mmarczyk: I don't think it will really solve the problem.

10:04 borkdude: how can I pull in some changes from a origin/master branch until a certain commit?

10:04 dnolen: mmarczyk: tiny maps are common {:x n :y n}

10:05 mmarczyk: even under V8 you can't update a map more than 100000 times in under 1s.

10:05 mmarczyk: dnolen: even a PHM, no hash collision? hm

10:05 dnolen: mmarczyk: actually you're probably right, should make a benchmark for this.

10:06 mmarczyk: dnolen: yeah, some plots would be nice

10:10 dnolen: do you mean small obj maps primarily or maps in general (possibly w/ complex keys)?

10:10 mystiiq: how can I generate partial sums of a list (example: [1, 3, 6, 2, 7, 4] -> [0, 1, 4, 10, 12, 19, 23] I know it's very basic but I haven't done any functional programming tbh

10:11 KIMAvcrp: mystiiq: take a look at the reduce function

10:11 mfex: ,(reductions + [1 3 6 2 7 4])

10:11 clojurebot: (1 4 10 12 19 ...)

10:11 dnolen: mmarczyk: small maps, simple keys

10:12 mfex: mystiiq, see reductions and reduce

10:13 KIMAvcrp: cool haven't heard of reductions before

10:13 mfex: ,(reductions + 0 [1 3 6 2 7 4])

10:13 clojurebot: (0 1 4 10 12 ...)

10:14 mystiiq: mfex: thanks :>

10:14 mfex: KIMAvcrp, I like your paip with clojure blogpost. I also went through paip and translating to clojure, I found it to be a very helpful way to go through the material

10:32 dnolen: mmarczyk: I'd also like to see PHMs get to PV level perf, currently they seem like 10X too slow for all operations.

10:38 mmarczyk: dnolen: heh, certainly a goal worth pursuing :-)

10:39 dnolen: I'll look into some possible optimizations, both for small maps and PHMs

10:47 dnolen: mmarczyk: haha! checkout these graphs for PV construction :) http://www.50ply.com/cljs-bench/#plot15

10:48 mmarczyk: dnolen: yeah, that's great :-)

10:50 dnolen: hm, I wonder what's the deal with (get {:foo 1 :bar 2} :foo) suddenly getting slower? (which I'd have never noticed w/o the graphs -- soooo cool)

10:52 dnolen: mmarczyk: well SM and JSC got slower V8 didn't change.

10:54 mmarczyk: oh, maybe I'm not looking at the right one - which graph?

10:54 mmarczyk: dnolen: apparently (:foo {...}) got slower across the board

10:54 dnolen: [coll {:foo 1, :bar 2}] (:foo coll) is most interesting

10:57 dnolen: mmarczyk: hmm not sure what's going on there all those commits are PV related.

10:57 mmarczyk: dnolen: right

10:58 dnolen: mmarczyk: so one thing that's really slow in CLJS is hashing strings

10:59 mmarczyk: dnolen: we inherit that from gclosure lib, I believe?

10:59 dnolen: mmarczyk: I believe the JVM caches string hash codes somehow? but clearly that's not the case for us.

11:00 mmarczyk: dnolen: ah, yeah, that's true unfortunately :-(

11:00 dnolen: mmarczyk: I have a simple optimization here that caches strings makes things 10X faster for hashing strings - but of course that proably won't scale in real programs.

11:02 mmarczyk: doubles PHM access performance

11:03 mmarczyk: dnolen: no native hashing function in JS? :-(

11:04 dnolen: mmarczyk: I wonder how hard a fast weakmap implementation would be?

11:08 mmarczyk: dnolen: there's no native support for weak refs, right?

11:08 dnolen: apparently Mozilla is playing around with native weakmaps though, https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/WeakMap

11:09 dnolen: also googled http://code.google.com/p/es-lab/source/browse/trunk/src/ses/WeakMap.js which claims to implement what's needed in JS, ~450 lines

11:23 bosie: i am trying to get leiningen to run but all i get is this: "- klass: 'java/lang/classnotfoundexception'"

11:23 i installed lein with homebrew (macosx here)

11:27 clojure was installed with homebrew as well

11:27 S11001001: no need to install clojure if you have lein

11:27 lein won't even use it

11:27 bosie: https://gist.github.com/2852929

11:28 S11001001: well, uninstalled clojure now

11:29 S11001001: hmm, try lein new bosie/clojure-stuff

11:30 I am not sure what running lein without a subcommand does :)

11:30 bosie: S11001001: i executed "lein new bosie/clojure-stuff"

11:30 S11001001: lein --version and lein help are also helpful

11:30 bosie: S11001001: i can't run lein --version

11:30 S11001001: the same Trace/BPT trap thingie appears

11:31 S11001001: how about a ~/.lein/? There should be a leiningen jar in that tree somewhere

11:31 bosie: S11001001: under self-isntalls there is leiningen-1.7.1-standalone.jar

11:32 S11001001: from which you can try java -cp path/to/leiningen.jar clojure.main -e '(pr "hello")'

11:32 bosie: worked

11:32 printed hello

11:32 ~ » java -cp ~/.lein/self-installs/leiningen-1.7.1-standalone.jar clojure.main -e '(pr "hello")' "hello"%

11:34 S11001001: hmm, does homebrew's lein script deviate from the standard one?

11:35 bosie: S11001001: beats me

11:35 S11001001: (I'm hinting towards installing the standard way, which I know to work on OS X)

11:35 bosie: S11001001: i went to homebrew cos the standard way didn't work

11:36 S11001001: if by standard you mean the script

11:36 S11001001: if the standard way didn't work your system config has bigger problems

11:37 bosie: S11001001: i put the script into my bin, made it 755, and executed "lein repl"

11:37 result: https://gist.github.com/2852988

11:37 S11001001: like this thing is suspicious -Xbootclasspath/a:"$CLOJURE_JAR"

11:38 definitely nonstandard

11:38 bosie: my os is actually a fresh install (< 7 days)

11:38 ivan: putting clojure.jar in Xbootclasspath reduces startup time

11:39 S11001001: someone trying to be clever and speed up startup at the cost of screwing anyone who wants to run a different clojure

11:39 bosie: S11001001: its in the script

11:39 S11001001: https://raw.github.com/technomancy/leiningen/stable/bin/lein

11:39 S11001001: weird, that's not in mainline

11:40 and, er, it only works if you have that clojure jar

11:40 bosie: hm

11:41 S11001001: so what is THE standard way then?

11:41 S11001001: you've got it, grab the script, stick it somewhere, lein self-install

11:41 bosie: S11001001: i can't. any "lein X" command goes to the same trap-excpetion

11:42 classnotfound shit

11:42 gah

11:42 dnolen: mmarczyk: https://github.com/clojure/clojurescript/compare/master...string-hash-cache

11:43 bosie: anyone else has a brilliant idea?

11:44 TimMc: bosie: What does `which lein` tell you?

11:45 bosie: TimMc: /Users/bosie/bin/lein

11:45 success

11:45 had to nuke both .m2 and .lein

11:45 TimMc: heh

11:45 bosie: now "lein version" installed something and "lein version" gives me

11:46 S11001001: cool

11:46 bosie: Leiningen 1.7.1 on Java 1.6.0_31 Java HotSpot(TM) 64-Bit Server VM

11:46 TimMc: Nuking .m2 always helps.

11:46 bosie: TimMc: seems to be the clojure installation or sth?

11:46 TimMc: Helps keep your system regular.

11:46 S11001001: wagon likes to leave empty/incomplete files lying around

11:46 bosie: what is wagon?

11:46 TimMc: bosie: .m2 the Maven local cache.

11:46 S11001001: bit of maven that downloads stuff

11:46 bosie: k

11:47 TimMc: Lein uses Maven behind the scenes to manage dependencies.

11:47 S11001001: it's an enterprise file copying framework

11:47 mmarczyk: dnolen: very cool!

11:47 TimMc: clojurebot: Maven is <reply>Help, I'm trapped in an XmlFactoryFactory!

11:47 clojurebot: Ok.

11:47 S11001001: there's a chart and everything https://maven.apache.org/wagon/

11:48 bosie: TimMc: speaking of ... "Couldn't find project.clj, which is needed for deps" haha ;)

11:48 mmarczyk: dnolen: is it faster than hash on short strings once mru is filled though?

11:49 dnolen: mmarczyk: mru is only used for populating the cache after it exceed 256 keys.

11:50 mmarczyk: dnolen: hm, it's being pushed onto and shifted once per add op

11:51 dnolen: mmarczyk: yes it always holds most recent new keys.

11:51 mmarczyk: open to better ideas! :)

11:52 mmarczyk: on V8 getting hash-code for strings is down to 4ms, JSC strangely lagging.

11:52 mmarczyk: dnolen: hey, I'm not claiming I have any :-)

11:53 dnolen: basically bashing stuff at random to see if an idea jumps at me

11:53 dnolen: how about hashing, say, 1000 different strings in sequence?

11:53 dnolen: I guess each of them twice to match map-related usage patterns

11:53 clojurebot: Pardon?

11:55 dnolen: mmarczyk: that's a good idea

11:55 mmarczyk: dnolen: also, which string length are you testing this with?

11:56 dnolen: mmarczyk: very short key :f0

11:56 mmarczyk: dnolen: oh, that's great :-)

11:56 dnolen: mmarczyk: 8-10X faster for V8 and SM, 2X faster for JSC

11:57 mmarczyk: you're hash-coll test idea is a good one checking that now.

11:58 mmarczyk: dnolen: hm, I guess the smallest dynamic use case is construct map with a string key in one place, pass it to another place, look at same key again fairly soon... in a more "static" case the map might be constructed very early, so maybe no help from early hashing (assoc time) once the code gets around to late caching (lookup time)

11:59 dnolen: obviously some loops hash the same string all the time, so these will benefit like crazy

11:59 dnolen: meaning, seems like a good idea :-)

12:00 dnolen: mmarczyk: yes, it trying simulate what we get from the JVM for free for most programs.

12:01 mmarczyk: nice Brendan Eich gave CLJS a shoutout at FluentConf

12:02 mmarczyk: dnolen: cool :-)

12:09 bosie: thanks S11001001 , TimMc

12:09 dnolen: mmarczyk: hmmm given that we hash caching for all collections, I'm not sure hashing perf matters much :) but I'm checking anyway.

12:19 mmarczyk: http://github.com/clojure/clojurescript/compare/master...string-hash-cache

12:20 mmarczyk: excellent point about hash-coll, neglible hit now, hash takes a second parameter which can be used to skip the cache check.

12:28 mmarczyk: dnolen: hm, it seems that caching logic would fit nicely in string's -hash

12:29 dnolen: clearly problematic if an extra arg is needed... hm

12:30 dnolen: also, I think hashing moderate-to-large numbers of strings in sequence is a reasonable usage pattern outside of hashing colls -- I don't mean in one place: in total

12:32 dnolen: so I'm wondering about the perf of something like (dorun (map #(dotimes [_ 4] (hash %)) [...lots of strings...])) (or maybe 8-16?) as an approximation of the usage pattern where lots of strings are hashed with relatively poor "locality"

12:32 dnolen: yes CLJ JVM baselines! http://www.50ply.com/cljs-bench/

12:33 mmarczyk: yeah, I'm sure this idea needs tweaking further thought / testing, thus in a branch for now.

12:38 JanxSpirit: can I ask a dumb newb question about clojure dev workflow?

12:38 RickInGA: JanxSpirit: Sure, and cool name

12:39 JanxSpirit: I keep reading about the tight integration with the REPL - and I've tasted a bit of that sweetness playing around with the ClojureOne project

12:39 dnolen: mmarczyk: http://dev.clojure.org/jira/browse/CLJS-291, one PHMs are slow.

12:39 JanxSpirit: RickInGA thanks :)

12:39 so I get that you can dynamically modify the running program with the REPL - that's indeed cool

12:40 but when I get something I want to save - something that works - do I still go back and edit source files to add the things I liked from the REPL?

12:40 or is there some slicker workflow I'm missing?

12:41 mmarczyk: dnolen: ah, interesting

12:41 dnolen: will look into it, and also test out another idea about find that I had

12:41 llasram: JanxSpirit: The part you're missing is that usually the things you evaluate in the REPL are bits of the actual source file(s) for the poject you're working on

12:42 mmarczyk: dnolen: incidentally, I've been playing with chunks & array-reduce

12:42 JanxSpirit: workflow I'm used to (in Scala) is - edit source, SBT auto compiles for me, deploys, rinse, repeat

12:42 mmarczyk: dnolen: didn't manage to squeeze out much of a perf win so far though.

12:42 llasram: JanxSpirit: In any of the full-on Clojure environments you edit a snippet of code, evaluate, and you're already-running environment is updated with the new code, without skipping a beat

12:42 s,you're,your,

12:43 JanxSpirit: llasram but essentially I'm "trying things out" in the REPL and if I want to keep them in the project, I go into Emacs and add them to my various source files, correct?

12:43 RickInGA: JanxSpirit: The way I do it, is I will write the new code in a source file in emacs, and then I use C-M-x to send a form to an inferrior lisp repl

12:43 llasram: JanxSpirit: Yes and no. I v v rarely type things into the REPL directly. Instead I just type them into a file and evaluate from there.

12:44 JanxSpirit: oh - OK - the evaluate from a file bit is something I'm missing I think

12:44 PeregrinePDX: Yeah, actual code you want to use goes into the file.

12:45 RickInGA: JanxSpirit: yeah can use either swank/slime or inferrior lisp in conjunction with the source file in emacs.

12:45 PeregrinePDX: I occasionally test a function or whatever from the repl.

12:46 JanxSpirit: cool - so the upside is that you can evaluate a single form in a source file and have that reflected in the running process

12:46 that's a step up from my Scala workflow - maybe 2

12:48 TimMc: I just write everything correctly the first time. Way faster.

12:49 I don't know what you people are on about. ;-)

12:49 RickInGA: TimMc: I can see why that would be a good workflow, I have never once been able to implement it though

12:49 TimMc: can you teach that? I bet that would be a popular class

12:51 TimMc: Haha! "The first step is, be a rock star."

12:51 "There is no second step."

12:51 RickInGA: :)

12:52 TimMc: JanxSpirit: In reality, I tend to write a bunch of stuff in Emacs -- including tests -- then run and debug until it works.

12:52 technomancy: the Feynman problem solving method

12:52 1. Write down the problem

12:52 2. Think very hard

12:52 3. Write down the answer

12:52 RickInGA: TimMc: I just saw this video yesterday, think it sums up your work flow http://www.youtube.com/watch?v=jFUYYNVZuek

12:53 TimMc: "This video is currently unavailable."

12:54 cshell: Is congomongo the best clojure library for MongoDB?

12:56 Bronsa: Feynman was a good man.

12:57 RickInGA: jcrossley3: Just read your interview on the Clojure/core blog. Cool stuff. you definitely will have to host an immutant coding session

12:59 jcrossley3: RickInGA: thanks, man. that would be fun!

13:04 fbru02: Hi all, stupid question probably does anyone know if Datomic supports idempotent writes/deletes?

13:13 cemerick: dnolen, mmarczyk, et al.: remarkable results you guys are getting out of cljs. Phenomenal work.

13:30 dnolen: mmarczyk: yeah chunks need careful inspection to determine what's slowing things down.

13:32 cemerick: thanks, lot more work to do. hopefully we be very close or surpassing JVM on all benchmarks by StrangeLoop

13:33 at least on V8 anyhow, with a good show on JSC and SM

13:33 mmarczyk: cemerick: thanks, lots of fun to be had in the process :-)

13:33 dnolen: agreed

13:35 dnolen: as for surpassing jvm, for now I'm not sure what the deal is with (list) -- the others must surely be due to :opts :adv compiling things away? (except transients which don't have to deal with (AtomicReference. (Thread/currentThread)))

13:37 dnolen: mmarczyk: I think there are very few benchmarks where we'll beat the JVM, but I wouldn't be surprised if we have a couple legitimate cases.

13:39 mmarczyk: dnolen: yeah, and the 2x - 4x target does seem realistic

13:39 dnolen: and V8 is getting better, so... :-)

13:40 ok, must dash off for now

14:38 devth: setup a simple logger according to https://github.com/malcolmsparks/clj-logging-config but I see no log output in my console when i "lein run". am I missing something?

14:44 ezyang: Do Clojure sorted maps have a range query mechanism?

14:46 turbofail: yes, though i can't remember the name of the function off the top of my head

14:48 gtrak: anyone have an example of extending a protocol to a record by delegating to a member field?

14:48 amalloy: &(doc subseq)

14:48 lazybot: ⇒ "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true"

14:50 antares_: ezyang: yes, for example: (subseq (sorted-map :a 1 :b 2 :c 3 :d 4) > :b < :d)

14:54 borkdude: ,(subseq (sorted-map :a 1 :b 2 :c 3 :d 4) > :b < :d)

14:54 clojurebot: ([:c 3])

14:55 borkdude: ,(into {} (subseq (sorted-map :a 1 :b 2 :c 3 :d 4) > :b < :d))

14:55 clojurebot: {:c 3}

14:56 borkdude: ,(< :a :b)

14:56 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.Number>

14:57 borkdude: ok, it selects based on the values

14:57 ezyang: Ah, I see, you have to use the Seq mechanism. OK.

14:57 borkdude: or not? no

14:59 amalloy: borkdude: it selects on keys, using ##(doc compare)

14:59 lazybot: ⇒ "([x y]); Comparator. Returns a negative number, zero, or a positive number when x is logically 'less than', 'equal to', or 'greater than' y. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable"

14:59 antares_: ezyang: technically subseq is part of the "sorted" abstraction. But not knowing that totally fine ;)

15:00 borkdude: amalloy ok

15:00 ezyang: Actually, that is kind of important, since I'm interacting with the Java classes not in Clojure.

15:03 antares_: ezyang: sorted maps implement Map and Iterable. Do you think you'll need something else from them?

15:04 ezyang: Iterators don't support iteration from specified element (e.g. range query)

15:06 antares_: ezyang: so you need to do subseq from Java?

15:07 ezyang: Yep.

15:08 Looks like ISeq doesn't have an iterator method, which makes sense, I suppose.

15:08 antares_: ezyang: subseq implementation is pretty small but relies on take-while

15:08 ezyang: right, I think I'll just reimplement that in Java.

15:08 antares_: ezyang: ISeqs may or may not be ordered

15:08 ezyang: ok

15:09 KIMAvcrp: finally managed to port Chapter 4 of PAIP to clojure, enjoy

15:09 http://kimavcrp.blogspot.de/2012/06/porting-paip-to-clojure-chapter-4-gps.html

15:10 amalloy: chouser: i just made an update to http://dev.clojure.org/jira/browse/CLJ-865 - you were screening it for me months ago, and i think i just addressed the main issue you had, thanks to a suggestion from andy fingerhut on the mailing list. i'd appreciate it if you could take a look and see if i'm headed the right direction

15:10 ezyang: Hmm, I wonder what the 'Seq' that is returned contains.

15:11 Is it nodes? If that's the case, this will be kind of annoying...

15:13 (since TreeMap nodes are not a public type...)

15:14 antares_: ezyang: Map.Entry?

15:16 TimMc: &(class (first (sorted-map :a :b)))

15:16 lazybot: ⇒ clojure.lang.PersistentTreeMap$BlackVal

15:17 TimMc: &(bases (class (first (sorted-map :a :b))))

15:17 lazybot: ⇒ (clojure.lang.PersistentTreeMap$Black)

15:17 tomoj: suppose (last (into [] (persistent! (doto tcoll (conj! x) end!)))) returns x

15:18 but (into [] (persistent! (doto (-> tcoll (conj! x)) end!))) and (into [] (persistent! (-> tcoll (conj! x) end!))) return []

15:18 are these persistent/transient semantics seriously broken?

15:18 TimMc: tomoj: I don't think you're supposed to use doto there.

15:18 &(doc conj!)

15:18 lazybot: ⇒ "([coll x]); Alpha - subject to change. Adds x to the transient collection, and return coll. The 'addition' may happen at different 'places' depending on the concrete type."

15:18 antares_: tomoj: conj does not add stuff to the end for all specific collection implementations

15:19 hiredman: tomoj: doto is bashing in place

15:19 S11001001: ah yes, that would be a problem

15:19 tomoj: I know

15:19 TimMc: &(isa? (class (first (sorted-map :a :b))) java.util.Map$Entry)

15:19 lazybot: ⇒ true

15:19 TimMc: ezyang: ^ You're in luck.

15:20 tomoj: conj adds on the end for these collections

15:20 ezyang: Huh, I guess they are MapEntry.

15:20 tomoj: and bashing in place is part of the example

15:20 S11001001: ,(doc end!)

15:20 clojurebot: Excuse me?

15:20 tomoj: end! is extra

15:20 S11001001: I agree clojurebot

15:20 ezyang: that's handy.

15:20 amalloy: tomoj: what example?

15:20 TimMc: ezyang: https://www.refheap.com/paste/2961

15:20 amalloy: bashing in place is absolutely not the intended/working use pattern for transients

15:21 tomoj: the example I gave of the three bits of code

15:21 amalloy: okay. then those are broken, yes

15:21 ezyang: It is too bad ISeq is not iterable though >:-)

15:23 amalloy: new clojure.lang.SeqIterator(someSeq)

15:23 tomoj: mainly because the supposedly persistent collections are not immutable?

15:25 S11001001: tomoj: assuming that end! uses transient funcs on its arg, the only example with reliable semantics you gave was the last one

15:26 ezyang: amalloy: Hmm. They should've added implements Iterable to ISeq then...

15:26 amalloy: no, yuck

15:27 TimMc: Why the heck not?

15:27 amalloy: because then everyone who implements ISeq would have to implement Iterable too

15:28 this way, you can just wrap it in a pre-built iterator

15:28 composition, not inheritance

15:28 TimMc: Hmm...

15:28 ezyang: aight

15:28 kmicu: amalloy: bottom-up FTW

15:28 TimMc: OK, that makes sense.

15:29 S11001001: tomoj: as for the mutability of immutable collections, such situations do exist, but it's highly unlikely you've found one

15:29 tomoj: I am implementing a new collection

15:29 ezyang: I mean, if it were an abstract class, you'd just put in a default implementation and that'd be it.

15:29 It's mostly a convenience thing ^_^

15:30 TimMc: ezyang: Exactly, that's what I was thinking.

15:30 ezyang: And you can even overload it so that something more efficient happens later.

15:30 This would be how you'd probably do it in Haskell.

15:30 tomoj: I have basically future seqs from cljque (a future seq is an element and a watchable promise for a future seq). except I want to uncomplect the INotify and ISupply interfaces inside the fseq impl. so you have say a "builder" (corresponding to a transient) exposing the ISupply into which you can conj! an element, returning a new builder for the next fcons

15:31 * S11001001 shivers

15:31 tomoj: then you have a future seq (corresponding to the persistent?) into which you could maybe conj a new element, but that would not add it statefully

15:32 i.e. it would create a new fcons cell, not resolve the fcons cell of the fseq's builder

15:32 hiredman: tomoj: transients are essentially for optmizing birthing of new collections, sounds like what you want is an atom

15:34 tomoj: hmm

15:35 hiredman: https://blogs.oracle.com/jrose/entry/larval_objects_in_the_vm

15:39 llasram: This may be more of a Java question than a Clojure question, but:

15:39 I've got a deftype implementing Comparable, but sort time for it is ~2x sorting the equivalent String representations, even after re-writing the comparison itself as a Java static method, and AOTing the Clojure to verify that the .compareTo implementation isn't doing anythin crazy

15:41 tomoj: no clue if this is relevant, but did you also turn on reflection warnings?

15:41 llasram: tomoj: Oh yeah. No reflection. The AOTing was so I could verify the bytecode :-)

15:41 The compareTo implementation ultimately walks two byte-arrays, comparing byte-by-byte

15:42 Is that just ultimately going to be slower in Java than the java.lang.String's compareTo, or is there anyhing else I might be missing?

15:42 I guess I need to compare a pure Java version, for completeness

15:43 amalloy: llasram: have you looked at the implementation of String/compareTo?

15:44 llasram: I found *an* implementation in Java, but I don't know my JVM well enough to know if this is ultimately what's being used

15:45 http://hg.openjdk.java.net/jdk7/build-gate/jdk/file/tip/src/share/classes/java/lang/String.java

15:45 amalloy: llasram: https://gist.github.com/a3af4bd957fc1545483d is the jdk6 impl

15:45 borkdude: ,(javadoc String)

15:45 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: javadoc in this context, compiling:(NO_SOURCE_PATH:0)>

15:45 borkdude: hehe

15:46 amalloy: $javadoc String

15:46 lazybot: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

15:46 llasram: Well, looks the same. Is that actually what gets used? No funky speed-ups from swapping in native code for core classes?

15:47 amalloy: yes

15:47 llasram: (well, I guess I could try to determine that for myself as well)

15:47 Ok

15:47 Hmm

15:47 amalloy: or at least, i know of no mechanism that would make this not get used

15:48 llasram: Ok. Well, thanks for the information. That gives me hope that if I keep poking at it, I can find the issue

16:08 ethanis: is it possible to write a regular expression that spans multiple lines in clojure?

16:08 (the expression itself, this is not a question about matching multiple lines)

16:09 is the most idiomatic way to do this by using the (re-pattern) function explicitly?

16:10 borkdude: I guess strings can span multiple line in clojure

16:10 so..?

16:10 matthavener: anyone have any opinions/papers/blogposts/presentations they could recommend on the balance between hammock-time/planning and overplanning/ http://en.wikipedia.org/wiki/Analysis_paralysis

16:10 ezyang: "Think until you understand, code until you don't."

16:11 bbloom: ezyang: nice. who said that?

16:11 matthavener: ezyang: damn thats good :)

16:11 technomancy: matthavener: one thing that's helped a lot for me with Leiningen is being willing to wait for the right solution to come

16:11 bbloom: ethanis: are you asking about regexp options? like ignore case & multiline and stuff?

16:11 technomancy: sometimes you need something right now that works, but if you don't you'll be much happier in the end

16:11 ethanis: no, I'm talking about writing a regexp literal itself over multiple lines

16:11 #"bla

16:12 new line

16:12 ..."

16:12 ezyang: bbloom: Me. :P

16:12 matthavener: technomancy: i like that too :) but sometimes 'schedules' interfere :P

16:12 bbloom: :-)

16:12 ethanis: that seems to work fine

16:12 borkdude: ibdknox wow you passed 300k :)

16:13 ethanis: (re-matches #"a

16:13 b" "ab")

16:13 bbloom: ethanis: yeah, you need the multiline option :-)

16:13 1 sec while i find those docs

16:13 duck1123: ethanis: create your pattern as a string then pass to re-pattern

16:13 ethanis: ah, ok, thanks bbloom

16:13 yep, i can definitely make it as a string

16:13 borkdude: ethanis it will match a followed by a newline I guess this way and then b

16:14 bbloom: ethanis: use (?m) like this

16:14 technomancy: does anyone know of any maven repos with self-signed SSL certs?

16:14 duck1123: ,(let [pattern "foo\nbar"] (re-pattern pattern))

16:14 clojurebot: #"foo

16:14 bar"

16:14 bbloom: #"(?m) ....

16:15 borkdude: ethanis https://gist.github.com/2854854

16:15 ethanis: very cool, thanks for the tips everyone

16:15 bbloom: hmm… that's just multiline mode

16:15 not "verbose" mode where you can have whitespace and comments

16:16 (?x) maybe

16:16 user=> (re-matches #"(?x)a

16:16 b" "ab")

16:16 "ab"

16:16 yup that works

16:17 ethanis: ,(re-matches #"(?x)a

16:17 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading regex>

16:17 ethanis: b" "ab")

16:17 bbloom: clojure bot doesn't support multi line, use this:

16:17 ethanis: no worries, definitely works in the ole' repl

16:17 bbloom: ,(re-matches #"(?x)a\nb" "ab")

16:17 clojurebot: nil

16:17 bbloom: hmm

16:17 ,(re-matches irc://irc.freenode.net:6667/#"(?x)a\\nb" "ab")

16:17 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: irc://irc.freenode.net:6667, compiling:(NO_SOURCE_PATH:0)>

16:17 bbloom: guess not on the \n heh

16:18 documented here: http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#COMMENTS

16:18 borkdude: bbloom you should put #" in front of that

16:19 bbloom: borkdude: ?

16:19 borkdude: nm

16:19 bbloom: ,(re-matches #"a\\nb" "ab")

16:19 clojurebot: nil

16:20 bbloom: *shrug*

16:20 borkdude: bbloom in clojure you don't have to escape \n I think

16:20 bbloom: yeah, but didn't seem to work w/ clojurebot

16:20 thought maybe clojurebot was doing funky line handling

16:20 &(re-matches irc://irc.freenode.net:6667/#"a\\nb" "ab")

16:20 lazybot: java.lang.RuntimeException: No such namespace: irc://irc.freenode.net:6667

16:21 bbloom: why is my dopey irc client copy pasting poorly

16:21 …. grrr

16:21 &(re-matches #"a\\nb" "ab")

16:21 lazybot: ⇒ nil

16:21 borkdude: ,(re-matches #"a\nb" "a\nb")

16:21 clojurebot: "a\nb"

16:21 bbloom: &(re-matches #"(?x)a\nb" "ab")

16:21 lazybot: ⇒ nil

16:21 borkdude: bbloom there is a \n in your pattern, so it has to match that

16:22 bbloom: borkdude: the point is to get the ?x mode working :-P

16:22 it works in my repl w a real newline instead of \n

16:22 no biggie, glad it worked for the guy asking about it :-)

16:23 borkdude: ,(re-matches #"(?x)a\nb" "ab")

16:23 clojurebot: nil

16:23 borkdude: that should return "ab"?

16:24 bbloom: yes

16:24 try it with a newline instead of \n in your repl

16:24 ,(re-matches #"(?x)a\rb" "ab")

16:24 clojurebot: nil

16:24 bbloom: ,(re-matches #"(?x)a\\rb" "ab")

16:24 clojurebot: nil

16:24 borkdude: bbloom with spaces in between it works

16:25 bbloom: makes sense

16:25 solussd: in korma can I rename the key populated by a (with …) clause? e.g. (select user (with address :as addresses)) ?

16:25 bbloom: ,(re-matches #"(?x)a b" "ab")

16:25 clojurebot: "ab"

16:25 bbloom: the ?x mode also supports # comments

16:26 borkdude: ,(re-matches #"(?x)a b #well, this is a very cool pattern, don't you think?" "ab")

16:26 clojurebot: "ab"

16:26 borkdude: ,(re-matches #"(?x)a b #well, this is a very cool pattern, don't you think?" "ababab")

16:26 clojurebot: nil

16:32 coventry`: Is there a framework for clojure which somehow tracks the functions with side effects for you? Kind of like the IO monad, but without the bondage and discipline?

16:34 borkdude: coventry` I don't think s

16:38 coventry`: Am I right that to do that it would be enough to lexically track which functions call which, and having a configurable whitelist of pure functions, propagating all impure calls back along the call graph?

16:38 *and have*

16:38 abp: Do Leiningen 1.7.1, lein-newnew 0.2.6. and cljs-template 0.1.5 work together? When i create a new project using lein new cljs-template cljsperiments the template isn't applied (seems like the template files aren't copied).

16:38 technomancy: coventry`: you basically would need a type inference engine for that

16:39 coventry`: even then it would break in the presence of runtime resolve/eval, but it would certainly be nice

16:39 borkdude: coventry` als you could automatically add functions ending with ! to the blacklist

16:42 coventry`: Hmm, maybe it would be easier to depend on a callgraph pulled out of profiling data. Thanks technomancy, borkdude.

16:43 bbloom: coventry`: yeah, an "online" analysis process would be more reliable and easier to create.

16:43 amalloy: coventry`: lexical analysis wouldn't be sufficient anyway because of higher-order functions

16:45 coventry`: Hmm, good point.

16:46 amalloy: (map do-side-effects coll) - you can't tell just by looking at the source of map that it might have side effects

16:48 borkdude: why doesn't dissoc work on vectors

16:48 since ##(associative? [])

16:48 lazybot: ⇒ true

16:51 S11001001: borkdude: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Associative.java

16:52 amalloy: neat. that file hasnt' been touched for three years, and the last commit to touch it involved IMutableAssociative

16:52 borkdude: so basically only get, assoc and contains are guaranteed to work I guess

16:54 well you can also partially implement an interface so no guarantees whatsoever ;)

16:55 TimMc: Yeah, it's annoying. You have to do crap like ##(let [v (vec (range 20))] (into (subvec v 0 10) (subvec v 14 19)))

16:55 lazybot: ⇒ [0 1 2 3 4 5 6 7 8 9 14 15 16 17 18]

16:56 TimMc: s/19/20/, whatever

16:56 &(let [v (vec (range 20))] (class (into (subvec v 0 10) (subvec v 14 20))))

16:56 lazybot: ⇒ clojure.lang.APersistentVector$SubVector

16:57 TimMc: Interesting that it stays a subvector.

16:59 gtrak: (dissoc [1 2 3] 0)

16:59 ,(dissoc [1 2 3] 0)

16:59 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.IPersistentMap>

17:00 borkdude: dissoc only works for… maps and sets?

17:00 ,(doc dissoc)

17:00 clojurebot: "([map] [map key] [map key & ks]); dissoc[iate]. Returns a new map of the same (hashed/sorted) type, that does not contain a mapping for key(s)."

17:00 borkdude: ,(dissoc {:a 1})

17:00 clojurebot: {:a 1}

17:00 borkdude: ,(dissoc {:a 1} :a)

17:00 clojurebot: {}

17:01 borkdude: ,(dissoc #{:a :b} :a)

17:01 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to clojure.lang.IPersistentMap>

17:01 borkdude: nope, only for maps

17:01 ,(disj #{:a :b} :a)

17:01 clojurebot: #{:b}

17:01 borkdude: ,(disj {:a 1 :b 2} :a)

17:01 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to clojure.lang.IPersistentSet>

17:02 borkdude: right

17:02 why??

17:02 lazybot: borkdude: What are you, crazy? Of course not!

17:02 borkdude: lazybot a bit, yes

17:09 TimMc: Yeah, I don't get it either.

17:09 disj shouldn't exist, for that matter.

17:11 patrkris: this must be easy: how do I convert the result of an (and …) in to true or false, depending whether the result is logical true (i.e. nil or not nil)? i mean, what's the idiomatic way. sure I could do a (not (nil? (and …)))

17:12 borkdude: patrkris ##(boolean (and nil "true"))

17:12 lazybot: ⇒ false

17:13 patrkris: thanks!

17:13 borkdude: ,(boolean (or nil "true"))

17:13 clojurebot: true

17:13 michaelr`: returns a lazy seq which when realized returns paged records from database: https://www.refheap.com/paste/2967 <----- can this be written in a better way?

17:15 I used [nil] to signify end-of-seq

17:16 And then test for it using (take-while identity...

17:16 i feel that there must be some function which already does what i wrote there//

17:16 ..

17:16 TimMc: michaelr`: Not seeing the need for take-while identity...

17:17 Just return [] instead of [nil].

17:18 michaelr`: TimMc: you are right regarding take-while identity! thanks :)

17:18 but [] instead of [nil] won't work

17:19 TimMc: Worked for me.

17:19 michaelr`: really?

17:19 what clojure version?

17:19 amalloy: TimMc: i think you are probably crazy

17:20 TimMc: amalloy: I think michaelr` hasn't given me a good explanation of what's happening.

17:20 amalloy: it should return a lazy sequence with three fast elements, and then one infinitely-slow decision about whether or not there's another element

17:20 because you'll be calling (lazy-cat [1 2 3] (lazy-cat [] (lazy-cat [] ...)))

17:21 TimMc: Oh, now I see it.

17:21 Didn't realize it was recursive. >_<

17:22 So yes, I am probably crazy.

17:22 S11001001: (lazy-cat a ...) => (concat (lazy-seq a) ...)

17:22 hiredman: if you know you've reached the end, can't you just stop recursing?

17:23 (yes you can)

17:23 michaelr`: but then you would use something else than lazy-cat, right?

17:24 borkdude: lazy-cat is deprecated right?

17:24 hiredman: nope

17:24 TimMc: michaelr`: (I thought rows was some external thing, since I wasn't expecting recursion -- so I didn't run the full sample.)

17:24 borkdude: oh….. what was the thing that got deprecated in the context of lazy sequences then?

17:24 michaelr`: TimMc: okay, i don't blame you ;)

17:25 borkdude: maybe I remember it wrong

17:26 abp: Answering my own question: Installed Leiningen 2 and lein new cljs-template cljsperiments worked out of the box. Template autofetch is really nice. :)

17:28 TimMc: borkdude: lazy-cons, I think

17:29 borkdude: TimMc I thought that as well, but couldn't find the docs on it anymore

17:29 TimMc: http://clojure.org/lazy

17:30 michaelr`: TimMc: so i can't remove take-while identity

17:30 hiredman: you can

17:30 michaelr`: hiredman: how?!

17:30 how do i make it stop?

17:30 hiredman: think about it

17:30 TimMc: Ah, the Feynman approach. :-P

17:31 michaelr`: hehe

17:31 hiredman: and still keep lazy-cat?

17:31 hiredman: you could

17:31 I would switch to just plain concat

17:31 but that doesn't really change anything

17:32 michaelr`: okay, let me think about it :)

17:33 TimMc: Would that end up with nested concats? Thinking about stack overflows...

17:33 hiredman: michaelr`: why don't you write it as a recusive function with an accumulator (no laziness) and see where it goes from there

17:35 michaelr`: hiredman: you mean loop recur recursive function?

17:35 hiredman: sure

17:36 michaelr`: well, i don't want to accumulate. my use case it to "run over" a large table in the database, processing each row

17:36 without retaining the result

17:36 hiredman: I am not suggesting that as a final product

17:37 I am suggesting it as a learning exercise

17:37 borkdude: lazyness and resources are often a problem right

17:38 michaelr`: oh, i know how to write loop recur stuff, the learning excersize for me right now is to use lazy seqs :)

17:38 hiredman: good

17:38 so write it with loop/recur

17:38 michaelr`: why?

17:38 clojurebot: michaelr`: because you can't handle the truth!

17:38 michaelr`: clojurebot: no one can

17:38 hiredman: michaelr`: then don't

17:38 clojurebot: RejectedExecutionException is fixed in Leiningen, so give it an upgrade

17:39 michaelr`: hmm

17:48 tomoj: https://gist.github.com/9ac8496e40ed7cdbdd6e

17:53 michaelr`: clojurebot: no one can

17:53 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

17:54 michaelr`: clojurebot: RejectedExecutionException

17:54 clojurebot: RejectedExecutionException is fixed in Leiningen, so give it an upgrade

17:55 TimMc: michaelr`: It might be a misfire of the inference feature.

17:55 clojurebot: (+ 2 2)

17:55 clojurebot: 5 (for large values of 2)

17:55 hiredman: misfire?

17:56 TimMc: Not in the technical sense.

17:56 In the "what the hell, clojurebot!" sense.

18:04 michaelr`: hiredman: check this: https://www.refheap.com/paste/2968

18:05 hiredman: excellent, now wrap the body of rows in a lazy-seq, and change the if to a when in get-rows, and remove the call to seq

18:05 then you're done

18:06 michaelr`: ;)

18:09 hiredman: i still like lazy-cat better, just i don't like the ugly [nil] stop condition

18:10 every time i have to write a let for it feels like a bump in the flow of the language

18:10 s/let for/let form

18:11 hiredman: michaelr`: lazy-seq+concat is better in this case

18:11 bbloom: michaelr`: why?

18:11 hiredman: if you do it with lazy-cat you'll lose some level of laziness

18:12 michaelr`: hiredman: how so?

18:12 bbloom: why it feels like a bump?

18:13 hiredman: lazy-cat has to go inside the let, so the work done in the let will happen has soon as you call the row function, but if you use lazy-seq you can wrap the whole body, so the work in the let doesn't happen unless you actually start traversing the seq

18:14 solussd_: ibdknox: does readyforzero.com still use noir?

18:14 michaelr`: hiredman: i like the lazy-cat without the let, i want to get rid of the let form

18:14 ibdknox: solussd_: yes

18:14 hiredman: michaelr`: no you don't

18:14 solussd_: ibdknox: excellent. ammo for work. :D

18:15 michaelr`: hiredman: of course i do

18:17 hiredman: but i don't mind writing a version of lazy-cat which inside uses a let to do the real work :)

18:24 cshell: ,(= 1.1 1.09)

18:24 michaelr`: here both versions side by side, the first one reads much easier imho: https://www.refheap.com/paste/2970

18:24 clojurebot: false

18:24 cshell: Does anyone know how to check if a double is approximately equal?

18:25 ,(== 1.1 1.09)

18:25 clojurebot: false

18:25 S11001001: cshell: is 0.4444 approximately 0.4445?

18:25 moreover

18:25 doubles are inexact

18:26 so comparison of them is, by definition, approximate

18:26 cshell: S11001001: Correct, but when I'm doing a unit test, I want to say (= x 11.2) rather than (= x 11.192343221341)

18:26 S11001001: use an evenly represented num

18:27 11.5 has a clear exact representation

18:27 cshell: S11001001: Okay, maybe a better question is how to go from 11.499999 to 11.5?

18:27 S11001001: round

18:27 TimMc: cshell: Check that the delta is < an epsilon. :-)

18:27 S11001001: or subtract abs compare epsilon

18:28 remember not transitive though

18:28 cshell: What namespace is round in?

18:28 S11001001: compare with round is transitive, but has sharp edges

18:29 math.numeric-tower

18:30 cshell: S11001001: Thanks!

18:30 TimMc: Thanks as well!

18:31 TimMc: S11001001: What do you mean re: transitive?

18:31 S11001001: a = b = c implies a = c

18:31 TimMc: Ah, you mean that approx= is not transitive.

18:31 S11001001: with epsilon

18:35 (constantly true) is a perfectly transitive approx=, so is (constantly false) :)

18:41 brainproxy: wondering if i understand correctly ... if I define protocols P and Z and (some of) their methods have the same names, then I need to define them in distinct namespaces

18:42 S11001001: brainproxy: yes, think of them as functions before methods

18:43 hiredman: protocols don't have "methods", the are collections of functions, and yes, if you want to have two functions bound to the same name, you will need to put them in different namespaces

18:43 brainproxy: cool, thanks

19:01 technomancy: anyone on OS X with jdk7 able to help test a leiningen fix?

19:02 kilon: i am

19:02 but i think i got 1.7

19:02 i mean lein

19:03 technomancy: that's fine; mind if I /msg you?

19:03 kilon: sure

19:14 gtrak: i wonder how hard it would be to have like a background on-the-fly compilation in slime that doesn't stop on the first error? for instance, say I rename a method and I want a list of affected code locations.

19:14 Is it something I could whip up in a few hours?

19:15 technomancy: gtrak: slamhound does something sort of like that

19:15 I guess it's kind of the inverse

19:15 I've had dreams of making it go both directions though

19:16 gtrak: interesting

19:17 we don't really need a full compilation though for something like that, right? just identify affected namespaces by walking a tree, then reading in and checking vars, right?

19:18 I'm trying to think of ways to automate refactoring a little better, more like what I'm used to with java

19:18 technomancy: swank needs to expose restarts on compilation exceptions

19:19 "looks like you're missing this defn; want to add it?"

19:20 gtrak: right now, I'm just making a breaking change, then running 'lein compile' and fixing things one-by-one

19:20 S11001001: technomancy: what would you add?

19:23 technomancy: haven't thought it through

19:25 scottj: gtrak: not sure if it even works, but clojure-refactoring has a global-rename

19:26 gtrak: scottj: right, so, the problem is not that I want to rename... but I want to know what I should consider fixing when I make a breaking change to a function, basically I want to rename locally then fix all the callers up, then perhaps rename it back

19:27 scottj: gtrak: but not M-x slime-who-calls?

19:27 gtrak: doing a local rename achieves the breaking-at-compile-time instead of runtime, and would aid a systematic approach

19:27 hmm

19:28 does that work across files?

19:28 doesn't seem to

19:29 scottj: gtrak: when called on reduce it shows me several functions from various files

19:29 gtrak: plus, with slime there's the added complication of actually having to recompile all the ns's to pick up a change

19:30 I actually get an exception when I try it on reduce :-)

19:31 scottj: gtrak: http://jaderholm.com/tmp/2012-06-01-slime-who-calls.png

19:31 gtrak: interesting, not sure why mine's broken

19:57 cshell: Is there a better web security framework for Clojure than Spring Security?

19:58 I'm using noir as my web server

20:00 PeregrinePDX: cshell, friend by cemerick maybe?

20:00 technomancy: cshell: look at cemerick's friend

20:00 jinx

20:00 PeregrinePDX: Lol

20:01 xeqi: the noir mailing list has a couple of threads about how to use friend

20:01 PeregrinePDX: I almost went for the let me google that for you link since all I did was use google to answer the question.

20:01 zakwilson: ibdknox: congratulations on that kickstarter. That's... a lot of money.

20:01 xeqi: use as it get them to work together

20:03 badjer: is there a way to reload a namespace in clojure, even if the source file hasn't changed?

20:08 tmciver: badjer: use the :reload keyword with require.

20:10 badjer: tmciver: thanks - that's working for me. I thought :reload only worked when the .clj had changed - I must be loosing my mind

20:18 cshell: technomancy: Thanks, I hadn't heard of that but I like Chas' work

20:18 PeregrinePDX: Thanks as well!

20:19 PeregrinePDX: I must have searched on something else :)

20:30 PeregrinePDX: cshell, it's easy to do I admit.

20:45 technomancy: I think I've addressed the issues in the bad leiningen 2.0.0-preview5 release

20:46 will probably release current master as preview6 tonight or tomorrow; would be great if you could give it a try if you were having trouble earlier

21:00 bbloom: Hiccup does a neat thing with defhtml which lets you define multiple arity functions with the html wrapping logic, but it seems surprisingly complicated

21:00 i find myself wanting multiple arity functions somewhat regularly that come out of a def macro of sorts

21:00 i kinda want a defdefn macro-writing macro :-)

21:02 S11001001: bbloom: easier to go with fn alone

21:02 bbloom: S11001001: what do you mean?

21:03 S11001001: defn is the amalgamation of multiple concepts, whereas fn is just the one, so the latter makes a better basis for composably expressive macros

21:04 well, destructuring and recur-targeting is thrown into fn, but no worries

21:04 bloody recur.

21:04 bbloom: so let's say i have:

21:04 (defn f [x] {:x 1})

21:05 and i want a macro defoo which expands to (defn f [x] {:foo f :x 1})

21:05 as a sort of contrived example

21:06 it's pretty easy to define a macro that does that for a single arity function, you have a macro of the form (defmacro [name [& args] & body] …)

21:06 but for multiple arity, you need to do funky stuff like: (split-with #(not (or (list? %) (vector? %))) fdecl)

21:08 see: https://github.com/weavejester/hiccup/blob/master/src/hiccup/def.clj#L5

21:08 i find myself wanting to write a macro similar to defhtml about once per project :-P

21:09 aperiodic: i have that urge about half as often, but usually i realize it should just be a function

21:10 bbloom: aperiodic: should that defhtml macro be a function?

21:10 aperiodic: the urge to write macros in general, that is, they're usually not extending defn and such

21:11 but what's the end goal here?

21:12 bbloom: so i'm defining a domain specific data model that don't feel like getting into explaining… however i have several different types of nodes in this tree structure that have a few common keys

21:12 one of those keys always matches the constructor's name

21:12 so for example:

21:13 hm… need to have a good examplee before saying "for example"

21:13 aperiodic: why not just use what the macro you want to write expands to, and then mention the added key in the docstring if you're worried about discoverability?

21:13 S11001001: bbloom: you should consider the possibilities offered by partial, comp, and other combinators

21:14 macros are the hammer to the function screwdriver, as aperiodic says

21:14 ethanis: does anyone have experience using noir-cljs? ibdknox: quick question about advanced-compilation.

21:14 bbloom: S11001001: so yeah, usually the combinators get the job done. if you're just adding a key or something to the result it's pretty easy

21:16 S11001001: can just expand (defx foo x y z) to (def foo (comp #(…) (fn foo x y z)))

21:16 the problem comes in when you want the expansion to add a macro inside each of the fn bodies, like with defhtml

21:17 S11001001: that's just macro pollution

21:17 bbloom: S11001001: it's just going to be a single macro that's going to be used in 25 places or so...

21:18 do you think that defhtml is macro pollution?

21:19 S11001001: macros aren't so amenable to combinators, so defining something as a macro tends to pollute the stacks of its users, by preventing them from using combinators. I don't know what defhtml is, so wouldn't speculate on the possibilities

21:19 bbloom: similar in noir with defpartial https://github.com/ibdknox/noir/blob/master/src/noir/core.clj#L103

21:20 take a look at defhtml here: https://github.com/weavejester/hiccup/blob/master/src/hiccup/def.clj#L5

21:20 i understand the downsides of macros… i don't expect to need to combine these things at all

21:20 S11001001: programming is combination

21:21 bbloom: im defining a macro that defines top levels....

21:21 S11001001: no, I don't think html should be a macro either

21:23 bbloom: …. why?

21:23 it's the only macro in hiccup/core

21:23 it seems like a perfectly reasonable use case to me

21:24 aperiodic: yeah, i think that's a legitimate macro use-case, assuming you really need that reference back to the constructing fn in the map. that seems sort of fishy to me, but i don't know how you're planning on using it. regardless, why doesn't that split-with thing do the trick?

21:24 S11001001: no, it is definable as an ordinary defn with a metadata inliner

21:25 in fact the macro seems to be merely simulating a less powerful version of that

21:25 bbloom: S11001001: metadata inliner?

21:25 S11001001: see `zero?' and many other :inline places in clojure.core for examples

21:25 bbloom: aperiodic: it does in fact do the trick

21:27 S11001001: I'm looking at zero? now

21:27 … how exactly is that not just a macro? :-P

21:29 ethanis: does anyone here have experience with using external libraries in clojurescript and doing advanced compilation?

21:30 bbloom: ethanis: a *tiny* bit what's up?

21:30 ethanis: I've written a teensy wrapper around the javascript Facebook api in cljs

21:30 and I'm now trying to do advanced compilation

21:30 I understand I need an externs file

21:30 aperiodic: i appear to have a project that does that

21:31 ethanis: which explicitly specifies all of my javascript function/object calls

21:31 oh yeah?

21:31 aperiodic: i'm using my external library as my externs file

21:31 it's working out fine so far

21:31 bbloom: ethanis: 1) you're not trying to compile the fb lib, right? just call into it?

21:31 ethanis: right

21:32 I'm using the copy of the lib on fb's servers

21:32 bbloom: ok

21:32 how did you produce the externs file?

21:32 is it provided by facebook? or you made it by hand? or some other way?

21:32 ethanis: made it by hand

21:33 bbloom: can you pastebin it somewhere?

21:33 ethanis: https://gist.github.com/2856072

21:33 barebones, only refers to the functions/objects I use

21:33 bbloom: simple enough

21:33 cemerick: technomancy, PeregrinePDX: feel free to use "say hello to my little friend" when pointing people at the project :-P

21:34 hrm, maybe wrong crowd for that movie anyway ;-)

21:34 ethanis: ok, now facebook's library puts an object called FB in the global namespace

21:34 bbloom: ethanis: and can you also paste the code you're using for compilation?

21:35 ethanis: sure, sure

21:35 PeregrinePDX: Scarface?

21:35 ethanis: https://gist.github.com/2856072#file_main.cljs

21:35 it's a bit of a mess

21:36 (def FB (.-FB js/window))

21:36 bbloom: ethanis: no worries

21:36 ethanis: is there a more correct way to do that?

21:36 PeregrinePDX: cemerick, since you're at keys. I have the kindle version of the clojure book. Unfortunatly it doesn't show page numbers or paginate the same way as the paper book. Which makes it impossible to take advantage of the clojureatlas offer.

21:37 bbloom: ethanis: just checking that you're not sending any functions to fb by name, if you did that you'd need exports too

21:38 ethanis: oh, I am

21:38 example

21:38 (.login FB login-response (clj->js {:scope "user_about_me,user_relationships,email"})))

21:38 sending login-response by name

21:38 if that's what you mean

21:38 bbloom: ethanis: no, there you're sending the value inside login-response

21:38 ethanis: which will be a reference to a function

21:38 cemerick: PeregrinePDX: yeah, that was an unforeseen flaw in the game :-(

21:39 PeregrinePDX: Ok

21:39 bbloom: ethanis: if you had done something like with html where you did: <a href="javascript:foo();">

21:39 ethanis: ah yeah, understood. I don't do that anywhere.

21:39 bbloom: ethanis: in that case, you need to "export" the name, which tells google not to rewrite those symbols

21:39 ethanis: yep, got it.

21:39 cemerick: PeregrinePDX: check your PMs for a shibboleth.

21:39 oh, nm :-)

21:40 bbloom: ethanis: anyway — how do you invoke the compiler?

21:40 PeregrinePDX: Clojureatlas looks amazing for helping find things in the clojure libraries for us newbies.

21:40 ethanis: noir-cljs

21:40 bbloom: via cljs build? manually via code? cljsc or anything?

21:40 k i dunno anything about noir-cljs, but you need to pass through an :externs key somehow

21:41 if you ran gclosure's compiler directly, you need a —externs flag or a the java api equiv

21:41 ethanis: https://gist.github.com/2856072#file_server.clj

21:41 noir-cljs calls cljsbuild for me

21:41 right

21:42 (def cljs-options {:advanced {:externs ["externs/facebook.js"]}})

21:42 and my understanding is that this directory is relative to my class path?

21:42 bbloom: i *think* so

21:42 mos tof the code uses io/resource to load files

21:42 ethanis: yeah, this is where things get spotty for me

21:43 trying to grok https://github.com/ibdknox/noir-cljs/blob/master/src/noir/cljs/compiler.clj

21:43 bbloom: yeah, load-externs in cljs/clsoure.clj

21:43 aperiodic: ethanis: it is relative to the project root

21:43 ethanis: ah!

21:43 ok

21:43 aperiodic: it least, in my project.clj i use with lein-cljsbuild, it is

21:43 s/it/at/

21:44 bbloom: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/closure.clj#L146

21:44 cemerick: PeregrinePDX: I use it myself, which has surprised me. It's developed a reasonable following. At some point, I need to revisit the visualization.

22:05 muhoo: where would the options to clojure.java.io/writer be documented?

22:09 TimMc: muhoo: http://clojuredocs.org/clojure_core/clojure.java.io/iofactory

22:09 ...although that took a little source reading.

22:24 muhoo: thanks

23:47 Omer: ()

23:47 (+ 5 2)

23:47 clojurebot: *suffusion of yellow*

23:52 Omer: (= 1 1)

23:52 amalloy: &(= 1 1)

23:52 lazybot: ⇒ true

23:52 Omer: Oh, I see.

23:52 Mango_Man: (* 42 42)

23:52 clojurebot: *suffusion of yellow*

23:52 Mango_Man: what

23:52 ivan: (*

23:52 Mango_Man: &(* 42 42)

23:52 amalloy: you gotta ask 'em nicely

23:52 lazybot: ⇒ 1764

23:53 Omer: &(not (= 1 1))

23:53 lazybot: ⇒ false

23:53 Mango_Man: &(* 335235235 2352352352)

23:53 lazybot: ⇒ 788591393525522720

23:53 Mango_Man: hehe this is fun

Logging service provided by n01se.net