SlideShare a Scribd company logo
1 of 38
WIESŁAW KAŁKUS
Holte Software
Poland
Functional Programming
Is it possible in C#?
Today’s Agenda
C# Functional Programming
Is It Worth An Effort? Maybe It Is
Controlling Complexity
Composition Function Composition
Programming Example
Copying Photo Files Implementation Variants
What Is Functional Programming?
Theoretical Perspective C# Programmer Perspective
What is Functional
Programming?
What Is Functional Programming?
Wikipedia
Functional Programming is a programming paradigm,
a style of building the structure and elements of
computer programs, that treats computations as the
evaluation of mathematical functions and avoids
changing-state and mutable data. It is a declarative
programming paradigm, which means programming is
done with expressions.
Programming Paradigms
• Focus on describing how a program operates
• Programs described in terms of statements that change a program
state
• Structural (procedures as main actors) and object-oriented (objects as
main actors) programming styles fall into imperative paradigm
Imperative
• Focus on describing what a program should accomplish without
prescribing how to do it in terms of sequences of actions to be taken
• Programs expressed in terms of computation logic without describing
its control flow
• Functional (mathematical function as main actor) programming style
falls into declarative paradigm
Declarative
Multi-paradigm programming languages
Type inference (C# & F#)
Anonymous functions (C# & F#)
Language Integrated Query (C#
& F#)
Currying (F#)
Pattern matching (F#)
Lazy evaluation (F#)
Tail recursion (F#)
Immutability (F#)
Control statements (C#)
Classes (C#)
.NET framework (C# & F#)
Do notation (F#)
Declarative
Imperative
Object-Oriented vs. Functional Programming Style
Characteristic Object-oriented (imperative) approach Functional (declarative) approach
Programmer focus
How to perform tasks (algorithms) and
how to track changes in state.
What information is desired and what
transformations are required.
State changes Important. Localized and tightly controlled.
Order of execution Important. Low importance.
Primary flow control
Loops, conditionals, and function
(method) calls.
Function calls, including recursion.
Primary manipulation unit Instances of structures or classes.
Functions as first-class objects and data
collections.
Programming Example
Programming Example – problem statement
Copy photo files from the source folder (include subfolders) to the
destination folder (create subfolders as necessary). While copying
rename each file using pattern <base-name><sequence-number>.
Sequence numbers should preserve the order of date taken for each
photo. Additionally allow for each source photo file to create multiple
copies of the file in the target folder (useful for extending time-lapse
photography sequences).
Programming Example – object-oriented approach
foreach (sourceFile in sourceFilesSortedByPhotoDateTaken)
{
try
{
CreateTargetFolderPathIfNecessary
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor)
{
MakeNewTargetFileName
CopySourceFileToTheTargetFolderUnderTheNewName
fileCopyCount += 1
}
}
catch
{
}
}
Programmer focus on how to perform
tasks (algorithms) and how to track
changes in state.
Programming Example – object-oriented approach
foreach (sourceFile in sourceFilesSortedByPhotoDateTaken)
{
try
{
CreateTargetFolderPathIfNecessary
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor)
{
MakeNewTargetFileName
CopySourceFileToTheTargetFolderUnderTheNewName
fileCopyCount += 1
}
}
catch
{
}
}
var sourceFiles = .Visit (sourceFolder);
sourceFiles.Sort( .ByDateTaken);
foreach (var sourceFile in sourceFiles) {
try {
CreateTargetFolderPathIfNecessary
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor) {
MakeNewTargetFileName
CopySourceFileToTheTargetFolderUnderTheNewName
fileCopyCount += 1
}
}
catch{
}
}
public static class FolderVisitor {
public static List<FileInfo> Visit(string rootFolder) {
return DoVisitFolder(rootFolder);
}
private static List<FileInfo> DoVisitFolder(string folder) {
var files = new List<FileInfo>();
var thisFolder = new DirectoryInfo(folder);
files.Add(thisFolder.EnumerateFiles());
var subFolders = thisFolder.EnumerateFolders();
foreach (var folder in subFolders) {
files.Add(DoVisitFolder(subfolder.FullName));
}
return files;
}
}
public static class Photo {
public static int ByDateTaken (FileInfo f1, FileInfo f2) {
if (f1 == null && f2 == null) {
return 0;
} else if (f1 == null) {
return -1;
} else if (f2 == null) {
return 1;
}
return Photo.DateTaken(f1).CompareTo(Photo.DateTaken(f1));
}
private static DateTime DateTaken(FileInfo f) {
DateTime dateTaken = DateTime.Now;
try {
using (var reader = ExifReader (f.FullName)) {
reader.GetTagValue<DateTime>(
ExifTags.DateTimeDigitized,
our dateTaken);
}
}
catch (IOException) {}
return dateTaken;
}
}
Add files from the
current folder.
Recursively add files
from subfolders.
Open source Exif Library
– read EXIF tag from the
photo file.
Programming Example – object-oriented approach
var sourceFiles = FolderVisitor.Visit (sourceFolder);
sourceFiles.Sort(Photo.ByDateTaken);
foreach (var sourceFile in sourceFiles) {
try {
CreateTargetFolderPathIfNecessary
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor) {
MakeNewTargetFileName
CopySourceFileToTheTargetFolderUnderTheNewName
fileCopyCount += 1
}
}
catch{
}
}
public static class FolderHelper {
public static void MaterializeFolder(string root string path) {
var realtivePath = path.SubString(root.Length);
if (string.IsNullOrWhitespace(relativePath)) {
return;
}
var segments = relativePath.Split(new char[] {
Path.DirectorySeparatorChar,
Path.AltDirectorySeparatorChar
}, StringSplitOptions.RemoveEmptyEntries);
var workingPath = root;
foreach (var segment in segments) {
workingPath = Path.Combine(workingPath, segment);
if (!Directory.Exists(workingPath)) {
Directory.CreateDirectory(workingPath);
}
}
}
}
Create missing
folders.
Programming Example – object-oriented approach
var sourceFiles = FolderVisitor.Visit (sourceFolder);
sourceFiles.Sort(Photo.ByDateTaken);
foreach (var sourceFile in sourceFiles) {
try {
FolderHelper.MaterializeFolder(targetFolder, sourceFile.Directory.FullName);
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor) {
MakeNewTargetFileName
CopySourceFileToTheTargetFolderUnderTheNewName
fileCopyCount += 1
}
}
catch{
}
}
public static class FolderHelper {
public static void CopyFile(string targetRoot,
FileInfo sourceFile, string fileNameBase, int sequenceNo) {
var newFileName = string.Format(„{0}{1}{2}”,
fileNameBase, sequenceNo,
Path.GetExtension(sourceFile.Name));
var realtivePath = sourceFile
.Directory.FullName
.SubString(targetRoot.Length);
var targetPath = Path.Combine(targetRoot, relativePath,
newFileName);
sourceFile.CopyTo(targetPath);
}
}
Make target file
name
Extract target
relative path.
Create target
absolute path.Copy source file to
the target folder.
Programming Example – object-oriented approach
var sourceFiles = FolderVisitor.Visit (sourceFolder);
sourceFiles.Sort(Photo.ByDateTaken);
foreach (var sourceFile in sourceFiles) {
try {
FolderHelper.MaterializeFolder(targetFolder, sourceFile.Directory.FullName);
fileCopyCount = 0
while (fileCopyCount < PhotoFileCopyMultiplicationFactor) {
FolderHelper.CopyFile(targetFolder, sourceFile,
newFileNameBase, sequenceNo);
fileCopyCount += 1;
sequenceNo += 1;
}
}
catch{
}
}
Make a list of source files.Sort source files by the
photo date taken.
Ensure target folder.
Make required file copies.
Update copying process state.
Programming Example – functional approach
• Make the list of source files
• Sort the source file list by picture date taken
• Make the list of pairs - source file and target
folder path
• Make the list of tuples – boolean flag
indicating sucessful file copy, source file,
copy operation status (destination path or
error message)
Programmer focus on what
information is desired and what
transformations are required.
Programming Example – functional approach
• Sort the source file list by picture date taken
• Make the list of pairs - source file and target
folder path
• Make the list of tuples – boolean flag
indicating sucessful file copy, source file,
copy operation status (destination path or
error message)
• Make the list of source filesvar sourceFiles = .Visit (sourceFolder);
type public FileVisitor() =
static member private folderFiles folderPath filter =
let emptyDirectory = List.Empty.AsEnumerable()
let dirInfo = new DirectoryInfo(folderPath)
try
dirInfo.EnumerateFiles(filter)
with
| :? ArgumentException -> emptyDirectory
| :? DirectoryNotFoundException -> emptyDirectory
| :? SecurityException -> emptyDirectory
| :? UnauthorizedAccessException -> emptyDirectory
static member private subFolders folderPath =
let dirInfo = new DirectoryInfo(folderPath)
let noSubFolders = List.Empty.AsEnumerable()
try
dirInfo.EnumerateDirectories()
with
| :? DirectoryNotFoundException -> noSubFolders
| :? SecurityException -> noSubFolders
| :? UnauthorizedAccessException -> noSubFolders
static member public Visit rootFolder fileNameFilter =
seq { yield! FileVisitor.folderFiles rootFolder fileNameFilter
for subFolder in FileVisitor.subFolders rootFolder do
yield! FileVisitor.Visit subFolder.FullName fileNameFilter }
A sequence is a logical series of elements all of one
type. Sequences are particularly useful when you have
a large, ordered collection of data but do not
necessarily expect to use all the elements. Individual
sequence elements are computed only as required, so
a sequence can provide better performance than a list
in situations in which not all the elements are used.
var sourceFiles = FolderVisitor.Visit (sourceFolder);IEnumerable<FileInfo>
Programming Example – functional approach
• Make the list of pairs - source file and target
folder path
• Make the list of tuples – boolean flag
indicating sucessful file copy, source file,
copy operation status (destination path or
error message)
var sourceFiles = FolderVisitor.Visit (sourceFolder);
• Sort the source file list by picture date taken
var sortedFiles = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken);
IEnumerable<FileInfo>
public static class Photo {
public static DateTime DateTaken(FileInfo f) {
DateTime dateTaken = DateTime.Now;
try {
using (var reader = ExifReader (f.FullName)) {
reader.GetTagValue<DateTime>(
ExifTags.DateTimeDigitized,
our dateTaken);
}
}
catch (IOException) {}
return dateTaken;
}
}
Programming Example – functional approach
• Make the list of pairs - source file and
target folder path
var sortedFiles = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken);
• Make the list of tuples – boolean flag
indicating sucessful file copy, source file,
copy operation status (destination path or
error message)
var copier =new (targetFolder, baseName, seqStart, noCopies);
var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath);
public class FileCopier {
private readonly string _targetFolder;
private readonly string _baseName;
private readonly int _noOfCopies;
private int _sequenceNo;
public FileCopier(string targetFolder, string baseName, int seqStart, int noOfCopies) {
_targetFolder = targetFolder;
_baseName = baseName;
_noOfCopies = noOfCopies;
_sequenceNo = seqStart;
}
public IEnumerable<Tuple<FileInfo, string>> MakeTargetPath(FileInfo file) {
var result = new List<Tuple<FileInfo, string>();
for (var i = 0; i < _noOfCopies; ++i) {
var newFileName = string.Format(„{0}{1}{2}”, _baseName, _sequenceNo,
Path.GetExtension(file.Name));
var realtivePath = file.Directory.FullName.SubString(_targetFolder.Length);
var targetPath = Path.Combine(_targetFolder, relativePath, newFileName);
result.Add(new Tuple<FileInfo, string>(file, targetPath));
_sequenceNo += 1;
}
return result;
}
}
var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies);
var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath);
IEnumerable<Tuple<FileInfo, string>>
Projects each element of a sequence to an IEnumerable<T> and
flattens the resulting sequences into one sequence.
public static IEnumerable<TResult> SelectMany<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TResult>> selector
)
Programming Example – functional approach
• Make the list of tuples – boolean flag
indicating sucessful file copy, source file,
copy operation status (destination path or
error message)
var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies);
var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath);
var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies);
var fileCopyStatus = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath)
.SelectMany(copier.CopyFile);
public class FileCopier {
private readonly string _targetFolder;
private readonly string _baseName;
private readonly int _noOfCopies;
private int _sequenceNo;
public FileCopier(string targetFolder, string baseName, int seqStart, int noOfCopies) {
_targetFolder = targetFolder;
_baseName = baseName;
_noOfCopies = noOfCopies;
_sequenceNo = seqStart;
}
public IEnumerable<Tuple<bool, FileInfo, string>> CopyFile(Tuple<FileInfo, string> file) {
var result = new List<Tuple<bool, FileInfo, string>();
try {
MaterializeFolder(_targetFolder, file.Item2);
file.Item1.CopyTo(file.Item2);
result.Add(new Tuple<bool, FileInfo, string>(true, file.Item1, file.Item2);
} catch (Exception ex) {
result.Add(new Tuple<bool, FileInfo, string>(false, file.Item1, ex.Message);
}
return result;
}
}
IEnumerable<Tuple<bool, FileInfo, string>>
Programming Example – functional approach
var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies);
var fileCopyStatus = FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath)
.SelectMany(copier.CopyFile);
var fileCopyObserver = new ();
fileCopyStatus.Subscribe (fileCopyObserver);
Console.WriteLine(fileCopyObserver.Summary());
public class FileCopyObserver : IObserver<Tuple<bool, FileInfo, string> {
private int _copiedFileCount;
private int _errorCount;
public string Summary() {
return string.Format(„Attempt to copy {0} files; {1} successful; {2} errors.”,
_copiedFileCount + _errorCount, _copiedFileCount, _errorCount);
}
public void OnCompleted() { }
public void OnError (Exception error) {}
public void OnNext(Tuple<bool, FileInfo, string> copyStatus) {
if (copyStatus.Item1) {
_copiedFileCoput += 1;
} else {
_errorCount += 1;
}
}
}
var fileCopyObserver = new FileCopyObserver();
fileCopyStatus.Subscribe (fileCopyObserver);
Console.WriteLine(fileCopyObserver.Summary());
System.Reactive.Linq
Programming Example – Object-Oriented vs Functional approach
var sourceFiles =
FolderVisitor.Visit (sourceFolder);
sourceFiles.Sort(Photo.ByDateTaken);
foreach (var sourceFile in sourceFiles) {
try {
FolderHelper.MaterializeFolder(targetFolder,
sourceFile.Directory.FullName);
fileCopyCount = 0
while (fileCopyCount < noOfCopies) {
FolderHelper.CopyFile(targetFolder,
sourceFile,
newFileNameBase,
sequenceNo);
fileCopyCount += 1;
sequenceNo += 1;
}
}
catch{
}
}
var copier = new FileCopier(targetFolder,
baseName,
seqStart,
noCopies);
var fileCopyStatus =
FolderVisitor.Visit (sourceFolder)
.OrderBy(Photo.DateTaken)
.SelectMany(copier.MakeTargetPath)
.SelectMany(copier.CopyFile);
var fileCopyObserver = new FileCopyObserver();
fileCopyStatus.Subscribe (fileCopyObserver);
Console.WriteLine(fileCopyObserver.Summary());
Control
statements,
state changes Function call
composition
Controlling Complexity By
Controlling Complexity
Composition
Composition is the key to controlling complexity in software.
Expert programmers control the complexity of their designs by
combining primitive elements to form compound objects, they
abstract compound objects to form higher-level building blocks.
One form of composition, function composition, describes the
dependencies between function calls.
Function Composition
Function composition takes two functions and passes the result of
the second function as the argument of the first function –
effectively creating one function taking argument of the second
function and returning result of the first function.
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
Anonymous function (lambda) calling second function (g) with argument x and
passing its result as first function (f) argument, and returning the result of the
first function.
Function Composition
var r = f(g(x))
•Explicit
dependency
between f and g
var r = f.Compose(g)(x)
•Abstracted
dependency
between f and g
Abstract compound objects to form higher-level building blocks
Function Composition Laws
• Identity.Compose(f) = f
Left
identity
• f.Compose(Identity) = f
Right
identity
• f.Compose(g.Compose(h) =
(f.Compose(g)).Compose(h)Associative
public static T Identity<T>(this T value)
{
return value;
}
Function Composition – sometimes values are not enough
Generic (constructed) types package (amplify) values (integers,
strings, objects of class T)
The type IEnumerable<T> represents a lazily computed list of values
of type T
The type IEnumerable<T> packages (amplifies) the type T
Function Composition with IEnumerable<T>
public static Func<T, IEnumerable<V>> Compose<T, U, V>(
this Func<U, IEnumerable<V>> f,
Func<T, IEnumerable<U>> g)
{
return x => f(g(x));
}
Error – g(x) returns IEnumerable<U> while f takes U
We need to bind the result of g(x) with the function f. Binding will
iterate over a list returned by g(x) and pass individual list items to
the function f. The result of binding g(x) to the function f is a list of
results returned by the function f.
public static Func<T, IEnumerable<V>> Compose<T, U, V>(
this Func<U, IEnumerable<V>> f,
Func<T, IEnumerable<U>> g)
{
return x => g(x).Bind(f);
}
public static IEnumerable<V> Bind (
this IEnumerable<U> m,
Func<U, IEnumerable<V>> f)
public static IEnumerable<V> Bind (this IEnumerable<U> items, Func<U, IEnumerable<V>> f)
{
var result = new List<V>();
foreach (var item in items)
{
result.Add(f(item));
}
return result;
}
Function Composition with IEnumerable<T>
• Our Bind function allows the function f to use IEnumerable returned by the function g
• We need some function converting a type T to IEnumverable<T>
public static IEnumerable<T> Unit (this T value)
• Together the amplified type IEnumerable<T>,
the function Bind, and the function Unit enable
function composition with amplified values
A
type
A Unit
function
A Bind
function
Monad
Monads enable function
composition with amplified values
Monads Satisfy Function Composition Laws
•Unit(v).Bind(f) = f(v)Left identity
•m.Bind(Unit) = mRight identity
•m.Bind(x => k(x).Bind(y => h(y)) =
m.Bind(x =>k(x)).Bind(y => h(y))
Associative
Creating a Monad
To define a particular monad, the writer
supplies the triple (a Type, a Unit function,
and a Bind function), thereby specyfying
the mechanics of the aplified values
IEnumerable<T> Monad
IEnumerable<T> Monad
SelectMany
function
AsEnumerable
function
Type
T
C# Functional
Programming
C# Functional Programming
• Is it worth an effort?
• Maybe it is
• The Maybe monad is an example of a monadic
container type wrapping a value. The container
can either have a value or have missing value.
The Maybe monad is a better nullable type.
C# Functional Programming – Maybe monad
public class Maybe<T> {
public readonly static Maybe<T> Nothing = new Maybe<T>();
public bool IsNothing { get; private set; }
public T Just { get; private set; }
public Maybe() {
IsNothing = true;
Just = default(T);
}
public Maybe(T value) {
IsNothing = false;
Just = value;
}
public new string ToString() {
if (IsNothing) {
return "Nothing";
}
return Just.ToString();
}
}
Nothing represents all instances lacking a value.
Just the value if we have one.
We have the type. Now we need the Unit and
Bind functions to have the Maybe monad.
The Unit function which we call AsMaybe,
wraps a value.
The Bind function which we call SelectMany,
takes a Maybe instance and if there is a value
then it applies the delegate to the contained
value. Otherwise, it returns Nothing.
Maybe monad – Unit and Bind functions
public static class MaybeExtensions {
public static Maybe<T> AsMaybe<T> (this T value){
return new Maybe<T>(value);
}
public static Maybe<U> SelectMany<T, U>(this Maybe<T> m,
Func<T, Maybe<U>> doSemthingWith) {
if (m == null) {
return Maybe<U>.Nothing;
}
if (m.IsNothing) {
return Maybe<U>.Nothing;
}
try {
return doSomethingWith(m.Just);
}
catch (Exception) {
return Maybe<U>.Nothing;
}
}
}
The Unit function which we call AsMaybe, wraps
a value.
The Bind function which we call SelectMany,
takes a Maybe instance and if there is a value
then it applies the delegate to the contained
value. Otherwise, it returns Nothing.
The delegate takes the un-wrapped value of the
type T and returns wrapped (amplified) value of
the type U – we can bind another delegate to
ther result Maybe<U>.
Maybe monad – usage examples
var maybeStringArray = (new string[] {„Ala”, „ma”, „kota”}).AsMaybe();
var maybeResult = maybeStringArray
.SelectMany(x => x.FirstOrDefault(s => s.Equals(„Ala”)).AsMaybe())
.SelectMany(s => s.ToUpperInvariant().AsMaybe());
Console.WriteLine(maybeResult.ToString());
maybeResult = maybeStringArray
.SelectMany(x => x.FirstOrDefault(s => s.Equals(„Ola”)).AsMaybe())
.SelectMany(s => s.ToUpperInvariant().AsMaybe());
Console.WriteLine(maybeResult.ToString());
Writes ALA.
Writes Nothing.
Maybe<string>
Questions

More Related Content

What's hot

Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravelwajrcs
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Jonas Follesø
 
Zend Studio Tips and Tricks
Zend Studio Tips and TricksZend Studio Tips and Tricks
Zend Studio Tips and TricksRoy Ganor
 
...and thus your forms automagically disappeared
...and thus your forms automagically disappeared...and thus your forms automagically disappeared
...and thus your forms automagically disappearedLuc Bors
 
Dependency Injection with Unity Container
Dependency Injection with Unity ContainerDependency Injection with Unity Container
Dependency Injection with Unity ContainerMindfire Solutions
 
JavaFX Dependency Injection with FxContainer
JavaFX Dependency Injection with FxContainerJavaFX Dependency Injection with FxContainer
JavaFX Dependency Injection with FxContainerSrikanth Shenoy
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfoliomwillmer
 
Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1willmation
 
Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDeclan Whelan
 
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 Ecosystem
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 EcosystemSpark IT 2011 - Context & Dependency Injection in the Java EE 6 Ecosystem
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 EcosystemArun Gupta
 
Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Stephan Hochdörfer
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection SmellsMatthias Noback
 
Dependency injection with unity 2.0 Dmytro Mindra Lohika
Dependency injection with unity 2.0 Dmytro Mindra LohikaDependency injection with unity 2.0 Dmytro Mindra Lohika
Dependency injection with unity 2.0 Dmytro Mindra LohikaAlex Tumanoff
 
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Greg Szczotka
 

What's hot (19)

Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008Silverlight 2 for Developers - TechEd New Zealand 2008
Silverlight 2 for Developers - TechEd New Zealand 2008
 
Zend Studio Tips and Tricks
Zend Studio Tips and TricksZend Studio Tips and Tricks
Zend Studio Tips and Tricks
 
CDI @javaonehyderabad
CDI @javaonehyderabadCDI @javaonehyderabad
CDI @javaonehyderabad
 
...and thus your forms automagically disappeared
...and thus your forms automagically disappeared...and thus your forms automagically disappeared
...and thus your forms automagically disappeared
 
Dependency Injection with Unity Container
Dependency Injection with Unity ContainerDependency Injection with Unity Container
Dependency Injection with Unity Container
 
Introduction to CDI
Introduction to CDIIntroduction to CDI
Introduction to CDI
 
IoC with PHP
IoC with PHPIoC with PHP
IoC with PHP
 
JavaFX Dependency Injection with FxContainer
JavaFX Dependency Injection with FxContainerJavaFX Dependency Injection with FxContainer
JavaFX Dependency Injection with FxContainer
 
.NET Portfolio
.NET Portfolio.NET Portfolio
.NET Portfolio
 
Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1Behaviour Driven Development V 0.1
Behaviour Driven Development V 0.1
 
Java
Java Java
Java
 
Domain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with Rails
 
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 Ecosystem
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 EcosystemSpark IT 2011 - Context & Dependency Injection in the Java EE 6 Ecosystem
Spark IT 2011 - Context & Dependency Injection in the Java EE 6 Ecosystem
 
Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11
 
Testing untestable code - DPC10
Testing untestable code - DPC10Testing untestable code - DPC10
Testing untestable code - DPC10
 
Dependency Injection Smells
Dependency Injection SmellsDependency Injection Smells
Dependency Injection Smells
 
Dependency injection with unity 2.0 Dmytro Mindra Lohika
Dependency injection with unity 2.0 Dmytro Mindra LohikaDependency injection with unity 2.0 Dmytro Mindra Lohika
Dependency injection with unity 2.0 Dmytro Mindra Lohika
 
Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014Dependency injection Drupal Camp Wrocław 2014
Dependency injection Drupal Camp Wrocław 2014
 

Similar to Wiesław Kałkus: C# functional programming

Automating Content Import
Automating Content ImportAutomating Content Import
Automating Content ImportDavid Lippman
 
Python Programming for ArcGIS: Part II
Python Programming for ArcGIS: Part IIPython Programming for ArcGIS: Part II
Python Programming for ArcGIS: Part IIDUSPviz
 
Consuming Libraries with CMake
Consuming Libraries with CMakeConsuming Libraries with CMake
Consuming Libraries with CMakeRichard Thomson
 
Eclipse Day India 2011 - Extending JDT
Eclipse Day India 2011 - Extending JDTEclipse Day India 2011 - Extending JDT
Eclipse Day India 2011 - Extending JDTdeepakazad
 
3.1 file input and output
3.1   file input and output3.1   file input and output
3.1 file input and outputallenbailey
 
Library management system
Library management systemLibrary management system
Library management systemsiddiqui241993
 
Drupal 8 meets to symphony
Drupal 8 meets to symphonyDrupal 8 meets to symphony
Drupal 8 meets to symphonyBrahampal Singh
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talkdtdannen
 
Jaffle: managing processes and log messages of multiple applications in devel...
Jaffle: managing processes and log messages of multiple applicationsin devel...Jaffle: managing processes and log messages of multiple applicationsin devel...
Jaffle: managing processes and log messages of multiple applications in devel...Masaki Yatsu
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Pythondn
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenchesIsmail Mayat
 
Files and Directories in PHP
Files and Directories in PHPFiles and Directories in PHP
Files and Directories in PHPNicole Ryan
 

Similar to Wiesław Kałkus: C# functional programming (20)

Automating Content Import
Automating Content ImportAutomating Content Import
Automating Content Import
 
Python Programming for ArcGIS: Part II
Python Programming for ArcGIS: Part IIPython Programming for ArcGIS: Part II
Python Programming for ArcGIS: Part II
 
Consuming Libraries with CMake
Consuming Libraries with CMakeConsuming Libraries with CMake
Consuming Libraries with CMake
 
Persistences
PersistencesPersistences
Persistences
 
Eclipse Day India 2011 - Extending JDT
Eclipse Day India 2011 - Extending JDTEclipse Day India 2011 - Extending JDT
Eclipse Day India 2011 - Extending JDT
 
3.1 file input and output
3.1   file input and output3.1   file input and output
3.1 file input and output
 
Library management system
Library management systemLibrary management system
Library management system
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
Power tools in Java
Power tools in JavaPower tools in Java
Power tools in Java
 
Local Storage
Local StorageLocal Storage
Local Storage
 
Drupal 8 meets to symphony
Drupal 8 meets to symphonyDrupal 8 meets to symphony
Drupal 8 meets to symphony
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talk
 
IR with lucene
IR with luceneIR with lucene
IR with lucene
 
Jaffle: managing processes and log messages of multiple applications in devel...
Jaffle: managing processes and log messages of multiple applicationsin devel...Jaffle: managing processes and log messages of multiple applicationsin devel...
Jaffle: managing processes and log messages of multiple applications in devel...
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
 
Examiness hints and tips from the trenches
Examiness hints and tips from the trenchesExaminess hints and tips from the trenches
Examiness hints and tips from the trenches
 
Basic Make
Basic MakeBasic Make
Basic Make
 
Helberg acl-final
Helberg acl-finalHelberg acl-final
Helberg acl-final
 
CodeIgniter & MVC
CodeIgniter & MVCCodeIgniter & MVC
CodeIgniter & MVC
 
Files and Directories in PHP
Files and Directories in PHPFiles and Directories in PHP
Files and Directories in PHP
 

More from AnalyticsConf

Dawid Gonzo Kałędowski: R jako osobisty GPS
Dawid Gonzo Kałędowski: R jako osobisty GPSDawid Gonzo Kałędowski: R jako osobisty GPS
Dawid Gonzo Kałędowski: R jako osobisty GPSAnalyticsConf
 
Tor Hovland: Taking a swim in the big data lake
Tor Hovland: Taking a swim in the big data lakeTor Hovland: Taking a swim in the big data lake
Tor Hovland: Taking a swim in the big data lakeAnalyticsConf
 
Rafał Korszuń: Security in Design of Cloud Applications
Rafał Korszuń: Security in Design of Cloud ApplicationsRafał Korszuń: Security in Design of Cloud Applications
Rafał Korszuń: Security in Design of Cloud ApplicationsAnalyticsConf
 
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2AnalyticsConf
 
Grzegorz Rycaj: Zdebuguj swoja prezentacje
Grzegorz Rycaj: Zdebuguj swoja prezentacjeGrzegorz Rycaj: Zdebuguj swoja prezentacje
Grzegorz Rycaj: Zdebuguj swoja prezentacjeAnalyticsConf
 
Przemysław Dzierżak: Hurtownie dla DBA
Przemysław Dzierżak: Hurtownie dla DBAPrzemysław Dzierżak: Hurtownie dla DBA
Przemysław Dzierżak: Hurtownie dla DBAAnalyticsConf
 
Paweł Ciepły: PowerBI part1
Paweł Ciepły: PowerBI part1Paweł Ciepły: PowerBI part1
Paweł Ciepły: PowerBI part1AnalyticsConf
 
Paweł Kucharski: Oswajamy Słonia czyli po co nam Hadoop
Paweł Kucharski: Oswajamy Słonia czyli po co nam HadoopPaweł Kucharski: Oswajamy Słonia czyli po co nam Hadoop
Paweł Kucharski: Oswajamy Słonia czyli po co nam HadoopAnalyticsConf
 
Michał Żyliński: Cortana dla niewtajemniczonych
Michał Żyliński: Cortana dla niewtajemniczonychMichał Żyliński: Cortana dla niewtajemniczonych
Michał Żyliński: Cortana dla niewtajemniczonychAnalyticsConf
 
Shannon Holgate: Bending non-splittable data to harness distributed performance
Shannon Holgate: Bending non-splittable data to harness distributed performanceShannon Holgate: Bending non-splittable data to harness distributed performance
Shannon Holgate: Bending non-splittable data to harness distributed performanceAnalyticsConf
 
Tomasz Nadolny: Open Data in Gdańsk
Tomasz Nadolny: Open Data in GdańskTomasz Nadolny: Open Data in Gdańsk
Tomasz Nadolny: Open Data in GdańskAnalyticsConf
 
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktyka
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktykaWłodek Bielski: Efektywne wdrożenie BI - z notatnika praktyka
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktykaAnalyticsConf
 
Piotr Janczyk: Modele zachowań klientów
Piotr Janczyk: Modele zachowań klientówPiotr Janczyk: Modele zachowań klientów
Piotr Janczyk: Modele zachowań klientówAnalyticsConf
 
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...AnalyticsConf
 

More from AnalyticsConf (14)

Dawid Gonzo Kałędowski: R jako osobisty GPS
Dawid Gonzo Kałędowski: R jako osobisty GPSDawid Gonzo Kałędowski: R jako osobisty GPS
Dawid Gonzo Kałędowski: R jako osobisty GPS
 
Tor Hovland: Taking a swim in the big data lake
Tor Hovland: Taking a swim in the big data lakeTor Hovland: Taking a swim in the big data lake
Tor Hovland: Taking a swim in the big data lake
 
Rafał Korszuń: Security in Design of Cloud Applications
Rafał Korszuń: Security in Design of Cloud ApplicationsRafał Korszuń: Security in Design of Cloud Applications
Rafał Korszuń: Security in Design of Cloud Applications
 
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2
Tomasz Kopacz: Architektura i service fabric - jak budować aplikacje w paas v2
 
Grzegorz Rycaj: Zdebuguj swoja prezentacje
Grzegorz Rycaj: Zdebuguj swoja prezentacjeGrzegorz Rycaj: Zdebuguj swoja prezentacje
Grzegorz Rycaj: Zdebuguj swoja prezentacje
 
Przemysław Dzierżak: Hurtownie dla DBA
Przemysław Dzierżak: Hurtownie dla DBAPrzemysław Dzierżak: Hurtownie dla DBA
Przemysław Dzierżak: Hurtownie dla DBA
 
Paweł Ciepły: PowerBI part1
Paweł Ciepły: PowerBI part1Paweł Ciepły: PowerBI part1
Paweł Ciepły: PowerBI part1
 
Paweł Kucharski: Oswajamy Słonia czyli po co nam Hadoop
Paweł Kucharski: Oswajamy Słonia czyli po co nam HadoopPaweł Kucharski: Oswajamy Słonia czyli po co nam Hadoop
Paweł Kucharski: Oswajamy Słonia czyli po co nam Hadoop
 
Michał Żyliński: Cortana dla niewtajemniczonych
Michał Żyliński: Cortana dla niewtajemniczonychMichał Żyliński: Cortana dla niewtajemniczonych
Michał Żyliński: Cortana dla niewtajemniczonych
 
Shannon Holgate: Bending non-splittable data to harness distributed performance
Shannon Holgate: Bending non-splittable data to harness distributed performanceShannon Holgate: Bending non-splittable data to harness distributed performance
Shannon Holgate: Bending non-splittable data to harness distributed performance
 
Tomasz Nadolny: Open Data in Gdańsk
Tomasz Nadolny: Open Data in GdańskTomasz Nadolny: Open Data in Gdańsk
Tomasz Nadolny: Open Data in Gdańsk
 
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktyka
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktykaWłodek Bielski: Efektywne wdrożenie BI - z notatnika praktyka
Włodek Bielski: Efektywne wdrożenie BI - z notatnika praktyka
 
Piotr Janczyk: Modele zachowań klientów
Piotr Janczyk: Modele zachowań klientówPiotr Janczyk: Modele zachowań klientów
Piotr Janczyk: Modele zachowań klientów
 
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...
Alex Kornilov: Building Big Data Company in Sports-Betting Industry - BETEGY ...
 

Recently uploaded

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 

Recently uploaded (20)

Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 

Wiesław Kałkus: C# functional programming

  • 1. WIESŁAW KAŁKUS Holte Software Poland Functional Programming Is it possible in C#?
  • 2. Today’s Agenda C# Functional Programming Is It Worth An Effort? Maybe It Is Controlling Complexity Composition Function Composition Programming Example Copying Photo Files Implementation Variants What Is Functional Programming? Theoretical Perspective C# Programmer Perspective
  • 4. What Is Functional Programming? Wikipedia Functional Programming is a programming paradigm, a style of building the structure and elements of computer programs, that treats computations as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions.
  • 5. Programming Paradigms • Focus on describing how a program operates • Programs described in terms of statements that change a program state • Structural (procedures as main actors) and object-oriented (objects as main actors) programming styles fall into imperative paradigm Imperative • Focus on describing what a program should accomplish without prescribing how to do it in terms of sequences of actions to be taken • Programs expressed in terms of computation logic without describing its control flow • Functional (mathematical function as main actor) programming style falls into declarative paradigm Declarative
  • 6. Multi-paradigm programming languages Type inference (C# & F#) Anonymous functions (C# & F#) Language Integrated Query (C# & F#) Currying (F#) Pattern matching (F#) Lazy evaluation (F#) Tail recursion (F#) Immutability (F#) Control statements (C#) Classes (C#) .NET framework (C# & F#) Do notation (F#) Declarative Imperative
  • 7. Object-Oriented vs. Functional Programming Style Characteristic Object-oriented (imperative) approach Functional (declarative) approach Programmer focus How to perform tasks (algorithms) and how to track changes in state. What information is desired and what transformations are required. State changes Important. Localized and tightly controlled. Order of execution Important. Low importance. Primary flow control Loops, conditionals, and function (method) calls. Function calls, including recursion. Primary manipulation unit Instances of structures or classes. Functions as first-class objects and data collections.
  • 9. Programming Example – problem statement Copy photo files from the source folder (include subfolders) to the destination folder (create subfolders as necessary). While copying rename each file using pattern <base-name><sequence-number>. Sequence numbers should preserve the order of date taken for each photo. Additionally allow for each source photo file to create multiple copies of the file in the target folder (useful for extending time-lapse photography sequences).
  • 10. Programming Example – object-oriented approach foreach (sourceFile in sourceFilesSortedByPhotoDateTaken) { try { CreateTargetFolderPathIfNecessary fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { MakeNewTargetFileName CopySourceFileToTheTargetFolderUnderTheNewName fileCopyCount += 1 } } catch { } } Programmer focus on how to perform tasks (algorithms) and how to track changes in state.
  • 11. Programming Example – object-oriented approach foreach (sourceFile in sourceFilesSortedByPhotoDateTaken) { try { CreateTargetFolderPathIfNecessary fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { MakeNewTargetFileName CopySourceFileToTheTargetFolderUnderTheNewName fileCopyCount += 1 } } catch { } } var sourceFiles = .Visit (sourceFolder); sourceFiles.Sort( .ByDateTaken); foreach (var sourceFile in sourceFiles) { try { CreateTargetFolderPathIfNecessary fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { MakeNewTargetFileName CopySourceFileToTheTargetFolderUnderTheNewName fileCopyCount += 1 } } catch{ } } public static class FolderVisitor { public static List<FileInfo> Visit(string rootFolder) { return DoVisitFolder(rootFolder); } private static List<FileInfo> DoVisitFolder(string folder) { var files = new List<FileInfo>(); var thisFolder = new DirectoryInfo(folder); files.Add(thisFolder.EnumerateFiles()); var subFolders = thisFolder.EnumerateFolders(); foreach (var folder in subFolders) { files.Add(DoVisitFolder(subfolder.FullName)); } return files; } } public static class Photo { public static int ByDateTaken (FileInfo f1, FileInfo f2) { if (f1 == null && f2 == null) { return 0; } else if (f1 == null) { return -1; } else if (f2 == null) { return 1; } return Photo.DateTaken(f1).CompareTo(Photo.DateTaken(f1)); } private static DateTime DateTaken(FileInfo f) { DateTime dateTaken = DateTime.Now; try { using (var reader = ExifReader (f.FullName)) { reader.GetTagValue<DateTime>( ExifTags.DateTimeDigitized, our dateTaken); } } catch (IOException) {} return dateTaken; } } Add files from the current folder. Recursively add files from subfolders. Open source Exif Library – read EXIF tag from the photo file.
  • 12. Programming Example – object-oriented approach var sourceFiles = FolderVisitor.Visit (sourceFolder); sourceFiles.Sort(Photo.ByDateTaken); foreach (var sourceFile in sourceFiles) { try { CreateTargetFolderPathIfNecessary fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { MakeNewTargetFileName CopySourceFileToTheTargetFolderUnderTheNewName fileCopyCount += 1 } } catch{ } } public static class FolderHelper { public static void MaterializeFolder(string root string path) { var realtivePath = path.SubString(root.Length); if (string.IsNullOrWhitespace(relativePath)) { return; } var segments = relativePath.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); var workingPath = root; foreach (var segment in segments) { workingPath = Path.Combine(workingPath, segment); if (!Directory.Exists(workingPath)) { Directory.CreateDirectory(workingPath); } } } } Create missing folders.
  • 13. Programming Example – object-oriented approach var sourceFiles = FolderVisitor.Visit (sourceFolder); sourceFiles.Sort(Photo.ByDateTaken); foreach (var sourceFile in sourceFiles) { try { FolderHelper.MaterializeFolder(targetFolder, sourceFile.Directory.FullName); fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { MakeNewTargetFileName CopySourceFileToTheTargetFolderUnderTheNewName fileCopyCount += 1 } } catch{ } } public static class FolderHelper { public static void CopyFile(string targetRoot, FileInfo sourceFile, string fileNameBase, int sequenceNo) { var newFileName = string.Format(„{0}{1}{2}”, fileNameBase, sequenceNo, Path.GetExtension(sourceFile.Name)); var realtivePath = sourceFile .Directory.FullName .SubString(targetRoot.Length); var targetPath = Path.Combine(targetRoot, relativePath, newFileName); sourceFile.CopyTo(targetPath); } } Make target file name Extract target relative path. Create target absolute path.Copy source file to the target folder.
  • 14. Programming Example – object-oriented approach var sourceFiles = FolderVisitor.Visit (sourceFolder); sourceFiles.Sort(Photo.ByDateTaken); foreach (var sourceFile in sourceFiles) { try { FolderHelper.MaterializeFolder(targetFolder, sourceFile.Directory.FullName); fileCopyCount = 0 while (fileCopyCount < PhotoFileCopyMultiplicationFactor) { FolderHelper.CopyFile(targetFolder, sourceFile, newFileNameBase, sequenceNo); fileCopyCount += 1; sequenceNo += 1; } } catch{ } } Make a list of source files.Sort source files by the photo date taken. Ensure target folder. Make required file copies. Update copying process state.
  • 15. Programming Example – functional approach • Make the list of source files • Sort the source file list by picture date taken • Make the list of pairs - source file and target folder path • Make the list of tuples – boolean flag indicating sucessful file copy, source file, copy operation status (destination path or error message) Programmer focus on what information is desired and what transformations are required.
  • 16. Programming Example – functional approach • Sort the source file list by picture date taken • Make the list of pairs - source file and target folder path • Make the list of tuples – boolean flag indicating sucessful file copy, source file, copy operation status (destination path or error message) • Make the list of source filesvar sourceFiles = .Visit (sourceFolder); type public FileVisitor() = static member private folderFiles folderPath filter = let emptyDirectory = List.Empty.AsEnumerable() let dirInfo = new DirectoryInfo(folderPath) try dirInfo.EnumerateFiles(filter) with | :? ArgumentException -> emptyDirectory | :? DirectoryNotFoundException -> emptyDirectory | :? SecurityException -> emptyDirectory | :? UnauthorizedAccessException -> emptyDirectory static member private subFolders folderPath = let dirInfo = new DirectoryInfo(folderPath) let noSubFolders = List.Empty.AsEnumerable() try dirInfo.EnumerateDirectories() with | :? DirectoryNotFoundException -> noSubFolders | :? SecurityException -> noSubFolders | :? UnauthorizedAccessException -> noSubFolders static member public Visit rootFolder fileNameFilter = seq { yield! FileVisitor.folderFiles rootFolder fileNameFilter for subFolder in FileVisitor.subFolders rootFolder do yield! FileVisitor.Visit subFolder.FullName fileNameFilter } A sequence is a logical series of elements all of one type. Sequences are particularly useful when you have a large, ordered collection of data but do not necessarily expect to use all the elements. Individual sequence elements are computed only as required, so a sequence can provide better performance than a list in situations in which not all the elements are used. var sourceFiles = FolderVisitor.Visit (sourceFolder);IEnumerable<FileInfo>
  • 17. Programming Example – functional approach • Make the list of pairs - source file and target folder path • Make the list of tuples – boolean flag indicating sucessful file copy, source file, copy operation status (destination path or error message) var sourceFiles = FolderVisitor.Visit (sourceFolder); • Sort the source file list by picture date taken var sortedFiles = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken); IEnumerable<FileInfo> public static class Photo { public static DateTime DateTaken(FileInfo f) { DateTime dateTaken = DateTime.Now; try { using (var reader = ExifReader (f.FullName)) { reader.GetTagValue<DateTime>( ExifTags.DateTimeDigitized, our dateTaken); } } catch (IOException) {} return dateTaken; } }
  • 18. Programming Example – functional approach • Make the list of pairs - source file and target folder path var sortedFiles = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken); • Make the list of tuples – boolean flag indicating sucessful file copy, source file, copy operation status (destination path or error message) var copier =new (targetFolder, baseName, seqStart, noCopies); var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath); public class FileCopier { private readonly string _targetFolder; private readonly string _baseName; private readonly int _noOfCopies; private int _sequenceNo; public FileCopier(string targetFolder, string baseName, int seqStart, int noOfCopies) { _targetFolder = targetFolder; _baseName = baseName; _noOfCopies = noOfCopies; _sequenceNo = seqStart; } public IEnumerable<Tuple<FileInfo, string>> MakeTargetPath(FileInfo file) { var result = new List<Tuple<FileInfo, string>(); for (var i = 0; i < _noOfCopies; ++i) { var newFileName = string.Format(„{0}{1}{2}”, _baseName, _sequenceNo, Path.GetExtension(file.Name)); var realtivePath = file.Directory.FullName.SubString(_targetFolder.Length); var targetPath = Path.Combine(_targetFolder, relativePath, newFileName); result.Add(new Tuple<FileInfo, string>(file, targetPath)); _sequenceNo += 1; } return result; } } var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies); var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath); IEnumerable<Tuple<FileInfo, string>> Projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence. public static IEnumerable<TResult> SelectMany<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector )
  • 19. Programming Example – functional approach • Make the list of tuples – boolean flag indicating sucessful file copy, source file, copy operation status (destination path or error message) var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies); var toBeCopiedFiles = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath); var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies); var fileCopyStatus = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath) .SelectMany(copier.CopyFile); public class FileCopier { private readonly string _targetFolder; private readonly string _baseName; private readonly int _noOfCopies; private int _sequenceNo; public FileCopier(string targetFolder, string baseName, int seqStart, int noOfCopies) { _targetFolder = targetFolder; _baseName = baseName; _noOfCopies = noOfCopies; _sequenceNo = seqStart; } public IEnumerable<Tuple<bool, FileInfo, string>> CopyFile(Tuple<FileInfo, string> file) { var result = new List<Tuple<bool, FileInfo, string>(); try { MaterializeFolder(_targetFolder, file.Item2); file.Item1.CopyTo(file.Item2); result.Add(new Tuple<bool, FileInfo, string>(true, file.Item1, file.Item2); } catch (Exception ex) { result.Add(new Tuple<bool, FileInfo, string>(false, file.Item1, ex.Message); } return result; } } IEnumerable<Tuple<bool, FileInfo, string>>
  • 20. Programming Example – functional approach var copier =new FileCopier(targetFolder, baseName, seqStart, noCopies); var fileCopyStatus = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath) .SelectMany(copier.CopyFile); var fileCopyObserver = new (); fileCopyStatus.Subscribe (fileCopyObserver); Console.WriteLine(fileCopyObserver.Summary()); public class FileCopyObserver : IObserver<Tuple<bool, FileInfo, string> { private int _copiedFileCount; private int _errorCount; public string Summary() { return string.Format(„Attempt to copy {0} files; {1} successful; {2} errors.”, _copiedFileCount + _errorCount, _copiedFileCount, _errorCount); } public void OnCompleted() { } public void OnError (Exception error) {} public void OnNext(Tuple<bool, FileInfo, string> copyStatus) { if (copyStatus.Item1) { _copiedFileCoput += 1; } else { _errorCount += 1; } } } var fileCopyObserver = new FileCopyObserver(); fileCopyStatus.Subscribe (fileCopyObserver); Console.WriteLine(fileCopyObserver.Summary()); System.Reactive.Linq
  • 21. Programming Example – Object-Oriented vs Functional approach var sourceFiles = FolderVisitor.Visit (sourceFolder); sourceFiles.Sort(Photo.ByDateTaken); foreach (var sourceFile in sourceFiles) { try { FolderHelper.MaterializeFolder(targetFolder, sourceFile.Directory.FullName); fileCopyCount = 0 while (fileCopyCount < noOfCopies) { FolderHelper.CopyFile(targetFolder, sourceFile, newFileNameBase, sequenceNo); fileCopyCount += 1; sequenceNo += 1; } } catch{ } } var copier = new FileCopier(targetFolder, baseName, seqStart, noCopies); var fileCopyStatus = FolderVisitor.Visit (sourceFolder) .OrderBy(Photo.DateTaken) .SelectMany(copier.MakeTargetPath) .SelectMany(copier.CopyFile); var fileCopyObserver = new FileCopyObserver(); fileCopyStatus.Subscribe (fileCopyObserver); Console.WriteLine(fileCopyObserver.Summary()); Control statements, state changes Function call composition Controlling Complexity By
  • 23. Composition Composition is the key to controlling complexity in software. Expert programmers control the complexity of their designs by combining primitive elements to form compound objects, they abstract compound objects to form higher-level building blocks. One form of composition, function composition, describes the dependencies between function calls.
  • 24. Function Composition Function composition takes two functions and passes the result of the second function as the argument of the first function – effectively creating one function taking argument of the second function and returning result of the first function. public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g) { return x => f(g(x)); } Anonymous function (lambda) calling second function (g) with argument x and passing its result as first function (f) argument, and returning the result of the first function.
  • 25. Function Composition var r = f(g(x)) •Explicit dependency between f and g var r = f.Compose(g)(x) •Abstracted dependency between f and g Abstract compound objects to form higher-level building blocks
  • 26. Function Composition Laws • Identity.Compose(f) = f Left identity • f.Compose(Identity) = f Right identity • f.Compose(g.Compose(h) = (f.Compose(g)).Compose(h)Associative public static T Identity<T>(this T value) { return value; }
  • 27. Function Composition – sometimes values are not enough Generic (constructed) types package (amplify) values (integers, strings, objects of class T) The type IEnumerable<T> represents a lazily computed list of values of type T The type IEnumerable<T> packages (amplifies) the type T
  • 28. Function Composition with IEnumerable<T> public static Func<T, IEnumerable<V>> Compose<T, U, V>( this Func<U, IEnumerable<V>> f, Func<T, IEnumerable<U>> g) { return x => f(g(x)); } Error – g(x) returns IEnumerable<U> while f takes U We need to bind the result of g(x) with the function f. Binding will iterate over a list returned by g(x) and pass individual list items to the function f. The result of binding g(x) to the function f is a list of results returned by the function f. public static Func<T, IEnumerable<V>> Compose<T, U, V>( this Func<U, IEnumerable<V>> f, Func<T, IEnumerable<U>> g) { return x => g(x).Bind(f); } public static IEnumerable<V> Bind ( this IEnumerable<U> m, Func<U, IEnumerable<V>> f) public static IEnumerable<V> Bind (this IEnumerable<U> items, Func<U, IEnumerable<V>> f) { var result = new List<V>(); foreach (var item in items) { result.Add(f(item)); } return result; }
  • 29. Function Composition with IEnumerable<T> • Our Bind function allows the function f to use IEnumerable returned by the function g • We need some function converting a type T to IEnumverable<T> public static IEnumerable<T> Unit (this T value) • Together the amplified type IEnumerable<T>, the function Bind, and the function Unit enable function composition with amplified values A type A Unit function A Bind function Monad Monads enable function composition with amplified values
  • 30. Monads Satisfy Function Composition Laws •Unit(v).Bind(f) = f(v)Left identity •m.Bind(Unit) = mRight identity •m.Bind(x => k(x).Bind(y => h(y)) = m.Bind(x =>k(x)).Bind(y => h(y)) Associative
  • 31. Creating a Monad To define a particular monad, the writer supplies the triple (a Type, a Unit function, and a Bind function), thereby specyfying the mechanics of the aplified values
  • 34. C# Functional Programming • Is it worth an effort? • Maybe it is • The Maybe monad is an example of a monadic container type wrapping a value. The container can either have a value or have missing value. The Maybe monad is a better nullable type.
  • 35. C# Functional Programming – Maybe monad public class Maybe<T> { public readonly static Maybe<T> Nothing = new Maybe<T>(); public bool IsNothing { get; private set; } public T Just { get; private set; } public Maybe() { IsNothing = true; Just = default(T); } public Maybe(T value) { IsNothing = false; Just = value; } public new string ToString() { if (IsNothing) { return "Nothing"; } return Just.ToString(); } } Nothing represents all instances lacking a value. Just the value if we have one. We have the type. Now we need the Unit and Bind functions to have the Maybe monad. The Unit function which we call AsMaybe, wraps a value. The Bind function which we call SelectMany, takes a Maybe instance and if there is a value then it applies the delegate to the contained value. Otherwise, it returns Nothing.
  • 36. Maybe monad – Unit and Bind functions public static class MaybeExtensions { public static Maybe<T> AsMaybe<T> (this T value){ return new Maybe<T>(value); } public static Maybe<U> SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe<U>> doSemthingWith) { if (m == null) { return Maybe<U>.Nothing; } if (m.IsNothing) { return Maybe<U>.Nothing; } try { return doSomethingWith(m.Just); } catch (Exception) { return Maybe<U>.Nothing; } } } The Unit function which we call AsMaybe, wraps a value. The Bind function which we call SelectMany, takes a Maybe instance and if there is a value then it applies the delegate to the contained value. Otherwise, it returns Nothing. The delegate takes the un-wrapped value of the type T and returns wrapped (amplified) value of the type U – we can bind another delegate to ther result Maybe<U>.
  • 37. Maybe monad – usage examples var maybeStringArray = (new string[] {„Ala”, „ma”, „kota”}).AsMaybe(); var maybeResult = maybeStringArray .SelectMany(x => x.FirstOrDefault(s => s.Equals(„Ala”)).AsMaybe()) .SelectMany(s => s.ToUpperInvariant().AsMaybe()); Console.WriteLine(maybeResult.ToString()); maybeResult = maybeStringArray .SelectMany(x => x.FirstOrDefault(s => s.Equals(„Ola”)).AsMaybe()) .SelectMany(s => s.ToUpperInvariant().AsMaybe()); Console.WriteLine(maybeResult.ToString()); Writes ALA. Writes Nothing. Maybe<string>

Editor's Notes

  1. Kompozycja, w sensie składania mniejszych elementów w większe konstrukcje jest kluczem do kontroli złożoności oprogramowania. Zawodowcy kontrolują złożoność swoich projektów poprzez składanie prostych elementów w złożone obiekty. Abstrahowanie pozwala przekształcić złożone obiekty w klocki wyższego poziomu obdarzone funkcjonalnością umożliwiającą budowanie skomplikowanych systemów z dobrze zdefiniowanych składników (którymi łatwo się można posługiwać, bo są inteligetne tj. zawierają tyle funkcjonalności, że łatwo się jest składa w większą całość). Jedną z form kompozycji (składania) jest złożenie funkcji.
  2. Compose – funkcja zwracająca funkcję – co za pomysł! Na dodatek to extension method?! I to jeszcze generic! A dlaczego nie?
  3. Associative - przechodni
  4. Wróćmy do naszej funkcji Compose i zamieńmy parametr typu V na parametr typu IEnumerable<V>. Czy taka podmiana nadal umożliwia składanie funkcji? Dobrze nam szło ale się skończyło. Jak zaradzić tej drobnej przeszkodzie?
  5. Podsumujmy to co do tej pory uzyskaliśmy. Bind umożliwia funkcji f konsumpcję wyniku zwracanego przez funkcję g Przydałaby się funkcja, która wzmacnia dowolny typ T to IEnumerable<T> - nazwijmy ją Unit – pomińmy na moment jej implementację Co daje nam ta trójka (IEnumerable<T>, Bind i Unit)? Możliwość złożenia funkcji biorących argumenty wzmocnionych typów i zwracających wyniki w wzmocnionych typach. Taka trójka ma swoją nazwę – poznajcie Monadę – tajemniczy termin ze słownictwa programowania funkcjonalnego