This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-07-08
Channels
- # aleph (10)
- # announcements (4)
- # beginners (25)
- # calva (4)
- # cider (56)
- # clj-kondo (10)
- # cljdoc (1)
- # cljs-dev (58)
- # clojure (42)
- # clojure-austin (5)
- # clojure-dev (90)
- # clojure-europe (2)
- # clojure-greece (2)
- # clojure-italy (3)
- # clojure-nl (63)
- # clojure-quebec (1)
- # clojure-seattle (2)
- # clojure-spain (4)
- # clojure-spec (19)
- # clojure-uk (25)
- # clojuredesign-podcast (5)
- # clojurescript (24)
- # cursive (15)
- # datomic (1)
- # events (1)
- # figwheel-main (10)
- # fulcro (62)
- # graphql (7)
- # keechma (11)
- # nrepl (1)
- # off-topic (12)
- # re-frame (8)
- # reitit (2)
- # remote-jobs (3)
- # shadow-cljs (127)
- # specter (1)
- # sql (43)
- # testing (2)
- # tools-deps (30)
- # xtdb (1)
Given that (.getResource (var-get clojure.lang.Compiler/LOADER) "cognitect/test_runner.clj")
works, why wouldn't (require 'cognitect.test-runner)
given that the failure is FileNotFoundException Could not locate Clojure resource on classpath: cognitect/test_runner.clj clojure.lang.RT.loadResourceScript (RT.java:388)
. Disclaimer: I'm using a custom classloader.
Ah, clojure uses getResourceAsStream
instead of getResource
, I think the class loader is broken for AsStream with files. Bummer.
09:33 $ clj
Clojure 1.10.0
user=> (let [{:keys [foo]} 3] (println "foo"))
Syntax error (UnsupportedOperationException) compiling at (REPL:1:1).
Can't type hint a primitive local
user=>
what's slightly confusing is that there are no type hints in the user code, it's coming from destructuring macroexpansion
I'd be curious to see if this repro was distilled from a different scenario in the wild @slipset
@ghadi No, I was rewriting some code at work and made the mistake of trying to destructure a number. So apart from naming the key foo and trying to print it, this was code I actually wrote.
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6015
user=> *e
#error {
:cause "Can't type hint a primitive local"
:via
[{:type clojure.lang.Compiler$CompilerException
:message "Syntax error compiling at (1:1)."
:data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 1, :source "NO_SOURCE_PATH"}
:at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
{:type java.lang.UnsupportedOperationException
:message "Can't type hint a primitive local"
:at [clojure.lang.Compiler$LocalBindingExpr <init> "Compiler.java" 6015]}]
:trace
[[clojure.lang.Compiler$LocalBindingExpr <init> "Compiler.java" 6015]
[clojure.lang.Compiler analyzeSymbol "Compiler.java" 7297]
[clojure.lang.Compiler analyze "Compiler.java" 6768]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3888]
[clojure.lang.Compiler analyzeSeq "Compiler.java" 7108]
[clojure.lang.Compiler analyze "Compiler.java" 6789]
[clojure.lang.Compiler analyze "Compiler.java" 6745]
[clojure.lang.Compiler$HostExpr$Parser parse "Compiler.java" 1020]
So the macroexpanded thing looks like:
user=> (clojure.pprint/pprint (macroexpand '(let [{:keys [foo]} 3] (println foo))))
(let*
[map__165
3
map__165
(if
(clojure.core/seq? map__165)
(clojure.lang.PersistentHashMap/create (clojure.core/seq map__165))
map__165)
foo
(clojure.core/get map__165 :foo)]
(println foo))
nil
user=>
Which at least seems to have a redundant call to seq
in the true
branch of the if
test.
cljs.user=> (macroexpand '(let [{:keys [foo]} 3] (println foo)))
(let* [map__24 3
map__24 (if (cljs.core/implements? cljs.core/ISeq map__24) (cljs.core/apply cljs.core/hash-map map__24) map__24)
foo (cljs.core/get map__24 :foo)]
(println foo))
cljs.user=>
repro
user=> (let [x 1] (when (seq? x) (.first ^clojure.lang.ISeq x)))
Syntax error (UnsupportedOperationException) compiling at (REPL:1:27).
Can't type hint a primitive local
Even if it is needed, wouldn’t it be safer to add it at the point where create
is called?
yeah it was needed when the macro expanded to (c.l.PHM/create gmapseq)
instead of (c.l.PHM/create (seq gmapseq))
Ah, so we need to somehow coerce/typehint the gmap
local to get the correct version of c.l.PHM/create
?
a previous implementation did, and so the type hinting was in place, but then a call to seq
was introduced which rendered the type hint unnecessary but i guess it was just forgotten there
JIRA seems really slow. Not sure if there's something wrong, but for instance I am stuck at a loading screen here: https://clojure.atlassian.net/projects/TCLI/issues
so could we just do (c.l.PHM/create gmap)
(since we know from the if thest that gmap
is a seq
?
- gmapseq (with-meta gmap {:tag 'clojure.lang.ISeq})
defaults (:or b)]
(loop [ret (-> bvec (conj gmap) (conj v)
- (conj gmap) (conj `(if (seq? ~gmap) (clojure.lang.PersistentHashMap/create (seq ~gmapseq)) ~gmap))
+ (conj gmap) (conj `(if (seq? ~gmap) (clojure.lang.PersistentHashMap/create (seq ~gmap)) ~gmap))
@bronsa @slipset this seems really low on the priority list. the input code doesn't make sense, and removing that type hint (while it is unnecessary) will make it silently be accepted
The issues page never loads (just spins) if you're logged into JIRA with a different account (or perhaps just not logged into your Clojure account?).
another possibility would be forbidding numbers on the right hand side of a map/vector destructuring
You can do other stuff in JIRA with projects but the issues page won't load for un-auth'd accounts @devn
I guess my main point was that while happy it didn’t fail silently, I was a bit surprised by the error message, and since those have been a priority lately, I figured it would be worth mentioning.
https://github.com/clojure/core.specs.alpha/blob/master/src/main/clojure/clojure/core/specs/alpha.clj#L53
perhaps init-exprs shouldn't be any?
-- maybe they can be sensitive to the left hand side
Is associative destructuring sugar on top of get
? Or is that never specified anywhere? (The reason I ask is that, if so, it seems to be related to whether get
on a number is meant to return nil
.)
if (get 3 :foo)
makes sense then I guess (let [{:keys [foo]} 3]..)
makes sense as well?
Cool, just trying to keep it straight in my head (outside of this nonsensical example). Associative destructuring is sugar for get
and sequential is sugar for nth
with nil
for unknown, in my simplified mental model.
Right, and we will never really know whether (get 3 :foo)
is meant to return nil
or not, I bet.
Yeah, that's what I resorted to as the spec of the behavior as well. Using the impl as the spec.
(get 3 :foo) returns the correct thing (nil) but makes no sense from a user perspective
destructuring is slightly different in that you have the opportunity to check a spec at macroexpansion time
Speculative decided to allow any for the map
argument to get
https://github.com/borkdude/speculative/blob/master/src/speculative/core.cljc#L203
I agree with @ghadi, since
user=> (def lol 3)
#'user/lol
user=> (let [{:keys [foo]} lol] (println foo))
works as expectedmmm, I guess my point was that if the above example would fail with an error, I’d be a little unhappy, because it’s not always clear that a var contains a constant
BTW, since you linked to https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L786
are there reasons (like performance), for duplicating the code in get(Object coll, Object key, Object notFound)
and get(Object coll, Object key)
?
(too long since I programmed Java to remember if there are problems related to overloading static fns)