#clojure log - Mar 10 2016

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

6:43 amoe_: it seems strange to me that (def blah nil) (blah) => NullPointerException. I mean, it totally makes sense, but I wonder why there is not a more specific error message.

6:55 tdammers: amoe_: because clojure doesn't abstract away all the JVM peculiarities

6:55 for the same reason, you'll also see the underlying Java class names and such in stack traces instead of their clojure appearances

8:08 faxmodem: I've been successfully using lein try a lot and it's awesome

8:08 how can I use it for a local project?

8:08 e.g. 'lein try .'

8:15 ridcully_: faxmodem: isnt that just lein repl then?

8:17 faxmodem: ridcully_: I guessed the same

8:17 but then the deps arent' being fetched

8:17 so I guess I'm just looking at the lein command to do that :)

8:19 ridcully_: oh you mean you want to temporarily try it out with an existing project

8:19 i either add it then or use lein plz. i only ever used try without projects

8:37 faxmodem: yes

8:38 lein plz is that shipped with leiningen?

8:40 tdammers: lein *is* leiningen

8:40 ridcully_: plz is another plugin

8:40 tdammers: oh nm

9:08 faxmodem: tdammers: then 'lein deps && lein repl' should be enough to get started?

9:08 s/tdammers/ridcully_/

9:15 ridcully_: faxmodem: yep (even without the deps first)

9:15 your project.clj should contain the deps beforehand

9:22 faxmodem: ridcully_: I thought it did :)

9:22 ridcully_: so lein repl should run deps

9:40 so when I run lein deps, where do the deps get stored?

9:42 schmir: faxmodem: ~/.m2/

9:42 faxmodem: thanks!

9:59 sdegutis: I'm about to use reduce-kv for the first time ever!

10:10 fod: https://www.youtube.com/watch?v=-W6as8oVcuM

13:20 backnforth: Hello, can someone explain to me how to short snipper of code works: http://pastebin.com/y8tHJ47Z . Really I'm trying to understand how "i" and "y" obtain their values, how does the "?" work, and how does filter, identiy, and map-indexed work? And whether it was right for me to add a println to the main when calling the questioned function.

13:21 hiredman: ? isn't anything special

13:21 ,(let [x?y?z 1] x?y?z)

13:21 clojurebot: 1

13:22 hiredman: filter, identity, and map-indexed all have docs you can read on clojure.org

13:23 backnforth: ,(let [x?y?z? 1] x?y?z?)

13:23 clojurebot: 1

13:23 hiredman: when you added the println, you replaced the call to listread with the call to println

13:24 backnforth: How should the return of the function be printed?

13:42 I'm having a hard time understanding how "filters" how.

13:44 Oh, so it returns a lazy sequence for which the "pred" holds true,

13:51 Anyone know where I may find a Clojure tutor?

13:52 justin_smith: backnforth: have you checked for nearby clojure meetups?

13:52 backnforth: None unfortunely.. I would even be willing to pay for a tutor.

13:53 justin_smith: if remote tutoring is an option, maybe you can find someone here, or on the clojurians slack channel

13:54 backnforth: I would prefer remote tutoring

13:54 I'll also check the slack channel

13:55 rhg135: We don't talk about that place

13:55 justin_smith: I'd offer but I'm very busy with the day job at the moment (though I do make time to check in and answer questions here)

13:55 haha

13:56 backnforth: I have all day, justin_smith. If you'd like to help me later I could try to have a session prepared for then.

13:56 Or possibly another day.

14:04 justin_smith: backnforth: what I meant was I can probably answer one-off questions on this channel on a case by case baisis but can't promise to do one on one tutoring right now

14:04 but maybe someone else here is available

14:05 backnforth: in my experience if you share a link to some code and say "what's wrong with this code" you'll probably get a lot of good advice

14:06 backnforth: ok

14:30 Why do variables often have ":" added in front of them?

14:31 justin_smith: backnforth: :foo is not a variable, it is a keyword

14:31 backnforth: keywords are a special type that is self evaluating

14:31 backnforth: A keyword to the function? And the functions should know how this keyword matches?

14:31 justin_smith: backnforth: wat

14:32 backnforth: How might they be self evaluating?

14:32 justin_smith: ,:foo

14:32 clojurebot: :foo

14:32 justin_smith: that's what I mean - they always stand for themselves

14:32 amalloy: backnforth: :charles is a constant value, just like 5 is a constant value

14:32 justin_smith: right, that might be a clearer way to say it

