Fork me on GitHub
#clojure
<
2015-11-13
>
mbertheau03:11:48

I prefer (case choice :set value "") over (if (= choice :set) value ""). Am I strange?

mbertheau03:11:23

Just strange, or dangerously misled? simple_smile

mbertheau04:11:52

Extremely amazing and convenient that (assoc ["foo"] 1 "bar") adds an element to the vector!

delaguardo04:11:42

why not using (conj [“foo”] “bar”)?

mbertheau04:11:28

@delaguardo: It's convenient that I don't have to distinguish between modifying an element of the vector and adding one to the end.

mbertheau04:11:36

Except for the first element 😕 (assoc nil 0 "bar") is {0 "bar"} instead of ["bar"]

delaguardo04:11:48

because (not= nil []) )

bhagany04:11:40

fnil would work well there

delaguardo04:11:11

and in doc section for assoc - Note - index must be <= (count vector).

mbertheau04:11:47

@bhagany: Thanks! I have (update-in db [:product :times] (fnil #(assoc % index time) [])) now

bhagany04:11:13

@mbertheau: alright, nice. Maybe I don't quite understand your goal, but it makes more sense to me to wrap the '%' in fnil… otherwise (I think) you're going to end up with an empty vector if you don't already have a vector, instead of a one-element vector

bhagany04:11:18

(assuming that's what you want)

bhagany04:11:02

like (update-in db [:product :times] #(assoc (fnil % []) index time))

mbertheau04:11:05

bhagany: but % is not a function - am I missing something?

bhagany04:11:42

hahaha, you're right, I'm forgetting the signature

bhagany04:11:25

it's been awhile since I've had a need, but I remember it fondly

bhagany04:11:52

you were correct, I retract my "help"

mbertheau04:11:28

@bhagany: Thanks for the effort anyway! simple_smile

mbertheau05:11:17

Hmm, for filter there's filterv, but no removev for remove?

tungsten06:11:14

Hi - really simple question -- why doesnt this code work: http://pastebin.com/cFu7juQH

thheller06:11:37

you are basically calling (map inc 2) since you destructure the args [a [b]]

thheller06:11:35

make it [a b] and it works

martinklepsch06:11:12

lein repl
nREPL server started on port 54991 on host 127.0.0.1 - 
REPL-y 0.3.7, nREPL 0.2.10
Clojure 1.7.0
OpenJDK 64-Bit Server VM 1.7.0-u60-unofficial-b30
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> #?(:clj 1 :cljs 2)

RuntimeException Conditional read not allowed  clojure.lang.Util.runtimeException (Util.java:221)
IllegalArgumentException Wrong number of args passed to keyword: :clj  clojure.lang.Keyword.throwArity (Keyword.java:97)
This should work right?

mbertheau06:11:07

I can iterate over a map with for: (for [e {:a 1 :b 2}] e). How can I put the result back into a neat map?

noonian06:11:48

can use into

noonian06:11:50

(into {} (for [e {:a 1 :b 2}] e))

mbertheau06:11:02

Ah! Thanks. I wish there was a for-into or for-map.

noonian06:11:24

Yeah, there are utility libraries like https://github.com/Prismatic/plumbing that provide map-keys and map-vals.

mbertheau07:11:46

Hmm, I have a map {:mon {:a true :b [2 4 3]} :tue {:a false :b [1 5 2]}} and I want to return the same map with :b of the weekday ordered, but leave the current weekday (`current-weekday`) alone.

mbertheau07:11:14

That seems so easy to put in words, but hard to express with clojure. I have (reduce-kv #(assoc %1 %2 (case %2 current-weekday %3 (update-in %3 [:b] order-b))) {} my-map)

noonian07:11:44

If you are trying to update a value in a map, you probably want an update-in like function. (update-in {:a {:b 10}} [:a :b] #(+ 5 %)) ;=> {:a {:b 15}}

cjmurphy07:11:44

@mbertheau: Can the ordering you want be permanent? If so perhaps easier to use a sorted-map... (not sure your business use)

dm307:11:41

(require '[com.rpl.specter :as sp])
(sp/transform [sp/ALL sp/LAST :b] (comp vec sort) {:mon {:a true :b [2 4 3]} :tue {:a false :b [1 5 2]}})
=> {:mon {:a true, :b [2 3 4]}, :tue {:a false, :b [1 2 5]}}

meikemertsch07:11:04

😊 great minds think alike

asolovyov10:11:29

anybody using pedestal here? I have an url like "/campaign/:code-name/", and requests to that url with trailing slash return 404. While requests without trailing slash are handled normally. Any ideas how can I handle trailing slash?

nowprovision10:11:53

explicit route that 301s? never alias bad for seo

robert-stuttaford10:11:01

@asolovyov: they’re different routes in Pedestal’s world. i recommend pinging @ohpauleez on twitter for a quick answer

nowprovision10:11:54

they're different routes in any world. I think the think that apache does and I guess nginx with try_files followed by index directive leads to this idea that both should work as some standard practice

asolovyov10:11:07

@robert-stuttaford: yeah, I had an interceptor strip-trailing, which stopped working... 😕

asolovyov10:11:22

well, the problem is that pedestal just drops trailing slash

nowprovision10:11:37

@asolovyov ah I see, that is odd

asolovyov10:11:50

when I try to put an interceptor which would strip trailing slash from requests, it never gets called - pedestal returns 404 before that

asolovyov10:11:14

I wonder if I should update my :path-re by hand... 😕

martinklepsch11:11:12

when I want override a specific implementation of a multimethod in a test, is defing it in the test namespace “clean”? are there other ways?

tcrayford11:11:52

@martinklepsch: you can alter-var-root on it, or I think you can setDynamic on the var and then use binding

tcrayford11:11:57

unsure about the latter though

martinklepsch11:11:22

@tcrayford: what would I bind it to though? if I alter-var-root the var/dispatcher the already defined implementations will probably just stick around?

mbertheau12:11:31

@noonian, @cjmurphy, @meikemertsch: Thanks for your input :) specter looks like the most readable. I'll see if I can get the conditional in as well. Thanks simple_smile

tcrayford12:11:23

@martinklepsch: rebind it to a function, and the already defined implementations do stick around, but you don't hit them

martinklepsch12:11:32

@tcrayford: if I do that all other implementations will not work anymore and they’re needed 😄

tcrayford12:11:30

@martinklepsch: in which case I'd do the typical thing of "change your design so that this kind of var based thing can be swapped out in tests without actually using vars"

martinklepsch12:11:49

this is about clojure.test/report — guess I’ll stick with def’ing it in the test namespace simple_smile

tcrayford12:11:03

@martinklepsch: I hate clojure.test/report simple_smile

tcrayford12:11:17

bolth directly monkeypatches the method definitions in it: https://github.com/yeller/bolth/blob/master/src/bolth/runner.clj

tcrayford12:11:31

but that's suitable for a test runner, and probably not for what you're doing simple_smile

colin.yates12:11:31

@martinklepsch: I am ashamed to admit it, but I got around this by declaring a ‘normal’ defn which simply dispatched to a defmulti and then in tests overrode the defn. For an individual defmethod I had the implementation call out to a defn- which I could override in a test … yeah, not great but it worked

martinklepsch13:11:54

specifically the usecase is allowing users of test.chuck to customize how their smallest failing thing is getting printed

tcrayford13:11:40

@martinklepsch: huh, so they could pretty print it? Is this for checking or something else?

tcrayford13:11:56

(yeller has a fork of checking internally)

tcrayford13:11:23

@martinklepsch: btw Gary and I have been talking a lot about making defspec work significantly better with clojure.test, including incorporating the ideas in checking with regards to report and such. It seems like pretty printing or whatever would also be a good thing to throw in that (might wanna ping him about it)

martinklepsch13:11:05

yes for checking… Mostly stumbled upon it because I tried making collection-check and then test.chuck work with cljs

Alex Miller (Clojure team)14:11:24

@martinklepsch: that must be a lein thing - this works in 1.7 without lein

Alex Miller (Clojure team)14:11:46

@martinklepsch: in reference to your reader conditional repl question earlier that is

rauh14:11:28

Now that we have update shouldn't there also be an update! for transients?

Alex Miller (Clojure team)14:11:16

if you want to file a jira, you could see if anyone votes for it as useful. not sure what Rich would think about it.

jaen17:11:09

I'm fully aware this is a somewhat stupid question, but is there any JVM/Clojure hook that gets called on program exit?

jaen18:11:27

@itruslove: looks legit, thanks

zentrope18:11:23

jaen: Works great, but won’t be invoked with “lein run” then Control-C. Does work is you “lein trampoline run” before Control-C.

jaen18:11:15

I don't use lein, but still - good to know.

zentrope18:11:29

jaen: Yeah, one can get, uh, frustrated, wondering why it doesn’t work before one tries running from an uberjar or something. ;)

jaen18:11:44

Yeah, I imagine it's probably not so obvious to get why it's not working

txus19:11:04

quiz: I have a vector [:a :b :c :d] and an integer 6, and I want to “extend” the vector repeating its last argument until its length is 6, like this: [:a :b :c :d :d :d]. What’s the most concise way?

eraserhd19:11:15

(vec (take 6 (concat v (repeat (last v)))))?

txus19:11:02

wow, nice

txus19:11:50

I had (map-indexed (fn [i e] (nth v i e)) (repeat n (last v)), v being my original vector and n the integer

txus19:11:06

yours is better! than you @eraserhd 😄

eraserhd19:11:32

welcome 😄

colin.yates19:11:53

@eraserhd: +1 nice example of thinking functionally rather than idiomatically

colin.yates19:11:29

or maybe ‘declaratively’ is a better work than ‘functionally'

swizzard19:11:38

this one’s not as good as @eraserhd’s but: (into v (repeat (- n (count v)) (last v))))?

colin.yates19:11:17

how about this: (if (<= 6 (count v)) v (ask-slack))) simple_smile

colin.yates19:11:39

OH: Col, you need to stop trying to be funny! simple_smile

txus19:11:06

@colin.yates: good one! that’s the one I went with 😉

ghadi19:11:30

if you have a vector, never use last instead use peek

ghadi19:11:07

last is O(N), peek is O(1) on vectors

ghadi19:11:27

last is a seq operation, uses linked list traversal

swizzard19:11:32

well i’m convinced simple_smile

ghadi19:11:31

you're in a macro... then who cares, it's run only once. butlast is prevalent in macros

swizzard19:11:57

are macros really only run once?

swizzard19:11:47

if you’ve got something like (defn foo [& args] (my-very-inefficient-macro…)), wouldn’t the macro get run every time the function gets called?

xeqi19:11:11

only once, the compiler runs the macro and uses the result to create the runtime function

jeff.terrell19:11:14

It's worth mentioning that if e.g. last is used in the code returned by the macro (i.e. if it's in the macro-expanded form), it will be run whenever the macro is run. But if it's just in the code that generates the expansion, it will only be run once.

jeff.terrell19:11:21

At least, I'm pretty sure that's how macros work…

bronsa19:11:37

@swizzard: macros are expanded at compile time

bronsa19:11:00

unless you're doing weird stuff with eval (that you shouldn't be), macros won't expand at runtime

swizzard19:11:18

makes sense, i guess

swizzard19:11:52

honestly i still don’t really ‘get’ macros, especially when compared to e.g. HOFs

swizzard19:11:20

i think i’ve only ever written one in the year or so i’ve been using clojure

colin.yates19:11:31

it helps to think of macros as compile-time functions that generate functions

bronsa19:11:51

@colin.yates: it probably helps because that's what they are simple_smile

colin.yates19:11:02

or think of them as the ‘text-expander’ utilities that you get on OSX

bronsa19:11:08

macros are literally implemented as functions run by the compiler rather than the runtime

colin.yates19:11:28

@bronza simple_smile. They aren’t often described like that though

swizzard19:11:36

no they are not

bronsa19:11:57

well s/generate functions/generate code/ I guess would be more accurate

swizzard19:11:36

yeah, presumably the defwhatever-type macros you get in e.g. korma don’t necessarily generate functions

bronsa19:11:57

@swizzard: when learning lisps, I found that it helped me quite a lot to understand macros by understanding that there's nothing magical about `

colin.yates19:11:19

yep - code rather than functions - my bad

bronsa19:11:28

and that's it's only used in macros because it's convenient, rather than because it's needed

bronsa19:11:26

so to take the usual example of

(defmacro unless [cond & body] `(if (not ~cond) body))

bronsa19:11:36

if you think of it as a function (defn unless [cond & body] (list* 'if (list 'not cond) body))

bronsa19:11:35

and realize that the difference between this function and the defmacro is just: 1- we don't need to use "` ", it's not special syntax it's just a convenience to avoid nesting quotes and calls to list

bronsa19:11:54

2- it just takes implicitely quoted args and the result is implicitely evaluated

bronsa19:11:03

than macros really are as simple as functions simple_smile

swizzard19:11:54

i think part of the problem is that i haven’t had enough use cases where the pain of writing a working macro is less than just using HOFs or whatever

bronsa19:11:40

most experienced clojure devs would tell you that if you can use a HOF, you shouldnt' write a macro for that

swizzard19:11:02

like i said, i’ve only written the one, and it was just ->-but-takes-a-seq

swizzard19:11:04

thanks for the insights!

jaen21:11:42

Is it just me or does defonce not accept a docstring?

jgdavey21:11:16

@jaen I believe you have to provide it as normal metadata: (defonce ^{:doc “Hello”} foo (+ 1 2))

jaen21:11:57

That's kinda... arbitrary. But at least that's a workaround, thanks.

Alex Miller (Clojure team)21:11:02

there's a ticket for this - turns out to be surprisingly complicated to fix

jaen22:11:22

Interesting, why would it be so? No clear agreement on semantics?

Alex Miller (Clojure team)22:11:39

you can follow the comment/patch trail there

ikitommi22:11:21

can someone explain what happens to a record, when it gets evaluated?

(defrecord Kikka [])
(= (->Kikka) (->Kikka)) ; true
(= (->Kikka) (eval (->Kikka))) ; false

Alex Miller (Clojure team)22:11:33

there were changes in this area in 1.8 - I think you will now see true for both

ikitommi22:11:13

alexmiller: thanks! just tested with 1.8.0-RC1 and both give true.

Alex Miller (Clojure team)22:11:52

I think for a records with at least one element, you would have seen true for both even in 1.7

Alex Miller (Clojure team)22:11:08

this was the special case of records or types with no fields (which is not common)

eraserhd22:11:09

So the weird thing about using test.check to verify how rewrite-clj does things is that I’m generating random clojure programs.

ikitommi22:11:52

what about this one (with 1.8.0-RC1):

(= pos? (eval pos?)) ; true
(= [pos?] (eval [pos?])) ; false

ikitommi23:11:20

relates to the real life case I’m trying to figure out: (= schema.core/Keyword (eval schema.core/Keyword)) ; false. Keyword is a record with clojure.core/keyword? in it. Evaluating the record loses it’s equality.

eraserhd23:11:24

I am looking for a way to kill the repetition in this file: https://gist.github.com/eraserhd/bcdc5a04a54f96e95ab2

eraserhd23:11:50

I don’t even want the functions with stars appended.

eraserhd23:11:52

All I can think of so far is a macro that takes a map and generates all the things, but this seems pretty ugly.

noonian23:11:31

You might be interested in this library that helps create test.check generators: https://github.com/holguinj/jen

eraserhd23:11:10

@noonian Does this help with recursive generators?

noonian23:11:42

@eraserhd: yep, there is an example in the readme. YMMV as I haven’t used it myself. But I know the author and watched him give a talk on the library. Its motivation was making it easier to create complex generators.

eraserhd23:11:19

It appears that all it does is call gen/recursive anyhow. I think what I want is letrec for generators.

noonian23:11:41

ah, sorry for the noise then 😛

eraserhd23:11:09

@noonian: np, I mean I came here for ideas simple_smile

noonian23:11:07

well, I was thinking you could pull the node into an arg and just have one higher order function that you call with the different nodes in container node

noonian23:11:14

to get rid of the asterisk functions

eraserhd23:11:56

I’m going to try.