Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de programação funcional em .NET

434 Aufrufe

Veröffentlicht am

C# como você nunca viu: conceitos avançados de programação funcional em .NET

Veröffentlicht in: Bildung
  • Als Erste(r) kommentieren

TDC2016POA | Trilha .NET - C# como você nunca viu: conceitos avançados de programação funcional em .NET

  1. 1. C# como você nunca viu! Conceitos avançados de programação functional em .NET Elemar Júnior @elemarjr elemarjr@ravendb.net elemarjr@gmail.com elemarjr.com
  2. 2. Olá, eu sou Elemar Jr
  3. 3. Programação functional com C# Mas, vamos falar de
  4. 4. Func<int, int> square = x => x*x; var range = Enumerable.Range(1, 10); var sqs = range.Select(square); Funções são 1st class citzens
  5. 5. Func<int, bool> isEven = x => x%2 == 0; var original = new[] {4, 7, 9, 3, 2}; var sorted = original.OrderBy(x => x); var filtered = original.Where(isEven); Direcionamento a imutabilidade
  6. 6. using System; using System.Threading.Tasks; using static System.Linq.Enumerable; using static System.Console; class Program { static void Main() { Title = "Concurrent problems"; var data = Range(-10000, 20001).Reverse().ToList(); // [10000, 9999, .. -9999, -10000] Action t1 = () => WriteLine($"T1 = {data.Sum()}"); Action t2 = () => { data.Sort(); WriteLine($"T2 = {data.Sum()}"); }; Parallel.Invoke(t1, t2); } }
  7. 7. using System; using System.Threading.Tasks; using static System.Linq.Enumerable; using static System.Console; class Program { static void Main() { Title = "Concurrent problems"; var data = Range(-10000, 20001).Reverse().ToList(); // [10000, 9999, .. -9999, -10000] Action t1 = () => WriteLine($"T1 = {data.Sum()}"); Action t2 = () => { data.Sort(); WriteLine($"T2 = {data.Sum()}"); }; Parallel.Invoke(t1, t2); } }
  8. 8. using System; using System.Threading.Tasks; using static System.Linq.Enumerable; using static System.Console; class Program { static void Main() { Title = "Concurrent problems"; var data = Range(-10000, 20001).Reverse().ToList(); // [10000, 9999, .. -9999, -10000] Action t1 = () => WriteLine($"T1 = {data.Sum()}"); Action t2 = () => { data.Sort(); WriteLine($"T2 = {data.Sum()}"); }; Parallel.Invoke(t1, t2); } }
  9. 9. using System; using System.Threading.Tasks; using static System.Linq.Enumerable; using static System.Console; class Program { static void Main() { Title = "Concurrent problems"; var data = Range(-10000, 20001).Reverse().ToList(); // [100, 99, .. -99, -100] Action t1 = () => WriteLine($"T1 = {data.Sum()}"); Action t2 = () => WriteLine($"T2 = {data.OrderBy(x => x).Sum()}"); Parallel.Invoke(t1, t2); } }
  10. 10. class Rectangle { public double SideA { get; set; } public double SideB { get; set; } public Rectangle(double sideA, double sideB) { SideA = sideA; SideB = sideB; } public double Area => SideA*SideB; }
  11. 11. class Rectangle { public double SideA { get; set; } public double SideB { get; set; } public Rectangle(double sideA, double sideB) { SideA = sideA; SideB = sideB; } public double Area => SideA*SideB; }
  12. 12. struct class Rectangle { public double SideA { get; } public double SideB { get; } public Rectangle(double sideA, double sideB) { SideA = sideA; SideB = sideB; } public double Area => SideA*SideB; }
  13. 13. struct Rectangle { public double SideA { get; } public double SideB { get; } public Rectangle(double sideA, double sideB) { SideA = sideA; SideB = sideB; } public Rectangle WithSideA(double newSideA) => new Rectangle(newSideA, SideB); public Rectangle WithSideB(double newSideB) => new Rectangle(SideB, newSideB); public double Area => SideA*SideB; }
  14. 14. static IEnumerable<T> Where<T>( this IEnumerable<T> source, Func<T, bool> predicate ) { foreach (var e in source) { if (predicate(e)) yield return e; } } Você já conhece High-order functions
  15. 15. using System; using static System.Diagnostics.Debug; class Program { static void Main() { Func<int, int, int> divide = (a, b) => a/b; var divideBy = divide.SwapArgs(); Assert(divide(8, 2) == divideBy(2, 8)); } } static class Extensions { public static Func<T2, T1, TResult> SwapArgs<T1, T2, TResult>( this Func<T1, T2, TResult> f ) => (t2, t1) => f(t1, t2); }
  16. 16. using System; using static System.Console; class Resource : IDisposable { public Resource() { WriteLine("created ..."); } public void Foo() => WriteLine("Foo"); public void Fee() => WriteLine("Fee"); public void Dispose() => WriteLine("cleanup..."); } public class Program { public static void Main() { using (var r = new Resource()) { r.Foo(); r.Fee(); } } }
  17. 17. using System; using static System.Console; class Resource //: IDisposable { private Resource() { WriteLine("created ..."); } public void Foo() => WriteLine("Foo"); public void Fee() => WriteLine("Fee"); void Dispose() => WriteLine("cleanup..."); public static void Use(Action<Resource> block) { var r = new Resource(); // pooling? try { block(r); } finally { r.Dispose(); } } } public class Program { public static void Main() { Resource.Use(r => { r.Foo(); r.Fee(); }); } }
  18. 18. public class Program { public static void Main() { using (var reader = new StreamReader("file.txt")) { WriteLine(reader.ReadToEnd()); } } }
  19. 19. public class Program { public static void Main() { string content; using (var reader = new StreamReader("file.txt")) { content = reader.ReadToEnd(); } //.. } }
  20. 20. using System; using System.IO; using static Functional; using static System.Console; public class Program { public static void Main() { Using(new StreamReader("file.txt"), reader => { WriteLine(reader.ReadToEnd()); }); } } public static class Functional { public static void Using<T>( T input, Action<T> action ) where T : IDisposable { using (input) action(input); } }
  21. 21. public static TR Using<T, TR>( T input, Func<T, TR> func ) where T : IDisposable { using (input) return func(input); }
  22. 22. public class Program { public static void Main() { var content = Using(new StreamReader("file.txt"), reader => reader.ReadToEnd() ); } }
  23. 23. public static class Functional { public static void Using<T>( T input, Action<T> action ) where T : IDisposable { using (input) action(input); } public static TR Using<T, TR>( T input, Func<T, TR> func ) where T : IDisposable { using (input) return func(input); } } O problema com o Void
  24. 24. public class Program { public static void Main() { Using(new StreamReader("file.txt"), reader => { WriteLine(reader.ReadToEnd()); return Unit(); }); } } public struct Unit { } public static class Functional { static readonly Unit unit = new Unit(); public static Unit Unit() => unit; public static TR Using<T, TR>( T input, Func<T, TR> func ) where T : IDisposable { using (input) return func(input); } }
  25. 25. public static Func<T, Unit> ToFunc<T>(Action<T> action) => o => { action(o); return Unit(); }; Action<StreamReader> print = (s) => WriteLine(s.ReadToEnd()); Using(new StreamReader("file.txt"), ToFunc(print));
  26. 26. public interface IRepository<T, TId> { T GetById(TId id); } O problema com o null
  27. 27. public struct Option<T> { internal T Value { get; } public bool IsSome { get; } public bool IsNone => !IsSome; internal Option(T value, bool isSome) { IsSome = isSome; Value = value; } public TR Match<TR>(Func<T, TR> some, Func<TR> none) => IsSome ? some(Value) : none(); } public static class Option { public static Option<T> Of<T>(T value) => new Option<T>(value, value != null); }
  28. 28. public struct Option<T> { internal T Value { get; } public bool IsSome { get; } public bool IsNone => !IsSome; internal Option(T value, bool isSome) { IsSome = isSome; Value = value; } public TR Match<TR>(Func<T, TR> some, Func<TR> none) => IsSome ? some(Value) : none(); } public static class Option { public static Option<T> Of<T>(T value) => new Option<T>(value, value != null); } public static void Main() { string _ = null, s = "Elemar"; var o1 = Option.Of(_); // None var o2 = Option.Of(s); // Some("Elemar") }
  29. 29. public struct Option<T> { internal T Value { get; } public bool IsSome { get; } public bool IsNone => !IsSome; internal Option(T value, bool isSome) { IsSome = isSome; Value = value; } public TR Match<TR>(Func<T, TR> some, Func<TR> none) => IsSome ? some(Value) : none(); } public static class Option { public static Option<T> Of<T>(T value) => new Option<T>(value, value != null); } public static void Main() { string _ = null, s = "Elemar"; var o1 = Option.Of(_); // None var o2 = Option.Of(s); // Some("Elemar") } public void SayHello(string name) => WriteLine(GreetingFor(name)); public string GreetingFor(string name) => Option.Of(name).Match( some: n => $"Hello {n}", none: () => "Sorry..." );
  30. 30. public struct NoneType { } public static class Functional { public static Option<T> Some<T>(T value) => Option.Of(value); public static readonly NoneType None = new NoneType(); … public struct Option<T> { ... public static readonly Option<T> None = new Option<T>(); public static implicit operator Option<T>(T value) => Some(value); public static implicit operator Option<T>(NoneType _) => None; }
  31. 31. public class Program { public static void Main() { SayHello("Elemar"); SayHello(null); } public static void SayHello(string name) => WriteLine(GreetingFor(name)); public static string GreetingFor(Option<string> name) => name.Match( some: n => $"Hello {n}", none: () => "Sorry..." ); }
  32. 32. public static class Option { public static Option<T> Of<T>(T value) => new Option<T>(value, value != null); public static Option<TR> Map<T, TR>( this Option<T> @this, Func<T, TR> func) => @this.IsSome ? Some(func(@this.Value)) : None; } public static void Main() { string _ = null, s = "Elemar"; Func<string, string> greetingFor = name => $"Hello {name}"; var o1 = Option.Of(_).Map(greetingFor); // None var o2 = Option.Of(s).Map(greetingFor); // Some("Hello Elemar") }
  33. 33. public static class Option { public static Option<T> Of<T>(T value) => new Option<T>(value, value != null); public static Option<TR> Map<T, TR>( this Option<T> @this, Func<T, TR> func) => @this.IsSome ? Some(func(@this.Value)) : None; } Option<string> _ = null, s = "Elemar"; _.Map(n => $"Hello {n}"); s.Map(n => $"Hello {n}");
  34. 34. public static Option<Unit> ForEach<T>( this Option<T> @this, Action<T> action) => Map(@this, ToFunc(action)); Option<string> _ = null, s = "Elemar"; _.Map(n => $"Hello {n}").ForEach(WriteLine); s.Map(n => $"Hello {n}").ForEach(WriteLine);
  35. 35. var host = AppSettings["RavenDB.Host"] ?? "localhost"; int port; if (!int.TryParse(AppSettings["RavenDB.Port"], out port)) port = 8080; // ..
  36. 36. public static class Parsing { public static Option<int> ParseInt(this string s) { int result; return int.TryParse(s, out result) ? Some(result) : None; } }
  37. 37. public static T GetOrElse<T>( this Option<T> @this, Func<T> fallback) => @this.Match( some: value => value, none: fallback ); public static T GetOrElse<T>( this Option<T> @this, T @else) => GetOrElse(@this, () => @else);
  38. 38. var host = AppSettings["RavenDB.Host"] ?? "localhost"; var port = AppSettings["RavenDB.Port"].ParseInt().GetOrElse(8080);
  39. 39. public static Option<T> Where<T>( this Option<T> @this, Func<T, bool> predicate ) => @this.IsSome && predicate(@this.Value) ? @this : None;
  40. 40. var host = AppSettings["RavenDB.Host"] ?? "localhost"; var port = AppSettings["RavenDB.Port"].ParseInt() .Where(p => p > 0) .GetOrElse(8080);
  41. 41. public interface IRepository<T, TId> { Option<T> GetById(TId id); }
  42. 42. public void Run() { WriteLine("Starting..."); var f30 = Fibonacci(30); var f35 = Fibonacci(35); var f40 = Fibonacci(40); var f45 = Fibonacci(45); WriteLine("Results: {0}, {1}, {2}, {3}", f30, f35, f40, f45); WriteLine("Done!"); } public int Fibonacci(int n) { if (n == 0) return 0; if (n == 1) return 1; return Fibonacci(n - 1) + Fibonacci(n - 2); }
  43. 43. public void Run2() { Func<int, int> fibonacci = Fibonacci; WriteLine("Starting..."); var f30 = fibonacci(30); var f35 = fibonacci(35); var f40 = fibonacci(40); var f45 = fibonacci(45); WriteLine($"Results: {f30}, {f35}, {f40}, {f45}"); WriteLine("Done!"); }
  44. 44. public void Run3() { Func<int, int> fibonacci = Fibonacci; WriteLine("Starting..."); var f30 = fibonacci(30); WriteLine($"Input: 30 Result: {f30}"); var f35 = fibonacci(35); WriteLine($"Input: 35 Result: {f35}"); var f40 = fibonacci(40); WriteLine($"Input: 40 Result: {f40}"); var f45 = fibonacci(45); WriteLine($"Input: 50 Result: {f45}"); WriteLine($"Results: {f30}, {f35}, {f40}, {f45}"); WriteLine("Done!"); }
  45. 45. public static class Combinators { public static Func<T, TResult> Print<T, TResult>(Func<T, TResult> func) { return (input) => { var result = func(input); WriteLine($"Input: {input} Result: {result}"); return result; }; } }
  46. 46. public void Run4() { var fibonacci = Combinators.Print<int, int>(Fibonacci); WriteLine("Starting..."); var f30 = fibonacci(30); var f35 = fibonacci(35); var f40 = fibonacci(40); var f45 = fibonacci(45); WriteLine($"Results: {f30}, {f35}, {f40}, {f45}"); WriteLine("Done!"); }
  47. 47. public static Func<T, TResult> Time<T, TResult>(Func<T, TResult> func) { return (input) => { var before = DateTime.Now; var result = func(input); WriteLine($"Time to this input: {DateTime.Now - before}"); return result; }; }
  48. 48. public void Run5() { var fibonacci = Combinators.Time( Combinators.Print<int, int>(Fibonacci) ); WriteLine("Starting..."); var f30 = fibonacci(30); var f35 = fibonacci(35); var f40 = fibonacci(40); var f45 = fibonacci(45); WriteLine($"Results: {f30}, {f35}, {f40}, {f45}"); WriteLine("Done!"); }
  49. 49. public static double Divide(double a, double b) { if (Math.Abs(b) < 0.00001) { throw new ArgumentException("b could not be 0."); } return a/b; } O problema com o Exceptions
  50. 50. public struct Either<TL, TR> { internal TL Left { get; } internal TR Right { get; } public bool IsLeft => !IsRight; public bool IsRight { get; } internal Either(TL left) { IsRight = false; Left = left; Right = default(TR); } internal Either(TR right) { IsRight = true; Right = right; Left = default(TL); } public static implicit operator Either<TL, TR>(TL left) => new Either<TL, TR>(left); public static implicit operator Either<TL, TR>(TR right) => new Either<TL, TR>(right); }
  51. 51. public static Either<string, double> Divide(double a, double b) { if (Math.Abs(b) < 0.00001) { return "b could not be 0."; } return a/b; }
  52. 52. public TR Match<TR>(Func<L, TR> left, Func<R, TR> right) => IsLeft ? left(Left) : right(Right); public Unit Match<TR>(Action<L> left, Action<R> right) => Match(ToFunc(left), ToFunc(right));
  53. 53. WriteLine(Divide(a, b).Match( right: res => $"Result {res}", left: error => $"Error {error}") );
  54. 54. elemarjr.com @elemarjr linkedin.com/in/elemarjr elemarjr@ravendb.net elemarjr@gmail.com Mantenha contato!
  55. 55. C# como você nunca viu! Conceitos avançados de programação functional em .NET Elemar Júnior @elemarjr elemarjr@ravendb.net elemarjr@gmail.com elemarjr.com

×