Type system of Go/C# Seminar Ralf Vogler TU-München 15.11.2018
Outline Go & C# Static vs. dynamic typing Nominal vs. structural Duck typing Explicit vs. implicit declaration Go: interfaces C#: CTS, LINQ, dynamic Summary Dynamic in C# 4.0
Go Go (Google, 2009) Imperative, compiled, garbage-collected, concurrent “It's a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.” [golang.org] Channels (based on Hoare’s Communicating Sequential Processes)
C# C# (Microsoft, 2001) Compiled, garbage-collected Multi-paradigm: imperative & functional, object-oriented, generic .NET: CLI, CTS, CLR, DLR C# 4.0 April 2010 CLI .. Common Language Infrastructure (Spec.) CTS .. Common Type System CLR.. Common Language Runtime (garbage collection, JIT…) DLR .. Dynamic Language Runtime (IronRuby, IronPython)
Static vs. dynamic typing Type checking during compile-time ActionScript 3, Ada, C, C++, C#, D, Eiffel, F#, Fortran, Go, Haskell, Java, ML, Objective-C, OCaml, Pascal, Scala Dynamic Type checking during run-time APL, Erlang, Groovy, JavaScript, Lisp, Lua, PHP, Prolog, Python, Ruby, Smalltalk, Clojure, Tcl
Static vs. dynamic typing Example (C# 4.0) // static int a = "1"; // type error at compile-time // dynamic dynamic b = "1"; // b.GetType() = System.String int c = b; // type error at run-time int d = int.Parse(b); // ok
Static vs. dynamic typing Verification: type errors caught early Type checking done once -> faster Developer needs to think about types Dynamic Testing: type errors might be hard to find Overhead of type checking during run-time Easier to learn, fast prototyping Design/Planning Complex projects: not really relevant whether static or dynamic (Facebook: PHP)
Static vs. dynamic typing Example (PHP)
Static vs. dynamic typing Example (PHP) Praktisch, weil meistens das was man will Erschwert Fehlersuche
Nominal vs. structural Example Nominal typing in C# struct A { public int i; } struct B { public int i; } … A a; B b; b = a; // compile-time error
Nominal vs. structural Nominal (name-based) Type-compatible if declarations name same type C, C++, C#, Java… Structural (property-based) Type-compatible if types have the same structure Go (interfaces), ML, OCaml, Haskell, C++ templates
Duck typing Example Duck typing in C# dynamic s = "Hello"; s.ToUpper(); // ok, method of System.String s.foo(); // run-time exception
Duck typing checks whether object has called method at run-time -> style of dynamic typing Structural & nominative typing: checks at compile-time
Duck typing Go Interfaces are implemented by implementing their methods, no type inheritance “Static duck typing” -> safe C# Duck typing for objects of type dynamic Go: type-safe “duck typing” promotes separation of concerns and improves code re-use, and makes it easier to build on patterns that emerge as the code develops
Explicit vs. implicit declaration Java… Implicit: Local type inference: Go & C# (since 3.0) Complete type inference: Haskell, Standard ML, OCaml
Explicit vs. implicit declaration Type inference in Go: := Explicit: var s string = “hello” s = “good bye” Implicit: s := “hello” Type inference in C#: var 2.0: List<string> list = new List<string>(); Added in 3.0: var list = new List<string>();
package main import "fmt" type Walker interface { walk() } type Talker interface { talk() } type Duck struct {} type Human struct {} func (x Duck) walk() { fmt.Printf("Duck walks\n") } // Duck now automatically implements the Walker interface func (x Human) walk() { fmt.Printf("Human walks\n") } func (x Human) talk() { fmt.Printf("Human talks\n") } // Human implements the Walker and Talker interfaces now func doTheWalk(x Walker) { x.walk() } func main() { d := new(Duck) // type inference, d is of type Duck h := new(Human) // h of type Human doTheWalk(d) // call over the interface doTheWalk(h) h.talk() // call on the struct var d2 Walker = new(Duck) // explicit typing var h2 Walker = new(Human) d2 = h2 // ok because same interface d2.walk() // h2.talk() couldn't be accessed because it's not in the Walker interface } Go: interfaces C-like syntax, injected semicolons, type behind indentifier Reference types (channels, slices, maps), everything else value types (even arrays (length part of type)) Functions on every type possible (except pointers & interfaces)
C#: CTS Fig. 1. Common Type System [2] Single-root unified type system -> e.g. all have ToString(), GetType()… Value types (stack, structs (incl. all primitives), enums), Reference types (heap) Fig. 1. Common Type System [2]
C#: LINQ Example LINQ query with implicitly typed variables and lambda expression string[] names = { "Delta", "Charlie", "Bravo", "Alfa" }; // type IEnumerable<string> var query = from s in names where s.Length == 5 orderby s select s.ToUpper(); foreach (var item in query.Select(x => x+1)) Console.WriteLine(item); // BRAVO1, DELTA1 // additional Select() with lambda expression, LINQ does the same
C#: LINQ Example Anonymous types var book1 = new { Title = "A", Pages = 123 }; var book2 = new { Title = "B", Pages = 321 }; var book3 = new { Title = "C", Pages = 321, Author = "D" }; Console.WriteLine(book1); // { Title = A, Pages = 123 } book1 = book2; // ok because same type book2 = book3; // compile error because implicit conversion not possible Very useful for projections in LINQ-queries
C#: LINQ Example Nullable types int? n = 3; //same as using Nullable<int> n = 3 Console.WriteLine(n); // 3, same as n.Value n = null; Console.WriteLine(n.HasValue); // False DB
C#: dynamic Since C# 4.0 (2010) Still static type checking Type checking for objects of type dynamic is just deferred to run-time Main reason: interoperability (COM), LINQ, DLR, reflection much easier no framework type “dynamic” -> compiler does the work
C#: dynamic Example dynamic method dispatch, member lookup and object creation Action<dynamic> Print = x => Console.WriteLine(x); Func<dynamic,int> GetLength = x => x.Length; Print(123); // calls WriteLine(int) Print("abc"); // calls WriteLine(string) Print(GetLength("Hello, world")); // a string has a Length property Print(GetLength(new int[] { 1, 2, 3 })); // an array too Print(GetLength(42)); // but not an integer -> run-time exception dynamic foo = new ExpandoObject(); foo.att1 = "I'm dynamic"; foo.meth1 = Print; foo.meth1(foo.att1); // prints "I'm dynamic"
Summary Go C# Static type checking Structural type system “Duck typing” through interfaces Static type checking Nominative type system Duck typing on dynamic type Extra dynamic type Try it yourself: Go im Browser: http://golang.org/ C# Express oder VS kostenlos über Maniac
References The Go Programming Language, http://golang.org/ The C# Language, http://msdn.microsoft.com/en-us/vcsharp/aa336809