Skip to content

Comparison to Typed Clojure

LuxLang edited this page Jan 18, 2017 · 2 revisions

a.k.a. core.typed

Typed Clojure offers optional typing; Lux offers full static typing:

Clojure is a dynamically typed language, and no project is ever going to change that.

The best that Typed Clojure can offer is a means for individual programmers to annotate their own libraries with types, and sort-of monkey-patch foreign libraries (including Clojure's own libraries), in case they're missing typing information.

Unfortunately, this poses some issues.

One is that Clojure wasn't designed with types in mind, which means some of its functions, macros and other constructs don't play well with attempts to type them.

Typed Clojure, for instance, does not have a complete story when it comes to typing Clojure's libraries, with many functions missing annotations: https://github.com/clojure/core.typed/wiki/clojure.core-Annotations

Not only that, but because the typing is optional, and most Clojure programmers are fine with using dynamic types, the ecosystem is very dependent on the whims and needs of library providers, which often don't match the needs of library users who want types.

This forces library users to provide the types for the libraries they're consuming, instead of being able to just expect the types to be present (a practice that gets old rather quickly).

Community participation to expand the usage of core.typed is necessary, but lacking:

In contrast, Lux's type-system is a part of the language, and not subject to the whims of users.

There is an implicit contract between library providers and library consumers, that types will be present and that code will conform to the types, and won't deviate from expected behavior.

All Lux libraries are typed.

The type-system is a fundamental component of the compiler.

Types are even available to macros for the purpose of meta-programming.

In short, the type-system is not a hack.

Typed Clojure offers bounded subtyping; Lux offers no subtyping:

Clojure's design is intimately coupled to the JVM, and Typed Clojure follows suit.

Because of that, Typed Clojure must have support for the kind of subtyping that goes on in object-oriented programming.

Lux's type-system is not dependent on any host platform, and does not support subtyping (since, in the future, Lux may be hosted by platforms which lack this).

Lux's type-checker does allow subtyping to play a part during the analysis of programs, to avoid flagging correct JVM programs as invalid.

However, there is no way to specify inheritance relationships or polymorphic bounds for type-variables in Lux.

With that said, even Typed Clojure has some issues when handling some of the intricacies of OO subtyping: https://github.com/clojure/core.typed/wiki/Accurate-downcasting

Typed Clojure has kinds; Lux doesn't:

Higher-kinded types are an idea that some typed functional languages have adopted.

They are sort of a type-system on top of the type-system, and they allow you to impose some constraints on type-variables, in order to prevent invalid types from being constructed.

Typed Clojure has some support for this: https://github.com/clojure/core.typed/wiki/User-Guide#higher-kinded-variables

However, Lux doesn't implement higher-kinded types, as it was felt that the benefits they provided were not enough to justify the increase in complexity they would introduce.

Typed Clojure doesn't integrate well with the language; Lux's type-system is part of the language:

Typed Clojure is an abstraction layer that exists on-top-of Clojure.

This is an important thing to consider, and one is often reminded about that when using the core.typed library.

For example, core.typed doesn't handle primitives properly: https://github.com/clojure/core.typed/wiki/Primitives

Also, core.typed's type-checker is not sophisticated enough as to properly understand Clojure's syntax and semantics.

This has led the Typed Clojure project to introduce a variety of alternative macros that are meant to be used instead of Clojure's own macros, in order to deal with the core.typed type-checker's limitations.

Typed Clojure needs extra assistance to understand functions: https://github.com/clojure/core.typed/wiki/User-Guide#functions

Typed Clojure needs extra assistance to understand protocols: https://github.com/clojure/core.typed/wiki/User-Guide#datatypes-and-protocols

Typed Clojure can't understand basic Clojure expressions (like loop and for): https://github.com/clojure/core.typed/wiki/User-Guide#typed-wrapper-macros

On the other hand, Lux's type-system is intimately connected to the compiler, and the type-checker works properly with all Lux expressions.