# #clojure log - Sep 28 2012

The Joy of Clojure
Main Clojure site
IRC
List of all logged dates

0:00 uvtc: shachaf: "Y'all're". Nice. :)

0:03 SrPx: shachaf: the x is a free variable on (fn [x] x)

0:03 TimMc: uvtc: "shouldn't've" is also nice

0:05 uvtc: TimMc: Oh, yes,. One of my personal faves. :)

0:05 cjfrisz: SrPx: x is not free in (fn [x] x) because x is in the argument list of (fn [x] x)

0:05 SrPx: But x *is* free in (fn [y] x) because it *doesn't* appear in the argument list and is referred to in the body of the function

0:06 SrPx: In mathematics, and in other disciplines involving formal languages, including mathematical logic and computer science, a free variable is a notation that specifies places in an expression where substitution may take place.

0:06 o.o

0:06 Oh they have a different definition for CS

0:07 So x there is a free variable. Clojure looks that variable on the ns or in the next parent function?

0:08 ,(def x 4) (let [x 5] (fn [y] x))

0:08 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

0:08 SrPx: ,(def x 4)

0:08 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

0:08 eggsby: SrPx: if you want the counter example: https://www.refheap.com/paste/5349

0:08 SrPx: oh

0:09 cjfrisz: SrPx: It tries to find a value for x in the closest enclosing scope until it find a value

0:09 So in your example, x in the body of (fn [y] x) will have the value 5 because x was bound in the scope of the let expression

0:10 Sgeo_: Grah, I hate having to think for two seconds about whether something that looks recursive like that is problematic in Cloure or not

0:10 cjfrisz: If x was not bound in the let, say if you used (let [z 5] (fn [y] x)), then x would have the value 4

0:10 Because it would search each enclosing scope until it got to the outer environment (the ns, as you say) and find the value of 4 for x

0:11 SrPx: So wait Clojure's scope is based on the ()'s?

0:11 (this is a scope (this is another (and another)))

0:11 cjfrisz: As shachaf said, it's all about understanding free variables and lexical scope

0:11 Urthwhyte: I'm porting this code: https://gist.github.com/3140941 over to clojure as a learning exercise, am I confused as the best way to model it would be in clojure

0:12 cjfrisz: SrPx: exactly

0:12 Sgeo_: cjfrisz, wait what?

0:12 Urthwhyte: I suppose instead of objects I should be using records?

0:12 cjfrisz: SrPx: Scope is determined by the nesting of parentheses

0:14 SrPx: hmm

0:14 Sgeo_: That feels ... like it should be wrong

0:14 shachaf: hi Sgeo_

0:15 What's wrong?

0:15 Sgeo_: Scope determined by nesting of parentheses. Surely you could do .. stuff that won't create a new scope, and could introduce a new scope without nesting

0:16 SrPx: I guess the problem is that I see (((fn [x] (fn [y] (+ x y))) 5) 4) just as a partial application. The interesting application of closure on my last language was that I could create a closed environment for a function. But I guess that has no sense without mutability

0:16 eggsby: it's not the nesting of parens, is it? it's the lexical bindings via things like fns and let and with-bindings

0:17 like (do (one ..) (two ..)) separate parens same scope

0:17 TimMc: out and up

0:18 cjfrisz: eggsby: So in your example, one and two have the same *enclosing* scope

0:18 Sgeo_: let can in priciple be reduced to applying an fn

0:18 As long as the fn does lexical scoping stuff etc.

0:18 cjfrisz: Sgeo_: Yes

0:18 Sgeo_: Not particularly relevant to the discussion under discussion

0:19 Suppose you had some macro that ... did weird stuff

0:19 How about <<- from swiss-arrows

0:19 SrPx: Sgeo_: interesting

0:19 Sgeo_: (<<- (let [a 1]) (let [a 2]) a) ; 2

0:20 SrPx: like ((fn [x] (my stuff)) 5) = (let [x 5) (my stuff)) ?

0:20 Sgeo_: SrPx, exactly

0:20 cjfrisz: Sgeo_: What's teh code generated by your example?

0:20 Sgeo_: Except for your syntax error

0:20 cjfrisz: *the

0:21 SrPx: Sorry for that. It is still complicated but ..

0:21 Sgeo_: (let [a 1] (let [a 2] a))

0:21 cjfrisz: Sgeo_: And there's your scope

0:21 Sgeo_: To your point, macros can play with scope, but in general scoping is determined by the nesting or parens

0:22 Sgeo_: And by play with scope I mean rearrange things in unintuitive ways

0:22 For certain examples (i.e. that one)

0:24 Ugh...I meant "nesting *of* parens," not "nesting *or* parens"

0:28 Sgeo_: "It's based on parentheses" does not generalize to non-Lisps

0:28 cjfrisz: Sgeo_: Kind...of?

0:28 Sgeo_: I think it's far more general, and far less fragile, to base it on conceptual nesting of scope-introducing constructs.

0:29 SrPx: Im testing some things, just to confirm, the difference between ' and ` is just that with ` you can use ~ not to quote a part of your list? '(a b c...)

0:29 Sgeo_: An fn introduces a scope to everything within its body

0:29 ,`(1 (+ 2 3) ~(+ 4 5))

0:29 clojurebot: (1 (clojure.core/+ 2 3) 9)

0:29 Sgeo_: ,'(1 (+ 2 3) ~(+ 4 5))

0:29 clojurebot: (1 (+ 2 3) (clojure.core/unquote (+ 4 5)))

0:30 Sgeo_: Oh woah I didn't realize clojure.core/unquote existed

0:30 I'm going to go ahead and say that I think that this in and of itself may make Clojure better than Common Lisp at some macro stuff.

0:31 ,'(`blah ~blah ~@blah)

0:31 clojurebot: ((quote sandbox/blah) (clojure.core/unquote blah) (clojure.core/unquote-splicing blah))

0:31 Sgeo_: ,'('blah `blah ~blah ~@blah)

0:31 clojurebot: ((quote blah) (quote sandbox/blah) (clojure.core/unquote blah) (clojure.core/unquote-splicing blah))

0:31 Sgeo_: Hmm, that's weird that ' and ` are similar like that

0:31 I'm confused now

0:33 SrPx: o.o

