3 ms·
The issue I have with gradual typing in most languages is that it's added after the fact and not native. As a result, the integration isn't native and you start
by Ovid 11y ago
The issue I have with gradual typing in most languages is that it's added after the fact and not native. As a result, the integration isn't native and you start seeing issues like this.
This, incidentally, is one of the reasons I like Perl 6 (http://perl6.org/ http://perl6.org/). It also has gradual typing, but if a third-party library doesn't have a type annotation, that's OK: it will simply fail at run time instead of compile time.
Another reason to like native gradual typing instead of third party gradual typing is that it can be integrated natively into the system instead of being used as an afterthought. Perl 6 has native type infererence to allow for compile time failures:
$ perl6 -e 'sub foo(Int $x) { say $x }; foo("bob")'
===SORRY!=== Error while compiling -e
Calling foo(str) will never work with declared signature (Int $x)
at -e:1
------> sub foo(Int $x) { say $x }; ⏏foo("bob")
(Yes, that's compile time instead of run time)
What happened above is that the optimizer saw that the call to foo() requires an Int and checks the argument type to see if the call is allowed.
And here's the untyped version:
$ perl6 -e 'sub foo($x) { say $x }; foo("bob"); foo(3)'
bob
3
Interestingly, the Perl 6 core team could allow for powerful type inference with this, but one of the core issues has always been that many languages using type inference have rather opaque error messages because they essentially dump a "proof" of type failure and many struggle to understand them. Thus, the the Perl 6 devs are taking more careful approach, though they know they can do more. For example, this falls back to a runtime failure instead of a compile time failure:
$ perl6 -e 'sub foo(Int $x) { say $x }; my $name = "Bob"; foo($name)'
Type check failed in binding $x; expected 'Int' but got 'Str'
in sub foo at -e:1
in block <unit> at -e:1
In other words, because it's not sure of the type of $name at compile time, it falls back to run time (though in the simplistic example above, that's clearly not the case). Annotate the $name variable and you get a compile time failure again:
$ perl6 -e 'sub foo(Int $x) { say $x }; my Str $name = "Bob"; foo($name)'
===SORRY!=== Error while compiling -e
Calling foo(Str) will never work with declared signature (Int $x)
at -e:1
------> t $x) { say $x }; my Str $name = "Bob"; ⏏foo($name)
With this, third-party libraries which don't declare types work just fine, but you get type-safe run time failures. If they do declare types, you often get compile time failures (though it will still fall back to run time, and won't check at run time if it knows at compile time that it works).
- bjr- 11y agoI believe that's where core.typed is going: http://frenchy64.github.io/2015/06/19/gradual-typing.html http://frenchy64.github.io/2015/06/19/gradual-typing.html Typed and untyped code must (and will soon) be able to cooperate in providing compile-time and run-time type checking in Clojure.
- mattrepl 11y agoThere are also tentative plans to integrate core.typed with the Clojure compiler so type annotations can be used during compilation (e.g., type hints through inference). There was a post about it, but the best I could find is a recent paper: http://frenchy64.github.io/papers/typed-clojure-draft.pdf http://frenchy64.github.io/papers/typed-clojure-draft.pdf
- Gonzih 11y agoClojure core.typed is not there yet, but aims to support exactly same thing (like type racket).