#clojure log - Jun 12 2015

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

1:20 ronh_: -scon 'a disconnect

1:25 mercwithamouth: so...has anyone written a syntax highlighter before?

1:26 i've always loved crayon syntax highlighter but it's written in php and jquery... i'm really tempted to try writing one that works as well in clojurescript

1:28 though it seems like a daunting project at my level

3:36 kap: compared to PersistentVector is there a performance difference when getting indexed items from PersistentList ?

3:36 aka, is it worth modifying conj like so? (conj (or (k m) []) v)

3:37 hiredman: ,(doc fnil)

3:37 clojurebot: "([f x] [f x y] [f x y z]); Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x. Higher arity versions can replace arguments in the second and third positions (y, z). Note that the function f can take any number of arguments, not just the one(s) being nil-patched."

3:38 TEttinger: (inc hiredman)

3:38 lazybot: ⇒ 80

3:41 kap: ,(class (conj nil 3))

3:41 clojurebot: clojure.lang.PersistentList

3:41 kap: ,(class (conj (or nil []) 3))

3:41 clojurebot: clojure.lang.PersistentVector

4:51 WickedShell: justin_smith, thats the impression I had, but hadn't been able to find any documentation on it either way (and was far from a computer on which to test from)

5:57 whodidthis: whats a command in clojure-mode/paredit to move forms backwards/forwards in a list

6:07 elvis4526: hey guys whats the best way to delete a nested key in a map ?

6:09 oddcully: ,(update-in {:a {:b {:c 1 :d 2}}} [:a :b] dissoc :d)

6:09 clojurebot: {:a {:b {:c 1}}}

6:10 elvis4526: that's really neat - thanks

7:40 acron^: is there a form to describe 'if x is a var, perform fn on it, else if x is a sequence of vars, perform fn on each one'?

7:40 without a load of (if (seq? etc..

7:41 justin_smith: acron^: is (range) a sequence of vars?

7:41 (I mean literally it is not, just making sure I understand what you mean)

7:41 Empperi: ,(doc var?)

7:41 clojurebot: "([v]); Returns true if v is of type clojure.lang.Var"

7:41 justin_smith: Empperi: I don't think acron^ means var at all

7:41 Empperi: ,(doc sequence?)

7:41 clojurebot: It's greek to me.

7:41 acron^: maybe i dont mean var

7:42 Empperi: ,(doc sequential?)

7:42 clojurebot: "([coll]); Returns true if coll implements Sequential"

7:42 acron^: for this example, interchange var with string

7:42 justin_smith: OK, you mean value

7:42 acron^: sorry :) yes

7:42 justin_smith: acron^: the snarky reply to your situation is "fix the code that can't decide whether to return a collection or not"

7:43 acron^: hmmm

7:43 justin_smith: acron^: for example, in my code I often use collections of collections - how would any function know if the collection I provided was one collection out of a sequence of them, or my top level collection?

7:44 acron^: if I am using an API that returns sometimes a collection, sometimes a string, I like to make a thin wrapper that puts the string into a vector, just so all my other code doesn't have to worry about it

7:44 acron^: my instruction is "make this fn accept a value or a seq of values" so my immediate reach is (if (seq? x) etc...

7:45 justin_smith: acron^: the reason I avoid ever having that kind of logic is that it is contagious

7:45 acron^: so yeah, i could just throw an (if (seq? x) x [x]) in place

7:45 justin_smith: you allow one function to work that way, and suddenly every other function that uses it needs a similar if check...

7:45 acron^: yes, that is the sane way to do it :)

7:45 acron^: thanks justin_smith :)

9:15 CookedGryphon: has anyone here used bolth?

9:16 it looks pretty good, but I want to use it on my CI server and it doesn't seem to have a command line way of just doing run all tests?!

9:16 even if I make a main method that calls run-all-tests, I need to explicitly import all my test namespaces, it doesn't pick up everything from the classpath

9:54 ionthas_: (doc foreach)

9:54 clojurebot: I don't understand.

9:55 ionthas_: Is there any function to apply a function to each element of a vector?

9:55 code-ape: ionthas_: I'm not super experienced with clojure yet, but won't map work?

9:59 oddcully: ,(map #(* % %) [1 2 3])

9:59 clojurebot: (1 4 9)

10:01 joegallo: ,(mapv #(* % %) [1 2 3]) ; if it's important to you that you get a vector back rather than a sequence

10:01 clojurebot: [1 4 9]

10:09 rumblepack: Hi everyone :D

10:10 ionthas_: thanks! I forgot mapv :)

10:10 (just doing my first project in clojure)

10:10 rumblepack: Cool! How is it going?

10:11 joegallo: oh, in that case, here: ((()((())))(())) i've got some extra parens you can have

10:11 oddcully: you never stated the returntype you are after ;p

10:11 joegallo: :)

10:12 code-ape: Also, just out of curiosity, has anyone started using the clojure.core/typed package?

10:12 rumblepack: Never needed to so far.

10:13 shem: code-ape: i have tried to but it's pretty painful if you have lots of dependencies

10:15 code-ape: shem: yeah, I was trying it with aleph and that was my experience.

10:15 ToxicFrog: Yeah, I've tried using it a few times, but it chokes on dependencies, it has trouble with command line args, eventually I just gave up.

10:15 Probably going to give it another shot next year and see if it's mature enough to use then.

10:15 I really like it as a concept, the implementation just isn't there yet.

