This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-03-07
Channels
- # announcements (19)
- # babashka (19)
- # beginners (76)
- # bitcoin (2)
- # calva (1)
- # chlorine-clover (1)
- # cider (7)
- # clara (1)
- # clj-kondo (1)
- # cljsrn (1)
- # clojars (4)
- # clojure (139)
- # clojure-dev (65)
- # clojure-europe (2)
- # clojure-uk (2)
- # clojurescript (7)
- # community-development (3)
- # conjure (15)
- # core-async (5)
- # cursive (11)
- # data-science (9)
- # duct (6)
- # fulcro (4)
- # honeysql (12)
- # jobs (3)
- # jobs-discuss (3)
- # keechma (1)
- # malli (31)
- # meander (14)
- # midje (1)
- # off-topic (21)
- # pathom (6)
- # practicalli (3)
- # quil (7)
- # re-frame (10)
- # reitit (6)
- # slack-help (4)
- # tree-sitter (6)
- # xtdb (1)
1. is there a syntax guide for Var meta :arglists
? things like clojure.core/eduction
have hand-written syntax '([xform* coll])
2. are there better ways to extract the arities from normal defn
s?
3. what ways there are to pull out return type hints per artities, besided Var :tag
meta - which is shared for all arities?
4. what ways there are to get argument type hints?
5. would it be possible to extract all the info (arities, basic type hints) programmatically in the future? e.g. compiler option to inject more info into Var & fn meta?
could use the stellar tooling from @borkdude (sci, edamame & clj-kondo), but as the clojure compiler knows all these already, would like to hear if it is possible to get access to that info directly
the algo for return type is to first check on the argvec and fallback on the var type hint
the compiler does no validation on 'correct' arglist format, so sometimes handmade ones are not in the right format and they're just ignored
there is no formal spec and in the wild you can encounter things that deviate from what you see in core
in general, "locking" a var into a concrete set of arities immediately raises questions about what that means for future (additive) modifications to the signature
Well but the compiler does specialise interop calls according to the "current" arglist so it is locking in a way
> the compiler does no validation on 'correct' arglist format, so sometimes handmade ones are not in the right format and they're just ignored does the compiler do anything with the handmade arglists at all other than adding it to the metadata?
it just looks for type hints if the arglist is present, if the format is incorrect it may ignore it or derive the wrong type hint at callsites
I'm surprised since I assumed that the "handwritten" arglists was just for documentation clarification
so you could have a different arglist for documentation that doesn't need to be 'correct', while keeping the true one for the compiler
but as things are you just need to be careful if you're crafting a tyoe hinted arglist manually
e.g. when I define a function using comp
but I want some type hint optimization, I might as well not use comp
but write my fn using defn
tools.analyzer
is just for analyzing source code, right? it’s awesome tool, but could the normal clojure compiler expose more info to the runtime? (via compiler option)
(->> (jvm/analyze
'(fn
([] "kikka")
([x] (inc x))
(^Boolean [x y] (+ x y))
([x y & zs] (apply + x y zs)))
(jvm/empty-env))
:methods
(mapv (fn [{:keys [arglist body tag params]}]
{:tag (or (:tag body) tag)
:arglist arglist
:args (mapv (fn [arg] (select-keys arg [:form :tag])) params)})))
;[{:tag java.lang.String
; :arglist []
; :args []}
; {:tag java.lang.Number
; :arglist [x]
; :args [{:form x, :tag java.lang.Object}]}
; {:tag java.lang.Boolean
; :arglist [x y]
; :args [{:form x, :tag java.lang.Object}
; {:form y, :tag java.lang.Object}]}
; {:tag java.lang.Object,
; :arglist [x y & zs],
; :args [{:form x, :tag java.lang.Object}
; {:form y, :tag java.lang.Object}
; {:form zs, :tag clojure.lang.ISeq}]}]
just pointing to that function to extract the relevant argvec for an arity, which more or less defines the syntax the compiler understands
Bronsa knows best, but my understanding is that the Clojure compiler might reveal some or all of this via JVM objects that it creates, but none of it is documented outside of the Clojure compiler source code (and perhaps someone's personal documentation notes), and none of it is promised not to change across versions of the Clojure compiler
this kinda thing:
(let [f (fn
([] "kikka")
([x] (inc x))
(^Boolean [x y] (+ x y))
([x y & zs] (apply + x y zs)))]
(pull-out-arities-and-types f))
no, the clojure compiler only uses arglists during a 'read' and analysis, it's not exposed in the ast
but also not super useful, type hints are used at callsites, in a HOF setting they would not be analyzeable
unless doing complex flow analysis and per object specialisation which clojure doesn't do
(defn f
([] "kikka")
([x] (inc x))
(^Boolean [x y] (+ x y))
([x y & zs] (apply + x y zs))) )
(meta #'f)
;{:arglists ([] [x] [x y] [x y & zs]),
; :line 2331,
; :column 1,
; :file ...
; :name f,
; :ns ...}
clojure doesn't do return type inference, it only does a simple form of local type inference (to specialise interop calls), but doesn't propagate across fn boundaries
t.a could, and with some minor enhancements so could the clojure compiler, but I believe it's a design decision not to
there's at least one function in core that has a ^String type hint on an argument that could be a symbol, and to the compiler that's fine
thanks for the great explanation. Couldn't find the relevant jira issue, only the SO question with few ways to resolve the fn arity at runtime. Would be great if core could expose those directly (in a dev-mode, as extra meta would consume memory)
https://stackoverflow.com/questions/1696693/clojure-how-to-find-out-the-arity-of-function-at-runtime