#clojure log - Jul 31 2012

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

0:47 muhoo: ordnung, eh?

0:51 nkkarthik: in clojurescript to connect to repl from a page I need to add 'repl/connect' code to the page

0:51 but this I cannot check-in... into production I mean

0:52 is there some conventional way that you guys follow?

0:52 emezeske: nkkarthik: (when config/debug (repl/connect))

0:54 nkkarthik: emezeske: ah where do I set this?... is config/debug automatically available at compile time?

0:55 emezeske: nkkarthik: No, I just assumed that your app has some kind of configuration to tell it to e.g. use minified/plaintext assets, verbose logging, etc

0:56 nkkarthik: emezeske: ok... is there a conventional way to set these properties (or specify a file)... in cljsbuild options or somewhere?

0:57 or do your own way

0:58 emezeske: I'm not sure if there's much of a standard convention at this point

0:59 I tend to put my configuration stuff in a crossover .clj file, personally

0:59 I don't know if that scales well or not, though

1:00 nkkarthik: emezeske: oh a config.clj file... not config.cljs?... so that this 'connect' code gets compiled out altogether?

1:01 emezeske: nkkarthik: The crossovers allow you to share .clj code with .cljs; I use that for my config so that both clojure and clojurescript have access to the config variables

1:01 nkkarthik: You could use a macro to compile out that code altogether if you wanted

1:02 nkkarthik: If you are just using cljs, and no clj, then crossovers don't buy you anything

1:03 nkkarthik: emezeske: yeah I just started out with cljs and going through the quick start... and had this question... I thought maybe we use clojure to compile it to javascript and so we can use a clj file to compile it out

1:03 emezeske: the macro idea sounds good too

1:03 emezeske: nkkarthik: That's definitely an option. If you're just starting out, though, I recommend staying away from advanced features like crossovers until you feel comfortable with the basics

1:03 nkkarthik: They are kind of a hack, and are tricky to get right

1:04 nkkarthik: emezeske: yeah I will keep out then :)

1:07 emezeske: I will stay with the config.cljs file for now then

1:07 emezeske: by the way... thank you for the plugin

1:08 emezeske: nkkarthik: Yeah, I'm glad you've found it useful!

1:30 mk: can I change part of a function defined using defn, or must I use a second defn to redefine the function?

1:33 ,(defn f [n] (* 2 n)) (f 2)

1:33 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

1:34 mk: if I'm on the repl, and there's a thread executing a loop within f, how can I change the 2 to a 3 without interrupting that thread?

1:44 emezeske: mk: The defn macro takes a list of forms, makes a fn, and then puts it into a Var

1:44 mk: The list of forms is definitely immutable

1:44 mk: And I think the fn is too

1:44 mk: Meaning that if you want to change things, you need to change the "f" Var, which you could do by, as you said, another defn

1:45 mk: If you want to change the "2" by itself, you'd have to do some work up front

1:45 mk: how do I go about mutating it?

1:45 emezeske: You could make 2 an atom

1:45 (defonce multiplier (atom 2))

1:45 (defn f [n] (* 2 @multiplier))

1:46 Then, somewhere else, (swap! multiplier (fn [old] new-value ...))

1:46 That would mutate multiplier in a thread-safe manner

1:47 mk: what does defonce do? the doc's "root value" is confusing

1:47 emezeske: It just ensures that if you reload the namespace the atom doesn't get redefined

1:47 mk: or, what is a "root value"?

1:47 emezeske: It's not strictly necessary, but it can avoid some confusion

1:48 I probably shouldn't try to explain the root value, etc -- I would probably not get it right

1:48 You can read the docs on Vars if you want to understand that

1:48 mk: oh, I see. Does it redefine if the value has later been removed from the namespace?

1:48 emezeske: I'm not sure, I would guess so, though

1:50 mk: I want to mutate the multiplier while programming via the repl... is atom appropriate for that?

1:53 emezeske: Yep!

1:53 mk: then why don't we use atoms even for definitions?

1:54 emezeske: Well, Vars and atoms have different concurrency properties

1:54 Like when you mutate a Var, it's usually done in a thread-local context

1:54 Vars are not good for sharing state across threads

1:54 Raynes: emezeske: I think fs's cwd mechanism is a good example of it.

1:54 (of how vars work)

1:55 emezeske: Raynes: Yeah, it does, IIRC

1:55 Raynes: cwd is a dynamic var, right?

1:55 Raynes: But I don't know, since I might have force pushed a branch at some point. I damaged the universe like that once, much like Walter's crossing over in Fringe.

1:55 emezeske: Fringe, that show with Spock?

1:56 Raynes: emezeske: Haha

1:56 Yes.

1:56 emezeske: :)

1:56 Raynes: emezeske: But yes, it is a dynamic var. The fun bit is that you can set it with set!.

1:56 mk: what is a dynamic var?

1:56 Raynes: The pot of gold at the end of the rainbow.

1:57 * Raynes leaves before emezeske compels him to force push more branches.

1:57 * emezeske swings at Raynes' shadow.

1:58 emezeske: mk: It's a Var created like (def ^:dynamic x 5) that can be changed in a thread-local dynamic scope via things like (binding ...)

1:58 mk: But for more detail, the docs are king :)

1:58 mk: when I mutate a var using the repl, and there's a thread busy crunching data, isn't that out of thread-local?

1:59 emezeske: Yeah, although if you set the root binding (as you mentioned) I do believe it would affect other threads

1:59 But really, that is what atoms are for

2:00 mk: so in cases where we suspect that we might end up modifying code in this way, we should use atoms throughout?

2:01 this seems strange

2:02 if we're both writing the same code, and you do it in one go, while I do it interactively using the repl, my code now has atoms everywhere while yours doesn't...

2:02 emezeske: Well, if you reload a namespace with (require ... :reload), all the Vars get changed

2:02 And if you really want to, you can set! a Var

2:03 I suggest you do some more reading on clojure's concurrency primitives and make an informed decision

2:06 mk: if you look at the first example, with the multiplier - if I've chosen to use the repl to fine-tune the value of multiplier, I end up making it an atom. But if you know what you want the multiplier to be, you'd just (def multiplier 7.23), without using an atom. This doesn't seem strange?

2:07 we end up with the same code, but many of my values are wrapped in atoms. Do I then just remove all of the atom definitions, when I'm done messing via the repl?

2:08 emezeske: This would be a good place to start: http://clojure.org/concurrent_programming

2:09 ro_st: anyone know of a pubsub impl in cljs that isn't the shoreleave one?

2:09 it's broken and ohpauleez is AWOL :-)

2:10 mk: emezeske: is there something particular there that I should read?

2:10 ro_st: also, does anyone use enfocus? i'm curious as to whether i can use it to focus a textfield

2:11 emezeske: mk: I would start with reading about Vars and Atoms, to see what the differences/similarities are.

2:12 mk: There's no clear answer about which is "better" -- they are different, and which one you want depends a lot on context

2:21 meenal: Hi, can someone please point me to a good example of slingshot ex-info/ex-data in clojure?

2:21 I am trying to use slingshot to avoid writing custom exceptions

2:24 emezeske: meenal: I happen to know that https://github.com/cemerick/friend/blob/master/src/cemerick/friend.clj uses throw+ and try+

2:24 meenal: It's not meant to be an example, but that was the first place I saw slingshot in action

2:26 michaelr`: Is there a way to destructure in one compojure route definition all of the following: a paramter from params with an aliased name, user-agent header, all headers, all session? Something like this: https://www.refheap.com/paste/3914

2:27 meenal: thanks emezeske. i will try to read thro' the code

2:34 michaelr`: ok

2:34 that's the way you do it: https://www.refheap.com/paste/3915

2:34 (money for nothing and chicks for free)

2:36 muhoo: the fun thing about slingshot is it shows the local variables at play when the exception happened

2:38 ro_st: michaelr`: i think destructuring is clojure's MVP

2:38 it is insanely useful

2:46 y3di: do the prismatic guys ever stop by this channel?

2:46 ro_st: you also want their data store abstractions? :-)

2:47 really enjoyed that guy's talk

2:47 emezeske: ro_st: at clojure/west?

2:48 ro_st: yes, that's the one

2:48 http://www.infoq.com/presentations/Why-Prismatic-Goes-Faster-With-Clojure

2:48 emezeske: ro_st: yeah, that was great

2:48 Those guys are using the #&*? out of clojure

2:49 ro_st: it rocks. i wish more big guys would talk about how they use it

2:49 emezeske: aye

2:49 ro_st: convince the fence sitters to take a look

2:49 michaelr`: ro_st: minimal viable product?

2:49 ro_st: most valued pfeature -grin-

2:49 emezeske: *pheature

