Fork me on GitHub
#beginners
<
2018-12-04
>
Daouda04:12:32

can someone help me with reduce use?

Daouda04:12:11

i read the doc, but can't get to apply it to resolve my problem

Daouda04:12:08

i want to use reduce to collect the ids of all object filling certain condintions

Daouda04:12:27

i can't use map and filter cause both give me back the entire object

Daouda04:12:44

here is what i've tried so far

(reduce (fn [public-connections profile]
                           (if (:visibility profile)
                           (conj public-connections (:id number)))
                          []
                        profiles))

Daouda04:12:25

wrong code

Daouda04:12:46

sorry it's correct one

Daouda04:12:18

i get error say profile doesn't exist in the context

yuhan04:12:41

the else clause of your if expression should return the unchanged map, right now it's returning nil

Daouda04:12:59

i am only interested in the if

Daouda04:12:27

if else just do nothing and go to next one

yuhan04:12:17

public-connections here is your accumulator value, you have to explicitly pass it to the next iteration

Daouda04:12:24

i guess i am messing up with the if sintaxe

yuhan04:12:46

otherwise it "resets" to nil

Daouda04:12:59

can you please show me how?

Daouda04:12:12

i never use reduce before

Daouda04:12:28

and it's getting really frustrating hehehehehe

yuhan04:12:29

(reduce
 (fn [public-connections profile]
   (if (:visibility profile)
     (conj public-connections (:id number))
     public-connections)
   []
   profiles))

yuhan04:12:20

wait, your init and collection were also in the wrong level of nesting

yuhan04:12:43

(reduce
 (fn [public-connections profile]
   (if (:visibility profile)
     (conj public-connections (:id number))
     public-connections))
 []
 profiles)

yuhan04:12:31

in this case you could also go the easier route with map and filter

yuhan04:12:40

(map :id (filter :visibility profiles))

👍 8
Daouda04:12:28

hehehehehehehe

Daouda04:12:44

really that shooooooort?????

Daouda04:12:21

thank you very much @qythium that helped a lot

yuhan04:12:33

glad to have helped 🙂

Acted04:12:44

Is there guidelines on the largest size of a data structure used in an atom? Besides memory constraints?

andy.fingerhut05:12:30

If it fits in memory, you can put it "inside" an atom. An atom is just a pointer and a little bit of Java object overhead, and takes very little memory on its own.

nikola05:12:06

while learning Clojure I seem to get back to basic questions on how to deal with data structures like sets, maps, and so on. Is there a cheat-sheet or a good introduction? What resources would you recommend?

clojure beginner05:12:13

(reduce + (map :copies-sold [book1 book2 book3])) Just adding the sum total of all books sold. How is this evaluated internally?. Do we need to worry about how many times the collection is internally looped ?

clojure beginner05:12:56

and by this does it extend to any level of nesting ?

clojure beginner05:12:06

map , folter , reduce all used in the same expression

clojure beginner05:12:10

or we can just assume that clojure will do better than if you were to loop and just write our map, filter and reduce

andy.fingerhut05:12:34

@nikola.kasev Have you seen this cheatsheet? https://clojure.org/api/cheatsheet That page links to this one which has tooltip variants showing function docs when you hover the mouse cursor over symbols: https://jafingerhut.github.io/

andy.fingerhut05:12:00

Look for the sections on collections

seancorfield05:12:31

