Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Julia dynamically typed?

A lot of blogs, and the manual itself, say that Julia is dynamically typed. But from my reading of the manual, it sounds to me more like it is statically typed with type inference, like F#.

  • Is Julia statically typed with type inference?
  • Is it dynamically typed?
  • I'm assuming it is dynamically typed, it seems unlikely the manual is wrong.
  • Is type inference involved in Julia at all?
like image 570
Lyndon White Avatar asked Jan 21 '15 22:01

Lyndon White


People also ask

Is Julia a dynamic language?

Dynamic languages have become popular for scientific computing. They are generally considered highly productive, but lacking in performance.

Is Julia gradually typed?

Julia is dynamically typed, but in well-written julia code the types can usually be inferred. You often get a major performance enhancement when that is possible. There's some discussion of this in the FAQ.

Is Julia strongly typed?

Julia is strongly typed like OCaml. Julia has dynamic typing, not static. You can specify types, but they don't really do anything except help with performance. A far cry from OCaml's great type inference and compile time static checking.


1 Answers

Tim Holy's answer is quite correct, but I'll elaborate a bit. First, let's define some terms – you may disagree with my definitions, but at least you'll know what I'm saying. The primary difference between static and dynamic languages, in my view, is this: in static languages, expressions have types; in dynamic languages, values have types.

In a static language, there are rules for determining the type of every expression in a program. The types of expressions dictate the behavior of the program. A program that doesn't admit a consistent type to be determined for every expression is considered incorrect and will not compile. In the presence of polymorphism, the type of an expression may not be a single concrete type: parametric polymorphism can be thought of as a way of letting the same code describe a whole family of concretely typed algorithms, indexed by the parameters of the types; subtype polymorphism can be thought of as introducing a limited amount of dynamic behavior into an otherwise static language.

Dynamic languages, on the other hand do not have rules for assigning types to expressions: types are implied by the way data flows through the program as it executes. In general, expressions can potentially produce values of any type at all. Because of this, type theorists sometimes describe dynamic languages as "unityped" – i.e. from the static perspective, where a "type" is inherently a property of an expression, all expressions in a dynamic language have the type Any. Of course, that's applying the static notion of type – which is only meaningful for expressions – to a language where the notion of type is only meaningful for values.

Julia is squarely in the dynamic camp: types are a property of values not expressions. The result type of code is determined by how values flow through it when it executes; the language does not include any rules for assigning types to expressions before executing them. Unlike many dynamic languages, however, Julia has a fairly sophisticated language for talking about types, and you can annotate expressions with types. For example, x::T is an assertion that x is a value of type T; if that is true, x::T evaluates to the value of x, otherwise an error is raised and the expression returns no value. Type annotations in method signatures have a slightly different meaning: instead of asserting the type of an existing value, they indicate that the method only applies if the corresponding argument is of the indicated type. In either case, the following code can safely assume that the value of x is of type T.

[Aside: In some languages with "gradual" or "optional" typing, type annotations switch the language from dynamic to static mode: methods without type annotations are dynamic; methods with type annotations are static. In static code, there are rules for assigning types to all expressions and the code must satisfy those. This is not the way Julia works – code with type annotations is still dynamic and has the same semantics as code without type annotations.]

Type inference in languages like F#, OCaml or Haskell is part of how the types of expressions are determined. If the compiler cannot infer the type of any expression, your program is broken and will not compile. These languages all use some form of Hindley-Milner type inference, which is a very clever way to derive the types of expressions from the structure of the code without having to write out explicit types (compare this to dynamic languages where the types are implied by execution of the code). Much of the time no type annotations are required at all, which is quite pleasant compared to the verbose type declarations which can be necessary in languages like C++, C# and Java. This is very different, however, from dynamic languages like Julia and Python where no type annotations are required simply because it is perfectly acceptable for expressions not to have a predetermined type. In Hindley-Milner languages, you may not have to write as many types as in C++ or Java, but every expression must have a predetermined type that the compiler can compute.

Julia's compiler does type inference, but it is very different: it is not necessary for every expression to have an inferrable type. The compiler analyzes code to try to predict the types of expressions and uses that information to generate more efficient machine code. But if it can't determine the type of an expression, it's no big deal: the compiler just emits generic code that will work anyway, using run-time type information. For the most part in Julia, type inference is just an optimization – your code will work the same way with or without it – but with successful type inference, it will run a lot faster.

like image 72
StefanKarpinski Avatar answered Sep 19 '22 08:09

StefanKarpinski