14:33 amalloy: whereas there are other structures that don't evaluate to themselves. lists, for example: the list (+ 1 2) doesn't evaluate to the list (+ 1 2), it evaluates to 3

14:34 backnforth: ,(= :charles :charles)

14:34 clojurebot: true

14:34 backnforth: ,(= :charles charley)

14:34 clojurebot: #error {\n :cause "Unable to resolve symbol: charley in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: charley in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: charley i...

14:35 backnforth: ,(let :charles 3)

14:35 clojurebot: #error {\n :cause "let requires a vector for its binding in sandbox:"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "let requires a vector for its binding in sandbox:"\n :at [clojure.core$let invokeStatic "core.clj" 4333]}]\n :trace\n [[clojure.core$let invokeStatic "core.clj" 4333]\n [clojure.core$let doInvoke "core.clj" 4325]\n [clojure.lang.RestFn invoke "RestFn.java" 467...

14:35 justin_smith: and charley is not self-evaluating - clojure looks for a binding (and throws an error if it does not find one)

14:35 backnforth: for the top level you need def, and keywords are not valid bindings

14:35 backnforth: So i assume I can't assume values to :charles considering :charles is its value.

14:35 justin_smith: backnforth: what does that mean?

14:36 you can't bind a value to :charles because it always is just :charles if that's what you mean

14:36 backnforth: Yes, thank you.

14:36 justin_smith: unlike charley which can be bound

14:36 ,(def charley "just some guy")

14:36 clojurebot: #'sandbox/charley

14:36 backnforth: It's so simple.

14:37 justin_smith: I like to think so, heh

14:42 backnforth: ,(= poopy poopy)

14:42 clojurebot: #error {\n :cause "Unable to resolve symbol: poopy in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: poopy in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: poopy in this...

14:42 backnforth: ,(= :poopy :poopy)

14:42 clojurebot: true

14:55 TMA: ,(= 'karlos 'karlos) ; backnforth

14:55 clojurebot: true

14:57 justin_smith: ,(apply = (map (comp symbol name) ["foo" :foo 'foo]))

14:57 clojurebot: true

14:57 backnforth: ,(= 'karlos 'karlos)

14:57 clojurebot: true

14:59 TMA: backnforth: 'thing prevents the evaluation of the thing; in other words, the result of 'thing is thing for whatever the thing might be. see:

14:59 ,(+ 1 2)

14:59 clojurebot: 3

14:59 TMA: ,'(+ 1 2)

14:59 clojurebot: (+ 1 2)

15:01 backnforth: ,:(+ 1 2)

15:01 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :>

15:01 backnforth: ,(= 'a 'a)

15:01 clojurebot: true

15:01 backnforth: Then why used :thing?

15:08 TMA: ,(:foo {:foo 1})

15:08 clojurebot: 1

15:08 TMA: ,('foo {'foo 1})

15:08 clojurebot: 1

15:09 * TMA did not expect the second to work

15:10 TMA: backnforth: no idea, :foo is a keyword, 'foo is a symbol; there might be some reason I do not know why they are separate

15:10 backnforth: maybe there is something with namespaces that make :foo better in some contexts than 'foo

15:41 justin_smith: TMA: 'foo is usually used in those cases where you eventually want to look up foo (eg. it's a var to resolve / eval later), while :foo doesn't have that implication

15:42 TMA: of course we could just use 'foo instead of :foo, but that adds a little bit of ambiguity about what kind of lookup / meaning we expect with that symbol

15:42 TimMc: That's a good way of putting it.

15:42 justin_smith: I mean, really, we could use strings for all of these things anyway, the rest is nuance

15:42 TimMc: thanks

15:50 TimMc: I usually put it as "symbols usually refer to code, keywords are usually used in data structures" but of course code is data so... :-P

16:16 matt______: a little bit confused about an error i'm getting using deftype and implementing an interface. stripped-down example is here: http://pastebin.com/AVupasmR

16:16 amalloy: keywords are faster too

16:17 interface methods are interop calls. they're not functions

16:18 matt______: nailed it, amalloy. thanks.

16:25 sdegutis: Can (for [x xs, y ys] (get-in y [...])) be simplified/combined somehow?

16:27 amalloy: i don't think so

16:34 sdegutis: Thanks.

16:45 justin_smith: amalloy ♥'s for

17:16 randomcharhere: why does this not work (apply inc '(1 2 3 4)) but this does (apply + '(1 2 3 4)) ?

17:18 yellow13: inc is a function of only one argument

17:18 + receives 1..n argr

17:19 TEttinger: 0..n

17:19 ,(+)

17:19 randomcharhere: my assumption was that apply would iterate of the arg?

17:19 clojurebot: 0

17:23 yellow13: actually apply take the args from [1 2 3 ...] and then call (fn arg1 arg2 arg3 ...)

17:23 macrolicious: I'm loving testing db calls from within my code via nREPL but I'm still unclear what it is in functional languages that make this possible and why it's not in other types of languages... can someone explain?

17:26 randomcharhere: evidently map was design to iterate over args

17:28 Db calls can be made from within other languages nothing to do with funtioanl languages its just more imediate with repl *shrug*

18:26 rhg135: there's an assembly repl out there. not functional at all

18:26 it's mostly the power of repls and recognizing their utility

18:44 TimMc: macrolicious: Being able to define functions outside of classes makes it easier to define functions. :-)