(depending on what you're actually looking for)

andy.fingerhut05:12:33

I have heard many people like the book "Clojure for the Brave and True" as an introduction to Clojure, too (free on-line I believe)

seancorfield06:12:42

@gayathrik map is lazy, so it will walk the collection "on demand" as reduce walks through the data. That said, an intermediate sequence is constructed and then consumed so, technically, you are walking two sequences.

seancorfield06:12:05

If you use the transducer form of this, you won't get that intermediate sequence (transduce (map :copies-sold) + 0 [book1 book2 book3])

nikola06:12:36

thank you, I have the book too

clojure beginner06:12:27

@seancorfield thanks. Will read up on transduce.

Daouda06:12:04

can you tell me how to call fixture?

Daouda06:12:48

i read about how to create them everthing, but where when and how i call them?

Daouda06:12:27

who do i say run my fixture

Lennart Buit06:12:53

You mean like this: (use-fixtures :once your-fixture)

Daouda07:12:34

I've created this file

(ns nukr.test-config
    (:require [nukr.profiles-database :refer :all]
              [taoensso.timbre :as timbre :refer [info]]))


(def nu-maflany {:id (swap! id-seq inc)
                 :firstname "Maflany"
                 :lastname "Traore"
                 :visibility true
                 :connections #{}})

(def nu-teca {:id (swap! id-seq inc)
              :firstname "Teca"
              :lastname "Alves"
              :visibility true
              :connections #{}})

(defn up-database
  (info "Setting database")
  (swap! profiless assoc :id nu-teca)
  (swap! profiless assoc :id nu-maflany))

(defn down-database
  (info "Resetting database")
  (reset! profiless (hash-map))
  (reset! id-seq 0))

(defn once-fixture [f]
  (up-database)
  (f)
  (down-database))

(use-fixtures :once once-fixture)

Daouda07:12:25

they way i understand it i should call defn once-fixture somewhere

Lennart Buit07:12:45

If I have interpreted the docs correctly, when you call use-fixtures in a namespace with tests, each test in that namespace is wrapped in your fixtures

Daouda07:12:45

i don't know wow to use it

Lennart Buit07:12:27

Either each individually (`:each`) or all at once (`:once`)

Daouda07:12:44

lets say you want to use the code i just put here

Daouda07:12:52

what will you do next?

Daouda07:12:17

define a deftest tesing in a test file and just call it?

Lennart Buit07:12:18

if I have a namespace with tests in which I would like to use these fixtures, lets say some_tests.clj, I would at the top, but below the requires, call use-fxtures

Daouda07:12:25

then use it in my deftest right?

Daouda07:12:55

and it will be use for all testes define in this file so?

Lennart Buit07:12:40

yes, in this case, it will be ran once before all tests in the namespace

Lennart Buit07:12:01

Here is a blog by Stuart Sierra (author of clojure.test) on a typical way that fixtures are used: https://stuartsierra.com/2016/05/19/fixtures-as-caches

Daouda07:12:14

ooooooooook thank you very much @lennart.buit 🙏

Lennart Buit07:12:21

Not the best blogpost ever to explain them, but the first few paragraphs are helpful

JanisOlex09:12:51

hi, somewhat phylosophical question. What are usecases where multimethods shine?

JanisOlex09:12:48

to me it looks like somwhat overpowered switchcase which takes a function as it's argument and then bunch of results mapping to another functions taking the same argument as original dispatch function

danielneal09:12:44

You can only extend switch case if you own the code. If a library author uses a multimethod for extension points you can extend the behaviour without forking the library.

danielneal09:12:07

So it shines most when you care about having an open, extendable system. It's a bit less important if you own all the code and the things you need to switch on are very finite - in that case as you say, a cond or case will probably do the job.

verneri09:12:59

also when you want to distrivute the cases to different namespacet

👍 4
Felicity Martinez09:12:35

Hi! How would I do a sort on a string so that it doesn’t default to alphabetical order, but rather in order of appearance? i.e. “Hello” -> “Hello” instead of “eHllo”.

danielneal09:12:24

@felicityfmn would it be a pain to provide another example? I haven't quite got what you meant from just that one

Felicity Martinez09:12:28

so, something like "Leeeeeeroy" in problem 30 of 4clojure, when I do (sort (set (str/split "Leeeeeeroy"))) it comes out as "\e \L\o \r \y" and I want it to be "\L \e \r \o \y"

Daouda09:12:20

hey friends, i lost here

Daouda09:12:58

i can't understand what is going on, i tried long time to understand but keep making no sense to me

Daouda09:12:16

here is my code (mapcat get-profiles-connections (map get-profile! ids-profile))

Daouda09:12:45

basically i a passing a list fo ids in the map

Daouda09:12:14

which will be used to get the corresponding profile

Daouda09:12:52

after getiing those corresponding profile, i pass them to mapcat which is supposed togaeher each profile connection and give me back a big array with all the ids

Daouda09:12:01

buuuuuuuuuuuut

danielneal09:12:04

ah, @felicityfmn I think you'll need something different from a sort - you want to go through the string removing duplicates rather than sorting the whole thing

Daouda09:12:13

what i get back doesn't make sense

Daouda09:12:35

look like it grabs some and leave some

Daouda09:12:45

anyone could help please?

Felicity Martinez09:12:58

I’ll get to it then

danielneal09:12:12

(I'm guessing because it's a problem question you can't use dedupe...)

danielneal09:12:47

(apply str (dedupe "Leeeeeroy")) => Leroy 😄

Felicity Martinez09:12:44

i never heard of dedupe

Felicity Martinez09:12:00

there are no restrictions on it in the problem so it might just work

danielneal09:12:34

@quieterkali would it be a problem to put your code for get-profiles-connections and get-profile! - might help spot the problem

Daouda09:12:59

moment please

Daouda10:12:20

(defn get-profile-connections
  "Take a profile and return corresponding profile connections"
  [profile]
  (info "Calling get-profile-connections")
  (let [{connections :connections} profile]
    (into [] connections)))

Daouda10:12:15

(defn get-profile!
  "Return profile by id"
  [id]
  (info "Calling get-profile! with ID: ", id)
  (@profiles id))

Daouda10:12:09

ids-connections-of-connections (map :connections (map get-profile! ids-connection))

danielneal10:12:18

hmm should work..

danielneal10:12:39

@quieterkali have you got some example failing data?

Felicity Martinez10:12:39

hmm, it’s giving me an "unable to resolve symbol: dedupe in this context"

danielneal10:12:18

there are no notes in the question saying dedupe is disabled?

danielneal10:12:29

(sometimes they do that, forcing you to reimplement).

danielneal10:12:33

Maybe it's an older version of clojure

danielneal10:12:47

dedupe came in in 1.7

Felicity Martinez10:12:48

shame, it is useful and it works in my repl

Daouda10:12:05

[
  {
    "id": 7,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": []
  },
  {
    "id": 1,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      4,
      6,
      3,
      2,
      5
    ]
  },
  {
    "id": 4,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      1,
      3
    ]
  },
  {
    "id": 6,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      1,
      3
    ]
  },
  {
    "id": 3,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      1,
      4,
      6,
      5
    ]
  },
  {
    "id": 2,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      1
    ]
  },
  {
    "id": 11,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": []
  },
  {
    "id": 9,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": []
  },
  {
    "id": 5,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": [
      1,
      3
    ]
  },
  {
    "id": 10,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": []
  },
  {
    "id": 8,
    "firstname": "string",
    "lastname": "string",
    "visibility": true,
    "connections": []
  }
]

