#clojure log - Feb 22 2015

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

0:00 julianleviston: ddellacosta: yeah, it’s just creating a copy with bits missing, effectively… so should be roughly that.

0:00 justin_smith: ddellacosta: if you are removing n keys out of m, the into solution is N=(m-n), the select-keys solution is N=n

0:00 ddellacosta: I guess it's O(n) where n is the set of keys you are removing

0:00 right

0:00 justin_smith: ddellacosta: so the number of keys being removed, and the initial count, are going to affect things a lot

0:00 julianleviston: now I have my beautiful function thanks guys… you really do rock… (defn filter-on-keys [pred coll] (select-keys m (filter pred (keys m))))

0:00 ddellacosta: right, right

0:01 julianleviston: haha coll !- m

0:01 good work justin_smith

0:01 I mean good work julianleviston

0:01 justin_smith: heh

0:08 tomjack: If I cared about performance I think I would write (fn [pred m] (reduce-kv (fn [m k v] (if (pred k) m (dissoc m k))) m m))

0:08 ,(time (let [m {:a "hey" :b "yes" "string-key" "should not include"} pred #(keyword? %)] (reduce-kv (fn [m k v] (if (pred k) m (dissoc m k))) m m)))

0:08 clojurebot: "Elapsed time: 1.471779 msecs"\n{:b "yes", :a "hey"}

0:09 justin_smith: ten times faster than the select-keys

0:09 tomjack: (for no good reason besides superstition)

0:09 justin_smith: *slower

0:09 ddellacosta: I'm not sure we can determine much from testing on such a small set of values

0:09 tomjack: right :)

0:09 justin_smith: that's true

0:10 tomjack: I guess the point of the reduce-kv is that you're seq-free

0:10 justin_smith: you've still got a seq on the last arg

0:10 tomjack: no

0:10 justin_smith: no?

0:10 clojurebot: no is tufflax: there was a question somewhere in there, the answer

0:10 ddellacosta: I would think the main thing is to reduce (ha) the number of linear scans over the same set of data

0:11 tomjack: well, I thought not

0:11 but maybe you're right

0:12 justin_smith: tomjack: this seems relevant https://github.com/clojure/clojure/blob/96e8596cfdd29a2bb245d958683ee5fc1353b87a/src/clj/clojure/core/protocols.clj#L180

0:12 tomjack: PHM and PAM's kvreduce are seq-free

0:12 ddellacosta: what does having a seq vs. not do for you? Doesn't it still end up being the same amortized time?

0:12 tomjack: eh, not really

0:12 I mean, not really seq-free I guess

0:12 ddellacosta: oh, yeah, absolutely

0:12 julianleviston: is there a reject-keys? or should I just comp not my pred?

0:13 justin_smith: ddellacosta: the difference is you have lower constant cost

0:13 julianleviston: complement*

0:13 tomjack: but if that's all we cared about, we wouldn't have PHM at all, would we?

0:13 ddellacosta: justin_smith: sorry, can you explain? I'm not getting it

0:13 tomjack: :)

0:13 justin_smith: ddellacosta: same rationale as transducers - same time complexity, less time spent generating garbage

0:13 julianleviston: erm.. that was a silly question… is there a reject keys?

0:13 ddellacosta: justin_smith: dissoc ?

0:13 er, sorry, that was for julianleviston

0:13 see tomjack reduce above

0:14 tomjack's *

0:14 julianleviston: ddellacosta: oh yeah, apply dissoc…stupid me!

0:14 tomjack: justin_smith: it looks like kvreduce for PHM ends up going through a NodeSeq in PersistentHashMap.java

0:14 ddellacosta: justin_smith: still not quite getting it

0:14 justin_smith: right, you need a linear view of the keys no matter what

0:14 tomjack: but looks to be less overhead than a normal seq, I think

0:14 julianleviston: apply makes me somewhat anxious...

0:14 tomjack: (anyway I think it hardly ever matters :))

0:14 ddellacosta: justin_smith: so it's about space considerations?

0:15 justin_smith: ddellacosta: two ops with the same time complexity can take a different amount of time due to overheads that are linear

0:15 it's about time constraints

0:16 tomjack: ddellacosta: binary trees often can get O(log_2(n)) operations. We get O(log_32(n)) stuff for our 32-ary trees. But O(log_2(n)) and O(log_32(n)) are the same -- O(log(n)) -- because log_2(n) = 5 * log_32(n)

0:16 justin_smith: reductio ad absurdum: consider an operations that takes 1 ms per element and is O(n) vs. an op that takes 1 year per input and is O(n)

0:16 ddellacosta: ^

0:16 tomjack: yet, for some reason, we still care about the difference

