Fork me on GitHub
#beginners
<
2021-08-27
>
stopa03:08:49

Hey team, noob question. Right now, I have a nested data structure of vecs. Example:

[:pair [:symbol "="] [:pair [:symbol "lit"] [:pair [:symbol "clo"] [:pair [:symbol "nil"] [:pair [:symbol "args"] [:pair [:pair [:symbol "if"] [:pair [:pair [:symbol "no"] [:pair [:pair [:symbol "cdr"] [:pair [:symbol "args"] [:symbol "nil"]]] [:symbol "nil"]]] [:pair [:symbol "t"] [:pair [:pair [:symbol "some"] [:pair [:symbol "atom"] [:pair [:symbol "args"] [:symbol "nil"]]]] [:pair [:pair [:symbol "all"] [:pair [:pair [:symbol "fn"] [:pair [:pair [:symbol "_"] [:symbol "nil"]] [:pair [:symbol "id"] [:pair [:symbol "_"] [:pair [:pair [:symbol "car"] [:pair [:symbol "args"] [:symbol "nil"]]] [:symbol "nil"]]]]]] [:pair [:pair [:symbol "cdr"] [:pair [:symbol "args"] [:symbol "nil"]]] [:symbol "nil"]]]] [:pair [:pair [:symbol "and"] [:pair [:pair [:symbol "apply"] [:pair [:symbol "="] [:pair [:pair [:symbol "map"] [:pair [:symbol "car"] [:pair [:symbol "args"] [:symbol "nil"]]]] [:symbol "nil"]]]] [:pair [:pair [:symbol "apply"] [:pair [:symbol "="] [:pair [:pair [:symbol "map"] [:pair [:symbol "cdr"] [:pair [:symbol "args"] [:symbol "nil"]]]] [:symbol "nil"]]]] [:symbol "nil"]]]] [:symbol "nil"]]]]]]] [:symbol "nil"]]]]]]]
Now, is there a way I can pretty print this, to be indented in a readable way? Currently, pprint and println all print in 1 line

adi04:08:46

Hm, I pasted the form in a CIDER REPL. That prints it out with indentation.

adi04:08:53

I feel like clojure.pprint/pprint should also do the same.

stopa04:08:54

This is what I am getting, by typing it in an nrepl, ran via clj :thinking_face:

adi04:08:23

Hmm... It may have to do with REPL middleware. I use leiningen to start REPLs. It prints out fine in terminal as well. I've never used clj so I don't know what the equivalent would be. Ah here's the https://docs.cider.mx/cider/repl/configuration.html#pretty-printing-in-the-repl in CIDER docs. I'm guessing other tools should have options / configurations in a similar vein.

adi04:08:12

Oh wait, clojure.pprint/pprint works fine for me with clj as well! I'm out of guesses right now.

Esteban León Soto07:08:57

pretty printin in Repls is a setting you can configure. Here a couple of links that might help: https://groups.google.com/g/clojure/c/ydtWuNrq_6I https://clojure.org/guides/repl/data_visualization_at_the_repl these helped me with the same problem a few months back.

stagmoose09:08:37

If I have ([1 0] [2 1] [3 0] [4 1] [5 0] [6 1]) , how can I generate sth like ((1 3 5) (2 4 6)) i.e. group by the second item in the sub-vector. My idea is to create a key-val pair, where key is the second value of sub-vector, and the val is a empty vector. Then add first value of sub-vector to the empty vector in the map accordingly. (glad to hear a better idea) What I am stuck in is how to create that key-val pair in advance.

Martin Půda09:08:46