Daouda10:12:21

take a close look to id 1 and id 2

Daouda10:12:33

1 and 1 are friends. i want to give some friend sugestion to 2 base on 1 friends. so i take id 1 friends and i look up there friend one by one and see the number which high repetion, so that one is suppose to be the fisrt on the list

Daouda10:12:19

actually 3 have to come first

danielneal10:12:20

so you call your mapcat function with all of 1's friends

danielneal10:12:32

so

4,
      6,
      3,
      2,
      5
is the input

Daouda10:12:16

because among id ' friends, the number with high frequency is 3

danielneal10:12:29

then you'd expect 1,3,1,3,1,4,6,5,1,1,3 as the output from the mapcat

danielneal10:12:56

what are you getting instead?

Daouda10:12:27

but for some reason i am always getting the id 1 list of connection 😞

Daouda10:12:00

always getting this

4,
      6,
      3,
      2,
      5

Daouda10:12:22

which is exactly id 1 friends list

danielneal10:12:37

ok let me try

danielneal10:12:30

(def profiles
  [{"id" 7, "firstname" "string", "lastname" "string", "visibility" true, "connections" []}
   {"id" 1, "firstname" "string", "lastname" "string", "visibility" true, "connections" [4 6 3 2 5]}
   {"id" 4, "firstname" "string", "lastname" "string", "visibility" true, "connections" [1 3]}
   {"id" 6, "firstname" "string", "lastname" "string", "visibility" true, "connections" [1 3]}
   {"id" 3, "firstname" "string", "lastname" "string", "visibility" true, "connections" [1 4 6 5]}
   {"id" 2, "firstname" "string", "lastname" "string", "visibility" true, "connections" [1]}
   {"id" 11, "firstname" "string", "lastname" "string", "visibility" true, "connections" []}
   {"id" 9, "firstname" "string", "lastname" "string", "visibility" true, "connections" []}
   {"id" 5, "firstname" "string", "lastname" "string", "visibility" true, "connections" [1 3]}
   {"id" 10, "firstname" "string", "lastname" "string", "visibility" true, "connections" []}
   {"id" 8, "firstname" "string", "lastname" "string", "visibility" true, "connections" []}])