2:50 michaelr`: oh, we add those all the time to our applications ;)

3:12 ro_st: contains? checks if a key is in a collection. how do i check for the presence of a value in a collection? in this case, a vector?

3:13 DaoWen: I think you can use (.indexOf v element)

3:13 ro_st: whoa. didn't think i'd have to use java!

3:13 DaoWen: of you could use (some #{element} vector)

3:13 emezeske: ro_st: Maybe some?

3:14 Hah, DaoWen beat me to it :)

3:15 DaoWen: :)

3:16 djcoin: Is there a problem using .indexOf (besides "it's java") ?

3:16 ro_st: some does the trick. just found it weird that i'd have to drop to java to find that index. of course, i don't have to, because (some) does the job

3:21 DaoWen: ro_st: if you need to check for the presence of a value in a vector, you might think about switching to a set

3:21 it depends on what you're doing of course

3:21 how big your vector is, how often you need to check, etc

3:22 ro_st: i could use a set, but in this case i want the order items were added to remain in place

3:22 DaoWen: one thing I've done in the past is keep a vector AND a set

3:25 emezeske: ro_st: There is a sorted-set if you need it

3:26 DaoWen: emezeske: I think he's trying to maintain things in the order they were added, which isn't necessarily a sorted order

3:26 emezeske: Oh, quite right!

3:26 ro_st: yup

3:26 emezeske: There might or might not be some beer in me

3:27 ro_st: as long as you don't drunk-commit -grin-

3:27 emezeske: I have had to revert drunk commits before, I'm sad to admit

3:30 ro_st: oh dear :-)

3:41 muhoo: wow, nrepl in the hizzy

3:41 successfully upgraded to emacs24, latest nrepl.el, and pdo is working

3:46 lein2 pdo cljsbuild auto, repl :headless

3:46 ro_st: sounds awesome

3:46 what's pdo? :)

3:46 muhoo: ro_st: github.com/raynes/lein-pdo

3:46 ro_st: ok so you have cljsbuild running, and a headless repl, so that you can nrepl in from emacs?

3:46 muhoo: a nifty plugin that lets one lein process handle multiple tasks in parallel. like, a cljsbuild, and a headless repl

3:46 ya

3:46 ro_st: i would love to see your emacs and project.clj config for this

3:46 please :-)

3:46 muhoo: ro_st: https://www.refheap.com/paste/3918

3:46 ro_st: that looks straightforward

3:46 i guess i'm more curious about nrepl.el and how it works with clojure-mode

3:46 muhoo: there's no .emacs , i just manually am loading nrepl.el for now, from github.com/kingtim/nrepl.el

3:46 ro_st: i'm using emacs-live which has swank-clojure and clojure-mode all glommed together

3:46 muhoo: M-x load-file RET /home/clojure/src/nrepl.el/nrepl.el RET

3:47 ro_st: *reads nrepl.el issues*

3:47 muhoo: easy enough to just read nrepl.el, it's about 1200 lines

3:48 ro_st: i'll make time to play with it this afternoon

3:48 it looks great

3:48 muhoo: i find it a lot more approachable than swank, then again, i'm not an old-skool swank user

3:48 seems like the keybindings are the same though

3:54 ro_st: cool

4:12 i guess if i want a vector sorted, i should use sorted-set or sorted-map, and then (vec) afterwards?

4:13 ejackson: or just call sort !

4:18 amalloy: if you want a vector sorted, you probably don't want a vector

4:22 ro_st: ejackson: i don't see the fn you refer to on http://clojuredocs.org/quickref/Clojure%20Core

4:23 amalloy: i actually want a sorted-map, but sorted-map sorts on the key, not on the value, and i need to sort on a field in the map that makes up the values in my map

4:23 amalloy: ro_st: that's a heap

4:23 ro_st: this map is an atom, which makes using a sorted-set problematic (ito updating values in this data)

4:26 amalloy: are you referring to heap-sorting?

4:26 ejackson: ,(sort [12 4 8 23 1])

4:26 clojurebot: (1 4 8 12 23)

4:26 amalloy: http://en.wikipedia.org/wiki/Heap_%28data_structure%29

4:27 ejackson: but amalloy is correct,

4:28 ro_st: ok, this is well out of my comfort zone. i never did compsci :-) can i use a heap/heap sort in cljs?

4:29 in this case, i don't need lazy, as it's to sort a series of models in preparation for displaying a list of html nodes

4:30 so the full collection will be realised. so i'll start with (sort comp coll) for now

4:59 sort fns usually return 1 0 −1 based on whether A is less than, equal to, or greater than B

4:59 i see clojure's sort uses true and false. what do i return for the equality case? i won't have this case now, just curious.

5:14 DaoWen: ro_st: I know tis is a bit late, but you might want to use sort-by rather than sort since it sounds like you're sorting on a specific field in a data structure. that will keep your comp function simpler.

5:15 ro_st: yeah, i found that :-)

5:15 thanks

5:37 surely there's a better way to print vectors and maps to the js console than cljs.core.ObjMap and cljs.core.PersistentVector trees?

5:38 *reads himera again*

5:48 ejackson: ro_st: I just log em to the the console

5:49 ro_st: yeah but having to drill down into PersistentVectors is sucky compared to plain js arrays

5:50 DaoWen: ro_st: what do you mean by "drill down?"

5:51 ro_st: http://rationalist.co.za/uploads/Screen%20Shot%202012-07-31%20at%2011.50.38%20AM-rS07Grmbqs.PNG

5:52 i guess i could augment my log fn to dig into these and show the internal items i'm interested in

8:44 lotia: greetings all. new projects, relative noob to clojure. nrepl or swank for new projects.

8:44 whats better?

8:44 ro_st: nrepl is still brand new

8:45 that said, it's probably better for you to learn that and grow with it than take swank on and switch

8:45 lotia: i ask because i'm starting a new pallet project using lein2 and want to be able to eval forms from within my files.

8:45 ro_st: i believe nrepl does that no problem

8:45 lotia: so using emacs, i'd need to get the nrepl client

8:46 ro_st: thanks. anywhere there's a list of advantages, disadvantages of either? or are the roughly equivalent for most use cases?

8:47 ro_st: swank is about to be deprecated, once the guys doing nrepl get it to the point they're happy with it

8:47 coupla weeksish

8:47 lotia: ro_st: thanks

8:48 anyone using el-get for their emacs here?

8:54 ro_st: i'm using emacs24 for osx

8:54 comes with package-install.. i just added the marmalade repo

9:01 lotia: thanks ro_st

9:04 cshell: does anyone know how to pretty print to a file in clojure?

9:04 XPherior: Anyone ever seen the error message "Incorrect table name ''" in Korma?

9:05 I darn sure specified a name.

9:10 gfredericks: cshell: at the very least you could (spit "foo.cljj" (with-out-str (pprint data)))

9:10 and improve from there for any needed perf

9:10 there might be a pprint-str also, not sure

9:17 cshell: gfredericks: cool, i'll give that a shot - thanks!

9:20 ro_st: XPherior: what does the sql dry-run look like?

9:20 XPherior: ro_st: I just noticed that my usage of create-db is returning a PersistentArrayMap. That can't be right, heh.

9:21 ro_st: haha, um, no, probably not :-)

9:23 XPherior: ro_st: Have a look. https://gist.github.com/eecf4c8857596c73b72f

9:23 Line 3 is still returning an array map. Weird.

9:25 ro_st: XPherior: db contains an execution result, where i think you actually want a defdb definition

9:26 XPherior: ro_st: I need to create the connection dynamically. I don't know what the DB name is at compile time.

9:27 ro_st: i get that. i speak under correction, but as far as i know korma uses static defdb definitions.

9:27 you can probably overcome this by doing what defdb does yourself

9:28 XPherior: I basically am. Check it out. https://github.com/ibdknox/Korma/blob/master/src/korma/db.clj#L60

9:33 ro_st: ah

9:33 weird

9:35 so, presumably there's something different about the spec there and the one you're providing?

9:40 XPherior: Looks like it, yeah.

9:43 antoineB: hello, how can i construct a list from 2 list?

9:43 (apply list '(1 2 3) '(1 2 3)) => ((1 2 3) 1 2 3) where i expect (1 2 3 1 2 3)

9:44 xeqi: $findfn [1 2 3] [1 2 3] [1 2 3 1 2 3]

9:44 lazybot: [clojure.set/union clojure.core/lazy-cat clojure.core/concat clojure.core/into]

9:44 xeqi: I'd use concat there

9:47 antoineB: simply concat, thanks

9:51 leafw: what is the current authoritative repository for clojure monads? Used to be part of clojure-contrib

9:51 but now clojure-contrib is fragmented

9:53 xeqi: ~contrib

9:53 clojurebot: Monolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

9:54 xeqi: leafw: looks like https://github.com/clojure/algo.monads/

9:55 leafw: xeqi: thanks. So does that mean that it is included in the main clojure repository?

9:55 I see, no

9:55 it is in its own

9:56 xeqi: leafw: no, you'll need something like [org.clojure/algo.monads "0.1.0"] as a dependency

9:57 leafw: thanks

9:57 mk: how do I get lein repl started using 1.3?

9:59 or, does anyone's lein repl start using (clojure-version) 1.3 by default?

10:00 xeqi: mk: make a project using 1.3 and then run `lein repl` in it

10:02 mk: I was running it in a random dir to get access to a repl. I suppose I can just run clojure instead of lein repl?

10:02 is there any difference between the two?

10:03 ToxicFrog: mk: 'lein repl' sets up the CLASSPATH and stuff appropriate to your project, and I think also uses jline automatically

10:04 If you don't have a project and just want a Clojure repl, 'clojure' (if your distro comes with it) or 'java -cp ...jline.jar:...clojure.jar jline.ConsoleRunner clojure.main' if it doesn't should do the trick.

10:05 Or just 'java -jar /path/to/clojure.jar' if you don't care about readline support.

10:07 mk: yeah, just clojure seems to work. I was under the impression that lein repl was enhanced in some way, though I'm not sure what way that would be since it's about as bland as it gets

10:11 is the only difference between bigint and biginteger the hashcode?

10:12 leafw: how does one specify a local jar in the project.clj?

10:12 as in, where does one put it so that it ends up in the classpath and it is read as a dependency?

10:13 ifesdjeen: leafw: pretty much the same way as you would do with maven

10:13 leafw: you can add :repositories {"local" ...

10:13 leafw: ifesdjeen: I have no idea how to use maven

10:13 ifesdjeen: point to (.toUri (java.io.File. "maven_repository_path"))

10:13 leafw: lein is supposed to shelter us all from maven

10:13 ifesdjeen: :)

10:13 yeah, it certainly does

10:14 leafw: so the .toUri you add in the project.clj?

10:14 ifesdjeen: yup

10:14 leafw: ok

10:14 thanks

10:14 wouldn't need to if org.clojure/algo.monads "0.1.3-SNAPSHOT" existed.

10:14 ifesdjeen: leafw: hm, people say that you can just say :repositories {"local" "path" }

10:15 leafw: the git repos pom.xml says that's the current.

10:15 ok

10:15 ifesdjeen: oh my, there's even plugin for that :D

10:15 https://github.com/kumarshantanu/lein-localrepo

10:15 leafw: lein is as complicated as it gets, mostly from lack of documentation.

10:16 ifesdjeen: so far didn't get much issues with that...

10:16 leafw: the default project.clj could have, commented out, all possible examples with a one-liner explaining what they are for. Like for the "local"

10:16 thanksf or the help ifesdjeen

10:17 ifesdjeen: leafw: npnp

10:17 hope it does it's job :)

10:17 leafw: ever since the break down of contrib, I have not been able to use any contrib projects.

10:17 so trying again

10:18 uvtc: leafw: jumping in to the middle of this, but if you're looking for a project.clj with all possibilities, see https://github.com/technomancy/leiningen/blob/master/sample.project.clj .

10:18 DaoWen: mk: no, the difference between bigint and biginteger is not just the hashcode

10:18 leafw: thanks uvtc

10:19 uvtc: leafw: y/w. Also, if you're new, you might find this useful: http://www.unexpected-vortices.com/clojure/brief-beginners-guide/

10:19 mk: DaoWen: what are the main differences?

10:19 DaoWen: sorry, I was looking up a URL

10:19 http://grepcode.com/file/repo1.maven.org/maven2/org.clojure/clojure/1.3.0-alpha5/clojure/lang/BigInt.java

10:20 that's the BigInt class

10:20 you can see right at the top that it wraps both a long and a BigInteger

10:21 leafw: uvtc: thanks, not new to clojure, but haven't used it for 2 years

10:21 and now it's all different. Still no good IDE unfortunately.

10:21 DaoWen: mk: BigInt will use the native operations for long when possible

10:22 but if the number gets to big then it uses the arbitrary-precision BigInteger methods to do operations like add, multiply, etc

10:23 ifesdjeen: leafw: not sure what would make it for a good ide for you, i use it with emacs + paredit + clojure-mode + autocomplete-mode + swank

10:23 leafw: lein is full of magic that I find hard to grasp. For example, a function defined in core.clj, how do I refer to it from project.clj? core.main having written (defn main ..) doesn't do it.

10:23 ifesdjeen: works really really well for me

10:23 leafw: core/main ?

10:24 ifesdjeen: emacs destroys my hands. vim, eclipse, or a plain text editor I prefer.

10:24 ifesdjeen: ah

10:24 well, only problem with vim I have is that it's not playing with lips as well as emacs does

10:24 DaoWen: leafw: I use lein with vim

10:24 mk: DaoWen: I see, thanks

10:24 ifesdjeen: but i do feel very comfy with it, so dunno)

10:25 leafw: DaoWen: I am at the moment.

10:25 DaoWen: nice :)

10:25 do you use slime.vim?

10:25 leafw: DaoWen: so how does one refer to a fn named "main" in core.clj from project.clj?

10:25 it's not core.main

10:25 and not core/main

10:25 xeqi: projectname.core/main ?

10:26 DaoWen: try that ^

10:26 you need the fully-qualified namespace

10:26 leafw: what does the (ns) declaration look like at the top of your core.clj file?

10:26 leafw: project is parse-bib, so parse_bib.core/main fails, and parse_bib.core.mains fails too

10:26 DaoWen: try

10:27 parse-bib.core/main

10:27 (hyphen instead of underscore)

10:27 if that doesn't work

10:28 did you :require it in your ns declaration in the current file?

10:28 leafw: DaoWen: the default

10:29 DaoWen: leafw: what exactly are you trying to do? are you trying to declare the main method in project.clj for a runnable jar or something?

10:29 leafw: DaoWen: parse-bib.core

10:30 antoineB: how could i do a recursive call without a named function?

10:30 leafw: I am doing the simplest thing possible: (ns parse-bib.core) (defn main [] (println "ok"))

10:30 DaoWen: and you just want to call that function from another file?

10:30 leafw: no, I want to define main as the main function in project,clj

10:30 DaoWen: (another namespace)

10:30 ok

10:30 leafw: so either lein doesn't like hyphens

10:31 in the project name

10:31 or I don't get it

10:31 Cheiron: How to get the name of a called function? for logging purpose

10:31 leafw: tried all combinations

10:31 DaoWen: yeah, it's weird

10:31 you actually have to declare it as (defn -main [& args] ...) in core.clj

10:31 leafw: that's my experience with lein always: can't get over the simplest things. There is a set of expectations that are not written anywhere about how lein works.

10:31 trying that

10:32 DaoWen: I guess that's the clojure magic for defining a java main method

10:32 leafw: (reads like static public final void main(String[] args) ....)

10:33 DaoWen: but then in your project.clj you just give the class

10:33 parse-bib.core

10:33 leafw: still doesn't work. So, removing the hyphen from the project name ...

10:33 DaoWen: also, in parse-bib.core you need to tell it to :gen-class

10:33 leafw: I see: so :main is not the function, but the name of the file

10:33 DaoWen: (ns parse-bib.core (:gen-class))

10:33 :main is the name of the class

10:34 xeqi: :main is the namespace

10:34 leafw: finally, it worked

10:34 thanks

10:34 uvtc: leafw: re. "set of expectations that are not written anywhere about how lein works" ... if you find that lein is making an assumption and not telling you about it, and it's not documented, I'd suggest filing a bug.

10:34 leafw: so lein does respect hyphens in the project name

10:34 it is :main in project.clj that asks not for the main function but for the class in which a function named -main exists ...

10:34 Cheiron: I'm passing a function to another function, i want to print the name of the passed function. how to do it?

10:34 DaoWen: I don't think these are so much lein quirks as just clojure-java interop quirks

10:35 leafw: uvtc: doing so

10:35 DaoWen: leafw: I think :main is kind of like the class manifest in a JAR file

10:35 it asks for a "main" class

10:35 leafw: because the sample.project.clj doesn't say anything about it in :main

10:36 DaoWen: you could have any number of classes in a JAR with a main method with the legal signature, but you specify one as the "main" class

10:36 antoineB: i get it i just set a name to a fn: (fn f[a] (+ 1 (f a)))

10:36 leafw: DaoWne: the point here is, how is a novice user of lein ever to find out?

10:36 DaoWen: I've only been using lein for a couple of weeks

10:36 I googled how to make a runnable JAR

10:37 there are lots of blog posts on the subject :)

10:38 uvtc: leafw: Note, there's also a #leiningen channel.

10:39 Cheiron: when passing a function and parameters to macro, how to call it? ~(func ~@params) ?

10:39 leafw: uvtc: I hope not to have to use it, thanks

10:43 DaoWen: leafw: https://github.com/technomancy/leiningen/blob/preview/doc/TUTORIAL.md#uberjar

10:43 leifw: that section on the uberjar option explains everything on making a runnable jar

10:44 leafw: DaoWen: the point here is to use a jar from the file system

10:44 not to export the project to a jar

10:44 turns out the :repositories is only for looking for dependencies

10:44 what a game of guessing. Second guessing the maven developer/superuser that wrote lein

10:45 lein is wonderful, if one doesn't want to do something out of the ordinary

10:45 I was hoping referring to a jar would be that

10:46 maybe :javac-options would let me add a -cp

10:46 DaoWen: leafw: http://stackoverflow.com/questions/2404426/leiningen-how-to-add-dependencies-for-local-jars

10:47 leafw: uvtc: so I am moving to #leiningen, looks like the wall is high

10:47 xeqi: ~repeatability

10:47 clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability

10:47 leafw: DaoWen: thank you. The top answer is a hack.

10:47 xeqi: that explains why lein doesn't want to just include jars from the file system

10:48 uvtc: leafw: looks like the author of lein (technomancy) is not around right now. I'd suggest bringing up your questions again next time he's around.

10:48 DaoWen: leafw: the second answer seems better, but I don't know how to make a private maven repo.... but it looks like the third post explains how

10:48 leafw: I take note. Surely there are good reasons not to depend on a jar but on a repository instead. It's just baffling to a newcomer.

10:49 there is room for a book on how to create leinigen projects.

10:50 uvtc: A book? Maybe a booklet. Or a pamphlet. Or a leaflet. :)

10:50 DaoWen: leafw: I agree with you there. what if I want to use a JAR that's not in the maven repository? what if I'm using a proprietary JAR that can't be included in the repository? it seems like setting up a local repository just for one JAR in one project is a little bit overkill.

10:50 leafw: uvtc: no, a book, with 10-pgae chapters: a project with jars, why is (defn -main [& args]... needed, and so on.

10:50 Cheiron: Hi, would you please take a look to my with-try macro attempt: http://pastie.org/4365552

10:51 DaoWen: leafw: https://github.com/kumarshantanu/lein-localrepo

10:51 leafw: DaoWen: the "hack" of ptting the jar in /lib should do it

10:51 so there is way

10:51 it is just not elegant

10:51 neither explained anywhere

10:51 DaoWen: leafw: looks like that plugin goes and make the local repo for you, and then you can add jars with a simple command

10:51 uvtc: leafw: writing good documentation is tricky. If you have any specific feedback on how to reorganize the lein docs to improve clarity, I'm sure technomancy would be all ears.

10:52 leafw: uvtc: indeed, complaining is not useful beyond a point.

10:52 TimMc: leafw: Don't put things in lib.

10:52 It won't work, that's why it's not mentioned.

10:53 leafw: TimMC: it didn't work, likely because the algo.monads-0.1.3-SNAPSHOT.jar doesn't work with clojure-1.4.0. Just found that out

10:53 Cheiron: ah, ok. e# :)

10:54 uvtc: Cheiron: e#?

10:54 leafw: I am looking forward to join the priesthood of being able to use lein. Can't be that hard to use algo.monads in a clojure project.

10:54 Cheiron: (catch Exception e#)

10:54 TimMc: leafw: No, it won't work (at least in 1.x) because lib gets cleared.

10:54 Are you using the 2.x preview? I came in late.

10:55 leafw: TimMc: using lein from 2 years ago, updated it self to 1.6 or so

10:55 TimMc: Yeah, ./lib is a local cache. Lein 1.x will delete the contents when updating deps.

10:56 uvtc: leafw: Yeah, I'm not sure I'm following exactly what the problem you're having is, but if you want to use a contrib library, I put up some basic notes at http://www.unexpected-vortices.com/clojure/brief-beginners-guide/libs-management-and-use.html#using-contrib-libraries .

10:56 dgrnbrg: hello clojurians

10:56 leafw: so algo.monads-0.1.1-SNAPSHOT exists, but can't run with 1.2, 1.3 or 1.4: error is Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure/tools/macro__init.class or clojure/tools/macro.clj on classpath:

10:56 mk: Cheiron: why does e# work?

10:56 dgrnbrg: i'm having an issue getting a namespace that uses a macro for doing dynamic codegen to compile efficientyl

10:56 is there a way to get the macroexpansion to occur at AOT time?

10:57 Cheiron: i think because it generates a name, e could be bind somewhere else

10:57 leafw: uvtc: the program I am writing depends on algo.monads. I thought it would be nice to use lein to aleviate the dependency issues, but it is resulting in me wasting your time

10:57 Cheiron: mk: variable capture issue of other Lisps

10:57 uvtc: leafw: Oh, no waste of time. :) Sorry if that came out wrong.

10:58 leafw: sorry, didnt mean to make it sound harsh on you, rather on me (I am fumbling with lein when I expected a smooth ride)

10:58 so does anybody know what clojure version would work with algo.monads?

10:59 DaoWen: Cheiron: you are right, the e# syntax helps to avoid variable capture

10:59 leafw: uvtc: I see in your tutorial that the right approach is to query first maven central

10:59 mk: what is that syntax called?

10:59 TimMc: gensyn

10:59 *gensym

11:00 "generate (unique) symbol"

11:00 leafw: a pity maven central has 0.1.0 and not 0.1.3 for algo.monads

11:00 TimMc: &[`[e# e#] `[e# e#]]

11:00 lazybot: ⇒ [[e__18236__auto__ e__18236__auto__] [e__18237__auto__ e__18237__auto__]]

11:01 uvtc: DaoWen: what is "variable capture"?

11:01 xeqi: leafw: looks like the algo.monads test suite passes on >=1.2.0 http://build.clojure.org/job/algo.monads-test-matrix/

11:01 DaoWen: uvtc: name capture

11:01 uvtc: DaoWen: what is "capture"? :)

