Fork me on GitHub
#beginners
<
2018-12-06
>
Daouda04:12:02

hey guys, can some one tell me to which function the coll is being passed and how, please?

Daouda04:12:07

(map #(%1 %2) (cycle [inc identity]) [1 2 3 4 5 6 7 8 9 10])

Daouda04:12:34

to map or cycle ?

hiredman05:12:17

there is no "coll" there

hiredman05:12:58

you are mapping the function #(%1 %2) over two sequences, one produced by cycle and one produce by calling seq on the vector [1 2 ...]

Daouda05:12:48

this is not a [1 2 3 4 5 6 7 8 9 10])

hiredman05:12:17

so in the function #(%1 %2) %1 is bound to an item from the first seq (created by cycle) and %2 is bound to an item from the second seq (created from the vector)

Daouda05:12:21

i mean map, vector, list they are not called coll?

Daouda05:12:41

collections?

hiredman05:12:20

you might use an argument coll to indicate a collection is passed in, but if you don't have a binding for the name coll it doesn't mean anything

hiredman05:12:08

user=> (map vector [:a :b] [1 2])
([:a 1] [:b 2])
user=>

Daouda05:12:05

but how does it know that it should go over the next 2 element of the vector and not the same first two element at each call?

hiredman05:12:36

because it doesn't do that

Daouda05:12:16

hehehehehe

hiredman05:12:23

it is written to take the first item from each input and apply the function to them, and then do the same thing again with the rest of each input

hiredman05:12:36

(taking the first of the rest and so on)

Daouda05:12:51

so cycle make it repeat taking two next parameter till finish

hiredman05:12:02

cycle makes it repeat them infinitely

hiredman05:12:17

but map stops mapping one one of the inputs ends

Daouda05:12:19

when does it know it should stop then?

Daouda05:12:37

hummmmmmmmm

Daouda05:12:54

i got it now

Daouda05:12:50

so all this (cycle [inc identity]) [1 2 3 4 5 6 7 8 9 10] is map second argument

Daouda05:12:24

i mean map func arg right?

hiredman05:12:43

have you looked at the doc string for map?

hiredman05:12:05

it takes as many arguments as you pass to it, not just two

hiredman05:12:11

so the function is the first argument, the seq created by cycle is the second, the vector is the third, and so on as many arguments as you want (as long as the function can take that many arguments)

hiredman05:12:11

what is your background, some other functional language?

Daouda05:12:31

just starting with clojure

Daouda05:12:54

only oriented object programming

Daouda05:12:21

so i am re-learning everything

Daouda05:12:26

but it's funny

hiredman05:12:31

ah, I was going to say the ability to take any number of arguments can be kind of confusing if you are used to other functional languages where features like type systems and auto currying might make that not possible

Daouda05:12:58

hehehehehehe

Daouda05:12:23

some others like which one?

hiredman05:12:00

I don't think any ml derivatives or haskell have varargs

hiredman05:12:39

I guess haskell has some way to do it https://wiki.haskell.org/Varargs

Daouda05:12:50

thanks for your explanations

Daouda05:12:00

they helped a lot 🙂

nikola06:12:19

How can I sort desc this list ([\d 9] [\e 17]) by the integer? I get an error that the key must be an integer when I do (sort (fn [[_ int]] int) ([\d 9] [\e 17]))

seancorfield06:12:27

(sort-by second ...)

nikola19:12:04

great, it works, I chose to reverse the list

seancorfield07:12:09

sort accepts a comparator, which is expected to take two arguments and return -1, 0, 1

seancorfield07:12:56

@nikola.kasev ^ does that help?

seancorfield07:12:00

For descending, either reverse the sorted list or use a key-fn like (comp - second)

seancorfield07:12:15

