MarketFlow-sensitive typing
Company Profile

Flow-sensitive typing

In programming language theory, flow-sensitive typing is a type system where the type of an expression depends on its position in the control flow.

Examples
Ceylon See the following example in Ceylon which illustrates the concept: // Object? means the variable "name" is of type Object or else null void hello(Object? name) { if (is String name) { // "name" now has type String in this block print("Hello, ``name``!"); // and it is possible to call String methods on the variable print(" String.size is ``name.size``"); } else if (exists name) { // "name" now has type Object in this block print("Hello, object ``name``!"); } else { print("Hello, world!"); } } hello(null); hello(1); hello("John Doe"); and which outputs: Hello, world! Hello, object 1! Hello, John Doe! String.size is 8 Kotlin See this example in Kotlin: fun hello(obj: Any) { // A type cast fails if `obj` is not a String obj as String // Since the type cast did not fail, `obj` must be a String! val l = obj.length println("'$obj' is a string of length $l") } hello("Mooooo") == Benefits ==
Benefits
This technique coupled with type inference reduces the need for writing type annotations for all variables or to do type casting, like is seen with dynamic languages that use duck typing. It reduces verbosity and makes for terser code, easier to read and modify. It can also help language implementers provide implementations that execute dynamic languages faster by predicting the type of objects statically. Finally, it increases type safety and can prevent problems due to null pointers, labeled by C.A.R. Hoare—the null reference inventor—as "the billion dollar mistake" ==History and Implementations==
History and Implementations
The history of the idea goes back at least to Tony Hoare's "record class discriminators" from the mid-1960s. However, practical type systems including it as a feature are much more recent. Typed Scheme, a type system for Scheme developed by Sam Tobin-Hochstadt and first published in 2008, was the first type system to include occurrence typing. Its successor, Typed Racket (a dialect of Racket), is also based on occurrence typing. Shortly after Typed Scheme, David J. Pearce independently reinvented flow-typing in Whiley. Typed JavaScript observed that in "scripting" languages, flow-typing depends on more than conditional predicates; it also depends on state and control flow. This style has since been adopted in languages like Ceylon, TypeScript and Facebook Flow. There are also a few languages that don't have union types but do have nullable types, that have a limited form of this feature that only applies to nullable types, such as C#, Kotlin, and Lobster. ==Alternatives==
Alternatives
Pattern matching reaches the same goals as flow-sensitive typing, namely reducing verbosity and making up for terser code, easier to read and modify. It achieves this is in a different way, it allows to match the type of a structure, extract data out of it at the same time by declaring new variable. As such, it reduces the ceremony around type casting and value extraction. Pattern matching works best when used in conjunction with algebraic data types because all the cases can be enumerated and statically checked by the compiler. See this example mock for Java: int eval(Node n) { return switch(n) { // try to type cast "Node" into "IntNode", and create the variable "i" of type "int". // If that works, then return the value of "i" case IntNode(int i) -> i; // try to type cast "Node" into "NegNode", and create the variable "n" of type "Node". // If that works, then return the negation of evaluating the "n" node case NegNode(Node n) -> -eval(n); // try to type cast "Node" into "AddNode", and create the variables "left" and "right" of type "Node". // If that works, then return the addition of evaluating the "left" and "right" nodes case AddNode(Node left, Node right) -> eval(left) + eval(right); // try to type cast "Node" into "MulNode", and create the variables "left" and "right" of type "Node". // If that works, then return the multiplication of evaluating the "left" and "right" nodes case MulNode(Node left, Node right) -> eval(left) * eval(right); // no "default" because the compiler knows all the possible cases have been enumerated }; } In a statically typed language, the advantage of pattern matching over flow-sensitive typing is that the type of a variable always stays the same: it does not change depending on control flow. When writing down the pattern to be matched, a new variable is declared that will have the new type. ==References==
tickerdossier.comtickerdossier.substack.com