#clojure log - Aug 16 2011

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

0:24 amalloy: i guess we'll never know

0:30 grant_: it was a macro bug :)

1:32 is there a good way (in emacs/slime) to stop a thread thats spamming me with printlns in the background?

1:42 ShreeMulay: if anyone's awake and can help me with getting the following loop to work, I'd LOVE it!

1:42 (fn [n] (loop [n] (if (empty? (next n)) (n) (recur (next n)))))

1:43 trying to solve http://www.4clojure.com/problem/19#prob-title

1:46 kephale: the true clause

1:49 amalloy: grant_: go back in time and don't start that thread

1:50 ShreeMulay: you don't want (n), which would call n as a function

1:50 cemerick: ShreeMulay: Loop needs pairs of binding name/values in its vector. Why next? And (n) won't ever work.

1:51 grant_: amalloy: but that's O(make a time machine) :(

1:51 amalloy: cemerick seems to be a better reader than me

1:52 cemerick: I don't know what the hell I'm still doing up, but I'm glad I'm not ground beef yet.

2:14 amalloy: hm, i'm reading over the compiler, and it looks like the 1.3 primitive-function support only works for top-level vars? like, i couldn't pass around a function and then eventually treat it as something taking a primitive long, even if i have a primitive in scope. anyone who knows about 1.3 primitive stuff care to confirm that for me?

2:17 jeffrey04: erm, may I know what these warning means?

2:17 Warning: *default-encoding* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *default-encoding* or change the name. Warning: *buffer-size* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *buffer-size* or change the name. Warning: *byte-array-type* not declared dynamic and th

2:17 get those after using duck-streams in my script

2:19 amalloy: duck-streams is super-old and you're using it with the super-new clojure 1.3

2:20 jeffrey04: amalloy: oh, ok

2:23 amalloy: honestly if duck-streams were completely removed that might be better. a few people would be sad about having to upgrade, but a lot of new people would *realize* they shouldn't use it even though their book uses it

2:24 jeffrey04: so if i don't use duck-streams

2:24 erm... what should i use?

2:24 BufferedReader?

2:24 clojurebot: Reader syntax of collections has gotchas

2:24 amalloy: *chuckle* thanks, clojurebot

2:24 jeffrey04: lol

2:24 amalloy: jeffrey04: most of duck-streams is in clojure.java.io now

2:25 just like you shouldn't use str-utils2 or whatever nonsense, because it's in clojure.string now

2:25 jeffrey04: http://richhickey.github.com/clojure/clojure.java.io-api.html <- this

2:25 ?

2:26 amalloy: http://clojure.github.com/clojure/clojure.java.io-api.html

2:26 oh, and slurp/spit are in clojure.core

2:27 jeffrey04: erm is there a tutorial on how to read a file the proper way?

2:29 amalloy: i guess it depends what you mean by "read a file" and "the proper way"

2:30 jeffrey04: amalloy: is clueless right now lol

2:30 amalloy: (probably also the definition of "tutorial" will come into play)

2:30 jeffrey04: what do you want to do with the contents of the file you're reading?

2:30 jeffrey04: create a hadoop sequencefile

2:30 http://stackoverflow.com/questions/7062327/generating-a-sequencefile/7063762#7063762

2:30 amalloy: then you probably don't want to read a file at all, just ask hadoop to do it?

2:32 jeffrey04: i still need to pass the content to hadoop sequencefile writer no?

2:32 amalloy: or, frankly, this looks like a pretty complicated first task in clojure

2:33 jeffrey04: lol

2:34 if i can't figure out how to do it in clojure, would probably just write it in java (java is not my first language either, so would be equally just as tough)

2:36 amalloy: if you're writing a sequence file, can't you do that offline in whatever language you want?

2:37 jeffrey04: afaik sequencefile is usually created with some hadoop api

2:37 http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/io/SequenceFile.Writer.html

2:42 amalloy: well, i can point you at ##(doc line-seq) and ##(doc clojure.java.io/reader)

2:42 lazybot: (doc line-seq) ⇒ "([rdr]); Returns the lines of text from rdr as a lazy sequence of strings. rdr must implement java.io.BufferedReader."

2:42 (doc clojure.java.io/reader) ⇒ "([x & opts]); Attempts to coerce its argument into an open java.io.Reader. Default implementations always return a java.io.BufferedReader. Default implementations are provided for Reader, BufferedReader, InputStream, File, URI, URL, Socket, byte arrays, character a... http://gist.github.com/1148555

2:42 amalloy: since i guess you want to do something for each line of the input file

2:50 jeffrey04: amalloy: thanks

