This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-29
Channels
- # announcements (1)
- # beginners (40)
- # calva (30)
- # cider (3)
- # clj-kondo (1)
- # cljdoc (12)
- # clojure (79)
- # clojure-dev (7)
- # clojure-france (4)
- # clojure-spec (10)
- # clojure-uk (13)
- # clojurescript (19)
- # core-async (1)
- # core-typed (1)
- # cursive (2)
- # datomic (2)
- # emacs (3)
- # events (1)
- # kaocha (2)
- # klipse (14)
- # off-topic (26)
- # pathom (1)
- # reagent (8)
- # rewrite-clj (8)
- # shadow-cljs (22)
- # tools-deps (18)
How would I fully qualify a symbol from within a macro, but outside a qualified quote. For example if I use a sym and pass that into the macro, and get it's value to do some processing?
Not sure I understand the question. When you say you want the macro to get the value of a symbol that was passed as a parameter to the macro, and do some processing on that symbol, what kind of processing do you mean?
Or, do you have an example of what you want as the macro call, and the expanded version of the macro, that might help clarify?
The main reason that the syntax-quote (signified via a back-quote character) causes unqualified symbols within it to become fully namespace qualified, is to prevent accidental name collisions with symbols having the same name where the macro is called.
this macro doen't work with the following input
(defmacro with-args
"Bind "
{:style/indent [1]}
[argv arg-bindings & body]
(let [bind-list (->> (partition 2 arg-bindings)
(map-indexed (fn [i v]
[(first v) i]))
flatten)
bind-form (-> (apply hash-map bind-list)
(assoc :or (apply hash-map arg-bindings)))
bind-arg (vec argv)]
`(let [~bind-form ~bind-arg]
~@body)))
(let [args ["127.0.0.1"]]
(with-args args
[host "0.0.0.0"
port "3030"]
(tap> [host port])))
it does with this
(with-args ["127.0.0.1"]
[host "0.0.0.0"
port "3030"]
(tap> [host port]))
it complains at the (vec argv) when it's a symbol, that it's not an Object[]
Remember that macros operate on code before it is evaluated.
so argv
in your macro is args
in that first case.
You want (vec ...)
evaluated at runtime, not compile time.
so
`(let [~bind-form (vec ~argv)]
~@body)
ahh, yes
(and remove the bind-arg
local symbol)
This is why the first rule of Macro Club is Don't Use Macros 🙂
@theeternalpulse maybe this is what you looking for? https://github.com/wilkerlucio/pathom/blob/master/src/com/wsscode/pathom/connect.cljc#L1267-L1269
haha, I like taking a break from doing real projects to hit my head over fine macro details
@i Spec is so many things. Yes, it does allow you to write assertions but that's not even scratching the surface. We use Spec very heavily in production code -- not assert style -- to describe data structures, so we can perform validation of API inputs and other things, and use the data from validation failures to provide custom, sensible responses to clients. We use Spec to auto-generate test data that we use in example-based tests. We use Spec to support generative testing of the properties behind our functions. We use Spec to provide development-time verification of function arguments under test. We use Spec to describe function behaviors so they can be generatively tested. We use Spec to describe data structures so that we can derive functionality from that -- such as CRUD functions, automatically generated via macros.
have you used schema before?
It's similar in that you can create contracts to your functions as to what data goes in and out, and ads other complex layers like pulling apart data based on the different parts of the specs. Also it has generative testing functionality that is as fined grained as the specs themselves.
I think comp “pushes” its functions onto the args. So the rightmost hits it then the next, etc
Nothing in core works the way comp does, except with reverse order of args
@i Spec is so many things. Yes, it does allow you to write assertions but that's not even scratching the surface. We use Spec very heavily in production code -- not assert style -- to describe data structures, so we can perform validation of API inputs and other things, and use the data from validation failures to provide custom, sensible responses to clients. We use Spec to auto-generate test data that we use in example-based tests. We use Spec to support generative testing of the properties behind our functions. We use Spec to provide development-time verification of function arguments under test. We use Spec to describe function behaviors so they can be generatively tested. We use Spec to describe data structures so that we can derive functionality from that -- such as CRUD functions, automatically generated via macros.
Ya, you just got to learn to love comp, even though the ordering is opposite of intuition, depending what intuition you have, since in math right to left makes sense for composition: f * g
is first g, then f. And you can think of it as just f(g())
. So comp is the same: (comp f g)
is like (f (g))
or f * g
. I also don't find that ordering intuitive, but I'm pretty sure this is why comp works the other way.
To make it extra confusing, but also convenient, transducers composed with comp
apply left to right: (comp (map inc) (filter even?))
will first increment, and then filter. It makes it more confusing, because now you have to ask yourself if comp is used with transducers or not. But, when you do use transducers with it, which is what I most often use it for, it is in the more intuitive ordering.
The issue with transducers is that things like (map inc)
and (filter even?)
are transforms -- so they compose in the opposite direction to "regular" functions.
In other words, you're not composing functions, you're composing transforms -- and they inherently work outside in, rather than inside out.
Transducers are really interesting higher-order functions and figuring out how to write them -- with three arities (0, 1, and 2 arguments) -- teaches you a lot about function composition.
If you like books there is also the book https://www.amazon.com/dp/0070004846/?ref=idea_lv_dp_
in this book transducer are covered. and It might be that Rich was inspired by this, since he mention also in his list of books.. But this is just speculation 🌕
There's a follow-up Rich Hickey talk that deep-dives into stuff if you need it.
Anywhere you might use ->>
and a multi-stage pipeline, you can use transducers.
@seancorfield what is multi-stage pipeline?
Yes, where we used to have clojure.java.jdbc/query
and then post-processing, we're switching to next.jdbc/plan
and a reduce
or transduce
operation.
I dunno. I didn't need to read the source to make sense of this. If anything, I think the source is confusing.
The abstractions are a lot more important than the implementations.
then there is this talk: https://www.youtube.com/watch?v=4KqUvG8HPYo
Yes, that's the follow-up talk I alluded to above.
I wish comp for regular functions worked in the same direction comp for transducers does
Ah, and once you understand everything, comp
behaves exactly as it should 🙂
That's not quite what I said...
Several "special forms" foo
are actually macros that are implemented in terms of foo*
compiler forms.
I prefer ->
to comp
where possible, but comp
still has valid use cases, where order of arguments to comp
corresponds to order I'm which computation happens (transducers for example`)
there is a thing with comp and/or -> lambdas e.g #(-> % f g h)
, where a an "anonymous" java class is generated on every call(? or something) instead of just reusing the same. I forgot in which case that is, since it did not affect me much. But one of the approaches results in cleaner runtime.
Hi guys, I've written a Clojure library for the Event Store DB, and I'd really appreciate any suggestions you might have, and any stars you can spare! https://github.com/dcprevere/evst
hey, anyone using carmine 🙂 I’m trying to monitoring like this
(def listener
(car/with-new-listener server1-conn
(fn [reply initial-state] (println reply initial-state))
{:initial-state true}
(car/monitor)))
Anyone remember the existence of a lib or gist that lets you use datomic pull syntax on arbitrary clj data structures? I feel like I vaguely remember someone mentioning the existence of such a thing once, but no luck googling it. Otherwise I'll just write it (can post as gist if other folks would find it useful), but I'd just as soon grab it elsewhere if it already exists. Caveat: I'm looking for something that operates entirely independently of datomic, something that just uses the same or similar syntax for describing nested data structures.
was it datascript? https://github.com/tonsky/datascript
Hmm. The timing's right in terms of when I think I heard about it, but I don't recall datascript letting you do pulls against arbitrary nested data structures (as opposed to collections of datoms). On the other hand, seems like with datascript you might be able to just create an ad hoc mini-DB... I'll go back & read some of the docs. Thanks!
Nah, as awesome as datascript is, and as lightweight as it is relative to datomic, I'm really looking for just a one-trick pony that lets you describe & retrieve a substructure of a typical, arbitrary, heavily nested clj/s data structure. Probably easier and funner to just write it 🙂
It wasn’t https://github.com/juxt/pull/blob/master/README.md was it?
@U08BW7V1V not sure, but that's exactly what I was looking for! On the other hand, I've just happily whiled away the last couple of hours writing my own, so I may stick with that 😆 Although juxt's definitely has a few cool features that mine doesn't (shadow attributes, references). Thanks!
Hi! I’m playing with new protocols feature extend-via-metadata
. And satisfies?
seems to be broken:
(defprotocol P
:extend-via-metadata true
(a [this])
(b [this]))
(let [o (reify P
(a [_] :a)
(b [_] :b))]
(satisfies? P o)) ;; => true
(let [o (with-meta []
{`a (constantly :a)
`b (constantly :b)})]
(satisfies? P o)) ;; => false
This is a known issue
In my testing, binding *print-readably*
to false and using println
, print
, pr-str
, etc., rather than the default *print-readably*
true, causes characters in a string value like newline and tab to be printed differently, but only affects the handful of characters, those in the value of clojure.core/char-escape-string
The doc string for *print-readably*
says " When set to logical false, strings and characters will be printed with
non-alphanumeric characters converted to the appropriate escape sequences."
Does "non-alphanumeric characters" there refer only to the handful in the value of char-escape-string
, and no others?
If anyone happens to know of a built-in way to get more (or 'all') non-printable characters to be printed with escape sequences like \u1234
, please let me know. Easy to implement myself I know.