scala의 println은 여러 줄을 출력할 수 있는 기능이 있다. 다른 언어에서는 """ 비슷한 multi line 개념이 있어서 참 좋았다. scala에 이 기능이 있어서 편리하다. 


예시 1 - """ """ 만 쓰면 그대로 공백이 나온다.

예시 2 -""" """에 stripMargin 메소드를 사용해서 공백을 정리한다.  (토큰은 디폴트로 | 이다.)

예시 3-stripMargin 메소드에 사용자 정의 토큰을 정리할 수 있다.

예시 4- new line을 empty string으로 치환할 수 있다.

예시 5 - "" 안에 expression을 사용할 수 있다. 


println {
s"""A is
not B"""
}
println

println {
s"""A is
|not B"""
.stripMargin
}
println

println {
s"""A is
@not B"""
.stripMargin('@')
}
println

println {
s"""A is
@not B"""
.stripMargin('@').replaceAll("\n", " ")
}
println

val commands = List("put", "get", "delete")
val number = 3
println {
s"""
|${commands.size}
|${commands.size / number} """
.stripMargin
}



결과



A is

          not B


A is

not B


A is

not B


A is not B



3

1        




Posted by '김용환'
,


튜플과 _1, _2와 match를 이용한 예시이다. 


튜플은 다양하게 생성할 수 있고, 내부 요소를 _1, _2로 만들 수 있다. 튜플의 개수에 따라 실제로 생성되는 클래스가 동적으로 생성된다. 2개의 요소를 가진 튜플은 scala.Tuple2 타입이다. 

tuple을 통해 타입과 값에 대한 match를 실행해봤고, 이를 더 응용해 메소드에서 match를 쓸 수 있도록 테스트했다.

val student = "Kyle" -> 22
// val student = ("Kyle", 22)
println(student._1, student._2)
println(student.getClass)

val result = student._1 match {
case "ABC" => "What?"
case s: String => "String"
}
println(result)
println(testMatch(student._1))



testMatch 코드는 다음과 같다. string의 값을 case문으로 비교한다. 

def testMatch(str : String) = str match {
case "Kyle" => "KK"
case _ => "Aha"
}



결과는 다음과 같다. 


(Kyle,22)

class scala.Tuple2

String

KK


Posted by '김용환'
,


스칼라의 콜렉션 객체에서 foldLeft을 많이 사용한다. 왼쪽 항부터 마지막 항까지 계산되는 것을 의미한다. 

리스트의 값을 왼쪽에서 오른쪽으로 계산한다. 0(초기값) + 3 + 6 + 9  = 18이 예상된다.

val list : List[Int] = List(3, 6, 9)
println(list.foldLeft(0) ((x, y) => x + y))

결과는 다음과 같다.


18



이 코드는 조금 아래처럼 잼나게 _+_로 바꿔 쓸 수 있다.  결과는 동일하다. 


val list : List[Int] = List(3, 6, 9)
println(list.foldLeft(0) (_+_))

동작이 어떻게 되는 지 궁금하다면 다음처럼 디버깅하듯이 코딩할 수 있다.

val list : List[Int] = List(3, 6, 9)
println(list.foldLeft(0) { (x : Int, y : Int) => println("x:"+ x + ",y:"+ y); x + y })


결과는 다음과 같다.


x:0,y:3

x:3,y:6

x:9,y:9

18








이제, foldRight 메소드를 사용한다.


val list : List[Int] = List(3, 6, 9)

println(list.foldRight(0) ((x, y) => x - y))


 


결과를 0으로 생각할 수 있겠지만, 사실 결과는 6이 출력된다.




출력할 수 있도록 println을 사용해본다.

val list : List[Int] = List(3, 6, 9)
println(list.foldRight(0) { (x : Int, y : Int)
=> println("x:"+ x + ",y:"+ y); x - y })


결과는 다음과 같다. 3 - (-3) = 6 이 된다. 


x:9,y:0

x:6,y:9

x:3,y:-3

6






문자열도 foldLeft도 사용할 수 있다. 


val list : List[String] = List("aaa", "bbb", "ccc")
list.foldLeft("xxx") { (x : String, y : String)
=> println("x: " + x + " y: " + y) ; x + ":" + y}


출력은 다음과 같다.


x: xxx y: aaa

x: xxx:aaa y: bbb

x: xxx:aaa:bbb y: ccc

Posted by '김용환'
,



naive에 대한 좋은 설명이 있는 싸이트


http://www.ohmynews.com/NWS_Web/View/at_pg.aspx?CNTN_CD=A0001330871


말뜻 그대로라면 '소박'이나 '순진'이나 '천진난만'이라는 '나이브'는 '해맑은'이나 '티없는'으로 적바림해야 알맞습니다. 착하거나 맑거나 티없는 사람은 때때로 '고지식하'거나 '어리석'은 짓에 휘말려들곤 하니 '철없다-바보스럽다-꾸밈없다' 같은 낱말을 넣어 볼 수 있습니다.


Posted by '김용환'
,


Stream 객체를 써서 List의 요소를 반복하고 싶다면, Stream.continually(리스트).take() 메소드를 사용한다.


val list : List[String] = List("aaa", "bbb", "ccc")
println(Stream.continually(list).take(10).flatten.toList)



결과


List(aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc, aaa, bbb, ccc)







주의할 점은 다음 코드는 Stream(aaa, ?) 타입을 리턴하게 되니. 값을 확인할 수 없다.


println(Stream.continually(list).take(10).flatten)



scala> Stream.continually(list.toStream).take(10).flatten

res5: scala.collection.immutable.Stream[String] = Stream(aaa, ?)




Posted by '김용환'
,



JIT compiler compiles bytecode on-the-fly.

JIT 컴파일러는 바이트 코드를 즉시 반영할 수 있도록 컴파일한다. 



바로 반영할 수 있는 바이트코드 컴파일러

An On-the-fly Bytecode compiler 



바로 지원

on-the-fly support



서버에서 응답 결과를 압축(gzip)해서 클라이언트로 전송

on-the-fly compression



Posted by '김용환'
,



package object 에 대한 설명은 다음과 같다.

http://www.scala-lang.org/docu/files/packageobjects/packageobjects.html



com/google/utility 디렉토리에 package.scala를 생성하고 다음 코드를 저장한다.

scala에 패키지용 utility 처럼 쓸 수 있는 클래스와 같다. 


package com.google

import org.slf4s.Logging

package object utility extends Logging {
def print(message : String): Unit = {
println(message)
}
}


com/google 디렉토리에 test.scala를 생성한다.


package com
package google

object test {
def main(args: Array[String]): Unit = {
utility.print("test")
}
}


실행 결과는 다음과 같다.


test 




참고로 같은 패키지에 존재하기 때문에 test 클래스는 다음처럼 사용할 수 있다.


package com
package google

object test {
def main(args: Array[String]): Unit = {
print("test")
}
}

또는


object test {
def main(args: Array[String]): Unit = {
print("test")
}
}


Posted by '김용환'
,





네이트 실버의 <신호와 소음>이라는 책 뒷 부분에 아래 글이 있어서 참 좋았다. (오래만에 본 정말 최고의 책이었다.)

이 책에서 인용한 글의 원문은 Serenity Prayer이었다.



예측은 아주 중요하고 그 때문에 더욱 어렵다. 소음에서 신호를 분리하려면 과학적 지식과 자기 인식을 갖추어야 한다. 즉, 객관적 실체와 주관적 실체를 교차시켜야 한다. 우리가 예측할 수 없는 것에 대한 겸손함과 예측할 수 있다는 것을 예측할 수 있는 용기, 그리고 이 둘 사이의 차이를 아는 지혜가 필요하다.




기도문에 있는 라인홀트 리버라는 신학자가 설교에 쓴 기도문이라고 한다.



https://ko.wikipedia.org/wiki/%ED%8F%89%EC%98%A8%EC%9D%84_%EB%B9%84%EB%8A%94_%EA%B8%B0%EB%8F%84


God, give us grace to accept with serenity the things that cannot be changed, courage to change the things that should be changed, and the wisdom to distinguish the one from the other.
(주여, 우리에게 우리가 바꿀 수 없는 것을 평온하게 받아들이는 은혜와 바꿔야 할 것을 바꿀 수 있는 용기, 그리고 이 둘을 분별하는 지혜를 허락하소서.)



참조

http://www.aahistory.com/prayer.html

Posted by '김용환'
,