4:59 lnostdal: does lein have a "verbose mode"? .. seems it hangs waiting around for something at times (e.g. when doing `lein uberjar' just now)

5:47 pyr: doseq has no :when guards ?

5:47 it seems

5:50 ejackson: hmm... that's contrary to the docs :(

5:51 pyr: i may be using it wrong

5:52 ,(doseq [a [0 1 2]] :when even? (println a))

5:52 clojurebot: 0

5:52 1

5:52 2

5:53 pyr: same thing for #(even? a)

5:53 :let works though

5:54 mrBliss: ,(doseq [a [0 1 2], :when (even? a)] (println a))

5:54 clojurebot: 0

5:54 2

5:55 pyr: erf

5:55 it's too early i guess... :)

5:56 thorwil: how can i turn this naive recursive function into a loop-recurse? http://paste.pocoo.org/show/459250/

5:56 pyr: mrBliss: thx

6:00 clgv: thorwil: if you keep it lazy you won't need loop-recur

6:01 thorwil: otherwise you need some "work-queue"

6:02 thorwil: does the result have to resemble the hierarchic structure of the data? or is a flat collection as output ok?

6:08 thorwil: here is a recur version for a flat result list: http://paste.pocoo.org/show/459254/

6:08 thorwil: clgv: the queries are via appengine datastore, so nothing lazy about that, i assume

6:09 clgv: thorwil: You used map so your function itself is lazy

6:09 thorwil: clgv: in the end i want to render this in html with nested divs

6:10 clgv: thorwil: ok then you need a hierarchic output - that's more complicated. but you might not need to implement it yourself. you could use clojure.walk/prewalk similar to the replace functionality in there

6:13 thorwil: clgv: ok, i'll have a look at prewalk and/or using an accumulator. thanks!

6:14 clgv: thorwil: but I think your lazy implementation via map should be fine too

6:15 unless you force it all at once - that might blow the stack

6:16 thorwil: clgv: do i not have a problem with a growing stack, given my implementation?

6:16 bbiab

6:17 clgv: not in general - that depends how you use the lazyseq that is the result of your function

7:10 lnostdal: seems sort of random which exception/stack-trace ends up in the Slime debugger and which one ends up in the terminal .. i'm using Ring, so i'm guessing it is something thread related(?)

7:12 (the ring jetty adapter)

7:14 manutter: Hmm, I haven't looked at it extensively, but I have a rough impression that the terminal gets "logged" exceptions (i.e. caught and logged by middleware) and Slime gets the exceptions that Ring can't catch (e.g. compile errors)

7:15 lnostdal: ok, clojure being a dynamic language needs to present run-time errors; compile-time ain't enough :)

7:16 ..digging through jetty.clj now, ...hm

7:17 manutter: I'm not sure about Ring proper, but I know Compojure likes to use a wrap-stacktrace middleware that does exactly that

7:17 tho now that I think about it, I believe Ring is the source for that middleware

7:19 lnostdal: http://mmcgrana.github.com/ring/ring.middleware.stacktrace-api.html ..? but that isn't useful while developing (perhaps for testers); exceptions needs to go to Slime where people can click stack-frames and get to the source

7:20 manutter: I wonder if the exception would bubble-up to slime without the middleware? I suspect not, due to threads.

7:21 lnostdal: dunno .. i'm only using the jetty middleware at the moment

7:21 manutter: There was some really interesting code at the end of The Joy Of Clojure that involved writing your own debugger into your code -- you could set break points and evaluate functions and such with very little effort

7:22 I bet you could do something similar with embedded code that would "read" from an atom or something

7:22 then it would work across threads.

7:23 * manutter just got an idea for come cool functionality that could be added to, say, clooj

7:26 clgv: manutter: the break or also called debug-repl from JoC is great

7:35 manutter: Yeah, I was pretty impressed

7:35 I tried to write one in PHP, but oh well :P

8:08 wunki: anyone familiar with jetty, I currently use wrappers for an entire app. Is it possible to split the app so I can use a different set of wrappers on them, finally serving it up as one app?

8:10 raek: wunki: in Moustache this is pretty simple: (def master-handler (app ["a"] [wrapper-a sub-handler-a] ["b"] [wrapper-b1 wrapper-b2 sub-handler-b]))

8:10 wunki: raek: would this work for compojure and jetty?

8:11 raek: moustache is a lib that does routing and middleware composition. (it fills the same place as compojure)

8:11 I suspect compojure can do something similar

8:13 wunki: raek: could you explain what ``app ["a"]`` stands for?

8:13 is that a set of routes?

8:14 manutter: wunki: I havent tried it in Compojure, but there's no reason it wouldn't work

8:14 raek: yes, app is the route macro from Moustache

8:14 wunki: manutter: I'm really green on this, are you willing to create a gist example for me/

8:15 manutter: well, willing in theory, but I'm at work, so I can't really take the time to go into detail

8:15 wunki: manutter: ok, no problem, will do trial-by-error

8:15 manutter: why do you want to use different wrappers for different parts of your app?

8:16 wunki: manutter: because I have some views that need a authentication wrapper (creates a basic-auth request)

8:16 manutter: ah, that makes sense

8:16 wunki: raek: so, that would be defroutes in compojure?

8:16 raek: wunki: in theory, you could mix compojure and moustache (they both follow the Ring spec) but I think Compojure has its own way of doing what I showed in Moustache

8:16 manutter: You might want to look up the sandbar lib if you haven't already

8:17 sandbar lets you specify access on a route-by-route basis

8:17 raek: wunki: basicaly yes. Moustache and Compojure fill the same function, but you do things in different styles

8:17 wunki: ok, thanks for the help guys, I'm going to try some stuff out

8:18 raek: wunki: so where do you put the middleware in your defroutes form?

8:19 wunki: raek: https://gist.github.com/37acc39ae1856652f1cf

8:20 defroutes combines all the routes, then app adds all the middleware

8:20 finally, app get's served

8:21 I would like to have a "auth-app" or something, that add the authentication wrapper also

8:21 and serve those two together

8:21 raek: wunki: this might work: in the (defroutes routes ...) code, maybe you can wrap the individual items there with middleware

8:22 wunki: raek: how do I wrap something? :/

8:22 raek: (defroutes routes (-> episto.users.core/user-routes wrap-foo wrap-bar) (-> episto.auth.core/auth-routes wrap-baz wrap-quux))

8:22 wunki: like you do in (def app

8:22 a wrapper is just a function that takes a handler and returns a wrapped handler

8:24 manutter: Yes, that should work fine in Compojure

8:24 wunki: ok, I'm gonna do that. Don't want to repeat the wrappers for every route though. Will look how to DRY that up

8:24 manutter: If you look at the code for defroutes, it's basically just passing the request to each of the handlers in turn until one returns non-nil

8:25 raek: wunki: you can compose wrappers just like ordinary functions

8:25 wunki: raek: good idea, will do that

8:25 raek: (def wrap-json-and-error-handling (comp wrap-error-handling wrap-json-params))

8:26 manutter: I believe you could use defroutes more than once

8:27 (defroutes auth-routes foo bar baz), then wrap auth-routes, then (defroutes routes regular unleaded auth-routes)

8:28 or rather (defroutes routes regular unleaded wrapped-auth-routes)

8:28 I'm leaving a couple steps as "an exercise for the reader" but you get the idea

8:30 raek: but doesn't he already do that?

8:32 manutter: I can't tell -- he's passing auth-routes to the main defroutes macro, but I'm not sure he realized he can wrap auth-routes before passing it to the main defroutes

8:33 and I'm assuming he's using defroutes in episto.auth.core--if so, he's 90% of the way there

8:33 wunki: sorry guys, just got some people over. I'm logging this however :)

9:05 manutter: ,(doc println)

9:05 clojurebot: "([& more]); Same as print followed by (newline)"

9:06 manutter: yay, clojurebot is alive again

9:06 clojurebot: help

9:06 clojurebot: http://www.khanacademy.org/

9:06 manutter: lol, ok, that's actually MORE help than I necessarily wanted.

9:58 pyr: ,(let [a "s"] (case (class a) java.lang.String :found :not-found))

9:58 clojurebot: :not-found

9:58 pyr: ,(class "s")

9:58 clojurebot: java.lang.String

9:59 pyr: i'm not getting what I'm doing wrong

9:59 i know that the right idiom is multi-method in this case

10:00 manutter: ,(let [a "s"] (class a))

10:00 clojurebot: java.lang.String

10:01 manutter: ,(let [a "s"] (case (class a) 'java.lang.String :found :not-found))

10:01 clojurebot: :not-found

10:01 manutter: hrmmm

10:01 Bronsa: ,(let [a "s"] (case (class a) 'java.lang.String :found (class a)))

10:01 clojurebot: java.lang.String

10:01 manutter: ,(= (class "s") java.lang.String)

10:01 clojurebot: true

10:01 pyr: yep tried all of this

10:02 manutter: ,(doc case)

10:02 clojurebot: "([e & clauses]); Takes an expression, and a set of clauses. Each clause can take the form of either: test-constant result-expr (test-constant1 ... test-constantN) result-expr The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can foll...

10:04 manutter: ,(let [a "s"] (case (class a) (class "s") :found :not-found))

10:04 clojurebot: :not-found

10:04 manutter: lol

10:04 that's messed up

10:05 lobotomy: ,(let [a 1] (case (< a 2) :yes :no))

10:05 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching clause: true>

10:05 lobotomy: hmm, apparently i don't know how to use case ;p

10:06 tufflax: ,(let [a 1] (case (< a 2) true :yes :no))

10:06 clojurebot: :yes

10:06 raek: pyr: case uses compile-time constants (and does not evaluate them). so you get the java.lang.String _symbol_, not the class.

10:06 manutter: case is a simplification of cond -- it works faster because the first element of each pair has to be a literal

10:06 pyr: raek: that's what I figured by running macroexpand

10:07 raek: pyr: it is actually possible to use case on classes, but you have to write a macro that expands to a case form which has class object instead of symbols in the code

10:07 pyr: https://gist.github.com/997652

10:08 pyr: raek: thanks

10:08 raek: i was misled by this article: http://pragprog.com/magazines/2011-07/growing-a-dsl-with-clojure

10:09 raek: hrm. that code doesn't work, right?

10:09 pyr: nope

10:09 raek: "that code" = (case (class a) ...)

10:09 pyr: yep

10:10 TimMc: Anyone know of an Clojure graph layout libraries along the lines of Vijual?

10:11 manutter: lacij?

10:11 TimMc: Ooh, thanks!

10:11 manutter: Don't know anything about either one, but I think I saw something about graph layout in connection with lacij

10:12 daveray is also playing with something he calls Dorothy

10:12 clojure interface to graphviz

10:12 TimMc: (I'm getting fed up with client-side (JS) graph layout libraries.)

10:14 manutter: I hear ya :)

10:16 TimMc: I'm tempted to use a server-side lib to generate layouts and then animate any differences on the client side,

10:17 .

10:20 cemerick: raek, pyr: It'd be safer to use symbols all around than to ensure that the constants provided to case were classes. Doing so would avoid issues if you were to AOT-compile the code using class-based case clauses, thus locking in their hashcodes at compile-time. I neglected this aspect as well before: http://cemerick.com/2010/08/03/enhancing-clojures-case-to-evaluate-dispatch-values/#comment-8

10:21 manutter: ,(let [a "s"] (case (str (class a)) "java.lang.String" :found (str (class a))))

10:21 clojurebot: "class java.lang.String"

10:22 manutter: *snap*

10:24 wunki: what do you call a "->" in clojure?

10:24 cemerick: It's a threading macro.

10:25 wunki: cemerick: thanks, looking it up

10:26 ah, good piece: http://blog.fogus.me/2009/09/04/understanding-the-clojure-macro/

10:26 cemerick: also: http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/

10:27 wunki: I started reading the book "The Joy of Clojure" yesterday, awesome book

10:43 TimMc: manutter: Actually, the problem I'm having is finding a graph layout engine that provides relative stability over graph operations (don't completely rearrange everything when a single node is added) and can handle disconnected graphs with any gracefulness.

10:44 manutter: Yeah, sounds like a tricky set of requirements

10:45 TimMc: (Background: I'm trying to write a good display for what is effectively an RDF explorer.)

11:21 duck1123: TimMc: sounds interesting. github link?

11:22 TimMc: duck1123: Sorry, it's a project for work.

11:22 Although, any supporting code I write might make it onto GitHub.

11:24 This component of the project allows the user to see links between people and locations and such that have been derived from a bunch of documents. I'm currently using TheJIT's Force-Directed graph for it, but it kind of stinks with disconnected graphs.

11:25 Project leader is pretty friendly to open-sourcing components, though.

11:26 duck1123: That's cool. It's good to see companies give back

11:28 TimMc: Yeah, it can be a really nice symbiosis.

11:45 Pupeno: Where do you put the connection calls when using lobos?

11:51 manutter: Looks like you can def a map with the db connection specs, then pass the map to (with-connection db-spec &body)

11:52 check out the code at the bottom of the frontend docs on the Lobos site

11:56 cemerick: What's the state of Clojure sandboxes these days? Is clojail the only game out there (aside from the one embedded in clojurebot)?

11:58 TimMc: clojurebot doesn't use clojail?

11:59 I kind of assumed it did.

11:59 cemerick: clojurebot predates clojail

12:00 It'd be nice if there was one obvious sandboxing option.

12:00 * cemerick abhors choice ;-)

12:01 Pupeno: manutter: yes, I seen that, but there may be some commands that load some files automatically expecting them to define the connection. Apparently it's src/lobos/config.clj.

12:04 TimMc: cemerick: When it comes to security, I kind of like having diversity.

12:06 Although... that is predicated on having at least two *comprehensive* options.

12:07 cemerick: TimMc: Probably wise. But, when the different options aren't readily comparable (short of understanding their source top to bottom), it's tough.

12:08 dnolen: nice looks like the pattern matching / predicate dispatch talk at NYC Clojure tomorrow will definitely get recorded

12:08 TimMc: cemerick: Is your abhorrence based on choice paralysis or the problem where 100% of the libraries solve 80% of the problem?

12:08 technomancy: dnolen: woo

12:09 cemerick: TimMc: I was trolling a bit, but I think choice paralysis is a big source of friction generally.

12:09 Just about every X is an 80% solution in any case.

12:10 TimMc: Oh hey, there's a Clojure meetup on Thursday in Boston.

12:11 I have to make it to that.

12:11 technomancy: TimMc: absolutely

12:13 dnolen: the fact that the JVM can optimize call sites when you're pulling fns out of arrays is pretty astounding.

12:15 fast predicate dispatch might not be as hard as I thought...

12:17 symbole: dnolen: Will there be a recording of the talk on Wednesday?

12:17 dnolen: symbole: 90% chance it seems like.

12:22 TimMc: What would you call a HOF that is the opposite of partial, e.g. (fn a b c d e) -> (fn d e) ?

12:24 symbole: dnolen: I'll email the organizer then.

12:27 TimMc: (defn unpartial [f n] #(apply f (drop n %&)))

12:28 amac: I think unpartial [f & n], no?

12:29 and then drop the count of the number of args passed in

12:29 TimMc: Why?

12:29 clojurebot: why not?

12:30 TimMc: clojurebot: Glad to see you aren't flailing around helplessly today.

12:30 sjl: Hmm, if I (def foo (force (delay (some-fn huge-argument))) is that going to prevent huge-argument from being garbage collected?

12:30 clojurebot: what should I do today, it is the weekend and all

12:30 TimMc: amac: With my definition, ((unpartial + 2) 1 10 100 1000) => 1100

12:30 sjl: Or will it allow it to be GC'ed once it's forced and the argument isn't necessary any longer?

12:31 (assuming there aren't any other references to huge-arg anywhere else, of course)

12:31 amac: ok, I see where you're going

12:32 TimMc: I guess it is basically a member of a class of HOFs that do something to the arglist and reapply it.

12:32 amac: I thought you wanted to define more of an... anti?-prototype

12:34 TimMc: (defn modarg [f m] #(apply f (m %&)))

12:34 ((modarg + (partial drop 2)) 1 10 100 1000)

12:36 manutter: ,(letfn [(skip-args [f c &args] (apply f (drop c args)))] (skip-args + 2 1 10 100 1000))

12:36 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: args in this context, compiling:(NO_SOURCE_PATH:0)>

12:36 manutter: oops

12:36 ,(letfn [(skip-args [f c & args] (apply f (drop c args)))] (skip-args + 2 1 10 100 1000))

12:36 clojurebot: 1100

12:37 manutter: TimMc: ^^^

12:37 nollidj: is there a good reference for all the internal clojure interfaces that define behaviors, like IObj, ILookup, and IPersistentMap?

12:38 i have gotten away with copy-pasting from others' code i find when googling, but it would be nice if there were a single javadoc-style go-to reference explaining things

12:39 okay, let me modify that: i can look at the javadoc, but it's really not that informative.

12:39 symbole: nollidj: They're mostly under one package, so looking at the source will give a list.

12:39 nollidj: anything better that actually explains things?

12:41 symbole: They're scattered through out. I know the book Joy Of Clojure mentions internal structures fairly often to give you a good understanding of things under the hood.

12:42 nollidj: hm, ok. thanks.

12:42 clgv: nollidj: yeah you should make some noice that clojure.core starts documenting their implementation jvm and clj more! :)

12:42 *noise

12:42 nollidj: there's little documentation to explain, for example, what meta and withMeta do and why i should implement them in something

12:43 hm. i guess it's worth opening an issue

12:43 clgv: nollidj: you want to know that? that's easy, it's the emtadata support

12:43 the one assigns meta the other reads it

12:44 nollidj: i figured that, but it wasn't clear that's what it meant. also, an experienced programmer learning clojure might need to learn about metadata support just to create a custom datatype

12:45 i'm not saying that's bad, i'm just saying there's a bit of a gotcha there

12:45 clgv: nollidj: I totally agree with you that they should document more

12:45 nollidj: sure, thanks for the feedback

12:45 clgv: some of the clojure.core implementation would be a lot easier to understand with some comments in it

12:49 nollidj: oh, there's an attempt at developing a literate programming-style book documenting things. that's fantastic

12:49 clgv: link?

12:49 clojurebot: your link is dead

12:50 Scriptor: docco?

12:51 nollidj: found this: http://groups.google.com/group/clojure/browse_thread/thread/460417fe45f314c3?pli=1

12:51 the pdf and source are linked there

12:51 clgv: thx

12:59 TimMc: manutter: Yeah, but mine is a HOF. So neener neener.

13:02 manutter: ,(letfn [(skip-args [f c] (fn [& args](apply f (drop c args))))] ((skip-args + 2) 1 10 100 1000))

13:02 clojurebot: 1100

13:02 manutter: :)

13:04 TimMc: ,(letfn [(marg [f m] #(apply f (m %&)))] ((marg - reverse) 1 10))

13:04 clojurebot: 9

13:05 TimMc: I guess the arguments should really go the other way.

13:06 ,(letfn [(marg [m f] #(apply f (m %&)))] ((marg reverse -) 1 10))

13:06 clojurebot: 9

13:07 manutter: Surgeon General's Warning: HOF's may be hazardous to your free time, and may cause spontaneous giggling in PHP programmers who aren't used to them.

13:47 amac: ,(defn predmap [p m & c] (apply map #(if (p %) (m %) %) c))

13:47 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

13:51 amac: ,((fn [p m & c] (apply map #(if (p %) (m %) %) c)) even? inc (range 1 11))

13:51 clojurebot: (1 3 3 5 5 ...)

13:53 TimMc: amac: You might call it ifmap

13:53 Or... hmm, maybe not.

13:54 amac: I run into this usecase surprisingly often

13:54 TimMc: You could also turn it inside out.

13:54 amac: ?

13:55 TimMc: let me work something up

13:57 amac: :)

13:58 TimMc: ,(letfn [(xif [p f] #(if (p %) (f %) %))] (map (xif even? inc) (range 1 11)))

13:58 clojurebot: (1 3 3 5 5 ...)

13:58 amalloy: amac: something like this is in useful

13:58 TimMc: xif = "transform-if"

13:59 amalloy: TimMc: hah, that's what i called the one in amalloy-utils. ninjudd convinced me to rename it (and rework it) to "fix" when i ported to useful: https://github.com/flatland/useful/blob/develop/src/useful/fn.clj#L16

13:59 TimMc: nice!

13:59 amac: TimMc: neat, much clearer

13:59 TimMc: That's a good name.

14:00 amalloy: well, actually to-fix returns the function like xif; fix applies it immediately. same thing

14:00 TimMc: amac: Of course, if you are really going to be mapping almost all of the time, predmap would actually be more useful.

14:00 amalloy: (map (to-fix even? inc, string? read-string) [3 2 "1"]) ;=> (3 3 1)

14:00 TimMc: amalloy: And I suppose yours takes &args.

14:01 Ah, yours does something like case.

14:01 amalloy: more like condp

14:01 TimMc: right

14:02 amalloy: ninjudd also built in a macro version with syntax more like update-in for better threading, but i haven't found any uses for it

14:08 TimMc: amalloy: I could also see reworking it to take multiple args for the predicate and transformation functions.

14:09 The tricky bit would be the else case.

14:09 amalloy: TimMc: i think mod-args is a function of the same order as skip-args, right? so you don't get to claim HOF superiority over manutter

14:09 (finally caught up on the backlog)

14:10 manutter: I did 2 versions of skip-args tho

14:10 TimMc: Is it? Mine returns a function.

14:10 manutter: 2nd one returned a function instead of just processing its args

14:10 TimMc: I'm actually not clear on the technical definition of HOF.

14:10 * TimMc goes reads

14:10 amalloy: skip-args takes a first-order function and returns a value; mod-args takes two first-order functions and returns a first-order function

14:11 TimMc: http://www.eecs.usma.edu/webs/people/okasaki/jfp98.ps

14:11 TimMc: thanks

14:14 "map is second-order" means that as far as map is concerned, the input function doesn't need to be higher order, right?

14:14 Because in (map f ls) map can't actually *know* that f isn't something fancy.

14:15 amalloy: i can't see a way for the alternative to be meaningful: every function would be nth-order

14:15 TimMc: except inc

14:15 amalloy: every function (with any function argument at all)

14:16 Pupeno: I'm running a function and all the errors I'm getting is this: java.util.IllegalFormatConversionException: d != java.lang.String (NO_SOURCE_FILE:0), any ideas how to get more details?

14:16 TimMc: There's probably a formalization of that statement using the phrase "point-free equivalent".

14:16 amalloy: &(format "%d" "test")

14:16 lazybot: java.util.IllegalFormatConversionException: d != java.lang.String

14:16 amalloy: Pupeno: ^

14:17 TimMc: That's a confusing error message.

14:17 Pupeno: amalloy: ok… I'll grep all the sources for %d.

14:18 amalloy: TimMc: yeah, it is. tbh i've never seen it before, but what else could have caused it?

14:22 manutter: Pupeno: you probably should search for other numeric formatting chars too: %f, %x (I think--been a while since I've used old-style C formatting)

14:23 Pupeno: manutter: the library that most likely is causing this is only using %s.

14:23 amalloy: TimMc: btw thanks for making me talk about fix/given/etc. i've just found a nice use for the macro version i said i never used

14:23 Pupeno: A stack trace would be kinda useful.

14:24 amalloy: &(format "%x" "test") ;; i think this throws a different error message

14:24 lazybot: java.util.IllegalFormatConversionException: x != java.lang.String

14:24 manutter: ,(format "%s" 20)

14:24 clojurebot: "20"

14:24 manutter: ,(format "%s" :some)

14:24 clojurebot: ":some"

14:24 amalloy: manutter: %s calls .toString on its argument, so it's never inapplicable

14:24 manutter: I was about to draw the same conclusion myself :)

14:25 Pupeno: So, it's definitely a %d.

14:25 amalloy: Pupeno: so it says no source file, and gives you no stacktrace at all?

14:25 Pupeno: amalloy: correct.

14:27 I found the REPL sometimes fails to give proper stack traces.

14:28 Ok, now I got a file and line number, but it's not helpful: https://gist.github.com/1149795

14:29 bbl

14:29 amalloy: Pupeno: one of the libraries you're require'ing has an error at macroexpansion time, i think

14:30 Pupeno: amalloy: I see.

14:30 amalloy: so if you try requiring them one at a time, you can narrow down which it is

14:30 not that this is an ideal solution, but lacking a stacktrace...

14:31 TimMc: Doesn't *e give you the error object?

14:31 I thought I remember something about that.

14:31 amalloy: also a good point

14:32 TimMc: (.printStackTrace *e)

14:32 manutter: Pupeno: looks like you're both (use)'ing and (require)ing lobos.core, maybe that's an issue?

14:32 amalloy: shouldn't be

14:33 manutter: I can't see how it would matter, but it does look like there's a problem with the libs he's pulling in

14:33 and it just seemed a little odd

14:33 amalloy: agreed, he should change it. but it also shouldn't fix the problem if we live in a half-sane world

14:35 manutter: A half-sane world? WIth computers in it??

14:35 TimMc: use just expands to require + refer, right?

14:35 manutter: :D

14:35 amalloy: yes

14:36 manutter: Sorry, I'm a PHP programmer by trade, I just have a hard time grasping the concept of sanity in programming.

14:36 amalloy: manutter: there's still time to jump overboard

14:38 manutter: Don't think I'm not tempted

14:38 amalloy: return array_filter(function ($x) use ($foo, $bar, $baz) { return ... ;}, $someArray); // not enough punctuation and noise yet

14:39 assuming you're on a version of php that even *has* closures

14:39 symbole: Is there a way to require a function to accept a type that extends a particular protocol?

14:39 Scriptor: argh, those don't count as closures

14:40 nollidj: symbole: do you know of type annotations on function parameters?

14:40 manutter: lol, I'm working on a system that has mixins and extensible classes

14:40 home grown PHP extensions

14:40 amalloy: Scriptor: really? i'm curious why you feel that way. rage i understand, but it's hard to see how those could be considered not closures

14:41 symbole: nollidj: Yes.

14:42 nollidj: symbole: protocols automatically generate a corresponding interface. see (doc defprotocol)

14:43 Scriptor: amalloy: a bit exaggerating, I guess, but mainly because it only allows enclosing of varriables in the same scope

14:43 er

14:43 in the scope directly above it

14:43 nanarpuss: anybody familiar with clojurescript?

14:43 amalloy: nollidj: ack no don't use those

14:43 symbole: nollidj: Thanks.

14:43 nollidj: amalloy: ok.

14:43 symbole: maybe you should listen to amalloy instead of me

14:44 amalloy: (defprotocol Printable (print [this])) (extend-protocol Printable String (print [this] (println this))) ;; String satisfies Printable the protocol, but doesn't implement Printable the interface

14:44 nollidj: ah, right

14:45 amalloy: symbole: just add a precondition or an assertion that checks ##(doc satisfies?)

14:45 lazybot: ⇒ "([protocol x]); Returns true if x satisfies the protocol"

14:46 nanarpuss: I was curious about the compiled javascript, it seams to not ever define function prototypes; is it just me, or does that sound like a performance bottleneck?

14:46 symbole: I'll give preconditions a try.

14:47 ibdknox: nanarpuss: it would only make sense to do so for objects, which I assume deftype uses, though I haven't looked into it

14:50 nanarpuss: hmm, deftype, i've never used that yet in clojurescript... let me try it now; but in the meantime, anybody else think this could be a point worth looking into? I'm no blackbelt in javascript, so input would be useful...

14:50 symbole: Is it a good idea to require records that extend a particular protocol as a way to enforce an interface? Seems like passing records would improve readability and create better self documenting code.

14:51 As supposed to passing maps.

14:52 I guess that doesn't make much sense, because if some object doesn't extend a protocol, it would signal an error anyway.

14:54 I'm just thinking about how to create interfaces which are enforced and not giving the user the ability to just pass anything in.

14:55 amalloy: symbole: use a statically typed language

14:56 ibdknox: nanarpuss: The only advantage provided by prototype functions is that they are not redeclared per instance of an object.

14:57 nanarpuss: So since there are no objects in this code, except for those created by deftype, I don't see how there would be a benefit

14:58 nanarpuss: thanks, that is the insight I was looking for.

14:59 amalloy: so, this isn't really a question or a proposal, but it annoys me that in something like (defn foo [x] (filter (comp bar baz) x)), the comp has to be reconstructed every time the function is called, even though it's a constant. i can (let) it around the defn, but that seems like overkill for something that's not a real performance hog. i guess what i want is automatic constant folding; anyone working on this or know how hard it would be?

14:59 technomancy: are you sure it isn't fixed at compile-time?

15:00 amalloy: no, i'm not. i guess it would be simple to test

15:00 technomancy: I guess it would be fixed to the current value of the var if it were

15:00 which isn't usually desirable

15:00 amalloy: right, which seems like the way 1.3 is going

15:01 technomancy: except 1.3 will detect recompilation and clear relevant caches

15:01 but I don't think it would catch this unless you did #'foo

15:01 ibdknox: what is the real perf loss here?

15:01 did you test?

15:02 I can't imagine it's much at all

15:02 amalloy: ibdknox: i agree, but it's galling, just like compiling (+ 1 2) into an actual addition

15:03 ibdknox: amalloy: haha yeah.

15:04 I bet the real cost is in GC'ing all the extra functions you would make

15:04 amalloy: technomancy: okay, i've changed my mind, i'm no longer sure it's easy to test

15:05 ibdknox: haha

15:05 technomancy: there are a few places where I assumed a new function was being constructed at runtime with an fn literal where I was surprised to see it happened at compile-time

15:06 comp may or may not be the same, I just remember enough to not trust my initial intuition.

15:06 ibdknox: how can it make those guarantees with things like thread-level binding?

15:06 I guess in 1.3 you have :dynamic

15:07 so you can know up front

15:07 bpr: technomancy: how did you find that it was happening at run-time v. compile-time? I'm not sure how I would approach discovering that.

15:07 err.. compile-time v. run-time anyhow

15:07 arohner: ,(source comp)

15:07 clojurebot: Source not found

15:08 amalloy: technomancy: on 1.2.1 my simple foo is calling comp at runtime. (disclaimer: to prove this, i redefined clojure.core/comp, so conceivably it might be detecting that and turning off some optimization)

15:08 technomancy: bpr: counting .class files on disk after an AOT run IIRC

15:08 been a while

15:08 bpr: technomancy: ah, pretty simple. thanks

15:08 TimMc: technomancy has the bytecode rendered as 24-color bitmaps combined into a 24fps video, and then watches the video out of the corner of his eye.

15:08 bpr: lol

15:08 arohner: comp calls (fn []) on every invocation

15:08 TimMc: *24-bit color

15:09 ibdknox: TimMc: who doesn't?

15:09 :D

15:10 TimMc: For fun he writes programs that, when transformed in the above manner, appear to be Shakespearean plays.

15:10 ibdknox: n00bs like me who can only read the hex

15:11 technomancy: TimMc: only for erlang code

15:11 I don't use a lot of actors in clojure

15:11 TimMc: ba-dum tish

15:11 ibdknox: (inc technomancy)

15:11 lazybot: ⟹ 3

15:11 ibdknox: so bad, but it deserved +1

15:12 amalloy: maybe the easiest solution would be to write a macro that looks for subexpressions consisting only of free variables and factors them out into a let

15:12 then you don't need any compile-time support

15:12 technomancy: relevant: http://shakespearelang.sourceforge.net/report/shakespeare/#SECTION00090000000000000000

15:12 ibdknox: hah I haven't seen that in a while

15:22 edbond: How to deal with peer not authenticated [Thrown class javax.net.ssl.SSLPeerUnverifiedException] in clj-http or other apache http client based?

15:25 symbole: edbond: I don't understand your question.

15:30 edbond: symbole: I am trying to read https response from server with self-signed cert and get an exception.

15:31 grumpytoad: so in scala you can use zip to combine two collections - is this possible in clojure ?

15:32 scgilardi: combine as in one collection becomes keys in a map and the other becomes corresponding values?

15:32 amalloy: scgilardi: zip questions are usually answered with map

15:32 &(map list '[a b c] '[1 2 3])

15:32 lazybot: ⇒ ((a 1) (b 2) (c 3))

15:32 grumpytoad: hmm.. not sure, too unfamiliar, at best a tuple if that exists

15:33 hmm ok.. will try that

15:33 scgilardi: amalloy: thanks. was trying to understand "combine"

15:33 ibdknox: yeah it wasn't clear to me if he actually wanted concat

15:33 but given he was referencing zip..

15:33 amalloy: scgilardi: yeah, combine is vague. i've learned that "zip" means "i'm coming from haskell or scala and where is the zip function"

15:33 thus: map lis

15:34 scgilardi: yes, looks right. generating an alist

15:34 amalloy: more like a list of tuples; i think the similarity to an alist is a coincidence

15:35 symbole: edbond: I don't believe clj-http handles self-signed certificate.

15:35 scgilardi: or it's a rose

15:35 amalloy: i wonder how haskell/scala do a three-way zip, since they don't have &rest args

15:36 grumpytoad: yes a list of tuples as i need/want to access each in pairs (x - y coordinates)

15:36 TimMc: amalloy: ANy reason to use (map list ...) over (map vector ...) here?

15:37 amalloy: grumpytoad: since you're here, care to satisfy my curiosity? what would you do if you had three lists, [a b], [x y], [1 2], and wanted [(a,x,1), (b,y,2)]?

15:37 TimMc: in Scala, I presume

15:37 amalloy: TimMc: two characters shorter. as you're doubtless aware i strive to avoid wasted characters, which tire out my fingers unnecessarily

15:37 grumpytoad: euhmm .. hehe i would shriek and run far away

15:38 it's possible to have tuples of tuples or some similar construct

15:40 so why doesn't merge do what i need ?

15:40 amalloy: because it does something different

15:40 and map does do what you need

15:42 grumpytoad: though map cannot be used on a LazySeq ?

15:44 clj-noob: how to call mysql stored procedure with INOUT parameter using clojure.java.jdbc and print the OUT parameter?

15:46 amalloy: apparently haskell has zip, zip3, zip4...up to some arity N

15:46 *shudder*

15:47 grumpytoad: it worked ;-)

15:47 ibdknox: (map3 list (range 10) (range 10) (range 10))

15:47 technomancy: the price of currying is eternal arities.

15:48 amalloy: indeed. i feel silly for actually asking in #haskell instead of just hoogling for it though

15:48 ibdknox: did they scoff at you? lol

15:48 grumpytoad: where does that word come from arities

15:48 amalloy: nah

15:48 grumpytoad: it's like an indian side dish

15:48 amalloy: they're friendly dudes over there too

15:49 technomancy: arities and naan go particularly well together

15:49 grumpytoad: lol

15:49 amalloy: technomancy: just don't order it with the curry?

15:50 ibdknox: now that I think about it, I don't think I heard the term before I started messing with Clojure

15:51 opqdonut: amalloy: that's because generic type-safe tuples would be a PITA. but you can look up HList if you want

15:51 pdk: does haskell not support varargs or something

15:51 technomancy: grumpytoad: arity just means the number of arguments a function takes

15:51 opqdonut: (generic in the sense of having a generic first operation etc)

15:51 technomancy: pdk: that's correct, you can't have currying with varargs

15:51 amalloy: pdk: no. and it has a reason, just like clojure has for using lots of parens :P

15:52 grumpytoad: technomancy: yes, seems so, but it's my first encounter since trying clojure

15:52 opqdonut: and besides, for many of the use cases of zipN, transpose is the correct function

15:52 amalloy: *nod*

15:52 opqdonut: sorry, just venting

15:53 amalloy: opqdonut: yes, i can see that most of the time you don't really need zipN

15:53 grumpytoad: currying brings a lot of syntax sugar in statically typed languages, AFAICS

15:54 amalloy: it's clearly something they *wish* they had or they wouldn't have written zip5, but it's something the type system constrains them to be unable to generically express

15:54 opqdonut: grumpytoad: I have no idea what you mean with that

15:54 amalloy: which doesn't seem like an unreasonable compromise: for all the benefits of haskell's powerful type system, you lose zipN. sounds good to me :)

15:54 grumpytoad: opqdonut: you get some shortcuts instead of having to wrap functions and their definitions

15:55 opqdonut: grumpytoad: yeah sure, partial application is great for writing functional code succinctly

15:56 choffstein: Hey all. I am using leiningen to manage my projects and compiled & installed one of my libraries (aws-logging) via "lein install". I am using this library in another library, and after importing using "lein deps" I try to require it via the repl ("lein repl"), but get the error: java.lang.NoClassDefFoundError: Could not initialize class aws_logging.core__init (NO_SOURCE_FILE:0). "lein deps" moves the appropriate j

15:56 into the lib folder -- so the library is definitely there. The project file and core file for aws-logging can be seen here: https://gist.github.com/1150013

15:56 Any thoughts on this one? I can't seem to figure it out.

15:56 AWizzArd: Anyone here on Java 7?

15:57 TimMc: grumpytoad: bin*ary*, tern*ary*, quatern*ary* <- arities

15:57 oh, and not to mention nullary and unary

15:57 grumpytoad: so... now i want to curry something.. i guess that's not possible

15:58 pdk: did they go through with the stuff talking about closures in java 7

15:58 bpr: does anyone know if there's a way to get the byte length of a gloss codec? Assuming that the codec has a constant length? (which I can safely do)

15:58 TimMc: As far as I can tell it is a sort of back-formation.

15:58 AWizzArd: There is this powerful new class java.nio.file.Paths. I would like to call it from Clojure. How to do it? One Java example is this: Path path = java.nio.file.Paths.get("d:", " temp "","test.txt");

15:58 pdk: seems goofy as hell having closures alone without the rest of the functional stuff that makes them useful, it's like building an arch with one stone

15:58 same story with c++0x

15:59 TimMc: AWizzArd: (Paths/get ...) probably

15:59 AWizzArd: Well, I tried that.

15:59 The funny thing is that the get method is overloaded.

15:59 TimMc: Oh, is it varargs?

15:59 AWizzArd: yes

15:59 amalloy: pdk: no, closures were delayed to jdk8 i think

15:59 choffstein: Any idea on my issue, oh clojure wizards?

15:59 TimMc: It probably wants a string array

15:59 AWizzArd: Either it is a vararg String... or an URI

16:00 pdk: did that at least suggest other stuff that makes closures useful

16:00 TimMc: ,(doc strings)

16:00 clojurebot: Excuse me?

16:00 pdk: like real lambdas/higher order functions

16:00 AWizzArd: But the funny thing is that (Paths/get (into-array String ["c:" "temp"])) warns me that a String array can not be cast to an URI

16:00 Clojure sees that I call with one argument and tries to call the method taking the URI

16:00 TimMc: Haha, weird!

16:00 AWizzArd: yup

16:00 opqdonut: try hinting?

16:00 AWizzArd: yes

16:01 amalloy: AWizzArd: javadoc for the new thingy?

16:01 opqdonut: ^"[java.lang.String;" or however it goes

16:01 amalloy: ^"[Ljava.lang.String;"

16:01 opqdonut: that

16:01 AWizzArd: but also (Paths/get ^"[Ljava.lang.String;" (into-array String ["c:" "temp"])) doesn't help.

16:02 Excetpion: [Ljava.lang.String; cannot be cast to java.net.URI

16:02 opqdonut: oh, that sucks

16:03 choffstein: Anyone ever seen a java.lang.NoClassDefFoundError: Could not initialize class classname__init (NO_SOURCE_FILE:0)

16:03 TimMc: choffstein: Yeah, usually when I am flailing around trying to create a new project tree.

16:03 choffstein: any idea where it might be stemming from?

16:03 TimMc: I suppose Clojure can't resolve varargs because of the whole dynamic typing thing.

16:03 *automatically

16:04 dnolen: AWizzArd: is that a Java var args method?

16:04 AWizzArd: http://download.oracle.com/javase/7/docs/api/java/nio/file/Paths.html

16:05 amalloy: AWizzArd: it takes two args

16:05 first, then an array of more

16:05 AWizzArd: ah okay

16:05 Good, that works.

16:05 amalloy: (inc javadoc)

16:05 lazybot: ⟹ 1

16:05 AWizzArd: Phew :-)

16:06 amalloy: i was going out of my mind (a) trying to find the javadocs, and (b) trying to imagine how it could be happening with the method signature you described

16:06 AWizzArd: Excellent (:

16:06 choffstein: i'm about to punch a baby seaturtle

16:06 what. the. hell.

16:06 AWizzArd: I also didn't understand it, especially since hinting also didn't help

16:07 Because Java also needs some way to differentiate.

16:07 I just didn't see from that example code that there is a first arg.

16:07 technomancy: choffstein: what you're describing should work as long as you restart your jvms after running deps

16:07 AWizzArd: Paths.get("d:", " temp");

16:07 choffstein: restarting my jam?

16:07 jvm?

16:08 TimMc: AWizzArd: That's a great example of example code biting you in the ass.

16:11 technomancy: I would not presume to instruct you in when your jams should be started and/or restarted.

16:11 only that they should be periodically pumped up.

16:14 amalloy: just the other day we were discussing how everything is the jam's fault

16:15 choffstein: autocorrect … how I love thee.

16:17 …double-you, tee, eff. Now lein install is broken because it can't find the namespace? What in the world have I done?!

16:17 TimMc: Ooh, that's good news!

16:18 It probably means something is wrong more globally, not with your project.

16:18 choffstein: This might be a very, very, very stupid question

16:18 amalloy: TimMc: and if his computer catches fire, it's time to throw a party, because something *very* global is broken?

16:18 ibdknox: lol

16:18 TimMc: Well, at least he will know what is wrong.

16:18 ibdknox: (inc amalloy)

16:18 lazybot: ⟹ 1

16:19 choffstein: But if library A relies on library B, I build A and do a lein install, then include library A into library C -- C shouldn't have to know anything about B, right?

16:19 amalloy: huh. lazybot, when did you forget all the karmas?

16:19 technomancy: choffstein: you're right; C shouldn't need to mention B in project.clj

16:19 leonid__: (amalloy)

16:19 ,(amalloy)

16:19 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: amalloy in this context, compiling:(NO_SOURCE_PATH:0)>

16:19 choffstein: technomancy: that is what I thought. herrm…. intriguing.

16:19 leonid__: ,amalloy

16:19 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: amalloy in this context, compiling:(NO_SOURCE_PATH:0)>

16:19 choffstein: might just try starting a fresh project

16:20 leonid__: tetris!

16:20 amalloy: oh, haha. when we renamed him from sexpbot to lazybot, he started reading from the lazybot database instead of the sexpbot database

16:21 technomancy: remember to merge-with + when you port the data over

16:22 choffstein: can you guys check out this gist real quick? https://gist.github.com/1150013

16:22 TimMc: WHen did sexpbot become lazybot?

16:22 choffstein: The errors are at the bottom. They confuse me.

16:22 amalloy: a few weeks ago?

16:23 TimMc: choffstein: As far as I can tell it is some sort of compile-time error in the ns declaration.

16:24 choffstein: I would certainly not disagree with that deduction :)

16:24 I'm just confused as to what the hell it is though.

16:24 TimMc: Yeah, I'm not sure where to go from there.

16:25 I'm guessing it's a case of clojure.core taking its sweet time in checking for nil.

16:26 I can paste that into the REPL without getting that error (and instead getting Not Found errors.)

16:27 tufflax: How do I use :rename within a :use? I'm trying this but it does not work :p' (:use [clojure.string :only (split split-lines replace) :rename {'replace 'srep}])

16:27 choffstein: that confuses me and frustrates me and intimidates me.

16:27 amalloy: no quotes

16:28 technomancy: tufflax: have you considered require :as?

16:28 tufflax: yes briefly

16:28 but, I'm just curious now :p

16:28 amalloy: technomancy: something wrong with :use/:rename? i mean, when i use clojure.string i usually do requre/as, but use/rename is viable too

16:29 TimMc: choffstein: Namespace appears to be looking up a symbol in a hash map, and I'm not sure how that would successfully dispatch to the get method and still cause an NPE.

16:29 Unless that hashmap disallows null, and the symbol is somehow null.

16:30 tufflax: amalloy: sigh, tried that but got an unrelated error and didn't check it :p

16:30 thanks

16:30 technomancy: amalloy: it works, but it's less obvious

16:30 TimMc: Looks like a b0rken project.

16:30 choffstein: TimMc: So just wipe it and re-create?

16:31 TimMc: Yeah. Create a new project and start reinstating pieces until the error shows up (or doesn't).

16:32 I can't think of anything more clever.

16:33 choffstein: i'll give it a go.

16:33 I think it has to do with clj-logging-config to be quite honest, since that's when the project broke.

16:42 hmmm …. it was in importing the last two classes. that is interesting.

16:56 grumpytoad: hmm.. enjoying this. thx & laters

16:57 amalloy: well, i've managed to accidentally give everyone twice the karma they used to have. that's almost like rescuing the old values

16:59 there

17:01 mattmitchell: is there a built in sum function?

17:01 amalloy: mattmitchell: it's called +

17:01 mattmitchell: ahh ok just use apply :)

17:01 amalloy: indeed

17:02 dnolen: ,(time (reduce + (range 100000)))

17:02 clojurebot: "Elapsed time: 167.327 msecs"

17:02 4999950000

17:02 dnolen: ,(time (apply + (range 100000)))

17:02 clojurebot: "Elapsed time: 83.701 msecs"

17:02 4999950000

17:02 dnolen: ,(time (reduce + (range 100000)))

17:02 clojurebot: "Elapsed time: 54.336 msecs"

17:02 4999950000

17:02 dnolen: ,(time (apply + (range 100000)))

17:03 clojurebot: "Elapsed time: 49.355 msecs"

17:03 amalloy: dnolen: practicing your hotspot optimizations?

17:03 clojurebot: 4999950000

17:03 dnolen: amalloy: ;) I feel like reduce is usually quicker than apply.

17:03 ,*clojure-version*

17:03 clojurebot: {:interim true, :major 1, :minor 3, :incremental 0, :qualifier "master"}

17:03 amalloy: i don't see why that would be the case

17:03 apply just calls reduce

17:03 (for the particular case of +)

17:05 and for some functions, of course, apply will be faster than reduce

17:05 dnolen: amalloy: apply calls reduce when using + ? line?

17:06 ,(time (reduce + (range 1000000))

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

17:06 dnolen: ,(time (reduce + (range 1000000)))

17:06 clojurebot: "Elapsed time: 523.616 msecs"

17:06 499999500000

17:06 amalloy: $source +

17:06 lazybot: + is http://is.gd/zh9ARG

17:06 dnolen: ,(time (apply + (range 1000000)))

17:06 clojurebot: "Elapsed time: 536.39 msecs"

17:06 499999500000

17:06 kephale: oh heh, i didnt know that either

17:06 amalloy: https://github.com/clojure/clojure/blob/1.2.x/src/clj/clojure/core.clj#L809

17:06 dnolen: amalloy: that's 1.2

17:07 amalloy: but you're right + calls reduce1 in 1.3

17:07 grumpytoad: ,(repeat 1)

17:07 clojurebot: (1 1 1 1 1 ...)

17:07 amalloy: right. and if it changed, i would expect apply to be the one that got faster, not reduce

17:07 grumpytoad: heh no explode? shame

17:10 amalloy: &(time (= (apply str (repeat 1e7 "test"))))

17:11 hm. too many zeros

17:11 lazybot: Execution Timed Out!

17:11 amalloy: &(time (= (apply str (repeat 1e5 "test"))))

17:11 lazybot: ⇒ "Elapsed time: 112.653346 msecs" true

17:11 amalloy: &(time (= (reduce str (repeat 1e5 "test"))))

17:11 lazybot: Execution Timed Out!

17:14 mattmitchell: is there a function that is somewhat similar to partition, except that it creates a max number of groups based on a number? For example: (my-group-fn 2 [1 2 3 4 5 6 7 8]) => [[1 2 3 4] [5 6 7 8]])

17:14 clojurebot: Roger.

17:14 dnolen: amalloy: huh interesting. for + case, reduce / apply are pretty much the same.

17:14 amalloy: dnolen: sure, because no interesting optimizations can happen for +

17:15 but for str, they can; and only apply can take advantage because it knows all the args ahead of time

17:15 mattmitchell: https://github.com/flatland/useful/blob/develop/src/useful/seq.clj#L51

17:16 mattmitchell: amalloy: slice yeah! that's it. thank you.

17:16 amalloy: mattmitchell: well, that's an external library you'll have to depend on

17:16 it's not in core or anything

17:18 kephale: i wonder about + with something like a recursive (map + (partition 2 coll))

17:19 aaelony: hi all, I'm trying to understand java inter-op better and dealing with 3 java objects from the jets3t.service library.. I'm currently not specifying the order of the classes correctly as listObjects should be associated with s3Service and not S3Bucket....

17:19 (. s3service (.getObject (S3Bucket. bucket-name) (. (.listObjects (S3Bucket. bucket-name)) (.getKey ))))

17:19 java.lang.IllegalArgumentException: No matching field found: listObjects for class org.jets3t.service.model.S3Bucket (NO_SOURCE_FILE:0)

17:20 I'm likely abusing the dot macro somehow

17:26 TimMc: Looks like a good opportunity for the stitching macros.

17:27 Anyway, I recommend sequentially binding those values to names so you can see what you are doing.

17:27 aaelony: I think it is the dot special form, but something is not quite right

17:27 perhaps getting more coffee will help...

17:27 TimMc: (let [bucket (S3Bucket. bucket-name), objects (.listObjects bucket)] ...)

17:28 raek: aaelony: could you write what you are trying to do in java syntax?

17:28 aaelony: sure

17:28 TimMc: aaelony: (.listObjects (S3Bucket. bucket-name)) is saying new S3Bucket(bucket-name).listObjects()

17:29 aaelony: it is something like this:

17:29 final S3Bucket s3Bucket = new S3Bucket(bucketName);

17:29 for (final S3Object s3Object : s3Service.listObjects(s3Bucket)) {

17:29 S3Object completeObject = s3Service.getObject( s3Object.getKey() );

17:29 TimMc: Is s3Service a class or an object?

17:30 aaelony: => (class s3service)

17:30 org.jets3t.service.impl.rest.httpclient.RestS3Service

17:30 it is an instance of that class with credentials needed to talk to the bucket

17:30 TimMc: ah, OK

17:31 aaelony: somehow my chaining is garbled

17:31 TimMc: s3Object vs. S3Object is pretty confusing also

17:31 aaelony: yes, sorry

17:32 s3Object is just an instance of an S3Object

17:33 I am referencing this: http://jets3t.s3.amazonaws.com/toolkit/code-samples.html

17:33 TimMc: So yeah, naming your intermediate values (and naming them well) is probably the best approach to finding your problem.

17:33 raek: (let [s3-bucket (S3Bucket. bucket-name)] (for [s3-object (.listObject s3-service)] (let [complete-object (.getObject s3-service (.getKey se-object))] ...))

17:33 this would be a literal translation of your code

17:34 if the for body only does side-effects, you should replace for with doseq

17:34 aaelony: ok. cool. let me study this.

17:35 dnolen: amalloy: still don't agree w/ you on the diff between apply and reduce perf. apply str is fast because of special case StringBuilder hack in str

17:35 apply does not know how many arguments it gets, it uses a Seq

17:41 aaelony: hmmm, how would I translate this? s3Service.listObjects(s3Bucket)

17:42 would it be: (. (s3Service (.listObjects s3Bucket))) ???

17:43 ShreeMulay: alright all, I'm trying to solve http://www.4clojure.com/problem/21#prob-title but I keep getting the following error message: You tripped the alarm! nth is bad!

17:43 The following is my solution: (fn [[f & rest] x] (if (= 0 x) f (recur rest (dec x))))

17:43 why am I getting that problem?

17:43 TimMc: aaelony: (.listObjects s3Service s3Bucket)

17:44 ,(macroexpand-1 '(.listObjects s3Service s3Bucket))

17:44 clojurebot: (. s3Service listObjects s3Bucket)

17:44 aaelony: thanks, TimMc... pondering it...

17:46 TimMc: aaelony: dot by itself gives you the Java ordering: (. object method args...)

17:47 A symbol beginning with a dot is a special form that makes for a functional programming ordering of names: (.function object args...)

17:47 It expands into the other form.

17:47 aaelony: TimMc: thanks.. this worked but brought me to a org.jets3t.service.S3ServiceException: S3 GET failed ...

17:47 TimMc: Ah, but now you have the right syntax, it would seem!

17:47 aaelony: ... The specified key does not exist

17:47 getting closer ;)

17:48 TimMc: Thanks for now...

17:53 amalloy: dnolen: right. that's why apply str is faster, no question. my point is that, when apply/reduce produce the same results, reduce will be faster iff it gets parallelized, and apply will be faster iff there's a special-case "global" optimization available like for str. i don't think it's out of the question to suppose that functions other than str will have global optimizations available

17:53 ShreeMulay: destructuring ([f & rest]) expands into a use of nth

17:54 kinda annoying imo, but it means you can't use it to solve the nth problem

17:55 Raynes: amalloy: That is very unfortunate.

17:55 amalloy: dnolen: for example, conj could be written so that (apply conj foo xs) used transients like into does

17:56 in which case, apply conj would be faster than reduce conj

17:56 Raynes: i agree, but what can we do?

17:56 Raynes: Nothing, I suppose. I wish sandboxing wasn't so unscientific.

17:56 dnolen: amalloy: I recall having this conversation with you before. Yuck.

17:57 ;)

17:57 amalloy: *chuckle*

17:59 Raynes: amalloy: I don't know why anybody would write such an awful sandboxing library when sandboxing is so impossibly diffi... Oh wait, that was us wasn't it?

18:00 Chousuke: :P

18:00 It's kind of difficult to let people do whatever they want without letting them to do whatever they want

18:00 amalloy: imo the root cause of this particular issue is that (let [[x y] foo]) uses nth instead of first/rest

18:01 arohner: holy crap, why didn't anyone tell me midje is awesome?

18:01 AWizzArd: arohner: example please

18:01 Raynes: amalloy: Submit a patch. And then go ahead and decline it and save them the trouble. ;p

18:01 amalloy: srsly

18:01 arohner: AWizzArd: https://github.com/marick/Midje/wiki/Midje-mode

18:03 AWizzArd: arohner: I saw that mode but never took a closer look at it. I will watch that vid now.

18:05 amalloy: arohner: those are terrible keybindings

18:06 arohner: amalloy: so rebind them. it is emacs after all

18:06 amalloy: i know

18:06 arohner: the point is, there is an emacs mode, and it works

18:07 amalloy: it's just i'm morally offended that someone would create a minor mode that uses C-c <letter> bindings, which are specifically reserved for the user's personal use

18:07 *grumble grumble get off my lawn*

18:08 Raynes: amalloy: We must hunt him.

18:18 technomancy: amalloy: http://p.hagelb.org/pay.png

18:19 amalloy: technomancy: i'm trying to find the "right" bindings for minor modes. what is it, C-x <letter>?

18:43 wilfredh: what's the Clojure equivalent of Python's zip()? Do I have to use map?

18:43 jeremyheiler: ,(doc zipmap)

18:43 clojurebot: "([keys vals]); Returns a map with the keys mapped to the corresponding vals."

18:43 jeremyheiler: wilfredh: does that work for yoU?

18:44 wilfredh: I was hoping for a list of lists, but I could make do with that

18:45 thanks :)

18:45 amalloy: (12:34:47 PM) grumpytoad: so in scala you can use zip to combine two collections - is this possible in clojure ?

18:45 (12:36:17 PM) amalloy: &(map list '[a b c] '[1 2 3])

18:45 wilfredh: ^

18:46 wilfredh: oh, of course. Perfect.

18:46 amalloy: and now i've added another language to my list of "languages from which people ask about zip"

18:46 raek: wilfredh: map vector or map list... choose your preferred tuple type :-)

18:47 wilfredh: raek: exactly. Python mindset still showing through...

18:55 technomancy: amalloy: if you still need it: (info "(elisp)Key Binding Conventions")

18:57 amalloy: technomancy: yeah, i found that. it seems to be a list of things not to do

18:57 no suggestion about things to actually do, for minor modes

18:57 technomancy: "Sequences consisting of `C-c' followed by any other punctuation character are allocated for minor modes." ?

18:58 amalloy: ah, yes. i guess that seemed like a pretty small set of things, and i thought there were more

18:58 but in Keymaps and Minor Modes i just found "The key sequences bound in a minor mode should consist of `C-c'

18:58 followed by one of `.,/?`'"[]\|~!#$%^&*()-_+='", and i guess it couldn't get any clearer

19:32 omg. i just realized i can stop writing (apply concat (for [x xs] (make-a-list x))), and instead write (for [x xs, list-item (make-a-list x)] list-item)

19:39 &(time (dorun (apply concat (for [x (range 100)] (range x)))))

19:39 lazybot: ⇒ "Elapsed time: 24.139846 msecs" nil

19:40 amalloy: &(time (dorun (for [x (range 100), y (range x)] y)))

19:40 lazybot: ⇒ "Elapsed time: 896.231447 msecs" nil

19:40 amalloy: these two are generating the same sequence (per my comment above). does anyone know why the second would be so much atrociously slower? i don't really understand how `for` works internally

19:40 tufflax: amalloy i think it's a list monad

19:41 in the beginning of http://intensivesystems.net/tutorials/monads_101.html you can learn about them. more than that i dunno

19:45 hm, maybe not. the source is some kind of monster

19:45 I was just guessing really

19:46 amalloy: i'm now wondering if maybe it's to do with chunking. the first one preserves chunks, and the second one might be ripping them apart

19:52 bpr: amalloy: that is odd

19:52 the timings, that is

19:53 amalloy: bpr: i tried replacing (range x) with (take x (iterate inc 0)), and that gets the timings closer together. so i think it probably is a chunking thing

19:54 ie, the version with apply concat gets 25 times slower and the version without stays about the same :P

19:54 bpr: wow

20:52 amalloy: bpr: on further investigation, it seems to be something weird about lazybot's environment. in my repl, and on two other bots, the runtimes are comparable

20:55 specifically, he's always running with a profiler attached, so that when he starts misbehaving (as happens once a month or so) i can see where all the CPU is going; probably the profiler is slowing down allocs

21:04 ninjudd: what do you think about https://gist.github.com/f30273d77ae8301d2852?

21:05 hm, wrong channel. oh well, he's in here too

21:30 livingston: I'm having trouble with a macro that ultimately calls defn it's putting my parameter names in a namesapce and the complier really doesn't want them there.

21:30 how do I get around this: git://gist.github.com/1150606.git

21:32 sorry I guess that's actually here: https://gist.github.com/1150606

21:37 the answer is that I used free variables instead of gensyms it should be kb-creator#

21:38 zakwilson: livingston: also google variable capture in Clojure if you find that you want variable capture in your macros. It's dangerous, of course, but useful.

21:39 livingston: thanks. I'm familiar with capture, I just didn't realize that's how it was done in clj, (I'm used to commonlisp)