10:16 code-ape: ToxicFrog: I really like the idea of it too, I've debated taking some time to type declare some of the smaller libraries I use and throw our a PR for it.

10:17 ToxicFrog: (I also managed to crash it outright a few times in totally unhelpful ways, which ate up a lot of my patience for dealing with it)

10:54 ionthas_: I have a vector of vectors [[1 2] [3 4] [5 6]] and I want to apply a function to calculate the product of all the sub-vectors #(apply * %). The problem I have is, if I apply (mapv %(apply * %) [[1 2] [3 4] [5 6]]) I get the only the result of that operations [2 12 30]. What I really want is: [[[2 [1 2]] [12 [3 4]] [30 [5 6]]]. I implemented that with a loop/recur but I would like to find a more idiomatic way.

10:55 justin_smith: ,(mapv (juxt (partial apply *) identity) [[1 2] [3 4] [5 6]])

10:55 clojurebot: [[2 [1 2]] [12 [3 4]] [30 [5 6]]]

10:56 justin_smith: something like that?

10:56 ionthas_: wow thanks justin_smit. Exactly like that.

10:56 justin_smith: (inc juxt)

10:56 lazybot: ⇒ 22

10:56 ionthas_: I didn't know the functions juxt and partial

10:57 justin_smith: ionthas_: check out http://conj.io - just looking around on that page every time you want to figure out a new problem helps learning the core language

10:57 most of clojure.core is on that page

10:58 ionthas_: thanks :)

10:58 lasergoat: If I want to use core.async's poll! and offer!, what's my best option? There hasn't been a release in a while

11:01 i'm happy to use snapshots or whatever

11:02 jgdavey: How would I compare two sequences, given a fn f for comparing, that would return something like [[in-a in-b] [nil only-in-b] [only-in-a nil]] ?

11:02 justin_smith: jgdavey: clojure.data/diff