(defn get-profile [id]
  (first (filter #(= (get % "id") id) profiles)))

(defn get-connections [id]
  (-> (get-profile id)
      (get "connections")))

(defn connection-frequencies [id]
  (let [connections (get-connections id)]
    (mapcat get-connections connections)))

danielneal10:12:32

this works for me

danielneal10:12:57

(connection-frequencies 1) => (1 3 1 3 1 4 6 5 1 1 3)

danielneal10:12:02

you could then use `frequencies in the last function too

(defn connection-frequencies [id]
  (let [connections (get-connections id)]
    (frequencies (mapcat get-connections connections))))

Daouda10:12:46

yeah that is the ideia

Daouda10:12:07

but the output get me sad

danielneal10:12:41

You've got the right shape of things - I'm just not sure where in your code there is probably some small mistake.... difficult to tell without being in front of it!

Daouda10:12:33

i know how it is

Daouda10:12:53

and the one in front of got blind :rolling_on_the_floor_laughing:

danielneal10:12:01

you can try maybe taking my code above which works for the sample data - and then changing get-profile to work with however you have them

danielneal10:12:08

I'm guessing it's coming from some kind of api?

Daouda10:12:12

exactly, guessed right

danielneal10:12:53

it might be something simple like a mix up of keywords/strings ....

Daouda10:12:49

hehehehehe, then i will hit my face

Daouda10:12:05

i am still looking for the problem

Daouda10:12:19

i'll found out

Daouda10:12:31

have no choice

danielneal10:12:43

sorry I couldn't help really

Daouda10:12:01

@danieleneal thank very much for your help 🙂

Daouda10:12:18

you've helped a lot 🙂

😄 4
Daouda10:12:26

believe me

Daouda11:12:36

@danieleneal it was working the whole time

Daouda11:12:40

hehehehehehehe

Daouda11:12:53

i was testing wrong

Daouda11:12:20

i can't believe that

Daouda11:12:39

lost a good time to sleep because of that

Mario C.17:12:01

reduced is to reduce as ___ is to filter

Mario C.17:12:16

is there an equivalent to reduced for filter?

bronsa17:12:28

no, and it doesn't make sense for it to exist

bronsa17:12:39

reduce folds, filter is a lazy traversal

johnj21:12:38

Confused, isn't reduce eager? or what do you mean here?

bronsa21:12:58

edited, I typoed

😉 4
bronsa17:12:44

if you want to terminate early, take on it

didibus17:12:13

Filter automatically terminates early, because of its lazy semantics

Daouda17:12:12

contdwon 10mn to @potetm Advent of Code in Clojure day 2

didibus17:12:04

And I don't believe there's a way to do it with filterv

jstaab20:12:33

Curious why there's no pipe function in clojure, but there is a comp? Thread macros aren't always the right fit.

Chris20:12:51

Can you elaborate a bit please? If you’re thinking of pipes plus auto curried functions, the reason is it’s difficult/impossible to do with multi-arity and variadic functions

jstaab20:12:58

Just order, (defn pipe [& xs] (apply comp (reverse xs)))

jstaab20:12:42

I'm only really worried about unary functions, though if comp handles something more, great

Chris20:12:33

comp is just for unary funcs AFAIK

Chris20:12:43

I guess one reason pipe isn’t in core might be it’s trivial to write, as you have shown 🙂

jstaab20:12:49

Sure, I'm just curious why comp would be in the standard library, when pipe wouldn't, since it's more readable. I mean, that's the whole idea behind threading macros

jstaab20:12:58

Yeah, it is trivial 🙂

jstaab21:12:09

And comp is more lambda-calculus-y

Riles21:12:46

This is my guess: In cases where you have all the functions written out in front of you, threading works just as well: (-> x f g h) or (fn [x] (-> x f g h)) In the case where you are pipe-ing down a seq of functions, you lose the clarity pipe brings anyway

noisesmith21:12:05

another thing to consider here, is that since transducers chain a transducing context rather than the data itself when first called, the transducer (comp (map f) (map g)) behaves like (map (comp g f) ...) - reversing the effective order

jstaab21:12:16

Ohh @noisesmith that's interesting. I've noticed the same pattern with connecting multiple react components with react-redux (in javascript) — it's actually more intuitive to compose those with comp than with pipe, since you move down the tree in reverse the order of composition.

noisesmith21:12:53

I bet a similar mechanism goes on under the hood (but I don't know react-redux at all)

jstaab21:12:37

Yeah, it's all about higher-order components, so you're creating a data structure by composing decorators, so the nesting reflects the composition

Riles00:12:52

^^ this pattern shows up a lot in mathematics too. If you ever hear category theory people talk about duality, this direction reversal is what they mean

👍 4
noisesmith00:12:28

oh, awesome - thanks for that info

hiredman20:12:22

what is the difference between pipe and comp?

Alex21:12:08

comp is right to left, pipe is left to right

nikola21:12:11

I have a function f with two parameters and a list like this ((1 2) (2 3)). I'd like to map over the list and call the function. I do (map (fn [[one two]] (f one two)) <the list>). Is there a better way to apply the function for each pair in the list?

noisesmith21:12:09

you could replace (fn [[one two]] (f one two)) with (partial apply f)

noisesmith21:12:16

I'll let you decide which is clearer

victorb22:12:20

regarding naming conventions, is it a convention to name functions with side-effects with a ! as a suffix? For example, swap! uses it, and I was thinking specifically about API calls such as create-txt-record might be better off being create-txt-record! instead to signal the side-effect

noisesmith22:12:19

it's a loose convention

noisesmith22:12:53

there's also the io! macro, which you can use to wrap code that does side effects, it gives an error if your code runs in a transaction (as transactions should be able to retry safely)

nikola23:12:08

@noisesmith how does this work? partial is when a function is partially applied, but in my case I have all parameters

noisesmith23:12:55

Rereading this, another thing I can point out is that you don't actually have all the parameters when that form is evaluated. map doesn't accept a body of code to run, it needs some function (compared to eg. for which does use a body of code instead of a function arg)

noisesmith23:12:43

partial returns a function, you can use it in place of fn, if your args will be tacked to the end of a function call

noisesmith23:12:02

so we use apply to spread the input coll into args for f

noisesmith23:12:13

and we use partial to create a function ready to apply f to some coll

noisesmith23:12:23

(partial apply f) is another way of saying (fn [& args] (apply apply f args))

nikola23:12:08

I'll read more about apply, thanks

noisesmith23:12:17

or (fn [arg] (apply f arg)) for the one arg case only

noisesmith23:12:50

user=> (apply + 1 2 3 [4 5 6])
21

Nicki_Vance23:12:23

Hi all, I'd like to practice pair programming. If you're interested in doing a 45min call with me, we can work on advent of code or a problem from exercism. I'll be on west coast US time. Email me at <mailto:[email protected]|[email protected]>.

victorb23:12:51

@noisesmith got it, thanks a lot