22:01 amalloy: livingston: it's usually not - when possible you should use gensyms

22:02 livingston: amalloy: what's usually not?

22:03 amalloy: using symbol capture is not usually how it's done. or were you saying you didn't realize you have to do it at all

22:03 if you want to make it accessible from within the expanded body you can't use a gensym, so you can either make the user pass in the name to bind to, or do something anaphoric

22:04 livingston: I just didn't realize that's how it was done in clj. I understand avoiding capture in general. that's just not a case were I think that it would have been an issue in say commonlisp so I wasn't thinking about it.

22:04 amalloy: eg, you could use it as (kb-test test-kb-up test-triples [kb] (is kb))

22:04 okay

22:04 basically clojure defaults to making accidental capture impossible

22:05 Pupeno: I wrote a post called Why I love Lisp, featuring Clojure… yesterday it got 11k views :)

22:05 livingston: amalloy: yeah. it would have been generally safe there, but it's guaranteed safe this way.

22:06 jeremyheiler: Pupeno: Care to share the link?

22:07 Pupeno: jeremyheiler: sure: http://pupeno.com/2011/08/16/why-i-love-lisp/

22:07 Someone +1 it on G+, I wonder if I could find those comments, if any.

22:13 jeremyheiler: Pupeno: nice little blog post +1