11:02 DaoWen: uvtc: it happens with macros. Cheirion was trying to make a try/catch-like macro

11:02 leafw: xeqi: thanks

11:02 uvtc: DaoWen: Ah. Will research further next time I'm reading about macros. Thanks.

11:02 mk: I'm looking at clojure.org/reader, and it has nothing about # suffix. Where are the docs on this?

11:02 DaoWen: uvtc: what are you reading?

11:03 TimMc: mk: It's really the syntax-quote that does it.

11:03 leafw: xeqi: maven central has 0.1.0 for algo-monads, but setting it as dependency and then "lein run" doesn't download the jar into /lib, and fails with "Could not locate clojure/algo/monads__init.class or clojure/algo/monads.clj on classpath"

11:04 uvtc: DaoWen: I mean that I wanted to know what the term "capture" meant, and you pointed out that it has to do with macros, and at the moment I've only skimmed the documentation on macros.

11:04 leafw: ok "lein deps" did it

11:04 would have expected that to hppen as fallback from lein run

11:05 xeqi: leafw: that would be my expectation too, we try to make sure all reuired tasks are run in lein2

11:05 mk: TimMc: thanks, I see that in the docs now, where it says ends with '#'

11:05 DaoWen: uvtc: "capture" happens when a name declared in a macro conflicts with a name already declared in the scope where it's used, so the macro "captures" the user's attempts to reference the binding they declared--and bad stuff happens

11:05 xeqi: not sure how well that was done in lein1, esp not if you have n older version

11:05 leafw: xeqi: nice to hear there is a better version of lein in the works

11:06 xeqi: using lein 1.6.1.1

11:06 uvtc: DaoWen: Thanks. :)

11:07 leafw: finally ready to go; thanks uvtc, xeqi and DaoWen.

11:15 TimMc: uvtc: There are two kinds of capture (maybe one has a different name): 1) Macro introduces a binding that shadows an existing lexical binding, 2) macro's introduced binding is shadowed by an internal lexical binding in the expansion.

11:15 I'd be hard-pressed to come up with a good example of the second.

11:18 jsabeaudry: Is it new that cljsbuild triggers a compilation when a clj file changes and not only when a cljs file changes?

11:20 uvtc: TimMc: thanks for the info. Added to my own notes for when I dig into macros. :)

