Fork me on GitHub
#beginners
<
2016-11-25
>
michaelmrose06:11:55

hey question I note that you can avoid problems with order of functions via (declare), is there any reason clojure doesn't just do this for you?

bbss06:11:38

it's because a clojure file should sort of represent an interaction you have with a REPL, having top level declarations automatically would require the whole file to be parsed once just for that purpose (JavaScript compilers usually does this).

bbss06:11:05

I think, not an expert 😄

michaelmrose06:11:32

thanks that sounds reasonable

michaelmrose06:11:18

although sometimes I find I want to use functions in other functions its not TOO cumbersome to write (declare foo) just annoying

bbss06:11:19

Hmm, then eval them first?

bbss06:11:27

How are you running your code?

bbss06:11:42

This is not usually a problem for me during development.

michaelmrose06:11:04

emacs + cider it initially works if I forget to put them in order it just fails when I reconnect later

bbss06:11:33

ah yeah, have to eventually put them in order.

michaelmrose06:11:43

my project per se is a big disordered pile of functions designed not towards any real end but to learn

bbss06:11:37

okay, well yeah then declaring might be your quickest option.

michaelmrose06:11:38

going through clojure for the brave and true and the little schemer

roelofw06:11:44

@michaelmrose and do you like the first book. I liked the book but found the exercises to hard

roelofw06:11:00

Expeially the last two of each chapter

echristopherson07:11:44

I just read that declare is discouraged

echristopherson07:11:48

somewhere in the docs

genmeblog07:11:19

just order your functions, mutual recursion is rare

genmeblog07:11:00

and use different namespaces to separate functionalities

kauko10:11:19

It helps in learning what a namespace does if you know you can start reading it from the bottom up. You lose that if you use declare. Granted, sometimes there's situations where using declare does make your namespace more readable

Alex Miller (Clojure team)13:11:47

declare is fine, not discouraged

Alex Miller (Clojure team)13:11:20

but generally the recommendation is order your fns to minimize the need for it

Alex Miller (Clojure team)13:11:53

Clojure requires this because it’s a single-pass compiler, which has huge benefits in simplicity and performance

roelofw16:11:27

How can I make a vector without the () of this :

[(1 2) (4 5) (7 8)] 

roelofw16:11:01

I tried with concat and flatten but that does not produce the output I wanted

roelofw16:11:30

flatten gives : (1 2 4 5 7 8) where the challenge wants to be : [ 1 2 4 5 7 8]

bbss16:11:44

(vec (flatten ))

kauko16:11:52

That's better actually

bbss16:11:58

is it? 😄

roelofw16:11:54

