브루스 테이트의 세븐 랭귀지
언어
- 논리 중심 프로그래밍 언어 : 프롤로그
- 객체지향 언어 : 루비,
스칼라
, 파이썬 - 함수형 언어 :
스칼라
, 얼랭, 클로저, 하스켈 - 프로토타입 언어 : Io, 자바스크리트, 루아
스칼라
: 복수 패러다임 언어
스칼라
스칼라 언어의 한쪽 끝이 자바라면, 다른 쪽의 끝은 하스켈이다.
자바와의 관련성
- 스칼라는 자바 가상 머신 위에서 동작한다. 따라서 스칼라는 이미 존재하는 코드다. 나란히 실행될 수 있다.
- 스칼라는 자바 라이브러리를 직접 사용할 수 있다. 따라서 개발자들은 이미 존재하는 프레임워크와 레거시 코드를 활용할 수 있다.
- 스칼라는 자바와 마찬가지로 정적 타이핑을 사용한다. 따라서 두 언어는 철학적 기반을 공유한다.
- 스칼라의 문법은 자바와 가깝기 때문에 개발자들이 쉽게 배울 수 있다.
- 스칼라는 객체지향과 함수 프로그래밍 패러다임을 모두 지원한다. 따라서 개발자들은 자신의 코드에 함수 프로그래밍 개념을 단계별로 조금씩 적용할 수 있다.
자바와의 차이점
- 스칼라는 가능한 모든 곳에서 변수의 자료형을 컴파일러가 유추한다.
- 스칼라는 자바 안에 중요한 함수 개념을 도입했다.
- 스칼라는 변수가 불변인지 아닌지 미리 결정하도록 강제한다.
스칼라 관련 최고의 베스트셀러 : Programming in Scala
함수 언어의 성격
- 함수 프로그램은 함수로 이루어져 있다.
- 함수는 항상 어떤 값을 리턴한다.
- 동일한 입력이 주어지면 함수는 언제나 동일한 결과를 리턴한다.
- 함수 프로그램은 상태를 변경하거나 데이터를 변경하는 것을 피한다. 하나의 값을 설정했으면, 그 값을 끝까지 유지한다.
트레이트
모든 객체지향 언어는 하나의 객체가 여러 개의 역할을 담당할 수 있어야 한다. 하나의 객체는 영원히 나열할 수 있는 나무를 품은 관목 숲과 같다. C++는 다중 상속을 이용하고, 자바는 인터페이스를 이용하고, 루비는 믹스인을 이용하고, 스칼라는 트레이트를 이용한다.
var
로 선언된 값은 변경이 가능하다. val
은 불변이다.
고계함수
- 고계함수는 다른 함수를 생산하거나 소비하는 함수를 의미한다.
- 더 엄밀하게 말하면 고계함수란 다른 함수를 입력 매개변수로 받아들이거나 다른 함수를 리턴하는 함수다.
핵심 강점
스칼라의 장점은 대부분 자바 환경과 잘 통합된다는 사실과 잘 설계된 기능을 중심으로 존재한다. 특히 액터, 패턴 매칭, XML의 통합은 매우 중요하며 훌륭하게 설계되어 있다.
동시성
스칼라가 동시성을 다루는 방식은 동시성 프로그래밍에서 이루어지고 있는 주요한 발전을 반영한다. 액터 모델과 스레드 풀은 환영할 만한 발전이며, 변경 가능한 상태를 배제한 상태에서 애플리케이션을 만들 수 있도록 한 부분은 엄청난 발전이다.
낡은 자바의 진환
스칼라 애플리케이션은 자바 라이브러리를 직접 사용할 수 있고, 필요하면 프록시 객체 코드를 생성함으로써 그렇게 할 수도 있다. 스칼라와 자바의 호환성interoperability은 탁월하다.
DSL
스칼라가 가진 유연한 문법과 연산자 오버로딩은 루비 스타일의 도메인 언어를 개발하는 데 적합하다.
루비
DSL(domain-specific language 도메인 언어)은 어떤 언어를 특정한 도메인용으로 가다듬을 수 있도록 해준다. 루비에서 가장 널리 알려진 예로, 액티브레코드 프레임워크는 클래스를 데이터베이스 테이블에 매핑하기 위해 도메인 언어를 사용한다.
- 루비는 객체를 단일하고 일관성 있는 방식으로 다루도록 해주는 순수한 객체지향 언어다.
- 루비는 환상적인 스크립트 언어다. 두 개의 애플리케이션을 서로 붙이는 접착제 코드를 작성하거나, 주식 시세나 책의 가격 등을 파악하기 위해서 부지런히 웹 페이지를 읽어때는 스파이더 코드를 작성하거나, 로컬 빌드 환경이나 자동화된 테스트 코드를 작성할 때 루비는 탁월한 선택이다.
nil
과 false
를 제외한 다른 모든 것은 true로 평가된다. C와 C++ 프로그램들은 0조차 true 라는 사실을 잘 기억하기 바란다.
Io
- Io는 루아나 자바스크립트처럼 프로토타입 언어인데, 그것은 모든 객체가 다른 객체의 클론이라는 사실을 의미한다.
- Io 에서는 클래스와 객체를 구별하기 위해 노력할 필요가 없다. 모든 것이 객체이며, 필요하면 그들을 복제할 수 있다. 이렇게 복제물을 양산하는 객체를
프로토타입
이라고 부른다.
인터프리터: http://iolanguage.com
정리
- 다른 객체를 복제함으로써 객체를 만든다.
- 객체는 슬롯의 컬렉션이다.
- 메시지를 보냄으로써 슬롯에 담긴 값을 받아볼 수 있다.
기초적인 규칙
- 모든 것이 객체다
- 모든 상호작용은 객체에 메시지를 보내는 방식으로 이루어진다.
- 클래스를 이용해서 인스턴스를 만들지 않는다. 프로토타입이라는 객체를 복제함으로써 만든다.
- 객체는 자신의 프로토타입을 기억한다.
- 객체는 슬롯을 갖는다.
- 슬롯은 객체를 담는다. 메서드 객체도 포함된다.
- 메시지는 슬롯에 담긴 값을 리턴하거나 그 안에 있는 메서드를 호출한다.
- 객체가 자신에게 전달된 메시지에 응답할 수 없다면, 자신의 프로토타입 메시지를 전송한다.
Io 장점
- 프로토타입 언어는 일반적으로 상당히 유연하다.
- Io의 메모리 사용량 footprint 은 적다
프롤로그
- 프롤로그는 선언형declarative 언어다.
- 사실과 추론inference을 프롤로그에게 던지고, 생각reasoning또 프롤로그가 하게 한다.
데이터를 구성하는 빌딩 블록
- 사실: 사실fact은 세계의 어떤 측면에 대한 기본적인 선언assertion이다. (베이브는 돼지다. 돼지는 진흙을 좋아 한다.)
- 규칙: 규칙rule은 해당 세계 안에 존재하는 사실에 대한 추론이다. (그 동물이 돼지라면 진흙을 좋아할 것이다.)
- 질의: 질의query는 세계에 대한 질문이다. (베이브는 진흙을 좋아하는가?)
프롤로그에서 첫글자가 소문자로 시작하면 그것은 루비의 심벌처럼 고정된 값은 의미하는 원자atom다. 만약 첫글자가 대문자나 밑줄이면 변수variable다. 변수 값은 변할 수 있다. 원자는 변하지 않는다.
얼랭
얼랭은 어려운 일을 쉽게 만들고, 동시에 쉬운 일을 어렵게 만든다. 클라우드 컴퓨팅과 관련해서 인기를 끌고 있는 데이터베이스 카우치디비와 심플디비를 구현하는 데 사용된 언어이기도 한다.
- 프로그램이 전적으로 함수로 구성되며, 객체는 어디에도 없다.
- 이러한 함수들은 대개 입력이 같으면 언제나 동일한 내용을 리턴한다.
- 이러한 함수들은 대개 부수효과가 없다. 즉, 프로그램의 상태를 변경하지 않는다.
- 변수에 값을 오직 한 차레만 할당할 수 있다.
함수 언어에서는 기호symbol가 다른 언어에서보다 중요하다. 기호는 가장 기초적인 데이터 요소이며 프로그래머가 원하는 어떤 내용이라도 나타낼 수 있다.
- 리스트 컴프리핸션은
[표현||클로즈1, 클로즈2, ..., 클로즈N]
형태를 갖는다. - 리스트 컴프리핸션은 임의의 수의 클로즈를 포함할 수 있다.
- 클로즈는 생성자generator나 필터를 가질 수 있다.
- 필터는 불리언 표현이나 불리언을 리턴하는 함수일 수 있다.
- 매칭 <- 리스트의 형태를 갖는 생성자는 왼쪽에 있는 패턴을 오른쪽에 있는 리스트의 요소에 매치한다.
핵심 강점
얼랭은 모든 며에서 동시성과 에러 방지에 대한 언어라고 볼 수 있다. 얼랭은 무엇보다도 안정성을 위해서 만들어진 언어다.
클로저
클로저는 JVM 위에서 동작하는 리스프 언어다. 혼란스럽고 강력한 리스프는 최초로 개발된 언어임과 동시에 가장 최근에 사용되는 언어이기도 하다.
많은 면에서 클로저는 사려 깊은 쿵푸 마스터, 언덕 위의 오라클, 혹은 신비로운 제다이 훈련교관이다.
모든 것은 리스프로부터
리스프라는 이름은 리스트 처리^Listt Processing^에서 따온 말이다.
- 리스프는 리스트를 위한 언어다. 함수 호출은 리스트의 첫 번째 인수를 함수로, 나머지를 인수로 사용한다.
- 리스프는 코드를 표현하기 위해 고유한 자료구조를 사용한다. 리스프를 사용하는 사람들은 이것을
코드로서의 데이터
^data as code^ 라고 부른다.
이 두 가지 아이디어를 결합하면, 메타프로그래밍에 적합한 언어를 얻게 된다.
리스트, 맵, 집합, 벡터
다른 함수 언어에서와 마찬가지로 리스트와 튜플 같은 자료구조가 핵심적인 기능을 담당한다.
클로저에서 가장 중요한 세 가지 구조를 꼽으면 리스트, 맵, 벡터다.
리스트
는 순서가 있는 요소들을 저장하는 컬렉션이다.백터
는 리스트와 마찬가지로 요소들을 순서를 고려해서 담는 컬렉션이다.집합
은 순서가 없는 요소들을 저장하는 컬렉션이다.맵
은 키-값 짝이다.
시퀀스
클로저 생태계에서 시퀀스는 다양한 컨테이너의 주위를, 구현되는 내용으로부터 독립된 방식으로 추상화해주는 기능이다. 시퀀스는 클로저의 컬렉션(집합, 맵, 백터 등), 문자열, 그리고 심지어 파일시스템 구조(스트림, 디렉토리 등)를 감싼다. 자바 컬렉션, 배열, 문자열 같은 자바 컨테이너를 위한 공통의 추상도 제공한다.
핵심 강점
좋은 리스프
프로그래밍 언어의 전문가이며 파워블로거인 팀 브레이는 '클러저를 위한 11개의 대제’에서 클로저를 좋은 리스프라고 불렀다. 사실 그는 클로저를 '역사상 최고의 리스프’라고 불렀다. 나는 클로저가 아주 좋은 리스프라는 의견에 동의한다.
- 대폭 줄어든 괄호: 클로저는 백터에 대괄호를 사용하고, 맵에 중괄호를 사용하고, 집합에 문자의 조합을 사용하는 등, 문법을 다소 수정함으로써 가독성을 향상시켰다.
- 생태계: 리스프의 변종들은 대개 하나의 언어를 위한 지원 및 라이브러리라는 막힌 길을 밟아나갔다. 역설적이게도 새로운 변종 하나가 등장하면 그러한 문제가 해결되었다. 클로저는 JVM 위에서 동작을 수행함으로써 엄청난 양의 라이브러리를 사용하는 자바 프로그래머와 동일한 수준의 혜택을 누릴 수 있게 해주었다.
- 제한: 읽기 매크로를 피하기 위해 클로저의 문법을 제한하는 방법을 채택함으로써 히키는 클로저의 기능을 실질적으로 제한했지만, 엉뚱한 변종이 등장해서 발전이 저해되는 상홛오 피할 수 있었다.
동시성
STM 은 너무나 새로운 개념이기 때문에 그것을 이용하는 프로그래머들에게 거추장스럽게 느껴지기도 하지만, 상태를 변경하는 동작이 적절하게 작성된 함수에 의해 수행되는지 여부를 자동으로 검출함으로써 프로그래머들이 동시성 문제로 고통받지 않아도 되게끔 만들었다.
자바와의 통합
클로저는 자바와 훌륭하게 통합된다. 하지만 클로저는 자바보다 JVM과의 통합이라는 측면에서 더 빛을 발한다.
게이른 평가
클로저는 매우 강력한 게으른 평가 기능을 포함한다. 게이른 평가는 문제를 단순화해준다.
코드로서의 데이터
프로그램은 리스트로 이루어진다. 리스프와 마찬가지로 데이터를 코드로 표현할 수 있다.
약점
- 전위 표기법: 코드를 리스트의 형태로 표현하는 것은 리스프 언어가 가지고 있는 가장 강력한 기능의 하나인데, 거기에는 전위 표기법이라는 비용도 수반된다.
- 가독성: 데이터를 코드로 표현하는 데 따르는 비용의 하나는 압도당할 정도로 많은 괄호다.
- 학습 과정의 어려움: 클로저는 기능이 풍부한 언어이며, 따라서 학습 과정이 쉽지 않다. 리스프가 제대로 사용되도록 하기 위해서는 극도로 뛰어난 재능과 경험을 가진 팀이 필요하다. 게으른 시퀀스, 함수 프로그래밍, 매크로 확장, 트랜잭션 메모리, 그 밖의 다른 정교한 기능들은 완전히 익힐 때까지 많은 시간을 요구하는 강력한 개념들이다.
- 제한된 리스프: 모든 타협에는 비용이 수반된다. JVM 위에서 동작하기로 결정했기 때문에 클로저는 꼬리 재귀 최적화를 제한적으로 밖에 지원하지 못한다.
- 접근성: 클로저는 개발자에게 엄청난 수준의 노력을 요구한다. 프로그래머의 두뇌를 압도할 정도로 많은 추사 도구와 개념이 포함되어 있다.