스칼라 2주차
1. Higher-Order Functions
Higher order function이란?
function을 파라미터로 받는 function
anonymous function syntax
def cube(x: Int): Int = x * x * x
(x: Int) => x * x * x
2. Currying
def sum(f: Int => Int): (Int, Int)=> Int = {
def Sumf(a: Int, b: Int):Int = {
if (a>b) 0
else f(a) + Sumf(a+1, b)
}
Sumf
} //> sum: (f: Int => Int)(Int, Int) => Int
def sum2(f: Int => Int) (a: Int, b: Int):Int = {
def loop(a: Int, acc:Int):Int = {
if (a>b) acc
else loop(a+1, f(a) + acc)
}
loop (a, 0)
} //> sum2: (f: Int => Int)(a: Int, b: Int)Int
def sum3(f: Int => Int) (a: Int) (b:Int):Int = {
def loop(a: Int, acc:Int):Int = {
if (a>b) acc
else loop(a+1, f(a) + acc)
}
loop (a,0)
} //> sum3: (f: Int => Int)(a: Int)(b: Int)Int
sum2(x=>x)( 1,2) //> res4: Int = 3
sum3(x=>x)(1)(2) //> res5: Int = 3
val sum2a = sum2(x=>x*x)_ //> sum2a : (Int, Int) => Int = <function2>
sum2a(1,2) //> res6: Int = 5
sum2a(1)_ //컴파일 에러 뜬다. sum3형태로 하면 뜨지 않으니 무조건 인자를 하나씩 끊는 게 좋을 듯.
과연 sum하고 sum2는 같은 타입일까? sum2는 뒤에 언더바를 붙이지 않으면 f만 넣은 상태에서 컴파일 에러가 뜬다.sum
의 타입이 (Int=>Int)=>((Int, Int)=>Int)
혹은 (Int=>Int)=>(Int=>Int)=>Int
(right associativity)
sum2는 (Int=>Int, Int, Int)=>Int
타입과 sum2 타입의 중간 정도라고 생각…??
3. 스칼라 syntax
Language Elements Seen So Far:
We have seen language elements to express types, expressions and
definitions.
Below, we give their context-free syntax in Extended Backus-Naur
form (EBNF), where
\ denotes an alternative,
[…] an option (0 or 1),
{…} a repetition (0 or more).
Types
종류 | syntax |
---|---|
Type | SimpleType \ FunctionType |
FunctionType | SimpleType ‘=>’ Type \ ‘(’ [ Types ] ‘)’ ‘=> ’ Type |
SimpleType | Ident |
Types = | Type { ‘ , ’ Type } |
A type can be:
▶ A numeric type: Int, Double (and Byte, Short, Char, Long,
Float),
▶ The Boolean type with the values true and false,
▶ The String type,
▶ A function type, like Int => Int, (Int, Int) => Int.
Expressions
Expr = InfixExpr | FunctionExpr
| if ‘( ’ Expr ‘) ’ Expr else Expr
InfixExpr = PrefixExpr | InfixExpr Operator InfixExpr
Operator = ident
PrefixExpr = [ ‘+ ’ | ‘-’ | ‘! ’ | ‘~ ’ ] SimpleExpr
SimpleExpr = ident | literal | SimpleExpr ‘. ’ ident
| Block
FunctionExpr = Bindings ‘= > ‘ Expr
Bindings = ident [ ‘: ’ SimpleType ]
| ‘( ’ [ Binding { ‘ , ’ Binding }] ‘) ’
Binding = ident [ ‘: ’ Type ]
Block = ‘{ ’ { Def ‘; ’} Expr ‘} ’
Expressions (2)
An expression can be:
▶ An identifier such as x, isGoodEnough,
▶ A literal, like 0, 1.0, ”abc”,
▶ A function application, like sqrt(x),
▶ An operator application, like -x, y + x,
▶ A selection, like math.abs,
▶ A conditional expression, like if (x < 0) -x else x,
▶ A block, like { val x = math.abs(y) ; x * 2 }
▶ An anonymous function, like x => x + 1.
Definitions
Def = FunDef | ValDef
FunDef = def ident { ‘( ’ [ Parameters ] ‘) ’}
[ ‘: ’ Type ] ‘= ’ Expr
ValDef = val ident [ ‘: ’ Type ] ‘= ’ Expr
Parameter = ident ‘: ’ [ ‘= > ’ ] Type
Parameters = Parameter { ‘ , ’ Parameter }
A definition can be:
▶ A function definition, like def square(x: Int) = x * x
▶ A value definition, like val y = square(2)
A parameter can be:
▶ A call-by-value parameter, like (x: Int),
▶ A call-by-name parameter, like (y: => Double).
4 & 5. Functions and Data
class Rational(x: Int, y: Int) {
def numer = x
def denom = y
def add(r: Rational) =
new Rational(numer * r.denom + r.numer * denom, denom * r.denom)
override def toString = numer.toString + '/' + denom.toString
def max(that: Rational) = if (this.less(that)) that else this
}
스칼라에서 클래스 정의를 하면 새로운 타입을 정의하고, 그걸 만들 수 있는 생성자 함수를 만들어낸다. 스칼라에서는 types와 values가 다른 공간에 있기 때문에 클래스 이름을 다른 정의에 사용가능하다. ex) def Rational = 1
this로 자기 자신을 refer.
require and assert
둘다 컨디션과 옵셔널한 스트링 메세지로 호출할 수 있는 predefined 함수.
assert는 assertionError를, require은 IllegalArgumentException을 throw한다.
2차 생성자 함수
class Rational(x: Int, y: Int) {
def this(x: Int) = this(x, 1)
...
}
Evaluation and Operators
new Rational(1, 2).less(new Rational(2, 3))
→ [1/x, 2/y] [newRational(2, 3)/that] [new Rational(1, 2)/this]
this.numer * that.denom < that.numer * this.denom
= new Rational(1, 2).numer * new Rational(2, 3).denom < new Rational(2, 3).numer * new Rational(1, 2).denom
→→ 1 * 3 < 2 * 2
→→ true
substitution의 순서는 항상 상관없나? 상관없을 것 같은데… 확실하지 않음.
single parameter method의 경우r add x <=> r.add(x)
method의 identifier
자바랑 다르게 특수문자 사용가능. 규칙은 다음과 같다.
▶ Alphanumeric: starting with a letter, followed by a sequence of letters or numbers
▶ Symbolic: starting with an operator symbol, followed by otheroperator symbols.
▶ The underscore character ’_’ counts as a letter.
▶ Alphanumeric identifiers can also end in an underscore, followed by some operator symbols.
Examples of identifiers:
x1 | * | +?%& | vector_++ | counter_= |
---|---|---|---|---|
우선순위
점수가 높을수록 높다.
점수 | 기호 |
---|---|
1 | all letters) |
2 | ‘or 기호’ |
3 | ^ |
4 | & |
5 | < > |
육 | = ! |
7 | : |
8 | + - |
9 | * / % |
10 | (all other special characters) |
'프로그래밍' 카테고리의 다른 글
Jquery Ajax cache 문제 (0) | 2016.07.23 |
---|---|
윈도우에서 tensorflow 개발 환경 세팅 (0) | 2016.07.22 |
coursera 스칼라 1주차 (0) | 2015.05.18 |
[이펙티브 자바] 챕터 3 - 공통 메서드 (0) | 2015.04.08 |
[이펙티브 자바] 챕터 2 (0) | 2015.04.07 |