Similar to the above ... now with symbols. Is there a neater way to handle symbols? I have something working / workable on this code but would rather just have the symbols than their quoted form
(let [in-exprs '(let [symbol-keys {'first-name "Jane"
'last-name "Doe"}
first-name (get symbol-keys 'first-name)]
first-name)]
(let->destructured-let (pr-str in-exprs)))
=>
{:string-form "(let [symbol-keys {(quote first-name) \"Jane\", (quote last-name) \"Doe\"}
first-name (get symbol-keys (quote first-name))] first-name)",
:edn-form (let [symbol-keys {(quote first-name) "Jane", (quote last-name) "Doe"}
first-name (get symbol-keys (quote first-name))]
first-name)}
it's more to do with the reader than with spec but still, would welcome suggestionsthe biggest problem is that I need to eval the list to get the symbol ... or at least I think that's what I need to do 🤨
to put it in the spec scope ... this is how I have the spec for get
(s/def ::get-k-from-m
(s/cat
:name (s/and symbol? #(= 'get %))
:map ::map-value
:key (s/or :keyword keyword?
:string string?
:symbol (s/or :sym symbol?
:quoted-sym list?))
:default (s/? any?)))
would be great to avoid the need for (s/or :sym symbol? :quoted-sym list?)
maybe a tighter question: how should one spec a map with keys that are symbols?
@hiredman thanks for challenging my approach. I am still learning.
I have made the context clearer now
;; A spec for `get` that works only on maps, with keywords, strings or symbols as keys
;; It is only applicable for conforming data from :init-expr (the right hand side) of :bindings
(s/def ::get-k-from-m
(s/cat
:name (s/and symbol? #(= 'get %))
:map ::map-value
:key (s/or :keyword keyword?
:string string?
:symbol (s/or :sym symbol?
:quoted-sym (s/coll-of symbol? :distinct true :count 2)))
:default (s/? any?)))
I would still like a better spec than (s/coll-of symbol? :distinct true :count 2) but it does the job for now
that isn't a map with keys that are symbols
' is a reader macro so 'x is read into the same form as (quote x) (which is a list containing two symbols)
it sounds like you are trying to use the same spec for data pre and post evaluation, which doesn't seem like a good idea
Yeah, agreed. And it’s why I’m asking for alternatives
maybe step back and talk about what you are trying to achieve?
you get for example breaks down on (let [get (constantly nil) ] (get x :foo)) or whatever, which is basically another way of saying it is conflating different levels of meaning
The project is to demonstrate how access to maps can be conducted using destructuring
and how is that connected to spec?
The specs are there to conform cases that would match that use case rather than all use cases
And I’m using conform as a parser
sure, but a parser here is context free
but you need a context (an evnironment) to properly do the static analysis
There are tests in there to demonstrate the use cases
sure, but I am saying at a fundamental level, spec is a context free analysis, but in order to do abstract interpretation of the code to understand it, you need context
The context is the let form
no, that is the code
like how do you know that get somewhere is clojure.core/get?
The specs are designed to work within that context
Oh, ok. I see. I hadn’t backed out that far. It didn’t feel necessary.
(let [m {:a/k1 1 :b/k2 2 :c/k3 3}
get (constantly 1)
k1 (get m :a/k1)
k2 (:b/k2 m)]
(+ k1 k2))
It’s a assumption that I’m happy to live with though
that assumption is why your spec doesn't work with the quoted symbols
Sure, that’s gonna parse ok
Actually it does work
I’m seeking something more elegant
But maybe that’s as good as it gets within these assumptions 🤷🏻♂️
I only apply the get spec to the rhs