728x90
함수(function)
- def으로 선언
- 함수를 선언할 때 리턴문과 리턴 타입은 생략이 가능하고, 매개변수의 파라미터 타입은 생략할 수 없음
- 리턴값이 없는 함수를 선언할 때는 Unit을 이용
- 함수의 매개변수는 불변 변수이기 때문에 재할당 할 수 없음
- 리턴 타입을 생략하면 컴파일러가 반환값을 이용하여 자동으로 추론
- 리턴문이 생략되고, 리턴 타입이 Unit이 아니면 함수의 마지막 값을 리턴
// 함수 선언
def add(x: Int, y: Int): Int = {
return x + y
}
// x는 val 이기 때문에 변경 불가
def add(x: Int): Int = {
x = 10
}
// 리턴 타입 생략 가능
def add(x: Int, y: Double) = {
x + y
}
// 리턴 타입이 Unit 타입도 생략 가능
def add(x: Int, y: Int) = {
println(x + y)
}
// 리턴 데이터가 없는 경우 Unit을 선언
def add(x: Int, y: Int): Unit = {
println(x + y)
}
함수의 축약
함수가 1라인으로 처리 가능한 경우에는 중괄호({}) 없이 선언할 수도 있음
// 중괄호 없이 선언
def printUpper(message:String):Unit = println(message.toUpperCase())
// 반환타입도 생략
def printLower(message:String) = println(message.toLowerCase())
파라미터의 기본값
파라미터를 선언하는 시점에 기본값을 지정하고, 파라미터의 개수대로 전달하지 않으면 기본값을 이용
// y에 기본값 선언
def add(x: Int, y: Int = 10): Unit = {
println(x + y)
}
// 기본값 이용
scala> add(1)
11
// 전달값 이용
scala> add(10, 3)
13
가변 길이 파라미터
같은 타입의 개수가 다른 가변 길이의 파라미터를 입력 받는 경우 *를 이용하면 Seq형으로 변환되어 입력
// 여러개의 Int 형을 입력받아서 합계 계산
def sum(num:Int*) = num.reduce(_ + _)
scala> sum(1, 2, 3)
res22: Int = 6
scala> sum(1)
res23: Int = 1
함수에 변수 결과 할당
함수를 def로 선언하지 않고 var, val로 선언할 수도 있음 →
함수를 실행하여 그 반환값이 변수에 입력되므로 함수의 결과(정해져 있는 같은 값)를 여러곳에서 이용할 때만 사용하는 것이 좋음
val random1 = Math.random()
var random2 = Math.random()
def random3 = Math.random()
// random1, random2는 호출할 때마다 같은 값 반환
// 선언 시점에 값이 확정됨
scala> random1
res19: Double = 0.1896318278308372
scala> random1
res20: Double = 0.1896318278308372
scala> random2
res21: Double = 0.817421180386978
scala> random2
res22: Double = 0.817421180386978
// random3은 실행시점에 값이 확정됨
scala> random3
res24: Double = 0.4491518929189594
scala> random3
res25: Double = 0.7644113222566244
중첩 함수(nested function)
함수를 중첩하여 사용 가능
def run() {
def middle() {
println("middle")
}
println("start")
middle()
println("end")
}
scala> run
start
middle
end
람다 함수(Lambda function)
- 익명의 람다 함수를 선언할 수 있음
- 언더바 _를 이용하여 묵시적인 파라미터를 지정할 수 있음
- 묵시적인 파라미터를 이용할 때는 언더바의 위치에 따라 파라미터가 선택 됨
ex)
[exec 함수]
두개의 Int 파라미터를 받고, Int를 반환하는 고차함수 f 와 Int 형 파라미터 x, y를 입력받아서 f 함수를 호출 하면서 파라미터로 x, y를 전달하는 함수
// exec는 3개의 파라미터(함수 f, x, y)를 받음
def exec(f: (Int, Int) => Int, x: Int, y: Int) = f(x, y)
// 람다 함수를 전달하여 처리. x+y 작업을 하는 함수(f) 전달
scala> exec((x: Int, y: Int) => x + y, 2, 3)
res12: Int = 5
// 선언시에 타입을 입력해서 추가적인 설정 없이 처리 가능
scala> exec((x, y) => x + y, 7, 3)
res13: Int = 10
// 함수에 따라 다른 처리
scala> exec((x, y) => x - y, 7, 3)
res14: Int = 4
// 언더바를 이용하여 묵시적인 처리도 가능
scala> exec(_ + _, 3, 1)
res15: Int = 4
커링(currying)
- 여러 개의 인수 목록을 여러 개의 괄호로 정의할 수 있음
- 함수를 정해진 인수의 수보다 적은 인수로 호출하면 그 리턴 값은 나머지 인수를 받는 함수임
// x를 n으로 나누어 나머지가 0인지 확인하는 함수
//함수의 파라미터를 표현하는 방법은 다르지만 같은 함수
def modN(n:Int, x:Int) = ((x % n) == 0) // 1번 n, x 인수를 2번에서는 여러개의 괄호로 받은 것
def modN(n: Int)(x: Int) = ((x % n) == 0) // 2번 커링을 이용해서 n 값을 미리 바인딩 하는 다른 함수로 선언하거나, 다른 함수의 파라미터로 전달할 수 있음
def modN(n: Int)(x: Int) = ((x % n) == 0)
// modN함수를 커링을 이용하여 n 값이 정해진 변수로 호출
def modOne:Int => Boolean = modN(1)
def modTwo = modN(2) _ // _가 modN(2)메소드를 함수로 만들어줌 없으면 에러 남, eta-expansion이라고 함
println(modOne(4)) // true
println(modTwo(4)) // true
println(modTwo(5)) // false
클로저(Closure)
- 함수형 언어에서 클로저는 내부에 참조되는 모든 인수에 대한 묵시적 바인딩을 지닌 함수
- 자신이 참조하는 것들의 문맥을 포함
- 지연 실행의 좋은 예(클로저 블록에 코드를 바인딩함으로써 그 블록의 실행을 나중으로 연기할 수 있음)
타입(Type)
타입을 이용해서 클래스와 함수를 제네릭하게 생성할 수 있음
제네릭(Generic)한 생성이란?
제네릭(generic)이란 데이터의 타입(data type)을 일반화한다(generalize)는 것을 의미하고,
제네릭하게 생성하는 것은
클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법(컴파일 시에 미리 타입 검사(type check)를 수행)
→
1. 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있음
2. 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있음
클래스
import scala.collection.mutable //스칼라는 기본적으로 불변(immutable) 데이터를 이용하기 때문에 변경가능한 스택처리를 위해 import 문을 추가해야 함
trait TestStack[T] {
def pop():T
def push(value:T)
}
class StackSample[T] extends TestStack[T] {//[T] 부분
val stack = new scala.collection.mutable.Stack[T]
override def pop(): T = {
stack.pop()
}
override def push(value:T) = {
stack.push(value)
}
}
val s = new StackSample[String]
s.push("1")
s.push("2")
s.push("3")
scala> println(s.pop())
3
scala> println(s.pop())
2
scala> println(s.pop())
1
메소드
def sample[K](key:K) {//[K] 부분
println(key)
}
def sample2 = sample[String] _// [String] 부분
scala> sample2("Hello")
Hello
참조:
728x90
'language > Scala' 카테고리의 다른 글
[Scala] 스칼라 배우기 6. 스칼라 기본 문법5(collection,배열,리스트,튜플,맵) (2) | 2023.06.11 |
---|---|
[Scala] 스칼라 배우기 5. 스칼라 기본 문법4(trait, singleton object) (0) | 2023.06.11 |
[Scala] 스칼라 배우기 4. 스칼라 기본 문법3(클래스) (0) | 2023.05.23 |
[Scala] 스칼라 배우기 2. 스칼라 기본 문법1(진입점, 객체, 자료형, 문자열, 변수) (0) | 2023.05.14 |
[Scala] 스칼라 배우기 1. 스칼라란? 특징 및 스칼라 언어에 관한 통계 (0) | 2023.05.13 |
댓글