11:03 ,(require 'clojure.data)

11:03 clojurebot: nil

11:03 jgdavey: Does data.diff allow custom fn for compare?

11:03 justin_smith: ,(clojure.data/diff {:a 0 :b 1 :c [1 2 3]} {:a 1 :b 1 :c [1 2 3 4]})

11:03 clojurebot: ({:a 0} {:c [nil nil nil 4], :a 1} {:c [1 2 3], :b 1})

11:03 justin_smith: hmm

11:09 jgdavey: Similiar in concept to a full outer join

11:13 andyf_: jgdavey: Easiest way might be modifying source code of clojure.data/diff

13:25 expez: when I don't want to use (concat a b c) because that would blow the stack with LazySeq nonsense, what should I do instead? I re-wrote it using ->> and into but that looks a lot clunkier.

13:42 devn: expez: could you give a more concrete example of what you're trying to achieve?

13:42 expez: devn: https://github.com/clojure-emacs/refactor-nrepl/commit/cdc4c8dbcc7b61c3809321f738597266657b9b73

13:43 I didn't expect this at all because the numbers involved are so small, but I just had my stack blown :p

13:44 justin_smith: expez: an alternative would be a reduce with conj, but that's effectively what into is anyway

13:45 expez: perhaps a reduce of into though

13:45 ,(reduce into [] '((1 2 3) (a b c)))

13:45 clojurebot: [1 2 3 a b ...]

13:45 justin_smith: expez: that should clean up your thing a big?

13:45 *bit

13:46 expez: yeah, that is prettier :)

13:46 justin_smith: (reduce into (when-let ...) [(slamhound/cantidates ...) (slamhound/cantidates ...))

13:47 devn: expez: http://stuartsierra.com/2015/04/26/clojure-donts-concat

13:47 expez: devn: that blogpost is actually why I instantly knew what the problem was when I saw the stacktrace :)

13:51 devn: :D

13:53 llz: I'm an experienced Haskeller. I'll be reading Clojure at a new job. I've read some basic info on Clojure. Any pointers for further reading?

13:54 justin_smith: llz: if you already have some fp background, joy of clojure is good

13:54 llz: also, stuartsierra's blog is a good source for good clojure style and coding guidelines

13:55 TEttinger: llz: comp is going to be familiar. right to left function composition like the dot in haskell

13:56 it isn't used super often, but can be very concise. there are other fns in clojure that draw from haskell like that

13:56 (doc juxt)

13:56 clojurebot: "([f] [f g] [f g h] [f g h & fs]); Takes a set of functions and returns a fn that is the juxtaposition of those fns. The returned fn takes a variable number of args, and returns a vector containing the result of applying each fn to the args (left-to-right). ((juxt a b c) x) => [(a x) (b x) (c x)]"

13:56 TEttinger: juxt is joy

13:56 llz: (doc comp)

13:56 clojurebot: "([] [f] [f g] [f g & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc."

13:57 TEttinger: other fun functions: reductions is scan or scanl or something. reduce is foldl.

13:58 ,(reduce *' (range 2 10))

13:58 clojurebot: 362880

13:58 llz: How does ->> relate to comp? Basically just flipped?

13:58 TEttinger: comp returns a new fn

13:58 ->> returns the result

13:58 llz: Ah

13:58 TEttinger: ,(reductions *' (range 2 10))

13:58 clojurebot: (2 6 24 120 720 ...)

13:59 TEttinger: ,(->> [1 2 3] (map inc) (reduce +))

13:59 clojurebot: 9

13:59 TEttinger: which is the same as

14:00 ,(reduce + (map inc [1 2 3]))

14:00 clojurebot: 9

14:00 TEttinger: but the "threading macros" -> and ->> are very handy when you want to clarify that something is being passed consecutively

14:01 there's also doto when dealing with mutable (typically from java) objects

14:01 ,(doto (new java.util.Random) .nextInt)

14:01 clojurebot: #object[java.util.Random 0x1879219e "java.util.Random@1879219e"]

14:02 llz: Is partial application a common idiom?

14:02 TEttinger: doto returns the actual object that is being mutated, what's a better example for that...

14:02 not often. there is ##(doc partial)

14:02 lazybot: ⇒ "([f] [f arg1] [f arg1 arg2] [f arg1 arg2 arg3] [f arg1 arg2 arg3 & more]); Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable number of additional args. When called, the returned function calls f with args + additional args."

14:03 TEttinger: partial can be more clear, especially with variadic fns, but if you want a certain number of args the anonymous fn syntax is probably more common

14:04 ,(reduce #(/ %2 %1) [1 2 3 4 5])

14:04 clojurebot: 15/8

14:04 Cr8: ,(doto (java.util.ArrayList.) (.add 1) (.add 2))

14:04 clojurebot: [1 2]

14:04 TEttinger: ah, good example Cr8

14:04 (inc Cr8)

14:04 lazybot: ⇒ 4

14:05 TEttinger: (closing dot is the same as calling new on the preceding class, closing dot is preferred)

14:05 Cr8: doto is mostly handy in interop situations -- i think it is or at least used to be listed under interop in the docs

14:05 TEttinger: sounds about right

14:06 it is similar to the threading macros though

14:06 llz: (The preceding comma you all've been including is just for clojurebot, right?)

14:06 Cr8: yeah fun thing you can do with it is toss a (doto println) in the middle of a -> -- doesn't affect the subject but prints it out in the middle of your -> chain

14:06 yes

14:07 commas are whitespace in clojure

14:07 justin_smith: ,,,,,,,,,,,,,,,,,,42,,,,,,,,,,,,,

14:07 clojurebot: 42

14:09 Cr8: ,(-> 1 inc (doto prn) inc)

14:09 clojurebot: 2\n3

14:10 llz: Thanks all

14:48 dnolen: Bronsa: ping

14:58 Bronsa: dnolen: pong

14:59 TEttinger: stomach: pang

15:09 noncom: some long time ago someone, maybe even technomancy has dropped here a link to a fun video about maven, a parody on some known poetry "this just raven" where it was about "this just maven".. does anyone remember where to find it?

15:11 Xorlev: http://timberglund.com/blog/2012/08/03/the-maven/ ?

15:15 noncom: Xorlev: truly it is! :)

15:15 thank you very much

15:24 how do i file-seq but only 1 level?

15:24 i do not want recursive...

15:24 dnolen: Bronsa: so I think I understand what needs to happen w/o messing around with full namespace reification.

15:25 Empperi: noncom: (-> (File. "/foo/bar") (.listFiles))

15:25 noncom: ah!

15:25 dnolen: Bronsa: basically we need to read the ns form to compute the alias map as well as information for ns-map

15:25 Empperi: just use the java api

15:25 noncom: thanks!

15:25 Empperi: returns a java array of File objects

15:25 if you want that to a seq, then just convert into one

15:25 and np

15:26 dnolen: then we can bind *ns* to an synthetic ns thing that more or less simulates namespaces in Clojure. I think this is enough for tools.reader

15:26 justin_smith: noncom: ##(into [] (.list (java.io.File. ".")))

15:26 lazybot: java.security.AccessControlException: access denied ("java.io.FilePermission" "." "read")

15:26 justin_smith: noncom: anyway, that will work on your machine

15:27 noncom: yeah!

15:27 justin_smith: oh, on scrollup I see listFiles above - but .list lists directories too

15:28 timvisher: should criterium output it's bench results when executed from an uberjar?

15:29 or do you need to do something special to get that to work?

15:29 as far as i can tell it uses println so it should just print?

15:30 Bronsa: dnolen: are you saying that tools.reader should parse the ns form?

15:31 dnolen: Bronsa: nah, I think we can sort it out over in ClojureScript so the ns and resolution stuff just ports over

15:32 in tools.reader

15:33 timvisher: here's an example. https://gist.github.com/timvisher/8e9da8d92fee8cdba482

15:34 notice how i get the evaluation count and such but none of the other stats

15:40 i just added example repl output for the same call to https://gist.github.com/timvisher/8e9da8d92fee8cdba482

15:46 bizarre. if i wrap the call to bench in `with-out-str` and then println on it works...

15:48 tiger`: my emacs/cider M-. doesn't jump to symbol anymore. Does it work for you in latest cider ?

15:48 timvisher: tiger`: define latest cider

15:48 tiger`: cider from melpa

15:48 timvisher: tiger`: melpa what? what's the cider version report?

15:49 tiger`: 0.9.0-snapshot

15:50 "CIDER 0.9.0snapshot (package: 20150612.315)"

15:50 timvisher: tiger`: you have that in your dependencies as well? in `.lein/profiles.clj` or elsewhere?

15:50 mmm. fwiw it works for me in melp stable on 0.8

15:50 but that sounds like you have the basics right

15:50 tiger`: yes, [cider/cider-nrepl "0.9.0-SNAPSHOT"]

15:52 it goes to emacs prompt Symbol:

15:52 and prints "no source location" :-(

15:59 jonathanj: do the bindings in (with-open) have to be closeable or can i use it as a general purpose let?

16:00 amalloy: jonathanj: try it and see

16:01 eg, (with-open [x 5] (inc x))

16:02 jonathanj: cute :)

16:21 irctc: hey I'm having difficult understanding symbols vs keywords

16:21 I know a keyword would be used in a map, because it strictly evaluates to itself

16:21 and a keyword can be a symbol

16:21 im just trying to get a more concrete idea in my head

16:22 justin_smith: irctc: keywords cannot be symbols

16:23 irctc: but what about ':foo?

16:23 justin_smith: ,(type ':foo)

16:23 clojurebot: clojure.lang.Keyword

16:23 justin_smith: that's not a symbol

16:23 ' is not the "create a symbol" operator

16:23 irctc: (symbol)

16:24 justin_smith: ,(type (symbol :foo))

16:24 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.lang.String"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.lang.String"\n :at [clojure.core$symbol invoke "core.clj" 550]}]\n :trace\n [[clojure.core$symbol invoke "core.clj" 550]\n [sandbox$eval49 invoke "NO_SOURCE_FILE" 0]\n [clojure.lang.Compiler eval "Compiler.java" 6792...

16:25 arohner_: irctc: keywords evaluate to themselves, symbols evaluate to something else

16:25 justin_smith: ,(def foo 'bar)

16:25 clojurebot: #'sandbox/foo

16:25 justin_smith: ,(def bar 'foo)

16:25 clojurebot: #'sandbox/bar

16:25 justin_smith: ,(iterate eval 'foo)

16:25 clojurebot: (foo bar foo bar foo ...)

16:26 justin_smith: with more room to print you could even make a nice circular chain

16:28 irctc: thanks arohner

16:28 and justin

16:28 justin_smith: https://www.refheap.com/102484 <- a nice cycle

16:28 kaiyin_: this might be a bit off-topic, but how does the following bit magic work? 0x00 << 24 | b & 0xff

16:29 justin_smith: ,(bit-shift-left 0 24)

16:29 clojurebot: 0

16:29 kaiyin_: it's supposed to convert a byte into an "unsigned int"

16:29 amalloy: 0 << 24? that is bizarre

16:29 justin_smith: inorite

16:30 amalloy: i guess the compiler will optimize it out, and then it serves as a hint to the human reader or something? or maybe it is just a special case of a more general "mask off some 8 bits" algorithm that looks dumb in this case

16:30 kaiyin_: it is the same as just: b & 0xff

16:31 kaiyin: ok, i see.

16:45 jonathanj: using (for) is it possible to determine whether i'm iterating the last element?

16:45 amalloy: jonathanj: no, but you probably don't have to

16:45 justin_smith: jonathanj: nope

16:45 jonathanj: i want to treat the last element differently to any other, any suggestions?

16:46 amalloy: jonathanj: my argument is that you probably done need to do that. why do you think you do?

16:46 *don't

16:47 jonathanj: i'm rendering a tree, every other element should turn out like "|-- key: value" while the last element should turn out like "`-- key: value"

16:50 amalloy: ,(let [nodes (range 6), decorators (-> (map (fn [a b] a) (repeat "|--") (rest nodes)) (concat ["`--]))] (map str nodes decorators)) maybe?

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

16:50 TimMc: THat's a pretty good reason.

16:50 amalloy: ,(let [nodes (range 6), decorators (-> (map (fn [a b] a) (repeat "|--") (rest nodes)) (concat ["`--"]))] (map str nodes decorators))

16:50 clojurebot: ("0|--" "1|--" "2|--" "3|--" "4|--" ...)

16:50 amalloy: &(let [nodes (range 6), decorators (-> (map (fn [a b] a) (repeat "|--") (rest nodes)) (concat ["`--"]))] (map str decorators nodes))

16:50 lazybot: ⇒ ("|--0" "|--1" "|--2" "|--3" "|--4" "`--5")

16:50 amalloy: it's a bit ham-handed, probably there is a nicer solution

16:51 TimMc: Oooh, I always forget about using rest to count to one from the end.

16:52 jonathanj: ugh, i sometimes find myself with a nested vector and i don't know why

16:52 justin_smith: jonathanj: that sounds like join

16:53 amalloy: that was my reaction too, justin_smith, but i think jonathanj's use case is distinct enough that join doesn't really help

16:53 justin_smith: ahh, OK

16:55 jonathanj: how do i write the equivalent of Python's zip() in Clojure?

16:55 zip([1, 2], [3, 4]) -> [[1, 3], [2, 4]]

16:55 justin_smith: ,(map list [:a :b :c] [1 2 3])

16:55 clojurebot: ((:a 1) (:b 2) (:c 3))

16:56 justin_smith: ,(mapv vector [:a :b :c] [1 2 3])

16:56 clojurebot: [[:a 1] [:b 2] [:c 3]]

16:56 Bronsa: ,(zipmap [:a :b :c] [1 2 3])

16:56 clojurebot: {:a 1, :b 2, :c 3}

16:56 justin_smith: ,(mapv vector [:a :b :c] [1 2 3] ["a" "b" "c"])

16:56 clojurebot: [[:a 1 "a"] [:b 2 "b"] [:c 3 "c"]]

17:08 jonathanj: does (map f xs ys) end when the longest or shortest seq ends?

17:09 shortest, it looks like

17:09 justin_smith: yes, shortest

17:10 jonathanj: can i iterate backwards with (for)?

17:11 justin_smith: (for [x (reverse y)] ...)

17:11 that's the closest you can get I think

17:11 jonathanj: ,(reverse (map list (reverse [:a :b]) (cons "`" (repeat "|"))))

17:11 clojurebot: ((:a "|") (:b "`"))

17:12 jonathanj: not sure if reverse is terrible in terms of efficiency (like it is in Python)

17:12 justin_smith: jonathanj: also, regarding the "detect the last item" thing, butlast might help (and just manually stick the last tihng on the end)

17:13 jonathanj: how do i actually stick the last thing on?

17:13 justin_smith: jonathanj: a cheap version of reverse if you are also building a collection is (into () ...) or to conj onto () at each step

17:13 ,(into () (range 10))

17:13 clojurebot: (9 8 7 6 5 ...)

17:14 justin_smith: there's not point if all you are doing is reversing, but if you are doing other stuff too it can make sense

17:14 jonathanj: hrm

17:14 i'm sorting

17:14 justin_smith: ,(reduce (fn [c x] (conj c (inc x))) () (range 10))

17:14 clojurebot: (10 9 8 7 6 ...)

17:14 jonathanj: maybe i can sort in reverse?

17:14 justin_smith: yeah, you can use a reversed comparitor

17:15 jonathanj: (sort-by < coll)?

17:15 justin_smith: ,(sort-by < (range 1000))

17:15 clojurebot: (0 1 2 3 4 ...)

17:15 justin_smith: ,(sort-by > (range 1000))

17:15 clojurebot: (0 1 2 3 4 ...)

17:15 justin_smith: ,(sort > (range 1000))

17:15 clojurebot: (999 998 997 996 995 ...)

17:16 jonathanj: my coll is a map

17:16 ,(sort < {:a 1 :b 2})

17:16 clojurebot: #error {\n :cause "clojure.lang.MapEntry cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.MapEntry cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers lt "Numbers.java" 221]}]\n :trace\n [[clojure.lang.Numbers lt "Numbers.java" 221]\n [clojure.core$_LT_ invoke "core.clj" 870]\n [clojure.lang.AFunction compare "AFunction.ja...

17:16 justin_smith: ,(sort-by key > {1 0 2 -1 3 -2})

17:16 clojurebot: ([3 -2] [2 -1] [1 0])

17:17 jonathanj: ,(sort-by < {:a 1 :b 2})

17:17 clojurebot: ([:a 1] [:b 2])

17:17 justin_smith: bonus points, getting to show what sort-by is actually for

17:17 jonathanj: hrm, that sorts in the opposite direction on my machine

17:18 => (sort-by < {:a 1 :b 2})

17:18 ([:b 2] [:a 1])

17:18 justin_smith: jonathanj: look at my sort-by again

17:20 jonathanj: okay, but that doesn't actually work for a map of my shape

17:20 dagda1: How could I display this as a number and keep the trailing 0's "0.500000"

17:20 jonathanj: ,(sort-by key > {:a 1 :b 2})

17:20 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers gt "Numbers.java" 229]}]\n :trace\n [[clojure.lang.Numbers gt "Numbers.java" 229]\n [clojure.core$_GT_ invoke "core.clj" 1040]\n [clojure.lang.AFunction compare "AFunction.jav...

17:20 jonathanj: i just want to order the keys alphabetically

17:20 justin_smith: ,(sort-by identity (comp (partial * -1) compare) {:a 0 :b 1 :c 2})

17:20 clojurebot: ([:c 2] [:b 1] [:a 0])

17:20 justin_smith: dagda1: format

17:21 ,(sort-by key (comp (partial * -1) compare) {:a 0 :b 1 :c 2}) ; if you really only care about the key

17:21 clojurebot: ([:c 2] [:b 1] [:a 0])

17:21 justin_smith: jonathanj: ^

17:21 jonathanj: what the heck is the *-1 for

17:21 invert the compare result?

17:22 justin_smith: jonathanj: exactly, a comparator returns a number

17:22 to reverse sorting, you can flip the sign of hte number

17:22 dagda1: justin_smith will that not format as a string

17:22 amalloy: justin_smith: (= (partial * -1) -)

17:22 jonathanj: that seems crazy unexpressive

17:22 justin_smith: amalloy: ! I always forget

17:22 jonathanj: even so

17:22 justin_smith: ,(sort-by key (comp - compare) {:a 0 :b 1 :c 2}) ; thanks amalloy

17:23 clojurebot: ([:c 2] [:b 1] [:a 0])

17:23 jonathanj: ,(sort-by key (comp - compare) {:a 1 :b 0 :c 2})

17:23 clojurebot: ([:c 2] [:b 0] [:a 1])

17:23 justin_smith: (inc amalloy)

17:23 lazybot: ⇒ 279

17:23 jonathanj: (inc amalloy)

17:23 lazybot: ⇒ 280

17:23 jonathanj: (inc justin_smith)

17:23 lazybot: ⇒ 263

17:23 amalloy: jonathanj: make sure you're not just using "unexpressive" to mean "different from how python does it"

17:24 jonathanj: amalloy: no i mean that "negate a number to change the sorting direction" is kind of a weird way of saying "sort this thing the other direction"

17:24 in python, for example, sorted(..., reverse=True) does what you'd expect

17:25 amalloy: it's more flexible, though. imagine if every function like sort had 4 different flags for all the ways you'd want to sort things

17:25 just allowing a single function argument allows all that power, and more, without adding a bunch of special cases

17:25 justin_smith: right, I could make my own silly comparator

17:25 amalloy: like i bet python's sort allows you to pass a function too, which means that all those flags are just for convenience

17:25 jonathanj: well if < or > were comparators that would be useful

17:26 justin_smith: ,(sort-by key (comp count str) {:longest 0 :longer 1 :long 2})

17:26 clojurebot: ([:longest 0] [:longer 1] [:long 2])

17:26 amalloy: ,(comparator >)

17:26 clojurebot: #object[clojure.core$comparator$fn__4659 0x2a851004 "clojure.core$comparator$fn__4659@2a851004"]

17:26 amalloy: ~def comparator

17:27 now > is a comparator

17:27 justin_smith: oh yeah, that str comparator is totally wrong

17:27 jonathanj: okay, but:

17:28 TimMc: jonathanj: (def reverse-comparator (partial comp -)) :-P

17:28 jonathanj: ,(sort-by key (comparator <) {:a 1 :b 0 :c 2})

17:28 clojurebot: #error {\n :cause "clojure.lang.Keyword cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.Keyword cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers lt "Numbers.java" 221]}]\n :trace\n [[clojure.lang.Numbers lt "Numbers.java" 221]\n [clojure.core$_LT_ invoke "core.clj" 870]\n [clojure.core$comparator$fn__4659 invoke "core....

17:28 TimMc: Now it's expressive.

17:28 amalloy: well yes. < and > work only on numbers. which is kinda lame, but that's the price you pay for host-level performance

17:28 justin_smith: jonathanj: well, < doesn't work on keywords, compare does

17:30 TimMc: or (def revcomp (comp - compare)) to specialize for reverse sorting

17:30 ,(sort-by identity (comparator rand) (range 10))

17:30 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: core/rand"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/rand"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 36]\n [clojure.core$comparator$fn__4659 invoke "core.clj" 2967]\n [clojure....

17:30 justin_smith: heh

17:32 ,(sort (fn [_ _] (- (rand-int 2) 1)) (range 10))

17:32 clojurebot: (2 3 5 7 6 ...)

17:33 andyf_: justin_smith: Trying to write shuffle the hard way?

17:34 amalloy: i can never quite keep straight exactly why that is a bad shuffle implementation

17:34 it's biased in some weird way

17:34 justin_smith: andyf_: just goofing around

17:35 https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle for anyone else curious

17:36 andyf_: I love that dance.

17:36 justin_smith: haha

17:37 jonathanj: #clojure is always so educational, i have a hundred new ways to think about things now

17:37 <3

17:39 justin_smith: oh wow - fisher-yates shuffle can be done lazily

17:40 I mean, the clojure shuffle just calls the java method, but we could totally have a lazy shuffle if we wanted it

17:40 the input would still have to be fully realized, but the output could be lazy

17:41 andyf_: justin_smith: Meaning it maintains state of all of the remaining elements that haven't been output yet, and each 'pull' randomly selects one of them uniformly and updates the internal state? Makes sense.

17:41 justin_smith: amalloy: that page mentions why my silly random sort is a bad shuffle - it's dependent on the sorting algo how bad it is

17:41 andyf_: exactly

17:42 andyf_: so the selection of new results can be lazy

17:42 jonathanj: if i wanted a way to whilelist keys from a map (for display purposes) a set seems reasonable, but assuming i have an arity that takes the whitelist and an arity that does not take a whilelist (assuming no whitelist means "everything") how do i actually element this in a concise way?

17:42 i guess what i want is some magical "everything" set

17:42 amalloy: justin_smith: there's a lazy shuffle in useful

17:42 justin_smith: amalloy: oh, cool

17:43 andyf_: jonathanj: Set theorists go mad contemplating everything sets, I think.

17:43 amalloy: there are some people who say it's not actually fisher-yates, because an important property of fisher-yates is that it's done in-place

17:43 justin_smith: jonathanj: well, a handy thing is that sets act as functions, returning the result of a lookup

17:43 jonathanj: actually, i guess if testing the whitelist is implemented as a function (#{...} k) then for the everything case i can pass (fn [_] true)

17:43 justin_smith: ,(#{:a :b :c} :a)

17:43 amalloy: but i don't really agree, just like quicksort/mergesort can be done functionally but not in place

17:43 jonathanj: or well identity

17:43 andyf_: Practically, you can have code like (or show-all (in-show-set k)) before deciding whether to show a key.

17:43 clojurebot: :a

17:43 zimablue: {set of all things not contained in this set}

17:43 justin_smith: jonathanj: which means that you could take a predicate, which could be a set, or (constantly true)

17:44 since all things not nil or false count as true for clojure tests

17:44 TimMc: jonathanj: Do you know that you'll never have nil or false as a value?

17:44 jonathanj: TimMc: no

17:44 well actually, nil or false will never be keys

17:44 so i guess that's a yes

17:45 justin_smith: jonathanj: so yeah, (fn [_] true) or (constantly true) or however you want to express it can take the place of the universal set

17:45 for this specific case that is

17:47 jonathanj: i can never remember what (constantly) is called

17:47 amalloy: (complement #{})

17:47 justin_smith: (repeatedly (forget constantly))

17:47 amalloy: a sillier way of doing it

17:48 TimMc: &(map (complement #{}) [nil false true :cats])

17:48 lazybot: ⇒ (true true true true)

17:49 TimMc: Oh wait, that wasn't what I meant to write.

17:50 Never mind. I was thinking for a sec that sets could take an optional not-found arg, but they don't.

17:50 amalloy: really?

17:50 ,(#{} 1 2)

17:50 clojurebot: #error {\n :cause "Wrong number of args (2) passed to: PersistentHashSet"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: PersistentHashSet"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 36]\n [sandbox$eval49 invoke "NO_SOURCE_FILE" 0]\n [clojure...

17:50 amalloy: well that's lame

17:50 justin_smith: that's oddly inconsistent!

17:51 amalloy: justin_smith: clojure is inconsistently odd, so it fits

17:52 stain: ,(:blah {} :notfound)

17:52 clojurebot: :notfound

17:53 andyf_: Vote early, vote often: http://dev.clojure.org/jira/browse/CLJ-1305

17:53 justin_smith: (inc amalloy)

17:53 lazybot: ⇒ 281

18:16 zimablue`: test

18:16 TEttinger: hello

18:21 stain: hi!

18:25 musicm122: Ello all

18:26 Is this the best place to ask noobish questions?

18:26 nm going to clojure-beginner

18:28 andyf_: musicm122: You may ask noobish questions here, too, if you wish.

18:35 musicm122: Cool

18:35 thanks @andy_f

18:36 well I've been trying to write a function with multi arity

18:36 that returns a file's extension

18:36 https://gist.github.com/musicm122/6d2eb4fd5dd5d538cfaf

18:38 but as it says in the comments I've been getting invalid # of args

18:40 the single arg version works fine (defn getFileExt [arg] (str (subs arg (.lastIndexOf arg "." ))))

18:42 but when I try to use the multi parity version

18:42 (defn getFileExt [arg] (str (subs arg (.lastIndexOf arg "." ))) [& *args*] (apply getFileExt *args* ))

18:42 amalloy: musicm122: that is not how multiarity works

18:42 remember that (defn foo [x] y z q) evaluates y, then z, then q

18:42 here [& args] is z, and evaluating that makes no sense

18:42 musicm122: k

18:42 amalloy: you need extra parens to group the various arities

18:43 (defn foo ([x] a) ([y z] b))

18:45 musicm122: k testing

18:51 I should still be able to recur my version with & to the one that takes a single arg right?

18:51 such that

18:51 (defn getFileExt ([arg] (str (subs arg (.lastIndexOf arg "." )))) ([& *args*] (apply getFileExt *args* )) )

18:53 amalloy: no

18:53 oh you can do that, sure. you just can't use recur

18:53 but also that is a broken implementation of your &args arity anyway. it will never do anything good

18:54 musicm122: AH

18:54 (defn getFileExt ([arg] (str (subs arg (.lastIndexOf arg "." )))) ([arg & *args*] (apply getFileExt arg *args* )) )

18:54 I have to actually supply a 1st before I can supply the rest

18:54 amalloy: that is still never going to do anything good

18:54 the multi-arity case will jsut call itself endlessly

18:55 musicm122: gah

18:55 amalloy: you have to simplify the problem somehow before recurring, otherwise the recursion never terminates

18:55 it's like (defn + [x y] (+ x y))

18:55 true, but not very useful

19:00 pkillean: I am trying the eduction example from http://clojure.org/transducers in a repl, getting TypeError: coll.cljs$core$IReduce$_reduce$arity$2 is not a function. Is this a bug?

19:00 ^(cljs)

19:04 ^nvm got it

20:52 zhadn: I'm defining a list coolList (def coolList '(1 2 3 4 5)), but when I try and peek/pop with (peek coolList) I get "Unbound can not be cast to persistentstack". But when I (peek '(1 2 3 4 5)) that works fine?

20:52 I can't figure out why

20:55 amalloy: zhadn: you evidently are not defining that list

20:55 eg, if you try to evaluate just coolList itself, you will be told it is unbound

20:55 zhadn: im working in TryClojure

20:56 and evaluating coolList will return the value

20:56 but when I try and operate on it, it throws that exception

20:56 so Im just setting it in a REPL

20:56 amalloy: try using a real repl. tryclojure probably has some weird eviction policy for vars

20:57 zhadn: yep you're right

20:57 works fine with lein

20:57 thanks!

21:57 jeramy_s: good evening all

21:58 I am completely new to Clojure, actually I haven't even started yet. Was wondering what the best resources are for learning Clojure

22:02 andyf: jeramy_s: The clojure.org getting started page has several links to on-line resources created by others: http://clojure.org/getting_started in the Community section

22:02 I haven't used them myself, but some people seem to like "Clojure for the Brave and True" and "Clojure from the ground up"

22:03 Only reason I haven't read them is that they were written after I was already quite familiar with Clojure.

22:03 jeramy_s: Has anyone read the prag prog book, Programming Clojure?

22:03 I meant to ask if you've heard good things about the book

22:06 whomp: is there a value-map function which, given a hash map, returns one with the values mapped?

22:07 andyf: I read 1st ed. long ago. I guess there is a 2nd now? I haven't read through all of the "Clojure Programming" book published by O'Reilly, but from the parts that I have, and my recollections of the "Programming Clojure" book, my preference is for the O'Reilly one.

22:07 justin_smith: whomp: it's very easy to write, but it doesn't exist in the core language

22:07 whomp: justin_smith, ty :)

22:08 justin_smith: #(into {} (for [[k v] %2] [k (f %1)]))

22:08 err, not quite

22:08 #(into {} (for [[k v] %2] [k (%1 v)]))

22:09 there we go

22:10 creese: I'm having a strange issue combining component with immutant. Can someone take a look?

22:11 whomp: nice

22:11 creese: https://gist.github.com/creese/3a6d38ffd1f2d554b21c

22:11 The job function takes zero arguments but I'm still getting an exception.

22:12 justin_smith: creese: you need to return a component

22:12 creese: start and stop must both return the component

22:12 everything breaks if you don't

22:12 creese: can it be an empty map?

22:13 justin_smith: creese: no it is the component that was passed in (your "this")

22:14 I mean maybe an empty map would work sometimes, but the general thing is to return the component itself

22:15 creese: that may be correct, but I don't think it's my problem here

22:15 justin_smith: creese: not returning a map of some sort will break component

22:15 creese: returning a map doesn't solve the ArityException for Heartbeat/fn

22:16 justin_smith: creese: also, the best practice is to attach something like :heartbeat :running to the component before returning it; that way you can check whether it is running already by checking that key before starting

22:16 creese: ok

22:17 justin_smith: so does schedule definitely call your job with 0 arguments?

22:17 creese: how can it not?

22:17 justin_smith: creese: ?

22:17 creese: that's what the docs say

22:17 justin_smith: it could provide whatever arguments it likes, hypoethetically

22:18 creese: "Your "job" will take the form of a plain ol' Clojure function taking no arguments. The schedule function takes your job and a specification map as arguments."

22:18 http://immutant.org/tutorials/scheduling/

22:19 justin_smith: OK

22:19 creese: This was working before I added component

22:19 justin_smith: what are the consequences of out-queue-group always being nil?

22:20 because it is guaranteed here

22:21 creese: it's nill for the function?

22:21 not for the pprint

22:21 justin_smith: creese: you don't pass in an out-queue-group

22:21 creese: I can't get it through scoping

22:21 justin_smith: creese: you pass in options, but out-queue-group will be nil because it is not provided

22:21 so you will publish to nil

22:21 which seems like it would fail

22:22 creese: doesn't matter because it doesn't get that far

22:22 I was using partial before

22:22 that doesn't work either

22:23 justin_smith: so you are saying that (fn [] (publish! nil .....)) crashes, but it's definitely not because you are publishing to nil?

22:23 unless you are not actually using heartbeat-ctor

22:25 oh never mind, clearly you are not using heartbeat-ctor, because in the stack trace outqueue-group is not nil

22:25 though line 15 ensures that out-queue will always be nil

22:26 ,(first (filter #(= first :hearbeat) [[:hearbeat] [:hearbeat] [:hearbeat]])

22:26 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:26 justin_smith: ,(first (filter #(= first :hearbeat) [[:hearbeat] [:hearbeat] [:hearbeat]]))

22:26 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: sandbox/eval47/fn--48"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: sandbox/eval47/fn--48"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.core$filter$fn__4578 invoke "core.clj...

22:27 justin_smith: so your code as written, I would expect to see that error, unless out-queue was never forced

22:27 creese: updated

22:27 https://gist.github.com/creese/3a6d38ffd1f2d554b21c

22:27 This is closer to the original implementation.

22:27 justin_smith: line 24 still guarantees that out-queue is nil

22:28 or not nil, sorry, just an invalid arity exception

22:30 creese: " Wrong number of args (1) passed to: Heartbeat/fn--9446"

22:30 that's the identical error I showed above

22:30 caused by the exact line I am talking about

22:30 #(= first :heartbeat) is a function of 0 arguments that always returns false

22:31 you want #(= (first %) :hearbeat) - which takes one arg and actually checks something about that arg

22:31 sorry, :heartbeat

22:32 creese: that fn is botched, no '%'

22:32 justin_smith: also, after you fix that, fix your stop implementation too - returning nil from stop prevents other components from being stopped properly

22:32 creese: right, and thus your arity error

22:32 which is what caused your exception

22:33 it was just an arity error in a different function than the one you thought

22:33 creese: yeah

22:33 java.lang.ClassCastException: clojure.lang.PersistentHashMap cannot be cast to java.util.concurrent.Future <— what does this mean?

22:34 I know what the first part is

22:34 justin_smith: ,@{}

22:34 clojurebot: #error {\n :cause "clojure.lang.PersistentArrayMap cannot be cast to java.util.concurrent.Future"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentArrayMap cannot be cast to java.util.concurrent.Future"\n :at [clojure.core$deref_future invoke "core.clj" 2182]}]\n :trace\n [[clojure.core$deref_future invoke "core.clj" 2182]\n [clojure.core$deref invoke "core.clj...

22:34 justin_smith: that's what causes that

22:34 you tried to deref a map

22:34 creese: ok

22:34 options was an atom before, now it's now

22:35 not

22:35 justin_smith: but someone seems to have tried to deref it

22:38 creese: publish! does because options use to be an atom

22:38 justin_smith: not needs to be?

22:38 creese: I'm using component so it's just a map now

22:39 this is working now, thanks

22:39 justin_smith: awesome, glad I could help

22:39 creese: component is pretty cool

22:39 justin_smith: I like it a lot

22:40 one of these days I am going to polish and share my .cljc version (it's useful on the frontend too)

Logging service provided by n01se.net