#clojure log - Apr 20 2013

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

0:19 gfredericks: tieTYT: that also checks that it's not false

0:20 tieTYT: right

0:38 Raynes: ibdknox: http://dl.dropbox.com/u/23745600/Screenshots/oNCd.png How did my vim end up with light table's icon?

1:57 You're all boring.

1:57 azkane: :(

2:32 sztamas: \quit

4:08 Netfeed: what's the best way to do "raw" sql in clojure? is there a library where i don't have to work with abstractions and can work directly with the sql?

4:10 callen_: Netfeed: jdbc or korma.

4:14 noprompt: oh m'god. media queries...

4:15 Netfeed: iv'e looked into jdbc, but i've not really got how i should best do stuff like custom insert and such, best thing i've found is do-commands and i'm not really sure if i can use the parameterized things with it. (i'm not sure how to explain it, i more or less want to do something like (do-commands "insert into foo (bar) values (?)" "baz") but a bit more advanced

4:17 ddellacosta: Netfeed, check out the tests for some examples if you haven't already: https://github.com/clojure/java.jdbc/blob/master/src/test/clojure/clojure/java/test_sql.clj

4:18 (for jdbc at least)

4:18 maybe that'll give you what you need…maybe not.

4:20 Netfeed: maybe, i'll take a look, jdbc seems to be nice until you need to do some custom things

4:20 ddellacosta: oh, sorry, I guess you saw that, you were talking about do-prepared

4:20 I was just checking this out too

4:20 https://github.com/clojure/java.jdbc/blob/master/src/test/clojure/clojure/java/test_jdbc.clj

4:21 it looks like you can do parameterized stuff from the examples there, but not sure again if it's enough for what you want.

4:22 Netfeed: oh, yeah, do-prepared might be what i need

4:22 thank you

4:23 ddellacosta: hope it helps.

4:30 Netfeed: yeah, that worked, only thing it doesn't seem to do is RETURNING

4:32 ah, might be another function for that

4:33 yeah, there was, great

5:45 noprompt: e

5:58 clj_newb: Hi, to perform N function execution, which is better, dotimes?

5:59 naeg: Guess that depends on what your functions are doing? e.g. do they have side effects, etc.

6:00 clj_newb: yeah, are sending signals to external systems

6:01 naeg: sounds like dotimes to me

6:02 clj_newb: cool, I also think is the more appropriate but just wondering it there was a more suitable way

6:03 thansk naeg

6:09 naeg: am I the only one who thinks a visualization of code debugged with tools.trace.deftrace would be great? here's what I mean: http://i.imgur.com/qOiiXdE.png

6:09 it's very ugly right now, but wondering whether there is something to that others could need to

6:09 too*

7:06 iamdrw: @noprompt what's wrong with media queries?

10:05 kmic: Jak tasiemiec.

10:14 clj_newb: Hi, anyone using langohr? By merely following their examples messages don't get publish in rabbitmq

10:15 no errors, and in logs (rabbitmq) I can see that the connection is performed

10:20 gdev: ,(contains? :a [])

10:20 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.Keyword>

10:25 gdev: ,(clojure-version)

10:25 clojurebot: "1.5.0-RC6"

10:25 kmic: , (contains? [1] 0)

10:25 clojurebot: true

10:26 ejackson: (use 'tradedesk.bootstrap)

10:26 ooops

10:31 gdev: ,(contains? {:doo "doo"} :poo)

10:31 clojurebot: false

11:42 Jambato: hi, I wanted to know whether you can access some global variables in a function

11:42 if yes, does it involve some namespace tricks?

11:43 naeg: Jambato: just put a def on the top of the file and you can access it from within that file with no problem

11:43 also from outside with namespace/var

11:43 Jambato: very well

11:44 thank you naeg

11:44 naeg: np

11:45 just ask again if you can't get it to work

11:46 zilti: I'm currently trying to use Friend with Compojure, but all I get is "Exception in thread "main" java.io.FileNotFoundException: Could not locate ring/util/request__init.class or ring/util/request.clj on classpath".

11:47 naeg: this basically means it can't find ring - did you add it to the dependencies of your project and :require it in the file you're accessing it?

11:49 zilti: naeg: I've added compojure as a dependency which requires ring, and when removing the require-statement from my core.clj I can run the application using lein-ring

11:49 So, no, currently I haven't explicitly declared or required ring anywhere.

11:52 naeg: never used Friend or ring, so dunno

11:55 cemerick: This is cute: https://gist.github.com/cemerick/5426430

11:55 (Only the first type specified in extend-protocol can be specified by an expression...)

11:56 ebaxt: is there a way to "invert" a vector [:foo :bar :baz] => :foo :bar :baz?

11:57 no7hing: ?(reverse [:foo :bar :baz])

11:57 Bronsa: cemerick: I'm more surprised by the fact that it works even just for the first type than that it doesn't work for the others

11:57 no7hing: @ebaxt: ah sry, i understood reverse

11:58 cemerick: Bronsa: a must for array types *shrug*

11:58 tmciver: ebaxt: if you're trying to use the vector contents as args to a fn, use apply.

11:58 zilti: Hmm I now explicitly added ring-core to my dependencies and explicitly required ring.util.request, but even then it seems to be unable to find that one...

11:59 cemerick: oddly, the broken sample is in some code I wrote *years* ago that used Clojure 1.3, but I can't get it to work with 1.3 now.

11:59 ebaxt: tmciver: Thanks, I know how to do it in a function, but I'm trying to share some parameters on the calling side (does that make sense?)

12:00 weavejester: zilti: Have you included ring-core 1.2.0-beta2?

12:01 Bronsa: cemerick: right, but I think it's more likely that it works by accident rather than it being a bug

12:01 zilti: weavejester: I manually included ring-core 1.1.8, but I just deleted ~/.m2 and re-fetched the dependencies for that project, and something seems to fetch 1.2.0-beta1

12:01 Bronsa: cemerick: it would be difficoult to distinguish between protocol function implementation and expressions to evaluate in order to get a class

12:01 weavejester: zilti: It might be Friend doing that

12:02 Bronsa: difficult*

12:02 weavejester: zilti: ring.util.request is only available in 1.2.0

12:02 zilti: weavejester: Isn't that paradox? Since it's friend complaining that ring.util.request is missing

12:02 cemerick: Bronsa: not it's not: they're pairs

12:02 ebaxt: I have an enlive template and I want to use the same selector/fn pair in a deftemplate and in a macro (deftemplate …. [:p] (h/content "foo")) and (some-macro (html/at nodes [:p] (h/content "foo")))

12:02 cemerick: oh, oh, nm

12:03 weavejester: zilti: No. The latest Friend depends on Ring 1.2.0. The ring.util.request namespace is only in Ring 1.2.0. If you've forced the dependency to Ring 1.1.8, then when Friend tries to get ring.util.request, it won't find it.

12:03 cemerick: anyway; that code definitely worked at some point. Maybe in 1.2? I don't remember the timelines of Clojure releases back that far

12:04 zilti: weavejester: Thanks, now I've placed friend as first dependency right after clojure itself, and now it works.

12:05 Bronsa: cemerick: not necessarily, it could be done by partitioning each (inc (count (keys (:sigs the-protocol)))) but then you're forcing users of extend-protocol to implement every function of the protocol

12:09 ebaxt: tmciver: Here is what I'm trying to do https://www.refheap.com/paste/13791

12:14 Jambato: when trying to apply nth on a vector of vectors I get the following error : UnsupportedOperationException nth not supported on this type: core$init_gamearea clojure.lang.RT.nthFrom (RT.java:798)

12:14 said vector is bound to a global variable

12:14 Bronsa: Jambato: can you nopaste the code you're using?

12:14 Jambato: sure

12:15 http://pastebin.com/c5stPg4U

12:16 Bronsa: Jambato: line 19

12:16 you probably want (def gamearea (init-gamearea))

12:17 Jambato: duh of course it is a function -_-

12:17 so stupid

12:17 Bronsa: also, assoc doesn't work the way you're using it in line 29 and 30

12:17 it has no side effect

12:17 so you're not modifying list-of-players or gamearea

12:18 Jambato: it isn't modifying any copys?

12:18 Bronsa: you probably want list-of-players and gamearea to be atoms

12:18 and then swap! gamearea assoc instead of assoc gamearea

12:19 ,(let [x {}] (do (assoc x :a 1) x))

12:19 clojurebot: {}

12:19 Jambato: I'll try that, thanks bronsa

12:19 Bronsa: ,(let [x (atom {})] (do (swap! x assoc :a 1) @x))

12:19 clojurebot: {:a 1}

12:25 Jambato: Bronsa: so the maps I'm using and whta's inside must all be atoms?

12:25 Bronsa: no

12:26 all clojure collections are immutable Jambato

12:26 assoc and friends returns copies of the collection, they don't modify it

12:26 if you want to modify something, you generally want to put it inside an atom

12:27 Jambato: ah so I swap the modified copy

12:27 Bronsa: swap! is a function that takes an atom, a function and optiona arguments

12:28 applies the function to the current state of the atom and sets the atom's value to the return value of the function

12:30 Jambato: what if I have to swap several atoms? must I wrap them within a specific form?

12:31 recursor94: Does anybody know of any good opensource projects that are relatively easy for a beginner to understand and learn from?

12:32 For clojure.

12:37 joegallo: Jambato: no, atoms are independent. if the swapping that you want to do is intended to be synchronized, then you're looking for a different data type, refs.

12:38 recursor94: is there any particular domain that would be especially interesting to you?

12:39 Jambato: joegallo: there isn't any concurrency involved

12:39 I just need to sequentially update 2 different atoms

12:40 Bronsa: Jambato: just using swap! on each atom will be sufficient

12:40 Jambato: ok

12:40 joegallo: Jambato: that's fine, of course. if you were worried about something else reading from a bad old value from atom b during the fraction of a second between the write to atom a and the write to atom b, then what you'd want is refs.

12:41 but since there isn't any such reader that you're worried about, then atoms are just fine, i suppose.

12:42 (like for instance if atom a represented a debit into an account, and atom b represented the credit to another account -- that'd probably be refs then)

12:46 recursor94: joegallo: Hard to say, I suppose the most interesting thing I can think of is artificial intelligence. Second would probably be databases, and third games. Most of the open source projects I have seen on github are web frameworks.

12:46 joegallo: you need a database-driven game with an AI component! :D

12:47 recursor94: Do such things exist XD?

12:48 joegallo: i doubt it, but it's a big world out there

12:51 i can't speak for the quality of this (it may very well be excellent, but who knows) http://stevelosh.com/blog/2012/07/caves-of-clojure-01/

12:52 recursor94: Cool, thanks!

12:53 joegallo: the code for that lives in a series of tags, here: https://github.com/sjl/caves/

12:53 might be a neat place to start with something

13:04 Jambato: http://pastebin.com/zieSRwp9 > now I got a IllegalArgumentException Key must be integer clojure.lang.APersistentVector.invoke (APersistentVector.java:265)

13:05 probably wasn't a good idea to use numbers as keywords

13:07 jjido: are you using assoc correctly

13:07 Jambato: oh litteral keywords don't change anything

13:07 jjido: I have no idea I'm a beginner

13:08 jjido: what is the third argument? the key?

13:08 Jambato: there is no third argument

13:09 only two

13:09 jjido: you used [np]

13:09 yes I can't count

13:10 anyway is [np] the key? try without brackets.

13:10 Jambato: np is the key yes

13:11 nope no better

13:11 without brackets

13:11 IamDrowsy: you should look at your swap! calls... swap! takes an atom and a fn of min 1 args.. calls (f @atom-stat .. rest-args) ... and swaps the result "into the atom"

13:11 jjido: what's the error?

13:11 Jambato: IllegalArgumentException Key must be integer clojure.lang.APersistentVector.invoke (APersistentVector.java:265)

13:12 IamDrowsy: so last line should be (swap! gamearea #(assoc % nga newstack)

13:12 )

13:12 jjido: yes IamDrowsy knows his/her stuff

13:13 Jambato: ok I see

13:13 funcitons not values

13:13 *functions

13:14 edlothiol: or even (swap! gamearea assoc nga newstack), since you can pass additional parameters to swap!

13:15 Jambato: holy mackerel it works

13:16 I'm so happy

13:16 I had so many troubles with the haskell version

13:16 thanks IamDrowsy and edlothiol

13:21 jjido: Jambato: clojure has lower entry threshold than Haskell

13:22 zilti: IMO Haskell-syntax is totally unreadable

13:22 Glenjamin: i'd say clojure is has a lower barrier to actually producing something real than haskell

13:22 basic haskell is pretty simple

13:24 Jambato: jjido: my haskell version involved the State monad

13:24 but stuf is quite unwieldy

13:25 to use that is

13:29 konr: Is there some meta-information I could add to a defn in cljs to compile it in whitespace mode, reglardless of what project.clj says?

13:31 gfredericks: konr: that would surprise me

13:32 zilti: Friend's documentation is so incredibly bad, if I had used the time otherwise I had written my own authentication system by now.

13:35 It does not even bother calling my credential-fn

13:36 It simply responds with login_failed.

13:47 Morgawr: hello.. I've been reading some clojure code and in one code snippet there's a call to a "some" function.. since it has a very ambiguous name I can't properly find its definition on google (or whatever), can someone tell me what it is and how to find it?

13:48 morphling: ,(doc some)

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

13:48 Morgawr: morphling: thanks!

13:50 xeqi: zilti: do you have a snippet you need help with?

13:52 zilti: xeqi: https://www.refheap.com/paste/13794 That's what I have by now. Registration works flawless, so does the auth/validate-user function, but it never gets called by Friend.

13:55 mebigfatguy: exit

13:56 xeqi: zilti: what do you mean registration works flawless?

13:56 that when a user posts the the /register page the user gets added to the db?

13:57 zilti: xeqi: The stuff gets stored in my db the way it should. Yes, that's what happens

13:58 xeqi: I notice you don't have wrap-session

13:58 is that on purpose?

13:58 zilti: no

13:59 but I kinda expected Friend to do that stuff

14:01 xeqi: since you are using compojure, you might want to use compojure.handler/site or compojure.handler/api to setup the standard middleware

14:02 the ring middleware ecosystem assumes you've setup and requied ones before hand. In general having each middleware setup what it needs doesn't compose well

14:03 though it could be possible for them to declare they're prerequisites and have a system solve that... hmm...

14:03 zilti: Well, anyway, that shouldn't be the reason stopping Friend from calling my validate-user function

14:05 asalaaak: hey mates

14:05 (- 465 200) (* 70)

14:05 i want to calculate 465 - 200 * 70

14:05 but

14:05 this expression only calculates 465 - 200

14:05 how can i fix this

14:05 please help

14:05 (- 465 200) (* 70)

14:05 this doesnt calculate * 70

14:05 Bronsa: ,(* (- 465 200) 70)

14:05 clojurebot: 18550

14:06 xeqi: ,(- 465 (* 200 70))

14:06 clojurebot: -13535

14:06 Aim_Here: ,(- 465 200)(* 70)

14:06 clojurebot: 265

14:07 zilti: Why does that even work?

14:07 Aim_Here: ,(* 70)

14:07 clojurebot: 70

14:07 Aim_Here: I'd have thought it would eval to 70

14:07 zilti: ,(do(- 465 200)(* 70))

14:07 clojurebot: 70

14:08 zilti: It does. Clojurebot only takes the first expression I gues

14:08 *guess

14:08 asalaaak: thx matesss

14:09 zilti: xeqi: I tried to include all the middleware defined there and found out that wrap-multipart-params is broken (It wants assoc-conj which doesn't exist)

14:12 Seems like ring 1.1.8 and ring 1.2.0 are too incompatible for Friend to work. Well, I guess I just wasted a whole afternoon.

15:03 tacoman: is there a relatively simple way to use a C library from either Clojure or Clojurescript? Or am I going to be stuck doing something like JNI/JNA manually, then making Clojure bindings to that?

15:05 I know I'm probably going to have to write wrappers eventually, but I'd prefer not to be writing two sets if I can avoid it

15:06 Aim_Here: I'm under the impression that until now, Clojurists figured that Java got them all the libraries they'd ever need, so they've never needed bindings and shims for native code before.

15:07 arkh: I haven't heard of a way to call native code outside of JNA but I don't have any first-hand experience with that

15:08 tacoman: I'm looking to use libtcod, but unfortunately it's a C lib

15:09 arkh: sweet : )

15:09 tacoman: no Java bindings iirc

15:09 actually... hmm, looks like someone *started* work on some since the last time I looked this up

15:10 clj, even, but only one commit, and a month ago

15:14 bordatoue: hello could anyone tell me if there is any equivalent for python's dir in clojure, say if want to list all the functions available in clojure's list what would be the best way to do it

15:16 joegallo: bordatoue: you mean functions that operate on lists?

15:17 lists don't really have functions... they're a datastructure

15:17 gfredericks: best bet is a combo of the clojure cheatsheet and clojure.repl/dir

15:18 bordatoue: okay

15:18 joegallo: http://clojuredocs.org/quickref/Clojure%20Core is pretty good

15:18 gfredericks: yeah if you had pressed me on a third thing it woulda been clojuredocs

15:19 oh also lazybot's $findfn can be nice

15:19 bordatoue: joegallo: i meant fns that operate on list

15:19 gfredericks: $findfn 3 4 7

15:19 lazybot: [clojure.core/bit-or clojure.core/bit-xor clojure.core/+ clojure.core/unchecked-add clojure.core/+' clojure.core/unchecked-add-int]

15:20 bordatoue: gfredericks: how do it get this findfn in repl

15:20 joegallo: bordatoue: okay, that's what i figured -- that's the issue, though. if you want a list of all the methods that a String has, you can look at the documentation for String, or you can use reflection to list them.

15:20 arkh: bordatoeu: also, http://stackoverflow.com/questions/2747294/how-to-list-the-functions-of-a-namespace

15:20 gfredericks: bordatoue: you don't really; much easier to have a PM with lazybot

15:20 joegallo: but with list, it doesn't have any functions -- there are other (disembodied) functions that happen to operate on lists, but they're not tied to list directly

15:20 bordatoue: thats cool

15:20 joegallo: so you just gotta look 'em up ;)

15:21 gfredericks: well i can't say for sure that getting the lazybot code and doing it from the repl is necessarily difficult

15:43 Morgawr: hey guys.. I'm playing around with ClojureScript.. since there's not a lot of available resources, I am copying this code http://nakkaya.com/2012/01/31/clojurescript-canvas-a-simple-breakout-implementation/ for a breakout clone but the program seems to be hanging on goog.Timer creation

15:43 the code is exactly the same (at least, I hope) and yet with the goog.Timer declaration (At the end, last snippet of code) the code simply doesn't go past that let statement

15:44 bordatoue: gfredericks: where can i get the information on how to interact with lazybot

15:44 Morgawr: if I remove that statement the code works but nothing happens (no timer, duh)

15:44 anyone knows what might be wrong?

15:45 gfredericks: bordatoue: no idea; the README on github might help

15:46 bordatoue: can you show me an example on how you would interact with lazybot, I am not getting any response from it

15:46 bawr: Hello. Which clojre repl do I want? Preferably a console version.

15:48 arkh: Morgawr: what does firebug / chrome dev tools say about it?

15:49 bawr: leinengen's?

15:49 Morgawr: arkh: it says "TypeError: goog.Timer is not a constructor"

15:49 bawr: arkh: ah, right, forgot all about lein

15:50 this is what I get for taking a year break from clojure xD

15:50 arkh: bawr: : )

15:50 bawr: you'll find leinengen has some nice improvements from a year ago

15:51 bawr: *refinements

15:51 bawr: Excellent, looks like I'm in for a treat.

15:51 arkh: Morgawr: do you have your code up somewhere?

15:52 Morgawr: arkh: http://nakkaya.com/2012/01/31/clojurescript-canvas-a-simple-breakout-implementation/ it's the same as this one, literally copypasted (I typed it by hand but I also made sure this part is exactly the same)

15:52 the last snippet

15:52 basically (let timer (goog.Timer. (/ 1000 60)))

15:52 bawr: Just as a general point of interest - if I want to keep a biggish data structure in memory (say a small tree of big lists) and I want to back it up sensibly every now and then... what do I want to read? :)

15:52 Morgawr: that's the part that causes error

15:55 bawr: mostly I don't want the backup to grind my process to a halt, so obviously persistent data structures are a win

15:55 arkh: Morgawr: it runs in the compiler in my head : ) maybe try that part at a repl

15:56 Morgawr: yeah I'm still struggling with integrating the repl with the browser code

15:58 arkh: bawr: you may want to try http://clojuredocs.org/clojure_core/clojure.core/print-dup but I thought there was another way ... it's just not coming to me right now

15:59 Morgawr: I'd try it myself but I just haven't dug into clojurescript much and I'm currently working on a datomic project - sorry!

15:59 Morgawr: arkh: it's alright, thanks anyways

16:00 the problem is that it says goog.Timer is not a constructor, maybe I'm missing somethin from clojure syntax (I'm still learning), what defines a constructor in Clojure?

16:00 the call is "(goog.Timer. 1000)", if I remove the '.' at the end the error complains about Timer not being a function (rightfully so)

16:01 arkh: Morgawr: the constructor it refers to is (in this case) javascript interop with that google closure library

16:02 Morgawr: goog.Timer(opt_interval, opt_timerObject) <-- this is how the constructor is defined in the clojure doc

16:03 clojurescript doc *

16:04 arkh: I was looking at that (old now) twitterbuzz app rich made after the initial announcement of clojurescript - it uses goog.Timer in the same way: https://github.com/clojure/clojurescript/blob/master/samples/twitterbuzz/src/twitterbuzz/core.cljs

16:05 Morgawr: yeah, same

16:05 arkh: Morgawr: double check for typos is all I can think of

16:06 Morgawr: arkh: oh damn! I think I found the problem.. I didn't have the correct require

16:06 curse me, sorry for the trouble ^^

16:06 arkh: haha - I've done the same - it's all good

16:11 recursor`: ,(println "Hello clojure programmers!")

16:11 clojurebot: Hello clojure programmers!\n

16:11 recursor`: SWEET

16:13 Morgawr: is there a ,(quit) ? :D

16:14 recursor`: Hopefully not XD

16:15 Bronsa: it should be disabled

16:15 ,(System/exit)

16:15 clojurebot: #<CompilerException java.lang.NoSuchFieldException: exit, compiling:(NO_SOURCE_PATH:0:0)>

16:16 Bronsa: ,(System/exit 1)

16:16 clojurebot: #<SecurityException java.lang.SecurityException: denied>

16:16 Bronsa: yeah

16:16 recursor`: ,(def my-name "recursor94")

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

16:17 recursor`: ,(let [my-name "recursor94"]

16:17 (println my-name))

16:17 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

16:17 recursor`: ,(let [my-name "recursor94"] (println my-name))

16:17 clojurebot: recursor94\n

16:19 recursor`: ,Math/PI

16:19 clojurebot: 3.141592653589793

16:40 tacoman: does anyone here actually use Ritz? Everything I've seen suggests the normal nrepl client is used by everyone, but I'm not sure if there's any advantages/disadvantages to switching

16:46 actually, it's in addition to, not instead of, on closer look. silly question, that

16:48 technomancy: tacoman: if you are lucky, you will never need a stepping debugger because you never have to deal with buggy code that's excessively deep or stateful. but if you find yourself needing one, ritz seems like your best bet.

16:49 tacoman: yeah, I'm hoping so. now that I'm out of school and had a few months off, I'm looking at finally doing some actual work in Clojure in some of my downtime

16:49 hoping it's both an enlightening and entertaining experience :)

16:53 weavejester: zilti: Just noticed your earlier message. Ring 1.2.0 is backward compatible with 1.1.8, so any code you have that can run with 1.1.8 can run with 1.2.0

16:54 zilti: weavejester: It seems to me like it's not since compojure didn't like it at all. Anyway I wrote my own authentication now ;)

16:54 weavejester: zilti: Compojure is definitely compatible with Ring 1.2.0

16:55 1.2.0 doesn't change any existing functions. It follows semantic versioning pretty strictly.

17:45 Glenjamin: is there a nice way to conditionally put things into -> ?

17:47 bbloom: Glenjamin: see also cond-> and as->

17:47 generally, (find-doc "->")

17:48 Glenjamin: ah, that's a good tip

17:48 i've got 4 forms, and only one is conditional

17:50 bbloom: ,(-> 5 (* 2) (as-> x (if (even? x) (dec x) x)) (- 3))

17:50 clojurebot: 6

17:52 Glenjamin: heh, the docstring for as-> does not make that obvious

17:52 bbloom: (doc as->)

17:52 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

17:52 Glenjamin: reading it again after seeing the example, i get it

17:53 bbloom: yeah, needs an example

17:53 Glenjamin: shame about clojuredocs being out of date

17:53 bbloom: agreed

17:54 Glenjamin: and the clojure.org cheatsheet - it's missing a bunch of 1.5 niceities

17:55 bbloom: dnolen: in addition to some cljs hacking, i'm interested in linear problems & optimization w/ core.logic, we should add that to the infinite list of projects to work on

17:58 mthvedt: ,(keyword "")

17:58 clojurebot: :

17:58 mthvedt: ,(: {})

17:58 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :>

17:58 mthvedt: hmm

17:59 bbloom: mthvedt: yeah, most core functions do not check their arguments b/c it would have a perf penalty

17:59 mthvedt: ##(keyword "////////+!@#$%^&*()~`=\\123")

17:59 lazybot: ⇒ :////////+!@#$%^&*()~`=\123

18:01 mthvedt: ,(print-dup (keyword "") *out*)

18:01 clojurebot: :

18:02 mthvedt: having keywords in memory that you can't write and read again

18:02 seems like a violation of some principle or other

18:03 bbloom: mthvedt: yeah, so don't do that :-P

18:03 TimMc: I don't like programs that make keywords out of arbitrary strings/

18:03 mthvedt: playing with a json parser

18:04 problem happens when you have "" as a json key

18:04 TimMc: JSON libs are OK, I guess, as long as you're using JSON with a known schema...

18:04 bbloom: (inc TimMc) ; fixed schemas when keywordizing json

18:04 lazybot: ⇒ 37

18:04 bbloom: personally, i don't think there is anything wrong with strings for keys, other than you can't do (:keyword map)

18:05 (map "string") is pretty reasonable

18:10 Glenjamin: presumably keywords are basically interned strings with nice syntax

18:11 better memory usage and faster lookup / comparison would make them preferrable to strings as map keys - no?

18:13 bbloom: Glenjamin: in general, yes. however, when parsing from strings, you'd need to do an extra lookup from string -> keyword, which is virtually the same as string key -> val. so you'd only really get a win if you are doing a lot of reads from the json structure. and even then it won't matter at all if your map is relatively small

18:13 Glenjamin: ah, i see

18:14 bbloom: Glenjamin: also, if you've got an algorithm, odds are that some JSON serialization shape is not a 1 to 1 match to your internal data structures for the algorithm, so you can convert to keywords when preparing those data structures

18:15 the bigger issue is one of semantic sanity: json does not have keywords.

18:16 if i give you some json w/o an agreed upon schema, you have no way of knowing whether or not keys will contain valid keyword identifiers, nor will you know if it would even make sense to view them as such... like a mapping of user names to profiles or whatever

18:16 you might want {"bbloom": {"first_name": "Brandon", "last_name": "Bloom"}} which would be most reasonably interpreted as {"bbloom" {:first-name "Brandon" :last-name "Bloom"}}, but that would require a schema

18:17 Glenjamin: mm, any sort of data interchange needs an agreed schema

18:17 bbloom: doesn't *need* it

18:17 but it's often nice

18:18 Glenjamin: well, you need to know what you're getting - which requires at least an informal schema

18:18 bbloom: yup

18:18 Glenjamin: whether you make that a formal schema, and whether it should actually be validated against the schema i'm not sure

18:19 bbloom: depends on many factors: do you trust the data source your loading? do you expect it to change? how can it change with or without breaking you? do you have a variety of services that need to interoperate and you want to validate them?

18:20 just like you write tests to make sure your code is correct, you can write schemas to make sure your data is correct

18:20 just like you write defense assertions & throw errors on bad input, you can validate a schema to keep clients honest & valid

18:21 Glenjamin: i guess it comes down to how often you expect it to fail, and then weighing up the cost of validating each payload via a schema, or just having it fail when you try and read the missing data

18:21 at this moment i'm writing a test which asserts an api payload i'm sending matches an xsd schema, but I wouldn't run it at runtime in this case

18:22 bbloom: yeah, if you trust the client not to send pathological documents that will put your code into an infinite loop or something, then you're good :-)

18:22 Glenjamin: and related, java api docs are really annoying - they use a bunch of classes without saying which namespace they exist in :(

18:22 bbloom: indeed.

18:27 Glenjamin: can't seem to find an existing clojure example of xsd validation either :(

18:28 bbloom: Glenjamin: rely on the java libs

18:28 that's what they are there for!

18:28 Glenjamin: mm, but they're awful! DocumentBuilderFactory.newInstance().newDocumentBuilder();

18:29 bbloom: (defn doc-builder (.newDocumentBuilder (DocumentBuilderFactory/newInstance)))

18:29 boom. wrapped.

18:29 get back to work :-)

18:29 Glenjamin: heh, cheers - not quite got the hang of the java interop yet

18:34 bbloom: btw, i forgot []

18:34 heh

18:55 bttf: where can i find a list of lein templates? i am looking for one with ring/compojure bootstrapped

18:56 Glenjamin: is there a neat way to filter a sequence of maps to those which are supersets of a given map?

18:59 gfredericks: select-keys would help

18:59 (let [ks (keys m)] (filter #(= m (select-keys % ks)) maps))

19:00 Glenjamin: seems reasonable, cheers

19:00 bttf: lein new compojure did_it_for_me_thanks

19:01 Glenjamin: is there a logical reason why filter takes [pred coll], seems fairly arbitrary having to use ->> over ->

19:02 bbloom: Glenjamin: it's to facilitate partial application

19:02 (def evens (partial filter even?))

19:02 Glenjamin: mm, i see

19:04 bbloom: as a bonus, you get less stacking close parens w/ literal functions

19:04 Glenjamin: hrm, is there a better way of writing (->> coll (filter pred) first) then?

19:04 bbloom: (filter #(f (g %)) coll) vs (filter coll #(f (g %)))

19:05 Glenjamin: that will work fine

19:05 Glenjamin: yeah, just feels a tad messy for some reason

19:05 bbloom: if a function takes 1 argument, then there isn't really a difference between -> and ->> is there?

19:05 it's not messy

19:06 Glenjamin: hrm, not so much messy, as repetitious - selecting the first matching item from a collection seems fairly common

19:07 maybe i should be using some

19:07 bbloom: some is better for that specific case, yes

19:08 Glenjamin: right, i knew something was bugging me about the construction

19:08 thanks

20:07 neilmock: clojurescript folks: anyone had success running a client-side repl outside of hosted html page, eg chrome extension.

20:10 bbloom: neilmock: currently, you need a server to run the production-quality cljs repl. it depends on java

20:11 neilmock: there is at least one cljs port that runs fully in cljs, so in theory could work in a chrome extension. however, that fork was made a while ago, so it's probably kinda out of date & definitely does no optimizations in the absence of google closure compiler

20:12 neilmock: sorry, I meant connecting to server repl via browser repl. in the same way opening http://localhost:9000 with (repl/connect "http://localhost:9000/repl") in the generated js

20:12 afaik there are some protocol issues when not loading html from server

20:13 bbloom: no theoretical issue with that to the best of my understanding. probably just a "simple matter of programming"

20:14 neilmock: gotcha. "Uncaught Error: URI chrome-extension://jlnmhnikmhdpmmhlajecejebdecghgpf/robots.txt is invalid for field ppu " is my current nemesis

20:14 bbloom: neilmock: turn off all closure optimizations, so you won't have strange field names like ppu & you can maybe make sense of it

20:15 if you find a particular thing that blocks you, you can propose a patch to cljs

20:15 neilmock: best i could find is a google groups post stating "Loading the file directly in your browser will not work. The Closure transport we use does not support that anymore."

20:15 which led me to believe dealing with a chrome extension would be problematic

20:16 also don't have optimizations enabled at the moment

20:17 bbloom: the repl transport probably assumes http

20:17 do chrome extensions not offer an http scheme for access resources?

20:18 neilmock: probably so. I think I understand the issue so far I'll dig into it a bit. many thanks for the feedback

20:19 bbloom: did you look at the stack trace of that error? is it coming from google closure http handling code?

20:22 neilmock: bbloom: I think it is originating from Chrome. re: http://comments.gmane.org/gmane.comp.java.clojure.user/60605

20:24 bbloom: neilmock: ok, gotcha. dnolen already clearly understands all this stuff :-P have you looked at src/cljs/clojure/browser/net.cljs ? there is an IConnection protocol

20:24 you can implement one that is chrome extension friendly

20:24 yeesh that's an ungly protocol tho....

20:25 ugly*

20:25 neilmock: heh yeah, was taking a look...

20:25 isn't the end of the world, was just seeing if possible

20:25 bbloom: like i said: no theoretical blockers

20:25 (that i know of)

20:48 Morgawr: guys, I am using repl with lein and clojurescript (using web repl), is there a way to use up/down arrows to cycle through commands?

20:53 bbloom: Morgawr: use rl_wrap

20:53 or rlwrap or whatever it is called

20:53 Morgawr: how does it work? is this a plugin?

20:53 bbloom: it's a command line tool that gives rudimentary readline support to any other command line tool

20:55 Morgawr: bbloom: this is great! Thank you very much it works like a charm

20:55 bbloom: rlwrap is magic. love it

20:55 Morgawr: yeah :D

20:55 anyhow, thanks and goodnight

21:31 blr: hey there, anyone happen to know if lighttable has a fuzzy file finder feature similar to ctrlp in vim?

21:36 mynomoto: blr: it has. You need to include the directory in the workplace. Then, ctrl+o and type away.

21:45 blr: mynomoto: awesome thank you!

22:43 TimMc: The Clojure Conj 2013 email says "Save the Date!" but doesn't say which date.

22:44 xeqi: Nov 14-16

22:44 its in the image

22:44 TimMc: Oh, OK.

22:44 My mail client doesn't do well with images sometimes.

22:44 and it's certainly not in the text version

22:44 xeqi: agreed, -1 for not being in the text

22:54 gfredericks: TimMc: that issue tripped me up a couple times as well

23:59 technomancy: heh; oops

Logging service provided by n01se.net