This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-08-29
Channels
- # admin-announcements (1)
- # announcements (3)
- # babashka (18)
- # beginners (35)
- # cider (4)
- # clj-kondo (52)
- # cljs-dev (2)
- # clojure (92)
- # clojure-spec (18)
- # clojurescript (17)
- # conjure (11)
- # core-async (1)
- # datomic (11)
- # emacs (5)
- # fulcro (11)
- # graalvm (10)
- # helix (21)
- # kaocha (6)
- # malli (1)
- # membrane (37)
- # off-topic (110)
- # re-frame (1)
- # reagent (12)
- # reitit (5)
- # rewrite-clj (1)
- # sci (1)
- # shadow-cljs (40)
- # vim (21)
- # vrac (17)
(match-list [:one :a] [ :one _ ] "one" [:one :a] "suba" [:one :b] "subb") ; => ("one" "suba") I have above functionality working EXCEPT the underscore _, I'm using <nil> instead, how can I change my function so that the underscore means "anything matches". I take it I need to use a macro. BTW, if this function exists already, let me know, I couldn't find equivalent.
https://github.com/metabase/metabase/blob/master/backend/mbql/src/metabase/mbql/util.clj#L56
yeah, the description of that sounds like what i want, although didn't really "get" the examples. core.match is also very close, but I want to match multiple, I didn't see how I could use that one.
there are tests that show how to use it. it seems like it descends into forms to perform matching at different levels which i didn't expect: https://github.com/metabase/metabase/blob/master/backend/mbql/test/metabase/mbql/util_test.clj#L31-L56
Is the use of :use
within the ns
macro considered bad form? Clj-kondo gives me the warning use :require with alias or :refer
when I write this:
(ns foo.bar.navigation
(:use (foo.bar.differentns))
yes it is. prefer (:require [foo.bar :refer [differents])
or perhaps even better (require [foo.bar :as bar])
and then use as bar/differents
. I often use the namespace alias as a way to add more information to call sites. So if an alias is users
then the var doesn't need to duplicate users
in it. For instance, users/fetch
instead of users/fetch-users
or something similar
So what I'm wanting to do is pull in all the public namespace members from the other namespace into the namespace I'm working in. Normally I would just use (require [full.ns.path :as whatever])
but in this case I do actually have legitimate reasons for wanting to be able to reference all the functions from the first namespace without using an alias
My understanding is that in Clojure you can use :refer :all
inside your ns
form, but this is a Clojurescript project, and apparently that https://stackoverflow.com/questions/24463469/is-it-possible-to-use-refer-all-in-a-clojurescript-require
i see. you want to expose other vars in a common namespace. Honestly I prefer a straightforward (def thing other-place/thing)
. Make your api explicit in that case
Noob question: Say I wanted to make a function, that "creates accumulators"
(def f (make-accum 1))
(f 2) ;; 3
(f 2) ;; 5
Here's my implementation:
(defn make-accum [n]
(let [acc (atom n)]
(fn [to-add]
(swap! acc (partial + to-add)))))
Would this be the idiomatic clojure way? Or is there something else you'd do?if there's state i'd want a good reason to not just pass the atom around. make it clear that you are updating a mutable container rather than behind a function. this reads like scheme code but not particularly like Clojure code.
also, you don't need to partial +
there. (swap! acc + to-add)
achieves the same result
Awesome! Thanks for the thoughts @dpsutton -- makes sense! And indeed re: scheme -- am going through sicp atm xD
yeah. scheme is "pure" and you make your mutable containers through closures and setting. clojure has really nice ways to do this and you should use them. caveat is if you are learning. there is always benefit to trying different strategies and making your own things to understand tradeoffs made by others.
Also, one other noob question: Was thinking one way I could model this, is to do something like generator with an infinite loop:
(defn make-accum-loop [n]
(loop [acc n]
(recur ??))
(fn [to-add]
;; somehow get the loop above to move forward a step, and get the latest value
))
Do you think something like this could be possible? One idea for doing this, is by using core-async (could have a in-ch and out-ch that keeps the loop going, and passes around the answer. But am not sure if there's a different wayi'm not following what the function should do. can you explain in words what you want to accomplish?
Sure thing! I want to create a function, which creates accumulators. It returns a function, that given a number, will increment the value, and remember it for a successive call:
(def f (make-accum 1))
(f 2) ;; 3
(f 2) ;; 5
One way I can do this, is by using an atom:
(defn make-accum [n]
(let [acc (atom n)]
(fn [to-add]
(swap! acc (partial + to-add)))))
But I was wondering if there was another way to do this:
For example, would it be possible to keep a kind of "generator"
This generator would run in an infinit loop, but be paused, waiting for f
to be called
When f
is called, the generator runs through one loop. This loop would increment the value with whatever f
providedif you squint, that's what an atom is. it is state that you can pass in a function to modify it. (swap! accumulator inc)
. The state is at rest until a function is passed in and it runs.
But i'm trying to figure out what you want. Do you want a list of successive values? You don't necessarily need an atom here. There are ways to build up sequences of successive states that might be useful to you
re: what I want -- I would just want the "next" value Something like initial value: 1 (f 1) // returns 2 (f 3) // returns 5 (f 5) // returns 10 --- If using core.async, I guess I could implement it like this:
(defn make-accum-loop [n]
(let [in-ch (channel)
out-ch (channel)]
(go-loop [acc n]
(let [to-add (<! in-ch)
new-v (+ acc to-add)]
(>! out-ch new-v)
(recur new-v)))
(fn [to-add]
(>!! in-ch to-add)
(<!! out-ch))))
(haven't actually used core-async deeply yet ^ above is kind of pseudocode)I guess one problem with that though, is that I have to know my values ahead of time. (In the accum, case, I am providing values with a function at a later, asynchronous point) I guess the main way to model this is with atoms / refs etc?
I’m still not sure I’ve seen anything other than changing mutable state so I’m not sure how to help more
You've helped quite a bit, thanks @dpsutton -- appreciate the insight about how atom, when squinted is in essence similar to the generator idea
(to clarify a bit more with what my intention was, I was trying to replicate something like this: https://github.com/islomar/seven-concurrency-models-in-seven-weeks/blob/master/Actors/counter/counter.ex#L22 -- here the mutation is "encapsulated in a kind of infinite loop, that is paused until called" -- From the research I think in clj the best way to do this is indeed either atoms, or if we really really wanted we could do something like the core-async approach
Ah! Okay one other way I can write this, which ~kind of matches the loop idea in example above:
(defn make-accum [n]
(fn [to-add]
(let [new-v (+ n to-add)]
[new-v (make-accum new-v)])))
(def f (make-accum 2))
(print (first (f 2))) ;; 4
(def f (second (f 2))
(print (first (f 2)) ;; 6
(Carry on! All of above pretty pointless, as atom is indeed best, but wanted to share along the learning : }