18:45 You could imagine a Java REPL that allows you to add static methods to a ReplFunctions class.

18:45 and then fix up references to make it work

18:46 tjd: I'm calling a function with keyword args, (foo :a 1 :b 2), if I have a map {:a 1 :b 2}, how can I effectively execute (foo {:a 1 :b 2})?

18:48 TEttinger: apply, I'd say, but I am not sure I understand tjd

18:48 ohhh

18:48 nvm

18:49 tjd: The keyword-args map is passed in to me, and I'm just sending it along the way. Really don't want to break it apart, because what

18:49 Because the content is implementation detais that my function doesn't care about

18:49 TEttinger: ,(defn foo [{a :a b :b}] (+ a b))

18:49 clojurebot: #'sandbox/foo

18:49 TEttinger: ,(foo :a 1 :b 2)

18:49 clojurebot: #error {\n :cause "Wrong number of args (4) passed to: sandbox/foo"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (4) passed to: sandbox/foo"\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" 44]\n [sandbox$eval50 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval5...

18:50 TEttinger: can't remember how this is done

18:51 something like the first example here, https://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure ?

18:51 tjd: This works: (apply foo (flatten (into [] {:a 1 :b 2})))

18:51 Not proud of that, though.

18:51 TEttinger: ohhh, :keys

18:52 ,(defn foo [& {:keys [a b]}] (+ a b))

18:52 clojurebot: #'sandbox/foo

18:52 TEttinger: ,(foo :a 1 :b 2)

18:52 clojurebot: 3

18:53 matt______: TEttinger: i think you're solving a different problem than tjd. :)

18:53 TEttinger: ,(foo (apply into [] {:a 1 :b 2}))

18:53 clojurebot: #error {\n :cause "Key must be integer"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Key must be integer"\n :at [clojure.lang.APersistentVector invoke "APersistentVector.java" 292]}]\n :trace\n [[clojure.lang.APersistentVector invoke "APersistentVector.java" 292]\n [clojure.core$transduce invokeStatic "core.clj" 6598]\n [clojure.core$into invokeStatic "core.clj" 6614]\n [...

18:53 TEttinger: ,(apply foo (apply into [] {:a 1 :b 2}))

18:53 clojurebot: #error {\n :cause "Key must be integer"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Key must be integer"\n :at [clojure.lang.APersistentVector invoke "APersistentVector.java" 292]}]\n :trace\n [[clojure.lang.APersistentVector invoke "APersistentVector.java" 292]\n [clojure.core$transduce invokeStatic "core.clj" 6598]\n [clojure.core$into invokeStatic "core.clj" 6614]\n [...

18:53 TEttinger: yeah, I'm still figuring out kwargs, matt______

18:54 tjd: ,(defn x [& {:keys [a b]}] (println a b))

18:54 clojurebot: #'sandbox/x

18:54 matt______: well, he wants all the keys and all the values passed to a function in order, it seems.

18:54 tjd: ,(apply x (flatten (into [] {:a 1 :b 2})))

18:54 clojurebot: 1 2\n

18:55 tjd: Although I can't help but think I should insist that my caller pass in a function instead of arguments to a sub-function.

18:55 TEttinger: ,(apply foo (apply concat {:a 1 :b 2}))

18:55 clojurebot: 3

18:55 TEttinger: ,(apply x (apply concat {:a 1 :b 2}))

18:55 clojurebot: 1 2\n

18:55 tjd: oh my

18:55 TEttinger: it doesn't order them though

18:56 ,(apply x (apply concat {:a 1 :b [1 2 3]}))

18:56 clojurebot: 1 [1 2 3]\n

18:56 TEttinger: which flatten would break

18:56 tjd: boo

18:56 TEttinger: apply concat only does one level of "flattening"

18:57 hash-maps are never ordered