0:16 ddellacosta: tomjack, justin_smith, okay, I think it's getting through my thick skull now--thanks

0:17 justgreg: I was walking through this tutorial: http://clojure-doc.org/articles/tutorials/vim_fireplace.html and I can't get cpr to run properly even though I have classpath.vim in my pathogen .vim/bundle/ folder.

0:17 ddellacosta: justin_smith: did you mean constant above vs. linear though? "two ops with the same time complexity can take a different amount of time due to overheads that are linear"

0:17 justin_smith: ddellacosta: linear as in their cost is multiplied by the side of the input

0:18 rather than being constant for the algo regardless of input size

0:18 justgreg: I'm using vim in the terminal, executing from the correct path, with $lein repl running in a separate GNU screen terminal

0:18 justin_smith: justgreg: are you sucessfully connected then?

0:18 justgreg: justin_smith, no, that's exactly the problem.

0:20 justin_smith, it was working, then I removed a line related to autocomplete from my .vimrc -- because autocomplete wasn't working properly.

0:20 justin_smith: OK - I don't know enough about fireplace to help beyond that, sorry. Thought maybe it was an issue where my clojure knowledge would help.

0:21 hopefully someone else knows more about fireplace and can help you out

0:21 justgreg: justin_smith, thanks anyway. #vim sent me here.

0:21 justin_smith: I find it odd that the tutorial does not mention any explicit "connect to a repl" step

0:22 I would think such a command would exist

0:22 justgreg: It mentions the :connect command, but it also ought to connect automatically.

0:23 justin_smith: I would try figuring out how to run connect manually

0:24 justgreg: (nod) I'm just annoyed because it was working previously, and pathogen.vim appears to be working erratically.

0:24 swarthy: When I was using vim 'Vundle' was a much simpler package manager

0:24 I had vim + fireplace working with that

0:25 justgreg: swarthy, really? pathogen claims to just require putting everything in .vim/bundle

0:26 swarthy: Vundle you just add the github repo as a line, plus two other lines to your vimrc

0:26 then when you start vim

0:26 it does it all automatically

0:26 to connect though

0:27 just open two terms

0:27 in one do $ lein repl

0:27 look at the port number it shows

0:27 then in the other term with vim

0:27 do ':connect'

0:27 follow the prompts using default for everything

0:27 except port

0:27 enter that from before

0:27 Alternatively, if everything is working you just open vim in the directory where there is a running repl

0:28 and a subsequent

0:28 '.nrepl-port' file

0:28 Not to start a flame war, but I've found emacs + prelude + evil-mode a better experience.

0:28 justgreg: run :connect as a vim command or enter it in the file?

0:28 swarthy: command

0:28 it might be :Connect

0:28 if that doesn't work

0:30 justgreg: I'm starting to get fed up w/ vim and liking lisps more and more. I might just try to deal w/ my c-ish scripting langauges in emacs rather than lisps in vim.

0:32 swarthy: justgreg: I had a hard time getting emacs going with evil mode on my own

0:32 prelude makes it really easy to get up and running after being a vim user

0:32 http://batsov.com/prelude/

0:32 I recommend that, turning on evil mode is one line

0:32 a lot of vim stuff works

0:33 not 100% but enough

0:33 I used vim for several years, but I'm not die hard about it.

0:34 honestly I use vim for stuff still plenty, do the c stuff there. No reason to only use one thing, use whatever is best.

0:34 justgreg: I never learned it especially well. I treat it more or less like a nano with syntax highlighting and indenting. I've also never genuinely tried emacs outside of learning sml in it, which was how I learned basic fp.

0:34 julianleviston: prelude? haha I thought I was in the wrong channel there for a second :)

0:34 swarthy: oh like Prelude in haskell?

0:34 might be where he got the name

0:35 julianleviston: swarthy: yeah :)

0:35 swarthy: justgreg: well prelude makes the barrier to entry basically 0. After two days I was flying around.

0:36 justgreg: Sweet. I was mostly looking for music-making in a language I could claim was making me a better programmer. There's a very good livecoding environment called Overtone.

0:36 swarthy: Yeah, I've seen it & I tried their emacs thing a while back. It was a bit complicated and I gave up.

0:36 Might be easier now.

0:36 julianleviston: I really like stuff that bridges things. Clojure is very bridgy, obviously.

0:39 So I ended up with a “better” thing for selecting parts of a map… (defn select-filter [pred coll] (select-keys coll (keys (filter pred coll))))

0:39 justgreg: I was *trying* to use a scheme dialect, but it's not very well-maintained.

