Pemrograman fungsional adalah paradigma yang sangat lucu. Di satu sisi, semua orang tahu tentang itu, dan semua orang suka menggunakan semua jenis pencocokan pola dan lambda, di sisi lain, beberapa orang biasanya menulis dalam bahasa FP murni. Oleh karena itu, pemahaman bahwa ini lebih cenderung untuk kembali ke mitos dan legenda perkotaan, yang sangat jauh dari kebenaran, dan orang-orang memiliki kesan bahwa "FP cocok untuk semua program perhitungan fraktal yang diisolasi dari kehidupan, tetapi untuk masalah nyata ada rekam jejak yang terbukti. dalam pertempuran OOP teruji waktu. "

Meskipun orang biasanya mengenali kenyamanan fitur FP, jauh lebih baik untuk menulis:
int Factorial(int n)
{
Log.Info($"Computing factorial of {n}");
return Enumerable.Range(1, n).Aggregate((x, y) => x * y);
}
int Factorial(int n)
{
int result = 1;
for (int i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
? . .
, ? , , โ ? , , .
, ? , , . :
โ , .
, , ? โ , . , :
f
f(x)
x
, " ". โ , ? ? " " ? , , , .
? :
โ ,
- var x = foo()
var x = result_of_foo
. . ( ) . โ , " ". , . , CPU โ ( , ). โ !
. , ? , , - Factorial(5)
120
โ ( " , " , . , , , ).
? : .
, , var x = result_of_foo
var x = foo()
. "Equational reasoning", " ". , โ , .
: . , . ST, . โ : ST
. , , , โ .
โ . ? , ST
( ) , โฆ โ . goto
, , goto
, - .
Equational reasoning , : . , , , .
. C#, , ( )
var something = function();
DoStuff(this.Field, something);
, :
DoStuff(this.Field, function());
, , . , function
:
... -
this.Field = GetUpdatedVersion(this.Field, localData) // !
...
:
var something = function();
var arg1 = this.Field; // function - !
var arg2 = something;
DoStuff(arg1, arg2);
:
var arg1 = this.Field; // function - !
var arg2 = function();
DoStuff(arg1, arg2);
DoStuff
, .
? " , "? , , . .
, , . , , - C# , , DI , function
DoStuff
, . , , .
. , . , - . , . , , . , . , , , . , โ . โ , - .
, Scala ( , , c ). , C#.
, . , .
, , :
public class Cafe
{
public Coffee BuyCoffee(CreditCard card)
{
var cup = new Coffee()
card.Charge(cup.Price)
return cup
}
}
card.Charge(cup.Price)
. โ , - - -, . , Coffee, "" " ".
- . " !". , :
public class Cafe
{
public Coffee BuyCoffee(CreditCard card, IPaymentProvider paymentProvider)
{
var cup = new Coffee()
paymentProvider.Charge(card, cup.Price)
return cup
}
}
: IPaymentProvider
. .
- -
IPaymentProvider
, . - - . โ InMemory DB, Insert/Save/โฆ , ( ) , . , โ ? , - , , .
- - . N . ( ):
public class Cafe
{
public Coffee BuyCoffee(CreditCard card, IPaymentProvider paymentProvider)
{
var cup = new Coffee()
paymentProvider.Charge(card, cup.Price)
return cup
}
public Coffee[] BuyCoffees(int count, CreditCard card, IPaymentProvider paymentProvider)
{
// 0 ,
// 0
if (count == 0) return Array.Empty<Coffee>();
var cups = Enumerable.Range(0, count).Select(_ => new Coffee()).ToArray();
paymentProvider.Charge(card, cups[0].Price * count)
return cups
}
}
. - , .
, ? โ , , . :
public class Cafe
{
public (Coffee, Charge) BuyCoffee(CreditCard card)
{
var cup = new Coffee()
return (cup, new Charge(card, cup.Price))
}
}
, . , , . , Charge
. : . Charge
DTO . , . , . , . , !
N ? , N BuyCoffee
, .
public class Cafe
{
public (Coffee, Charge) BuyCoffee(CreditCard card)
{
var cup = new Coffee()
return (cup, new Charge(card, cup.Price))
}
public (Coffee[], Charge) BuyCoffees(int count, CreditCard card)
{
var (coffees, charges) = Enumerable.Range(0, count)
.Select(_ => BuyCoffee(card))
.Unzip();
return (coffees, charges.Aggregate((c1, c2) => c1.ombine(c2))
}
}
- Combine
:
public class Charge
{
public CreditCard Card { get; set; }
public double Amount { get; set; }
public Charge(CreditCard card, double amount)
{
Card = card;
Amount = amount;
}
public Charge Combine(Charge other)
{
if (Card != other.Card)
throw new ArgumentException("Can't combine charges to different cards");
return new Charge(Card, Amount + other.Amount);
}
}
- . , , :
IEnumerable<Charge> Coalesce(IEnumerable<Charge> charges) =>
charges.GroupBy(x => x.Card).Select(g => g.Aggregate((c1, c2) => c1.Combine(c2))
, . , , , .
, , - , , , - Cafe
. , , , , , - ( , ).
, IPaymentProvider
, , : , , , "" , , . , , .
, , . " " , . RAII: , .
?
โ , . , , . , , , . ( int ) , (, goto) , (Templates vs Generics) , .
, , . , "" , , , . ? void UpdateOrders()
void UpdateUsers()
() -> ()
, . () -> OrdersUpdate
() -> UsersUpdate
. , ( ) , .
? , ( Rust)
// , - ,
fn foo<T>(a: &[T], b: T) -> T { ...- ... }
, , , โ b
. ? , T
. . , โ .
let a = [1,2,3,4,5];
let b = foo(a, 10);
assert!(b == 10 || a.iter().any(|x| x == b))
, UB - ( ). , , - - , (, , ).
:
fn foo<T>(a: &[T]) -> T { ...- ... }
, , , - . , , Bottom- โฅ
. ? T, . a
. -, . .
, , .
, ? , . , :
T Foo<T>(List<T> list, T value) => default(T);
, . . , , โ . , , , .
, T? :
fn foo<T: Default>(a: &[T]) -> T { ...- ... }
, , . , , - . โ . . ! , default(T)
.
99% , . , . Haskell Hoogle . .
(a -> Bool) -> [a] -> [a]
(, : , ) filter
takeWhile
.
. , ? , .
fn bar<T>(s: String) -> T { ... } // -
bar :: String -> a // -
, , . , โ . , โฅ
. , . , , :
fn bar<T>(s: String) -> T {
panic!(s);
}
โ ( ), . , . , , , .
, , , . foo
1000 , , . . 1000 . .
- ?
, . "", , " , HTTP , . . ".
, , . ", . , ( )? , , !".
? IO
, . , Charge
, /. IO , print "Hello world"
. main = print "Hello world"
. ?
, IO. main
. , . "" โ , , , . .
,
, . main
, .
, , โ , . , . "", . .
, , . Rust:
fn main() {
let _ = print!("Hello ");
println!("world!");
}
"Hello world!". Haskell:
main :: IO ()
main = do
let _ = print "Hello "
print "world!"
"world!". . " Hello
", . . main
world!
, . Rust print! , - .
( , - ) , . " " . , " ( ), HTTP ( , ), . , .
, . , , . , . - ANSI C , . . , Scala Haskell โ . , , , , . , .
. , - . DI. " "/" "/"...", .
, , , . . "" , , . , โ .