0:34 Sgeo_: ,'('~foo `~bar)

0:34 clojurebot: ((quote (clojure.core/unquote foo)) bar)

0:35 Sgeo_: uh

0:35 * Sgeo_ 's head hurts a bit

0:35 SrPx: what the ..

0:53 mpan: People who are using Clojure for web backends: is there something particular you're using for the frontends?

0:54 akhudek: mpan: clojurescript is neat, and has some very promising libraries, but it's not quite as mature as the clojure backend stuff yet

0:55 mpan: Is there a library that people are using to, say, synchronize state and display it?

0:56 akhudek: you mean the sync client side state and server state?

0:56 there has been some discussion of functional reactive programming and a few experimental implementations for that

0:56 not sure of the state of them though

0:57 one of the bigger efforts I've seen is https://github.com/ohpauleez/shoreleave

0:58 also look at http://clojurescriptone.com/

0:59 mpan: thanks

0:59 SrPx: Can this be shorter? (defn pow [a b] (Math/pow a b))

1:00 akhudek: yes (Math/pow a b)

1:01 mpan: how is the presenter using the repl to change the browser state?

1:01 SrPx: akhudek: this is not the same

1:01 akhudek: I guess you want to pass it as a fn?

1:02 defining it the way you did is probably fine, could also do #(Math/pow %1 %2) for a one time use

1:03 technically (def pow #(Math/pow %1 %2) is shorter too, but I'd prefer your version for clarity

1:03 mpan: I think that repl runs in the browser

1:04 I haven't looked to much into clojurescriptone, so I'm not sure how much they get into interaction with a server backend

1:04 mpan: think it's part of the core of cljs though

1:05 think I see where they make the explicit connection, but still confused where what runs

1:05 akhudek: clojurescript runs in a browser, or some other javascript engine

1:06 it has a repl that is distinct from the repl that would run on a server

1:06 so you could actually envision both a server repl and a clojurescript repl running concurrently for dev purposes

1:06 mpan: they're starting a server from the js from the browser?

1:06 wait, how?

1:07 akhudek: I'm not sure there is a server in that clojurescriptone demo

1:07 it's been a while since I've looked at it

1:08 but you can do a browser repl like this: http://vimeo.com/29535884

1:10 SrPx: How to include [org.clojure/math.numeric-tower "0.0.1"] from repl?

1:10 akhudek: SrPx: you need to pull it in as a lein dependency first

1:11 mpan: get it in your classpath (preferably: use lein for dep resolution), then "use" or "require" statement

1:11 akhudek: then (use 'clojure.math.numeric-tower)

1:11 SrPx: okok got it

1:12 and sorry but I have been googling for too long and couldn't find the syntax for requiring something and bringing part of it to scope

1:12 mpan: have you got the jar already? (either directly or through lein)

1:12 SrPx: (require ['clojure.string [:refer upper-case]]) something like that

1:13 (require ['clojure.string :refer 'upper-case]) ?

1:15 mpan: https://gist.github.com/287710 this is a tutorial for use with the ns statement, but there are corresponding require and use standalone forms

1:15 SrPx: But i'm not using ns but (require)

1:15 mpan: http://clojure.org/cheatsheet the general cheatsheet has info on both

1:15 the remainder of the syntax is the same

1:15 SrPx: ok

1:15 thanks

1:16 mpan: (I think; I hope)

1:21 srpx: also, in most use-cases, it's preferable to have the require/use along with your ns statement, rather than standalone

1:24 SrPx: ns creates a namespace and uses it, right? mpan

1:25 so it is like a thing you call once?

1:25 I'm avoiding it because I do not understand. do I have to name it following some convention based on my files or something?

1:25 mpan: uh, usually it goes like this

1:25 you have separate namespaces, one per file, with corresponding names

1:26 the ns statement switches the currently-used namespace for evaluating stuff

1:26 so if you eval something, it's done so in a given namespace

1:26 so at the repl, you can use ns to switch to evaling stuff in the context of a different namespace

1:28 it covers both separating stuff into namespaces and bringing stuff in from them

1:29 SrPx: ok thank you mpan

1:29 mpan: you're always in some name space or another

1:29 and you could switch between them with ns calls

1:29 the reason for the naming convention and file structure is so that the runtime knows where to look when you want to bring something in

1:36 ori-l: mpan: that's really useful

2:26 ThorZaINtedwisp: ken_barber, do you play StarCraft?

2:26 Raynes: Minerals.

2:27 mpan: is it just me or are there disproportionately many starcraft fans here?

2:28 ThorZaINtedwisp: I noticed

2:28 Also, I got this schweet schweet 2rax reaper buold TvP where you pressure the front while loading a reaper behind their mineral line, god it's hard to deal with

2:29 It also gives you really quick stim and a quicker CC than if you keep making marauders

2:34 mpan: What are some use cases for metadata? Like, why would you choose it over putting fields directly into data?

2:34 ifesdjee_: mpan: first of, documentation, i'd say

2:35 mpan: you can also checkout robert-hooke for an interesting use-case for meta data

2:35 Raynes: mpan: For the most part, don't care.

2:35 Raynes: mpan: When you need metadata (which may never happen), you'll know exactly what it is for.

2:35 :D

2:35 You'll realize "oshi-, I could use metadata for this"

2:36 ifesdjee_: i'd say when something belongs strictly to the function, that should be metadata

2:36 you can't carry hash around with your fn otherwise

2:36 mpan: oh cool

2:36 thanks you all

3:06 ThorZaINtedwisp: Raynes, you play as well?

3:06 Raynes: Nope.

3:54 zoldar: /j #neo4j

4:11 ThorZaINtedwisp: zoldar, do you play StarCraft?

4:38 zoldar: ThorZaINtedwisp: Long time ago I've played some, but rather single player campaigns, multiplayer was too hardcore for me. Why do you ask?

5:35 mindbender1: I think it's particularly good that clojure gives us the choice of rememberiance or forgetfulness

6:04 marianoguerra: hi! I catched a ExceptionInfo exception, how do I access it's data?

6:04 google doesn't bring useful results :S

6:04 (new to clojure)

6:04 ordnungswidrig: marianoguerra: an exception or and exceptioninfo (what is that)?

6:05 marianoguerra: clojure.lang.ExceptionInfo

6:06 ordnungswidrig: huh, never heard of this :)

6:06 clgv: isnt that the one of slingshot?

6:06 ordnungswidrig: according to clojure.core doc you can access the data with (ex-data ei)

6:06 marianoguerra: (.getData error) does the tric

6:07 ordnungswidrig: yep, that works too, thanks!

6:07 ordnungswidrig: you should use ex-data to not rely on implementation details

6:08 clgv: when does clojure throw those?

6:09 ordnungswidrig: (throw (ex-info {:there "is" :more "info"}))

6:09 ah, no

6:09 (throw (ex-info "something weird happened" {:more :data}))

6:10 clgv: ah lol thats brand new

6:10 ordnungswidrig: (try (...) (catch ExceptionInfo e (prn (ex-data)))

6:10 clgv: at least the interface dates 7 days ago

6:11 ordnungswidrig: *g*

7:32 ThorZaINtedwisp: jcromartie, do you lpay StarCraft?

7:43 mindbender1: "A name is imposed on what is thought to be a thing or a state and this divides it from other things and other states. But when you pursue what lies behind the name, you find a greater and greater subtlety that has no divisions..." — Visuddhi Magga

8:39 Cheiron: Hi, is it possible to use Scala classes from Clojure code?

8:43 jsabeaudry: Cheiron, this seems to say yes: http://stackoverflow.com/questions/12053079/how-to-nicely-call-other-jvm-languages-from-clojure

8:45 Cheiron: jsabeaudry: CompilerException java.lang.IllegalArgumentException: No matching ctor found is not fun at all :(

8:45 jsabeaudry: Cheiron, is that following the example fromt he accepted answer in the SO question?

8:46 Cheiron: i have scala code compiled into a jar file under lib directory

8:47 i don't know if i have to supply type hints to scala functions

8:48 jsabeaudry: Can you try to instantiate another class of your lib that doesn't take any parameters?

8:49 Cheiron: will try

8:51 yes i can

8:52 jsabeaudry: Cheiron, great, then we know the problem

8:52 What parameters does your other class take?

8:52 Cheiron: other java.util.File, another Scala class type and java.lang.Double

8:53 Lajjla: Cheiron, do you play starcraft?

8:53 Cheiron: Lajjla: should i?

8:53 Lajjla: Not at all, just wondering.

8:54 Cheiron: Lajjla: :) no not really, i don't play sc

8:54 jsabeaudry: And how are you calling it?

8:54 Cheiron: (ScalaClass. file scala-instance double-value)

8:57 jsabeaudry: Cheiron, my guess is that one of these parameters does not have the type you think it has. But I have never done scala, much less clojure-scala interop

8:57 Cheiron: Ah, the scala class is declaring implicit after the constructor definition, is it matter?

9:01 jsabeaudry: This says you should pass the implicit parameter explicitely: http://stackoverflow.com/questions/7808821/java-calling-scala-case-class-w-implicit-parameter

9:04 Cheiron: jsabeaudry: true, will try it. thanks a lot !

9:14 jsabeaudry: true, it is working now, a lot of thanks :)

9:15 jsabeaudry: Cheiron, glad to hear it :)

10:00 casion: could someone assist me on why this code is not working on the xml file in the paste? https://www.refheap.com/paste/5353

10:06 abalone: casion: did you already try putting in the rest of the path to :MediaTrack ?

10:06 clgv: casion: "not working" is not precise. you should post an error description. if you want to have the content you have to zip/node

10:07 casion: clgv: I get nil returned

10:07 and no examples I've seen use zip/node… but I shall try

10:07 abalone: yes I have

10:07 clgv: zip/node is for getting the content

10:09 all zipper tutorial I read used zip/node

10:09 casion: but for that "nil" I guess something's wrong with the navigation path

10:11 casion: clgv: as far as I understand, xml1-> should be searching for a tag when I supply a keyword

10:11 along the whole tree

10:11 jkkramer: casion: If memory serves, (zf/xml1-> xmlzipper :Song :Attributes :List :MediaTrack) would be the right thing

10:12 plus zip/node if you want the actual node and not a zipper returned

10:12 clgv: casion: there is nothing about searching the whole tree in the docs

10:12 casion: jkkramer: that returns nil as well

10:14 clgv: casion: thats because your file has nodes with different types of children

10:14 casion: just build a navigation path analogue to jkkramer's

10:15 the first one in :Attributes causes the nil since there is no :List

10:16 casion: clgv: I don't understand that last line, why is there no :List in the first :Attributes?

10:17 if I do just (zf/xml1-> xmlzipper :Song), I still get nil

10:17 clgv: because of your file in the gist. have a closer look and try to navigate by hand

10:18 casion: oh, I see...

10:18 but I don't get why :Song doesn't return anything either

10:38 jonasen: cemerick: About your kibit issue. I'd like to attempt to make the necessary changes in cljx instead. Work started at https://github.com/lynaghk/cljx/commit/1bc64f2c8cbf690178b611e10b1776fcb996e225

10:41 cemerick: jonasen: I was thinking of that prior to filing the issue, but figured things like tagged literals would put it in kibit's scope.

10:41 I'm not sure how it could be done in cljx though, since it needs to be able to operate on top-levels.

10:48 abalone: casion: are you able to get what you want with zip/down zip/left zip/next and friends instead?

10:48 casion: abalone: yes

10:50 jonasen: cemerick: That might be the case... but first I'd like to figure out sjacket. What does reply use sjacket for?

10:51 cemerick: jonasen: determining whether the content entered into the REPL is a complete form or not prior to sending it to the remote REPL.

10:52 jonasen: cemerick: ok. I looked at the sjacket repo but found no docs or examples. Is the euroclojure video the best source to learn about sjacket?

10:52 abalone: casion: i looked at my old code which requires zip-filter and then doesn't use it :-P i guess whoever helps you will end up helping me too.

10:53 casion: abalone: you're the 3rd person in here to tell me that exact thing :(

10:53 cemerick: jonasen: At present, unfortunately. I'm currently pestering cgrand to make some headway on docs.

10:53 casion: "Here's some code where I use… wait, I didn't use it"

10:53 abalone: casion: whatever it is, it loves company

10:53 cemerick: FWIW, I've found it straightforward to use, YMMV.

10:54 jonasen: (BTW, the munge-forms API shouldn't need to change; note that cljx is useful with non-files, so taking a reader for input is far preferred.)

10:54 casion: abalone: how did you end up doing things instead?

10:55 and it in the previous statement being data.zip.xml

10:55 abalone: casion: i ended up frowning and using zip/next instead.

10:55 jonasen: cemerick: agreed, I'll change that

10:55 casion: abalone: you just walk the whole tree that way?

10:56 abalone: casion: i didn't "just" walk. i frowned as well.

10:56 cemerick: jonasen: Thanks; my next project out enables one to use cljx at the REPL.

10:56 casion: abalone: :( I shall alert you if I manage to figure this out then. I'm quite stubborn

10:57 I'll get it or give up on the project

10:57 the latter has yet to occur

10:57 abalone: casion: "hope is a dangerous thing" just kidding of course. thanks in advance. alert those other folks too. maybe they're frowning.

11:01 casion: do existing zip filter examples work?

11:01 casion: abalone: from what I've found on google, maybe half work… probably less than half

11:02 I'm not sure how much, if any, of that is the fault of zip-filter/data.zip.xml or the authors of said code

11:03 abalone: casion: oh. well if something works maybe you can slowly transform it into your example by steps

11:04 casion: abalone: I've been trying that, pulling directly from the data.zip.xml test cases

11:04 I wonder if it's just my xml files I'm working with

11:05 I think more likely that I'm an idiot and missing something

11:09 jcromartie: casion: what is your issue? I just did some XML stuff and played with the clojure.data.zip.xml

11:09 (navigating the libraries and namespaces was a bit confusing at first)

11:09 casion: jcromartie: https://www.refheap.com/paste/5353, I'm having trouble pulling anything from that xml

11:10 and yeah, I'm having troulbe with namespaces as well. For now I'm just :as silly-name to amuse myself in this time of frustration

11:10 jcromartie: casion: yeah that predicate won't do anything

11:10 you want the full path

11:10 this isn't path :)

11:10 casion: jcromartie: would simply :Song work? I though it would change it to (tag= :Song)

11:10 jcromartie: XPath

11:10 start from the beginning

11:11 casion: err, should :Song work. It's not

11:11 jcromartie: you don't have to specify the root element

11:11 sorry

11:11 casion: oh?

11:11 jcromartie: so (xml-> zipper :Attributes :List :MediaTrack)

11:12 or whatever

11:12 casion: oh, that works!

11:12 jcromartie: that will return all media tracks

11:12 casion: how would I deal with multiple roots?

11:12 jcromartie: casion: you shouldn't have multiple roots, that is not valid XML

11:12 casion: jcromartie: I thought so :| but I do

11:13 jcromartie: casion: if you want to deal with multiple <Song> elements then wrap them in a single root

11:13 <Songs><Song /><Song /><Song /></Songs>

11:13 or whatever

11:13 but you definitely need a single root

11:14 casion: jcromartie: ok

11:14 jcromartie: if someone else is giving you XML with multiple roots, ask them to fix it, and/or munge the doc until they do

11:15 casion: jcromartie: unfortunately they insist that it's valid. So I've taken the stance of just assuming it is (for reasons unknown)

11:15 I can wrap it though, no problem

11:15 jcromartie: you've been a massive help, thank you :)

11:16 hammer: ,(find-doc "clojurebot")

11:16 clojurebot: nil

11:16 hammer: hehe, you said

11:17 you said it*

11:17 jcromartie: casion: if they think multiple roots is valid, just direct them to any XML validator, or W3C http://www.w3.org/TR/REC-xml/

11:18 casion: jcromartie: will do, thank you

11:18 jcromartie: you can have multiple elements in a document but they won't be roots

11:20 jonasen: cemerick: I read the euroclojure slides for sjacket and found it really interesting! Do you know of any examples of a 'putback' function. I don't really know how i'd write one.

11:20 casion: they a have project.xml that can have multiple root <song>

11:20 and another workspace.xml which has (as far as I've seen) 6 levels of the same tag name

11:22 cemerick: jonasen: what would putback do?

11:25 jonasen: cemerick: page 41 in the slides. The previous step (i.e. Expr->Expr2) is _exactly_ what kibit is trying to do. 'putback' is the part you would need for cljx I think

11:32 TimMc: (inc hammer)

11:32 lazybot: ⇒ 1

11:33 TimMc: casion: This raises troubling questions about how *they* are parsing the XML.

11:33 My guess: Regular expressions. -.-

11:35 hammer: TimMc: what's that mean? you incremented me?

11:35 casion: TimMc: the authors have an open source project that's a precursor to this propietary one that uses some crazy Boost property tree stuff

11:35 jsabeaudry: hammer, that is love

11:36 casion: I don't know how it's done in the current software I'm working with (or against maybe more appropriate)

11:37 and oddly enough, the software is the most stable and robust in its class

11:37 TimMc: hammer: It's a karma plugin on lazybot.

11:38 casion: the best part is that after parsing all these xml files, I have to rebuild it into something the software will accept

11:38 cemerick: jonasen: Yeah, I don't grok that yet either.

11:47 alpheus: Is there a function that returns attributes of a file, link count, in particular?

11:53 hammer: i want to run clojurebot on my own IRC server, but I'm stumped

12:02 dhofstet: alpheus: there is afaik no such function in clojure, but have a look at the readAttributes() method of the Files class: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html

12:09 antoineB: hello, assuming i want only use global vars through "binding" macro is there something special to do? (def ^:dynamic my-var) can be changed for instance

12:10 jcromartie: antoineB: that's it

12:11 antoineB: also understand that vars are thread-local bindings, too

12:11 with (binding [*foo* bar] …)

12:12 antoineB: ok

12:13 Amaryl: Hello, I have just begun to learn Clojure, and I have a stupid question. Could sb tell me the difference between (defn f[] (let [a 1 b 2] (println a b))) AND (defn f[] (def a 1) (def b 2) (println a b))

12:14 hiredman: let creates local bindings of names to values, def creates a global var

12:14 jcromartie: "global" var

12:15 (binding …) creates a thread-local reassignment, (set! …) changes the global value

12:15 antoineB: (def a something-new) work also?

12:15 Amaryl: that's what I understand, but when I execute the code in the online interpeter -> http://tryclj.com/ I can't access "a" and "b" outside the function in either case

12:15 jcromartie: oh sorry, confusing antoineB and Amaryl's questions :)

12:15 Amaryl: "let" creates local bindings

12:15 rlb: hiredman: yeah, coming from scheme, it took me a minute to realize that it wasn't doing what I thought it might be doing.

12:16 jcromartie: they are not available outside

12:16 rlb: (in scheme internal defines are more or less like let)

12:16 jcromartie: antoineB: what are you trying to do? what's in your global var?

12:17 antoineB: my gloabls var are just name (they don't carry anything outside binding macro)

12:18 jcromartie: Amaryl: the "def" inside a fn in tryclj.com is not behaving like it usually would, because tryclj is doing some sandboxing

12:18 antoineB: what's the purpose of them

12:19 antoineB: what I'm getting at is, are vars and bindings really the way to go here or do you want a ref or something else

12:20 Amaryl: tanks jcromartie , let's install Coljure on my computer then :)

12:20 jcromartie: Amaryl: yeah! Leiningen is the easiest way to run Clojure, and it's in many package managers now

12:20 shaungilchrist: what is the site which listed all the various clojure libs grouped by problem space?

12:21 antoineB: i think binding is the way to go

12:21 jcromartie: antoineB: so, one more time: what are the vars actually for?

12:21 alpheus: dhofstet: readAttributes should do it. Thanks.

12:21 jcromartie: antoineB: what does it represent?

12:21 antoineB: global state

12:24 jcromartie: antoineB: WHAT. ARE. THEY. FOR.

12:25 antoineB: current user? database connection? favorite flavor of ice cream? latest cat videos?

12:25 what?

12:25 clojurebot: what is wrong with you

12:25 antoineB: opengl state

12:25 jcromartie: thanks for the reality check, clojurebot

12:25 hammer: lol

12:25 antoineB: relax jcromartie

12:37 devth: is there a more concise way to retrieve the 2nd-to-last el? (last (butlast (range 10)))

12:39 technomancy: devth: there's a patch to do that concisely, but it was rejected because it was "goofy"

12:40 devth: technomancy: ah ok

12:40 scriptor: (last (drop-last (range 10))) would only go through the collection once

12:41 devth: oh, right

12:41 hiredman: butlast is just as lazy as drop-last

12:41 scriptor: it's implemented with loop/recur

12:42 hiredman: fuh

12:43 was that always like that?

13:04 loliveira: byte_bucket: hi, i discovered what was happening.

13:18 TimMc: jcromartie: I chose to interpret clojurebot as addressing antoineB, actually.

13:20 augustl: is it safe to intern user input to keywords? The Ruby equivalent, symbols, never gets garbage collected, so that's not safe. Is Clojure keywords similar to Ruby symbols, or are Clojure keywords garbage collected?

13:20 technomancy: augustl: since 1.3 they're GC'd

13:20 augustl: nice, thanks

13:21 technomancy: or possibly 1.2.1?

13:21 augustl: cheshire defaults to strings as keys, while my mongodb lib gives me keywords as keys, kind of cumbersome

13:22 dakrone: augustl: you can easily change cheshire to return keys as keywords

13:22 augustl: dakrone: goodie, then I'll do that

13:23 kind of expected cheshire to support that, especially since creating arbitrary keywords from user input run-time is safe

13:23 dakrone: augustl: it just doesn't by default to ensure it can be as fast as possible

13:24 augustl: ah, so it will create strings first anyway?

13:25 dakrone: well, keywords need to be created out of something in any case, and the string already exists because it's part of the json, are you concerned about the performance, or memory?

13:26 augustl: dakrone: consistency is the most important thing right now

13:27 dakrone: then you should be able to have it return keys as keywords and not worry about it

13:27 augustl: keywords are nice anyways, for (:foo bar) type access

13:28 and since I'll probably use records in the future

13:29 thorbjornDX: is this a good way to get each element of a sequence and the one that came before it? (partition 2 (interleave myseq (rest myseq)))

13:29 it seems like I would be doing twice the work

13:29 augustl: thorbjornDX: sounds like reduce would work

13:31 kensho: Hi. I'm working with swing and I wrote a macro to make sure that code gets only executed on the EDT, like (edt! (whatever) (foobar)). This works nicely but I would like to introduce a way to turn that off globally, so that if the setting is false the macro doesn't introduce this check. I thought this would be possible with dynamic vars but I can't get it to work. I'm probably misunderstanding their purpose. I thought I could do (def

13:31 ^:dynamic *force-edt* false) and then enable it with (set! *force-edt* true) but this always results in an error saying that the root binding can't be changed. I'm probably doing it wrong. What is the best way to achieve this kind of global setting (which is only supposed to be changed for dev ppurposes)?

13:34 jsabeaudry: kensho, perhaps an atom

13:34 I'm mostly a clojure noob so take that with a grain of salt

13:36 augustl: kensho: perhaps you should provide a function to set it anyway, so the actual thing you use to store the global setting is private

13:36 technomancy: use an atom if you can. if it won't change at runtime you can use alter-var-root, but it's a bit messier

13:36 augustl: </randomthought>

13:36 jcromartie: kensho: the issue is the thread-local binding of vars

13:36 kensho: never mind I think you've figured it out

13:37 kensho: ok thank you, I will use an atom then.

13:39 mefesto: I'm having trouble using lein-ring and stencil. Seems my views will not refresh unless I restart the ring server. Does anyone know what I could do to fix this?

13:45 augustl: mefesto: there's a known issue with lein ring and reloading in general, not sure if it's fixed, and not sure if there's another stencil specific issue around..

13:47 technomancy: mefesto: auto-reload heuristics are virtually impossible to get right

13:47 much better to reload from within your editor

13:48 mefesto: i think the issue im having is that stencil is caching the views but it's not clear to me how to disable view caching for development

13:49 all of my other code seems to be properly reloaded by lein-ring

13:52 augustl: will a lazy list "cache" its results if it's iterated multiple times? Guess not.

13:52 lazy sequence*

13:52 TimMc: augustl: It's not caching, it's realization.

13:53 augustl: (map println (range 60)) will only execute println once for each element of the input, no matter how many times you walk it.

13:53 augustl: calling (remove nil? ...) on a list. First going to count it, then if it contains more than 0 items, I'll do something with the list. Wondering if a count and later an iteration will "realize" the lazy sequence twice

13:53 thorbjornDX: augustl: here's what I came up with: ##(reduce (fn [s b] (conj s [(second (first s)) b])) '() (range 6))

13:53 lazybot: ⇒ ([4 5] [3 4] [2 3] [1 2] [0 1] [nil 0])

13:53 augustl: thorbjornDX: you can also give it an initial value of (first coll) and then reduce (rest coll) to avoid the nil

13:54 thorbjornDX: in other words, reduce takes an initial value as well as a list

13:54 TimMc: augustl: (map inc (range)) looks like this in memory: (... magic!)

13:54 augustl: TimMc: wut :)

13:54 TimMc: augustl: If you then (dorun (take 4 that-lazy-seq)), it looks like this: (1 2 3 4 ... magic!)

13:54 jsabeaudry: ,(println (... magic!))

13:55 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: magic! in this context, compiling:(NO_SOURCE_PATH:0)>

13:55 TimMc: augustl: It's only when you try to descend into the magic! bit that realization occurs, producing more cons cells.

13:55 Walking those cons cells again doesn't do anything.

13:56 It's like a magician pulling scarves out of thin air -- once they're out, they're out.

13:56 augustl: TimMc: neat :)

13:56 TimMc: Go read LazySeq.java, you'll see how it works.

13:57 augustl: TimMc: I'll do that, tnx :)

13:58 thorbjornDX: augustl: I guess I'm confused how to start off my reduce with a seq of a single vector. In my case, I can't just use first/rest when initializing it

14:00 augustl: thorbjornDX: what exactly are you trying to do?

14:01 ##(+ 1 2)

14:01 lazybot: ⇒ 3

14:01 augustl: ##(let [my-coll (range 6)] (reduce (fn [prev curr] (conj prev curr)) [(first my-coll)] (rest my-coll)))

14:01 lazybot: ⇒ [0 1 2 3 4 5]

14:01 augustl: thorbjornDX: ^^

14:02 quite silly though so I guess that's not what you're doing ;)

14:02 thorbjornDX: augustl: see lazybot's response above, I just want to get pairs of items from a seq, so [0 1 2 3] -> ([0 1] [1 2] [2 3])

14:03 jkkramer: ,(partition 2 1 [0 1 2 3])

14:03 clojurebot: ((0 1) (1 2) (2 3))

14:04 thorbjornDX: jkkramer: ah, I think that's it :) thanks

14:05 augustl: is there a deep merge of maps+sequences around?

14:12 TimMc: augustl: I think merges are hard to make semantically generic.

14:13 augustl: TimMc: makes sense, I don't need a generic merge anyway, the data I need to merge has a very specific structure

14:14 TimMc: Judicious application of merge-with and some custom fns would probably suffice.

14:15 augustl: is this a sensible way of "consuming" a sequence btw? I've ended up having a few of these in my code. https://www.refheap.com/paste/5355

14:16 the idea is that merge-error updates the result (performs the merge)

14:16 TimMc: Looks like you want a reduce.

14:16 hiredman: agumonkey: I would twiddle the argument order, sequences generally go last

14:16 augustl: hiredman: the idea is that the "result" is optional though

14:16 so you can jsut do (merge-errors errs)

14:17 hiredman: augustl: *shrug*

14:17 TimMc: augustl: (reduce merge-error result errors), where merge-error takes [result error] instead of [error result].

14:17 augustl: hmm

14:17 TimMc: ...for the binary form of merge-errors.

14:17 augustl: TimMc: will look into that, thanks

14:19 TimMc: (reduce merge-error (first errors) (rest errors)) :)

14:19 TimMc: noooo

14:19 augustl: hmm, why not?

14:20 "errors" is a list of maps, and it needs to be able to merge the first with the second

14:20 so it seems like one less operation to me

14:20 TimMc: Isn't a result different from an error?

14:20 augustl: perhaps result is a bad name. I'm merging a bunch of error maps, the result is the merge

14:21 TimMc: So merge-error takes [A A -> A]?

14:22 augustl: TimMc: yes (if I'm reading that correctly)

14:22 TimMc: OK. So the input is a list of errors, and the output is an error.

14:22 (for merge-errors, plural)

14:23 Anyway, "one less operation" is a bad reason to make code harder to reason about.

14:23 augustl: TimMc: true that

14:23 which one do you like best, now that you know more about what I'm trying to do?

14:25 TimMc: augustl: https://www.refheap.com/paste/5356

14:26 And if you really want performance, use the reducers lib -- you've got an associative reduction, so you can parallelize it.

14:26 augustl: not on 1.5 yet :)

14:26 ah, no need for an initial when it's the same collection, doh

14:27 TimMc: And reduce will handle the 0 and 1 corner cases for you.

14:27 thorbjornDX: man, code can be so cool. My code isn't :p

14:27 *yet

14:30 hiredman: /win 11

14:31 jcromartie: parallel reducers!

14:31 augustl: that was fun :D https://www.refheap.com/paste/5357

14:34 jcromartie: I don't really understand what Noir adds over just using Compojure

14:35 augustl: jcromartie: I'm using compojure, mostly because I didn't like (read: hated) the way Noir used thread local stuff for cookies etc

14:35 something as FP friendly as a web request/response cycle is best off written in a functional style if you ask me..

14:35 jcromartie: I think my first issue right off the bat is that (defpage …) doesn't give me a var in that namespace

14:36 it's just magic

14:36 augustl: jcromartie: indeed, I had that issue too :)

14:36 jcromartie: then I wanted to write a (defpage my-page-list ...), then I realized compojure is exactly what I want

14:36 jcromartie: no offense … obviously people are building sites with it

14:36 I'm trying to figure out how to add Swagger docs to Compojure routes now

14:37 augustl: jcromartie: i also use compojure.core/routes a lot

14:37 instead of defroutes

14:37 jcromartie: yeah

14:37 augustl: I prefer to just work with a set of handler functions

14:37 jcromartie: yeah, I tend to actually use the handers directly during development

14:37 to test/debug

14:38 or just explore

14:38 augustl: I also have a om nom system with a function that creates new handler functions with a specific environment/config

14:38 no singletons, yay

14:39 the config is made available in the request, as :config

14:43 jcromartie: I'm not sure how to approach the documentation thing

14:43 thorbjornDX: what's wrong with #({:key1 % :key2 %2}) ?

14:43 jcromartie: should I use metadata on handler vars?

14:43 thorbjornDX: it tries to call the map

14:44 augustl: thorbjornDX: #() assumes you want to call a function

14:44 jcromartie: ,#(+ 1 2)

14:44 clojurebot: #<sandbox\$eval27\$fn__28 sandbox\$eval27\$fn__28@5c6ad9e9>

14:44 jcromartie: err

14:44 thorbjornDX: jcromartie: ah, so I should use hash-map or something instead?

14:44 jcromartie: thorbjornDX: sure

14:44 thorbjornDX: ,(#(+ 1 2))

14:44 clojurebot: 3

14:44 augustl: thorbjornDX: if you just want to return a map you should use (fn [a b] {:key1 a :key2 b})

14:44 ..afaik

14:44 jcromartie: thorbjornDX: or use (fn [x y] {:foo x :bar y})

14:45 thorbjornDX: augustl: ah, okay. That's what I thought it would shortcut to, guess not

14:45 jcromartie: either way

14:45 hiredman: ,(macroexpand '#(x))

14:45 clojurebot: (fn* [] (x))

14:45 hiredman: ,'#(x)

14:45 clojurebot: (fn* [] (x))

14:45 jcromartie: ooh, very enlightening

14:45 hiredman: ,(macroexpand '#({:a 1 :b 2}))

14:45 clojurebot: (fn* [] ({:a 1, :b 2}))

14:46 jcromartie: ,'#(inc %)

14:46 clojurebot: (fn* [p1__161#] (inc p1__161#))

14:46 thorbjornDX: ,(macroexpand '#({:a % :b %2}))

14:46 clojurebot: (fn* [p1__188# p2__189#] ({:a p1__188#, :b p2__189#}))

14:46 jcromartie: and now we know

14:46 clojurebot: I love you

14:46 clojurebot: No entiendo

14:46 jcromartie: love is hard to understand

14:47 thorbjornDX: clojurebot: yo te amo

14:47 clojurebot: paste is not gist.github.com

14:47 hiredman: ~botsnack

14:47 clojurebot: thanks; that was delicious. (nom nom nom)

14:48 augustl: is there a way to turn :foo into "foo"?

14:48 aperiodic: ,(name :foo)

14:48 augustl: not ":foo", that's what str seems to do

14:48 clojurebot: "foo"

14:49 augustl: aperiodic: tnx

14:58 what's a good way to get the first item in a sequence that matches a predicate?

14:58 (first (filter pred coll)) comes to mind

14:59 aperiodic: ,(doc some)

14:59 clojurebot: "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

14:59 augustl: aperiodic: thanks

14:59 (inc aperiodic)

14:59 lazybot: ⇒ 2

14:59 aperiodic: de nada

15:00 hiredman: some may or may not work, depending on your predicate

15:00 it returns the value of the "predicate"

15:00 augustl: my predicate will return null or a map, so that should work me thinks

15:05 TimMc: Raynes: I tweaked refheap so I can run an internal pastebin where I work. :-)

15:05 aperiodic: augustl: as long as it returns the map you want

15:05 augustl: aperiodic: yeah it does, seems to work just fine

15:07 mpenet: ibdknox: ping

15:21 Raynes: TimMc: Cool!

15:31 casion: is there a better way to do something like (apply xml-> `(~zipper ~@path ~(attr :name)))