0:40 julianleviston: it makes things like this so much more readable: (let [expired-items (select-filter #(time-expired? (:timestamp %)) chan-maps)] …)

1:30 wenshan: I have two lists A: (1 2 3 4) and B (2 4 5 6), how do I do (- A B) to get (-1 -2 -1 -2)?

1:34 kriyative: wenshan: (map - '(1 2 3 4) '(2 4 5 6))

1:36 tomjack: (map - '(1 2 3 4) '(2 4 5 6) '(0 0 -1 0)) ? ;)

1:37 kriyative: ah, didn't see that ... I presume the second -1 was a typo?

1:48 wenshan: kriyative: yes, that was a typo, (map - A B) works, thank you

1:51 kriyative: wenshan: as tomjack indicated, `map` extends to (map - A B C ...) etc.

1:53 tomjack: ,(apply map vector [[1 2 3] [4 5 6] [7 8 9]])

1:53 clojurebot: ([1 4 7] [2 5 8] [3 6 9])

1:54 awwaiid: Question for any overtone folks who might be here: (apply eval ['(piano)]) works, but (apply-at (+ (now) 1000) eval ['(piano)]) does not; it appears to have some issue that it is silently discarding. Any pointers?

1:54 (note that the eval is because the '(piano) is actually dynamically generated)

2:28 wenshan: hmm, I have a single file (not within a project) opened and started a REPL with cider-jack-in. Now how can I use the math functions (e.g. round)? Simply evaluating (use 'clojure.contrib.generic.math-functions) returns "java.lang.ClassNotFoundException: clojure.contrib.generic.math-functions"

2:30 kriyative: wenshan: try (Math/round 3.14)

2:30 I'm pretty sure clojure.contrib.generic.math-functions is deprecated

2:45 wenshan: kriyative: thanks again, (Math/round 3.14) works, but (Math/round (/ 1 20)) does not work, I guess this is because (/ 1 20) is a ratio, not a number?

2:48 TEttinger: wenshan: to import a file without being in a project, you would still need some amount of lein usage. I think lein imports some of its dependencies into the REPL by default, one of which lets you download a dep in the repl

2:48 pomegranate maybe?

2:48 aether?

2:48 I can't remember

3:06 rritoch: Is anyone here skilled with regular expressions?

3:06 amalloy: ~anyone

3:06 clojurebot: anyone is anybody

3:09 rritoch: I wrote a blog/tutorial on reverse engineering regular expressions, and was hoping someone could review it to see if there is anything I've missed, or if there are any technical errors.

3:16 TEttinger: rritoch, post away

3:16 I like em, I wouldn't say I'm that skilled with them

3:16 rritoch: --> http://www.ritoch.net/2015/02/22/the-exorcism-of-regular-expressions/

3:16 TEttinger: wasn't someone making a regex prover or something?

3:17 rritoch: It is a little themed to sorcery, but other than that it should be fairly easy to read.

3:17 TEttinger: or a type checker for regexes?

3:18 rritoch: Hmm, I don't know. I made some code to ungreedy a regular expression using clojure, but I'm not aware of the projects your mentioning. This is more a manual process for reverse engineering a regular expression, though much of it can be automated.

3:19 I'm also making the suggestion that programmers document their regular expressions, as if that would ever happen, lol

3:21 TEttinger: nice article, rritoch

3:21 I scanned the second page, didn't read in depth, but it's sound advice

3:22 rritoch: TEttinger: Thanks. I have to be honest, it took me 4 hours to write the blog and reverse engineer the example, but I think the end result is at least helpful.

3:22 amalloy: rritoch: are you really recommending documenting regexes by adding a commented-out verrsion with newlines and indentations, rather tahn recommending use of the /x flag?

3:23 rritoch: amalloy: No, that is just a middle step of the reverse engineering process

3:24 amalloy: The final result is in the last code block.

3:24 TEttinger: ambrosebs might have been?

3:25 rritoch: amalloy: The final result is an approximation of BNF

3:27 TEttinger: rritoch: since such a big part of programming is giving names to things, the fact that regexes don't have much in the way of naming by default makes them hard to understand when they get large

3:27 I like your named component parser-style approach

3:33 rritoch: TEttinger: Well, the idea came to me while manually translating a BNF language definition into Java code. After translating enough entries it occured to me that the process was somewhat reversable, so this is what I came up with to extract the functionality of a complex regular expression.

4:29 the-kenny: Hm. Why is creating leiningen templates so painful? Copying all files over & then creating entries manually is cumbersome

4:33 rritoch: the-kenny: Leiningen is open source and can be extended with plugins. If your finding the process repetative you could probably make a plugin to automate the process. You would probably end up with a lot of users of the plugin.

4:44 the-kenny: rritoch: I know I know :/

5:09 julianleviston: the-kenny: or you could use that new thing instead of lein

5:09 the-kenny: julianleviston: doing that right now. It's still pretty cumbersome

5:09 julianleviston: the-kenny: what’s it called again?

5:09 the-kenny: newnew

5:09 julianleviston: the-kenny: why’s it cumbersome?

5:09 the-kenny: oh no, wait

5:10 it's [lein-create-template "0.1.1"]

5:10 julianleviston: still many manual steps. Cleaning up, etc. It creates a flat folder structure in resources/leiningen/new/ which is confusing in some situations.

5:10 julianleviston: the-kenny: I was talking about Boot

5:10 the-kenny: oh

5:11 julianleviston: the-kenny: sozzy :)

5:11 the-kenny: actually I'd like to be able to just specify a "normal" leiningen project as source and rename the namespaces. Like forking a git repository

5:12 julianleviston: the-kenny: make it so, captain :)

5:12 the-kenny: haha :)

5:43 wenshan: b

8:48 AeroNotix: Can anyone recommend a websocket library for ClojureScript? The one that appears the most is Sente, but my god is it bloody complex

8:49 dnolen: AeroNotix: Google Closure Library has some stuff you can use if you want something more minimal.

8:50 AeroNotix: dnolen: all I really need is something that returns perhaps channel and has no huge opinions on what the message format should be

8:50 https://github.com/james-henderson/chord seems reasonable at first glance.

8:51 dnolen: if I were to use the google library, I wonder how easily I can map the JS docs into Cljs. Is that something you think is a barrier?

8:52 (or perhaps some enterprisin' individual has converted the docs, I wouldn't be surprised)

8:52 dnolen: AeroNotix: the docs haven't been converted but there's really no need, CLJS interop is pretty simple after all.

8:53 AeroNotix: dnolen: I'm not really familiar with javascript at all tbh

8:53 dnolen: AeroNotix: it will be difficult to be as productive as possible with ClojureScript if you don't know JavaScript basic.

8:53 s/basic/basics

8:53 AeroNotix: I know the basics-ish

8:53 lets say

8:54 dnolen: AeroNotix: then you probably won't have a problem

8:54 AeroNotix: cool, I'll persevere

8:54 justin_smith: AeroNotix: dude wrote the lang in a week, you shouldn't take long to get up to speed

8:55 AeroNotix: lol

8:55 https://github.com/swannodette/om-async-tut oh this is nice

10:32 sol__: what does it mean if i have ^bytes in the signature? (defn foo [x ^bytes payload])?

10:33 oh, java type hints :)

10:36 frzn: oskarth: is breakfast running live anywhere? Couldn't see it running in http://breakfast.clojurecup.com/

10:40 AeroNotix: frzn: what the hell is that webpage haha :)

10:41 frzn: AeroNotix: no idea! haha. But the oskarth project looks nice. I'm planning to use it, if I can get it to work.

11:10 gfredericks: happy 10:10am to everybody in my time zone

11:12 devll: it is 10:00 pm here,but Happy to you too.

11:12 gfredericks: must be one of those weird off-by-ten-minutes time zones

11:13 devll: lol. 10:12

11:13 Any recommendations for scheduling libraries?

11:14 gfredericks: ~this one weird time zone |will destroy| your faith in humanity; programmers hate it!

11:14 clojurebot: c'est bon!

11:14 devll: quartzite , at-at

11:15 I am not sure which to pick.

11:17 frzn: AeroNotix: #clojurecup-breakfast

11:17 now is running nice :)

