Marcin Malinowski
Tata^2, mąż humanistki, mól książkowy, uparciuch, programista, konferencjoholik. Don Kichot walczący z entropią. Kocha sprzeczności i humor. Wierzy w przypadek. Piwny filozof. W nielicznych wolnych chwilach harata w gałę (na bramce).
Basic, Turbo Pascal/C, Assembler, Clipper, MS Access, Visual Basic, Java-XML :), C++, C#, JavaScript, F#... i ze wszystkiego miałem frajdę, ale nie za wszystkim tęsknię.
Absolwent informatyki i matematyki na UW. Tech lead w firmie Piątka.
Spojrzenie...
...do cudzego ogródka (Java) ...za siebie (C# 1-5) ...przed siebie (C# 6) ...przez ramię (C# 7+) ...z lotu ptaka
Zalety:
Wady:
Usunięte w ostatniej chwili z Preview:
Note: - skąd się to wzięło, kto nam tak język komplikuje? - inne: semicolon operator: var y = (var x = Foo(); Write(x); x * x)) - finalnie w C# 6: https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6
Don Syme is the designer and architect of the F# programming language [...] Earlier, created generics in the .NET Common Language Runtime, including the initial design of generics for the C# programming language [...]
F# dziś:
type Point(x, y) = member this.X = x member this.Y = y
C# 6 Preview:
public class Point(int x, int y) { private int x, y; }
public class Point(int x, int y) { public int X { get; } = x; public int Y { get; } = y; }konstruktory wyleciały prawd. z powodu planowanych rekordów, ale można inicjować w zwykłym konstruktorze
public class Customer { public string Name { get; } // backing field is readonly public Customer(string first, string last) { Name = first + " " + last; } }
F# dziś:
module Math = let Add x y = x + y Math.Add 2 2 open Math Add 2 2
C# 6:
public static class Math { public static int Add(int x, int y) { return x + y; } } using static Math; Add(2, 2); using static System.Console; WriteLine("Hello World!");czyli używajmy funkcji jak ludzie (w C# 7 funkcje na globalnym poziomie?)
F# dziś:
let success, x = Int32.TryParse("123") // lub match TryParse("123") with true, x -> ... | _ -> ...
C# 6 Preview:
if (int.TryParse("123", out int x)) // x dostępne else ...
F# dziś:
type ErrorCode = | UnexpectedArgument | InvalidFormat exception ArgsException of ErrorCode try raise (ArgsException UnexpectedArgument) with | ArgsException UnexpectedArgument -> printfn "Unexpected argument" | ArgsException _ -> printfn "Other parsing error"
C# 6:
try { throw new ArgsException(ErrorCode.UnexpectedArgument); } catch (ArgsException e) when (e.ErrorCode == ErrorCode.UnexpectedArgument) {...}
F# dziś:
let (>>=) x y = Option.bind y x // generalnie mało przydatne
C# 6:
var bestValue = points?.FirstOrDefault()?.X ?? -1; int? first = customers?[0].Orders?.Count();
F# dziś: ha, ha - wolne żarty
member thix.Move x y = Point(X + dx, Y + dy) member this.Distance = Math.Sqrt((X * X) + (Y * Y))
C# 6:
public Point Move(int dx, int dy) => new Point(X + dx, Y + dy); // property public double Distance => Math.Sqrt((X * X) + (Y * Y));
F# dziś:
let tuple = (5, "y")
C# 6 Preview:
// zamiast new Tuple<int, string>(5, "y") / Tuple.Create(5, "y") var tuple = new Tuple(5, "y"); // zamiast new KeyValuePair<string, Tuple<int, string>>(...) var pair = new KeyValuePair("x", tuple);
C# 7 Design Meeting Notes:
Let’s continue being inspired by functional languages, and in particular other languages – F#, Scala, Swift – that aim to mix functional and object-oriented concepts as smoothly as possible
C# dziś:
var e = s as ExpressionStatement; if (e != null) { var a = e.Expr as AssignmentExpressionSyntax; if (a != null) { var l = a.Left as IdentifierName; var r = a.RIght as IdentifierName; if (l != null && r != null & l.Name.name == r.Name.name) ...
C# 7:
if (s is ExpressionStatement( AssignmentExpressionSyntax(IdentifierName l, IdentifierName r)) && l.name = r.name) ... // lub switch (s) { case ExpressionStatement( AssignmentExpressionSyntax(IdentifierName l, IdentifierName r) where (l.name == r.name): ... }
Rekord to niezmienna klasa o semantyce value type. Zamiast pisać:
public class Point { public Point(int x, int y) { this.X = x; this.Y = y; } public int X { get; } public int Y { get; } public override int GetHashCode() {...} public override bool Equals(...) {...} // New pattern-matching decomposition operator public static bool operator is(Point self out int x, out int y) {...} }
Wystarczy:
class Point(int X, int Y); var p1 = new Point(15, 6); var p2 = p1 with { Y = 21 }; // == new Point(p1.X, 21) if (p1 is Point { X is 15, Y is int y }) ... if (p2 is Point(int x, 21)) ...prawdopodobnie przez to wstrzymali się z głównymi konstruktorami
abstract class Expr; class X() : Expr; class Const(double Value) : Expr; class Mult(Expr Left, Expr Right) : Expr; ... Expr Simplify(Expr e) { switch (e) { case Mult(Const(0), *): return Const(0); case Mult(*, Const(0)): return Const(0); case Mult(Const(1), var x): return Simplify(x); case Mult(var x, Const(1)): return Simplify(x); case Mult(Const(var l), Const(var r)): return Const(l*r); ... } }
public class Variable : Exception { public string Name { get; set; } } public class Add : Exception { public Exception Left { get; set; } public Exception Right { get; set; } } public static int Evaluate(Exception e, IDictionary<string, int> vars) { int res; try { throw e; } catch (Variable v) when (vars.TryGetValue(v.Name, out res)) { return res; } catch (Variable _) { throw new ArgumentException("Variable not found!"); } catch (Add a) { return Evaluate(a.Left, vars) + Evaluate(a.Right, vars); } }
F# dziś:
let tally = List.fold (fun (sum, count) v -> (sum + v, count + 1)) (0, 0)
C# dziś:
public void Tally(IEnumerable<int> values, out int sum, out int count) {...} public Tuple<int, int> Tally(IEnumerable<int> values) {...}
C# 7:
public (int sum, int count) Tally(IEnumerable<int> values) { var sum = 0; var count = 0; foreach (var v in values) { sum += v; count++; } return (sum, count); } var t = Tally(myValues); Console.WriteLine($"Sum: {t.sum}, count: {t.count}");wygodne w połączeniu z LINQ
Wszystkie pola readonly:
public readonly class Args { ...
Rekurencyjnie wszystkie pola readonly (faktycznie niezmienna klasa):
public immutable class Args { ...
string? n; // nullable string string! s; // non-nullable string n = null; // Ok s = null; // Error! WriteLine(s.Length); // Ok WriteLine(n.Length); // Error! if (n is string! ns) WriteLine(ns.Length); // Ok
Wyobraź sobie scriptcs wbudowany w VS, zintegrowany z Debuggerem i zastępujący "immediate window"...
lepszy REPL będzie już w VS 2015 update 1Żyjemy w ciekawych czasach :)
- FP jest trudne, może boleć głowa ;) - nie chodzi o to bym Was nauczył, a zainspirować: programowanie jest fajne!Materiały:
Ankieta: https://www.surveymonkey.com/r/QCT96FT Pls!
http://goqr.me/