15:31 it works, but it just seems wrong

15:34 emezeske: casion: I think this does the same thing? (apply xml-> zipper (concat path [(attr :name)]))

15:34 casion: If you know path is a vector, you could conj (attr :name) onto it

15:35 casion: emezeske: it tries to treat the zipper as an arglist then

15:35 emezeske: An arglist?

15:36 ohpauleez: emezeske: Quick question - have you successfully used cljsbuild for node targets? If not, what needs to be done/where should I start looking (more than happy to patch whatever)?

15:36 casion: emezeske: a list of arguments, e.g. it applies each element of the zipper rather than passing the zipper

15:37 hiredman: casion: apply only treats the last arg like that

15:37 emezeske: casion: Huh? Only the last argument to apply gets expanded into arguments

15:37 casion: ...

15:38 emezeske: ohpauleez: I don't use node.js myself. I don't think there's anything about lein-cljsbuild that would prohibit it, though.

15:38 ohpauleez: lein-cljsbuild basically just passes options to the ClojureScript compiler

15:38 ohpauleez: So if you can make it work with just the ClojureScript compiler, you should be able to use lein-cljsbuild

15:39 ohpauleez: There's no REPL support for node.js in lein-cljsbuild though

15:39 casion: emezeske: well that works

15:39 emezeske: Good deal.