22:13 livingston: so I can trigger mvn clojure:test to run with the test phase, but it doesn't show up in the test report (probably because the java test plugin is unaware of the clojure?) is there a way to make it aware?

22:13 Pupeno: jeremyheiler: thanks :)

22:16 Is it possible to use a library from source instead of a jar? with lein? how?

22:16 arohner: Pupeno: yes, read the section about checkout dependencies in the lein FAQ

22:17 Pupeno: arohner: thanks.

22:20 mattmitchell: i have a question about modifying maps. I find myself doing a lot of this: https://gist.github.com/1150671 is there a better way than if... else... if else... ? i get the feeling that monads could help me, but i haven't been able to completely understand how to apply them. Not sure if I'm explaining myself well enough, but I guess the example (and a lot of stuff I write) feels procedural, and not very functional. Anyone else be

22:20 here and beyond?

22:21 maybe bad example... but

22:21 livingston: woah

22:21 mattmitchell: it's the procedural thing that feels wrong

22:22 hiredman: (update-in m [:id] (fn [m] ...))

22:22 livingston: mattmitchell: there's no variability in that... I'm assuming one of those is a parameter of some function?

22:24 mattmitchell: livingston: could be yes. A lot of code just seems to be this stack within a "let", then a series of "if"'s, and merging etc.

