일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- backend
- hacking
- 웹해킹
- 파이썬
- c
- Linux
- flask
- 챗GPT
- BOF 원정대
- Scala
- c++
- ChatGPT
- webhacking
- Python
- php
- 러닝 스칼라
- Web
- 딥러닝
- 러닝스칼라
- deep learning
- 백엔드
- Javascript
- mysql
- 리눅스
- 인공지능
- 경제
- BOF
- hackerschool
- hackthissite
- Shellcode
- Today
- Total
jam 블로그
러닝스칼라 5장 - 일급 함수 본문
스칼라는 일급 함수, 선언형 프로그래밍을 지원한다.
**일급 함수(first-class function)**
: 함수형 프로그래밍에서 함수는 일급(first-class) 객체
- 다른 데이터 타입처럼 리터럴 형태로 생성될 수 있다.
- val, var로 저장될 수 있다.
- 다른 함수의 매개변수나 반환값으로 사용될 수 있다.
**선언형 프로그래밍(declarative programming)**
: 고차함수(또는 다른 함수를 사용하는 로직)는 단순히 이루어져야 할 작업을 선언하고 그 작업을 직접 수행하지 않음
함수 타입과 값
함수 타입은 입력 타입과 반환값 타입의 그룹으로 표현된다.
([<타입>, ...]) => <타입>
def double(x: Int): Int = x * 2
val myDouble: Int => Int = double
myDouble(5)
와일드 카드 연산자로 함수를 할당하면 함수 타입을 쓰지 않아도 된다.
val <식별자> = <함수명> _
val myDouble = double _
고차함수(higher-order function)
입력 매개변수나 반환값으로 함수 타입의 값을 가지는 함수
// safeStringOp: (s: String, f: String => String): String
def safeStringOp(s: String, f: String => String) = {
if (s != null) f(s) else s
}
def reverser(s: String) = s.reverse
safeStringOp(null, reverser) // null
safeStringOp("Ready", reverser) // "ydaeR"
함수 리터럴(function literal)
함수명이 없는 함수
익명 함수(Anonymous function), 람다 표현식(Lambda expression), 람다(Lambda), (function0, function1, function2…) 으로도 불린다.
([식별자: <타입>, ...]) => <표현식>
val doubler = (x: Int) => x * 2
// val doubler = x => x * 2 안됨
val doubled = doubler(22) // 44
함수 리터럴은 고차 함수 호출 내부에서 정의 가능
def safeStringOp(s: String, f: String => String) = {
if (s != null) f(s) else s
}
safeStringOp("Ready", (s: String) => s.reverse)
// safeStringOp("Ready", s => s.reverse) 가능
자리표시자 구문(placeholder syntax)
매개변수를 와일드카드 연산자( _ )로 대체
1) 함수의 명시적 타입이 정의되어 있고, 2) 매개변수가 한 번 사용되거나 사용되지 않을 때 사용가능
placeholder의 개수는 입력 인수 개수와 동일
val doubler: Int => Int = _ * 2
def safeStringOp(s: String, f: String => String) = {
if (s != null) f(s) else s
}
safeStringOp("Ready", _.reverse)
def combination(x: Int, y: Int, f: (Int, Int) => Int) = f(x,y)
combination(23, 12, _ * _) // 23*12
타입 매개변수 사용하기
def tripleOp1[A, B](a: A, b: A, c: A, f: (A, A, A) => B) = f(a,b,c)
tripleOp1[Int, Double](23, 92, 14, _ * _ + _)
// tripleOp1(23, 92, 14, _ * _ + _) 불가능
def tripleOp2[A, B](a: A, b: A, c: A)(f: (A, A, A) => B) = f(a,b,c)
tripleOp2(23, 92, 14)( _ * _ + _)
부분 적용 함수(Partially Applied Function)와 커링(currying)
부분 적용 함수: 와일드 카드 연산자를 이용해서 어떤 함수를 부분적으로 적용한 함수
def factorOf(x: Int, y: Int) = y % x == 0
val multipleOf3 = factorOf(3, _: Int)
val y = multipleOf3(78)
커링: 한 매개변수 그룹은 적용하고 다른 그룹은 적용하지 않는 기법
def factorOf(x: Int)(y: Int) = y % x == 0
val isEven = factorOf(2) _
val z = isEven(32) // true
다중 매개변수 그룹을 가지는 함수를 함수 체인(chain) 형태로 간주한다.
예를 들어 def factorOf(x: Int, y: Int)
의 함수 타입은 (Int, Int) => Boolean
이다.
하지만 def factorOf(x: Int)(y: Int)
의 함수 타입은 Int => Int => Boolean
(체인 형식)이다.
이 함수를 커링하면 Int => Boolean
이 된다.
이름에 의한(by-name) 호출 매개변수
값 또는 값을 반환하는 함수 모두를 취할 수 있는 매개변수, 함수 유연성을 높일 수 있다.
<식별자>: => <타입>
만약 함수를 매개변수로 받는 경우, 함수를 사용할 때 마다 함수를 호출한다.
함수에 반복하여 접근할 때 발생할 수 있는 문제들에 대해 생각하고 사용해야된다.
예를 들어, 데이터베이스에 고정값을 검색하고 그 값을 반환하는 표현식을 by-name 호출 매개변수로 사용한다면 함수 내에서 사용될 때마다 데이터베이스에 접근하게 된다.
def doubles(x: => Int) = {
println("Now doubling " + x)
x * 2
}
doubles(5)
// Now doubling 5
// res18: Int = 10
def f(i: Int) = { println(s"Hello from f($i)"); i }
doubles( f(18) )
// Hello from f(8)
// Now doubling 8
// Hello from f(8)
// res19: Int = 16
부분 함수(partial function)
입력타입을 만족하는 값을 모두 처리하지 못하는 함수
컬렉션과 패턴 매칭으로 작업할 때 유용하다.
val statusHandler: Int => String = {
case 200 => "Okay"
case 400 => "Your Error"
case 500 => "Our Error"
}
statusHandler(401) // scala.MatchError 발생
함수 리터럴 블록으로 고차 함수 호출하기
def safeStringOp(s: String)(f: String => String) = {
if ( s != null ) f(s) else s
}
val uuid = java.util.UUID.randomUUID.toString
val timedUUID = safeStringOp(uuid) { s =>
val now = System.currentTimeMillis
val timed = s.take(24) + now
timed.toUpperCase
}
- 데이터베이스 트랜젝션 관리에서 고차 함수는 세션을 열고, 함수 매개변수를 호출하고, 커밋또는 롤백을 하여 트랜젝션 종료
- 오류를 내지 않을 때까지 함수 매개변수를 여러번 재시도
- 지역, 전역, 외부값(환경변수)에 기반하여 조건부로 함수 매개변수 호출
함수 내용에 관계 없이 일반화해서 처리할 수 있는 부분를 고차 함수로 정의
'IT Book Study > 러닝 스칼라' 카테고리의 다른 글
러닝스칼라 7장 - 그 외의 컬렉션 (0) | 2020.09.28 |
---|---|
러닝스칼라 6장 - 보편적인 컬렉션 (0) | 2020.09.28 |
러닝스칼라 4장 - 함수 (0) | 2020.09.28 |
러닝스칼라 3장 - 표현식과 조건문 (0) | 2020.09.28 |
러닝스칼라 2장 - 데이터로 작업하기: 리터럴, 값, 변수, 타입 (0) | 2020.09.28 |