If 표현식에 대해 살펴보겠습니다.

일반적인 자바와 같은 명령형 프로글밍에서는 왼쪽 코드와 같이 if 문을 사용합니다. Args가 비어있지 않다면 filenameargs(0)을 할당하고 비어 있다면 “default.txt” 가 됩니다.

이런 if문은 어쩔 수 없이 var을 사용해야 합니다. If 조건문에 따라서 변수 값을 바꿔야 하기 때문입니다.

하지만 스칼라는 제어 구문이 결과를 내놓는다는 특징이 있기 때문에 오른쪽과 같이 코드를 바꿀 수 있습니다.

만약 args가 비어있지 않다면 args(0)값을 내놓고 비어있다면 “default.txt” 값을 내놓습니다. If 표현식이 내놓은 값을 filenam에 바로 집어넣습니다.

이렇게 하면 filename에 값을 바로 넣는 것이기 때문에 filenameval로 정의 가능하여 부수효과를 없앨 수 있습니다.

그리고 이러한 표현식은 하나의 값을 무조건 내놓기 때문에 표현식과 값을 동등하게 봐 아래와 같이 println내부에 표현식을 집어넣을 수 있습니다.

 

While은 일반적으로 참인 조건동안 특정 작업을 수행하는 데 사용하고 어떤 리턴하는데 사용하지 않습니다. , 값을 내놓지 않기 때문에 표현식이라 하지 않고 루프라고 합니다.

그래서 while 루프의 결과 타입은 Unit 이라는 빈 값이 되겠습니다.

Unit 에 대해 알아보면 Unit메소드에서 리턴이 없을 때, var 변수에 값을 재할당할 때 반환됩니다. 반환된 Unit 값은 “()”가 됩니다.

왼쪽 코드를 보면 greet()라는 println을 수행하는 메소드의 리턴값이 Unit이고 값으로 표현할 때는 빈괄호가 되는 것을 알수 있습니다.

오른쪽 코드는 특정 파일의 line빈문자열이 될 때까지 한 줄씩 읽는 것을 나타냅니다.

한 줄씩 읽는 코드를 보면 line변수에 읽은 문자열을 재할당하는 때 이 때 Unit 값인 ()가 반환됩니다. 따라서 “line=readLine()” 결과가 항상 ()이므로 “”와 같을 수가 없어 루프가 무한 반복됩니다.

다시 while루프에 대해서 보면 while 루프는 결과가 특정 값이 아니기 때문에 함수형 언어에서는 이를 종종 제외합니다.

while루프를 제외 이유는 작업을 통해 프로그램에 영향을 주기 위함인데  while 결과가 값이 아니라면 프로그램에 영향을 주기 위해 I/O를 수행하거나 외부 var 변수를 갱신해야해 부수효과를 일으키기 떄문입니다.

하지만 스칼라는 while을 사용한 코딩 방법의 가독성이 더 뛰어난 경우가 있기 때문에 while을 없애지 않았습니다.

따라서 while은 부수효과를 일으킬 가능성이 매우 높기 떄문에 사용할 때 var을 최소화하고 꼭 while을 사용해야 하는지 의심해야 합니다.

 

 

for 표현식 여러 기능에 대해서 살펴보겠습니다.

스칼라의 for 표현식은 배열이 아닌 어떤 컬렉션에도 iteration이 적용됩니다. <- 사용 iteration 합니다. <- 문법을 제너레이터라고 하는 데 제너레이터에 의해 생성되는 하나의 원소는 모두 val 타입이 됩니다.

또한 Range 타입이 존재하는 데 아래 코드와 같이 to를 사용하면 1,2,3,4 순회할 수 있고 until을 사용하면 마지막을 제외한 1,2,3 순회하게 됩니다.

위와 같은 기능들이 있기 때문에 아래의 코드는 스칼라에서 바람직하지 않습니다. To 대신 until을 사용해서 -1을 제거해 간단하게 보이게 할 수도 있고 맨 위 코드와 같이 직접 iteration 할 수 있기 때문입니다.

 

for를 수행하는 과정에서 전체 컬렉션 중에 조건에 맞는 원소들만 사용하고 싶을 경우가 있습니다. 이 때 필터를 사용하면 됩니다.

일반적인 명령형 프로그래밍에서는 맨 위와 같이 for문 아래에 if문을 넣으면 되지만 함수형에서는 for조건절 내부에 if문을 삽입하면 됩니다.

만약 여러 개 필터를 추가하고 싶을 때는 아래 코드와 같이 하면 됩니다.

 

2개의 루프를 중첩하고 싶다면 forgenerator 부분에 <-를 추가하면 됩니다.

여기서 각 <- 세미콜론으로 구분을 했는 데 소괄호가 아닌 대괄호를 사용하며 컴파일러에서 세미콜론을 추론해 세미콜론을 생략할 수 있습니다.

 

 

왼쪽 코드는 line.trim 이라는 코드가 반복됩니다. trim을 한 번만 계산하고 싶다면 오른쪽 코드와 같이 for문 내부에 변수를 만들 수 있습니다.

trimmed 변수가 val인지 var인지 명시되지 않았는 데 자동으로 val로 선언됩니다.

 

 