thanks, but does it makes any difference according to repl : (= '( 1 2 ) [ 1 2]) are the same

dominicm16:11:42

@roelofw The comparison is weakly typed

roelofw17:11:00

apparently clojure is weakly typed

roelofw17:11:27

Another question. I have now this code for dropping a nth item in a list

roelofw17:11:55

The code I have is this :

(defn my_nth_drop  [s  n]
   (loop [ s1  s
           acc [] ]
     (if (empty? s1 )
       (flatten acc)
       (recur (drop n s1 ) (conj acc (take ( - n 1) s1 ))))
     )) 

roelofw17:11:13

can I do the same with for example a map or a reduce function

roelofw17:11:41

I read that loop need to be avoided

bbss17:11:04

you can't do it with a map, because map does something for every thing in a collection, thus not changing the size. you could do it with a reduce.

Alex Miller (Clojure team)17:11:46

@roelofw: Clojure is not weakly typed. What you're encountering is that all sequentials (list, vector, seqs) are compared in the same equality partition. That is, they only check whether they contain the same elements in the same order (and not the type of the collection). This is a pragmatic choice that helps in blurring the line between collections and seqs.

roelofw18:11:24

Anyone a example where reduce takes more then 1 argument like my function does with take n ?

roelofw20:11:15

no one who can help me ?

dpsutton20:11:17

what are you working on

rauh20:11:27

If you want to use a reduce, you can def. do that. Just keep conj'ing and skip the conj when the count is n. @roelofw

roelofw20:11:00

oke, and set the counter to zero because let's say I have ( 1 2 3 4 5 6) and I want to delete all the 3th this schould be the answer ( 1 2 4 5 )

rauh20:11:20

No mutable counter involved

dangit20:11:06

The docs for carmine (a redis client https://github.com/ptaoussanis/carmine) recommend setting up a connection pool and access macro like this:

(def server1-conn {:pool {<opts>} :spec {<opts>}}) 
(defmacro wcar* [& body] `(car/wcar server1-conn ~@body))
What is the advantage of using a macro here instead of something like
(def wcar* (partial car/wcar server1-conn))

roelofw20:11:44

@rauh , how do you see then the count to n part. In my case I have to do it 2 times

rauh20:11:28

@dangit Try it, you won't be able to

rauh20:11:57

You can't pass around car/wcar since it's a macro, it's not an object during runtime

dangit20:11:15

Yeah, I know, that’s why I was looking for an alternative.

dangit20:11:00

Maybe I misunderstand what you’re saying, I’m asking why not define wcar* (I should change the name) as a partial instead of as a macro.

rauh20:11:44

Well, it also wouldn't work, you need it to be a macro since you can't evaluate your (car/ping) (etc) which would happen if you passed it to a function

rauh20:11:25

Anything you pass to function gets evaluated before the function is called.

dangit20:11:35

Oh, yeah, ok, thanks that makes sense.

rauh20:11:36

@roelofw you have to show some code

roelofw20:11:46

the code with the loop ? @rauh

rauh20:11:50

You asked "can I do the same with for example a map or reduce function", I said "If you want to use reduce..."

dpsutton20:11:16

roelofw just post what you are working on

roelofw20:11:22

yes, you did but I still do not fully understand how the reduce function looks like

rauh20:11:23

map can't remove elements, keep could

rauh20:11:45

If I write it for you, the learn effect is ~0

roelofw20:11:00

out of my head , I would do something like this : (fn [s count] (reduce (fn [acc, n] (if ( == ??? count) (acc) ((conj acc (take ( - n 1))) s ))

rauh20:11:31

(count acc)?

rauh20:11:51

Also, no take in this case, and way too many parentheses

dpsutton20:11:05

(acc) will definitely be an error, no?

roelofw20:11:19

yep, this was written out of my head without a ide

roelofw20:11:49

@dpsutton right that can be acc without the parentheses

dpsutton20:11:20

so what is acc in your reducing function?

dpsutton20:11:28

is it the conj'ed elements of the list?

dpsutton20:11:35

or how many elements you've seen?

roelofw20:11:35

the output

dpsutton20:11:48

so what does your function output?

roelofw20:11:51

if the input is s = ( 1 2 3 4 5 6) and n = 3 then the output must be ( 1 2 3 5)

rauh20:11:54

Btw, never use count has a variable name. It'll shadow the function count

dpsutton20:11:23

ok, so acc is the conj'ed together elements that you care about

rauh20:11:54

"Keep adding to the list (reduce conj [] xs), but skipping if the list is at n elements (if .... ..... ......)"

roelofw20:11:34

oke, so test the condition with a if

roelofw20:11:01

I have to find out how I can know at which position I am

roelofw20:11:41

oke, there I can use the .indexOf function

rauh20:11:27

How many elements acc has is given by (count acc)

roelofw20:11:29

so the anymous function will be (fn[acc n] ( if (= (.indexOf n) n1) ...,... ))

roelofw20:11:49

it depends how many items are already found

roelofw20:11:22

if my new function n is the current item and n1 is the number given by the user

rauh20:11:36

Why not use my suggestion?

roelofw20:11:59

@rauh , I try to use your suggestion of using a if then

roelofw20:11:38

the (count acc) could be more then 3 for example when acc = ( 1 2 4 5)

roelofw20:11:15

or do we misunderstood each other somehow

dpsutton20:11:23

roelofw, could you post which funtion you are trying to rewrite?

dpsutton20:11:33

or input and output?

roelofw20:11:20

the function with a loop :

(defn my_nth_drop  [s  n]
   (loop [ s1  s
           acc [] ]
     (if (empty? s1 )
       (flatten acc)
       (recur (drop n s1 ) (conj acc (take ( - n 1) s1 ))))
     ))  

roelofw20:11:34

where acc is the output that I wish

dpsutton20:11:41

and it should drop every nth item in a list?

roelofw20:11:19

example input s ( 1 2 3 4 5 6) and n 3

roelofw20:11:06

expected output : ( 1 2 4 5)

roelofw20:11:23

and the function with a loop does the job

roelofw20:11:52

the only thing I have read that loop schould be avoided and map or reduce can be better be used

roelofw20:11:10

but I do not see how that can work , @dpsutton

dpsutton20:11:27

dont avoid loops necessarily

roelofw20:11:33

til now I have only dealed with one item

dpsutton20:11:54

and you can mutate a var in the reducing function

roelofw20:11:01

and now reduce schould be working with more items

dpsutton20:11:15

what makes you think that

roelofw20:11:36

because I have used take in my loop function

roelofw20:11:49

and I think I have to use it into the reduce also

roelofw20:11:28

but I think im stuck in a thinking pattern

dpsutton20:11:49

i dont know what "i have used take in my loop function" means

roelofw20:11:51

I use take to take a part of the given string

roelofw20:11:53

so if n = 3 then I take 3 characters out of the given seq and then I can drop the next one

dpsutton20:11:08

so not string but sequence

dpsutton20:11:13

don't use take

roelofw20:11:13

sorry, I mean a seq

dpsutton20:11:19

let your reducer be the one that walks the input

dpsutton20:11:23

don't reach out and grab more

roelofw20:11:09

reducer is the acc in my code

dpsutton20:11:20

in your reducing function, decide if you care about the particular item (conj it) or dicard it

dpsutton20:11:32

the reducer is the function

dpsutton20:11:36

you are reducing

roelofw20:11:14

oke, but then I have to know if it's a first , second or thirth item in the list , so I have to count , right ?

dpsutton20:11:28

sounds right to me

roelofw20:11:25

and if in my example 3 is reached, I skip it, and the counter needs to be zero again

dpsutton20:11:33

sounds good to me

dpsutton20:11:45

or you could just keep the counter going and check remainder or modulus

roelofw20:11:56

hmm, rauh says I do not need a mutable counter

dpsutton20:11:22

i haven't thought of a solution that doesn't involve one

roelofw20:11:26

can also be working , check for modulus 3 is zero

dpsutton20:11:34

how about we solve it with the mutable counter

dpsutton20:11:39

and then we solve it a few other ways as well

dpsutton20:11:46

get it working first, then refine it

roelofw20:11:10

oke, so we have this (fn [s n] ........ )

roelofw20:11:34

where s is the given seq and n the number we want to skip,

dpsutton20:11:08

what have you got so far

roelofw20:11:42

What I wrote above

roelofw20:11:58

I started all over again

dpsutton20:11:09

well keep going

roelofw20:11:22

' (fn [s n] ..... ) `

dpsutton20:11:31

that's absolutely nothing

dpsutton20:11:39

that's what the skeleton of a function looks like

dpsutton20:11:42

what do you want to put in it

roelofw21:11:25

we cannot use reduce as far as I know because reduce uses 2 variables acc for the output and n for the current item

dpsutton21:11:50

we just talked about how we are gonna use a mutable one in it

roelofw21:11:53

and we need 3 I think acc for the output , the current item n and a counter

dpsutton21:11:06

the counter will be involved in the closure, not as an argument

dpsutton21:11:25

we're gonna keep a reference to it, and we don't have to pass it in every time

seancorfield21:11:52

Besides [[acc output] n] would let you have three values in two arguments. That’s a pattern I use quite a bit.

roelofw21:11:38

oke, then we could have : (fn [s n] (reduce (fn [[ acc output] n] ........ )

roelofw21:11:40

where acc could be the counter, output the output and n the current item

dpsutton21:11:08

ok. so finish the function

dpsutton21:11:18

but realize you have two n's

dpsutton21:11:29

let's use x for your inner n

roelofw21:11:40

oke, I will change that

dpsutton21:11:11

if acc == n, return [0 output] else [(acc + 1) (conj output x)]

dpsutton21:11:18

there's the logic right?

dpsutton21:11:33

if our counter has reached the top, don't conj, otherwise conj and increases the counter?

dpsutton21:11:53

now make that lisp style rather than whatever pseudo junk i just wrote

roelofw21:11:07

⁠⁠⁠⁠(fn [s n] (reduce (fn [[ acc output] x]  (if (= acc n  ) [ 0 output] [ (+ acc 1) (conj output x)] ))))

dpsutton21:11:31

does that work in your repl?

roelofw21:11:44

if I have all the parenteses right

dpsutton21:11:59

type it in your repl. it'll keep your parens straight

seancorfield21:11:38

(you’re missing an argument to reduce)

roelofw21:11:50

nope, I see this error message :

CompilerException java.lang.RuntimeException: Unable to resolve symbol: ⁠⁠⁠⁠⁠⁠⁠⁠ in this context, compiling:(C:\Users\rwobb\AppData\Local\Temp\form-init842216484282399039.clj:1:714) 

roelofw21:11:57

I found that already

roelofw21:11:35

I have now this :

⁠⁠⁠⁠⁠⁠⁠⁠(fn [s n] (reduce (fn [[ acc output] x] (if (= acc n ) [ 0 output] [ (+ acc 1) (conj output x)] )) s )) 

dpsutton21:11:49

you're going to want to give it an initial form for the reduction

roelofw21:11:05

of course , stupid of me

dpsutton21:11:41

you're also gonna need to figure out if we should use 0 based counting or 1 based counting

roelofw21:11:03

This seems to be compiling : '(fn [s n] (reduce (fn [[ acc output] x] (if (= acc n ) [ 0 output] [ (+ acc 1) (conj output x)] )) [] s )) `

roelofw21:11:29

but my feeling says I need to have a initial value for acc

dpsutton21:11:11

yes absolutely

dpsutton21:11:50

we gave it the more complicated first parameter that it is destructuring. its also gonna look at the acc thing first.

roelofw21:11:31

I changed the [] to [ 0 [] ] but no compile errors

dpsutton21:11:17

does it work?

roelofw21:11:06

no, I mean I see compile errors when doing this :

(fn [s n] (reduce (fn [[ acc output] x] (if (= acc n ) [ 0 output] [ (+ acc 1) (conj output x)] )) [ 0 [] ]   s ))  

roelofw21:11:55

wierd, I closed my repl and now no errors so it compiles

roelofw21:11:03

now a test if its working

roelofw21:11:46

and it does not work. I see this as output [2 [1 2 3 5 6]] instead of '( 1 2 4 5)`

dpsutton21:11:08

ok. so how do you fix it

roelofw21:11:17

When I change the zero as initial value with 1 , it's looking better , I see then [3 [1 2 4 5 6]]

dpsutton21:11:31

awesome. but why is the 6 in there

roelofw21:11:44

so I have to change the if then , to a modulo 3 , I think

dpsutton21:11:42

no we are already moduloing basically

dpsutton21:11:01

make sure you don't reset it to 0 but to 1

dpsutton21:11:10

if we are making 1 the initial value

roelofw21:11:20

yes, the part [ 0 output has to be changed to [ 1 output]

roelofw21:11:44

then I see [1 [1 2 4 5]]

roelofw21:11:24

so we still need to use last to get only the [ 1 2 4 5 ]

dpsutton21:11:31

so know, in the toplevel defun, just return that

dpsutton21:11:37

you can figure it out from here

dpsutton21:11:52

maybe use a let binding in the outermost function,

dpsutton21:11:06

or just return (second (reduce...

roelofw21:11:09

Nope , when I do ( (fn [s n] (last(reduce (fn [[ acc output] x] (if (= acc n ) [ output] [ (+ acc 1) (conj output x)] )) [ 0 [] ] s))) '( 1 2 3 4 5 6 ) 3) . I see this error : ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:128)

roelofw21:11:19

so last is not a good choice

roelofw21:11:33

Thanks both , I will take a break

dpsutton21:11:45

you broke it

dpsutton21:11:49

i see [ output]

dpsutton21:11:51

that is wrong

roelofw21:11:52

and goto bed . It's late here

dpsutton21:11:17

you added last but broke your reduction function

dpsutton21:11:27

and reverted back to using 0 for the intial value??

roelofw21:11:09

yes. I saw it

roelofw21:11:19

it works now well

roelofw21:11:33

many thanks for the explanation and the patience with me

roelofw21:11:29

this was hard to get but many thanks learned

roelofw21:11:54

if you both do not mind, im going to bed, It's 22.35 here

roelofw21:11:09

and tommorow a very busy day

roelofw21:11:36

At the later point. I like to learn how to make this work without a counter

roelofw21:11:59

again many and many thanks