clojure-spec

ray 2024-10-14T15:10:33.609189Z

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 suggestions

ray 2024-10-14T15:12:35.229839Z

the 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 🤨

ray 2024-10-14T15:18:46.908419Z

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?)))

ray 2024-10-14T15:19:59.975009Z

would be great to avoid the need for (s/or :sym symbol? :quoted-sym list?)

ray 2024-10-14T19:54:49.751569Z

maybe a tighter question: how should one spec a map with keys that are symbols?

ray 2024-10-15T08:13:40.478789Z

@hiredman thanks for challenging my approach. I am still learning.

ray 2024-10-15T14:04:06.448889Z

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?)))

ray 2024-10-15T14:04:57.918589Z

I would still like a better spec than (s/coll-of symbol? :distinct true :count 2) but it does the job for now

2024-10-14T20:01:11.180289Z

that isn't a map with keys that are symbols

2024-10-14T20:02:08.212659Z

' is a reader macro so 'x is read into the same form as (quote x) (which is a list containing two symbols)

2024-10-14T20:02:35.933059Z

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

ray 2024-10-14T20:56:10.522359Z

Yeah, agreed. And it’s why I’m asking for alternatives

2024-10-14T20:59:10.478069Z

maybe step back and talk about what you are trying to achieve?

2024-10-14T21:00:18.064689Z

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

ray 2024-10-14T21:01:48.363649Z

The project is to demonstrate how access to maps can be conducted using destructuring

2024-10-14T21:02:25.578439Z

and how is that connected to spec?

ray 2024-10-14T21:02:37.267189Z

The specs are there to conform cases that would match that use case rather than all use cases

ray 2024-10-14T21:03:07.827639Z

And I’m using conform as a parser

2024-10-14T21:03:42.656299Z

sure, but a parser here is context free

2024-10-14T21:04:08.503279Z

but you need a context (an evnironment) to properly do the static analysis

ray 2024-10-14T21:04:52.012279Z

https://github.com/repl-acement/destructive

ray 2024-10-14T21:05:34.749989Z

There are tests in there to demonstrate the use cases

2024-10-14T21:06:26.424799Z

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

ray 2024-10-14T21:06:35.085489Z

The context is the let form

2024-10-14T21:06:42.173789Z

no, that is the code

2024-10-14T21:07:23.758949Z

like how do you know that get somewhere is clojure.core/get?

ray 2024-10-14T21:07:36.081769Z

The specs are designed to work within that context

ray 2024-10-14T21:08:41.567679Z

Oh, ok. I see. I hadn’t backed out that far. It didn’t feel necessary.

2024-10-14T21:09:01.293959Z

(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))

ray 2024-10-14T21:09:22.164069Z

It’s a assumption that I’m happy to live with though

2024-10-14T21:10:05.480029Z

that assumption is why your spec doesn't work with the quoted symbols

ray 2024-10-14T21:10:07.120809Z

Sure, that’s gonna parse ok

ray 2024-10-14T21:10:45.182539Z

Actually it does work

ray 2024-10-14T21:11:08.517729Z

I’m seeking something more elegant

ray 2024-10-14T21:12:56.893479Z

But maybe that’s as good as it gets within these assumptions 🤷🏻‍♂️

ray 2024-10-14T21:20:37.554719Z

I only apply the get spec to the rhs