core-typed

paola pereira 2022-04-12T13:46:29.315779Z

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
2022-04-12T17:51:52.679549Z

Hi! Could you post the stack trace please?

2022-04-12T17:52:36.068569Z

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

2022-04-12T22:01:27.590679Z

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

2022-04-12T22:02:16.515419Z

Nope. I have no memory of writing this xD

2022-04-12T22:26:25.639639Z

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

2022-04-12T22:49:27.381809Z

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
2022-04-12T22:50:35.222179Z

Thanks very much for trying this feature, much appreciated.

2022-04-12T23:15:17.101839Z

Fixed in 1.0.27

paola pereira 2022-04-13T12:50:21.835409Z

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

🎉 1
2022-04-12T23:17:25.589389Z

rayat 2022-04-13T02:01:12.153239Z

chef_kiss

rayat 2022-04-13T02:06:40.558229Z

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?

2022-04-13T03:49:44.129549Z

You just described the status quo prior to this feature 🙂

2022-04-13T03:51:19.908439Z

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

2022-04-13T03:52:27.030109Z

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
2022-04-13T03:52:52.577879Z

Anyway, that's my hunch.

2022-04-13T03:53:31.267839Z

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
2022-04-13T04:32:40.579059Z

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
2022-04-13T04:41:26.763009Z

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
2022-04-13T04:41:58.909479Z

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

1
2022-04-13T04:42:16.511569Z

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

2022-04-13T04:42:41.215399Z

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

🤔 1
2022-04-13T13:23:44.501619Z

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

lilactown 2022-04-13T17:41:56.175669Z

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

lilactown 2022-04-13T17:42:13.729349Z

surprised that isn't a read/compile error

2022-04-13T18:17:17.874809Z

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

🤔 1
2022-04-13T18:18:15.301469Z

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

2022-04-13T18:18:54.582769Z

The compiler only cares about :tag in Clojure AFAIK.

2022-04-13T18:21:05.627259Z

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

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

2022-04-13T18:24:00.524369Z

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.

2022-04-13T18:24:58.769319Z

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

2022-04-13T18:27:00.647809Z

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
2022-04-12T00:57:03.597979Z

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
2022-04-12T17:50:27.063869Z

Annotate it myself.

2022-04-12T17:50:41.117729Z

There is no global inference in Typed Clojure.

Ben Sless 2022-04-12T04:09:29.583739Z

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

🤔 1