(->> '([1 0] [2 1] [3 0] [4 1] [5 0] [6 1])
     (group-by second)
     (map val)
     (map #(map first %)))

felipebarros14:09:54

An alternative using for to make it more readable:

(let [example '([1 0] [2 1] [3 0] [4 1] [5 0] [6 1])
      groups (vals (group-by second example))]
  (for [group groups]
     (map first group)))

🔥 2
finchharold09:08:39

Hi all, how to check if with multiple values?

finchharold09:08:23

Running a func with if and that function is having many args

👌 8
Ed09:08:56

So arg is a list of arguments?

Ed09:08:02

Then (apply function arg)

finchharold09:08:36

(if (apply function arg) ....)?

Ed09:08:56

That's the same as writing (function arg1 arg2 arg3 ...)

finchharold10:08:25

No I mean if the arg has the list of values

finchharold09:08:09

(If (function arg) (do this) (do that)) and arg can be 2, 3, 4...

finchharold09:08:23

So, it should take each and return the result for each

delaguardo09:08:58

isn’t this a case for map?

(map #(if (function %) (do this) (do that)) '(2 3 4 ...))

finchharold10:08:39

Not multiple args

finchharold10:08:49

arg which is having multiple elements as it's value

delaguardo10:08:23

ok, what the function is doing?

finchharold10:08:43

arg1 = (1 2 3) arg2= 4 (if (function arg1 arg2) (do this) (do that))

finchharold10:08:34

that function returns true or false based on the arg values

finchharold10:08:52

This function should execute for each value of arg and return for same

CarnunMP10:08:41

(function arg1 arg2 ... argn) is a function of n arguments. It returns once. Those arguments might be lists: (x1 y1 ...), (x2 y2 ...), etc. In which case the function would have to work on (multiple) lists. But it sounds like what you want is a function which takes a single list argument. Something like (function '(x1 y1 ...))? So (if (function '(x1 y1 ...)) (do this) (do that))?

alpox11:08:40

Maybe (every? function '(arg1 arg2))?

finchharold12:08:55

The situation is to run an if condition with a function and make multiple calls to that function? Example code where arg1 (1 2 3) arg2 (1)

(if (function arg1 arg2)
   (perform addition)
   (perform subtraction))
It has to execute for arg1 1 and arg2 1, again execute for arg1 2 and arg2 1, and finally for arg1 3 and arg2 1.

schmee12:08:50

what should be the return value? if you want a vector of values for each value of arg1, use map. if you want to add everything into a single result, use reduce

ade12:08:23

i quite didn't grasp what is the problem ó.ó

delaguardo12:08:50

look at the map function

(map #(if (function % arg2) (perform addition) (perform substraction)) arg1)
map will iterate over every item in arg1 and execute if expression

Edward Ciafardini13:08:39

From the core library - could someone explain the difference between the "name" and "identity" functions in practical terms?

sheluchin13:08:57

The name function will return the non-namespace part of a symbol or keyword, or just the argument if the arg is a string. The identity function will return the given value as is. They are not really related.

👍 3
Edward Ciafardini13:08:41

thanks. I was using (doc name) and (doc identity) in the REPL to try to understand it. It's helpful to see examples.

Aviv Kotek14:08:23

hi, i'm trying to write a simple method that will return true iff all given url's are responsive (2xx) my first approach would be using promises with http-kit:

(defn valid-urls? [urls]
  (let [callback (fn [{:keys [status body error]}]
                   (when-not error
                     (<= 200 status 299)))
        futures (doall (map http/get urls (repeat callback)))]
    (every? true? (map deref futures))))
i'm wondering: 1. in the impl above - this means for each url i'm creating a new thread -- is the thread number is limited somehow? couldn't find much on http-kit code 2. what would be the core async approach for such task, assuming i have no http-kit promise-like functionality, but simple sync http get method, maybe a simple go routine that writes to channel then read from that channel by main thread? thx

leif15:08:10

Is there a function to determine if a string is a valid identifier?

leif15:08:39

(Since if I write, say (symbol "hello world") out, I won't be able to read it back in.

leif15:08:35

Even when written out with pr)

leif15:08:49

(At least as far as I can see.)

dpsutton15:08:01

could you assert that (= x (read-string (name x)) something like that?

leif15:08:57

@dpsutton I thought name didn't work on lexical identifiers?

leif15:08:12

Double checking that now though.

leif15:08:58

Oh strange:

cljs.user=> (let [x "blue"]
       #_=>   (= x (cljs.reader/read-string (name x))))
false

leif15:08:56

(Oh wait, i was confusing name with a different function. But ya, still odd that was false.)

leif15:08:37

Oh...woops:

cljs.user=> (let [x 'blue]
       #_=>   (= x (cljs.reader/read-string (name x))))
true

leif15:08:09

And

cljs.user=> (let [x (symbol "hello world")]
       #_=>   (= x (cljs.reader/read-string (name x))))

leif15:08:20

So cool, thanks @dpsutton

dpsutton15:08:38

actually i don't think that works

(let [sym (symbol "a/b/c")]
  (= sym (read-string (str sym))))

leif15:08:16

Eh, in that case it at least throws an exception.

dpsutton15:08:57

it doesn't on the jvm for me

leif15:08:58

So maybe something like:

(defn valid-id? [id]
  (try
    (= (name id) (name (read-string (name id)))))
  (catch ...
     false))

leif16:08:11

Oh, I see.

dpsutton16:08:14

(let [sym (symbol "a/b/c")]
  (read-string (str sym)))
a/b/c

leif16:08:32

(I ran it in cljs. But I see what you mean in vanilla clj.)

leif16:08:53

In cljs:

cljs.user=> (let [sym (symbol "a/b/c")]
       #_=>   (= sym (cljs.reader/read-string (str sym))))
#error {:message "Invalid symbol: a/b/c.", :data {:type :reader-exception, :ex-kind :reader-error}}

leif16:08:14

So it looks like clojure.reader behaves differently in cljs.

olaf23:08:22

What is the best practice to set a default argument with multi-arity and use optional keywords arguments?

;; Code not correct
(defn fullname
  ([lastname & opts]
   (fullname "Mr " lastname opts))
  ([firstname lastname & {:keys [name-title middlename] :or {name-title nil middlename nil}}]
   (str (when name-title (str name-title " "))
        firstname
        (if middlename middlename " ")
        lastname)))

fullname("Potter") ; => Mr Potter
fullname("Albus" "Dumbledore" :name-title "Professor" :middlename "Percival") ; => "Professor Albus Percival Dumbledore"
fullname("Voldemort" :middlename "Lord") ; => Mr Lord Voldemort