15:39 casion: I wonder what I did to make it not work now :|

15:40 since that was the first thing I tried, I thought

15:40 ohpauleez: emezeske: Gotcha - thanks. I'm running into some issues, just wanted to see if there was anything hidden specific to node. (I'm seeing how viable it is to script in CLJS)

15:41 emezeske: ohpauleez: Feel free to open issues if you do run into lein-cljsbuild-specific problems.

15:41 ohpauleez: will do - patches attached ;0

15:41 ;)

15:41 thanks

15:42 emezeske: Great!

15:44 augustl: is there a function that checks if something is any kind of list/collection except a map?

15:44 casion: I had that exact code in earlier, and it was giving an error :(

15:44 and I've since cleared the repl

15:45 augustl: sequential? seems to be what I want

15:45 aperiodic: augustl: regarding collection attributes, http://www.brainonfire.net/files/seqs-and-colls/main.html is worth a read

15:46 augustl: aperiodic: nice, thanks

15:46 aperiodic: (inc TimMc)

15:46 lazybot: ⇒ 17

15:46 augustl: (inc aperiodic)

15:46 lazybot: ⇒ 3

15:47 augustl: you're catching up :)

15:58 TimMc: It's been a while since the karma counters were reset. :-P

15:58 mefesto: with refheap, is it possible to create a paste with multiple files of different content types?

16:00 Raynes: mefesto: No. That's on purpose. I plan to implement something that will serve the same practical purpose without being pointlessly attached to 'files'.

16:00 But you can't do that at all right now.

16:01 mefesto: Raynes: how's mongo db working out for this project?

16:01 Raynes: Delightfully.

16:08 jcromartie: Raynes: I don't believe you. Everybody hates Mongo now.

16:14 thorbjornDX: jcromartie: I like mongo, I use their mug every day!

16:15 dansalmo: is there a way to remove an item in a nested structure by type such that (1 2 (3 [4])) becomes (1 2 (3))?

16:15 it seems easy to replace, but not remove

16:16 I have tried postwalk

16:16 juhu_chapa: dissoc-in

16:19 dansalmo: I think dissoc-in only works for associative structures

16:19 :juhu_chapa I think dissoc-in only works for associative structures

16:19 juhu_chapa: I think dissoc-in only works for associative structures

16:20 augustl: are there any good collection types, other than maps, for lists with holes in it? currently doing something like {0 "abc" 6 "def"}

16:21 actual reason for asking: need to be able to detect different data types so I can separate "lists with holes in them" from normal maps

16:23 emezeske: augustl: Can you maybe do something like: (assoc {0 "abc" 6 "def"} :my-type :list-with-holes)

16:24 augustl: And then inspect (:my-type some-map) to see if it's a :list-with-holes?

16:24 Raynes: jcromartie: Yeah, I just don't care.

16:24 If and when it breaks, I'll switch to something else.

16:24 jcromartie: :)