앞에서 보았던 for문은 컬렉션을 iteration하면서 조작만 하고 결과는 무시했습니다. 하지만 iteration의 매 반복 단계의 결과를 저장할 수 있습니다.

이 때 for 표현 식 뒤 그리고 본문 앞에 yield 키워드를 사용하면 됩니다.

왼쪽 예는 파일 리스트를 순회하면서 “.scala로 끝나는 파일들을 반환합니다. 여기서 리턴값은 Array[File]이 됩니다.

오른 쪽은 “.scala로 끝나는 파일들의 파일 내용을 라인별로 순회하면서 for 문자열이 들어간 라인의 길이를 리턴합니다. 여기서 리턴 값은 Array[Int]가 되겠습니다.

또한 아래 처럼 yield 뒤에 본문에 중괄호를 써서 특정 로직을 명시할 수도 있습니다.

 

 

스칼라에서 try는 자바의 try와 비슷합니다. 예외를 발생시킬 때는 위 코드와 같이 “throw new Exception”으로 예외를 던지게 됩니다.

코드를 보면 n2로 나눌 때 예외가 발생할 때 예외를 던지는 데 이때 예외는 Nothing이라는 타입을 반환합니다. 그래서 halfNothing 타입 값이 들어갑니다.

그러나 예외가 나면 이 로직을 호출한 쪽으로 제어흐름이 넘어가기 때문에 half 변수를 다시 사용할 일이 없어 Nothing 타입에 대해 신경 쓸 필요가 없습니다.

단순히 throw를 자유롭게 쓰기 위한 기술적 장치일 뿐입니다.

Throw로 발생한 예외를 잡기 위해서는 자바와 똑같이 catch를 사용합니다. 다른 점은 자바는 catch 구문마다 파라미터에 throws로 자신이 잡을 예외 종류를 명시합니다.

하지만 스칼라는 하나의 catch 절 안에 case 구문을 이용해 예외를 잡게 됩니다.

 

 

Finally 절은 표현식의 결과가 어떻든 특정 코드를 반드시 수행하고 싶을 경우 finally 절로 감쌀 수 있습니다.

스칼라에서는 finally를 파일, 소켓, 데이터 베이스를 사용 후 자원을 확실히 닫기 위해 사용합니다.

다른 표현식과 마찬가지로 try-catch-finally의 결과도 값입니다.

왼쪽 코드를 보면 예외가 나지 않을 때는 path URL 객체를 반환하고 예외가 발생했을 때는 다른 url리턴하는 걸 볼 수 있습니다.

Finally 의 경우 독특합니다. 스칼라에서 finally는 무조건 자원을 닫는 정리 작업만 수행해야 합니다.

오른쪽 코드와 같이 finally 에서 명시적으로 return을 쓰면 finally에서 값을 내놓지만 return을 사용하지 않으면 finally에서 값을 내놓지 않습니다.

, finally는 결과값을 만들어 내기보다는 파일을 닫거나 정리 작업을 하는 등의 부수효과를 제공하는 방법으로 생각해야 합니다.

 

 

Match 표현식은 자바의 switch문과 유사합니다. 코드를 보면 match 표현식 앞에 비교할 변수를 적습니다. 그리고 각 case 별로 firstArg 변수가 “salt” 인지 확인합니다.

스칼라의 match 표현식이 자바의 switch와 다른 점은 case 문에 타입에 상관없이 상수를 사용할 수가 있습니다.

그리고 break문이 없는데 내부적으로 break문이 암묵적으로 있어서 break 문 없어도 다음 case 문으로 넘어가지 않습니다.

“_”는 디폴트 케이스에 해당합니다.

그리고 match도 역시 표현식이기 때문에 코드와 같이 값을 내놓는 것을 볼 수 있습니다.

 

 

스칼라는 break문과 continue 문이 없습니다. 왜냐하면 스칼라는 함수 자체가 값을 가지게 되는 데 breakcontinu를 사용하게 되면 어떤 경우에서는 값을 가지지 않게 되기 때문입니다.

그래서 스칼라에서는 continu문을 if문으로 , break문을 Boolean 변수로 대체하라고 합니다. 또는 breakcontinu문은 while 구문 안에서 많이 사용되는 데 이를 재귀함수로 바꾸라고 합니다.

 

 

 

변수 스코프는 자바와 동일합니다. 안쪽 스코프에서 정의된 변수는 외부에서 사용할 수 없고 외부에서 정의된 변수는 내부에서 사용할 수 있습니다.

자바와 다른 점은 자바는 안쪽 스코프와 바깥쪽 스코프에서 동일한 변수 이름을 재정의한다면 컴파일 오류가 납니다. 그런데 스칼라에서는 이게 가능합니다.

예에서 println(a)를 하게 되면 가장 가까운 스코프의 변수를 출력하게 되 2가 출력되고 이런 것을 안쪽 변수가 바깥 스코프의 변수를 가렸다 라고 표현합니다.

이와 같이 동일한 변수에 값을 재정의하는 것을 스칼라 인터프리터를 통해 봤었는 데 마음대로 재정의 할 수 있는 이유는 오른쪽과 같이 입력한 각 라인마다 안쪽에 새로운 스코프를 만들기 때문입니다.

그래서 재정의가 가능하고 a에는 외부 스코프의 변수를 가리고 최종적으로 3이 들어가 출력됩니다.

 

+ Recent posts