Is Clojure Uni-Typed?
Asked Answered
G

2

8

Robert Harper has written a fascinating piece called "Dynamic languages are static languages". In it he writes:

And this is precisely what is wrong with dynamically typed languages: rather than affording the freedom to ignore types, they instead impose the bondage of restricting attention to a single type! Every single value has to be a value of that type, you have no choice!

This has come to mean uni-typed languages. (Languages of a single type).

Now Clojure claims to be a dynamic language:

Clojure is a dynamic programming language that targets the Java Virtual Machine (and the CLR, and JavaScript). It is designed to be a general-purpose language, combining the approachability and interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming. Clojure is a compiled language - it compiles directly to JVM bytecode, yet remains completely dynamic. Every feature supported by Clojure is supported at runtime.

By 'dynamic' they mean 'can be interacted with at runtime', rather than 'doesn't have types'.

Now the key distinction being made between static and dynamic seems to be "can I get a type-failure at compile-time?"

If I write the following Clojure code:

(deftype circle-type [radius] )

(deftype square-type [side-length])


(defn def-check-type [new-symbol-type existing-symbol]
 (let [existing-symbol-type (type existing-symbol)]
    (cond 
     (= new-symbol-type existing-symbol-type) 
     (def new-symbol existing-symbol)
     :else (str "types didn't match: " new-symbol-type " : " existing-symbol-type))))

(println (def-check-type circle-type (square-type. 2)));)

Then compile it in Leiningen:

lein uberjar

Then I get the following:

$ lein uberjar
Compiling clojure-unittyped.core
types didn't match: class clojure_unittyped.core.circle-type : class clojure_unittyped.core.square-type

Which would appear to be a type-failure at compile-time in a dynamic language.

My question is: Is Clojure Uni-Typed?


Edit - I'm aware of core.typed - which is an excellent piece of work. I'm asking the question separate to that.

Gaylordgaylussac answered 25/4, 2014 at 1:26 Comment(3)
I don't think you'll find widespread usage of this "uni-typed" idea. He (Robert Harper) appears to uses it to codify his concern, although I cannot find widespread usage or support for such a "uni-typed" classification..Kraus
Apart from other remarks here, it's worth noting that dynamically typed vs. statically typed is not really a Boolean property. C is often considered statically typed, with good reason, but you can fool the compiler about types quite easily using pointers. (I'd say that dynamic/statically typed is a matter of degree, but that's just a crude way of putting it.) So passing or failing one test isn't necessarily enough to classify a language as one or the other.Villalobos
How does a run-time if-then-else conditioned on comparing run-time types in any way appear to be a type failure at compile-time?Vasty
G
11

Yes, Clojure is uni-typed, however Sam Tobin-Hochstadt argues the uni-typed classification is not very informative in practice.

The uni-typed theory reveals little about the nature of programming in a dynamically typed language; it's mainly useful for justifying the existence of "dynamic" types in type theory.

Projects like Typed Racket were invented precisely to discover and model the implicit type information utilised by programmers in such languages. Often types are quite accurate, and shows there's a lot more going on than meets the eye.

Geof answered 25/4, 2014 at 7:2 Comment(0)
S
8

I read it. I don't get it. But, as the author Robert Harper guesses, I didn't go to Carnegie Mellon. We seem to have a bunch of vitriol directed at straw men followed eventually by what amounts to the startling conclusion that dynamically typed languages are dynamically typed.

The main confusion here is between the terms "dynamic programming language" and "dynamically typed". These are not the same thing. A dynamic programming language can have a robust static type system for example, even though most do not. Harper is perpetuating this confusion by mixing terms.

Dynamic languages

The description of Clojure that you quoted is about Clojure being a "dynamic programming language".

Every feature supported by Clojure is supported at runtime.

The point is that the full power of Clojure is available at runtime. You can add new code, add new types, extend protocols to existing types, etc., all dynamically at runtime.

This is worth bragging about.

So, when Harper asks sarcastically, "So, hey, dynamic languages are cool, right?", I answer sincerely, "Yes, sir, they are, but apparently we aren't talking about the same thing!".

Dynamic types

Dynamically typed vs. statically typed is a whole other issue. Clojure is not bragging about not having a robust type system. Most Clojurians would welcome the option, hence the interest in core.typed. There is a lot to be said for the type system of Haskell for example. No one is really challenging that.

Your example

In your example, you are blurring run-time with compile-time (which is already blurry with a dynamic language in which the full power of the compiler is available at runtime). The type checking you did occurs at the run-time of your println statement. In Clojure, values have types, the storage location of reference types (such as var you created with def) do not.

Your question

To answer your title question, Clojure falls under the heading of dynamically typed. You can call dynamically typed "uni-typed" if you really want to; but, at least in the context of that article, it looks like that term is being used as a pejorative. Just call it dynamically typed, we know what that means.

The bigger issue though is that if you are focusing on dynamically vs statically typed, you are missing the, yes, totally cool, point of Clojure being a dynamic programming language. Projects like core.typed will eventually provide the typing. The cool parts will remain.

Siple answered 25/4, 2014 at 2:53 Comment(2)
It can be explained that what is often called a dynamically typed programming language is a "late bound" programming language - it only figures out what code it actually needs to find for a given function call at the last moment, at runtime, just before it actually has to call it. On the other hand, an early bound language like Haskell has sorted all that out during the compilation phase. These are not necessarily replacements for static/dynamic typing as terms, but can help (if nothing else highlighting that there's no simple distinction, many languages exhibit both ideas to some extent).Pyroelectricity
@MatthewWalton I think you may be in danger of mixing dynamic ("late") binding with dynamic dispatch. But, yes, to your point, one should distinguish "dynamic programming language" from "dynamically typed language" from language with "dynamic binding" from language with "dynamic dispatch". Some of these terms necessarily imply others, but not conversely. Clojure can/does resolve name symbols and methods at compile time (for the most part - you can ask for warnings when it cannot and provide type hints). Clojure also has both static and dynamic dispatch.Siple

© 2022 - 2024 — McMap. All rights reserved.