18:57 so if you pass a hash-map there's no guarantee of order

18:57 matt______: i meant as k1 v1 k2 v2, etc.

18:58 TEttinger: that's a kwarg thing

18:58 ,(defn foo [& {:keys [b a]}] (+ a b))

18:58 clojurebot: #'sandbox/foo

18:58 TEttinger: ,(apply foo (apply concat {:a 1 :b 2}))

18:58 clojurebot: 3

18:59 matt______: i don't think so. he said he doesn't care about the keys or values and is just acting as proxy.

18:59 amalloy: ~mapply

18:59 clojurebot: You have to do something like (defn mapply [f & args] (apply f (apply concat (butlast args) (last args)))), which just goes to show why unrolled keyword args are a bad idea

18:59 matt______: i mean, he also said he has a solution. in (apply foo (flatten (into [] {:a 1 :b 2})))

19:00 TEttinger: dothat isn't a solution, matt______

19:00 flatten kills any nesting

19:00 amalloy: ~flatten

19:00 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

19:00 matt______: well, maybe that matters.

19:00 tjd: does nesting matter for your use case?

19:01 tjd: nesting does not matter

19:01 TEttinger: flatten's fine but still terrible then

19:01 tjd: :-)

19:01 amalloy: people who think nesting doesn't matter are (a) usually wrong, and (b) working with data simple enough that mapcat or concat is easy

19:01 clojurebot: Ik begrijp

19:01 amalloy: nice

19:02 TEttinger: ~people who think nesting doesn't matter

19:02 clojurebot: Titim gan éirí ort.

19:02 TEttinger: ~people

19:02 clojurebot: you mean BugFactorySingletons

19:02 TEttinger: haha

19:02 amalloy: ~people who think nesting doesn't matter are (a) usually wrong, and (b) working with data simple enough that mapcat or concat

19:02 clojurebot: people who think nesting doesn't matter are (a) usually wrong, and (b) working with data simple enough that mapcat or concat is easy

19:02 TEttinger: mm

19:09 matt______: fair enough

19:09 tjd: unflattened: (apply foo (apply concat (into [] {:a 1 :b 2})))

19:10 TEttinger: don't need the into []

19:10 matt______: good call.

19:11 TEttinger: but yeah, this does seem a bit odd to have the unrolled kwargs mixed up with maps of those args

19:11 amalloy's mapply example is a good point

19:31 X-warrior: hey guys I'm new to clojure and I'm doing a project to learn it, I'm thinking if my code is on the right way of doing things on clojure and if it is readable. Could anyone take a look at it? https://bitbucket.org/matheusbrat/clojure

19:40 maya__: Hi, I have some bug with clojure interop with java, when I write the same (I think) code in the two languages, I got two diferent results. I don't have any idea why

19:40 (println (.contains (.getAllowedValues (PropertyInteger/create "propertyBottomPosition" 0 4)) 0)) // false System.out.println(PropertyInteger.create("propertyBottomPosition", 0, 4).getAllowedValues().contains(0)); // true

19:41 Do you have any idea about what can be wrong here ?

19:43 amalloy: unrelatedly to your problem, it will certainly be easier to read if you write it like (println (-> "propertyBottomPosition") (PropertyInteger/create 0 4) (.getAllowedValues) (.contains 0)))

19:45 maya__: amalloy: you'r right, juste didn't have the reflex yet

19:46 amalloy: those two snippets look equivalent to me, though. i'd say confirm that that's the exact code you're running, and if you still get different results then start seeing if there's something about the context you run them in in the respective languages

19:47 hiredman: well

19:48 the difference would be, in java that 0 is an int, in clojure it is a long

19:48 amalloy: oh dang

19:48 hiredman: so it depends on what the behavior of .contains is given that

19:48 amalloy: yeah that is almost certainly the answer. nice spot

19:50 maya__: getAllowedValue return a com.google.common.collect.RegularImmutableSet

19:51 hiredman: yeah, you want something like (Integer/valueOf 0) for contains

19:51 amalloy: hiredman: just (int 0) should do it, right? i think it doesn't re-box for interop calls

19:51 right, hiredman's point is that your clojure code translates to (...).contains(0L)

19:52 maya__: amalloy, hiredman : ok thx, I will try to fix that

19:52 amalloy: or well, obviously it does re-box, but it knows that it has an int so it boxes to an int rather than a long. unless you're on specifically clojure 1.3 or whatever version that was

19:53 hiredman: I dunno, it seems like the most explicit code is best here. it really needs to be an Integer

