Fork me on GitHub
#core-typed
<
2022-04-12
>
ambrosebs00:04:03

Here's the bug in malli that Typed Clojure found: https://github.com/metosin/malli/pull/690 The type for the new helper:

(t/ann miu/-reduce-kv-valid (t/All [a k v]
                                   [[a k v -> (t/U (t/Reduced a) a Invalid)] a (t/Option (t/Associative k v)) -> (t/U a Invalid)]))

1
1
Ben Sless04:04:29

Did you have to annotate it yourself or did inference catch it?

1
ambrosebs17:04:27

Annotate it myself.

ambrosebs17:04:41

There is no global inference in Typed Clojure.

paola pereira13:04:29

Hi everyone! I am facing problems using typedclojure with malli custom schemas. Here is a code snipet:

(ns my-project.schemas
  (:require [malli.core :as m]
            [malli.generator :as mg]
            [malli.util :as mu]
            [malli.registry :as mr]
            [typed.clojure :as t]))

(def my-schema
  {::some-schema
   [:map
    [:key1 string?]]

   ::some-other-schema
   [:map
    [:key2 [:ref ::some-schema]]]})

(t/tc-ignore
 (mr/set-default-registry! (mr/composite-registry (mr/schemas m/default-registry)
                                                  (mu/schemas)
                                                  my-schema)))

(defn my-func [arg]
  {:key2 {:key1 "test"}})
(m/=> my-func [:=> [:cat ::some-schema] ::some-other-schema])
When checking my namespace with (t/check-ns-clj) , typedclojure do not approve my schema name:
1. Unhandled java.lang.AssertionError
   Assert failed: :my-project.schema/some-schema
   (re-matches #"^[a-zA-Z]+[a-zA-Z0-9]*$" (name n))
Seems to me this regex do not consider the character '-', it should be something like #"^[a-zA-Z]+[-a-zA-Z0-9]*$" . Some ideias? Am I doing something wrong?

👀 1
ambrosebs17:04:52

Hi! Could you post the stack trace please?

ambrosebs17:04:36

The odds are that you're not doing something wrong, this is very new.

ambrosebs22:04:27

Ok found it. Really have no idea what I was thinking...did I copy this code from the malli.clj-kondo impl perhaps? https://github.com/typedclojure/typedclojure/blob/94d169ec4cc169b51cca421d0af0d603f58e99a9/typed/malli/src/typed/malli/schema_to_type.cljc#L150

ambrosebs22:04:16

Nope. I have no memory of writing this xD

ambrosebs22:04:25

ah, I bet it was defensive programming against gensyming an invalid symbol from an arbitrary string

ambrosebs22:04:27

Should be fixed by this commit https://github.com/typedclojure/typedclojure/commit/f0d2506f4c982b745fb36cf61e25d4bd4cf92b76 I added your example to the example projects, and I'll schedule a release if the tests pass.

😍 1
ambrosebs22:04:35

Thanks very much for trying this feature, much appreciated.

ambrosebs23:04:17

Fixed in 1.0.27

paola pereira12:04:21

Nice!! Ow, my code even became an example! Happy to contribute and thank you very much for the fix!

🎉 1
rayat02:04:40

I wonder if it makes sense to offer some macros so that the typed-clojure-less "syntax" look even less "almost not horrible". Ie, the metadata shape (to my eyes) appears onerous enough that I'd prob still not be very inclined to use it as a library author, even with the benefit of correctness/analysis/typed-clojure-free-runtime. But a macro or two that (lol) looks like typed-clojure's inline annotation fn macro but expands to the new metadata-based one would have easier ergonomics. Of course, in <insert prod-ish envs here> the macro expands to the underlying fn as-is. You would just need to distribute the macros as a dep that doesn't otherwise contain typed-clojure in any runtime way shape or form. How trivial or useful is the above you think?

ambrosebs03:04:44

You just described the status quo prior to this feature 🙂

ambrosebs03:04:19

typed.clojure/fn is the macro, and it lives in a single jar with no dependencies here: https://github.com/typedclojure/typedclojure/tree/main/typed/clj.runtime

ambrosebs03:04:27

There's a big difference between zero and one dependency when it comes to minimizing dependency hell, it's almost a non starter for many libraries to have dependencies at all.

1
ambrosebs03:04:52

Anyway, that's my hunch.

ambrosebs03:04:31

Certainly any libs that I wrote I would avoid a direct dependency to Typed Clojure if I used it. So maybe the tradeoff is worth it just for me only 🙂

😆 1
ambrosebs04:04:40

Now that I've eaten, I see you were suggesting macros that expand to the metadata one. I think that might be just as heavyweight as the real typed.clojure/fn macro, it would need the same parsing logic.`typed.clojure/fn` actually throws away the type annotation too after expansion, because it's never needed at runtime.

1
ambrosebs04:04:26

The power of the metadata annotations are also that they're compatible with any macro that expands to fn. We don't need to wrap macros endlessly. eg., the argument why defn- doesn't really need to exist because of defn ^:private.

1
💯 1
ambrosebs04:04:58

Next I want to support let metadata annotations. That'll be pretty much ann-form.

wow 1
ambrosebs04:04:16

(let [^{::t/- t/Int} a 1] ...))

ambrosebs04:04:41

many more macros expand to let bindings too, so it'll probably be massive bang for your buck.

1
ambrosebs13:04:44

@U037TPXKBGS sorry about the misread and the wall of text 😬 my attention has been stretched thin, moving house..

lilactown17:04:56

how does as-alias work with the symbol t/Int?

lilactown17:04:13

surprised that isn't a read/compile error

ambrosebs18:04:17

it reads as {:typed.clojure/- 't/Int} and I don't think it's evaluated. Currently figuring out how this works in CLJS.

1
ambrosebs18:04:15

user=> (fn [^{:foo (nil)} a])
#object[user$eval40352$fn__40353 0x28a2c41 "user$eval40352$fn__40353@28a2c41"]

ambrosebs18:04:54

The compiler only cares about :tag in Clojure AFAIK.

ambrosebs18:04:05

CLJS seems similar. I don't think any of this is documented behavior.

cljs.user=> (fn [^{:foo (nil)} a])
#object[ret__6855__auto__]

ambrosebs18:04:00

My interpretation is that metadata is generally not evaluated unless it's reified at runtime. That's why this probably won't work using defn's metadata map arg.

ambrosebs18:04:58

Though perhaps using a defn's :arglists might work by annotating defn params.

ambrosebs18:04:00

By the time it gets to Typed Clojure it's basically doing a (binding [*ns* here] (parse-type 't/Int)) and it looks up the current aliases with ns-aliases.

1