16:24 augustl: emezeske: that probably makes sense yeah

16:25 Raynes: They can all kiss the back of my hand.

16:25 * Raynes dons his shades.

16:25 augustl: emezeske: then I can post-walk it to remove the type references, for serialization

16:25 emezeske: augustl: You can use multimethods to dispatch on that :my-type entry, too, which can be convenient

16:25 TimMc: metadata! :-D

16:26 &(meta (empty (with-meta [1 2 3] {:a 5})))

16:26 lazybot: ⇒ {:a 5}

16:26 TimMc: Ooh, good to know that works.

16:28 thorbjornDX: TimMc: does empty just clear out the collection, but preserve the meta-data then?

16:29 TimMc: Yeah, it gives you an empty collection of the same type. I wasn't sur eabout the metadata.

16:29 Vrey handy for certain generic collection-munging fns.

16:30 augustl: what's "reduce1"? It's used in the implementation of merge-with

16:30 thorbjornDX: I have to play around w/ meta-data, right now I can only think of using it where I might otherwise use another key/val in a map, but that's just obfuscating things imo

16:32 TimMc: augustl: Is it private to clojure.core?

16:33 tbaldridge: agustl: reduce1, into1, etc. are used internally by clojure until it's able to bootstrap itself enough to create the normal reduce/into

