Fork me on GitHub
#beginners
<
2023-02-23
>
M J11:02:17

Hey, I have this list called multi-select-items:

({:deleted_at nil, :value Market Research, :label A. Market Research, :id 27554, :order 0} {:deleted_at nil, :value User Interviews, :label B. User Interviews, :id 27555, :order 1})
I have this set called selections:
#{27554}
I need a function that removes or adds the id from selections based on :label 's first letter. So for example, when I check if the condition "= A", it removes or adds id 27554 from selections

tomd12:02:17

something like this?

(defn remove-A-selection [multi-select-items selections]
  (reduce (fn [sels {:keys [label id]}]
            (if (re-find #"^A" label)
              (if (contains? sels id)
                (disj sels id)
                (conj sels id))
              sels))
          selections
          multi-select-items))

Markus11:02:33

Hello again! I’m trying to pass a function as a variable to a record, because I want to call it later from another namespace (the record represents some basic config variables/functions, which are needed in many places of my program). The problem is, that after destructuring the record, my function is always an unbound variable. I then experimented with records, where I can easily insert a function and call it later like this:

(defrecord hello-record [hello])

(defn hello [] (println "Hello"))

(def my-record (->hello-record hello))

(defn execute-hello [{:keys [hello]}]
  (hello))

(execute-hello my-record)
;; Hello
I assume the problem is my use of declare:
(defrecord hello-record [hello])

(declare hello)

(def my-record (->hello-record hello))

(defn hello [] (println "Hello"))

(defn execute-hello [{:keys [hello]}]
  (hello))

(execute-hello my-record)
;; Execution error (IllegalStateException) at user/execute-hello.
;; Attempting to call unbound fn: #'user/hello
Can I solve this without moving my record to the bottom of the file?

Markus11:02:23

Found the solution to my own question by digging for more resources on declare. To avoid binding the unresolved hello function to the record, the function has to be inserted like this:

(def my-record (->hello-record #'hello))
Maybe someone is able to better explain what exactly this change does, but at least it should solve this type of issue.

Markus11:02:15

@U04V4KLKC So this essentially means, that without #' the value of hello is read, which at this point in time is unbound. If I now use #' it references the object hello which can be later resolved to its correct value?

delaguardo11:02:44

so the difference is hello give you the value known at the time, and #'hello gives you var object

Markus11:02:11

Thanks a lot for the explanation!

Ben Sless11:02:15

Clojure has call-by-value semantics and the unit of compilation is a specific form, not file or module. This is why you captured the unbound value of hello

Hans Lux15:02:18

Confusion about keywords, maps and threading opertors In a conversation with @didibus I came across his prefered way of retrieving values from a map using keywords. > Another (beginners) question that came up while studying > @didibus > ddd example was why you use the threading operator to access a map by key like (-> account :number) instead of (account :number) or even (:number account)? > Is that a matter of taste, a certain style or a hint to the compiler ? His answer was: > Just a matter of taste. If you needed to get something nested it extends to (-> account :number :value) by just adding more keys. And it works equally for Java interop: (-> javaObject .getSomething .getSomethingElse) > (-> account :number) is the same as (:number account) , the former expands into the latter, and they'll behave the same. That said, (account :number) is different, in that it will throw in the case account is nil. The others will return nil instead. I adopted that style, because I find it nice and readble. But today I stumbled across something that surprised me, when I "nested" this way of reaching into a map. Here is what I found:

(def map-a
  {::name "name"})
(def map-b
  {::key-to-use ::name})
  
(map-a ::name)
;=> "name"

(map-a (map-b ::key-to-use))
;=> "name"

(map-a (-> map-b ::key-to-use))
;=> "name"

(-> map-a ::name)
;=> "name"

(-> map-a (map-b ::key-to-use))
;=> :user/key-to-use

(-> map-a (-> map-b ::key-to-use))  
=> nil
I can't really see why that happens. There is probably something I don't know about maps or keys or the threading operator.

dpsutton15:02:40

user=> (macroexpand '(-> map-a (-> map-b ::key-to-use)) )
(:user/key-to-use (map-b map-a))

dpsutton15:02:13

and a single step:

user=> (macroexpand-1 '(-> map-a (-> map-b ::key-to-use)) )
(-> map-a map-b :user/key-to-use)

delaguardo15:02:08

Worth mentioning that -> is not an operator but, as @U11BV7MTK pointed out, is a macro.

Hans Lux15:02:38

thanks for the response. So it was (at leas) the threading macro, that I hadn't understood properly. I should also get used to using macroexpand, I guess.

pppaul20:02:30

mocreexpand is a very important debug tool in lisp. it takes away all the magic

Matthew Twomey17:02:21

This should be easy - but I can’t quite get it: How do I do what I mean here? (update-in {:numbers ["one" "two" "three"]} [:numbers] remove "one")

delaguardo17:02:47

(update-in {:numbers ["one" "two" "three"]} [:numbers] #(filter (fn [x] (not= x "one")) %))

daveliepmann17:02:53

(update {:numbers ["one" "two" "three"]}
        :numbers
        (partial remove #{"one"}))

👀 2
👍 4
Ed18:02:12

If you care about it being a vector when you've finished you may want to (update {:numbers ["one" "two" "three"]} :numbers (partial filterv (compliment #{"one"})))

stantheman15:02:24

Or you could pull the work on the value that is a col to a fn?

Arya S20:02:30

Hi! I'm pretty new to Clojure and been experimenting for a few weeks now. I might have the opportunity to build a mobile app using clojure and having trouble understanding the landscape. I'm considering React Native and Expo, but one of my concerns is that we'll just have to eject from Expo and give up the advantages we were trying to win by using it. Specifically, I want to use background GPS on iOS and android. Anyone knowledgable in this or have recommended reading?

kennytilton20:02:01

Sorry, I have nothing to offer (ClojureDart/Flutter guy), just thought I would check to see if you knew about #C0E1SN0NM. Good group, from my early days on CLJS+RN. hth.

👀 2
Arya S21:02:44

Thanks yes it does help!

Bobbi Towers20:02:27

I was going to suggest ClojureDart. I haven't tried it but if I were making a mobile app I'd definitely consider it

👍 2
kennytilton22:02:06

I built this https://github.com/kennytilton/flutter-mx and, based on that experience, I would go with CLJD/Flutter, as well. The OO orientation is a bit off-putting, but its future seems bright. Worth considering. The #clojuredart lads have done a fine job, too.

Ian22:02:06

Hiya, I’d used Clojure for over a year a few years back, but trying to get back into it… I’m on OSX, trying to get lein repl working, but its erroring:

my-project.core=> (1 2 +)
Execution error (ClassCastException) at my-project.core/eval2428 (form-init1896655737463139813.clj:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')

Ian22:02:44

Installed via brew install leiningen Also brew install clojure/tools/clojure (but I’d prefer to use asdf)

Ed22:02:04

Try typing (+ 1 2). The verb comes first in lisps.

Ed22:02:06

The cryptic error message is trying to say that it can't call 1 as a function.

Ian22:02:54

omg, I really have forgotten it all, that works, many thanks!

elken22:02:47

You also don't really need lein anymore, clojure comes with it's own way to manage project and provides a repl 🙂 https://clojure.org/reference/deps_and_cli

Ian22:02:01

yep cheers, just a step towards getting back into it… next to IntelliJ…

🙌 4
Ian22:02:34

Are there any good setup guides to get IntelliJ working? I remember having to get the config right, but I don’t know what

practicalli-johnny22:02:27

The Cursive user guide covers Intellj config and Cursive install https://cursive-ide.com/userguide/ (although I have not used this tool myself) There are also many other editor options https://practical.li/clojure/clojure-editors/

👀 2
2