22:24 hiredman: thanks, will check that out

22:24 Pupeno: How should I run the REPL so it picks the checkouts if I'm not using lein to run the REPL?

22:25 amalloy: mattmitchell: there's something in ninjudd's/my useful that might make this a little more visually pleasing

22:25 livingston: typically rows or nests of if's beg for cond

22:26 mattmitchell: amalloy: ok great. i think i was just browsing through that this afternoon

22:26 livingston: but this is just weird.

22:26 mattmitchell: livingston: ha well, my example? yeah, need something real world.

22:26 livingston: could you share a more real function, that might help

22:27 amalloy: mattmitchell: https://gist.github.com/1150681

22:27 mattmitchell: livingston: i would have to dig around a little bit. I'll come back with something that better describes the "issue" I'm having.

22:28 amalloy: uses useful.fn/given

22:28 livingston: mattmitchell: a more specific question will get more specific feedback, I'm sure.

22:29 mattmitchell: livingston: yep totally. i'll post a real example tomorrow sometime

22:29 amalloy: that's nice, yeah more declarative and less ify

22:29 livingston: a list of functions and reduce also comes to mind, but again... depends on what

22:30 mattmitchell: livingston: using apply and reduce on a list of functions?

22:30 amalloy: just reduce, really

22:31 livingston: just reduce with an initial value being your map that's being progressively modified, each function returns a new map.