user=> (sort-by (comp - second) '([\d 9] [\e 17]))
([\e 17] [\d 9])
user=>

nam.hyunwoo07:12:09

I'm wondering why transducers are implemented in core namespace. (not like the reducers case.) Could it be complecting things into a single function? It doesn't feel like an usual arity overloading. What's the idea behind this design decision?

peter hull10:12:50

How can I call java.nio.files.Paths.get(String ...) from clojure? https://docs.oracle.com/javase/8/docs/api/java/nio/file/Paths.html#get-java.lang.String-java.lang.String...- If I try (Paths/get "file") or (Paths/get (into-array ["file"])), I get a class-cast exception ("cannot be cast to java.net.URI"), which is a different overload of that function.

mping10:12:52

@peterhull90 can you try (Paths/get (into-array String ["file"])) ? I think it needs a hint

peter hull10:12:35

I still get "[Ljava.lang.String; cannot be cast to java.net.URI"

peter hull10:12:22

So it is the right type ([Ljava.lang.String = array of string) but selecting the wrong overload.

schmee10:12:57

@peterhull90 you need (Paths/get "file" (into-array String []))

schmee10:12:51

the signature is get(String first, String... more) so the first arg needs to be a string, not a string array

peter hull10:12:02

@schmee Works! Thanks. I now have

(defn make-path [part & parts]
  (Paths/get part (into-array String parts)))

mseddon11:12:23

who/what is cljsjs-robot on clojars, and how can I encourage them to publish a later npm package?

mseddon12:12:03

Great, thanks!

grierson12:12:17

How do I sort a coll of maps with a {:datetime clj-time-value}?

schmee12:12:51

(sort-by :datetime coll)?

grierson12:12:55

doh, you are right. Thanks.

Ian Fernandez12:12:20

Guys I want to use a lib to hash some passwords with bcrypt, there's a recommendation?

mseddon13:12:40

hmm. is there a way to extract source position information within a macro to report error messages?

mseddon13:12:25

I have a DSL here that definitely could use more than 'something screwed up, here is the offending s-expr'

mseddon13:12:57

I looked at the metadata but it seems to be nil...

restenb15:12:20

so I have a list of filenames and a list of data. i want to filter out the unique filenames, and at the same time filter out the corresponding data in that list. is there a nice way of doing this?

restenb15:12:09

imagine something like (def filenames ["apples" "oranges" "apples" "oranges"]) with (def data [[1 2 3] [3 2 1] [1 2 3] [3 2 1]]).

restenb15:12:22

i can get the unique filenames, f.ex. (set filenames) which gives #{"apples" "oranges"}, but that doesn't necessarily help me filter out the duplicates from data

andy.fingerhut15:12:34

If you create a sequence of maps from filenames and data that looks like this: [{:filename "apples" :data [1 2 3]} {:filename "oranges" :data [3 2 1]} ... ]} then one way to get one step closer would be (group-by :filename filenames-and-data), then take the first element of each value (or whichever one you prefer).

andy.fingerhut15:12:22

e.g. step 1: (def filenames-and-data (map (fn [fname d] {:filename fname :data d}) filenames data))

andy.fingerhut15:12:34

step 2: (def g (group-by :filename filenames-and-data))

andy.fingerhut15:12:32

step 3: (def uniqed (map (fn [[k v]] (first v)) g))

andy.fingerhut15:12:36

I am sure, given my semi-low-sleep state, that there are even nicer-looking or more concise versions of some of those things.

restenb15:12:32

thanks, it works though

enforser15:12:22

@restenb is data unique per instance of filenames, or will any repeated filename have the exact same data?

restenb15:12:02

they can easily have the same data too, yes

restenb15:12:36

i also can't trust the order of the filenames, but i just want to keep those that are unique with their associated data

restenb15:12:54

so the above solution by @andy.fingerhut seems robust

enforser15:12:06

(def filenames ["apples" "oranges" "apples" "oranges"])
(def data [[1 2 3] [3 2 1] [1 2 3] [4 6 7]])

;; if each filename has a unique data set
(reduce-kv assoc
           {}
           (zipmap filenames data))

(def filenames ["apples" "oranges" "apples" "oranges"])
(def data [[1 2 3] [3 2 1] [1 2 3] [4 6 7]])

;; if each filename can have multiple different data sets
(reduce-kv (fn [m k v]
             (update m 
                     k
                     (fnil conj #{})
                     v))
           {}
           (zipmap filenames data))
maybe something like that?

restenb15:12:09

that's actually pretty sweet 🙂

restenb15:12:44

can just get the lists of filenames & data by map first and map second after, no need to involve extra keywords

enforser15:12:24

or with keys and vals! Just keep in mind that associating stuff in a map like this doesn't preserve order

restenb15:12:14

order isn't an issue here though, only uniqueness

restenb15:12:46

just threw this into our production app and tested it (with much larger dataset), works like a charm! thanks

Logan Powell15:12:59

Is there a "shallow" way to turn a clojurescript seq/coll into a javascript array? I'm trying into-array but the performance seems super bad for large collections/seqs of javascript objects...

Logan Powell15:12:41

perhaps it's not as bad as I'm thinking.. does prn take longer to print #js... stuff?

enforser17:12:08

I'm wondering why something like this blocks when I try to add two values to init-chan but not when I only add one. I would have thought each value would comes through the pipeline when added.

(defn make-go-loop
  [in-chan]
  (let [out-chan (chan 1)]
    (a/go-loop []
      (a/>! out-chan (a/<! in-chan)))
    out-chan))

(let [init-chan (chan 1)]
  (-> make-go-loop ;; a go-loop pipeline. Simply starts a go-loop which reads
      make-go-loop ;; values from channels then sends them to the next one.
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop
      make-go-loop)
  (>!! init-chan true)
  (>!! init-chan true))

hiredman17:12:28

because you aren't looping

enforser17:12:49

right, I just noticed that - not looping and I need to pass init-chan as the first argument to the threading - but it still blocks

hiredman17:12:01

you never read from the out-chan at the end

enforser17:12:13

right, but considering I have a channel per go-loop, then I would have thought I fill all of those channels before I'd hit a blocking put

hiredman17:12:22

I suspect (because the example you pasted is so full of issues) that you are attempting to share a simplified example of some more complicated code

enforser17:12:44

(defn make-go-loop
  [in-chan]
  (let [out-chan (chan 1)]
    (a/go-loop []
      (a/>! out-chan (a/<! in-chan))
      (recur))
    out-chan))

;; this blocks
(let [init-chan (chan 1)
      pipeline-chan (-> init-chan
                        make-go-loop)]
  (a/>!! init-chan :value)
  (prn (a/<!! pipeline-chan)))

;; this doesn't block
(let [init-chan (chan 1)
      pipeline-chan (-> init-chan
                        #_make-go-loop)]
  (a/>!! init-chan :value)
  (prn (a/<!! pipeline-chan)))

hiredman17:12:45

so who knows what issues that more complicated code has

enforser17:12:10

right, yeah - I am. I think I've fixed up the example now such that it should work.

enforser17:12:10

so I think the issue is with the go-loop, but I'm not entirely sure why it would be blocking, since it's literally just taking from a channel, then placing on another channel.

hiredman17:12:35

have you actually run the example? (I ask because in some places names from core.async are prefixed with a/ and in other places they are not)

enforser17:12:04

yeah, in my namespace I did a :refer :all then :as a, which is why they are a little all over the place.

hiredman17:12:29

neither of those blocks

enforser17:12:01

it is for me. That's weird.

hiredman17:12:38

have you had a repl open for a long time playing with core.async code?

enforser17:12:42

ah, restarted my REPL and it worked facepalm

hiredman17:12:41

my guess is you launched some go blocks at some point that blocked, and ended up launching enough of them that it completely stalled the executor that runs go blocks, so any go code stopped running

Daouda17:12:03

Advent to code in clojure by @potetm here: https://www.twitch.tv/timpote

enforser17:12:17

yep, my bad. Thanks for your help @hiredman

xonar18:12:06

Hi, any idea why this isn't summing numbers read from file?

xonar18:12:08

(clojure.core/reduce + (clojure.core/map int (clojure.string/split-lines (slurp "../../resources/adv1.txt"))))

xonar18:12:54

I get ClassCastException: java.lang.String cannot be cast to java.lang.Character instead

alexmiller18:12:32

I don’t think mapping int is what you want

alexmiller18:12:45

that’s trying to coerce a string to an int, which is not a thing

xonar18:12:59

what else can I use to parse string to int?

alexmiller18:12:59

you could simply count the output of split-lines

alexmiller18:12:09

oh, you’re trying to parse there

alexmiller18:12:27

use #(Integer/parseInt %)

alexmiller18:12:35

instead of int

jaihindhreddy18:12:43

or #(Integer. %)

alexmiller18:12:44

or #(Long/parseLong %)

alexmiller18:12:50

don’t use the Integer constructor

jaihindhreddy18:12:19

unnecessary boxing?

alexmiller18:12:20

many static analyzers will warn on this

alexmiller18:12:32

no, Integer (and Long I think) have caches around 0

alexmiller18:12:43

and latest JVMs actually special case all this stuff for performance

alexmiller18:12:02

you should always use the static factory methods rather than the constructors

xonar18:12:31

thanks! it worked

orestis18:12:06

I know it’s super low priority, but would you consider adding something parse-int etc? Would make cross platform code a little bit easier.

alexmiller19:12:33

Would consider

orestis19:12:54

I’ll file an issue :) Thanks!

orestis18:12:56

It’s a nice wtf moment for a newcomer, and probably their first (forced) Java Interop. It was for me :)

orestis18:12:55

Also the fact that you can’t map Integer/parseInt

jaihindhreddy18:12:31

^ This one got me a couple times 🙂

orestis18:12:16

Hm, searching Jira doesn’t show anything.

xonar18:12:09

so we can't use functions directly from Java jdk even if they match required signature?

orestis18:12:49

Static functions I think. You need to wrap them in an anonymous fn

xonar18:12:13

took me a while to realize that was an anonymous function 😛

noisesmith18:12:26

to be pedantically specific, methods are not functions, a function is an object you can call (it will have an invoke method), a method isn't a "thing" on it's own (though there are various mechanisms for representing one, like methodhandles etc.)

noisesmith18:12:17

(on the JVM that is)

rivas19:12:39

Hello everyone, I have a really silly question: how do I put newline characters into a string? If I write (str "string1" "\n" "string2"), for example, it will return "string1\nstring2", which is not what I want.

alexmiller20:12:05

I think that is what you want - it’s a string with newline characters in it

victorb20:12:45

yeah, (println (str "hello" "\n" "world")) works

rivas20:12:49

oh, is this an emacs issue

victorb20:12:00

it's just that it doens't show the newline unless printed somewhere I guess

rivas20:12:08

okay, thank you!

rivas20:12:22

I assumed it was automatically escaping it, or something odd like that

Joseph Hance21:12:06

Question about order of recursive execution in Clojure. The order that the recursion happens is not clear to me. Say I have this:

(def nested '(0 1 (11 12 (121 122) 13) 2 3))
(defn trv [v] (map #(if (list? %) (trv %) (println %)) v))
(trv nested)
I get the following as output:
0
1
2
11
12
13
121
122
3
But instead of this I want it to descend into the nested elements when they are encountered vs. after doing (mostly) everything at the same level. So I want to get this output:
0
1
11
12
121
122
13
2
3

enforser21:12:09

I believe that every recursive call to trv returns a lazy sequence, which isn't actually evaluated until it needs to be. Putting side effects in lazy sequences can be misleading

lispyclouds21:12:41

@joseph.hance you can try (defn trv [v] (doseq [e v] (if (list? e) (trv e) (println e))))

enforser21:12:51

if you wrap (map ...) in (doall (map ...)), then I'd expect it should work as you expect

enforser21:12:30

or if you don't care about the results, just the printing, then run! instead of map

alexmiller21:12:03

just fyi in case you’re not aware of it, you’re kind of reinventing tree-seq

Joseph Hance22:12:43

@alexmiller I'm not aware of it. As you know the Clojure vocabulary is fairly extensive. I'll look that up, thanks!

jstaab23:12:15

Hey all, so I'm trying something a little weird, and it's not working as expected. In clojure, as far as I know, functions are just values, which means you can e.g. use them as keys to maps, (defn x [] 1) ({x 1} x) ;; => 1. However, I can't use them as case matches, e.g. (case x x 1), which ought to be tautological, throws an error. Is this a bug? http://cljs.github.io/api/cljs.core/case doesn't say anything about not matching functions, but it does say it requires "constant expressions". Since functions are just bound to vars in my case, they would seem to me to qualify. For what it's worth, this is consistent between clojure and clojurescript.

dpsutton23:12:47

> The test-constants are not evaluated. They must be compile-time literals, and need not be quoted.

dpsutton23:12:14

from (doc case)

jstaab23:12:47

Yeah, I saw that. Maybe I'm confusing symbols with literals. So they have to be primitives, rather than just share a name?

noisesmith23:12:26

if you provide a symbol in a case clause on the left side, it matches that symbol

noisesmith23:12:32

not the thing the symbol resolves too

hiredman23:12:52

you can imagine case as automatically quoting the cases

jstaab23:12:01

Ooh so (case 'x x 1) works

jstaab23:12:55

Still not sure I 100% understand buuuuuut works for me

hiredman23:12:24

symbols are almost never literal symbols

hiredman23:12:43

they are almost always a binding of a name to a value

dpsutton23:12:04

(case 'inc inc 1) isn't matching the function inc but just the literal symbol inc (just to make the point clear). it is not pairing the function

noisesmith23:12:09

this is also a rare exception to the normal rules about what parens do

noisesmith23:12:33

user=> (case 1 (inc 1) :a :no-match)
:a

jstaab23:12:44

Yeah, just tried that in context and it still blew up because I had re-bound the function. So I guess in this case matching the symbol isn't helpful, because it's always tautological

hiredman23:12:09

(case 'quote 'x 1)

noisesmith23:12:39

yeah, I wouldn't expect case-matching a function to ever be useful, but cond can do it, it's just a little noisier code wise and slightly less fast dispatch

jstaab23:12:58

Yeah, that's the direction I'm going

dpsutton23:12:09

(let [x inc] (case x inc :found :not-found)) etc