Fork me on GitHub
#beginners
<
2017-03-20
>
jennifer00:03:39

hopefully quick question. i’m trying to make the value of the :complete key true if it’s false and false if it’s true (triggered by a checkbox toggling on the front end). if i have this set to just true without the conditional, it works. but with the conditional, it only sets to true (always defaults to false). i’ve also tried it with (if (true? :complete) false true) but that didn’t work either.

(swap! todolist-atom
      (fn [todolist]
        (assoc-in todolist [id :complete] (if (true?) false true))))

yonatanel00:03:55

@jennifer true? expects a single argument but you don't supply one. Also, you probably want update-in instead of assoc-in to implement a toggle more easily.

jennifer00:03:57

here’s an updated version, but i get a 500 server error. it doesn’t like the boolean. i think i’m checking the wrong thing in the conditional.

(swap! todolist-atom
      (fn [todolist]
        (update-in todolist [id :complete] (if (true? :complete) false true))))

jennifer00:03:18

i’m going to go look at the update-in docs, too.

noisesmith00:03:48

that if isn't a valid arg to update-in

noisesmith00:03:06

update-in needs a function (optionally followed by more args to the function)

yonatanel00:03:10

Now that you're using update-in, it expects a function and arguments instead of a value.

jennifer00:03:26

yeah. i’m seeing that. 🙂

noisesmith00:03:31

replacing the if with not will actually do a toggle

noisesmith00:03:42

(update-in todolist [id :complete] not)

jennifer00:03:24

yup! that did the trick! thanks!!!

ice505002:03:58

Hello! I’m a beginner here. I’m really confused this code.

(reduce #(%2 %1) [1 2] '(reverse))
;; nil

(reduce #(%2 %1) [1 2] (list reverse))
;; (2 1)

ice505002:03:46

Can anyone help me explain why it’s not the same ?

tbaldridge02:03:56

@ice5050 it really bizzare, so let's walk through it a bit simply:

tbaldridge02:03:14

'(reverse) expands to (quote reverse)

tbaldridge02:03:12

if you do (type (first '(reverse))) you'll see that what you have isn't a list of the function "reverse" but a list of a symbol who's name is "reverse"

ice505002:03:46

Oh, I see.

ice505002:03:27

I think I can use ’() shorthand for list of functions.

tbaldridge02:03:00

In Clojure, symbols are functions, and can look themselves up in associative collections. Vectors are associative collections (keys being integers). So your first example takes "reverse" and tries to look it up in the vector.

tbaldridge02:03:13

Of course the vector doesn't have a key named "reverse" so it returns nil.

tbaldridge02:03:09

In the second case, list is a function that takes arguments. So the compiler looks up reverse, and calls list passing in a reference to the function reverse. Now you have the actual function and not a symbol inside the reduce so it works as expected.

ice505002:03:01

@tbaldridge Thank you very much, you helped me a lot!

foamdino18:03:52

hi clojure.string/starts-with? looks perfect for a (filter) I have in mind, but I cannot apply starts-with? as a predicate to filter as it takes two params (s and substr) so this (filter (clojure.string/starts-with? "a") ["abc" "def"]) fails - is there something simple I'm missing or should I be looking at macros here?

Prakash18:03:19

@foamdino u can create a partial function and use that in filter

seancorfield19:03:20

You can’t use partial here since the missing argument is the first, not the last. You can use an anonymous function: (filter #(str/starts-with? % “a”) [”abc” “def”]) — assuming you require [clojure.string :as str] which is pretty standard in Clojure code.

foamdino19:03:26

^^ exactly what I was looking for - I didn't think I needed a macro to re-order the arguments!

seancorfield19:03:15

Macros are usually best thought of as a last resort: do everything with functions and only use macros where a) you can’t get a function to do what you need or b) you want some syntactic sugar to remove boilerplate.

seancorfield19:03:02

At work we have a flip utility function (named for the Haskell version) that is like partial but allows for the argument to be omitted at the front, so ((flip f :b :c :d) :a) will call f with :a :b :c :d in that order. It’s useful in cases like yours: (filter (flip str/starts-with? “a”) [”abc” “def”])

Alex Miller (Clojure team)19:03:33

Rich considers anon functions to be the Clojure approach to this

seancorfield19:03:53

Yeah, I know, but I find (flip f x y z) to be nicer to read than #(f % x y z) 🙂

seancorfield19:03:20

(or (fn [a] (f a x y z)))

seancorfield19:03:00

Sometimes I think it would be nice if we had filter-> etc: (filter-> (str/starts-with? “a”) […]) but then I love the threading macros and probably overuse them for your taste @alexmiller (or Rich’s taste) 🙂 We have condp-> and condp->> macros at work that thread the expression thru the predicate (as well as the expression) since that seemed to be a very common “need” in our code.

Alex Miller (Clojure team)19:03:57

sounds like a good thing to have outside of core :)

seancorfield19:03:16

Heh, yeah, worldsingles.util has a bunch of stuff that we use heavily that is “like” core stuff but absolutely should not be “in” core!

Alex Miller (Clojure team)19:03:47

the cool thing about functions is we can always make more :)

seancorfield19:03:20

Always Be Composing 🙂