16:34 patchwork: Has anyone used clojure.core.cache?

16:34 TimMc: Didn't it used to jut overwrite the def of reduce?

16:34 augustl: TimMc: hmm, perhaps

16:34 patchwork: I notice it is also immutable so do I need to put it behind a ref?

16:34 augustl: tbaldridge: ah

16:34 patchwork: I worry about putting a cache behind a ref because I would be making so many updates to it

16:34 or is that the accepted usage pattern?

16:35 TimMc: patchwork: more likely behind an atom

16:35 tbaldridge: augustl: the full blown reduce checks the collection to see if it implements "fast-path" protocols. If the right protocols are implemented then it skips making a seq out of the collection.

16:36 patchwork: TimMc: Aha, I haven't used atoms much. Do I still update them with dosync, or is there something more efficient?

16:36 just wanting to make sure I am doing the most efficient thing (as the whole point of using a cache is efficiency!)

16:37 emezeske: patchwork: Atoms are updated with (swap! ...)

16:37 dansalmo: (clojure.walk/postwalk #(if (vector? %) nil %) '(1 [2] 3 (4 [5] 6)))

16:38 cemerick: emezeske: it looks like cljsbuild does not support multiple source paths; do you know of a suggested way to make this jibe with cljs generated by cljx?

16:38 patchwork: emezeske: Aha! thanks

16:38 dansalmo: ,(clojure.walk/postwalk #(if (vector? %) nil %) '(1 [2] 3 (4 [5] 6)))

16:38 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: java.lang.ClassNotFoundException: clojure.walk>

16:38 cemerick: (short of crazy ignores and such…)

16:38 TimMc: patchwork: Atoms are used for uncoordinated updates, whereas refs are used for coordinated updates. Atoms are lower overhead.

16:38 emezeske: cemerick: I haven't really used cljx; what kind of output does it produce?

16:38 TimMc: ANd yeah, no dosyncrequired.

16:39 patchwork: TimMc: Perfect, exactly what I was looking for, thanks!

16:39 cemerick: emezeske: cljs files into a specified directory. The best I can think of at the moment is copying my regular cljs source dir's contents into the generated dir targetd by cljx, but that's a PITA.

16:39 dansalmo: how can I remove the vectors instead of just replacing them? (clojure.walk/postwalk #(if (vector? %) nil %) '(1 [2] 3 (4 [5] 6)))

16:40 emezeske: cemerick: If you have multiple :builds, they are all put on the classpath (and can thus access one another)

16:40 dansalmo: seems to not be a remove function for nested vectors or lists

16:40 emezeske: cemerick: Maybe have :builds {:cljx {...} :prod {...}} ?

16:41 cemerick: Then :prod would see the sources from :cljx on the classpath.

16:42 cemerick: emezeske: oh, nm, I can just have cljx build into the :crossover-path; that's always included in the build, right?

16:43 emezeske: cemerick: I believe so.

16:43 cemerick: Sounds like a winner.

16:44 emezeske: cemerick: The only hesitation I'd have is that the :crossover-path can be deleted whenever lein-cljsbuild feels like it

16:44 cemerick: Duct tape FTW!

16:44 emezeske: cemerick: Although I think it's only deleted on clean, in reality.

16:45 cemerick: Right; maybe I can hook the cljx process to always run before whatever gets triggered w/ cljsbuild auto…

16:45 jcromartie: what happened to visualvm on OS X?

16:45 cemerick: jcromartie: should be jvisualvm on your PATH

16:45 jcromartie: ah

16:45 there it is

16:45 tanks

16:45 (planes, boats, etc.)

16:46 cemerick: emezeske: I've been tinkering with cljx, and it would seem to be a good alternative to the crazytime that are crossovers ;-)

16:48 emezeske: cemerick: It's definitely less of a hack

16:48 cemerick: I don't like either option though, personally

16:49 cemerick: Yeah, it's all matters of degree at the moment.

16:49 emezeske: The fundamental problem IMHO is the stupid :use-macros and :require-macros things

16:49 cemerick: Those are the smallest problems IMO.

16:50 emezeske: I don't see any other problems really

16:50 Put the platform-specific stuff in separate namespaces

16:50 And make sure the right platform-specific version is loaded

16:50 Done.

16:51 cemerick: Things like error handling can't really be split out.

16:52 emezeske: Sure it can. Move the error handling code to a platform-specific namespace, factor out any neutral code, and implement in terms of that

16:52 cemerick: hrmph.

16:53 Being able to write a catch clause or throw an exception reasonably without such gymnastics is nice.

16:53 emezeske: I mean, for better or worse, error handling is platform-specific

16:53 I agree, but clj/cljs punt error handling to the platform :/

16:54 cemerick: Which is fine at this point. Sorta. I have a cljx rule that swaps JVM exception classes for js/Error.

16:55 emezeske: Gnarly!

16:56 cemerick: error handling is always going to be hosty. Maybe libraries can make up the middle ground eventually...

16:56 emezeske: hah, is that a good or bad thing? :-P

16:56 emezeske: Yeah, a cross-platform slingshot would be pretty sweet

16:56 cemerick: Both :)

16:57 cemerick: Righteous.

16:58 thorbjornDX: is (map (partial apply (fn [a b c])) myseq) pretty common practice?

16:59 cemerick: Still searching for a name for an nREPL middleware for cljx though. Nominations welcome. :-D

16:59 technomancy: thorbjornDX: if you have to do anything fancy in a map function it's better to use for

17:00 thorbjornDX: technomancy: I'm just using map destructuring to extract an item and then filter by it (not map actually)

17:00 S11001001: thorbjornDX: comp is cool for that kind of thing

17:01 thorbjornDX: (filter (partial apply (fn [{a :a} b c & s] (a > 3)) myseq)

17:01 cemerick: dnolen: I wonder how many tweets @dnolen on twitter gets that are just absolutely incomprehensible to him. ;-)

17:01 thorbjornDX: S11001001: so I would comp my 'extraction' and 'check-value' function and map that to the outer sequence?

17:03 Bronsa: thorbjornDX: (> a 3)

17:03 thorbjornDX: Bronsa: thanks, typo

17:03 S11001001: thorbjornDX: say you want all xs for which :score is positive: (filter (comp pos? :score) xs)

17:04 thorbjornDX: S11001001: that's fine, but I have a seq of seqs, ##(partition 2 1 (range 6))

17:04 lazybot: ⇒ ((0 1) (1 2) (2 3) (3 4) (4 5))

17:04 Raynes: TimMc: What did you need to change to get it running internally?

17:05 TimMc: If you generalized things to make it easier to change hostname and such, I'd accept that patch.

17:05 thorbjornDX: so would I just use (filter (comp pos? first :mykey) myseq)?

17:05 Raynes: I tried to make it possible to run refheap without calling it refheap, but I'll be damned if I know whether it actually can or not. :p

17:05 S11001001: thorbjornDX: put first last, but that's the idea

17:06 thorbjornDX: S11001001: my data structure is a bit different than that example: '(({:a 1 :b 2} {:a 2 :b 3}) ...)

17:06 dnolen: cemerick: heh, are you referring to something specific?

17:07 S11001001: thorbjornDX: remember that some, in a sense, is a function that converts a question about one thing to a question about whether that thing exists in a seq of things

17:08 thorbjornDX: the general pattern remains the same: (comp real-predicate extractor)

17:12 TimMc: Raynes: Alas, I just rampaged through the code and changed shit.

17:13 ripped out browserid, put a note at the top of the About page, changed the default language to Java (the main lang here), changed the title...

17:14 Raynes: Cool

17:28 thorbjornDX: S11001001: thanks for your advice. I have to use comp (and :keywords) more :)

17:28 jballanc: I feel like an idiot...how do I resolve a var?

17:28 octagon: hi, can anyone suggest a good reference for compiler design that would help me understand exactly what's going on in the clj and cljs compilers? I've read lots of things about interpreters and understand that pretty well, but for some reason the jump to compilation is giving me a lot of trouble

17:29 jballanc: so: (def foo "bar") ((fn [var] (println ...do-something-here...)) #'bar)

17:29 whoops...that should be #'foo

17:29 how do I make that print "bar"?

17:30 jkkramer: jballanc: @var. i.e., (deref var)

17:30 jballanc: damnit...I knew it was something stupid

17:30 I kept thinking ref/deref and var/?

17:31 jkkramer: there's also var-get, which does the same thing

17:31 jballanc: octagon: This is considered the gold standard text, I believe -- http://www.amazon.com/Compilers-Principles-Techniques-Tools-2nd/dp/0321486811

17:31 at least, enough so that the LLVM team choose a dragon as their mascot based on it

17:32 octagon: jballanc: thanks! my specific interest is in how the compiler was designed to take advantage of the underlying type system and other machinery already existing in JS and the JVM

17:33 jballanc: the dragon book is concerned with mostly lower level stuff, right?

17:34 jballanc: yeah, that's probably a bit more theoretical than you're looking for

17:41 dnolen: octagon: I also just recommend reading the CLJS compiler, it's not that big - ~1000 lines for the analyzer and ~800 lines for the compiler

17:42 octagon: dnolen: that's basically what i've been doing, and experimenting a bit. the frustrating part is that my interpreter that i built has an analysis phase that is aaaalmost compilation, but there is some maddening little key thing i'm missing

17:44 cemerick: dnolen: oh, I msg'd @dnolen and Brenton last night, and he replied to me and him

17:45 dnolen: cemerick: oh hah

17:45 octagon: can you be more specific?

17:48 octagon: dnolen: i have an interpreter for a lisplike language that runs in cljs. i'd prefer to compile to cljs instead, for performance reasons. my interpreter already has an analysis phase that compiles the syntactic analysis into a cljs function, also expanding macros and whatnot. so i feel like i'm very close, but moving from an interpreter that has a separate analysis phase to a compiler is giving me trouble.

17:51 jcromartie: is there any reason not for using "let" around "def"? like (let [nf (NumberFormatter/getInstance)] (defn parse-num [x] (.parse nf (str x))))

17:52 emezeske: jcromartie: There's no compelling reason to avoid judicious use of that

17:54 dnolen: octagon: that's pretty meta - interpreted lisp -> cljs -> js

17:54 cemerick: jcromartie: Closures are useful. Also, http://letoverlambda.com (warning, Common Lisp ;-)

17:54 eggsby: the author of let over lambda is pretty... opinionated

17:55 octagon: dnolen: it's worth using cljs if only for the persistent immutable data structures. it's hard to get that right when copying is expensive. my first iteration was in pure js and it had problems with that.

17:55 jcromartie: eggsby: indeed… "the most advanced language: COMMON LISP"

17:56 dnolen: octagon: right, I'm fighting mutable JS atm myself

17:56 eggsby: I'm trying to work my way through 'Lisp in Small Pieces'

17:56 it had the best name of the lisp books

17:57 octagon: dnolen: i ended up defensively copying a lot of data that probably didn't need to be. most of the time the thing was copying data instead of doing work

18:03 ohpauleez: dnolen: Thanks for pointing me to those tickets. I'll take a stab at them this weekend (working on CLJS CLI apps right now - interesting to tackle)

18:03 dnolen: ohpauleez: oh cool, thanks!

18:04 ohpauleez: if you do the unrolling bit I can probably look into the compiler part, just need to add some logic to the invoke case

18:04 augustl: hml, monger (the mongodb library) has keywords for keys on documents, but not for nested objects, they have strings as keys

18:04 dnolen: in the compiler

18:04 ohpauleez: dnolen: Cool, sounds good

18:33 TimMc: Starting a new thread -- is it weird to use future for that, given that I will never dereference it?

18:35 ohpauleez: TimMc: I missed the first part of that, but are you using futures just to send stuff to the background?

18:39 TimMc: Yeah.

18:40 ohpauleez: TimMc: I do that often. It's also popular, if you need more control over how things get background, you create your own executor pool

18:46 TimMc: I'm so excited, I'm actually getting to do concurrency stuff.

18:47 I finally get to use all these delicious primitives.

18:50 ohpauleez: TimMc: The future is wild

18:52 TimMc: :-P

19:32 jondot`: have a potentially boring question, looking at the language shootout, I see that clojure code is in most cases similar to java in size, and double that of ruby. from my personal experience, clojure gets me an insanely small LOC (less than my ruby code) - why would that be?

19:34 technomancy: jondot`: because the language shootout doesn't reflect real-world code

19:35 dnolen: jondot`: shoot out code is low level, also many of them are not that well written to take advantage of better ways to write that kind of kind post 1.3.0

19:35 jondot`: i just read that they measure code size in compressed gzip size and not LOC. wondering abotu that

19:35 i'm wondering if that means that clojure code doesnt compress as well as java's

19:35 technomancy: clojure allows you to drop to really low-level code if you need speed at the expense of readability; ruby does not.

19:37 jondot`: technomancy: yes, i saw that in the best case, clojure is x18 times JRuby. since both are on JVM and both dynamic - how could that be?

19:37 is it because clojure uses methodhandle and JRuby don't?

19:37 technomancy: could be a lot of reasons

19:37 dnolen: jondot`: big reason - Clojure's design takes performance seriously in a way Ruby never did.

19:37 technomancy: maybe no jruby fans care about the language shootout

19:37 hiredman: clojure is not constrained by trying to backwards compatible with cruby

19:37 jondot`: i didn't see type hints i think

19:37 technomancy: maybe the language shootout doesn't enable invokedynamic

19:38 dnolen: jondot`: type hints don't equal speed in Clojure.

19:38 jondot`: many things are fast that don't require type hints.

19:38 jondot`: i assume clojure uses MethodHandle?

19:40 technomancy: I don't think so

19:41 anyway, don't make any decisions based on data from the language shootout

19:42 hiredman: jondot`: the clojure compiler doesn't generate any code that won't run with java 1.5, so no methodhandles, invokedynamic, etc

19:42 jondot`: yep, i warned this is a bit of a boring question :)

19:42 hiredman: i see

19:44 bkirkbri: anyone know how to diagnose "It's possible the specified jar is not in any repository." when lien doesn't say which JAR?

19:44 s/lien/lein/

19:52 emezeske: bkirkbri: Maybe paste the full output from lein?

19:54 bkirkbri: emezeske: Sure, here's all the output I get http://pastebin.com/hn48aVZt

19:56 emezeske: bkirkbri: Huh, I've not seen that particular error message before. I assume you checked for typos? :)

19:57 bkirkbri: emezeske: I did. The funny thing is that I didn't change the codebase and this started after a deps check that auto ran.

19:58 emezeske: bkirkbri: Did you try removing all the .lein* and lib/ and whatnot, e.g., starting totally fresh?

20:00 bkirkbri: emezeske: I'm using lein2, so no lib/ and I did try removing my ~/.m2 and pulling everything all over again.

20:01 emezeske: bkirkbri: :/

20:02 bkirkbri: emezeske: Weird, right?

20:07 xeqi: bkirkbri: what version of lein?

20:07 bkirkbri: xeqi: 2.0.0-preview10

20:13 that's strange… added an exclusion and now it works.

20:13 not sure how that could have happened when the same project.clj and codebase has been working since yesterday.

20:14 emezeske: bkirkbri: Do you have any SNAPSHOT versions in your :dependencies ?

20:16 bkirkbri: nope, but it's possible that my deps have deps that are SNAPSHOT

20:16 emezeske: bkirkbri: I think "lein deps :tree" could be interesting

20:17 bkirkbri: emezeske: good call, that failed when deps was failing but I can run it now.

20:19 emezeske: no SNAPSHOTs http://pastebin.com/vXpJ88Rt

20:21 The :exclusion that made it work was the one on clj-aws-s3

20:30 TimMc: Is there something that is the opposite of an agent? i.e., a fn that gets events (data) sent to it, not data that gets fns sent to it.

20:31 Or do I just set up a blocking queue and run a fn in a loop waiting for data?

20:31 octagon: perhaps http://clojuredocs.org/clojure_core/clojure.core/add-watch ?

20:33 TimMc: Hmm, seems roundabout.

20:34 Maybe I'll just make something hacky and give it a pretty API.

20:37 thorbjornDX: is there a reasonable way to realize (or count) a seq until I get a nil value?

20:37 octagon: thorbjornDX: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/take-while ?

20:38 thorbjornDX: octagon: awesome, I love how every possible higher-order function already exists :)