11:21 DaoWen: TimMc: (fn [x] (let [loop #(apply prn %&)] (loop 1)))

11:22 uvtc: TimMc, DaoWen : Previously, I'd used the term "capture" to refer to pieces of regexes that matched. Like \1 and $1.

11:24 s/I'd used/I'd only used/

11:24 DaoWen: uvtc: this is a big problem in computer science--we re-use words way too much and give them way too many different meanings. I believe the "name capture" idea originally comes from the Lambda Calculus.

11:25 uvtc: Yeah. Trouble is, if you invent too many new words, you end up with too much jargon. :)

11:25 TimMc: It's a problem everywhere.

11:26 DaoWen: haha, good point.

11:27 oh wow, I just realized my example was totally messed up

11:28 entel: has anyone got the noir plugin to work with leinengen 2? is it even possible?

11:29 DaoWen: entel: you might want to try #leiningen

11:30 entel: DaoWen: ok thanks

11:37 m0smith: Any clojurescript gurus around? I am getting this not too helpful error: Exception in thread "main" java.lang.AssertionError: Assert failed: Only :refer-clojure, :require, :require-macros, :use and :use-macros libspecs supported

11:37 (#{:use-macros :require-macros :require :use} k)

11:37 nDuff: m0smith: Can you gist (or otherwise pastebin) your ns declaration?

11:38 m0smith: (ns crossfire.board (use [crossfire.protocol.location :only [display open?]]))

11:38 melipone: hello

11:38 nDuff: m0smith: ...so, first, that should be :use

11:39 melipone: how do a get a list of rows from an Incanter matrix?

11:39 m0smith: nDuff: you are a genius, thanks

11:40 TimMc: melipone: Try seq.

11:41 melipone: I tried seq but it still gives me a matrix back not a list of rows

11:43 timmc: sorry, appearances are deceiving. it does behave like a list of rows

11:43 m0smith: nDuff: now I get SEVERE: crossfire.board:4: ERROR - required "crossfire.protocol.location" namespace never provided

11:44 I am using cljsc, where does it expect to be compiling from?

11:48 goodieboy: Anyone know of a leiningen plugin that would provide the ability to download *resources* from s3, by looking at a config map in project.clj?

11:48 ... s3, or some other url

11:49 DaoWen: meliphone: I think the Incanter Matrix class supports the .toArray method, which returns a double[][] -- which may or may not be helpful

11:52 uvtc: Just added an example to http://clojuredocs.org/clojure_core/clojure.core/some-fn .

11:53 Incidentally, it would be pretty cool if there were a way for the site to send an automated message every time someone added an example.

11:53 I mean, an irc message to this channel.

12:10 nDuff: m0smith: I'd have to look at the source for the file containing crossfire.protocol.location.

12:10 * nDuff hasn't used cljsc in ages -- moved to lein-cljsbuild some time back -- and doesn't recall it well.

12:16 augustl: when I stop and restart my "lein ring server-headless", the :session key is not present in the first request, even though the :cookies entry is there. How come?

12:16 in subsequent requests, the :session works fine

12:17 correction: the :session key is present, but is empty

12:17 a minor annoyance, but still an annoyance :)

12:18 technomancy: https://twitter.com/gghhzz/status/230335904097656833 woo go clojure.org

12:18 hiredman: augustl: the defalut session store is an in memory store, you kill the process you lose it

12:18 augustl: hiredman: I'm using the cookie store

12:18 so the full session is present in the cookie

12:20 technomancy: Google Closure is similar (not only in name): you basically need to buy a book

12:20 the docs on the Google Closure site are abysmal

12:21 hiredman: *shrug*

12:22 I've gotten most of what I needed from the google closure api docs

12:22 the real pain is often the css for the ui widgets is not really documented

12:23 mabes: ,(doc realized?)

12:23 clojurebot: "([x]); Returns true if a value has been produced for a promise, delay, future or lazy sequence."

12:23 mabes: ,(realized? (iterate inc 1))

12:23 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IPending>

12:24 mabes: I am misunderstanding what the realized? doc string is telling me...

12:24 hiredman: ,(realized? (next (iterate inc 1)))

12:24 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to clojure.lang.IPending>

12:24 hiredman: fuh

12:24 ,(realized? (rest (iterate inc 1)))

12:24 clojurebot: false

12:25 hiredman: mabes: basically iterate doesn't produce it's fist item lazily, so it is not a lazy seq, but its rest is

12:26 mabes: hiredman: ah, got it.. ok, I can work with that. Thanks!

12:26 technomancy: wooooo eldoc in nrepl.el

12:27 m0smith: nDuff: https://github.com/m0smith/crossfire/blob/master/src/crossfire/protocol/location.clj

12:27 * technomancy rubs his hands together

12:29 nDuff: m0smith: ...so that's .clj, not .cljs

12:29 m0smith: nDuff: yes I was hoping to make a cross-compatible code base

12:29 * nDuff thought this was a ClojureScript issue. *confused*

12:29 nDuff: ahh.

12:32 m0smith: would that confuse the cljs compiler?

12:32 nDuff: m0smith: Yes. lein-cljsbuild will automate making .cljs copies of the .clj files you want to use in both worlds for you.

12:32 m0smith: ...I do suggest using it.

12:33 * nDuff actually has a fork of m0smith's code he's working on lein-cljsbuild-ifying.

12:33 m0smith: nDuff: many thanks

12:33 technomancy: mmm... taste the rainbow: https://github.com/kingtim/nrepl.el/network

12:34 eggsby: hey technomancy have you had problems with large output from nrepl.el ?

12:35 technomancy: eggsby: no, but I can't say I've used it on projects with lots of output

12:36 pbostrom: augustl: when you restart the server, the session is not intialized until after you make the first request, the server looks at the cookie, recognizes it, then sticks something in the session for all subsequent requests

12:36 eggsby: technomancy: for me, something as simple as: (for [x (range 0 1000)] (println x " | hi")) results in "error in process filter: could not decode object 1"

12:37 technomancy: eggsby: no problem here. are you on Emacs 24 and nrepl.el master?

12:37 eggsby: ya :(

12:37 actually just marmalade nrepl

12:38 technomancy: there's been a fair bit of activity since then; might try the latest

12:38 eggsby: will do, thanks

12:40 mk: is there a swap! that returns the old value?

12:47 nDuff: m0smith: Pull request pending.

12:48 augustl: pbostrom: so even if I have a cookie session, it puts stuff in memory?

12:48 nDuff: Oof.

12:49 ...ignore that, please...

12:50 * Hodapp looks at nDuff

12:50 * nDuff didn't add all the changes to the first rev of the pull request for m0smith (fixed now).

12:51 nDuff: (...so, the "ignore that" was in reference to the first rev of the pull request)

12:51 augustl: I assumed the :session values were added as soon as the middleware sees the cookie

12:52 TimMc: mk: Not anything in core.

12:53 You could do something fancy with a side-effecting fn and another atom...

12:57 mk: I see. It looks like a watch might work too, at least for some purposes

12:57 m0smith: nDuff: I'll pull it now

13:06 nDuff: that seems to have done the trick. Thanks again

13:10 pbostrom: august1: you should think of the cookie and session as two separate entities, if your app/service puts some key-value pair in the cookie, it will persist in the browser when you restart the server (depending on how the cookie is configured), if you put something into the session, it will persist in the server's memory by default (although I believe you can configure alternate session stores)

13:11 technomancy: question for anyone familiar with proxies: does it make sense to have one setting for HTTP proxies and a separate one for HTTPS?

13:11 Hodapp: technomancy: 'setting' in what sense?

13:12 technomancy: Hodapp: say you'd want to use a different proxy host for HTTPS?

13:12 I'm ... not really sure

13:12 basically I get all these feature requests for proxy support in Leiningen and I have no idea how proxies work or how people would expect them to be set =)

13:13 nDuff: technomancy: ...for a SOCKS proxy, it's typically the same one for all protocols

13:13 TimMc: (defn swap2! [a f & args](defn swap2! [a f] (let [old (promise)]

13:13 (let [oldp (promise)

13:13 f* (fn [oldv] (deliver oldp oldv) (apply f oldv args))]

13:13 (swap! a f*) @oldp))

13:13 technomancy: Apache's HTTP client uses separate http.proxyHost vs https.proxyHost settings, so presumably there's a reason for that

13:13 nDuff: technomancy: ...but some shops _do_ have protocol-specific proxies rather than using SOCKS.

13:13 TimMc: mk: crud, I thought I had the one liner in my clipboard, but... there you go

13:13 technomancy: nDuff: that's what I was wondering; thanks

13:14 TimMc: mk: Rather: https://gist.github.com/3218623

13:22 m0smith: nDuff: One last question I hope. When I copy the resulting .js file to my webserver directory, it is looking for a deps.js but I can't see where that is supposed to come from

13:29 pbostrom: m0smith: I think it's a GClosure compiler thing, I get rid of it by putting this inline in the html: <script type="text/javascript"> var CLOSURE_NO_DEPS = true; </script>

13:30 nDuff: m0smith: set CLOJURE_NO_DEPS=true in your javascript before including it.

13:30 pbostrom: m0smith: before loading your .js file

13:30 nDuff: Ahh.

13:30 * nDuff missed that pbostrom was answering the same thing.

13:31 tufflax: Is it sane to want letmulti---local multimethods in a function?

13:31 m0smith: Thank you both. That got rid of that error.

13:32 Now I just have to figure out how to get JS to call my code

13:33 rplevy: is jetty-util incompatible with ring-jetty-adapter, and if so does anyone know a version combination (or something) that is compatible?

13:35 the stack trace is especially unhelpful here, but I get a classnotfound for org.eclipse.jetty.util.component.Destroyable

13:35 weavejester: rplevy: What's jetty-util?

13:37 emezeske: m0smith: (defn ^:export my-fn [] ...)

13:37 nDuff: emezeske: last I knew, m0smith wasn't using advanced compilation (yet).

13:37 emezeske: m0smith: That tells the google closure compiler to make that function available to JS even when advanced optimizations are on

13:37 nDuff: Well, good to get in the habit now

13:37 nDuff: *nod*

13:38 m0smith: ...so, it should just be your.module.name.your_function(args), that is, completely normal javascript calling convention

13:40 eggsby: hey thanks technomancy using the master branch fixed the problem

13:40 m0smith: nDuff: I look in the .js file and none of my code, namespaces, etc is in there. At least a naive search does not find it

13:47 nDuff: Hmm -- there's an error in the source, and cljsbuild is only reporting it once, silently failing on subsequent passes. That's annoying.

13:48 rplevy: nm I was just had the name of a class wrong because they changed it recently

13:48 * nDuff grumbles about m0smith using use rather than require all over the place.

13:48 rplevy: and jetty-utils is included already

13:49 m0smith: nDuff: Should I use require instead? Use is slightly more convienent is all

13:50 emezeske: nDuff: If you can reproduce this "only reporting an error once" problem, open a bug

13:52 nDuff: emezeske: Can, but not sure I have the time to build a minimal reproducer right now. Also, likely a lein-cljsbuild thing rather than a cljs thing proper.

13:53 m0smith: nDuff and emezeske: I was :use to include a file that defined a protocol. That would cause the error. Swtiching to :require fixed the error and makes more sense anyway

13:54 technomancy: m0smith: whaaaaat?

13:54 I don't think that's possible

13:54 * nDuff doesn't know _why_ that fixes the problem... but yes, it does.

13:54 * nDuff <- doing no small amount of head-scratching on this end too.

13:54 * technomancy mutters something untoward about protocols

13:54 emezeske: nDuff: Well, if you aren't willing to make a repro, it's not getting fixed, because I have never seen that problem.

13:57 m0smith: technomancy: Debuggin a cljs problem.

13:57 technomancy: oh, ok; I know nothing about cljs

14:13 mk: is a var (setting aside dynamic scope) simply an atom but with only the reset! change semantic?

14:14 gtrak`: mk: vars are namespaced

14:14 I guess that's the dynamic-scoped bit

14:15 but they're also carry a thread-local stack for mutation, atoms are synchronous between all threads

14:15 s/they're/they

14:16 cemerick: saying "X is like an atom, but without the atomicity" is a curious comparison to try to make :-)

14:16 amalloy: cemerick: i don't think vars are missing any atomicity

14:17 alter-var-root behaves like swap, and binding can't ever have contention/races

14:17 mk: isn't the stack only used in dynamic scope?

14:17 gtrak`: mk: stack is used on lookup

14:18 mk: but if there's nothing put on the stack using binding, or the var isn't defined dynamic in the first place (do I have that right?), then it's simply an atom, and it's not thread-local

14:18 gtrak`: it's not an atom...

14:19 mk: gtrak`: right, I mean that it might as well be

14:19 gtrak`: so... why would I prefer to use (def a (atom 0)) instead of (def a 0)?

14:20 mk: I have no idea, at the moment

14:20 foodoo: changing of (def a 0) is only intended for development purposes. Isn't that the issue?

14:21 Gnosis-: How does one decide whether to use an atom or a ref?

14:21 gtrak`: it might be more a statement of intent I guess

14:21 convention

14:21 amalloy: Gnosis-: use a ref if an atom lacks a feature you need

14:21 Gnosis-: ah, okay

14:22 mk: foodoo: I don't know. It's a bad idea to confused def with assignment, so perhaps that convention is there to avoid misleading those new to clojure

14:22 amalloy: the only features i can think of are: coordinating with other refs; being able to return something other than the current value from a swap! (that one can be worked around, but it's easier to just use a ref)

14:23 mk: but really, it seems like (def v ...), used to assign a new value to v, isn't that much different from (swap! ...)

14:23 gtrak`: swap! takes a function and does a compare-and-swap

14:23 spin-loops if it has to

14:23 mk: gtrak`: you're right, I meant reset!

14:23 gtrak`: right

14:25 pbostrom_: there may also be a time when you want to coordinate side effects with a single ref

14:26 gtrak`: looks like var roots follow volatile semantics, JLS only guarantees 32-bit reads to be atomic

14:26 mk: and yes, like amalloy said, alter-var-root covers swap! (and therefore compare-and-set!)

14:27 gtrak`: probably not a real issue if you use boxed numbers

14:27 mk: I was under the impression that atoms offered something in addition to vars, but really, vars are effectively atoms, and in addition they provide dynamic scope

14:28 gtrak`: mk: it's misleading to keep saying that

14:28 atoms and vars are implemented totally differently

14:28 mk: gtrak`: I welcome correction :)

14:28 gtrak`: and have different use-cases

14:28 cemerick: amalloy: Of course; s/atomicity/CAS, but that wouldn't have rolled off the keyboard as nicely.

14:28 gtrak`: well, you know, for these things I like to just look at the source code

14:29 hiredman: vars are interned, they are linking construct, not a state management construct

14:29 mk: gtrak`: it doesn't matter if something is implemented + 4 1 or + 1 4, it's still the same result, unless one is faster. Vars seem to offer all of the features that atoms do, and then some

14:30 hiredman: they seem to have everything you need in order to manage state

14:30 gtrak`: vars are volatiles... atoms are AtomicReferences under the hood

14:30 mk: gtrak`: I'm not saying that one extends the other

14:31 gtrak`: what do you mean by volatiles?

14:31 gtrak`: there's a java keyword 'volatile' that offers particular memory semantics

14:31 hiredman: mk: the semantics of swap! are clearly a compare and swap, alter-var-root's semantics are not really defined

14:32 gtrak`: I think even if semantics were the same, the argument is the same as using a global vs a local... don't

14:32 hiredman: multiple alter-var-root's from different threads can stomp on each other

14:32 vars are a linking construct

14:32 mk: hiredman: I don't think swap! does comparison unless you implement that in the function (which you can)

14:32 hiredman: clojurebot: vars?

14:32 clojurebot: http://www.slideshare.net/mudphone/fun-with-vars

14:33 hiredman: clojurebot: vars |are| a linking construct

14:33 clojurebot: You don't have to tell me twice.

14:33 hiredman: mk: swap! is a CAS

14:33 e.g. if the value of atom changes it reruns the functions on the new value

14:34 augustl: how do you call a Java constructor that takes varargs? Just passing (MyThing. foo bar baz) doesn't seem to work.

14:34 gtrak`: augustl: into-array

14:34 varargs are arrays in java

14:34 hiredman: at the jvm level vargs don't exist, the java compiler turns java varargs in to an array

14:35 mk: hiredman: I'm pretty sure alter-var-root does the same. "atomically alters the root binding by applying f..."

14:35 augustl: gtrak`: looking it up, thanks

14:36 hiredman: mk: incorrect

14:36 mk: what happens if the value changes?

14:36 * nDuff tries to remember how to get from ([a b] [a b] ...) to (a a ...) (b b ...)

14:37 gtrak`: turns out alterRoot is synchronized anyway, that's slower than a CAS generally

14:37 hiredman: mk: if you aren't going to read what I type I will also put you on ignore, I told you what happens already

14:38 TimMc: nDuff: map vector

14:38 mk: hiredman: sorry, it's possible that I missed what you said among the other messages, or didn't understand you. I'll read up

14:38 TimMc: nDuff: Possibility of infinite seq?

14:39 nDuff: TimMc: Not necessarily infinite, but big enough that memory use is a relevant concern.

14:39 mk: hiredman: I still don't see where you answered my question

14:40 nDuff: mk: I do.

14:41 mk: <hiredman> e.g. if the value of atom changes it reruns the functions on the new value

14:41 mk: I'm not talking about atoms, I'm talking about vars

14:41 nDuff: ...

14:41 mk: you were given an example of a behavior atoms have that vars don't. That's pretty relevant.

14:42 mk: we're talking about alter-var-root. Doesn't that restart, in exactly the same way as atoms do?

14:43 I could be wrong, but that's what I'm taking the documentation to mean when it says "atomically"

14:43 hiredman: no, it locks, unlike atoms

14:43 aphyr: What's the canonical way to do exponentiation in 1.3? add clojure.math.numeric-tower?

14:45 foodoo: clojure.math is not an official library, is it?

14:46 gtrak`: mk: CAS is a processor instruction, much more fine-grained than locking on the var object, you might get a similar result, but the semantics and implementation aren't the same

14:46 amalloy: aphyr: (reduce * (repeat n b)) is pretty easy if your exponent is an integer

14:47 mk: I see. So vars offer all the functionality of atoms, but in some cases atoms offer better performance at the cost of potentially executing (hopefully pure) functions repeatedly

14:47 aphyr: Yeah, kinda floored that this isn't builtin, haha

14:47 foodoo: I usually do (Math/pow a b)

14:47 gtrak`: yea, that's the whole point of CAS

14:47 aphyr: (need something that supports the rational types)

14:47 amalloy: aphyr: it is built in, you are on the jvm

14:47 zerokarmaleft: how large would a set of bindings in a let be before being considered non-idiomatic or bad style?

14:47 gtrak`: it's a case of cpu manufacturers pandering to software implementers

14:48 hiredman: ~vars

14:48 clojurebot: vars are a linking construct

14:48 technomancy: zerokarmaleft: it depends on whether you're using them all in the body or using them to construct further bindings

14:48 amalloy: but seriously the core lib is so huge there's no reason to pollute it with operations that are easily constructed by composing existing stuff

14:48 mk: it should be added to that that vars offer all the same functionality as atoms

14:48 zerokarmaleft: technomancy: to construct further bindings, but the last set of bindings are also used in the body...for readability

14:49 aphyr: amalloy: just weird that there's +, -, *, /, but expt requires changing project.clj. First language I've ever used where that was the case, haha.

14:49 zerokarmaleft: it just smells...imperative, in a way

14:49 technomancy: zerokarmaleft: in that case I'd be comfortable letting it get pretty big, but consider whether you can't rewrite it using ->

14:49 foodoo: aphyr: well, you can still use (Math/floor x y)

14:50 if you are on the JVM

14:50 mk: whenever vars and def are brought up, people suggest that they shouldn't be changed at runtime, hinting that the reason for this is some sort of concurrency issue ("use atoms instead when you want concurrency")

14:51 but vars are as safe as atoms. Potentially more safe, since they block instead of repeatedly executing.

14:51 nDuff: mk: If nothing else, rebinding is going to make it hard on people reading your code.

14:51 hiredman: ~vars

14:51 clojurebot: vars are a linking construct

14:51 technomancy: no

14:51 they're less safe because they don't have to be dereferenced, so you can have mutability sneak into a function that looks pure

14:52 don't do it

14:52 nDuff: (inc technomancy)

14:52 lazybot: ⇒ 34

14:53 mk: technomancy: not sure that I follow how that might happen

14:54 amalloy: mk: (defn f [x] (+ x config/batch-size))

14:54 is (f 10) always the same value or no?

14:55 joly: not referentially transparent if the var value is going to change

14:55 that's bitten me before

14:56 technomancy: technically it's very difficult to write clojure functions that are guaranteed referentially transparent exactly because of alter-var-root and runtime-def, but for most purposes "referentially transparent unless someone does something completely daft" is perfectly fine.

14:57 aphyr: How do you feel about the use of dynamically bound vars for IO, though?

14:57 e.g. print-dup, out, etc?

14:58 technomancy: aphyr: the presence of *earmuffs* in a function makes it obvious that a function isn't referentially transparent, so there's not much room for confusion

14:58 mk: I think I see. We want to make sure that we have an explicit @ (or deref) at the start of all such values

14:58 technomancy: well, and the whole IO thing of course

14:58 aphyr: Yeah, like (prn) is definitely not referentially transparent, not even in the fixed IO sense. ;-)

15:00 mk: I was initially worried about what was happening when I defn'd using the repl. I was under the impression that this might put the entire program into an invalid state

15:00 technomancy: mk: that happens in some other languages (ML-based ones in particular) since they don't have the concept of vars, your changes do not apply retroactively.

15:01 different parts of the program will have access to a different version of your function

15:01 (this is true of some Clojure constructs like defmacro and defprotocol, which is one of many reasons you should always use defn if you can)

15:02 mk: is this still the case in clojure, in some rare cases? for example, a thread in a long-term recurring function

15:02 technomancy: if it goes through a var, it's safe

15:02 if it dereferences the var and holds on to the raw fn, then it will retain the old value

15:04 mk: ok, all of this is very good to know. I take it that the problems with mutation don't apply if I'm mutating things intentionally using the repl?

15:04 technomancy: right; the primary reason (possibly only reason?) vars are mutable is to support interactive development.

15:05 foodoo: they do, because you may have suprising results. But when in doubt, restart the repl

15:06 mk: foodoo: I'd like to try to know about those surprises, because if I'm using the repl to crunch a few hours of data, restarting isn't practical

15:06 foodoo: if you have some old functions that still exist in the repl but don't exist in your code

15:07 and you accidentally invoke them again for whatever reason

15:07 mk: I take it that we covered the main ones (not going through a var, and defmacro/defprotocol)

15:08 technomancy: in web apps you often see stuff like (run-jetty #'myapp {:port 8080}) in order to pick up dev-time reloads of myapp

15:11 mk: the way I'm thinking of it now, atoms are for the program to modify, while vars are there for the programmer; keeping in mind that changing a var might make a transparent-looking function no longer transparent, they're both safe in that changing them usually won't break clojure

15:18 dnolen_: mk: also if you use a def to change the value of something that should be an atom the likelihood of another Clojure programmer using your lib will diminish to zero ;)

15:18 someone should ad that case to kibit.

15:18 add

15:19 ohpauleez: dnolen_: It's a good idea

15:19 dnolen_: Raynes: even better if reheap got kibit support :) not sure if you've tried that yet.

15:19 technomancy: kibit-as-a-service

15:19 dnolen_: Raynes: it would give refheap the oneup over all the other Clojure paste services.

15:19 technomancy: does kibit require eval?

15:20 dnolen_: technomancy: no.

15:20 technomancy: cool

15:20 ohpauleez: technomancy: no

15:20 it's totally static

15:21 technomancy: oh gross, it tells you to replace single-clause if with when

15:21 danlarkin: yesssssssssssssssssss

15:21 amalloy: technomancy: i told you, you're hugely in the minority in preferring it the other way

15:21 mk: dnolen_: that should never happen, assuming that the programmer knows to only use def manually, right?

15:21 (via source, or repl)

15:21 danlarkin: amalloy technomancy: agreed

15:22 ohpauleez: technomancy: Why would you want it another other way?

15:22 technomancy: ohpauleez: because use of when indicates side-effects

15:22 ohpauleez: You're ticket still sits in the kibit repo for that haha

15:23 dnolen_: kibit (technomancy remix) ?

15:23 technomancy: huh... Kibit's reader crashed; see kibit.check/read-file:java.lang.RuntimeException: Invalid token: ::friend/unauthorized-uri

15:23 I guess that is a pretty weird keyword

15:24 ohpauleez: technomancy: because of a bug in clojure you can't do scoped keywords

15:25 technomancy: I can *sort of* see your point about `when`, but I personally don't think of side effects when I see `when`

15:25 I think of a clause where this is only a true branch, and nothing more

15:25 qerub: Is there an any? function somewhere in clojure.core? It should work like (defn any? [f seq] (reduce #(or %1 %2) (map f seq))).

15:25 pjstadig: don't worry technomancy i've got your back

15:25 ohpauleez: hahaha

15:25 aphyr: (some?)

15:26 technomancy: ohpauleez: so you think it's a design flaw that you can call if with only two args?

15:26 dnolen_: qerub: some, but note it doesn't return true/false

15:26 uvtc: ohpauleez: My understanding is `when` has an implied `do`, therefore you use it when you want side-effects.

15:26 pjstadig: the battle lines are drawn!

15:26 ohpauleez: hahah

15:26 qerub: dnolen_: Thanks!

15:26 danlarkin: pjstadig: you and technomancy are clearly wrong and you know it

15:26 ohpauleez: everyone, place your bets

15:26 technomancy: it's not like this is a thing I made up; it's a long-standing convention even from older lisps

15:26 pjstadig: i know only that you are wrong, danlarkin

15:27 technomancy: even used in CL, which is famous for not giving a crap about FP and side-effects

15:27 aphyr: (when) is easier to debug with print statements. :-P

15:27 technomancy: aphyr: which are (wait for it) side-effects =)

15:27 amalloy: technomancy: ::foo/bar is a token that can only be read if you're eval'ing as you go :P

15:27 technomancy: if you need to debug in an if, use (doto x prn)

15:27 amalloy: which seems like a pretty terrible choice for clojure's reader

15:27 aphyr: Yeah, but it's not like (if is free of side effects either. :/

15:28 ohpauleez: technomancy: I totally recognize the convention, and I don't think two arg if is a design flaw

15:28 technomancy: aphyr: of course; if is more general

15:28 aphyr: if/when only clues you in as to whether the *immediate lexical scope* has side effects

15:28 not a very useful distinction in my mind :/

15:28 ohpauleez: I think two arg if leads to unintential bugs at times, and I think when is more readable. Implicit do or not

15:28 danlarkin: ohpauleez +1

15:29 I think we won

15:29 technomancy: pft

15:29 ohpauleez: haha

15:29 pjstadig: how is when more readable than a single branch if

15:29 they're like practically the same thing

15:29 technomancy: I've never seen a bug come from if; what would be an example of that?

15:29 pjstadig: except that a when can have side-effects

15:29 qerub: Hey technomancy! Long time no see. Do you still do any Ruby nowadays?

15:29 amalloy: technomancy: you probably haven't read the ten thousand SO questions on (defn ! [n] (if (zero? n) 1) (* n (! (dec n))))

15:30 mk: the reason you use when instead of if is the same reason for using for ( : ) in java instead of for (int i=0;i...). By using when, you save readers having to decide each time they look at the word whether or not the branch has an else or not.

15:30 technomancy: amalloy: ok, how about a mistake that someone who actually knows the language would make?

15:30 qerub: whoa; hi. long time.

15:30 mk: as a convention, neither when nor if guarantee that something will or won't have side effects

15:30 technomancy: qerub: I'm actually picking back up a bit of ruby for my work at heroku

15:31 pjstadig: mk: that would be true, except that if can have one or two branches

15:31 so it's not exactly a single/double branch split

15:31 xeqi: heh, I use `when` without side effects all over the place for lein's pom generation

15:32 ohpauleez: technomancy: minimal. But I still think only-true-branching is more readabe as when - especially when you're tracing through code and debugging

15:32 for a similar reason stated by mk

15:32 haha I'm also amazed at how everyone is jumping in the pit here

15:32 :)

15:32 That said, I come from CL and Python, so I'm a convert

15:32 mk: pjstadig: sure, so use when. Then in all cases where readers see your code, they won't wonder. And if they run into an if with one arg, they can change it to a when

15:33 technomancy: I don't know java, so that example doesn't make sense to me

15:33 pjstadig: i guess the thing is that "when can have have side-effects" is more objective than "readability" arguments

15:33 wingy: what do you think about backends-as-a-service such as Parse?

15:34 pjstadig: if all it boils down to is "readability" then is seems more sensible not to make rules couched in absolute language

15:34 technomancy: there's nothing more readable about it. it's a two-character token vs a four-character token

15:34 mk: technomancy: using an iterating construct versus manually iterating over the array yourself. Each time you look at the latter, you have to decide if it's doing the former.

15:34 ohpauleez: pjstadig: I'll agree with that

15:34 danlarkin: the way I read "if" is ok here comes a choice of two things

15:34 and if there aren't two things it messes up my read-flow

15:34 pjstadig: danlarkin: but that's just not true

15:34 technomancy: danlarkin: so you're ignoring the fact that it works with one

15:35 ohpauleez: but does the implicit do really make you feel that strongly about the side-effects. it's not like when is HIDING the side-effect

15:35 qerub: technomancy: Will it be frustrating to code Ruby again? I'm flirting with Clojure because it isn't a joy to code functionally in Ruby.

15:35 technomancy: ohpauleez: it turns when into a more specific form

15:35 ohpauleez: if you can use that extra specificity to communicate something to the reader, you should

15:35 ibdknox: dnolen_: are there thoughts on the changes needed to use the cljs analyzer on JVM Clojure? (i.e. allowing unaliased :require and naked :use)

15:35 mk: pjstadig: the point is that tons of people aren't even familiar with this convention. You'll have whens without sf, and lone ifs with them. So unless you already know the code, you'll have to verify anyway, so what's the use?

15:35 pjstadig: technomancy ohpauleez: and objectively so

15:35 ibdknox: dnolen_: and :import

15:35 ohpauleez: technomancy: So intent. Sure, I can see that

15:36 pjstadig: readability is a bit more subjective

15:36 technomancy: mk: that's why it's good to raise awareness of the convention, because people are confused about it.

15:36 qerub: it's definitely frustrating on the tooling side; things have gotten so much more complicated

15:36 ohpauleez: so you're objectivity about "side-effects" is really just readability based on intent

15:36 technomancy: and I don't even have to deal with rvm

15:36 ohpauleez: You see when and you think "here come the side effects"

15:37 danlarkin sees when and he thinks, "he comes the truth"

15:37 pjstadig: i don't have heart burn over the fact that there's an if somewhere and i should be expecting to see a else clause...and oh no! it's not there! my world is crashing down! as some people seem to think

15:37 qerub: technomancy: What are you thinking of in particular? Bundler…?

15:37 technomancy: qerub: yeah, mostly that. I get a lot of bug reports coming from rvm, so even though I don't use it myself I still have to deal with it =\

15:38 qerub: technomancy: Oh, right; rvm and company.

15:38 dnolen_: ibdknox: related, stuarthallowy has brought up conditional reading ... I'm not sure exactly how the analyzer should be improved to deal w/ full Clojure ... worth figuring out

15:38 pjstadig: ohpauleez: but when you're talking about someones thoughts you're talking about subjectivity

15:38 mk: technomancy: I agree that marking sf is useful, but I think that should be marked in the function itself, not by using when to say "here come side effects... trust me"

15:38 qerub: technomancy: I like what you have done with Leiningen. It's a joy to use. Thanks!

15:38 dnolen_: ibdknox: also, ambrosebs has got something as well.

15:38 technomancy: qerub: also this tendency to just overcomplicate things; I'm working on a test suite that has a define_method inside an instance_eval just to allow for slightly more declarative test definitions, but just causes trouble down the road

15:38 pjstadig: it is an objective that if cannot have a then clause with a side-effect, unless you use a do

15:38 technomancy: qerub: thanks

15:38 ibdknox: dnolen_: his is still using the JVM analyzer though, right?

15:38 pjstadig: or just use a when with an implicit do

15:39 qerub: technomancy: Haha, I feel your pain.

15:39 technomancy: mk: that's a valid desire, but it entails changes to the language itself. I'm talking about working with what we've currently got.

15:40 ibdknox: dnolen_: yeah, and he's making it look like the CLJS output

15:40 dnolen_: ibdknox: perhaps, I haven't looked at it closely. If you want to lead the discussion on this please do, as you really need this stuff, I'll definitely chime in and chip in where I can.

15:40 ibdknox: dnolen_: k, I'll start up a thread later tonight

15:40 dnolen_: ibdknox: standardizing analyzer output, getting column data are two big things. I think column data isn't going to go anywhere without some one spending sometime to write up rationale.

15:41 ohpauleez: &(if true (println 1))

15:41 lazybot: ⇒ 1 nil

15:41 mk: technomancy: you're right about that, but I still worry about bugs due to trusting a misleading lone if. The convention seems to be there for the sake of efficiency, but ensuring a lack of side-effects in critical places shouldn't be made "efficient"

15:42 (programmer efficiency)

15:42 technomancy: "If the value of the if form is important in this situation, then the and construct may be stylistically preferable, depending on the context. If the value is not important, but only the effect, then the when construct may be stylistically preferable." - http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html

15:42 ohpauleez: I'm fine reading both forms, and personally I think both things when I read `when`

15:42 "Only true branch, implicit do"

15:42 technomancy: mk: seeing an if means you can't infer anything

15:42 because if is more general, and when is more specific

15:43 mk: technomancy: oh, well in that case you're probably right

15:44 scgilardi: that's "and" vs "when" and I agree with it

15:44 technomancy: and is only for return values, when is only for side-effects, if is somewhere in between due to being more general

15:45 mk: on the other hand, if you mislead some people into fearing sf when there really aren't any by using (when), then not much harm is done

15:45 pjstadig: "As a matter of style, when is normally used to conditionally produce some side effects, and the value of the when form is normally not used."

15:45 qerub: Bye for now!

15:45 pjstadig: ibid.

15:45 ohpauleez: nice to see scgilardi ringing in :)

15:45 pjstadig: what clojure needs is an 'unless' macro

15:46 scgilardi: :)

15:46 ohpauleez: pjstadig: (the-real-when ...)

15:47 to discourage more sideffects

15:47 technomancy: I think the readability argument only flies if you don't indent properly

15:47 pjstadig: i always found it confusing the way people used if and unless suffix conditions in ruby

15:47 especially when the conditions were negative

15:47 ohpauleez: pjstadig: same

15:48 pjstadig: something unless !notFooBar

15:48 technomancy: pjstadig: the one place I can see that making sense is "raise IOError if disconnected"

15:48 ohpauleez: technomancy: I disagree, but I also have a greater tolerance for when abuse

15:48 even for its return values

15:48 pjstadig: well sure with an if suffix

15:48 technomancy: because having a non-conditional raise makes absolutely no sense

15:48 pjstadig: but unless especially with complex conditions with ands and ors is confusing

15:49 technomancy: agreed

15:49 pjstadig: i think if suffixes can actually read better sometimes

15:50 or more naturally

15:50 uvtc: In Perl, I think `unless` works well for unlikely events: print "things went well, as expected." unless $catastrophe

15:51 Also, Clojure has `if-not` to use if you want `unless` ... (though, there's no implied `do` with `if-not`, fwict)

15:52 ohpauleez: uvtc: `when-not`

15:52 Gnosis-: it would be pretty simple to write an 'unless' macro...

15:52 mk: right, unless is for when you want to make the code seem like it's a normal part of the block, and not a special case

15:52 uvtc: ohpauleez: Hahah. Missed that. Thanks. :)

15:53 pjstadig: that's true

15:53 when-not is basically the 'unless' macro

15:54 arohner: I use 'when' all the time in non-side-effecting code

15:55 mk: for similar reasons, in c-syntax languages I end up converting long ifs which trail down to the bottom of a method or loop into if ( not condition) {... return, or break}

15:55 arohner: but IMO, one-armed ifs should be a syntax error

15:56 pjstadig: arohner: i would actually support that

15:57 Raynes: dnolen: There is an open issue for that.

15:57 pjstadig: let's end all the senseless violence

15:57 mattmoss: Everytime I see someone address ohpauleez, it sounds in my head like someone sighing, rolling their eyes and saying, "Oh, puh-lease..."

15:57 ohpauleez: mattmoss: That's the idea :)

15:58 Raynes: arohner: technomancy hates your guts.

15:58 ohpauleez: it's how most people address me

15:58 mattmoss: I am Master of Obviousness. :|

15:58 aphyr: (if [float? x) (write-float sock x) (write-int sock x)) etc

15:58 ohpauleez: :)

15:58 uvtc: pjstadig: Yes. Can't we all just get along ... ... ... and agree to rename `not=` to `!=`. ;)

15:59 aphyr: While we're at it, rename set! to =!

16:00 ohpauleez: uvtc: `!` implies stateful change :)

16:00 mattmoss: (with-perl-noise (=! (!= ...)))

16:03 uvtc: ohpauleez: interesting way to look at it, even though it's a leading and not a trailing `!`. Semi-related, I'd always thought that the single-quote mark implied quoting, but just yesterday learned of +'

16:04 Any idea why the trailing single quote mark was chosen for that?

16:04 Bronsa: mathematic notation?

16:04 f, f', f'' etc

16:04 uvtc: Ahhhh..... prime.

16:04 augustl: how do I add Java interop return type metadata when I already have a ^{:private true} metadata there? Normally I use #^TheReturnType

16:04 uvtc: Heh. Nice.

16:05 Bronsa: , (let [a'a'a'a' 1] a'a'a'a')

16:05 clojurebot: 1

16:05 Bronsa: :D

16:07 Gnosis-: that's an acceptable name?

16:08 uvtc: Gnosis-: acceptable to whom? :)

16:08 amalloy: if you're tarzan

16:08 mk: Gnosis-: by the compiler, but maybe not by humans

16:08 Gnosis-: I meant acceptable to the compiler, haha

16:10 pjstadig: augustl: ^{:tag TheReturnType :private true}

16:10 amalloy: pjstadig: or just use both; metadata tags stack iirc

16:10 mk: Gnosis-: technically any chars are allowed, except for a few reserved ones, and it's not clear what the reserved ones will actually be, so... most are disallowed

16:10 amalloy: &(meta ' ^String ^:private x)

16:10 lazybot: ⇒ {:tag String, :private true}

16:11 augustl: pjstadig: is this documented somewhere? :)

16:11 aphyr: augustl: seem to recall it's on the java interop page

16:11 augustl: nothing about #^ on the java interop page

16:11 Gnosis-: mk: how can they be reserved if the current compiler accepts them without complaining?

16:11 mk: I don't see any reason that unicode shouldn't already be allowed, since there's little chance that anything reserved by clojure will come from there

16:11 pjstadig: ,(meta '^String x)

16:11 clojurebot: {:tag String}

16:12 augustl: where is the ^foo ^bar meta type syntax documented btw?

16:12 mk: Gnosis-: :: and // etc. are reserved. +'- and many others are explicitly not reserved. Most symbols will eventually not be reserved.

16:12 pjstadig: stacking works too

16:12 ,(meta '^String ^:private x)

16:12 clojurebot: {:tag String, :private true}

16:12 mk: Gnosis-: more details http://clojure.org/reader

16:12 pjstadig: augustl: #^ is deprecated syntax

16:12 Gnosis-: pjstadig: what does '^ mean?

16:12 pjstadig: i guess the question is where you read that :)

16:13 augustl: pjstadig: ah

16:13 I should read the entire doc some day..

16:13 no idea what # actually is :)

16:13 Gnosis-: mk: ah, thanks

16:14 pjstadig: Gnosis-: ' just means quote the next that is coming and in this case the next thing happens to be a type tag and you don't need a space after the quote

16:14 ,(meta ' ^String ^:private x)

16:14 clojurebot: {:tag String, :private true}

16:14 pjstadig: adding a space works too

16:14 or

16:14 ,(meta (quote ^String ^:private x))

16:14 clojurebot: {:tag String, :private true}

16:14 uvtc: Bronsa: Gnosis- : now that you mention it, what's the opinion on using a single-quote/apostrophe in symbols, like `ted's-room` or `it's-looking-good`?

16:14 pjstadig: which is kinda what it becomes

16:14 ,''^String ^:private x

16:14 clojurebot: (quote x)

16:14 augustl: I suppose this is a symptom of reading code instead of reading docs to figure out how stuff works

16:15 uvtc: ,(let [it's-looking-good true] (when it's-looking-good (println "happy day")))

16:15 clojurebot: happy day

16:15 pjstadig: ITYM, 'if' :)

16:15 mk: the various special symbols are there for lazy programmers. Instead of always having to type and look at (deref a), we can write @a, and the reader replaces it

16:18 tufflax: I want to implement my own data structure that shall support conj and pop. I'm using defrecord and I must specify which interface/protocol I'm implementing. So which protocol/interface supports conj and pop? Seq? Is that the name I'm looking for?

16:23 mk: tufflax: https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang probably ipersistentcollection or something

16:25 tufflax: mk thanks

16:28 technomancy: is it just me, or is it ironic that the clojure source uses "jvm" for its java code despite repeated insistence that the JVM and Java are not the same thing?

16:28 I mean, I understand it's a hold-over from when the clr implementation was kept in the source tree, but I'm still amused by it

16:29 pjstadig: technomancy: just rename it...patches welcome

16:29 mk: maybe "stuff for targetting the jvm"?

16:29 gfredericks: s/clojure/lava/ while you're at it

16:29 pjstadig: haha

16:29 personally i think Sybilant is a better name than Clojure

16:29 but who am i to say

16:30 hiredman: lava is really hot right now

16:30 Raynes: technomancy: You'll be sorry when they start adding scala source code.

16:31 technomancy: Raynes: someone is actually using lein-scalac to avoid sbt

16:31 mk: are agents guaranteed to execute things in order of sending?

16:31 technomancy: makes me happy

16:32 pjstadig: mk: for the 'things' sent from the same thread, yes

16:33 llasram: maybe best to say that agents execute things in the order received? :-)

16:33 mk: llasram: perhaps, though a send and receive is presumably the same thing :)

16:34 pjstadig: will things sent from different threads be queued out of order?

16:35 llasram: If that's your definition, then definitely yes -- the purpose of agents is to serialize asynchronous updates to a identity

16:37 mk: llasram: ok, good. I was thinking that the spec might have left open that the actions are placed in a set rather than a queue, or that one might create an agent with a priority queue

16:37 I guess that can't be done

16:37 acheng: ,(let [a 1] (eval (read-string "a")))

16:37 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

16:38 acheng: "Unable to resolve symbol: a in this context"

16:38 tufflax: Hm, IPersistentCollection specifies that cons is part of the interface but not conj, what's up with that?

16:39 I don't see any interface mentioning conj

16:39 llasram: mk: Ah, not that I'm aware of. You'd probably need to create your own new reference type to support that sort of thing

16:41 gtrak`: mk: that kind of goes against the state-change aspect of an agent, yea? sounds like you just need the worker pool part

16:41 llasram: To the `future`!

16:42 mattmoss: ,(class 'a)

16:42 clojurebot: clojure.lang.Symbol

16:42 mk: acheng: interesting - same thing for ,(let [a 1] (eval 'user/a)) I'm not sure why that happens

16:42 mattmoss: ,(class #'a)

16:42 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: a in this context, compiling:(NO_SOURCE_PATH:0)>

16:42 mattmoss: ,(let [a "a"] (class #'a))

16:42 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: a in this context, compiling:(NO_SOURCE_PATH:0)>

16:42 mattmoss: Hmm.

16:42 dnolen: tufflax: the names in Clojure don't always reflect the names used for the Java Interfaces - look at RT.java. fwiw, the naming between fns & protocols is more consistent in ClojureScript.

16:43 gfredericks: mattmoss: ##(class #'clojure.core/nth)

16:43 lazybot: ⇒ clojure.lang.Var

16:44 tufflax: dnolen so my original problem: what should I put as interface in my defrecord when implementing conj?

16:44 mk: gtrak`: well, one might want a construct that doesn't care about the order of incoming actions, but does care about preserving state. This is different from a worker pool

16:44 mattmoss: thanks, g

16:44 dnolen: tufflax: whatever is in IPersistentCollection - cons + whatever else.

16:45 I mean cons + whatever that interface defines

16:46 amalloy: tufflax: you can't have a special impl of conj in a defrecord, only a deftype, afaik

16:46 tufflax: dnolen I think you misunderstood me. When I'm implementing a function in a record, I must state the interface.

16:47 gtrak`: mk: yea, looks like agents don't guarantee execution order either

16:47 tufflax: amalloy hm why not?

16:47 dnolen: tufflax: in records you can implement methods on interfaces, and fns on protocols.

16:47 tufflax: and amalloy is right.

16:47 amalloy: because records are maps. defrecord comes with implementations of all the map interfaces, including conj

16:47 dnolen: tufflax: you're not allowed to customize the map behavior of records

16:48 acheng: hm... if i have a value and a string, is it possible to let-bind the value to a variable named in the string, and then eval the string?

16:48 tufflax: oh i see

16:48 mattmoss: If I do (defn foo [] ...) and (def f #'foo) ... both (f) and (@f) both work. Why? Is it an implicit deref without the @ ?

16:48 Bronsa: vars are implicitly dereffed

16:48 tufflax: Ok then. Say I'

16:48 ops, pressed enter too early :p

16:49 Bronsa: (during function call)

16:49 tufflax: Ok then. Say I'm using deftype, what interface should I state as the interface I'm implementing when I'm defining conj?

16:49 mk: gfredericks: regarding varless symbols, mapped directly to values without an intermediary var, I think part of the problem is that you would no longer have an explicit construct for safely working with concurrency, like (alter-var-root)

16:49 mattmoss: Bronsa: thanks

16:50 gfredericks: mk: alter-var-root is for NOT working safely with concurrency

16:50 mk: gtrak`: interesting - do you have a link to where it talks about that? (agent execution order)

16:51 gfredericks: I thought all sends from the same thread should execute in the same order

16:51 mk: gfredericks: in that case you could just use def, no? alter-var-root has a potential verification function attached

16:51 Bronsa: mattmoss: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L391-412

16:52 acheng: mk: ya, alter-var-root is heavy-handed to the max. i found the only valid use case. it's all mine

16:52 gtrak`: mk: I was looking at this: http://stackoverflow.com/questions/5669084/is-clojures-send-asynchronous

16:52 gfredericks: mk: you could still do changes atomically; namespaces as a whole could be implemented as atoms

16:53 mk: gfredericks: if that's the case for the same thread, then why not for other threads? Don't they all use the same queue?

16:53 pepijndevos: why do zippers use metadata instead of a protocol?

16:53 tufflax: dnolen amalloy: What should I put in my deftype instead of some-interface? (deftype MyDataStructure [data] some-interface (conj [this element] ...))

16:54 gfredericks: mk: I don't know why that wouldn't be the case; it's just non-deterministic when things happen more or less at the same time

16:54 mk: gfredericks: I think you're correct, and I think that I like the idea of namespaces as atoms substantially more than what we have now. I think it might be much easier to understand and think about.

16:55 Bronsa: tufflax: you should put clojure.lang.IPersistentCollection, and replace conj with cons

16:56 tufflax: Bronsa ok. Will I be able to use conj then or just cons?

16:56 Bronsa: cons of clojure.core has nothing to do with cons on the IPersistentCollection interface

16:56 mk: gfredericks: well... things can happen more or less "at the same time" in the same thread. Shouldn't change for extra threads, if a proper concurrent queue is used...

16:56 gfredericks: how do things happen at the same time in the same thread?

16:56 tufflax: bronsa ok

16:57 So how does cons become conj then?

16:57 gfredericks: the source of conj calls RT.cons I think

16:57 or RT.conj calls #cons

16:57 tufflax: ah ok

16:57 mk: is there any reason that namespace maps weren't implemented as atoms?

16:57 pandeiro: does cljs not have clj->js anymore???

16:57 lazybot: pandeiro: Yes, 100% for sure.

16:57 Bronsa: yes

16:58 gfredericks: mk: atoms didn't exist initially

16:58 tufflax: thanks for clearing that up

16:58 Bronsa: RT.conj calls #cons

16:58 mk: gfredericks: how do they happen at the same time in different threads, assuming we've got a concurrent queue?

16:58 gfredericks: mk: I mean the sends are done at the same time; obviously they go into the queue in some order but it's hard to say anything interesting about it

16:59 pandeiro: ah oops, i am a moron, sorry

16:59 i was wanting js->clj

17:00 mk: gfredericks: right. But if we have that guarantee, then logging agents become much more useful, to take one example

17:02 and if we don't have that guarantee, then priority queues can be added to agents

17:05 tufflax: If anyone have the time, please take a look at this longish question http://pastebin.com/iHGwgf6i

17:06 kaoD_: hi

17:06 tufflax: hi

17:06 kaoD_: do multimethods support overloading by arity?

17:06 hiredman: multimethods support everything

17:06 kaoD_: (through overloaded dispatch fn, of course)

17:06 hiredman: that's good news then, I was afraid arity was fixed

17:07 tufflax: has* :P

17:12 kaoD_: tufflax: has?

17:15 tufflax: correction of my previous message

17:16 kaoD_: oh, I thought you were correcting me :P

17:20 mk: the reason agents don't guarantee ordering except in a single thread is that sends are only queued in the agent's queue at the end of a transaction, not at the actual logical time that the send occurs

17:27 cmajor7: does korma (transaction …) rollback on the exception?

17:29 pandeiro: how could i do the Array.prototype.slice.call(someArrayLikeObject, 0) trick with cljs? syntax?

17:30 nm, got it: (.call js/Array.prototype.slice thatArrayLikeObj 0)

17:31 cmajor7: I would think it does: http://dev.clojure.org/jira/browse/JDBC-11 but I am not sure whether I can use a "is-rollback?" to detect that..

17:40 kaoD_: is there any way to slurp stdin until EOF?

17:41 slurp itself seems to stay there waiting for more input (or maybe it's windows' fault)

17:45 mk: (def foo) is equivalent to (intern *ns* foo) ?

17:46 S11001001: kaoD_: yep it's windows's fault; how are you sending eof?

17:47 kaoD_: S11001001: not sending EOF, I expected Windows to append EOF after piping from an echo

17:47 though I'm probably wrong

17:48 S11001001: who really knows; it's windows

17:51 goodieboy: technomancy: hey, i'm thinking about writing a leiningen plugin. Are there directions somewhere to do it properly for the latest leiningen?

17:53 ok, i think this must be the place to look: https://github.com/technomancy/leiningen/blob/master/doc/PLUGINS.md

17:53 kaoD_: goodieboy: I was just going to point you there

17:53 technomancy: yup

17:53 kaoD_: it's unbelievably easy

17:54 goodieboy: kaoD_: good to know :)

17:54 thanks

17:55 emezeske: Once you know about technomancy, though, it becomes believably easy

17:55 Raynes: goodieboy: https://github.com/Raynes/lein-tag Here is a very simple example you can look at too.

17:55 goodieboy: Raynes: awesome thanks

17:56 cgray: technomancy: is writing a lein plugin for any jvm-based language essentially the same difficulty?

17:58 technomancy: cgray: for any compiler that has an ant task (which hopefully should be all of them), yes

17:59 cgray: technomancy: ok, good to know, then I've gotta write an ant task first :)

17:59 Raynes: technomancy: I thought we didn't use ant these days?

17:59 technomancy: Raynes: not for any of the core stuff

17:59 Raynes: but lein-scalac uses it

18:00 Raynes: cgray: Did you invent a JVM language?

18:00 cgray: Raynes: I didn't but there is one being invented at my work

18:00 Raynes: technomancy: You should use uncle.

18:00 technomancy: har har

18:00 Raynes: cgray: Make them stop.

18:01 technomancy: https://github.com/flatland/uncle

18:01 technomancy: I was serious.

18:01 technomancy: oh

18:01 lancet is a bit weird

18:01 but I don't have any plans to develop lein-scalac further, so whatevs

18:02 Raynes: Dude. You should totally turn lein into a complete Scala sy… oh, wait. I guess that's all there is to it, really. Just compiling Scala.

18:02 It's cool how little is necessary to make Leiningen an <insert jvm lang here> build tool.

18:03 technomancy: well the problem with scala specifically is the compiler is so slow that everyone ends up using the incremental compiler, and that's not hooked up to lein

18:03 but it's not my problem =)

18:03 Raynes: technomancy: You're a pretty cool chap.

18:04 eggsby: Raynes: I had to leave the office before I got a chance to thank you last friday -- Thank you!

18:04 Raynes: eggsby: What did I do?

18:05 eggsby: hmm, LA clojure meetup about cljs... wonder if I should go

18:05 Raynes: Besides my normal awesome level which doesn't necessitate thank yous.

18:05 eggsby: Raynes: fixed a retarded thing I did w/ refheap :p

18:06 Raynes: Oh.

18:06 Oh, right. Forgot about that.

18:06 You're lucky refheap has terrible traffic. :p

18:30 muhoo: what's the trick for debugging lein2 plugins? how does one get an in-lein repl to interactively work with the plugin?

18:30 i.e. not the project, but lein itself.

18:30 technomancy: muhoo: if you have :eval-in :leiningen in project.clj, then `lein repl` in the plugin project will put you in the right place

18:31 muhoo: fantastic, thanks!

18:32 technomancy: huh; I realized I added shorthand for forcing a repl to eval-in lein without changing the project.clj in lein1

18:32 oh, but you can do it with lein-assoc in 2.x

18:33 muhoo: whut?

18:33 technomancy: `lein assoc :eval-in :leiningen repl`

18:33 it's a plugin that gives you a higher-order assoc task

18:33 llasram: Ooooh

18:33 technomancy: you can add arbitrary project.clj keys on the command line

18:33 llasram: Now *that* is fancy

18:33 muhoo: oh https://github.com/technomancy/lein-assoc

18:33 technomancy: =D

18:34 muhoo: there is so much fancy stuff in lein these days. it's kind of disorienting

18:34 technomancy: tempted to merge that into lein proper

18:34 muhoo: higher-order tasks open up a lot of possibilities

18:34 muhoo: ya, i was stunned by how quickly raynes put together lein-pdo.

18:35 Raynes: muhoo: I was stunned at how long it took me, actually.

18:35 It was harder than I thought it'd be.

18:35 technomancy: there's always https://github.com/technomancy/leiningen/wiki/Plugins

18:35 but it's not exhaustive

18:35 for instance, Raynes forgot to add lein-pdo =

18:35 )

18:36 mk: how are symbols resolved? As far as I can tell, there's a special map from symbols to vars in each namespace. But is there some sort of secondary map for aliases, and requires? Are aliased symbols added to this map? Is there a separate map for vars that have been set to private?

18:37 technomancy: ,(take 10 (ns-map *ns*))

18:37 clojurebot: ([sorted-map #'clojure.core/sorted-map] [read-line #'clojure.core/read-line] [re-pattern #'clojure.core/re-pattern] [keyword? #'clojure.core/keyword?] [unchecked-inc-int #'clojure.core/unchecked-inc-int] ...)

18:38 technomancy: not sure if that includes aliases

18:38 oh, there's a separate ns-aliases

18:38 mk: does that mean there's a second map, or is it just a filter?

18:39 technomancy: pretty sure it's a separate map

18:39 since an alias by itself isn't a first-class thing afaik

18:41 mk: hmm. When the reader hits a symbol (it is the reader that does this, right?), how many and which maps does it check before finding the var that it will assign inside the form? (it assigns the var, and not e.g. a fully qualified symbol, correct?)

18:42 presumably for fully qualified symbols, the answer is two maps: the global map of namespaces containing the namespace, and then the namespace itself (which is a map) for the name

18:43 wingy: could someone provide datomic hosting?

18:44 muhoo: heh, (pprint (ns-map *ns*)) caused java to go to 99% cpu and nrepl to lock up

18:45 *nrepl-connection* up to 38644 lines

18:45 mk: ,(ns-map 'doesntexist)

18:45 clojurebot: #<RuntimeException java.lang.RuntimeException: java.lang.Exception: No namespace: doesntexist found>

18:46 mk: ,(in-ns 'extant)

18:46 clojurebot: #<Namespace extant>

18:46 mk: ,*ns*

18:46 clojurebot: #<Namespace sandbox>

18:46 muhoo: C-x C-k, problem solved

18:46 mk: ,(in-ns 'extant) (ns-map 'extant)

18:46 clojurebot: #<Namespace extant>

18:47 mk: ,(do (in-ns 'extant) (ns-map 'extant))

18:47 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ns-map in this context, compiling:(NO_SOURCE_PATH:0)>

18:47 mk: ,(do (create-ns 'extant) (ns-map 'extant))

18:47 clojurebot: {ProcessBuilder java.lang.ProcessBuilder, Enum java.lang.Enum, SuppressWarnings java.lang.SuppressWarnings, Throwable java.lang.Throwable, InterruptedException java.lang.InterruptedException, ...}

18:48 amalloy: mk: do you not own a repl?

18:49 TimMc: amalloy: Don't make fun of the poor!

18:49 mk: amalloy: publicly checking how the bot handles namespaces

18:50 muhoo: wow, soon there will be more lein plugins than there are apps in the apple app store.

18:50 mk: ...and making a mistake or two

18:51 muhoo: and yet, rhickey uses ant :-/

18:52 Frozenlo`: o_O

18:53 muhoo: nice, a way to use heroku without having to deal with ruby: https://github.com/technomancy/lein-heroku

18:53 Frozenlo`: Any recommendation regarding tests plugins?

18:53 technomancy: muhoo: keep in mind that's very unofficial =)

18:53 Raynes: I didn't find dealing with Ruby much of an issue.

18:54 technomancy: yeah, actually you don't even need to have rubygems installed anymore

18:58 kaoD_: is there any way to slurp piped stdin in windows and not wait forever for more input?

19:02 technomancy: kaoD_: on unix EOF results in a nil return value from read-line iirc

19:02 not sure about slurp

19:03 kaoD_: technomancy: I'm interested in stdin as a whole, not line by line... I know I can fake it but it just feels hacky

19:03 technomancy: yeah, but you could try it and see if it has the same problem

19:03 kaoD_: you're right, I'll try

19:25 amalloy: is there a clever way to take from a sequence up to, and including, the first item that satisfies a predicate? i think i've written that function before, but not well

19:30 mk: amalloy: source for take-while http://clojuredocs.org/clojure_core/clojure.core/take-while

19:32 metellus: amalloy: the best I can find is split-with or partition-by and then grabbing the first element from the second seq

19:34 gfredericks: amalloy: if nothing satisfies it returns the original?

19:34 amalloy: gfredericks: yeah, that's the plan

19:34 mk: in that source I linked, put the cons in front of the when

19:35 gfredericks: (fn f [pred coll] (if (empty? coll) coll (let [[x & xs] coll] (if (pred x) [x] (cons x (lazy-seq (f pred xs)))))))

19:36 amalloy: gfredericks: never use [x & xs] destructuring when consuming/producing a lazy seq, btw

19:36 & xs uses next, not rest

19:36 gfredericks: amalloy: now I know

19:37 amalloy: i'm always tempted, and usually remember not to

19:38 gfredericks: amalloy: using core.logic for a while made writing that ^ code feel really weird

19:41 mk: (defn take-while' [pred coll] (lazy-seq (when-let [s (seq coll)] (cons (first s) (when (pred (first s)) (take-while' pred (rest s)))))))

19:41 seems to work, and mimics take-while

19:42 gfredericks: maybe name it take-until

19:43 kaoD_: I'm having a hard time realizing when to use macros or when to stick with code... (which probably means I don't understand the subject enough) any quick tips/references?

19:43 mk: or take-along (...the non-matching value)

19:43 rbxbx: kaoD_ avoid macros until it's no longer feasible to do otherwise.

19:45 kaoD_ they're a sharp (and valuable) tool which one should exercise caution in using. As to learning when it's no longer feasible to do otherwise... I guess that just comes with experience?

19:45 kaoD_: rbxbx: that's what I suspected

19:45 thanks

19:45 technomancy: the best way to learn is to try to consume a codebase that uses too many macros

19:46 kaoD_: technomancy: what do you mean consume?

19:46 mk: kaoD_: you don't need to worry that you're missing out on the magic of lisp if you're not spending time defining macros. Clojure has many constructs that set it apart as a much higher-level language, and macros are only a minor part of all that

19:46 technomancy: kaoD_: I mean use it as a library or something

19:46 rbxbx: kaoD_ better yet try to fix a bug in the project's issue-tracker :)

19:47 kaoD_: technomancy: oh, as in "product consumer"

19:47 been there

19:47 (many times with my own macros, haha)

19:48 thanks for the insight

19:48 technomancy: I guess the key is you need to try to use the macros in ways that the original author didn't intend

19:50 emezeske: technomancy: One of the biggest gripes I have with macro-heavy libraries is that they basically force the user to write macros to deal with them

19:50 technomancy: E.g. if you have repetition in your use of a macro that you'd like to factor out, you have to write a macro

19:51 technomancy: heh; yeah, infectious macros

19:51 emezeske: exactly

19:51 kaoD_: and then... why macros? I mean, in which case are they useful? it all comes down to experience or is there any sort of pattern/well-suited task for macros?

19:52 arohner: in core.logic, if I have a logic variable that is a map, how do I write the expression "(== 3 (:foo q))"?

19:52 I tried the naive way and I'm getting NPE

19:53 technomancy: kaoD_: usually if you write a macro you should do it after writing the macroless way first

19:53 amalloy: arohner: i don't think that's possible yet. as of recently it wasn't, anyway

19:53 technomancy: so people can pick which way is appropriate for their circumstances; maybe they don't care about composability and want the extra convenience

19:54 kaoD_: technomancy: ugh, that means double mainteinance

19:54 benedikt: I'm using lein and emacs (+ clojure-mode) for clojure. starting the swank server with "M-x clojure-jack-in" makes it bind to 0.0.0.0. I want to bind to localhost.

19:54 arohner: amalloy: really? seems like it should be possible to build a fn that does that, even if it isn't built in

19:54 benedikt: I ws discussing this here the other day but I never managed to change the bind address.

19:54 technomancy: kaoD_: not really, the macro version needs the function version to exist anyway

19:54 amalloy: kaoD_: wat. write the macro to use the function

19:55 kaoD_: lol, so obvious

19:55 benedikt: technomancy: i belive you said that this is no longer the default behavior, but this is the default behavoir with the current lein.

19:55 amalloy: arohner: it needs hooks into the unification code

19:55 technomancy: benedikt: the version of lein is immaterial; it's the version of lein-swank that matters

19:55 but you might want to try https://github.com/kingtim/nrepl.el instead

19:56 benedikt: technomancy: right. so lein is using an outdeted version of swank?

19:56 hyPiRion: You should keep the amount of macros to a minimum though, they're not first class citizens.

19:56 technomancy: benedikt: right

19:56 benedikt: technomancy: one might argue this is an issue.

19:57 technomancy: thanks for the link, this seems useful.

19:57 technomancy: if you have a solution for how to retroactively fix old versions I would be glad to hear it =)

19:57 benedikt: technomancy: actually, i'm working on this time machine...

19:57 technomancy: sweeeet

19:58 benedikt: so if one uses this nrepl.el, one isn't dependent on lein any more?

19:59 scratch that

19:59 technomancy: no, you still need lein, but you don't need any lein plugins

19:59 benedikt: as long as it doesn't listen to 0.0.0.0 i'm happy.

20:04 arohner: amalloy: looks like (pred) works, as a worst case

20:04 (logic/pred q #(= 3 (:foo %)))

20:04 what does "non-relational" mean, in a core.logic docstring?

20:05 amalloy: it's not a two-way function

20:05 you can't, eg, use that pred to *build* the map {:foo 3}, only to check that it fits after someone else has built it

20:06 arohner: ah, right

20:11 benedikt: technomancy: this one also seems to listen to 0.0.0.0

20:14 technomancy: ugh; crap

20:14 Raynes: what the heck, man?

20:14 arohner: more stupid core.logic questions. How can I write "q is not a member of [x y z]"?

20:15 gfredericks: arohner: "not" is not very natural

20:15 but you can definitely say (!= q x) (!= q y) (!= q z)

20:16 * gfredericks really wishes he knew what he meant by his first statement

20:16 benedikt: technomancy: i'm leaning towards using iptables --- but thats not really a fix for the problem. Personally, I think this is the wrong default, and a dangerous one.

20:17 technomancy: benedikt: it definitely is. it was fixed years ago in swank, but I've only started using `lein repl` a couple weeks ago, so I didn't notice.

20:17 working on a fix

20:17 benedikt: so lein uses a version of swank that is outdated by years?

20:17 arohner: gfredericks: thanks

20:18 technomancy: no, lein uses whatever version of swank you tell it to

20:18 benedikt: the is a messy swamp of tools. then why am *I* using an outdated swank version?

20:18 and what baout nrepl.el

20:19 technomancy: nrepl.el is just using the built-in `lein repl` task, which I'm fixing right now

20:19 I don't know how you installed lein-swank, so it's hard to say anything about that

20:19 benedikt: technomancy: "lein self-install"

20:20 technomancy: that doesn't install lein-swank

20:20 benedikt: ..

20:20 then I dont know either!

20:20 technomancy: you would have had to either put it in your user profile, a project.clj, or run `lein plugin install`

20:20 benedikt: most likely lein plugin install

20:21 technomancy: though that would only work for lein 1.x

20:21 if you're using 2.x, check ~/.lein/profiles.clj

20:21 benedikt: i am

20:22 [lein-swank "1.4.3"]

20:23 technomancy: so does just regular `lein swank` start on localhost or 0.0.0.0?

20:23 maybe it's specific to the elisp launcher?

20:23 mk: the namespace can map directly to classes without first putting them in a var?

20:24 technomancy: hm; actually that's not right; jack-in is hard-coded to localhost

20:25 benedikt: yes and no.

20:25 it opens 33804 on * and 4005 on localhost

20:25 "Listening for transport dt_socket at address: 33804. \n Connection opened on localhost port 4005"

20:25 technomancy: oh, ok... that is cdt then

20:26 I have no idea what's going on with that code =(

20:26 lemme see if it's easy to disable

20:26 benedikt: why is that listening on all interaces?

20:26 interfaces*

20:26 (cdt, that is)

20:27 technomancy: I'm sure it's just an oversight

20:27 benedikt: sounds like a bug :)

20:27 technomancy: definitely

20:27 I got all the cdt support submitted as a big pull request without any real explanation of how it works =(

20:27 benedikt: I have to leave now, i'll happily continue when i get back

20:28 mk: where is the clojure code that resolves a var by looking things up in the namespace?

20:28 technomancy: ok, you should be able to disable it by putting :swank-cdt false in project.clj

20:28 or in your user profile

20:28 casion: how would one evaluate something like '(+ 1 2)

20:28 benedikt: technomancy: is my user profile ~/.leun/profiles.clj?

20:29 technomancy: benedikt: yeah, under the :user section of the map

20:29 mk: ,(eval '(+ 1 2)) ;?

20:29 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

20:29 technomancy: benedikt: thanks for catching this and the repl issue

20:30 adu: ,(first [1 2 3])

20:30 clojurebot: 1

20:30 casion: mk: thank you

20:30 adu: ,(first '(1 2 3))

20:30 clojurebot: 1

20:31 paxan: Has anybody been able to run JUnit tests via lein successfully? I am trying lein-junit, but I must be missing some important tip in its documentation regarding how to make it work. It simply succeeds very quietly with zero regard for failing tests

20:31 benedikt: technomancy: :)

20:32 adu: paxan: there should be a test for that

20:32 paxan: adu, got that plugin's src cloned. It passes its own tests :)

20:33 adu: :)

20:38 technomancy: benedikt: just pushed a fix to make the repl task bind to localhost only by default

20:40 Raynes: technomancy: What did I do?

20:40 technomancy: Raynes: benedikt just pointed out that `lein repl` listens on 0.0.0.0 by default

20:41 Raynes: Pretty sure I didn't have anything to do with anything related to that, technomancy.

20:41 technomancy: well I had to blame someone

20:43 amalloy: technomancy: it's my fault: i heard someone complain about it and was like "whoa that's awful" instead of "technomancy: ^ awful"

20:48 technomancy: hah

20:49 it could be cemerick's fault since that's what nrepl defaults to, but arguably in the context of nrepl-as-a-library it's a decent default

20:55 xeqi: technomancy: what did you use to record your clojure screencast?

21:01 guns: Hello, I am trying to determine if Unicode characters are explicitly valid in symbols. LispReader.java is very liberal, but clojure.org/reader says "alphanumeric"

21:01 Does this mean [A-Za-z0-9] or POSIX [:alnum:]?

21:05 Further confusing the issue is that Clojure 1.3+ allows ' in symbols

21:08 mk: ,(defn ↬ [a] a)

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

21:08 gfredericks: ,(let [↬ :foo] ↬)

21:08 clojurebot: :foo

21:08 guns: mk: the actual pattern for symbols is "[:]?([\D&&[^/]].*/)?([\D&&[^/]][^/]*)"

21:09 But that includes quite a bit more than "alphanumeric"

21:09 mk: guns: the only reason any characters would be prohibited is because clojure reserves them

21:10 guns: I've been freely using Unicode in my personal Clojure code, but someone mentioned that it is not part of the spec

21:10 from clojure.org/reader: "(other characters will be allowed eventually, but not all macro characters have been determined)"

21:10 gfredericks: I can't imagine there being non-ascii macro characters

21:11 maybe because I have no imagination

21:11 mk: or because it might reserve them in the future. Since I doubt that ↬ and the rest would ever be reserved by clojure, I really don't see why they would be prohibited even now

21:11 guns: Well, I'm happy with the status quo

21:11 gfredericks: #+ and #- might be coming

21:11 guns: just having a discussion about whether it's "legal" clojure code

21:11 mk: it's nice to see that they aren't, when it comes to code

21:12 if someone knows a good reason not to use unicode now and assume that it won't be prohibited, I'd love to hear it

21:13 guns: Even ASCII symbols like as->zs are commonly used, but don't adhere to the published definition

21:14 gfredericks: -> is used in clojure itself

21:14 amalloy: mk: the main reason would be portability of your source files. if you save a file as UTF-8 (say), and someone reads it as if it were Latin-1 (say), you might have issues if one of your multi-byte characters contains a 0x20

21:15 i think the clojure reader always reads files as UTF-8 now, but that's just an implementation detail; no promises about the character encoding

21:15 guns: I guess if we just continue to use Unicode, clojure/core will be forced to support it indefinitely

21:15 :)

21:16 mk: it's strange that > isn't listed among the permitted symbols in http://clojure.org/reader

21:16 gfredericks: those docs aren't very maintained

21:17 somebody was complaining about it not mentioning \' the other day

21:17 mk: I think the main problem is people saving their files in non-utf8... I don't have much sympathy for that

21:21 guns: what are you using unicode for? I've always wanted to replace -> with →, but I'm not sure that'd go over well

21:22 guns: mk: λ α β Σ, and so on for concision.

21:22 gfredericks: how do those get munged?

21:23 guns: I wouldn't do it in a team environment, but for myself, I have a very nice multibyte input setup

21:23 gfredericks: what do you mean? in the clojure symbol table?

21:23 gfredericks: no in class names and other java things

21:24 &((fn λ [] (fn [] :no)))

21:24 ,((fn λ [] (fn [] :no)))

21:24 clojurebot: #<sandbox$eval27$??__28$fn__29 sandbox$eval27$??__28$fn__29@3984d9f6>

21:24 gfredericks: ,((fn fooλbar [] (fn [] :no)))

21:24 clojurebot: #<sandbox$eval57$foo??bar__58$fn__59 sandbox$eval57$foo??bar__58$fn__59@4684c5b4>

21:24 goodieboy: technomancy: we're using leiningen < 2, can we still use the ".lein-classpath" feature for testing plugins?

21:25 gfredericks: the ?? is rather disturbing there

21:25 guns: That's true

21:25 mk: gfredericks: my repl shows the lambda, might be clojurebot bug

21:25 gfredericks: oh okay; so java must allow it

21:26 guns: Java identifiers explicitly allow unicode; I'm not sure if this impacts clojure in any way

21:26 http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.8

21:26 gfredericks: so clojure must only munge a few reserved symbols

21:28 goodieboy: technomancy: well dang, it works :)

21:28 mk: eclipse doesn't like ↬ in method names

21:29 it doesn't complain when given non-english alphabets, though

21:29 arohner: with core.logic, how do I say "all elements of seq x are members of seq y"?

21:30 gfredericks: (everyo #(membero % y) x)

21:30 after writing everyo

21:30 and that only works if you don't mind it succeeding multiple times for repeats

21:30 arohner: how do I write everyo? :-)

21:30 I'm still uncertain about how core.logic is implemented, and what is possible

21:31 gfredericks: (defn everyo [goalo coll] (matche [coll] ([[]]) ([[x . xs]] (goalo x) (everyo goalo xs))))

21:32 arohner: gfredericks: awesome. thank you. Is there something I should have read? I've read the primer on the wiki, but I still have lots of questions

21:32 mk: why do namespaces map directly to classes, instead of classes wrapped in vars?

21:32 gfredericks: arohner: The Reasoned Schemer

21:33 arohner: what are your questions? I'm right this second preparing a talk on core.logic so I'm interested in that sort of thing above and beyond the normal

21:33 I should probably even take notes on your questions :)

21:34 arohner: the main thing I'd like to understand is, enough of the implementation so that it I have an intuitive understanding of how to extend it

21:34 i.e. I didn't know that goals were functions, or how to compose new goals

21:34 i.e. I don't know what's "magic" and what's "user code"

21:34 gfredericks: by "extend it" do you mean writing your own goals, or really really extending it?

21:34 maybe you don't know what you mean yet

21:35 arohner: right, I don't know which kinds of extension are easy, and which take serious work

21:35 gfredericks: k cool

21:36 arohner: an hour ago I was wondering, if I have a logic variable q, and q is a map, how do I write the goal "q has a key named :foo, with value 3"

21:36 gfredericks: holy crap

21:36 afaik you can't

21:36 casion: maan, functional programming still maakes no sense to me :(

21:36 arohner: (pred q #(== 3 (:foo q)) worked for me

21:37 gfredericks: well if your map is ground you can do that

21:37 arohner: though as amalloy pointed out, that's non-relational

21:37 gfredericks: core.logic doesn't have good support for logic-variables-as-maps; you basically have to match all the keys at once which isn't very useful

21:38 that's partly because there's not a clear way for it to solidify a partially-specified map

21:38 i.e., if you said (run 1 [q] (q-has-value :foo 12)), what should it return?

21:38 (has-value q :foo 12) I should have said

21:39 arohner: {:foo 12} might be reasonable

21:39 in my particular case, I was selecting a map from a seq of maps

21:39 gfredericks: :/

21:40 also what about (run 1 [q] (fresh [x] (has-value q x 12)))

21:40 arohner: It appears I don't have goalo

21:40 gfredericks: that was an argument

21:41 arohner: oh, right

21:42 xeqi: gfredericks: couldn't that use the same value of x that (run1 [q] (fresh [x] (== q [x 12]))) would?

21:42 gfredericks: xeqi: it could; all these things feel a little icky though

21:43 the former because it doesn't distinguish between "this map might have had more keys" and "this map couldn't have more keys"

21:44 arohner: does it need to? that seems like a separate constraint

21:44 gfredericks: I mean the value returned from run

21:46 (run 2 [q] (conde ((firsto q 7)) ((== q [7])))) return two different things

21:46 muhoo: emezeske: it looks to me like lein-cljs plugin somehow manages to pull in support, but i can't figure out where it actually gets that or how it finds it or where it gets it from

21:47 gfredericks: while (run 2 [q] (conde ((has-key q :foo 7)) ((== q {:foo 7})))) wouldn't

21:49 muhoo: emezeske: nm, i found it, cljsbuild (without the lein-)

22:04 arohner: gfredericks: I'm getting stackoverflows when I use your everyo

22:04 (l/run* [q] (everyo #(l/membero % [4 5 6]) q))

22:04 amalloy: Raynes: lazybot seems to have passed out

22:05 muhoo: ,(l/run* [q] (everyo #(l/membero % [4 5 6]) q))

22:05 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: l, compiling:(NO_SOURCE_PATH:0)>

22:06 muhoo: bot appears to be alive, alhough it doesn't seem to do core.logic :-)

22:06 amalloy: muhoo: does that look like lazybot to you?

22:06 muhoo: it looks like a bot to me

22:07 ,are you a bot?

22:07 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: are in this context, compiling:(NO_SOURCE_PATH:0)>

22:07 gfredericks: arohner: that gives you a stack overflow?

22:07 muhoo: ,guards

22:07 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: guards in this context, compiling:(NO_SOURCE_PATH:0)>

22:07 arohner: gfredericks: yes, running c.l 0.7.5

22:07 muhoo: ,"foo"

22:07 clojurebot: "foo"

22:07 muhoo: ah, clojurebot

22:07 #"foo"

22:08 which one is ##"foo"

22:08 * muhoo got his bots all backwards

22:09 gfredericks: arohner: it might just be that's how the infinite-answers thing manifests itself

22:09 (run 5 ...) works fine for me

22:09 muhoo: &"alive?"

22:10 arohner_: ah, yes

22:10 run* .. gives stackoverflow, run 5 terminates immediately. thanks

22:11 mk: gfredericks: namespace's map actually is implemented as an atom, for what it's worth

22:11 gfredericks: mk: cool

22:14 goodieboy: technomancy: is it possible to use .lein-classpath when the plugin requires dependencies that the project doesn't have?

22:15 ... my plugin is using the "fs" library, but when testing in my project, "fs" can't be found

22:17 casion: as I don't think I have a proper grasp of functional programming yet, can someone look at this http://ideone.com/JUDLG and give me some clues on how to do it better?

22:18 it's just a small simulation of aa very simple game i suppose

22:18 it looks awful to me but I can't think of how else to approach it

22:20 Raynes: The variety of pastebins people use in here never ceases to amaze me.

22:20 :p

22:21 casion: heh, yeah

22:22 Raynes: I think it'd be fun to write a pastebin.

22:22 casion: I wrote that on my ipad while out on the porch, so it was already there

22:22 Raynes: I'd want it to look like https://www.refheap.com

22:22 casion: convenient

22:22 xeqi: I think it'd be fun to break a pastebin

22:23 cmajor7: what is the use of "#{::user}"? it evaluates to a current namespace, e.g. #{current.ns/user}, but what is the purpose?

22:24 Raynes: cmajor7: Sometimes you need there to be a difference between the :foo from the bar namespace and the :foo from the baz namespace.

22:24 It isn't particularly common though.

22:24 cmajor7: I am looking at "friend" roles

22:25 they are defined as #{::user ::admin ::etc}, and was wondering on how to store them in DB

22:25 I guess I can just store them as user, admin and such..

22:26 do you know the "friend"'s purpose? thx

22:26 gfredericks: ,(name ::admin)

22:26 clojurebot: "admin"

22:27 cmajor7: gfredericks: but ,(name :admin)

22:27 is also "admin"

22:27 gfredericks: yep

22:29 cmajor7: mm… do you know why "friend" for example uses "::"?

22:29 gfredericks: nope

22:30 cmajor7: e.g. https://www.refheap.com/paste/3951

22:30 gfredericks: it's used as a value rather than a key?

22:30 cmajor7: it is a set..

22:31 what do you mean "rather than a key"?

22:31 gfredericks: a key in a map

22:31 xeqi: cmajor7: in order to use `derive` to make a heirarchy the keywords need to be namespaced

22:31 gfredericks: I guess I can imagine a justification

22:31 ooh that

22:32 that sounds by far the most likely

22:32 xeqi: you can actually have the roles be anything if I remember correctly

22:32 you just don't get the ability to `derive` a heirarchy then

22:35 cmajor7: xeqi: I see.. reading about it now. thank you

22:56 muhoo: cmajor7: :: is a fully qualified symbol, no?

22:56 ,::foo

22:56 clojurebot: :sandbox/foo

22:57 cmajor7: right, "it" is just a "current name space forward slash it"

22:58 gfredericks: &(identical? (keyword "foo/bar") (keyword "foo" "bar"))

22:58 ,(identical? (keyword "foo/bar") (keyword "foo" "bar"))

22:58 clojurebot: true

23:03 muhoo: emezeske: if you're around, i'm trying to figure out exactly how lein-cljsbuild pulls in cljsbuild, so i can do some checkouts stuff to work on it

23:03 actually, it'd be great to hear what your workflow is for working on lein-cljsbuild, i might as well start with that

23:05 actually, in general how to use a plugin from checkouts, might be an interesting question

23:09 Raynes: amalloy: You have access to the VPS too btw.

23:15 amalloy: yeah, but you do weird shit with lazybot and if i touch him you get annoyed

23:16 technomancy: is anyone still seeing the bug where C-c C-k with nrepl.el would occasionally take a few tries to go all the way through?

23:16 Raynes: amalloy: Dude. All I do is run ./lazybot

23:16 Seriously, that's precisely all I do.

23:16 technomancy: I can't repro, but I can't tell if I'm just getting lucky or if the bug is gone

23:16 Raynes: I mean, I do it in a tmux session, but that isn't required. :P

23:17 technomancy: dude, at least nohup it

23:17 Raynes: Why?

23:17 clojurebot: why not?

23:17 Raynes: I stick it in a tmux session so I can attach and watch over my world.

23:18 technomancy: I guess if everyone has access to the tmux session it's fine

23:18 Raynes: Why would anyone else need access to my tmux session?

23:18 technomancy: I dunno; it's fine; disregard

23:18 Raynes: amalloy doesn't care about lazybot's output unless it stops doing it in which case he just wants to restart it which doesn't involve my tmux session at all.

23:18 :P

23:19 technomancy: but if you do run it outside a tmux, then you should use nohup

23:19 amalloy: for what it's worth i nohup 4clojure, but i don't know why

23:19 technomancy: from seeing how clojars is deployed I found upstart to be surprisingly simple

23:19 it is nice if everything works via familiar /etc/init.d scripts

23:20 Raynes: technomancy: What does nohup do? Apparently I don't understand.

23:21 I thought it was to make it run in the background.

23:21 technomancy: it prevents it from exiting when the parent process (bash in this case) terminates

23:21 Raynes: Which is what tmux does for me in the first place.

23:21 But tmux never terminates.

23:21 technomancy: right, I meant if you run it outside tmux you need it

23:21 Raynes: Oh, reading comprehension.

23:22 technomancy: but upstart is much nicer

23:22 Raynes: I thought you said 'inside'.

23:22 amalloy: technomancy: i've also never seen a process end when my bash ends

23:22 so i wonder if perhaps nohup is a relic of simpler times, when that happened?

23:22 Raynes: I sure have.

23:22 amalloy: As a matter of fact, I've killed 4clojure like that before.

23:22 technomancy: it happens

23:23 http://groups.google.com/group/clojars-maintainers/browse_thread/thread/d4149ec96316d5b1/4c66317ac3ecd9bb?lnk=gst&q=upstart#4c66317ac3ecd9bb <- nice description of clojars' upstart usage from _ato

23:25 I'm going to go out on a limb and say that particular nrepl.el bug is gone

23:28 muhoo: technomancy: nrepl.el is very very cool, thanks, i'm now switched over to using it

23:29 Raynes: muhoo: Welcome to the resistance.

23:29 muhoo: technomancy: sorry for so brutally whacking the popups, but all the popups had turned my sessions into an experience not unlike browsing porn sites.

23:29 technomancy: muhoo: oh, haha; irc/github nick mismatch =)

23:29 Raynes: You would know.

23:30 technomancy: I think you're right about the repl experience, but the fix in that pull request was just a bit too far-reaching

23:30 muhoo: agreed, i was just in a hurry

23:31 technomancy: muhoo: so you actually prefer just seeing the message going to stdout vs the whole trace?

23:31 muhoo: actually, what i've come to really enjoy is the way lein does it: a single-line clj-stacktrace summary

23:31 and (pst) to get the rest if needed

23:32 though, a hotkey in emacs to pop up the (pst) would be slick, so as not to pollute the repl buffer with a huge stacktrace

23:32 technomancy: what if clj-stacktrace omitted irrelevant frames by default?

23:32 muhoo: i think it does already, or at least shortens them

23:32 hiredman: as always, I object, who decides what is irrelevant?

23:33 technomancy: hiredman: I know you object =)

23:33 I'm asking muhoo because it never occurred to me that the behaviour of only showing .getMessage was actually preferred by anyone

23:33 muhoo: well, look. i type (ns 'foobar) too many times

23:33 hiredman: removing stack traces is optimizing for ignorance, it makes a better experience for people who can't read them

23:34 muhoo: and, a whole host of errors i make constantly in a repl, like (require foo.bar.baz) instead of (require 'foo.bar.baz)

23:34 do i really need a 2-page stacktrace every time?

23:34 technomancy: muhoo: I'm just wondering if you're objecting to their length or their presence at all

23:35 I think reply must have some magic to auto-refer clojure.repl into every ns or something... interesting

23:35 muhoo: i'm objecting to (1) popups in general, they disorient me, and (2) huge spews when i just made a typo

23:35 technomancy: muhoo: sure, I'm saying what if the trace went to stdout instead

23:36 and if they were shorter

23:36 muhoo: i actually wrote a hack for noir where it sends the stacktrace to /tmp/noir-error.clj, and then i auto-revert-mode a buffer that has taht in it

23:37 so when i blow something up, i just go to the buffer (or have it open in another window) and look at it, and the most recent error to occur is right there looking at me, with the top frame at the top, etc. (and some context and ring-request at the bottom too)

23:38 i like full stacktraces, and i enjoy the way clj-stacktrace cleans them up.

23:39 but i also like not *having* to look at them, when often the first line is all i need.

23:39 (also nice not to have to scroll around to find the top of them, which is why i wrote that hack for noir/ring)

23:39 technomancy: sure

23:40 I think you can actually set :caught in :repl-options in project.clj if you want to tweak it

23:40 muhoo: cool, i'll take a look at that.

23:40 technomancy: at least you could in 1.x; hopefully that's still possible

23:40 anyway, that would let you swap between prn and pst

23:41 muhoo: well, i'm fully converted over to lein2 now, so i'd have to find a way that works with it

23:42 technomancy: I actually didn't even know that the default was just to show the exception message

23:42 muhoo: really? wow. you've been using swank i presume

23:43 technomancy: only started paying attention to lein repl now with nrepl.el

23:46 muhoo: i see no :caught in leiningen/sample-project.clj

23:47 technomancy: it might not be documented; try putting it in :repl-options

23:49 muhoo: i'll try, but the word "caught" appears nowhere in the lein2 source

23:49 technomancy: yeah, it would get passed through to reply

23:55 amalloy: technomancy: oh, is reply the one responsible for me no longer getting reasonable exception messages in swank?

23:55 or are those not related?

23:56 technomancy: hrm

23:56 unrelated

23:56 you may be getting bit by a clj-stacktrace bug?

23:57 amalloy: maybe. i've never included clj-stacktrace on purpose

23:57 technomancy: it comes for free

23:57 because it's too awesome not to

23:58 amalloy: how can i disable it? i've had nothing but grief anytime i've had a project that uses it

23:58 technomancy: ... what?

23:58 how ... I mean

23:59 why would you want gross normal stack traces?

23:59 amalloy: stacktraces coming from inside clj-stacktrace's processing code, instead of from my code

23:59 technomancy: oh, right

23:59 amalloy: so that i can't track down any damn thing

23:59 technomancy: first thing would be to bug chouser to make his clj-stacktrace changes public so I stop procrastinating on the project

23:59 second thing would be to switch to nrepl.el

Logging service provided by n01se.net