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 konstruktorzepublic 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 konstruktoramiabstract 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 LINQWszystkie 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/