20:39 octagon: thorbjornDX: thank god for that

20:40 emezeske: I mostly thank Rich Hickey for that

20:40 thorbjornDX: thank someone, for sure :)

20:40 Rich et al

20:41 * emezeske checks to see if the Github ID "God" is taken.

20:41 octagon: lol i meant like "whew, lucky those things are already written", not implying that God was responsible

20:41 bkirkbri: emezeske and xeqi, thanks for the help!

20:42 emezeske: octagon: I know you were just using an expression, but that won't stop me from joking about it! :P

20:42 bkirkbri: not sure what the cause was, but at least it's working now...

20:42 thorbjornDX: can this be shorter?: ##(take-while #(not (nil? %)) '(1 2 3 nil nil))

20:42 lazybot: ⇒ (1 2 3)

20:42 emezeske: bkirkbri: Glad you're up and running. Too bad you didn't find the root!

20:42 octagon: (take-while identity ...) perhaps

20:43 since nil is falsy

20:43 bkirkbri: emezeske yeah, i have a feeling it'll be back. though I hope not.

20:43 emezeske: ,(take-while (complement nil?) [1 2 3 nil nil])

20:43 clojurebot: (1 2 3)

20:43 emezeske: I guess technically that's longer :)

20:43 octagon: ah true, identity is wrong there