19:54 the fact that there can be some uncertainty and some wiggle room around 'int', well maybe it isn't the best choice

19:54 amalloy: fair

20:09 maya__: Ok, that was the probleme, thx. Is that a way to specify to the reader the type (to Integer) of my literal ? other than (int 0)

20:12 justin_smith: no

20:25 Guest58040: What is the best way to determine if something is a collection or a single symbol? (complement coll?) ?

20:33 TimMc: Guest58040: Do you know it's always a symbol if it's not a collection?

20:33 If so, you can use symbol? to check instead.

20:40 Guest58040: Heh, my terminology might be bad. I did end up using coll? for my problem.

20:40 So, what would you call the first element of this list? (1 2 3)

20:41 vs the first element of this list ([1] 2 3)

20:41 Is 1 a symbol?

20:41 Okay, it's not... what can I call it?

20:42 amalloy: it's a number

20:42 Guest58040: I guess I'm looking for an equivalent term to "atom" from Scheme lingo...

20:43 amalloy: we don't have that, because clojure code is built of more than two primitive types

20:43 Guest58040: A primitive, then?

20:43 amalloy: there's no atom/pair dichotomy

20:44 no, primitive means something else. are you sure you *want* to make this distinction, even?

20:45 justin_smith: I guess we have "self evaluating objects that are not data structures" and "everything else", but given that java.lang.Long is an object I don't know how many things *really* belong in the former category if any...

20:45 Guest58040: Hmm. Perhaps I will stick with number for now - I don't seem to have the vocabulary to express myself well.

20:45 I see that the JVM complicates what I should call things.

20:45 turbofail: i mean... collection vs. non-collection seems to be pretty much what you're looking for

20:45 justin_smith: Guest58040: clojure chooses not to mask or manipulate the representations of its vm

20:46 turbofail: but Long is a class, its instances have fields, it has methods

20:46 amalloy: not data structures? that's not really a good description imo

20:46 since eg Symbol is a pair of strings

20:46 justin_smith: indeed

20:46 turbofail: justin_smith: yeah but you can't reduce over a Long

20:47 Guest58040: Have you ever gotten excellent instruction by doing something incorrectly in front of a room full of skilled folks?

20:49 justin_smith: Guest58040: oh man I was arrogant enough to audit a graduate seminar, before I had even enrolled in college, when I was 19. I feel sorry for the other people in that room, but I learned a lot.

20:50 amalloy: Guest58040: https://meta.wikimedia.org/wiki/Cunningham%27s_Law

20:51 Guest58040: And now I even have a term for it. Thanks!

21:23 csd_: why is ring telling me that i have an invalid csrf token when i havent enabled the anti-csrf middleware (at least, to the best of my knowledge)

21:24 i'm using ring-defaults but didn't enable the feature

21:25 oh wait, ugh i take that back :-/

21:40 amalloy: (filter (comp seq identity) xs)

22:34 renl: hi may i ask why drop would check a vector into a list?

22:34 ack * check = change

22:34 justin_smith: renl: I think you want seq

22:34 ,(seq [1 2 3])

22:34 clojurebot: (1 2 3)

22:34 justin_smith: renl: why do you need a list though?

22:35 most things that work with lists work with vectors without needing any explicit conversion

22:35 renl: i didnt want a list, but i did a drop on a vector, then i did a conj on that but it added the new stuff at the front which i didnt want

22:35 justin_smith: then you didn't have a vector

22:35 drop returns a list, not a vector

22:35 ,(drop 3 [1 2 3 4])

22:35 clojurebot: (4)

22:36 justin_smith: (doc subseq)

22:36 clojurebot: "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true"

22:36 justin_smith: err

22:36 (doc subvec)

22:36 clojurebot: "([v start] [v start end]); Returns a persistent vector of the items in vector from start (inclusive) to end (exclusive). If end is not supplied, defaults to (count vector). This operation is O(1) and very fast, as the resulting vector shares structure with the original and no trimming is done."

22:37 justin_smith: ,(subvec [1 2 3 4] 3) ; you can use subvec instead of drop if you need the return value to be a vector

22:37 clojurebot: [4]

22:37 renl: k thanks just felt that it would cause bugs for newbies when i put a vector into a function and the outcome gave me a list :(

22:37 ok thanks :D

22:37 justin_smith: renl: nope, pretty much every list function silently turns vectors into lists, by design

22:38 renl: nod

22:38 justin_smith: well that's wrong, sorry, they don't turn anything into anything - for a vector arg they return things that are seq not vector

22:39 renl: k

Logging service provided by n01se.net