11:17 (local)

11:17 oskarth: nice job.

11:59 irctc__: I don't know if it's okay to ask here but quick question guys: why does (for [a (range 4), b (range a)] [a b]) give the same result as (for [a (range 1 4), b (range a)] [a b]) even though `a` should be starting from 0? It's giving me ([1 0] [2 0] [2 1] [3 0] [3 1] [3 2]) as the result. And I'm expecting it to start from [0 0].

12:01 aroemers: devll: Depends on your usecase. I find at-at nice and simple. Quartzite has more features.

12:01 * aroemers has got to go now

12:05 vas_: ,(for [a (range 1 4)] [a])

12:05 clojurebot: ([1] [2] [3])

12:06 vas_: ,(for [a (range 4)] [a])

12:06 clojurebot: ([0] [1] [2] [3])

12:06 subhashgo: irctc__ : (range 0) -> ()

12:07 irctc__: ,(for [a (range 4) b (range a)] [a b])

12:07 clojurebot: ([1 0] [2 0] [2 1] [3 0] [3 1] ...)

12:08 irctc__: oh

12:08 subhashgo: ok thanks, it just hit me.

12:08 subhashgo: No worries

12:08 irctc__: :)

12:13 vas_: irctc_: i think this is an appropriate place to ask that stuff, by the way, as it always helps me out when i try and provide an answer, so everyone wins :]