22:31 amalloy: &(let [fixers [#(if (= 1 (:id %)) (assoc % :id 2) %)] (reduce #(%2 %1) {:id 1} fixers))

22:32 lazybot: java.lang.IllegalArgumentException: let requires an even number of forms in binding vector

22:32 amalloy: &(let [fixers [#(if (= 1 (:id %)) (assoc % :id 2) %)]] (reduce #(%2 %1) {:id 1} fixers))

22:32 lazybot: ⇒ {:id 2}

22:32 mattmitchell: ahh that's interesting, cool

22:33 livingston: I mean there are a million things to do (merge (if test {new-key-vals} {}) (merge (if test2 {other-new} {}) original)) etc.

22:35 mattmitchell: livingston: oh ok, multiple args to merge, need to remember that.

22:36 livingston: that too

22:57 srid: (find-doc "map") prints a huge list of sections; is there a way to prune it to show only the one I intended (which is the core map function)?

22:58 livingston: ,(doc find-doc)

22:58 clojurebot: "([re-string-or-pattern]); Prints documentation for any var whose documentation or name contains a match for re-string-or-pattern"

22:58 amalloy: &(doc map)

22:58 lazybot: ⇒ "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. A... http://gist.github.com/1150725

22:58 livingston: ,(doc doc)

22:58 clojurebot: "([name]); Prints documentation for a var or special form given its name"

23:00 srid: ah, thx. just figured that by looking at http://clojure.org/cheatsheet

23:14 * srid ran (iterate inc 0) in *inferior-lisp* process and had to kill Emacs because of that

23:14 livingston: nice

23:19 amalloy: &(doc *print-level*)

23:19 lazybot: ⇒ "; *print-level* controls how many levels deep the printer will print nested objects. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum level to print. Each argument to print is at level 0; if an arg... http://gist.github.com/1150742

23:20 amalloy: hm, not quite

23:20 &(doc *print-length*) ;; srid

23:20 lazybot: ⇒ "; *print-length* controls how many items of each collection the printer will print. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum number of items of each collection to print. If a collection con... http://gist.github.com/1150746

Logging service provided by n01se.net