Fork me on GitHub
#beginners
<
2022-12-09
>
slk50014:12:34

; somebody please explain me what's happening here: (= #(reverse %) '(1 1)) ; => false ; I was thinking it will eval to (= 1 1) (= 1 1) ; => true ; but (= #(reverse %) '(1 1)) ; => false ; or it will eval to (= nil '(1 1)) ???

Ed14:12:38

The function #(reverese %) is not equal to the list '(1 1)

👍 2
dumrat14:12:42

Did you mean (apply = (#(reverse %) '(1 1))) ? Because what your code is doing is comparing equality between a function and a list

slk50015:12:59

oh! now I get it, I compering function to list

slk50015:12:30

another question: ;; why comparing operator is allowed with only one args? (= 3) ;=> true (= nil) ;=> true (= false) ;=> true (=) ;=> ArtityException wrong number of arguments

slk50015:12:35

to make a partial form ? and add some args later ?

dumrat15:12:39

I think this question was asked yesterday somewhere also. Answer was: Probably to play well with apply i.e. (apply = [1 2 3]) (apply = [1]) Thought the 0 arg case is troublesome

dumrat15:12:56

You sometimes get situations where you want to do something like this: (filter (partial apply =) [[1 2] [5 5] [2 3]]) ;=> [5 5]

Jim Newton15:12:49

I’m looking at the clojure doc for reify. I don’t see the sentence that says what the function does. just lots of text about how to call it. Am I missing something?

dpsutton15:12:57

first sentence sums it up to me > reify creates an object implementing a protocol or interface.

Jim Newton15:12:57

reify is a macro with the following structure:
this is the first sentence that I see.

Jim Newton15:12:45

I think the http://clojuredocs.org text is missing some lines.

Jim Newton15:12:50

could that be true?

dpsutton15:12:57

looks like alex clarified your exact confusion recently and the clojuredocs site hasn’t updated https://github.com/clojure/clojure/commit/e1220832d900745727cf5a1b69f4a6cd664f1443

1
Jim Newton15:12:59

so does reify create a singleton object which for which the named function can be called with it as an argument?

dpsutton15:12:12

singleton usually means a globally unique single. And “named function” seems to imply only one. This returns an anonymous instance of an object that implements any number of protocols and interfaces you want.

dpsutton15:12:41

match=> (let [r (reify
          Object
          (toString [_] "custom str implementation")
          clojure.lang.Seqable
          (seq [_] (seq [:custom :seq :implementation])))]
  [(str r) (seq r)])
["custom str implementation" (:custom :seq :implementation)]

dpsutton15:12:21

so instead of singleton i’d say “one off” or anonymous. and instead of “the named function” i’d say any number of functions defined in protocols or interfaces

Alex Miller (Clojure team)17:12:57

I mean, technically it does return a globally unique instance, so singleton is not wrong. But singleton (as an oo pattern) often implies something about global state, which is not the case here, so not in that sense

👍 1
Jim Newton10:12:41

aren’t all objects anonymous?

Jim Newton10:12:12

what does singleton normally apply about global state? For me a singleton object is an instance of a class for which there is no other instance of that class. is no other can be enforced by the programming language, or might be simply enforced by the programming conventions.

dpsutton13:12:29

Fair enough. It is a singleton I suppose. You are correct

dpsutton13:12:27

For anonymity, most classes have a name that is accessible to the programmer. These do have a name that you could get but the instance itself is the usual way to interact with it and use

Piotr Kaznowski16:12:04

Given a list of functions and a list of arguments, is there a simple way to return a list with results of evaluation of first function with first arg, second func with second arg, etc.? Like:

(XXX [inc dec] [1 9]) => [2 8]
Feels like sth trivial but can't figure it out...

dumrat16:12:53

(map (fn [f v] (f v)) [inc dec] [1 9])

😁 1
Ed16:12:56

maybe something like

(map (fn [f a] (f a)) [inc dec] [1 9])
?

😂 1
Piotr Kaznowski16:12:15

OK, thanks, though there would be something even simpler 😛

R.A. Porter16:12:20

You could use an anonymous function to shorten it a little (map #(%1 %2) [inc dec] [1 9])

👍 1
Ed17:12:04

the (fn [x] ,,,) form is just as anonymous as the #(,,,) form. They are both unnamed functions. The latter is a reader macro that expands into the equivalent form

(read-string "#(+ 1 %)") ;; => (fn* [p1__24938#] (+ 1 p1__24938#))
it's a shorthand for the same thing : https://clojure.org/reference/reader#_dispatch

1
stantheman18:12:01

I went on a different tack and made a function that deals with unknown number of fn's and args pairs. Also I made it extra lazy...

skylize22:12:41

The answer given twice already would provide a much simpler signature than your fargs-pairs. It equally allows for an unknown count of fns and args. And map is already lazy.

(defn map-application [fs xs]
  (map (fn [f x] (f x)) fs xs))

(map-application [inc dec str #(* 10 %)] [1 9 5 -3])
; => (2 8 "5" -30)
Yes, you lose the opportunity to check for fn?. But this is likely not a great idea anyway. because idiomatic Clojure is full of "function calls" where you don't actually have a real function in hand. E.g. You will find (:some-key some-map) everywhere you look, but (fn? :some-key), not surprisingly, returns false. I know I would be super frustrated if I was trying to write code against your function, and found keywords were getting dropped as a "no-op".

dumrat05:12:30

@U90R0EPHA aside, is there a function that returns if you can call something? i.e.

(callable? (fn [])) ;=> true
(callable? :key) ;=> true
(callable? {}) ;=> true
(callable? #{}) ;=> true
etc>

Sam Ritchie05:12:24

Yes, it’s ifn?

👍 1
skylize06:12:59

And if you really wanted to check that, it still does not require describing your own recursion semantics. Just stick it inside the map function.

(defn map-application [fs xs]
  (map (fn [f x] (if (ifn? f)
                   (f x)
                   (prn {:noop true :f f :x x})))
       fs xs))

dumrat18:12:34

So, I've started to use integrant a few days back. Previously I had atoms peppered all over my files. I define the config and all the init-key and halt-key! methods in a single file right now. Was ok so far but now the config has 11 keys and keeps growing. Now I'm wondering if it's a good idea to put the methods close to their sources instead of a single central file. What's the received wisdom on this?

practicalli-johnny18:12:22

My own preference is to have a single resources/config.edn file with all the keys. Then initialise / halt all the services in a practicalli.service-name.service namespace which also has a -main that starts / shutdowns all the services If also using aero, then I move the areo-reader parts into their own namespace and require that from service.

👍 1
1
didibus19:12:00

You can also look into using Aero with Redelay: • https://github.com/aroemers/redelayhttps://github.com/juxt/aero You can define your state in a "redelay", which will feel similar to what you were doing with Atom, but will be much better because it does lifecycle start/stop/reset. And you put your configuration in Aero.

emccue19:12:33

I prefer very, very, very strongly to have a single system.clj

emccue19:12:00

What are your 11 keys?

dumrat20:12:48

@U3JH98J4R Please correct me I'm wrong, I've just put the entire system state there 😄 Here's the list (This is typed, not copy pasted so maybe typos):

{:adapter/jetty {:port 8080 :join? false :allow-null-path-info true :handler (ig/ref :handler/main)}
 :timbre/start nil
 :handler/main {:sockets (ig/ref :user/websockets)}
 :solace/message-receiver {:message-service (ig/ref :solace/message-service) :message-queue (ig/ref :publisher/message-queue)}
 :solace/message-service {:props (ig/ref :solace/connection-properties)}
 :solace/connection-properties nil
 :publisher/message-queue nil
 :publisher/instance {:message-queue (ig/ref :publisher/message-queue) :sockets (ig/ref :user/websockets)}
 :user/websockets nil
 :db/conn nil
 :views/filter {:dbconn (ig/ref :db/conn)}
}

dumrat20:12:02

Right now it looks like the single atom in re-frame. All the state in a single place. But I'm beginning to worry this might not be how it's intended to be used 😄

dumrat20:12:35

btw, why so many system libraries in Clojure?

emccue20:12:51

its a nerd snipe - i just wrote this whole thing on it

emccue20:12:20

I think this will feel a lot better if you just use a consistent prefix for the keys

emccue20:12:45

i.e. instead of :db/conn :views/filter etc - have all the stuff as example.system/conn, example.system/filter

👍 1
emccue20:12:01

and just use the :: syntax in your one file

emccue20:12:46

so ::conn ::filter (or ::view-filter wtvr)

dumrat20:12:21

@U3JH98J4R actually that’s what I had at first. Then I read the examples in integrant doc and gave everything different prefixes. 😆

emccue20:12:40

you can also, to be clear, not use integrant and still not have atoms peppered across your code

emccue20:12:32

integrant is doing two things • Automating the wiring code for starting the system and stopping the system • Giving a foundation for automating the repl workflow

emccue20:12:49

you can always just write that code out. its not illegal

gratitude 2
Apple21:12:59

(defn move-ordinate [head-ord tail-ord]
  (condp apply [head-ord tail-ord] = tail-ord
                                   < (dec tail-ord)
                                   > (inc tail-ord)))
how does this work, the condp and apply part? *-ord are vectors like [0 0] for ordinates

R.A. Porter22:12:56

That’s pretty. It can be interpreted as… Given the vector [head-ord tail-ord], run the following predicate tests and return the value associated with the first true result: • (apply [head-ord tail-ord] =) (are all elements in the vector equal?) • (apply [head-ord tail-ord] <) (is the vector sorted from smallest to largest?) • (apply [head-ord tail-ord] >) (is the vector sorted from largest to smallest?)

Apple22:12:58

now i understand.

Apple22:12:32

(println
    (condp = value
      1 "one"
      2 "two"
      3 "three"
      (str "unexpected value, \"" value \")))
turns into (= 1 value) and not (= value 1)

Apple22:12:02

so the above turns into (apply = [**-ord **-ord])

Apple22:12:04

thx

👍 1
Apple22:12:03

the inc dec part. how is that possible?

Apple22:12:14

doesn't work on vector

Apple22:12:15

nvm. it's x or y

Apple22:12:22

not [x y]

Apple22:12:07

Can this block of code be made nicer?

(->> (map - prev curr)
     (map #({2 1, -2 -1} % 0))
     (map - prev))

Apple22:12:47

prev and curr are vector of ordinates like [x y]

hiredman22:12:20

you likely don't need the negating pass if you swap the order of the initial subtraction

Sam Ritchie05:12:05

If you want a single pass:

(map #({2 1, -2 -1} (- %2 %1) 0)
     prev curr)

Apple05:12:51

(map - prev) not there?