4
votes

I understand that Lisps are (usually) dynamically typed, but I guess their values still have types. Functions are values in lisps, so I wonder what is the type of function +?

List of numbers -> number seemed most likely, so I tried (+ '(2 3)) and (+ [2 3]) in Clojure, but neither worked.

Is it possible to query the type of a value (or expression) in Clojure REPL?

2

2 Answers

4
votes

It's actually quite a complex type that is tricky to define formally for a number of reasons:

  • It's a multi-arity function (accepts an variable number of parameters). Note that this is different from a function that takes a single parameter which is a list of numbers. If you want to use + on a list of numbers you need to use apply e.g. (apply + [1 2 3 4])
  • Each parameter can be a Number of any type. There are many possible number types, indeed anything that extends the java.lang.Number base class would suffice.
  • Inlined versions are defined which can directly produce primitive types as a result.

There isn't an easy way to determine this from the REPL. But you might be interested in Typed Clojure which provides a type system along with methods to define types and do corresponding type checking in Clojure. It uses a neat approach called "gradual typing", so you can add type annotations just where you need them: you don't need to assign types to the whole program at once.

1
votes

Clojure has the type function.

> (type +)
clojure.core$_PLUS_

> (type clojure.core$_PLUS_)
java.lang.Class

> (type (+ 1 1))
java.lang.Long

> (type (+ 1.0 1.0))
java.lang.Double

So the + function returns either a Long or a Double depending on the arguments.

The other arithmetic functions also return different types depending on the arguments:

> (type (/ 3 1))
java.lang.Long

> (type (/ 3.0 1))
java.lang.Double

> (type (/ 1 3))
clojure.lang.Ratio

If you want to see how the function is implemented, it's as simple as visiting the source. This lets you see how to define multi-arity functions.