SlideShare una empresa de Scribd logo
1 de 81
Feel Functional
Lee Won Jun
https://see-ro-e.tistory.com/
FP
모나드
순수함수
불변성
패턴 매칭
재귀 함수
꼬리 재귀
커링
Stream
LINQ
참조투명성
비파괴적
레코드
Clojure
Scala
펑터
어플리케이티브
부수효과
조합기
Compose
F#
Option
Pipe
일급 객체
OOP
추상클래스
클래스
인터페이스
프록시
다중 상속
공변성
상속
LSP
ISP
Lock
바인딩
Java
this
가상상속
전략 패턴
SRP
ORM
C#
오버라이딩
OCP
DIP
케스팅
생성자, 소멸자
접근지정자
base
다형성
FP
불변과 순수함수
Map Reduce
Filter
“문” 과 “식”
함수
C# Kotlin
불변과 순수함수
No Side Effect
Expectable
Testable
순수 함수
순수하지 않은 함수
Unit Test Program
순수 함수
순수 함수
순수 함수
순수 함수
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Unit Test Program
안순수 함수
안순수 함수
안순수 함수
안순수 함수
Pass
Pass
Fail
Pass
Fail
Pass
Pass
Pass
순수 함수
순수 함수
순수 함수
순수 함수
순수 함수
안순수 함수
순수 함수
순수 함수
안순수 함수
안순수 함수
순수 함수
순수 함수
안순수 함수
안순수 함수
Pure Core
Program
안순수 함수
가변 객체
Time
안순수 함수 안순수 함수 안순수 함수
가변 객체
이 시점의 값은?
가변 객체
이 시점의 값은?
Program
안순수 함수
가변 객체
Time
안순수 함수 안순수 함수 안순수 함수
가변 객체
이 시점의 값은?
가변 객체
이 시점의 값은?
같은 객체지만, 다른값
Program
안순수 함수
가변 객체
Time
안순수 함수 안순수 함수 안순수 함수
가변 객체
이 시점의 값은?
가변 객체
이 시점의 값은?
다른 객체
가변 객체
재할당
Program
안순수 함수
불변 객체
Time
안순수 함수 안순수 함수 안순수 함수
불변 객체
이 시점의 값은?
불변 객체
이 시점의 값은?
public class Person
{
public string Name { get; set; }
public void Drink(string alcohol)
{
Console.WriteLine($"{this.name} drink {alcohol}");
}
}
class Program
{
static void Main(string[] args)
{
Person wonJun = new Person { Name = "이원준" };
wonJun.Drink("소주");
}
}
public class Person
{
public string Name { get; set; }
public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}";
public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol);
public void Drink(string alcohol)
{
var drinkString = Person.Drink(this, alcohol);
Console.WriteLine(drinkString);
}
}
class Program
{
static void Main(string[] args)
{
Person wonJun = new Person { Name = "이원준" };
wonJun.Drink("소주");
}
}
public class Person
{
public string Name { get; set; }
public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}";
public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol);
public void Drink(string alcohol)
{
var drinkString = Person.Drink(this, alcohol);
Console.WriteLine(drinkString);
Name = "리원준";
}
}
class Program
{
static void Main(string[] args)
{
Person wonJun = new Person { Name = "이원준" };
wonJun.Drink("소주");
wonJun.Drink("소주");
}
}
public class Person
{
public string Name { get; init; }
public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}";
public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol);
public void Drink(string alcohol)
{
var drinkString = Person.Drink(this, alcohol);
Console.WriteLine(drinkString);
Name = "리원준";
}
}
class Program
{
static void Main(string[] args)
{
Person wonJun = new Person { Name = "이원준" };
wonJun.Drink("소주");
wonJun.Drink("소주");
}
}
가변 + 안 순수 함수 불변 + 순수 함수
val p = Person(name = "이원준")
val p2 = p.copy(name = "리원준")
data class Person(val name:
String)
불변 레퍼런스
불변 데이터
“문” 과 “식”
Expression is Function for Immutable
For “문”
If “문”
Switch “문”
If “식”
Match “식”
반환이 없음, 내용을 수행 맞는 내용을 “반환”
static string FavoriteAlcohol(string name)
{
switch (name)
{
case "이원준":
return "위스키";
case "고세원":
return "막걸리";
case "백종현":
return "소주";
case "장준영":
return "맥주";
case "리원준":
return "대동강맥주";
default:
return "물";
}
}
static string FavoriteAlcohol(string name)
{
return name switch
{
"이원준" => "위스키",
"고세원" => "막걸리",
"백종현" => "소주",
"장준영" => "맥주",
"리원준" => "대동강맥주",
_=> "물"
};
}
static string FavoriteAlcohol(string name)
{
switch (name)
{
case "이원준":
return "위스키";
case "고세원":
return "막걸리";
case "백종현":
return "소주";
case "장준영":
return "맥주";
case "리원준":
return "대동강맥주";
default:
return "물";
}
}
static string FavoriteAlcohol(string name)
=> name switch
{
"이원준" => "위스키",
"고세원" => "막걸리",
"백종현" => "소주",
"장준영" => "맥주",
"리원준" => "대동강맥주",
_ => "물"
};
var myFavorite = FavoriteAlcohol("이원준"); var myFavorite = FavoriteAlcohol("이원준");
var name = "이원준";
//...
var myFavorite = "";
switch (name)
{
case "이원준":
myFavorite = "위스키";
break;
case "고세원":
myFavorite = "막걸리";
break;
case "백종현":
myFavorite = "소주";
break;
case "장준영":
myFavorite = "맥주";
break;
case "리원준":
myFavorite = "대동강맥주";
break;
default:
myFavorite = "물";
break;
}
var name = "이원준";
//...
var myFavorite = name switch
{
"이원준" => "위스키",
"고세원" => "막걸리",
"백종현" => "소주",
"장준영" => "맥주",
"리원준" => "대동강맥주",
_ => "물"
};
재할당이 필수 불가결
Destructuring
data class Alcohol(val name:String, val abv:Double)
data class Person(val name:String,val
drinkHistory:List<Alcohol>)
fun main(args: Array<String>) {
val soju = Alcohol(name = "소주",abv = 17.6)
val (nameOfSoju,_) = soju
println(nameOfSoju)
}
Destructuring
class User
{
public int X { get; set; }
public int Y { get; set; }
// Blah Blah
}
void GetUserXY(User u, out int x, out int y)
{
x = u.X;
y = u.Y;
}
var user = new User { X = 10, Y = 20 };
int x;
GetUserXY(user, out x, out _);
class User
{
public int X { get; set; }
public int Y { get; set; }
// Blah Blah
}
void GetUserXY(User u, out int x, out int y)
{
x = u.X;
y = u.Y;
}
var user = new User { X = 10, Y = 20 };
int x;
GetUserXY(user, out x, out _);
class User
{
public int X { get; set; }
public int Y { get; set; }
// Blah Blah
}
var user = new User { X = 10, Y = 20 };
int x = GetUserXY(user).X;
struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
Point GetUserXY(User u)
{
return new Point { X = u.X, Y = u.Y };
}
class User
{
public int X { get; set; }
public int Y { get; set; }
// Blah Blah
}
(int,int) GetUserXY(User u)
{
return (u.X, u.Y);
}
var user = new User { X = 10, Y = 20 };
(int x, _) = GetUserXY(user);
Map Reduce Filter
Assurance For Collection
Java Stream.. C# LINQ …
• 결국 리스트처리를 위한 함수!
• 리스트를 위한 함수가 왜 필요한가?
우리가 리스트를 거지같이 다루니까!
val list = listOf(1,2,3,4,5)
for (i in 0..list.count())
println(list[i])
var even = mutableListOf<Int>()
for (i in list)
if ( i % 2 == 0)
even.add(i)
val list = listOf(1,2,3,4,5)
for (i in 0..list.count())
println(list[i])
var even = mutableListOf<Int>()
for (i in list)
if ( i % 2 == 0)
even.add(i)
val list = listOf(1,2,3,4,5)
for (i in 0..list.count())
println(list[i])
val even = mutableListOf<Int>()
for (i in list)
if ( i % 2 == 0)
even.add(i)
인덱스 사이즈가 안 맞으면 어떡하지?
누가 Sum 을 바꿔버리면 어떡하지
Mutable 에 계속 Add 해야하나?
val list = listOf(1,2,3,4,5)
for (i in 0..list.count())
println(list[i])
var even = mutableListOf<Int>()
for (i in list)
if ( i % 2 == 0)
even.add(i)
다 돌고 싶다!
다 더하고 싶다!
Even 만 뽑고 싶다!
다 돌고 싶다!
다 더하고 싶다!
Even 만 뽑고 싶다!val even = list.filter { it%2 == 0 }
list.forEach(::println)
val sum = list.reduce{x,y-> x + y}
val sum = list.sum()
For Each는 똑같은거 아닌가요?
• Switch 문도 Jump 하는데 Go To를 안 쓰는 이유는?
• For Each 는 신뢰 할 만하다!
• “모든 요소 순회” 라는 개념의 추상화
• Index 기반의 For 문을 코드가 변경 되도 신뢰 할만한가?
auto list = new vector<int>()
//.....
for (int i = 0 ; i < list.length ; i++)
{
//어쩌고 저쩌고
}
i--;
선생님 저는 다 돌기 싫은데요?
• 앞에 100개 만 돌고 싶은데요?
• 뒤에 100개 만 돌고 싶은데요?
• 짝수 부분만 돌고 싶은데요?
미리 잘라 놓고 도세요..
val list = listOf(1,2,3,4,5)
val listTake100 = list.subList(0,100)
val sum =listTake100.sum()
println(sum)
잘못 잘라도 에러는 여기서 납니다
TMI
data class Alcohol(val name:String, val abv:Double)
data class Person(val name:String,val drinkHistory:List<Alcohol>)
val Lee = Person(name = "이원준",drinkHistory = listOf(
Alcohol(name = "소주",abv = 17.6),
Alcohol(name = "맥주",abv = 4.0),
Alcohol(name = "청하",abv = 16.9),
Alcohol(name = "예거",abv = 40.0)
))
val Ko = Person(name = "고세원",drinkHistory = listOf(
Alcohol(name = "소주",abv = 17.6),
Alcohol(name = "막걸리",abv = 3.0),
Alcohol(name = "꽃빛서리",abv = 17.6)
))
val Beak = Person(name = "백종현",drinkHistory = listOf(
Alcohol(name = "소주",abv = 17.6),
Alcohol(name = "꽃빛서리",abv = 17.6),
Alcohol(name = "보드카",abv = 40.0)
))
val Jang = Person(name = "장준영",drinkHistory = listOf(
Alcohol(name = "소주",abv = 17.6),
Alcohol(name = "막걸리",abv = 3.0)
))
val We = listOf(Lee, Ko, Beak,Jang)
val MTMMember = We.map { it.name }
val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name ==
"꽃빛서리" } }
.map { it.name }
val Alcohols = We.flatMap { it.drinkHistory }.distinct()
We.forEach(::println)
MTMMember.forEach(::println)
꽃빛서리.forEach(::println)
Alcohols.forEach(::println)
val We = listOf(Lee, Ko, Beak,Jang)
val MTMMember = We.map { it.name }
val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name ==
"꽃빛서리" } }
.map { it.name }
val Alcohols = We.flatMap { it.drinkHistory }.distinct()
We.forEach(::println)
MTMMember.forEach(::println)
꽃빛서리.forEach(::println)
Alcohols.forEach(::println)
이름만 뽑고싶네?
꽃빛서리
마신사람만 찾고싶네?
(꽃빛서리 마신사람들 의) 이름만 뽑고싶네?
사람들의 음주기록만 보고싶네
중복이 없으면 좋겠네..
전부 출력하고싶네?
Compose
Pipe
Chaining
Reduce assignment
fun f (x:Int) = x + 5
fun g (x:Int) = x + 10
fun h (x:Int) = x + 20
val x = 0
val x2 = f(x)
val x3 = g(x2)
val result1 = h(x3)
fun composed (x: Int) = h(g(f(x)))
val result2 = composed(x)
fun f (x:Int) = x + 5
fun g (x:Int) = x + 10
fun h (x:Int) = x + 20
val x = 0
val x2 = f(x)
val x3 = g(x2)
val result1 = h(x3)
fun composed (x: Int) = h(g(f(x)))
val result2 = composed(x)
let f x = x+5
let g x = x+10
let h x = x+20
let x = 0
let composed = f >> g >> h
let result1 = composed x
let result2 = x |> f |> g |> h
fun f (x:Int) = x + 5
fun g (x:Int) = x + 10
fun h (x:Int) = x + 20
val x = 0
val x2 = f(x)
val x3 = g(x2)
val result1 = h(x3)
fun composed (x: Int) = h(g(f(x)))
val result2 = composed(x)
let f x = x+5
let g x = x+10
let h x = x+20
let x = 0
let composed = f >> g >> h
let result1 = composed x
let result2 = x |> f |> g |> h
새로운 함수를 만들면
Compose
함수를 연속적으로 호출하면
Pipe
cat /etc/passwd | grep mail
val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name == "꽃빛서리"
} }
.map { it.name }
val 꽃빛서리People = We.filter { it.drinkHistory.any { (name,_) ->name ==
"꽃빛서리" } }
val 꽃빛서리PeopleName = 꽃빛서리People.map { it.name }
X
But…. Method 는…
• 근본적으로 순수하지 않음
this
We.filter { blah blah
}
.map { blah blah }
.map { blah blah }
.reduce { blah blah
}
.Drink()
List<Person> 의 Method 만 사용가능
val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().MixWater()
val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().MixWater()
람다를 쓰고 싶을 때는?
확장함수가 아닌 함수인 경우는?
val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().run { MixWater(this) }
run/let and so on…
Partial Application
Fit Function signature
val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct()
val YangJuAlcohols =
listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv
40.0))
val WeDrinkAlcoholsWithoutYangJu =
WeDrinkAlcohols.filterNot{YangJuAlcohols.contains(it)}
???
파라미터
람다
val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct()
val YangJuAlcohols =
listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv
40.0))
fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol)
val WeDrinkAlcoholsWithoutYangJu3 = WeDrinkAlcohols.filterNot(isContainInYangJu
val WeDrinkAlcoholsWithoutYangJu2 =
WeDrinkAlcohols.filterNot{isContain(YangJuAlcohols,it)}
???
파라미터
val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct()
val YangJuAlcohols =
listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv
40.0))
fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol)
val isContainInYangJu = {alcohol : Alcohol -> isContain(YangJuAlcohols,alcohol)
val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot(isContainInYangJu)
캡쳐
val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct()
val YangJuAlcohols =
listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv
40.0))
fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol)
val isContainInYangJu = {alcohol : Alcohol -> isContain(YangJuAlcohols,alcohol)
val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot(isContainInYangJu)
불변
//… YangJuAlcohols 가 변경되면?
Joy Of Clojure 에서 발쵀
스승과의 다음 산책 때 안톤은 스승에게 잘 보일 요량으로 이렇게 말했다.
“스승님. 열심히 수양을 닦으면서 객체야 말로 가난한 사람들의
진정한 클로저(Closure) 라는것을 이해하게 되었습니다.“
그러자 스승은 막대기로 안톤의 머리를 때리더니 이렇게 말했다.
“대체 언제 깨달으려 하느냐? 클로저는 가난한 사람의 객체이니라.”
그 순간 안톤은 이치를 깨닫게 되었다. – 안톤 반 스토라텐
Function is Value
First-class citizens
• 저장 할 수도 있고
• 넘길 수도 있고
• 리턴할 수도 있습니다.
Function is Value
val isContainInYangJu = {alcohol : Alcohol ->
isContain(YangJuAlcohols,alcohol)}
val WeDrinkAlcoholsWithoutYangJu =
WeDrinkAlcohols.filterNot(isContainInYangJu)
sealed class Liquid
data class Alcohol(val name:String, val abv:Double) : Liquid()
data class SoftDrink (val name:String): Liquid()
data class Methanol (val name:String) : Liquid()
data class Person(val name:String,val drinkHistory:List<Alcohol>)
fun HangOver(person: Person):Unit = println ( "${person.name} feels a hangover :(" )
fun Die(person: Person):Unit = println ( "${person.name} is dead :(" )
fun WhatToDoAfterDrinking(liquid: Liquid):(Person)->Unit = when (liquid) {
is Alcohol -> ::HangOver
is SoftDrink -> {_ -> Unit}
is Methanol -> ::Die
}
val Soju = Alcohol(name = "소주",abv = 17.6)
val AfterDrink = WhatToDoAfterDrinking(Soju)
AfterDrink(Lee)
enum class LiquidType{
Alcohol,
SoftDrink,
Methanol
}
val FuntionMap = mapOf<LiquidType,(Person)-
>Unit>(
LiquidType.Alcohol to ::HangOver,
LiquidType.SoftDrink to {_->Unit},
LiquidType.Methanol to ::Die
)
val AfterDrink = FuntionMap[LiquidType.Methanol] ?: {_->Unit}
AfterDrink(Lee)
Unit is type
Controllable
Null Maybe/Option
Void Unit
1
2
3
4
5
6
2
3
4
5
6
7
F(X) = X+1
1
2
3
4
5
6
Unit.
.
.
F(X) = Unit
fun YesResponse1() = 1
fun YesResponse2() = 2
fun YesResponse3() = 3
fun NoResponse() = Unit
fun main(args: Array<String>) {
val Response = listOf
(YesResponse1(),YesResponse2(),NoResponse(),NoResponse(),YesResponse3())
val ResponseWithoutUnit = Response.filterNot { it is Unit }.map { it as Int }
ResponseWithoutUnit.forEach(::println)
List[T]
Option[T]
Functional
Functional Programming은 대입문 없이 프로그래밍 하는것 by 엉클밥
불변 순수함수
Reliable regardless of time
Reliable regardless of Status
Composable 높은 추상화
선언적 쓰기 쉽다
More Safe (적어도 나보단)
Thread Safe
Testable
견고한 프로그램
유지보수가 쉬워짐
Functional
Functional Programming is Paradigm
C절차지향 언어 OOP 가능 (like Linux)
Functional Programming Language?
FP를 위한 “툴” 을 제공해주는 언어!
For Functional Study
• https://fsharpforfunandprofit.com/
• http://clojure.or.kr/docs/clojure-and-gof-design-patterns.html
• 클로저 프로그래밍의 즐거움
• 스칼라로 배우는 함수형 프로그래밍 (일명 빨간책)
• 한국에서 검색하려면 Haskell / Scala
QnA

Más contenido relacionado

La actualidad más candente

Do swift: Swift 무작정 해보기
Do swift: Swift 무작정 해보기Do swift: Swift 무작정 해보기
Do swift: Swift 무작정 해보기
YoonBong Steve Kim
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
유진 변
 
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
ETRIBE_STG
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)
SeongHyun Ahn
 

La actualidad más candente (20)

[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
[Main Session] 미래의 Java 미리보기 - 앰버와 발할라 프로젝트를 중심으로
 
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
스위프트, 코틀린과 모던언어의 특징 (Swift, Kotlin and Modern Languages)
 
Do swift: Swift 무작정 해보기
Do swift: Swift 무작정 해보기Do swift: Swift 무작정 해보기
Do swift: Swift 무작정 해보기
 
자바스크립트 함수
자바스크립트 함수자바스크립트 함수
자바스크립트 함수
 
파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301파이썬+Json+이해하기 20160301
파이썬+Json+이해하기 20160301
 
파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229파이썬+함수이해하기 20160229
파이썬+함수이해하기 20160229
 
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
 
Naive Bayes by Seo
Naive Bayes by SeoNaive Bayes by Seo
Naive Bayes by Seo
 
파이썬 기본 문법
파이썬 기본 문법파이썬 기본 문법
파이썬 기본 문법
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
 
빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)빠르게 활용하는 파이썬3 스터디(ch1~4)
빠르게 활용하는 파이썬3 스터디(ch1~4)
 
자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초자바스크립트 기초문법~함수기초
자바스크립트 기초문법~함수기초
 
Hacosa j query 10th
Hacosa j query 10thHacosa j query 10th
Hacosa j query 10th
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
[새차원, 코틀린(Kotlin) 강좌] 5. Control Flow
 
Haskell study 9
Haskell study 9Haskell study 9
Haskell study 9
 
Python datatype
Python datatypePython datatype
Python datatype
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdf
 
Python Programming: Function
Python Programming: FunctionPython Programming: Function
Python Programming: Function
 
Haskell study 10
Haskell study 10Haskell study 10
Haskell study 10
 

Similar a Feel functional

Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
지수 윤
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3
suitzero
 

Similar a Feel functional (20)

Kotlin with fp
Kotlin with fpKotlin with fp
Kotlin with fp
 
Scala
ScalaScala
Scala
 
코딩인카페 C&JAVA 기초과정 C프로그래밍(3)
코딩인카페 C&JAVA 기초과정 C프로그래밍(3)코딩인카페 C&JAVA 기초과정 C프로그래밍(3)
코딩인카페 C&JAVA 기초과정 C프로그래밍(3)
 
Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기Javascript개발자의 눈으로 python 들여다보기
Javascript개발자의 눈으로 python 들여다보기
 
GraphQL 적용기
GraphQL 적용기GraphQL 적용기
GraphQL 적용기
 
Valentine
ValentineValentine
Valentine
 
프로젝트 보고서
프로젝트 보고서프로젝트 보고서
프로젝트 보고서
 
2. c언어의 기본
2. c언어의 기본2. c언어의 기본
2. c언어의 기본
 
Swift의 함수와 메소드
Swift의 함수와 메소드Swift의 함수와 메소드
Swift의 함수와 메소드
 
HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3HolubOnPatterns/chapter3_3
HolubOnPatterns/chapter3_3
 
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?Realm은 어떻게 효율적인 데이터베이스를 만들었나?
Realm은 어떻게 효율적인 데이터베이스를 만들었나?
 
[113]how can realm_make_efficient_mobile_database
[113]how can realm_make_efficient_mobile_database[113]how can realm_make_efficient_mobile_database
[113]how can realm_make_efficient_mobile_database
 
반복문
반복문반복문
반복문
 
EcmaScript6(2015) Overview
EcmaScript6(2015) OverviewEcmaScript6(2015) Overview
EcmaScript6(2015) Overview
 
Angular2 가기전 Type script소개
 Angular2 가기전 Type script소개 Angular2 가기전 Type script소개
Angular2 가기전 Type script소개
 
함수적 사고 2장
함수적 사고 2장함수적 사고 2장
함수적 사고 2장
 
Swift 0x02 기본 연산자
Swift 0x02   기본 연산자Swift 0x02   기본 연산자
Swift 0x02 기본 연산자
 
알고리즘과 자료구조
알고리즘과 자료구조알고리즘과 자료구조
알고리즘과 자료구조
 
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌[C++ Korea] Effective Modern C++ Study item14 16 +신촌
[C++ Korea] Effective Modern C++ Study item14 16 +신촌
 
함수형 프로그래밍? 그래서 어떻게
함수형 프로그래밍? 그래서 어떻게함수형 프로그래밍? 그래서 어떻게
함수형 프로그래밍? 그래서 어떻게
 

Feel functional

  • 1. Feel Functional Lee Won Jun https://see-ro-e.tistory.com/
  • 2. FP 모나드 순수함수 불변성 패턴 매칭 재귀 함수 꼬리 재귀 커링 Stream LINQ 참조투명성 비파괴적 레코드 Clojure Scala 펑터 어플리케이티브 부수효과 조합기 Compose F# Option Pipe 일급 객체
  • 5. 불변과 순수함수 No Side Effect Expectable Testable
  • 8. Unit Test Program 순수 함수 순수 함수 순수 함수 순수 함수 Pass Pass Pass Pass Pass Pass Pass Pass
  • 9. Unit Test Program 안순수 함수 안순수 함수 안순수 함수 안순수 함수 Pass Pass Fail Pass Fail Pass Pass Pass
  • 13. 순수 함수 순수 함수 안순수 함수 안순수 함수
  • 14. 순수 함수 순수 함수 안순수 함수 안순수 함수 Pure Core
  • 15. Program 안순수 함수 가변 객체 Time 안순수 함수 안순수 함수 안순수 함수 가변 객체 이 시점의 값은? 가변 객체 이 시점의 값은?
  • 16. Program 안순수 함수 가변 객체 Time 안순수 함수 안순수 함수 안순수 함수 가변 객체 이 시점의 값은? 가변 객체 이 시점의 값은? 같은 객체지만, 다른값
  • 17. Program 안순수 함수 가변 객체 Time 안순수 함수 안순수 함수 안순수 함수 가변 객체 이 시점의 값은? 가변 객체 이 시점의 값은? 다른 객체 가변 객체 재할당
  • 18. Program 안순수 함수 불변 객체 Time 안순수 함수 안순수 함수 안순수 함수 불변 객체 이 시점의 값은? 불변 객체 이 시점의 값은?
  • 19. public class Person { public string Name { get; set; } public void Drink(string alcohol) { Console.WriteLine($"{this.name} drink {alcohol}"); } } class Program { static void Main(string[] args) { Person wonJun = new Person { Name = "이원준" }; wonJun.Drink("소주"); } }
  • 20. public class Person { public string Name { get; set; } public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}"; public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol); public void Drink(string alcohol) { var drinkString = Person.Drink(this, alcohol); Console.WriteLine(drinkString); } } class Program { static void Main(string[] args) { Person wonJun = new Person { Name = "이원준" }; wonJun.Drink("소주"); } }
  • 21. public class Person { public string Name { get; set; } public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}"; public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol); public void Drink(string alcohol) { var drinkString = Person.Drink(this, alcohol); Console.WriteLine(drinkString); Name = "리원준"; } } class Program { static void Main(string[] args) { Person wonJun = new Person { Name = "이원준" }; wonJun.Drink("소주"); wonJun.Drink("소주"); } }
  • 22. public class Person { public string Name { get; init; } public static string Drink(string name, string alcohol) => $"{name} drink {alcohol}"; public static string Drink(Person p, string alcohol) => Drink(p.Name, alcohol); public void Drink(string alcohol) { var drinkString = Person.Drink(this, alcohol); Console.WriteLine(drinkString); Name = "리원준"; } } class Program { static void Main(string[] args) { Person wonJun = new Person { Name = "이원준" }; wonJun.Drink("소주"); wonJun.Drink("소주"); } }
  • 23. 가변 + 안 순수 함수 불변 + 순수 함수
  • 24. val p = Person(name = "이원준") val p2 = p.copy(name = "리원준") data class Person(val name: String) 불변 레퍼런스 불변 데이터
  • 25. “문” 과 “식” Expression is Function for Immutable
  • 26. For “문” If “문” Switch “문” If “식” Match “식” 반환이 없음, 내용을 수행 맞는 내용을 “반환”
  • 27.
  • 28. static string FavoriteAlcohol(string name) { switch (name) { case "이원준": return "위스키"; case "고세원": return "막걸리"; case "백종현": return "소주"; case "장준영": return "맥주"; case "리원준": return "대동강맥주"; default: return "물"; } } static string FavoriteAlcohol(string name) { return name switch { "이원준" => "위스키", "고세원" => "막걸리", "백종현" => "소주", "장준영" => "맥주", "리원준" => "대동강맥주", _=> "물" }; }
  • 29. static string FavoriteAlcohol(string name) { switch (name) { case "이원준": return "위스키"; case "고세원": return "막걸리"; case "백종현": return "소주"; case "장준영": return "맥주"; case "리원준": return "대동강맥주"; default: return "물"; } } static string FavoriteAlcohol(string name) => name switch { "이원준" => "위스키", "고세원" => "막걸리", "백종현" => "소주", "장준영" => "맥주", "리원준" => "대동강맥주", _ => "물" };
  • 30. var myFavorite = FavoriteAlcohol("이원준"); var myFavorite = FavoriteAlcohol("이원준");
  • 31. var name = "이원준"; //... var myFavorite = ""; switch (name) { case "이원준": myFavorite = "위스키"; break; case "고세원": myFavorite = "막걸리"; break; case "백종현": myFavorite = "소주"; break; case "장준영": myFavorite = "맥주"; break; case "리원준": myFavorite = "대동강맥주"; break; default: myFavorite = "물"; break; } var name = "이원준"; //... var myFavorite = name switch { "이원준" => "위스키", "고세원" => "막걸리", "백종현" => "소주", "장준영" => "맥주", "리원준" => "대동강맥주", _ => "물" }; 재할당이 필수 불가결
  • 33. data class Alcohol(val name:String, val abv:Double) data class Person(val name:String,val drinkHistory:List<Alcohol>) fun main(args: Array<String>) { val soju = Alcohol(name = "소주",abv = 17.6) val (nameOfSoju,_) = soju println(nameOfSoju) } Destructuring
  • 34. class User { public int X { get; set; } public int Y { get; set; } // Blah Blah } void GetUserXY(User u, out int x, out int y) { x = u.X; y = u.Y; } var user = new User { X = 10, Y = 20 }; int x; GetUserXY(user, out x, out _);
  • 35. class User { public int X { get; set; } public int Y { get; set; } // Blah Blah } void GetUserXY(User u, out int x, out int y) { x = u.X; y = u.Y; } var user = new User { X = 10, Y = 20 }; int x; GetUserXY(user, out x, out _);
  • 36. class User { public int X { get; set; } public int Y { get; set; } // Blah Blah } var user = new User { X = 10, Y = 20 }; int x = GetUserXY(user).X; struct Point { public int X { get; set; } public int Y { get; set; } } Point GetUserXY(User u) { return new Point { X = u.X, Y = u.Y }; }
  • 37. class User { public int X { get; set; } public int Y { get; set; } // Blah Blah } (int,int) GetUserXY(User u) { return (u.X, u.Y); } var user = new User { X = 10, Y = 20 }; (int x, _) = GetUserXY(user);
  • 38. Map Reduce Filter Assurance For Collection
  • 39. Java Stream.. C# LINQ … • 결국 리스트처리를 위한 함수! • 리스트를 위한 함수가 왜 필요한가? 우리가 리스트를 거지같이 다루니까!
  • 40. val list = listOf(1,2,3,4,5) for (i in 0..list.count()) println(list[i])
  • 41.
  • 42. var even = mutableListOf<Int>() for (i in list) if ( i % 2 == 0) even.add(i)
  • 43. val list = listOf(1,2,3,4,5) for (i in 0..list.count()) println(list[i]) var even = mutableListOf<Int>() for (i in list) if ( i % 2 == 0) even.add(i)
  • 44. val list = listOf(1,2,3,4,5) for (i in 0..list.count()) println(list[i]) val even = mutableListOf<Int>() for (i in list) if ( i % 2 == 0) even.add(i) 인덱스 사이즈가 안 맞으면 어떡하지? 누가 Sum 을 바꿔버리면 어떡하지 Mutable 에 계속 Add 해야하나?
  • 45. val list = listOf(1,2,3,4,5) for (i in 0..list.count()) println(list[i]) var even = mutableListOf<Int>() for (i in list) if ( i % 2 == 0) even.add(i) 다 돌고 싶다! 다 더하고 싶다! Even 만 뽑고 싶다!
  • 46. 다 돌고 싶다! 다 더하고 싶다! Even 만 뽑고 싶다!val even = list.filter { it%2 == 0 } list.forEach(::println) val sum = list.reduce{x,y-> x + y} val sum = list.sum()
  • 47. For Each는 똑같은거 아닌가요? • Switch 문도 Jump 하는데 Go To를 안 쓰는 이유는? • For Each 는 신뢰 할 만하다! • “모든 요소 순회” 라는 개념의 추상화 • Index 기반의 For 문을 코드가 변경 되도 신뢰 할만한가? auto list = new vector<int>() //..... for (int i = 0 ; i < list.length ; i++) { //어쩌고 저쩌고 } i--;
  • 48. 선생님 저는 다 돌기 싫은데요? • 앞에 100개 만 돌고 싶은데요? • 뒤에 100개 만 돌고 싶은데요? • 짝수 부분만 돌고 싶은데요? 미리 잘라 놓고 도세요..
  • 49. val list = listOf(1,2,3,4,5) val listTake100 = list.subList(0,100) val sum =listTake100.sum() println(sum) 잘못 잘라도 에러는 여기서 납니다
  • 50. TMI
  • 51. data class Alcohol(val name:String, val abv:Double) data class Person(val name:String,val drinkHistory:List<Alcohol>) val Lee = Person(name = "이원준",drinkHistory = listOf( Alcohol(name = "소주",abv = 17.6), Alcohol(name = "맥주",abv = 4.0), Alcohol(name = "청하",abv = 16.9), Alcohol(name = "예거",abv = 40.0) )) val Ko = Person(name = "고세원",drinkHistory = listOf( Alcohol(name = "소주",abv = 17.6), Alcohol(name = "막걸리",abv = 3.0), Alcohol(name = "꽃빛서리",abv = 17.6) )) val Beak = Person(name = "백종현",drinkHistory = listOf( Alcohol(name = "소주",abv = 17.6), Alcohol(name = "꽃빛서리",abv = 17.6), Alcohol(name = "보드카",abv = 40.0) )) val Jang = Person(name = "장준영",drinkHistory = listOf( Alcohol(name = "소주",abv = 17.6), Alcohol(name = "막걸리",abv = 3.0) ))
  • 52. val We = listOf(Lee, Ko, Beak,Jang) val MTMMember = We.map { it.name } val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name == "꽃빛서리" } } .map { it.name } val Alcohols = We.flatMap { it.drinkHistory }.distinct() We.forEach(::println) MTMMember.forEach(::println) 꽃빛서리.forEach(::println) Alcohols.forEach(::println)
  • 53. val We = listOf(Lee, Ko, Beak,Jang) val MTMMember = We.map { it.name } val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name == "꽃빛서리" } } .map { it.name } val Alcohols = We.flatMap { it.drinkHistory }.distinct() We.forEach(::println) MTMMember.forEach(::println) 꽃빛서리.forEach(::println) Alcohols.forEach(::println) 이름만 뽑고싶네? 꽃빛서리 마신사람만 찾고싶네? (꽃빛서리 마신사람들 의) 이름만 뽑고싶네? 사람들의 음주기록만 보고싶네 중복이 없으면 좋겠네.. 전부 출력하고싶네?
  • 55. fun f (x:Int) = x + 5 fun g (x:Int) = x + 10 fun h (x:Int) = x + 20 val x = 0 val x2 = f(x) val x3 = g(x2) val result1 = h(x3) fun composed (x: Int) = h(g(f(x))) val result2 = composed(x)
  • 56. fun f (x:Int) = x + 5 fun g (x:Int) = x + 10 fun h (x:Int) = x + 20 val x = 0 val x2 = f(x) val x3 = g(x2) val result1 = h(x3) fun composed (x: Int) = h(g(f(x))) val result2 = composed(x) let f x = x+5 let g x = x+10 let h x = x+20 let x = 0 let composed = f >> g >> h let result1 = composed x let result2 = x |> f |> g |> h
  • 57. fun f (x:Int) = x + 5 fun g (x:Int) = x + 10 fun h (x:Int) = x + 20 val x = 0 val x2 = f(x) val x3 = g(x2) val result1 = h(x3) fun composed (x: Int) = h(g(f(x))) val result2 = composed(x) let f x = x+5 let g x = x+10 let h x = x+20 let x = 0 let composed = f >> g >> h let result1 = composed x let result2 = x |> f |> g |> h 새로운 함수를 만들면 Compose 함수를 연속적으로 호출하면 Pipe cat /etc/passwd | grep mail
  • 58. val 꽃빛서리 = We.filter { it.drinkHistory.any { (name,_) ->name == "꽃빛서리" } } .map { it.name } val 꽃빛서리People = We.filter { it.drinkHistory.any { (name,_) ->name == "꽃빛서리" } } val 꽃빛서리PeopleName = 꽃빛서리People.map { it.name } X
  • 59. But…. Method 는… • 근본적으로 순수하지 않음 this We.filter { blah blah } .map { blah blah } .map { blah blah } .reduce { blah blah } .Drink() List<Person> 의 Method 만 사용가능
  • 60. val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().MixWater()
  • 61. val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().MixWater() 람다를 쓰고 싶을 때는? 확장함수가 아닌 함수인 경우는?
  • 62. val AlcoholsWithWater = We.flatMap { it.drinkHistory }.distinct().run { MixWater(this) } run/let and so on…
  • 64. val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct() val YangJuAlcohols = listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv 40.0)) val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot{YangJuAlcohols.contains(it)} ??? 파라미터 람다
  • 65. val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct() val YangJuAlcohols = listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv 40.0)) fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol) val WeDrinkAlcoholsWithoutYangJu3 = WeDrinkAlcohols.filterNot(isContainInYangJu val WeDrinkAlcoholsWithoutYangJu2 = WeDrinkAlcohols.filterNot{isContain(YangJuAlcohols,it)} ??? 파라미터
  • 66. val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct() val YangJuAlcohols = listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv 40.0)) fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol) val isContainInYangJu = {alcohol : Alcohol -> isContain(YangJuAlcohols,alcohol) val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot(isContainInYangJu) 캡쳐
  • 67. val WeDrinkAlcohols = We.flatMap { it.drinkHistory }.distinct() val YangJuAlcohols = listOf<Alcohol>(Alcohol(name = "예거",abv = 40.0),Alcohol(name = "보드카",abv 40.0)) fun isContain (list:List<Alcohol>, alcohol: Alcohol) = list.contains(alcohol) val isContainInYangJu = {alcohol : Alcohol -> isContain(YangJuAlcohols,alcohol) val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot(isContainInYangJu) 불변 //… YangJuAlcohols 가 변경되면?
  • 68. Joy Of Clojure 에서 발쵀 스승과의 다음 산책 때 안톤은 스승에게 잘 보일 요량으로 이렇게 말했다. “스승님. 열심히 수양을 닦으면서 객체야 말로 가난한 사람들의 진정한 클로저(Closure) 라는것을 이해하게 되었습니다.“ 그러자 스승은 막대기로 안톤의 머리를 때리더니 이렇게 말했다. “대체 언제 깨달으려 하느냐? 클로저는 가난한 사람의 객체이니라.” 그 순간 안톤은 이치를 깨닫게 되었다. – 안톤 반 스토라텐
  • 70. • 저장 할 수도 있고 • 넘길 수도 있고 • 리턴할 수도 있습니다. Function is Value val isContainInYangJu = {alcohol : Alcohol -> isContain(YangJuAlcohols,alcohol)} val WeDrinkAlcoholsWithoutYangJu = WeDrinkAlcohols.filterNot(isContainInYangJu)
  • 71. sealed class Liquid data class Alcohol(val name:String, val abv:Double) : Liquid() data class SoftDrink (val name:String): Liquid() data class Methanol (val name:String) : Liquid() data class Person(val name:String,val drinkHistory:List<Alcohol>) fun HangOver(person: Person):Unit = println ( "${person.name} feels a hangover :(" ) fun Die(person: Person):Unit = println ( "${person.name} is dead :(" ) fun WhatToDoAfterDrinking(liquid: Liquid):(Person)->Unit = when (liquid) { is Alcohol -> ::HangOver is SoftDrink -> {_ -> Unit} is Methanol -> ::Die } val Soju = Alcohol(name = "소주",abv = 17.6) val AfterDrink = WhatToDoAfterDrinking(Soju) AfterDrink(Lee)
  • 72. enum class LiquidType{ Alcohol, SoftDrink, Methanol } val FuntionMap = mapOf<LiquidType,(Person)- >Unit>( LiquidType.Alcohol to ::HangOver, LiquidType.SoftDrink to {_->Unit}, LiquidType.Methanol to ::Die ) val AfterDrink = FuntionMap[LiquidType.Methanol] ?: {_->Unit} AfterDrink(Lee)
  • 77. fun YesResponse1() = 1 fun YesResponse2() = 2 fun YesResponse3() = 3 fun NoResponse() = Unit fun main(args: Array<String>) { val Response = listOf (YesResponse1(),YesResponse2(),NoResponse(),NoResponse(),YesResponse3()) val ResponseWithoutUnit = Response.filterNot { it is Unit }.map { it as Int } ResponseWithoutUnit.forEach(::println) List[T] Option[T]
  • 78. Functional Functional Programming은 대입문 없이 프로그래밍 하는것 by 엉클밥 불변 순수함수 Reliable regardless of time Reliable regardless of Status Composable 높은 추상화 선언적 쓰기 쉽다 More Safe (적어도 나보단) Thread Safe Testable 견고한 프로그램 유지보수가 쉬워짐
  • 79. Functional Functional Programming is Paradigm C절차지향 언어 OOP 가능 (like Linux) Functional Programming Language? FP를 위한 “툴” 을 제공해주는 언어!
  • 80. For Functional Study • https://fsharpforfunandprofit.com/ • http://clojure.or.kr/docs/clojure-and-gof-design-patterns.html • 클로저 프로그래밍의 즐거움 • 스칼라로 배우는 함수형 프로그래밍 (일명 빨간책) • 한국에서 검색하려면 Haskell / Scala
  • 81. QnA

Notas del editor

  1. 이때 디스트럭팅을 한것을 확인할수있숩니다.
  2. 근본적으로 같은 함수 (같은 JVM 시그니처) 임에도 불구하고 Chaining 을 위해서 extends 로 해줘야함.
  3. 근본적으로 같은 함수 (같은 JVM 시그니처) 임에도 불구하고 Chaining 을 위해서 extends 로 해줘야함.
  4. 근본적으로 같은 함수 (같은 JVM 시그니처) 임에도 불구하고 Chaining 을 위해서 extends 로 해줘야함.