20:44 cause you'd miss a false value

20:44 bkirkbri: yeah, (take-while identity) will stop at the first false

20:44 thorbjornDX: emezeske: complements to you :)

20:45 octagon: (comp not nil?) perhaps

20:45 emezeske: octagon: Why would you (comp not nil?) instead of (complement nil?) ?

20:46 thorbjornDX: I'd rather be idiomatic than as-short-as-possible

20:46 octagon: emezeske: haha you wouldn't

20:46 emezeske: :P

22:28 mpan: wow, job fair

22:29 some guy tried to convince me APL was just like Lisp

22:29 o_O

22:29 I mean, I thought the CL folks didn't like it if you said Clojure was like Lisp

23:03 ohpauleez: I always thing there is a doc about not using (not (nil? x)) - and using something else instead

23:03 am I crazy? or can someone tell me what I'm thinking of

23:03 think**

23:05 oh duh, I can just use identity

23:05 mpan: what behavior are you looking for?

23:06 &(not (nil? false))

23:06 lazybot: ⇒ true

23:06 mpan: &(identity false)

23:06 lazybot: ⇒ false

23:06 mpan: idk if that case ever affects you, however

23:06 but those aren't (in general) equivalent

23:10 ohpauleez: I'm looking for conditionals, not nil?

23:10 is just identity

23:10 for general purposes

23:15 oh for sure, I should have been more clear - it was a sequence of strings and nils

23:34 Raynes: ohpauleez: Thanks for looking at that patch.

23:35 ohpauleez: Raynes: Np - I've been digging into a lot of node stuff, so i've been hitting all the node patches today

23:35 and I'm familiar enough with all the CLJS source at this point

Logging service provided by n01se.net