12:17 irctc__: vas_: that's good to know :) thanks for helping out too

12:38 kras: Hi, why is this code hanging http://pastebin.com/yru9TzKx

12:38 I am just trying out a basic loop recur

12:39 Any hints will really help

12:41 hyPiRion: ,(next '(1))

12:41 clojurebot: nil

12:41 raek: kras: use 'empty?' instead of 'nil?', and use 'conj' instead of 'concat'

12:42 or, instead of changin the 'nil?', you could change the let to [e (seq v), res []]

12:43 hyPiRion: kras: what does (next v) return? :)

12:44 kras: ,(next [1 2 3 4 5

12:44 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

12:45 kras: ,(next [1 2 3 4 5])

12:45 clojurebot: (2 3 4 5)

12:45 hyPiRion: kras: Eventually, a better hint: What's the difference between (next v) and (next e)?

12:45 raek: kras: the propblem using 'concat' here is that it expects to sequences, but you are giving it a vector and an element

12:45 kras: :-|

12:45 Got it thanks hyPiRion

12:46 hyPiRion: np, was confused for a bit too

12:46 kras: I should be using the binded e inside the loop

12:46 raek: thanks for the suggestions

12:50 raek: concat works on two colls, whereas I am giving it one coll and one Long, so had to change it to conj

12:55 what is an idiomatic way of checking an element's presence in a collection? Equivalent of "in" operator in python

12:57 ,(some #{2] [1 2 3 4])

12:57 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

12:57 kras: ,(some #{2} [1 2 3 4])

12:57 clojurebot: 2

12:57 kras: this seems like an overkill

13:00 the-kenny: kras: yes, that's the idiomatic way

13:00 If your collection is a set, you can use contains?

13:07 oskarth: frzn: thanks! It's currently not running live (the free server clojurecup offered expired afaik)

13:07 frzn: curious, how did you find it?

13:08 frzn: oskarth: I found one project from clojurecup in hackernews, looked for others and found yours.

13:08 oskarth: oh cool

13:09 hope it's useful!

13:09 meant to extend it and clean it up, but never happened :p

13:09 frzn: I'm planning to create a integrated chat with IRC to put in a sidebar in my webapp.

13:09 oskarth: I now how it is! haha

13:09 but it will be useful, for sure.

13:10 oskarth: awesome :)

13:10 imanc_: what's the best way to write gui apps in clojure?

13:32 justin_smith: imanc_ seesaw makes it pretty easy, people like the way javafx looks though

14:15 vas_: what's a good approach for caching database results between queries?

14:19 justin_smith: vas_: I've used a wrapper where an atom maps from queries to results, and insertions remove keys from the hash (so you don't get stale results)

14:20 vas_: also, eg. datomic is cached for you automatically

14:24 gfredericks: anybody know why clojure seems to name its functions one package level up?

14:25 e.g. (ns foo.bar) (defn baz []) creates the class foo.bar$baz

14:25 vas_: justin_smith: well i have not used atoms before, so i will have some researching to do ... I was trying to naievely just memoize the function that connects to the DB, but I can't invoke "nth" on the result set .. dunno why

14:25 justin_smith: vas_: atoms are pretty straightforward, it's worth taking a few hours to figure them out

14:26 ,(let [a (atom {}] (swap! a assoc :a 0) (swap! a assoc :b 1))

14:26 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

14:26 justin_smith: er

14:26 ,(let [a (atom {})] (swap! a assoc :a 0) (swap! a assoc :b 1))

14:26 clojurebot: {:b 1, :a 0}

14:28 vas_: justin_smith: cool. arigato

14:30 by the way, some things just clicked for me the other day with enlive. was able to clean up my code immensely

14:30 justin_smith: vas_: for what you want atom / swap! (with assoc or dissoc) / @ should be all you need

14:30 cool

14:30 vas_: @?

14:30 clojurebot: @ is like the macro version of apply

14:30 vas_: lol thank you clojurebot! =D

14:31 justin_smith: ,(let [a (atom "hello")] [a @a])

14:31 clojurebot: [#<Atom@267038a5: "hello"> "hello"]

14:31 justin_smith: notice the difference between the two elements of that vector

14:31 that's what @ does

14:31 it's a reader shortcut for deref

14:49 gfredericks: oh clojurebot was trying to talk about ~@

14:50 justin_smith: oh, that makes much more sense, yeah

14:50 ~@?

14:50 clojurebot: @ is forget @

14:50 justin_smith: hahaha

14:52 ~~@?

14:52 clojurebot: ~@ is splicing unquote

14:52 justin_smith: there we go

14:53 kaplan_: justin_smith, what is difference between unquote and splicing unquote?

14:53 justin_smith: ,`(a b ~(+ 1 2 3))

14:53 clojurebot: (sandbox/a sandbox/b 6)

14:54 justin_smith: ,`(a b ~@(+ 1 2 3))

14:54 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

14:54 justin_smith: err

14:54 ,`(a b ~@[1 2 3])

14:54 clojurebot: (sandbox/a sandbox/b 1 2 3)

14:54 justin_smith: ,`(a b ~[1 2 3])

14:54 clojurebot: (sandbox/a sandbox/b [1 2 3])

14:54 justin_smith: it splices

14:55 kaplan_: justin_smith, that went over my head

14:57 justin_smith: ~ unquotes

14:57 clojurebot: Pardon?

14:57 justin_smith: ~@ inserts a collection, unquoted

14:57 clojurebot: Cool story bro.

14:58 justin_smith: I think I have a clearer way to show it

14:58 ,(def a 42)

14:58 clojurebot: #'sandbox/a

14:58 justin_smith: ,`(a ~a)

14:58 clojurebot: (sandbox/a 42)

14:58 justin_smith: see how ~ made it unquote?

14:59 ,`(a ~[a a a])

14:59 clojurebot: (sandbox/a [42 42 42])

14:59 kaplan_: justin_smith, ah, I see

14:59 justin_smith: ,`(a ~@[a a a])

14:59 clojurebot: (sandbox/a 42 42 42)

14:59 justin_smith: notice the differencebetween what ~[] did and what ~@[] did

14:59 kaplan_: yep

14:59 no vector around ~@

14:59 justin_smith: right, it gets spliced in to the parent

15:00 kaplan_: justin_smith, can you give a practical example of a macro?

15:01 justin_smith: ,(defmacro spy [form] `[~'form ~form])

15:01 clojurebot: #'sandbox/spy

15:01 justin_smith: ,(spy a)

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

15:01 justin_smith: hrm

15:02 right

15:02 ,(defmacro spy [form] `['~form ~form])

15:02 clojurebot: #'sandbox/spy

15:02 justin_smith: ,(spy a)

15:02 clojurebot: [a 42]

15:02 justin_smith: ,(spy (+ 1 2))

15:02 clojurebot: [(+ 1 2) 3]

15:03 justin_smith: the macro returns a vector containing the original input quoted, and what it evaluates to

15:03 kaplan_: justin_smith, ah, I see

15:04 justin_smith: the general idea with a macro, is you return the form that should be evaluated

15:04 kaplan_: justin_smith, but I still can't think of anything where I might find this useful

15:04 justin_smith: def is a macro

15:04 benmoss: is there a decent way to access the version number of a lib from within the lib itself

15:04 justin_smith: that's why you can just give the name you are defining, and don't have to quote it or anything

15:04 kaplan_: justin_smith, ah, I see

15:05 justin_smith: kaplan_: in general, you should rarely need to write macros. But they are very useful when you need them.

15:05 they are for when you need to change the evaluation rules, or introduce a new syntax

15:07 "the first rule of macro club, is don't write macros"

15:07 kaplan_: justin_smith, are all of clojure's built in keywords like def built with macros?

15:07 justin_smith: kaplan_: there are a lot of macros in the language

15:07 actually, it's possible to build a list

15:08 ,(filter (comp :macro meta) (vals (ns-publics 'clojure.core)))

15:08 clojurebot: (#'clojure.core/when-first #'clojure.core/cond->> #'clojure.core/gen-class #'clojure.core/while #'clojure.core/import ...)

15:08 justin_smith: in your repl, that will list all the things in clojure.core that are macros

15:08 &(filter (comp :macro meta) (vals (ns-publics 'clojure.core)))

15:08 lazybot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

15:09 justin_smith: blergh

15:18 crazydiamond: Hi. In CIDER, when *cider-error* buffer displayed, can I automatically jump to line/char where error happened?

16:05 devll: Hi,in mf Compojure appindex.htm is a valid url. I want to trim "index.htm/".

16:05 *my

16:07 but Compujure treats "index.htm" and "index.htm/" the same way

16:07 It never reaches my wrapper function.

16:09 I can manage to trim urls like "/music/" to "/music",but not the "htm" files.

16:09 How can I trim this?

16:12 justin_smith: why is it not reaching your wrapper?

16:15 devll: none of the static resources reach wrappers.

16:16 I think "index.htm/" is treated as static.

16:16 justin_smith: oh, because your middleware is shortcircuiting the request

16:17 yeah, having a route that should be the same as a static resource is a bad idea, you should move one of the two

16:18 why does the file "index.htm" need to be in the static resources folder?

16:18 devll: it is in the public folder.

16:18 justin_smith: why?

16:18 clojurebot: http://clojure.org/rationale

16:19 AeroNotix: ~why

16:19 clojurebot: http://clojure.org/rationale

16:19 AeroNotix: ,why

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

16:19 AeroNotix: THERE IS NO WHY

16:19 :)

16:19 justin_smith: devll: if you want something to be a route with a handler etc. then it shouldn't be a static resource, and visa versa

16:19 devll: I am just serving the file.

16:19 justin_smith: because one of the two is not going to work if you try to use both

16:20 devll: "index.htm" is not a route

16:20 AeroNotix: so you have a static file handler/middleware?

16:20 and you have a 'chop-off-the-trailing-slash-middleware'

16:20 ?

16:20 show your routing code.

16:20 devll: I dont have static file mw

16:21 justin_smith: devll: sorry, I misunderstood. In this case you need to switch the ordering of the static wrapping mw and the drop-slashes one

16:21 AeroNotix: justin_smith: yeah^ Was thinking this was the case.

16:21 justin_smith: devll: if the file is getting served, you do, it is likely hidden in the default ring middleware

16:21 devll: (route/resources "/")

16:21 (ANY "*" []

16:21 "404"))

16:22 and I have many route like "/music"...

16:22 OK

16:23 justin_smith: OK, so you explicitly serve resources

16:23 and you want to remove trailing slashes before that gets hit?

16:23 devll: yes.

16:24 justin_smith: do you have a middleware that does this already?

16:24 devll: I have one chops trailing slashes

16:24 It does the jobs for "/music/"

16:25 justin_smith: but you still get a 404 for /index.htm/

16:26 devll: in my case ,it is a file download

16:26 I guess I should add a static mw and reorder it.

16:26 am I right?

16:26 justin_smith: that sounds right, yes

16:27 devll: OK. thanks. (inc justin_smith)

16:28 (inc justin_smith)

16:28 lazybot: ⇒ 192

18:42 chr15m: Hello! I have been beating my head against the externs file requirement of Google's closure for days. I finally found this project, which fixed all of my problems by generating an externs file from my cljs code directly: https://github.com/ejlo/lein-externs - how come it only has two stars? Has everybody moved on from this? What do people use to handle the externs file situation?

20:06 JavaDog: Could anyone give me a quick hand? I'm doing this for a code gold thing:

20:06 golf*

20:06 (drop iterator (remove #(.contains (take-nth (nth collection iterator) collection) %) collection)))

20:07 However, I get a "java.lang.IndexOutOfBoundsException: null" on this line. I think it's related to lazy sequences, and I've tried using (doall thatSeq), but I'm not sure whether I'm doing that right.

20:17 irctc__: is there an atom? equivalent in clojure

20:34 gfredericks: nope

20:34 ,clojure.lang.IAtom

20:34 clojurebot: clojure.lang.IAtom

20:34 gfredericks: can check against that

20:35 there's a ticket somewhere about this I think

20:35 ,atom?

20:35 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:35 cfleming: gfredericks: Yeah, IIRC it might be for 1.7

20:39 gfredericks: ,*clojure-version*

20:39 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

20:39 crazydiamond: Hi. Is there ability to define functions like = for certain classes created with deftype?

20:42 gfredericks: I think overriding Object#equals will accomplish that

20:42 not sure what other functions are "like =" that you're referring to

20:43 amalloy: gfredericks: people who ask for an atom? equivalent usually mean it in the common lisp sense

20:44 crazydiamond: I'mhaving code like this: (deftype MyType [...] ...) (MyType. x [...]) (MyType. y [...]) (are_equal x y)

20:44 and there I have almost everything in class definitions

20:44 but standalone function are_equal

20:45 and I want it to be associated with types

20:45 though, everything works

20:45 but I still think it would be better to do association

20:47 gfredericks: amalloy: oh that sense of "equivalent"

20:58 amalloy: gfredericks: i'm curious what other sense of equivalent you're thinking of

21:00 TEttinger: ,atom?

21:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:00 TEttinger: ,promise?

21:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: promise? in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:00 TEttinger: hm

21:00 ,ref?

21:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ref? in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:00 TEttinger: are there any type checks for stuff like atoms?

21:01 gfredericks: amalloy: "equivalent to this thing from another language that actually exists" vs "equivalent to this imaginary clojure function"

21:01 TEttinger: what's a "type check"? you mean a function like the ones you're searching for?

21:01 ,(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))) shuffle)

21:01 clojurebot: [nil? fn? var? thread-bound? ifn? ...]

21:02 TEttinger: I guess, kinda like float? or something like it

21:02 gfredericks: ,(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))) shuffle)

21:02 TEttinger: ,float?

21:02 clojurebot: #<core$float_QMARK_ clojure.core$float_QMARK_@3ee8c23e>

21:02 [future-done? odd? future? bound? zero? ...]

21:02 gfredericks: ,(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))) shuffle)

21:02 clojurebot: [pos? identical? every? future-cancelled? ifn? ...]

21:02 TEttinger: whatcha doing gfredericks?

21:03 imaginary clojure, from the makers of invisible bike and high-performance INTERCAL

21:04 &(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))))

21:04 lazybot: java.lang.SecurityException: You tripped the alarm! ns-publics is bad!

21:04 TEttinger: haha

21:05 ,(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))) #(clojure.string/join " "))

21:05 clojurebot: #<sandbox$eval195$fn__196 sandbox$eval195$fn__196@5cdc4aaa>

21:05 TEttinger: ,(->> (ns-publics 'clojure.core) keys (filter #(= \? (last (str %)))) (clojure.string/join " "))

21:05 clojurebot: "decimal? contains? every? satisfies? seq? fn? vector? thread-bound? isa? char? some? future-done? pos? sequential? neg? reduced? float? set? reversible? bound? map? volatile? var? empty? string? associative? keyword? even? extends? counted? future? zero? not-every? class? future-cancelled? sorted? nil? instance? record? identical? true? integer? special-symbol? ratio? delay? ifn? chunked-seq? dis...

21:05 TEttinger: so we have var?

21:06 and delay?

21:06 very odd

21:07 gfredericks: there's a ticket for it

21:16 ,(defmacro defmulti! [name & args] `(do (def ~name nil) (defmulti ~name ~@args)))

21:16 clojurebot: #'sandbox/defmulti!

21:20 TEttinger: gfredericks, what... I'm slightly nervous to use that

21:22 rhg135: what is the point of this defmulti! i wonder

21:22 gfredericks: TEttinger: defmulti refuses to redefine things the second time you use it; defmulti! tricks it into doing so

21:22 rhg135: ah i see

21:23 TEttinger: that's... devious

21:23 gfredericks: also racey since the function is temporarily nil

21:24 rhg135: i don't think it's racey since do is guaranteed to run them in order

21:25 gfredericks: another thread could call it while it's nil

21:26 I bet you could fix that by setting it to a proxy function instead

21:28 rhg135: oh I see

21:30 gfredericks: amalloy: oh I just figured out how to throw that dynamic var exceptoin

21:31 it looks like it is only possible with futures and agents

21:32 amalloy: binding conveyance? i sorta expected that to prevent it, not cause it, but okay

21:32 gfredericks: TIL that what futures and agents do is different from what bound-fn does

21:32 which is different from what starting a raw thread does, which was your original suggestion

21:33 dynamic vars what are you gonna do.

21:35 crazydiamond: Hi. Is there a way to clean session in REPL? I'm using fireplace.vim and doing series of updates followed by %Eval. So, next time I hit eval, old things that I might deleted are still alive. Is there a way to start clean, each time I'm doing %Eval? (This effect makes Clojure sooo stateful for me).

21:43 justin_smith: crazydiamond: clojure.tools.namespace has a namespace recet

21:43 *reset

21:43 crazydiamond: justin_smith, thanks

21:44 (clojure.tools.namespace.repl/refresh) works for me now

21:44 TEttinger: (inc justin_smith)

21:44 lazybot: ⇒ 193

21:44 TEttinger: almost to 200

21:44 justin_smith: there is also stuartsierra's component for doing modular restarting of state

21:44 getting close

21:48 gfredericks: is tonight the night that justin_smith gets to 200?

21:48 justin_smith: quick start telling jokes

21:49 justin_smith: I've been lambda lifting all night, and boy are my arms tired!

21:49 rhg135: *crickets*

21:50 gfredericks: tonight is not going to be the night

21:53 justin_smith: My wife, lemme tell ya folks, I try to explain to her, Liskov's substitution principle says I could just trade her in for a mentally disabled donkey...

21:56 gfredericks: a mentally disabled monkey is a subtype of your wife?

21:56 justin_smith: it's quite unfortunate

21:57 (not even dating not to mention married)

21:57 rhg135: ok...

21:57 justin_smith: sorry, I will stop making intentionally cringeworthy CS themed jokes

21:58 it was my "best" interpretation of henny youngman groaners

21:58 https://www.youtube.com/watch?v=i7gg8GGP79w

22:05 gfredericks: I listened to that entire thing and now I'm older

22:06 justin_smith: hehe

22:07 chr15m: does anyone else find this passive aggressive:

22:07 $ git rebase --continue

22:07 No rebase in progress?

22:08 maybe i just need more sleep

Logging service provided by n01se.net