ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다이나믹언어처럼 느껴지는 스태틱언어 : Scala
    Humor 2016. 6. 14. 15:38

    다이나믹언어처럼 느껴지는 스태틱언어 : Scala

    Scala: The Static Language that Feels Dynamic


    Bruce Eckel

    by Bruce Eckel


    2011. 6. 12

    June 12, 2011


    개요

    Summary


    파이썬 진영에서 가져올 수 있는 최고의 보완은 "Pythonic하다"라고 말하는 것입니다. 한번도 정적언어가 그렇게 느껴질 수 있다고 생각해보지 않았는데 스칼라는 그렇게 느껴집니다. 어쩌면 좀 더 좋은지도 모르겠습니다.

    The highest complement you can deliver in the Python world is to say that something is "Pythonic" -- that it feels and fits into the Python way of thinking. I never imagined that a static language could feel this way, but Scala does -- and possibly even better.



    언어를 배우기 이전부터 오랫동안 이 순간을 기다려왔습니다. 왜냐하면 그동안 많은 이슈들이 있었기 때문입니다. 사실 언어의 여러가지 버전들은 하위호환성을 깨뜨려서 코드의 재작성을 필요하게 만들었습니다. 몇몇 사람들은 이런 점을 발견했을 때 당황하면서 언어가 "미숙"하고 "엔터프레이즈급에 대한 준비가 되지 않았다"고 생각했습니다. Scala가 약속하고 있는 것들 중 하나가 있는데 나중에 알게 될 수 있는 차선책이나 명백한 실수가 될 수 있는 결정을 조기에 미리 확정되도록 하지 않았다는 것입니다. Java는 오래전에 결정한 내용으로 인해 고정된 것들이 인터넷에서 약속된 기한까지 맞추기 위해서 더욱 나쁘게 만들어졌다는 것을 알 수 있는 완벽한 케이스스터디입니다. C++는 C 프로그래머들을 객체지향프로그래밍의 세계로 데려오면서 C호환성을 유지하기로 결정했을 때는 훌륭했었지만 문제점까지 카피한 것은 프로그래머들에게 더이상 좋은 것이 아니었습니다.

    I'm actually glad I waited this long before beginning to learn the language, because they've sorted out a lot of issues in the meantime. In fact, several versions of the language have made breaking changes with previous versions, requiring code rewrites. Some people have found this shocking; an indication that the language is "immature" and "not ready for the enterprise." I find it one of the most promising things about Scala -- it is not determined to become an instant boat anchor by committing to early decisions that are later revealed to be suboptimal, or outright mistakes. Java is the perfect case study, unable to pry its cold, dead fingers from old decisions made badly in a rush to meet an imagined deadline imposed by the Internet. C++ was admirable when it determined to be C-compatible because it brought legions of C programmers into the world of object-oriented programming, but coping with the resulting hurdles is no longer a good use of programmer time.


    사실 언어의 디자인이 프로그래머들의 시간보다 중요하다는 마인드때문에 피곤했었습니다. 그 때문에 언어가 프로그래머를 위한 것이 아닌 프로그래머가 언어를 위해서 일해야 했습니다. 그래서 완전히 프로그래밍과 함께 자라왔지만 언어의 지난 세대에 지쳤고 이제 다음 세대를 기다리고 있습니다. 특히 진보적인 언어를 기다리고 있습니다.

    Indeed, I grew tired of the whole mindset that language design is more important than programmer time; that a programmer should work for the language rather than the reverse. So much so that I thought I had grown out of programming altogether. But now I think I might just have been tired of the old generation of languages and waiting for the next generation -- and especially the forward-thinking around those languages.


    당신이 이전의 제가 작성한 글을 보았다면 그 자체의 목적(보통 "만약 X가 int라는 것을 알 수 없다면 세계를 파멸될 것이다!"로 이어졌습니다.)을 위해서 정적으로 타입을 체크하는 것에 대해서 별로 좋아하지 않는다는 것을 알 것입니다. 이러한 영향을 받지 않으면서 파이썬으로 충분히 안정적인 코드를 작성했습니다. 더 적은 양의 명확한 파이썬 코드로 무엇을 할수 있는가에 비하면 C++과 자바에서 강제된 것을 하기 위한 비용이 훨씬 작아보입니다.

    If you've read my past writings, you know I am unimpressed with arguments about static type checking for its own sake, which typically come down to "if I can't know X is an int, then the world will collapse!" I've written and seen enough robust code in Python to be unswayed by such histrionics; the payoff for all the hoop-jumping in C++ and Java seems small compared to what can be accomplished using far less, and much clearer, Python code.


    Scala는 정적 타입체크문제를 해결한 것처럼 보이는 첫번째 언어입니다. 놀랍도록 뒤틀려진 능력들은 정적 타입체킹이 없이도 가능할 거라고 생각합니다. 그리고 이 글에서 보여주려는 것처럼 정적타입체크는 비교적 간섭을 하지 않습니다. 그래서 스칼라로 프로그래밍하는 것은 파이썬 같은 동적 언어에서 프로그래밍하는 것처럼 느껴집니다.

    Scala is the first language I've seen where static type-checking seems to pay off. Some of its amazing contortional abilities would not, I think, be possible without static type checking. And, as I shall attempt to show in this article, the static checking is relatively unobtrusive -- so much so that programming in Scala almost feels like programming in a dynamic language like Python.


    단순히 타이핑양(Finger Typing)에 대한 것이 아닙니다.

    It's Not "Just About Finger Typing"


    파이썬같은 언어와 비교한 자바의 결점을 논의할 때 가장 많이 받은 반박은 "당신은 단순히 타이핑양(Finger Typing)에 대해서 불평하는 것입니다"라는 것입니다.(타입체킹에서 "Typing"과는 다른 개념입니다.)

    One retort I've gotten a lot when I discuss the shortcomings of Java compared with a language like Python is "oh, you're just complaining about Finger Typing" (as opposed to the "typing" of type-checking).


    "타이핑양"을 사소하게 생각할 수 있지만 경험상 실제로 큰 차이를 만들어 냅니다. 아이디어가 생겨서 표현하려고 할 때 아주 간단한 컨셉조차도 자바에서 필요한 코드양과 비교하면 훨씬 적은 코드량으로 표현할 수 있습니다. 진짜 문제는 타이핑 수가 아니라 정신적인 부하이다. 이렇게 강제된 것에 시간을 들이게 되면서 실제로 무엇을 타이핑하려고 했는지 잊어버리게 됩니다. 무언가를 하기 위해 강제된 형식들은 종종 시도조차 좌절시킬 것입니다.

    You can trivialize "finger typing" but in my experience it really does make a big difference when you can take an idea and express it in a few keystrokes versus the veritable vomiting of code necessary to express even the simplest concepts in Java. The real problem is not the number of keystrokes, but the mental load. By the time you've jumped through all those hoops, you've forgotten what you were actually trying to do. Often, the ceremony involved in doing something will dissuade you from trying it.


    Scala는 최대한 오버헤드(그리고 정신적 부하)를 없앴기 때문에 타이핑속도만큼 빠르게 higher-order 컨셉을 표현할 수 있습니다. 많은 경우에서 스칼라가 파이썬보다 더 간결하다는 것을 발견했을 때 놀랐습니다.

    Scala removes as much of the overhead (and mental load) as possible, so you can express higher-order concepts as quickly as you can type them. I was amazed to discover that in many cases, Scala is even more succinct than Python.


    이 모든 결과가 제가 항상 파이썬을 사랑했던 이유입니다: 추상화레벨은 일반적으로 화이트보드에 다이어그램을 그리는 것보다 더 쉽고 명확하게 코드로 아이디어를 표현할 수 있다는 것입니다.

    The result of all this is something I've always loved about Python: the level of abstraction is such that you can typically express an idea in code more easily and clearly than you can by making diagrams on a whiteboard. There's no need for that intermediate step.


    예제를 보겠습니다. 다음처럼 모델을 만들다고 가정해보겠습니다:

    Let's look at an example. Suppose you'd like to model buildings. We can say:


    class Building

    val b = new Building


    클래스를 만드는 형식의 양이 절대적으로 적기 때문에 스케치할때 아주 좋습니다. 괄호가 필요없다면 괄호를 쓰지 않습니다. val은 불변(immutable)하면서 동시성코드를 더 쉽게 작성할 수 있기 때문에 스칼라에서는 더 선호됩니다.(변수에는 var도 있습니다.) 그리고 b에 어떤한 타입 정보도 작성하지 않았다는 것을 주목해야합니다. 왜냐하면 스칼라는 타입추론을 가지고 있기 때문에 알아서 타입을 찾아줍니다. 더이상 게으른 언어에 만족하고 있을 필요가 없습니다.

    Note the absolute minimum amount of ceremony to create a class -- great when you're just sketching out a solution. If you don't need parens, you don't write them. A val is immutable, which is preferred in Scala because it makes concurrent code easier to write (there is also var for variables). And notice that I didn't have to put any type information on b, because Scala has type inference so if it can figure out the type for you, it will. No more jumping through hoops to satisfy a lazy language.


    Building이 몇 평방피트인지 알기를 원한다면 명시적인 방법이 있습니다:

    If we want the Building to know how many square feet it contains, there's an explicit way:


    class Building(feet: Int) {

      val squareFeet = feet

    }

    val b = new Building(100)

    println(b.squareFeet)


    타입정보를 제공해야 할 필요가 있을 때는 콜론(:) 다음에 타입정보를 주면 됩니다. println()이 자바의 System.out 범위를 필요로 하지 않는 다는 것을 알아야 합니다. 그리고 클래스 필드는 기본적으로 public 입니다. val로 선언한다면 읽기 전용이기 때문에 큰 문제가 아닙니다. 원한다면 언제든지 private로 만들수 있고 스칼라는 제가 본 어떤 언어보다 잘 만들어진 접근제어를 가지고 있습니다.

    When you do need to provide type information, you just give it after a colon. Note that println() does not require Java's System.out scoping. And class fields default to public -- which is not a big deal if you can stick to val, since that makes it read-only. You can always make them private if you want, and Scala has more fine-grained access control than any language I've seen.


    만약 하려는 것이 클래스에 아규먼트를 저장하는 것이 전부라면 스칼라에서는 쉽게 할 수 있습니다:

    If all you want to do is store the argument in the class, as above, Scala makes it easy. Note the addition of the val in the argument list:


    class Building(val feet: Int)

    val b = new Building(100)

    println(b.feet)


    이제 feet는 자동적으로 필드가 되지만 거기서 끝이 아니고 Scala는 더 많은 것을 제공하는 case class를 가지고 있습니다. case클래스에서는 val을 작성할 필요없이 아규먼트는 자동적으로 필드가 됩니다.

    Now feet automatically becomes the field. But it doesn't stop there. Scala has the case class which does even more for you. For one thing, arguments automatically become fields, without saying val before them:


    case class Building(feet: Int)

    val b = Building(100)

    println(b) // Result: Building(100)


    객체를 생성할때 new를 사용하지 않았고 파이썬에서도 동일합니다. case 클래스가 toString을 재작성해주기 때문에 보기 좋은 아웃풋을 생성합니다.

    Note the new is no longer necessary to create an object, the same form that Python uses. And case classes rewrite toString for you, to produce nice output.


    하지만 여기서 끝이 아닙니다. case 클래스는 자동으로 적절한 해쉬코드와 ==를 제공하기 때문에 Map에서 사용할 수 있습니다.(->는 값과 키를 구분합니다.)

    But wait, there's more! A case class automatically gets an appropriate hashcode and == so you can use it in a Map (the -> separates keys from values):


    val m = Map(Building(5000) -> "Big", Building(900) -> "Small", Building(2500) -> "Medium")

    m(Building(900)) // Result: Small


    Map은 어떤 import없이도 "스칼라가 기본적으로 제공하는 세트"의 일부로써 이용이 가능합니다.(추가적으로 List, Vector, Set, println()등이 있습니다.) 다시 말하지만 이것은 파이썬처럼 느껴집니다.

    Note that Map is available (along with List, Vector, Set, println() and more) as part of the "basic Scala building set" that comes without any imports. Again, this feels like Python.


    상속도 간단합니다. Building의 서브클래스로 House클래스를 만들어 보겠습니다:

    Inheritance is also succinct. Suppose we want to subclass Building to make a House class:


    class House(feet: Int) extends Building(feet)

    val h = new House(100)

    println(h.feet) // Result: 100


    extends 키워드가 자바에서 익숙한 키워드이지만 베이스클래스의 생성자가 어떻게 호출되는지 알아야 합니다. 가장 명확한 방법은 직접 보는 것이고 설명하는데 반드시 필요한 것 외에는 어떤 코드도 작성하지 않을 것입니다.

    Although the extends keyword is familiar from Java, notice how the base-class constructor is called -- a pretty obvious way to do it, once you've seen it. And again, you don't write any more code than what is absolutely necessary to describe your system.


    trait를 사용해서 행동(behavior)을 믹스인할 수 있습니다. trait는 클래스가 생성될 때 합쳐질 수 있는 메서드정의를 포함할 수 있다는 점을 빼고는 인터페이스와 아주 유사합니다. 여기 house를 묘사하는 여러 개의 trait가 있습니다:

    We can also mix in behavior using traits. A trait is much like an interface, except that traits can contain method definitions, which can then be combined when creating a class. Here are several traits to help describe a house:


    trait Bathroom

    trait Kitchen

    trait Bedroom {

      def occupants() = { 1 }

    }

    class House(feet: Int) extends Building(feet) with Bathroom with Kitchen with Bedroom

    var h = new House(100)

    val o = h.occupants()

    val feet = h.feet


    occupants()는 일반적인 Scala의 메서드정의입니다: def 키워드뒤에는 메서드명과 아규먼트리스트가 오고 그 다음에 =가 오고 중괄호안에 메서드 바디가 옵니다. 메서드에서 마지막 라인은 리턴값이 됩니다. 여기에서 또다른 타입추론이 일어났습니다; 더 명확하기를 원한다면 메서드의 리턴타입을 명시해 줄 수 있습니다

    occupants() is a typical Scala method definition: the keyword def followed by the method name, argument list, and then an = and the body of the method in curly braces. The last line in the method produces the return value. More type inference is happening here; if we wanted to be more specific we could specify the return type of the method:


    def occupants(): Int = { 1 }


    occupants() 메서드는 traits의 믹스인(mixin)을 통해서 이제 Howse의 일부가 되었습니다.

    Notice that the method occupants() is now part of House, via the mixin effect of traits.


    이 코드가 얼마나 간단하고 얼마나 집중되어 있는지 보십시오. 자바에서처럼 반드시 해야하지만 의미는 없는 문법적인 요구사항을 설명하는 대신에 무엇을 하는지에 대해서 얘기할 수 있습니다. model을 생성하는 것은 몇줄안되는 간단한 코드일뿐이다. 초급 프로그래머에게 이것을 가르치는 것이 자바보다 쉽지 않습니까?

    Consider how simple this code is ... and how undistracting. You can talk about what it's doing, rather than explaining meaningless syntactic requirements as you must do in Java. Creating a model takes no more than a few lines of straightforward code. Wouldn't you rather teach this to a novice programmer than Java?


    함수형 프로그래밍

    Functional Programming


    펑셔널 프로그래밍은 종종 동시성을 처리하는 방법으로 가장 잘 알려져 있습니다. 하지만 근본적으로 프로그래밍 문제를 분석하는 방법에 더 유용하다는 것을 발견했습니다. 사실 C++는 내장된 동시성 지원없이도 STL의 형식으로 처음부터 가상적인 함수형 프로그래밍을 가지고 있습니다. 파이썬 또한 중요한 함수형 프로그래밍 라이브러리를 가지고 있지만 이러한 것들은 쓰레드 지원에 독립적입니다.(파이썬이 진짜 병렬프로그래밍을 지원할 수 없기 때문에 코드체계화를 위한 것입니다.)

    Functional programming is often promoted first as a way to do concurrency. However, I've found it to be more fundamentally useful as a way to decompose programming problems. Indeed, C++ has had functional programming virtually from inception, in the form of the STL, without built-in support for concurrency. Python also has significant functional programming libraries but these are independent of its thread support (which, since Python cannot support true parallelism, is primarily for code organization).


    스칼라는 가장 좋은 2개의 세계를 가지고 있습니다: 실제 멀티프로세서 병렬화와 강력한 함수형 프로그래밍 모델이 그것입니다. 하지만 적절치 않다면 함수형으로 프로그래밍하도록 강제하지는 않습니다.

    Scala has the best of both worlds: true multiprocessor parallelism and a powerful functional programming model -- but one that does not force you to program functionally if it's not appropriate.


    제 생각에 함수형 프로그래밍 스타일에 접근할 때는 천천히 신사적으로 접근하는 것이 중요합니다. 많이 힘들다면 유저그룹에 참여할 수 있습니다. 사실 함수형 프로그래밍을 배웠을 때 가장 큰 이익의 하나는 문제를 증명할 수 있는 단계로 작게 나누는 훈련이 된다는 것입니다. 그리고 가능할 때마다 이러한 각 단계를 위해 이미 존재하는 코드(그리고 증명된)를 사용합니다. 이것은 비함수형 코드를 더 좋게 만들뿐만 아니라 함수형 프로그래밍이 데이터 변환에 초첨을 맞추기 때문에 작성한 모든 것이 더 테스트하기 좋도록 만듭니다. (그러므로 각 변환후에 테스트할 것을 가지게 됩니다.)

    When approaching a functional style of programming, I think it's important to go slow and be gentle with yourself. If you push too hard you can get caught up in knots. In fact, I think one of the great benefits of learning functional programming is that it disciplines you to break a problem into small, provable steps -- and to use existing (and proven) code for each of those steps whenever possible. This not only makes your non-functional code better, but it also tends to make everything you write more testable, since functional programming focuses on transforming data (thus, after each transformation, you have something else to test).


    함수형 프로그래밍의 많은 부분은 컬렉션에서 오퍼레이션을 수행하는 것입니다. 예를 들어 Vector 데이터를 가지고 있습니다:

    Much of functional programming involves performing operations on collections. If, for example, we have a Vector of data:


    val v = Vector(1.1, 2.2, 3.3, 4.4)


    for 루프를 사용해서 이것을 출력할 수 있습니다:

    You can certainly print this using a for loop:


    for(n <- v) {

      println(n)

    }


    왼쪽 화살표는  "in"이라고 읽을 수 있습니다. 여기서 n은 v의 각 값이 됩니다. 이 문법은 C++와 Java에서처럼 각 세부사항을 갖는 명확한 단계입니다. (Scala가 n을 위한 모든 생성과 타입추론을 합니다.) 하지만 함수형 프로그래밍에서는 순회 구조를 합쳐서 추출합니다. Scala의 컬렉션과 이터레이션은 이를 위한 많은 오퍼레이션들을 제공합니다. 가장 간단한 방법 중 하나인 foreach는 컬렉션에서 각 엘리먼트상에서 오퍼레이션을 수행합니다. 그래서 위의 코드는 다음과 같이 됩니다:


    v.foreach(println)


    이는 실제로 여러가지 숏컷을 제공합니다. 그리고 함수형 프로그래밍의 이점을 최대한 취하기 위해서 우선적으로 익명함수에 대해서 이해해야 합니다. 익명함수는 이름이 없는 함수이고 여기 기본적인 형식이 있습니다:

    This actually uses several shortcuts, and to take full advantage of functional programming you first need to understand the anonymous function -- a function without a name. Here's the basic form:


    ( function parameters ) => function body


    =>는 "rocket"이라고 읽으며 "좌측에 있는 파라미터를 우측에 있는 코드에 적용하라"는 의미입니다. 익명함수는 더 커질수도 있는데 여러절로 작성하였다면 바디를 중괄호안에 넣으면 됩니다.

    The => is often pronounced "rocket," and it means, "Take the parameters on the left and apply them in the code on the right." An anonymous function can be large; if you have multiple lines, just put the body inside curly braces.


    익명함수의 간단한 예제가 있습니다:

    Here's a simple example of an anonymous function:


    (x:Int, y:Double) => x * y


    앞의 foreach 호출은 명확하게 다음처럼 될 수 있습니다.

    The previous foreach call is, stated explicitly:


    v.foreach((n:Double) => println(n))


    보통 아규먼트상에서 타입추론을 하는 것은 Scala를 믿으면 됩니다. 이 경우에 스칼라는 v가 Double를 담고 있다는 것을 알 수 있으므로 n이 Double라는 것을 추론 할 수 있습니다.

    Usually, you can rely on Scala to do type inference on the argument -- in this case Scala can see that v contains Double so it can infer than n is a Double:


    v.foreach((n) => println(n))


    아규먼트가 하나뿐이라면 괄호를 생략할 수 있습니다.

    If you only have a single argument, you can omit the parentheses:


    v.foreach(n => println(n))


    하나의 아규먼트를 가지고 있다면 파라미터 리스트를 합칠 수 있고 익명함수 바디에서 언더스코어를 사용할 수 있습니다:

    When you have a single argument, you can leave out the parameter list altogether and use an underscore in the anonymous function body:


    v.foreach(println(_))


    마지막으로 함수바디가 파라미터 한개를 가지는 단일함수를 호출하는 것 뿐이라면 파라미터 리스트를 제거할 수 있습니다:

    And finally, if the function body is just a call to a single function that takes one parameter, you can eliminate the parameter list, which brings us back to:


    v.foreach(println)


    함수형 프로그래밍에서는 이렇게 가능한 옵션과 밀도로 쉽고 명확하게 만들수 있기 때문에 사람들이 너무 복잡해서 언어를 거부하지 않도록 코드를 작성할 수 있습니다.

    With all these options and the density possible in functional programming, it's easy to succumb to fits of cleverness and end up writing obtuse code that will cause people to reject the language as too complex. But with some effort and focus on readability this doesn't need to happen.


    foreach는 사이드 이펙트때문에 아무것도 리턴하지 않습니다. 더 일반적인 함수형 프로그래밍에서 오퍼레이션을 수행하고(보통 컬렉션에서) 결과를 리턴한 다음 결과상에서 오퍼레이션을 수행하고 다른 것을 리턴합니다. 가장 유용한 함수형 기능 중 하나는 map입니다. 이 이름은 별로 안좋은데 왜냐하면 Map 데이터구조와 혼동하기 쉽기 때문입니다. map은 foreach처럼 순차적으로 각 엘리먼트위에서 오퍼레이션을 수행하지만 결과에서 새로운 순서를 생성해서 리턴합니다. 예를 들어:

    foreach relies on side effects and doesn't return anything. In more typical functional programming you'll perform operations (usually on a collection) and return the result, then perform operations on that result and return something else, etc. One of the most useful functional tools is map, rather unfortunately named because it's easy to confuse with the Map data structure. map performs an operation on each element in a sequence, just like foreach, but map creates and returns a new sequence from the result. For example:


    v.map(n => n * 2)


    v에서 각 엘리먼트가 2배가 되어 만들어진 결과를 리턴합니다:

    multiplies each element in v by 2 and returns the result, producing:


    Vector(2.2, 4.4, 6.6, 8.8)


    또다시 숏컷을 사용해서 코드를 줄일 수 있습니다:

    Again, using shortcuts we can reduce the call to:


    v.map(_ * 2)


    다음처럼 파라미터 없이 호출될수 있는 간단한 오퍼레이션이 많이 있습니다:

    There are a number of operations that are simple enough to be called without parameters, such as:


    v.reverse

    v.sum

    v.sorted

    v.min

    v.max

    v.size

    v.isEmpty


    reverse와 sorted같은 오퍼레이션은 새로운 Vector을 리턴하고 원래의 Vector는 건드리지 않습니다.

    Operations like reverse and sorted return a new Vector and leave the original untouched.


    오퍼레이션들이 함께 체인되는 것은 일반적입니다. 예를 들어 순열(permutations)은 v의 다른 모든순열을 선택하는 이터레이터를 만듭니다. 이것들을 표현하기 위해서 foreach에 이터레이터에 전달합니다:

    It's common to see operations chained together. For example, permutations produces an iterator that selects all the different permutations of v. To display these, we pass the iterator to foreach:


    v.permutations.foreach(println)


    또다른 유용한 함수는 zip입니다. zip은 지퍼처럼 2개의 시퀀스를 가지고 각 인접한 엘리먼트를 하나로 합칩니다:

    Another helpful function is zip, which takes two sequences and puts each adjacent element together, like a zipper. This:


    Vector(1,2,3).zip(Vector(4,5,6))


    위를 실행하면 다음의 결과가 됩니다.

    produces:


    Vector((1,4), (2,5), (3,6))


    (파이썬에서처럼 Vector내에서 괄호로 묶인 것은 튜플(tuple)입니다.)

    (Yes, the parenthesized groups within the Vector are tuples, just like in Python).


    더 간단하게 만들 수 있는데 v의 엘리먼트와 v의 엘리먼트를 2배수한 값을 하나로 합칩니다:

    We can get fancy, and zip the elements of v together with those elements multiplied by 2:


    v.zip(v.map(_ * 2))


    위 코드는 아래의 결과를 생성합니다:

    which produces:


    Vector((1.1,2.2), (2.2,4.4), (3.3,6.6), (4.4,8.8))


    익명함수가 편리하고 일반적으로 사용되지만 함수형프로그래밍을 하는 본질적인 이유는 아니라는 것을 알아야 합니다. 익명함수가 코드를 너무 복잡하게 만든다면 언제든지 이름이 있는 함수를 정의해서 전달할 수 있습니다. 예를 들어:

    It's important to know that anonymous functions are a convenience, and very commonly used, but they are not essential for doing functional programming. If anonymous functions are making your code too complicated, you can always define a named function and pass that. For example:


    def timesTwo(d: Double) = d * 2


    (여기서 또 하나의 Scala 숏컷을 사용했습니다: 함수의 바디를 한줄로 작성할 수 있다면 중괄호는 필요없습니다.) 이것은 익명함수 대신 사용할 될 수 있습니다:

    (This uses another Scala shortcut: if the function body fits on one line, you don't need curly braces). This can be used instead of the anonymous function:


    v.zip(v.map(timesTwo))


    앞에서 for루프를 사용했던 코드와 같은 효과를 만들어 냅니다. 함수형 프로그래밍의 가장 좋은 점은 일반적인 오류들을 포함하고 있는 다루기 어려운 코드를 다룰 수 있다는 것입니다. 신뢰할 수 있는 함수형 코드블럭을 사용할 수 있고 더 빠르게 안정적인 코드를 작성할 수 있습니다. 함수형 코드는 확실히 쉽게 읽기 어려워질 수 있지만 약간의 노력으로도 명확하게 유지할 수 있습니다.

    You know you could produce the same effect as the code in this section using for loops. One of the biggest benefits of functional programming is that it takes care of the fiddly code -- the very code that seems to involve the kind of common errors that easily escape our notice. You're able to use the functional pieces as reliable building blocks, and create robust code more quickly. It certainly is easy for functional code to rapidly devolve into unreadability, but with some effort you can keep it clear.


    내가 함수형 프로그래밍을 해서 가장 좋았던 점은 그것이 만들어내는 정신적인 훈련입니다. 문제를 작고 테스트할 수 있으면서도 뚜렷하게 분석할 수 있게 나누는 법을 배우게 되었습니다. 때문에 이것은 시간을 들일만한 연습입니다.

    For me, one of the best things about functional programming is the mental discipline that it produces. I find it helps me learn to break problems down into small, testable pieces, and clarifies my analysis. For that reason alone, it is a worthwhile practice.


    패턴 매칭

    Pattern Matching


    프로그래머들이 얼마나 오랫동안 어셈블리 언어구조에서 작업을 했는가를 생각해 보면 놀라운 일입니다. switch문은 훌륭한 예제입니다. 진지하게 완전한 값기반이 되었는가? 실제로 도움이 되는 노력이 얼마나 있는가? 사람들은 switch에서 문자열을 사용하는 것 같은 간단한 것을 원하지만 언어 디자이너들은 보통 "안된다"는 답변을 한다. 

    It's amazing how long programmers have put up with stone-age (or more appropriately, assembly-age) language constructs. The switch statement is an excellent example. Seriously, jumping around based on an integral value? How much effort does that really save me? People have begged for things as simple as switching on strings, but this is usually met with "no" from the language designers.


    Scala는 어떤 것이든 선택할 수 있다는 것을 제외하고는 switch문과 유사해 보입니다. 명확성은 커지고 코드는 훨씬 줄어듭니다:

    Scala leapfrogs all that with the match statement, that looks much like a switch statement except that it can select on just about anything. The clarity and code savings is huge:


    // PatternMatching.scala (Run as script: scala PatternMatching.scala)


    trait Color

    case class Red(saturation: Int) extends Color

    case class Green(saturation: Int) extends Color

    case class Blue(saturation: Int) extends Color


    def matcher(arg:Any): String = arg match {

      case "Chowder" => "Make with clams"

      case x: Int => "An Int with value " + x

      case Red(100) => "Red sat 100"

      case Green(s) => "Green sat " + s

      case c: Color => "Some Color: " + c

      case w: Any => "Whatever: " + w

      case _ => "Default, but Any captures all"

    }


    val v = Vector(1, "Chowder", Red(100), Green(50), Blue(0), 3.14)

    v.foreach(x => println(matcher(x)))


    case클래스는 앞에서 본 것처럼 패턴 매처가 분석할 수 있기 때문에 특히 유용합니다.

    A case class is especially useful because the pattern matcher can decompose it, as you'll see.


    Java에서 primitive타입이 될 수 있는 것들을 포함한 모든 오브젝트는 루트 클래스가 될수 있습니다. matcher()는 Any를 받기 때문에 전달하는 어떤 타입도 다룰수 있습니다.

    Any is the root class of all objects including what would be "primitive" types in Java. Since matcher() takes an Any we can be confident that it will handle any type that we pass in.


    보통 =기호 우측에 전체 함수 바디를 감싸는 중괄호가 있습니다. 이 경우에 함수바디는 하나의 문장이기 때문에 숏컷을 사용해서 중괄호를 생략할 수 있습니다.

    Ordinarily you'd see an opening curly brace right after the = sign, to surround the entire function body in curly braces. In this case, the function body is a single statement so I can take a shortcut and leave off the outer braces.


    패턴매칭문은 매칭하기를 원하는 오브젝트로 시작합니다.(이것은 튜플이 될 수 있습니다.) match 키워드와 순차적인 case문으로 이루어진 바디가 있습니다. 각 case문은 매치할 패턴으로 시작하고 매치되었을 때 실행될 코드들로 되어 있습니다. 각 case문의 마지막 라인은 리턴값을 생성합니다.

    A pattern-matching statement starts with the object you want to match against (this can be a tuple), the match keyword and a body consisting of a sequence of case statements. Each case begins with the match pattern, then a rocket and one or more lines of code which execute upon matching. The last line in each case produces a return value.


    매치표현식은 여러가지 형식을 가질 수 있지만 여기서는 몇가지만 보여주었습니다. 첫번째로는 간단한 문자열 매치를 보았습니다; 하지만 scala는 세련된 정규표현식 문법을 가지고 있고 매치표현식에 변수로 선택하는 정규표현식을 사용할 수 있습니다. case x: Int에서처럼 변수로 매치문의 결과를 받을 수 있습니다. case 클래스는 Red(100)에서처럼 정확히 매치를 생성하거나 Green(s)에서처럼 생성자 아규먼트를 선택할 수도 있다. c: Color처럼 trait를 매치할 수도 있다.

    Match expressions can take many forms, only a few of which are shown here. First, you see a simple string match; however Scala has sophisticated regular expression syntax and you can use regular expressions as match expressions, including picking out the pieces into variables. You can capture the result of a match into a variable as in case x: Int. Case classes can produce an exact match as in Red(100) or you can pick out the constructor arguments as in Green(s). You can also match against traits, as in c: Color.


    그 외 모든 것에 매치하고 싶다면 2가지 선택이 있습니다. case w: Any처럼 변수를 잡기 위해서 Any를 매치할 수 있습니다. 값이 무엇인가에 신경쓰지 않는다면 그냥 case _ 라고 작성할 수 있습니다.

    You have two choices if you want to catch everything else. To capture into a variable, you can match Any, as in case w: Any. If you don't care what the value is, you can just say case _.


    각 case 바디끝에 "break"문은 필요없습니다.

    Note that no "break" statement is necessary at the end of each case body.


    액터를 사용한 동시성

    Concurrency with Actors


    프로그래밍에서 나를 멀어지게 하는 것 중 대부분은 무엇인지는 알아냈지만 다른 것으로 설득력있게 표현할 수 없는 것들입니다. 이러한 것들은 컴퓨터과학자들이 증명해야 하는 것들입니다. 다음처럼:


    - 프로그램 복잡도의 어떤 레벨을 뛰어 넘어 반드시 가비지 컬렉터를 가져야 합니다. 객체가 하나의 컬렉션이상에 소속될 수 있는 어떤 프로그램처럼 간단하게 될 수 있습니다. 하지만 어떤 면에서는 직접 메모리를 관리하는 것이 불가능하게 된다고 믿습니다.(C++0X가 지금은 가비지 컬렉션을 후킹했다고 하더라도 C++ 사람들은 이것을 갖지 않았습니다.)

    - Beyond a certain level of program complexity, you must have a garbage collector. This could be as simple as any program where objects can belong to more than one collection, but at some point I believe it becomes impossible to manage memory yourself. (C++ people didn't buy this one, although C++0X has hooks now for garbage collection).


    - 체크드 익셉션은 실패한 실험입니다. 작은 프로그램에서는 좋은 아이디어처럼 보였지만 확장이 어렵습니다.

    - Checked exceptions are a failed experiment. For small programs they seem like a good idea, but they don't scale up well.


    - 공유된 메모리(Shared-memory) 동시성은 옳은 방법을 가지는 것 자체가 불가능합니다. 이론적으로 세계에서 가장 똑똑한 개발자들은 모든 경쟁상태를 충분히 오랫동안 추적하면서 고치는 두더지잡기 게임을 할 수 있지만 당신이 해야하는 모든 것은 프로그램을 프로그램을 약간 고치는 것이고 모든 것은 다시 돌아옵니다. 공유된 메모리는 동시성을 위해서는 잘못된 모델입니다.

    - Shared-memory concurrency is impossible to get right. In theory the smartest programmer in the world could play whack-a-mole long enough to chase down and patch all the race conditions. But then, all you have to do is change the program a little and everything comes back. Shared-memory is just the wrong model for concurrency.


    이 모든 것은 확장성 이슈라는 것을 알아야 합니다. 프로그램이 더 커지고 복잡해지는 것에서 떨어져서 작게 시작하는 것입니다. 왜냐하면 데모 예제는 작고 명백하기 때문에 이것을 논의하는 것이 왜 어려운가 하는 것입니다.

    Note that all these are issues of scale -- things that work in the small start falling apart as programs get bigger or more complex. That's probably why they're hard to argue about, because demonstration examples can be small and obvious.


    잘못된 사람들과 논의하는 것을 멈추었습니다. 오히려 옳은 사람들은 그것에 대해서 논의하지 않습니다. 그들은 문제를 해결하고 문제가 동시성이 되었을 때의 정답은 엉망이 되지 않게 하는 것입니다: 당신은 안전한 지역내에 있고 메시지는 안전하게 전달될 것입니다. 어떤 것이 락이 걸리는지(로우레벨에 대한 것은 아닙니다.)에 대해서 생각하지 않아도 됩니다; 자신의 쓰레드에서 실행되는 약간 안전한 지역내에서 유지됩니다.

    It turns out I was arguing with the wrong people. Or rather, the right people were not arguing about it, they were off fixing the problems. When it comes to concurrency, the right answer is one that you can't screw up: you live behind a safe wall, and messages get safely passed back and forth over the wall. You don't have to think about whether something is going to lock up (not on a low level, anyway); you live in your little walled garden which happens to run with its own thread.


    이것에 대한 객체적인 접근의 대부분은 actor 입니다. 액터는 종종 "mailbox"로 참조되는 들어오는 메시지 큐를 가지고 있는 객체입니다. 당신의 보호된 기능 밖의 누군가가 당신에게 무언가를 하기를 원할때 mailbox에서 안전하게 나타나는 메시지를 보냅니다. 그리고 이 메세지를 어떻게 다룰지를 결정합니다. 메일박스를 통해서 다른 액터에게 메시지를 보낼 수 있습니다. 모든 것을 안전한 지역안에 유지하고 있고 오직 메시지로 통신한다면 당신은 안전합니다.

    The most object-ish approach to this that I've see is actors. An actor is an object that has an incoming message queue, often referred to as a "mailbox." When someone outside your walled garden wants you to do something, they send you a message that safely appears in your mailbox, and you decide how to handle that message. You can send messages to other actors through their mailboxes. As long as you keep everything within your walls and only communicate through messages, you're safe.


    액터를 생성하려면 Actor클래스를 상속받고 mailbox 메시지를 다루기 위해서 호출되는 act()메서드를 정의합니다. 여기 제가 생각할 수 있는 가장 평범한 예제가 있습니다:

    To create an actor, you inherit from the Actor class and define an act() method, which is called to handle mailbox messages. Here's the most trivial example I could think of:


    // Bunnies.scala (Run as script: scala Bunnies.scala)

    case object Hop

    case object Stop


    case class Bunny(id: Int) extends scala.actors.Actor {

      this ! Hop // Constructor code

      start()    // ditto

      def act() {

        loop {

          react {

            case Hop =>

              print(this + " ")

              this ! Hop

              Thread.sleep(500)

            case Stop =>

              println("Stopping " + this)

              exit()

          }

        }

      }

    }


    val bunnies = Range(0,10).map(new Bunny(_))

    println("Press RETURN to quit")

    readLine

    bunnies.foreach(_ ! Stop)


    act()메서드는 언어에 내장되어있지 않더라도 자동적으로 매치문이 됩니다. 스칼라는 이 방법으로 동작하는 Actor라이브러리를 만들어서 사용합니다. 매치문이기 때문에  case객체는 메시지에서 아주 잘 동작합니다.(어떤 매치문에서라도 가상적으로 어떤 것도 매치할 수 있습니다.) case 객체는 자동적으로 싱글톤 객체를 생성하는 것 외에는 case클래스와 유사합니다.

    The act() method is automatically a match statement, although this is not built into the language -- Scala magic was used to make the Actor library work this way. Because of the match statement, case objects work especially well as messages (although, as with any match statement, you can match on virtually anything) -- a case object is just like a case class except that defining one automatically creates a singleton object.


    loop{ react { 구조는 처음에는 약간 이상해 보입니다; 이것은 스칼라 액터가 진화한 결과물입니다. 초기디자인에서는 메일박스 메시지를 위한 매치문을 열기 위해서 loop만을 가졌습니다. 하지만 나중에 쓰레드에 의해서 제공된 동시성이 협력하는 멀티태스킹과 합쳐질수 있도록 결정되었습니다. 그 점에서 제어하는 싱글쓰레드는 주위의(협력적으로) 태스크들에 전달됩니다. 각 태스크는 무언가를 하고 그 다음에 명백하게 제어를 포기해서 다은 태스크에 전달됩니다. 협력적인 멀티태스킹의 이점은 가상적으로 스택공간이나 컨텍스트 스위칭 시간을 요구하지 않는다는 것이고 그래서 종종 100만개의 태스크까지 확장할 수 있습니다. 이렇게 쓰레드의 동시성을 합침으로써 협력적인 태스크의 속도와 확장성이라는 2가지 최상의 것을 가질 수 있습니다: 이것들은 또한 이용가능한 많은 프로세서로 분산됩니다. 이것들은 모두 투명하게 됩니다. loop{ react{ 구조는 기본적인 선택이 될것이고 어떤 비용도 들지 않습니다. 그들이 스케치하면서 액터를 만들었다고 짐작합니다. 이 구조는 아마도  그냥 loop{로 간단화 될 것입니다.

    The loop{ react{ construct looks a little strange at first; this is an artifact of the evolution of Scala actors. In the initial design, you only had a loop to open the match statement for mailbox messages. But later, in an act of brilliance, it was determined that the concurrency provided by threads could be combined with cooperative multitasking, wherein a single thread of control is passed around -- cooperatively -- among tasks. Each task does something and then explicitly gives up control, which is then passed to the next task. The benefit of cooperative multitasking is that it requires virtually no stack space or context switching time and thus it can scale up -- often to millions of tasks. By combining this with threaded concurrency, you get the best of both worlds: The speed and scalability of cooperative tasks, which are also distributed across as many processors as are available. This all comes transparently. The loop{ react{ construct should be your default choice, and doesn't cost anything. I suspect if they were creating actors from scratch now, this construct would probably have been simplified into just loop{.


    Bunny클래스의 시작부분에 있는 2개의 라인을 보십시오. 스칼라에서 객체 초기화 코드를 특별한 메서드에 넣을 필요가 없습니다. 클래스의 바디 어디에나 둘 수 있습니다. 첫 라인은 메시지를 보내는 Actor 오퍼레이터 !를 사용합니다. 그리고 이 경우에 작업하기 위해서 객체는 메세지를 자기자신에게 보냅니다. 그 다음 start()를 호출해서 액터의 메세지 루프를 시작합니다. 액터가 Hop 메세지를 받았을 때 그 자신을 출력하고 자신을 다른 Hop메시지에 보낸 후 0.5초동안 멈춥니다. Stop 메시지를 받았을때 Actor.exit()를 호출해서 이벤트 루프를 멈춥니다.

    Note the two "naked" lines of code at the beginning of class Bunny. In Scala, you don't have to put object initialization code inside a special method, and you can put it anywhere inside the body of the class. The first line uses the Actor operator ! for sending messages, and in this case the object sends a message to itself, to get things going. Then it calls start() to begin the actor's message loop. When the actor receives a Hop message, it prints itself, sends itself another Hop message, then sleeps for half a second. When it gets a Stop message it calls Actor.exit() to stop the event loop.


    Bunny 객체를 생성하기 위해서 Bunny생성자를 호출에 매핑되는 0부터 9까지의 순서를 만들기 위해서 Range()를 사용했습니다. readLine은 캐리지리턴을 사용자가 누르기를 기다리리다가 눌러지면 Stop메시지가 각 Bunny에 전달됩니다.

    To create all the Bunny objects I use Range() to create a sequence from 0 through 9, which is mapped onto calls to Bunny constructors. readLine waits for the user to press a carriage return, at which point a Stop message is sent to each Bunny.


    Scala 2.9는 foreach, map같은 오퍼레이션이 멀티프로세스를 쉽게 사용하는 강력한 방법인 병렬컬렉션을 포함하고 있습니다. 비용이 큰 함수 처리인 toBeProcessed를 호출하는 데이터객체의 컬렉션을 가지고 있다고 가정해 보겠습니다. 자동적으로 병렬로 프로세싱하기 위해서 단지 .par를 더하면 됩니다.

    Scala 2.9 includes parallel collections, a powerful way to easily use multiple processors for bulk operations like foreach, map, etc. Suppose you have a collection of data objects called toBeProcessed and an expensive function process. To automatically parallelize the processing, you just add a .par:


    val result = toBeProcessed.par.map(obj => process(obj))


    병렬로 프로세싱될 수 있는 객체를 가지고 있다는 것을 알고 있다면 이 구조는 거의 노력이 필요없습니다. 이번 Scala Days 2010 비디오에서 병렬 컬렉션에 대해서 더 찾아볼 수 있습니다.

    If you know that you have objects that can be processed in parallel, this construct makes it effortless. You can find out more about parallel collections in this Scala Days 2010 video.


    더 강력한 것은 akka 라이브러리입니다. 이것은 다른 것들 가운데 동시성 시스템을 만들고 투명하게 원격적입니다.

    Even more powerful is the akka library, which builds concurrent systems that are, among other things, transparently remoteable.


    스칼라는 동시성 프로그래밍을 위한 내가 본 가장 좋은 솔루션입니다. 그리고 점점 더 좋아지고 있습니다.

    Scala is the best solution for concurrent programming that I've seen, and it keeps getting better.


    하지만 스칼라는 너무 복잡합니다!

    But Scala is so Complex!


    스칼라는 좋은 이유였지만 복잡해져버린 잘못된 아이디어를 경험했습니다. 많은 얼리어댑터들은 그것들이 얼마나 명확한지 보여주기를 원하는 언어 열광자들이었습니다. 이것은 오직 초심자들에게만 혼란스러운 것입니다. 하지만 앞의 코드들에서 본 것처럼 스칼라를 배우는 것은 자바를 배우는 것보다 훨씬 쉬워질 것입니다. 단순히 "Hello, World!" 작성하는데 필수적인 자바의 형식같은 건 없습니다. 스칼라에서는 다음처럼 한줄로 작성할 수 있습니다:

    Scala does suffer from the mistaken idea that it's complicated, and for good reason. Many early adopters have been language enthusiasts who love to show how clever they are, and this only confuses beginners. But you can see from the code above that learning Scala should be a lot easier than learning Java! There's none of the horrible Java ceremony necessary just to write "Hello, world!" -- in Scala you can actually create a one-line script that says:


    println("Hello, world!")


    또는 스칼라의 익터렉티브 인터프리터를 통해서 쉽게 언어를 실행해 볼 수 있습니다.

    Or you can run it in Scala's interactive interpreter, which allows you to easily experiment with the language.


    파일을 열고 내용을 처리한다고 가정해보겠습니다.(자바에서 아주 많은 형식을 가지고 있는 것입니다.):

    Or consider opening a file and processing the contents (something that's also very high-ceremony in Java):


    val fileLines = io.Source.fromFile("Colors.scala").getLines.toList

    fileLines.foreach(println)


    (이 경우에 "프로세싱"은 단순히 각 라인을 출력하는 것입니다.) 파일을 열고 모든 라인을 읽는데 필요한 코드의 간결함은 언어의 모든 파워가 합쳐진 것입니다. 이것은 스칼라가 스크립팅 문제를 해결하는데 유용하다는 것을 의미합니다.(또한 스칼라는 XML을 위해서 강력한 네이티브 지원을 가지고 있습니다.)

    (The "processing" in this case is just printing each line). The simplicity of the code required to open a file and read all the lines, combined with the power of the language, suggests that Scala can be very useful for solving scripting problems (also Scala has strong native support for XML).


    단어갯수 세기 프로그램을 만들기 위해서 약간 수정해 보겠습니다:

    We can make some small modifications to create a word-count program:


    for(file <- args) {

      print(file + ": ")

      val contents = io.Source.fromFile(file).getLines.mkString

      println(contents.split(" ").length)

    }


    args는 모든 프로그램에서 이용가능하며 모든 커맨드라인 아규먼트를 담고 있기 때문에 이 프로그램은 한번에 하나씩 처리한다. 여기서는 단어를 공백으로 분리했지만 스칼라는 정규표현식도 가지고 있습니다.

    args is available to all programs and contains all the command-line arguments, so this program steps through them one at a time. Here, we split words at white space but Scala also has regular expressions.


    전문적인 기술적 해설이 필요한 복잡한 코드를 작성하는 것도 가능하지만 전적으로 초심자를 가르치는데는 이런 코드를 작성할 필요가 없습니다. 사실 제대로 배웠다면 스칼라가 다른 언어보다 훨씬 간단하고 일관된 언어라는 생각을 갖게 될 것입니다.

    It is possible to write complex code that requires expertise to unravel. But it's totally unnecessary to write such code when teaching beginners. Indeed, if taught right a person should come away from Scala thinking that it is a simpler, more consistent language than the alternatives.


    어떻게 배우는가

    How to Learn


    제가 본 모든 스칼라 튜토리얼은 대상을 자바프로그래머라는 가정을 하고 있었습니다. 앞에서 보여준 것처럼 자바를 배우기 위해서 강제적으로 해야했던 것보다 스칼라가 훨씬 덜 혼란스럽기 때문에 첫 언어로 배울 수 있음에도 자바를 배웠다는 것을 가정하는 것은 유감스러운 일입니다. 하지만 프로그래밍을 할 수 있다고 가정한다면 튜토리얼 작성자에게는 훨씬 쉬운 일입니다.

    All the Scala tutorials I encountered assume that you are a Java programmer. This is unfortunate because, as I've shown above, Scala could be taught as a first language in a much less-confusing way than we are forced to teach Java. But it does make it easier for writers to assume that you know how to program, and in Java.


    - 아주 유용한 시작점으로 Daniel Spiewak의 Scala for Java Refugees라는 제목의 블로그글들이 있습니다.

    - I found Daniel Spiewak's series of blog posts titled Scala for Java Refugees to be a very helpful starting point.


    - 다음으로 Martin Odersky, Lex Spoon, Bill Venners의 Programming in Scala 2판을 읽었습니다. odersky는 스칼라의 창시자이기 때문에 이 책은 믿을만 합니다.  독자가 자바프로그래머라고 가정하고 있으며 입문서는 아니지만 스칼라가 무엇을 할수 있는지에 대한 완전한 관점을 주는 책입니다.

    - Next, I read Programming in Scala, 2nd Edition by Martin Odersky, Lex Spoon, and Bill Venners. Odersky is the creator of the language so this is the authoritative book to read. It definitely assumes you're a Java programmer and it's not a particularly introductory book but it's worth pushing through to give you a fuller perspective on what Scala can do.


    - 스칼라 웹사이트는 아주 유용한 무료 튜토리얼들을 가지고 있습니다.

    - The Scala language website has a nice set of free tutorials which I've been finding very useful.


    - 또한 다른 책을 읽음으로써 새로운 관점을 보았습니다. 예를 들어 Venkat Subramaniam의 Programming Scala의 예제들이 있습니다. 비록 이 책은 너무 영리하게 작성되었다는 것이 명백하고(첫 챕터에서 너무 이해하기 어려운 예제를 주었고 그 다음에 걱정하지 말라고 말한 다음에 공부하고 이해하라고 말합니다.) 확실히 첫번째 책은 되지 말아야 하지만 도움이 되는 다른 관점을 발견했습니다.

    - I've also looked for different views by reading other books, for example Programming Scala by Venkat Subramaniam. Although this one definitely suffers from too much cleverness (in the first chapter he gives a very obtuse example, then tells you not to worry about it, then says to study and understand it) and should certainly not be your first book, I found the different perspective to be helpful.


    - 이러한 것들을 읽은 후에 5월에 Ann Arbor에서 열린 Bill Venners(Programming in Scala의 공동저자)와 Dick Wall(Java Posse의 리더)의 Stairway to Scala워크샵을 갔다왔습니다. 샌프랜시스코에서 8월 8~12에도 열립니다.; 더 찾아볼수 있고 여기서 등록할 수 있습니다: http://www.artima.com/shop/stairway_to_scala 이것은 입문클래스는 아니고 반드시 프로그래밍 경험이 있어야 합니다. 대부분 자바를 참조하기 때문에 자바를 할 줄 안다면 이상적입니다. 그리고 그전에 Programming in Scala를 읽기를 강력하게 추천하고 가능하다면 다른 책도 읽는다면 좋을 것입니다. 깊게 이해하지 못했다고 하더라도 먼저 당신의 뇌를 열어주어 더 편안하게 개념을 받아들수 있게 될 것입니다. 세미나 전에 공부하는 것은 아주 커다란 차이가 있습니다.

    - After reading those, I took the Stairway to Scala workshop by Bill Venners (coauthor of Programming in Scala) and Dick Wall (leader of the Java Posse) in Ann Arbor in May. There's one coming up August 8-12 in San Francisco; you can find out more and register here: http://www.artima.com/shop/stairway_to_scala. This is not an especially introductory class; you should have programming experience -- ideally in Java, because that's what they refer to most -- and I strongly recommend reading Programming in Scala beforehand, and other books if you can manage it -- even if you don't understand it in depth, exposing your brain early will allow some concepts to become more comfortable. It made a huge difference for me to do as much study as I did before the seminar.


    - Prgramming Summer Camp동안에 "Scala Campsite"에서 3개의 부스가 있습니다.

    - There are also three different "tents" at the "Scala Campsite" during the Programming Summer Camp.


    이 글에서 이야기한 것과 전혀 언급하지 않은 언어의 특징들이 있습니다. 여기서 보여준 것은 스칼라를 배우거나 사용하라고 하는 것일 수도 있고 선호하는 언어의로 돌아갈 수도 있습니다.

    There are language features that I have only touched on here, or not covered at all. What I've shown should either give you the urge to learn and use Scala, or it will have you running back to the safety of your favorite language.


    참조 사이트:

    https://blog.outsider.ne.kr/684?PageSpeed=noscript

    http://www.artima.com/weblogs/viewpost.jsp?thread=328540


Designed by Tistory.