summaryrefslogtreecommitdiffhomepage
path: root/ko-kr
diff options
context:
space:
mode:
Diffstat (limited to 'ko-kr')
-rw-r--r--ko-kr/brainfuck-kr.html.markdown84
-rw-r--r--ko-kr/clojure-kr.html.markdown383
-rw-r--r--ko-kr/coffeescript-kr.html.markdown58
-rw-r--r--ko-kr/go-kr.html.markdown346
-rw-r--r--ko-kr/java-kr.html.markdown408
-rw-r--r--ko-kr/javascript-kr.html.markdown433
-rw-r--r--ko-kr/lua-kr.html.markdown422
-rw-r--r--ko-kr/php-kr.html.markdown662
-rw-r--r--ko-kr/python-kr.html.markdown484
-rw-r--r--ko-kr/racket-kr.html.markdown640
10 files changed, 3920 insertions, 0 deletions
diff --git a/ko-kr/brainfuck-kr.html.markdown b/ko-kr/brainfuck-kr.html.markdown
new file mode 100644
index 00000000..c2e4341f
--- /dev/null
+++ b/ko-kr/brainfuck-kr.html.markdown
@@ -0,0 +1,84 @@
+---
+language: brainfuck
+contributors:
+ - ["Prajit Ramachandran", "http://prajitr.github.io/"]
+ - ["Mathias Bynens", "http://mathiasbynens.be/"]
+translators:
+ - ["JongChan Choi", "http://0xABCDEF.com/"]
+ - ["Peter Lee", "http://peterjlee.com/"]
+lang: ko-kr
+---
+
+Brainfuck(문장을 시작하는 단어가 아닌이상 첫글자는 대문자를 사용하지 않습니다)은
+여덟가지 명령어만으로 튜링-완전한 최소주의 프로그래밍 언어입니다.
+
+```
+"><+-.,[]" 이외의 문자들은 무시됩니다. (쌍따옴표는 제외)
+
+브레인퍽은 30,000 칸 짜리의 0으로 초기화된 배열과,
+현재 칸을 가르키는 포인터로 표현됩니다.
+
+여덟가지의 명령어는 다음과 같습니다:
++ : 포인터가 가르키는 현재 칸의 값을 1 증가시킵니다.
+- : 포인터가 가르키는 현재 칸의 값을 1 감소시킵니다.
+> : 포인터가 다음 칸(오른쪽 칸)을 가르키도록 이동시킵니다.
+< : 포인터가 이전 칸(왼쪽 칸)을 가르키도록 이동시킵니다.
+. : 현재 칸의 값을 ASCII 문자로 출력합니다. (즉, 65 = 'A')
+, : 하나의 문자를 입력받고 그 값을 현재 칸에 대입합니다.
+[ : 현재 칸의 값이 0이면 짝이 맞는 ] 명령으로 넘어갑니다.
+ 0이 아니면 다음 명령어로 넘어갑니다.
+] : 현재 칸의 값이 0이면 다음 명령어로 넘어갑니다.
+ 0이 아니면 짝이 맞는 [ 명령으로 다시 돌아갑니다.
+
+[이랑 ]은 while 루프를 만들어냅니다. 무조건, 짝이 맞아야 합니다.
+
+몇가지 간단한 브레인퍽 프로그램을 보겠습니다.
+
+++++++ [ > ++++++++++ < - ] > +++++ .
+
+이 프로그램은 문자 'A'를 출력합니다. 처음에는, 반복할 횟수를 정하기 위한 값을
+만들기 위해 첫번째 칸의 값을 6으로 증가시킵니다. 그리고 루프로 들어가서([)
+두번째 칸으로 넘어갑니다. 루프 안에서는 두번째 칸의 값을 10 증가시키고,
+다시 첫번째 칸으로 넘어가서 값을 1 감소시킵니다. 이 루프는 여섯번 돕니다.
+(첫번째 칸의 값을 6번 감소시켜서 0이 될 때 까지는 ] 명령을 만날 때마다
+루프의 시작 지점으로 돌아갑니다)
+
+이 시점에서, 두번째 칸의 값은 60이고, 포인터는 값이 0인 첫번째 칸에 위치합니다.
+여기서 두번째 칸으로 넘어간 다음 값을 5 증가시키면 두번째 칸의 값이 65가 되고,
+65는 문자 'A'에 대응하는 아스키 코드이기 때문에, 두번째 칸의 값을 출력하면
+터미널에 'A'가 출력됩니다.
+
+, [ > + < - ] > .
+
+이 프로그램은 사용자로부터 문자 하나를 입력받아 첫번째 칸에 집어넣습니다.
+그리고 루프에 들어가서, 두번째 칸으로 넘어가 값을 한 번 증가시킨 다음,
+다시 첫번째 칸으로 넘어가서 값을 한 번 감소시킵니다.
+이는 첫번째 칸의 값이 0이 될 때까지 지속되며,
+두번째 칸은 첫번째 칸이 갖고있던 값을 가지게 됩니다.
+루프가 종료되면 포인터는 첫번째 칸을 가르키기 때문에 두번째 칸으로 넘어가고,
+해당 아스키 코드에 대응하는 문자를 출력합니다.
+
+또한 공백문자는 순전히 가독성을 위해서 작성되었다는 것을 기억하세요.
+다음과 같이 작성해도 똑같이 돌아갑니다:
+
+,[>+<-]>.
+
+한 번 돌려보고 아래의 프로그램이 실제로 무슨 일을 하는지 맞춰보세요:
+
+,>,< [ > [ >+ >+ << -] >> [- << + >>] <<< -] >>
+
+이 프로그램은 두 개의 숫자를 입력받은 뒤, 그 둘을 곱합니다.
+
+위 코드는 일단 두 번의 입력을 받고, 첫번째 칸의 값만큼 바깥 루프를 돕니다.
+그리고 루프 안에서 다시 두번째 칸의 값만큼 안쪽의 루프를 돕니다.
+그리고 그 루프에서는 세번째 칸의 값을 증가시키는데, 문제가 하나 있습니다:
+내부 루프가 한 번 끝나게 되면 두번째 칸의 값은 0이 됩니다.
+그럼 다시 바깥 루프를 돌 때에 안쪽의 루프를 돌지 않게 되는데, 이를 해결하려면
+네번째 칸의 값도 같이 증가시킨 다음, 그 값을 두번째 칸으로 옮기면 됩니다.
+그러면 세번째 칸에 곱셈의 결과가 남습니다.
+```
+
+여기까지 브레인퍽이었습니다. 참 쉽죠?
+재미삼아 브레인퍽 프로그램이나 다른 언어로 브레인퍽 인터프리터를 작성해보세요.
+인터프리터 구현은 간단한 편인데,
+사서 고생하는 것을 즐기는 편이라면 한 번 작성해보세요… 브레인퍽으로.
diff --git a/ko-kr/clojure-kr.html.markdown b/ko-kr/clojure-kr.html.markdown
new file mode 100644
index 00000000..1d9e53cd
--- /dev/null
+++ b/ko-kr/clojure-kr.html.markdown
@@ -0,0 +1,383 @@
+---
+language: clojure
+filename: learnclojure-kr.clj
+contributors:
+ - ["Adam Bard", "http://adambard.com/"]
+translators:
+ - ["netpyoung", "http://netpyoung.github.io/"]
+lang: ko-kr
+---
+
+Clojure는 Java 가상머신을 위해 개발된 Lisp 계통의 언어입니다
+이는 Common Lisp보다 순수 [함수형 프로그래밍](https://en.wikipedia.org/wiki/Functional_programming)을 더욱 강조했으며,
+상태를 있는 그대로 다루기 위해 다양한 [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) 을 지원하는 프로그램들을 갖췄습니다.
+
+이를 조합하여, 병행처리(concurrent processing)를 매우 단순하게 처리할 수 있으며,
+대게 자동으로 처리될 수 있도록 만들 수 있습니다.
+
+(Clojure 1.2 이상의 버전이 필요로 합니다.)
+
+
+```clojure
+; 주석은 세미콜론(;)으로 시작합니다.
+
+; Clojure는 "폼(forms)"으로 구성되었으며,
+; 폼은 괄호로 감싸져있으며, 공백으로 구분된 것들이 나열된 것입니다.
+;
+; clojure의 reader는 첫번째로 오는 것을
+; 함수 혹은 매크로를 호출하는 것, 그리고 나머지를 인자라고 가정합니다.
+
+; namespace를 지정하기 위해, 파일에서 우선적으로 호출해야될 것은 ns입니다.
+(ns learnclojure)
+
+; 간단한 예제들:
+
+; str 은 인자로 받은 것들을 하나의 문자열로 만들어줍니다.
+(str "Hello" " " "World") ; => "Hello World"
+
+; 직관적인 수학 함수들을 갖고 있습니다.
+(+ 1 1) ; => 2
+(- 2 1) ; => 1
+(* 1 2) ; => 2
+(/ 2 1) ; => 2
+
+; = 로 동일성을 판별할 수 있습니다.
+(= 1 1) ; => true
+(= 2 1) ; => false
+
+; 논리연산을 위한 not 역시 필요합니다.
+(not true) ; => false
+
+; 중첩된 폼(forms)은 기대한대로 동작합니다.
+(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
+
+; 타입
+;;;;;;;;;;;;;
+
+; Clojure는 부울(boolean), 문자열, 숫자를 위해 Java의 object 타입을 이용합니다.
+; `class` 를 이용하여 이를 확인할 수 있습니다.
+(class 1) ; 정수는 기본적으로 java.lang.Long입니다.
+(class 1.); 소수는 java.lang.Double입니다.
+(class ""); 문자열은 쌍따옴표로 감싸져 있으며, java.lang.String입니다.
+(class false) ; 부울값은 java.lang.Boolean입니다.
+(class nil); nil은 "null"값입니다.
+
+; 데이터 리스트 자체를 만들고자 한다면,
+; '를 이용하여 평가(evaluate)되지 않도록 막아야 합니다.
+'(+ 1 2) ; => (+ 1 2)
+; (quote (+ 1 2)) 를 줄여서 쓴것
+
+; quote 가 된 리스트를 평가할 수 도 있습니다.
+(eval '(+ 1 2)) ; => 3
+
+; 컬렉션(Collections) & 시퀀스(Sequences)
+;;;;;;;;;;;;;;;;;;;
+
+; 리스트(List)는 연결된(linked-list) 자료구조이며, 벡터(Vector)는 배열이 뒤로붙는(array-backed) 자료구조입니다.
+; 리스트와 벡터 모두 java 클래스입니다!
+(class [1 2 3]); => clojure.lang.PersistentVector
+(class '(1 2 3)); => clojure.lang.PersistentList
+
+; 간단하게 (1 2 3)로 리스트를 나타낼 수 있지만,
+; reader가 함수라고 여기지 못하게 quote(')를 해줘야 합니다.
+; 따라서, (list 1 2 3)는 '(1 2 3)와 같습니다.
+
+; "컬렉션"은 단순하게 데이터의 그룹입니다.
+; 리스트와 벡터 모두 컬렉션입니다:
+(coll? '(1 2 3)) ; => true
+(coll? [1 2 3]) ; => true
+
+; "시퀀스" (seq) 는 데이터 리스트를 추상적으로 기술한 것입니다.
+; 리스트는 시퀀스입니다.
+(seq? '(1 2 3)) ; => true
+(seq? [1 2 3]) ; => false
+
+; 시퀀스는 접근하고자 하는 항목만 제공해주면 됩니다.
+; 따라서, 시퀀스는 lazy 할 수 있습니다 -- 무한하게 늘어나는 것을 정의할 수 있습니다:
+(range 4) ; => (0 1 2 3)
+(range) ; => (0 1 2 3 4 ...) (an infinite series)
+(take 4 (range)) ; (0 1 2 3)
+
+; cons 를 이용하여 리스트나 벡터의 시작부에 항목을 추가할 수 있습니다.
+(cons 4 [1 2 3]) ; => (4 1 2 3)
+(cons 4 '(1 2 3)) ; => (4 1 2 3)
+
+; conj 는 컬렉션에 가장 효율적인 방식으로 항목을 추가합니다.
+; 리스트는 시작부분에 삽입하고, 벡터는 끝부분에 삽입합니다.
+(conj [1 2 3] 4) ; => [1 2 3 4]
+(conj '(1 2 3) 4) ; => (4 1 2 3)
+
+; concat 을 이용하여 리스트와 벡터를 서로 합칠 수 있습니다.
+(concat [1 2] '(3 4)) ; => (1 2 3 4)
+
+; filter, map 을 이용하여 컬렉션을 다룰 수 있습니다.
+(map inc [1 2 3]) ; => (2 3 4)
+(filter even? [1 2 3]) ; => (2)
+
+; reduce 를 이용하여 줄여나갈 수 있습니다.
+(reduce + [1 2 3 4])
+; = (+ (+ (+ 1 2) 3) 4)
+; => 10
+
+; reduce 는 초기 값을 인자로 취할 수 도 있습니다.
+(reduce conj [] '(3 2 1))
+; = (conj (conj (conj [] 3) 2) 1)
+; => [3 2 1]
+
+; 함수
+;;;;;;;;;;;;;;;;;;;;;
+
+; fn 을 이용하여 함수를 만들 수 있습니다 .
+; 함수는 항상 마지막 문장을 반환합니다.
+(fn [] "Hello World") ; => fn
+
+; (정의한 것을 호출하기 위해선, 괄호가 더 필요합니다.)
+((fn [] "Hello World")) ; => "Hello World"
+
+; def 를 이용하여 var 를 만들 수 있습니다.
+(def x 1)
+x ; => 1
+
+; var 에 함수를 할당시켜보겠습니다.
+(def hello-world (fn [] "Hello World"))
+(hello-world) ; => "Hello World"
+
+; defn 을 이용하여 짧게 쓸 수 도 있습니다.
+(defn hello-world [] "Hello World")
+
+; [] 는 함수의 인자 목록을 나타냅니다.
+(defn hello [name]
+ (str "Hello " name))
+(hello "Steve") ; => "Hello Steve"
+
+; 약자(shorthand)를 써서 함수를 만들 수 도 있습니다:
+(def hello2 #(str "Hello " %1))
+(hello2 "Fanny") ; => "Hello Fanny"
+
+; 함수가 다양한 인자를 받도록 정의할 수 도 있습니다.
+(defn hello3
+ ([] "Hello World")
+ ([name] (str "Hello " name)))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+
+; 함수는 여러 인자를 시퀀스로 취할 수 있습니다.
+(defn count-args [& args]
+ (str "You passed " (count args) " args: " args))
+(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+
+; 개별적으로 받는 것과, 시퀀스로 취하는 것을 같이 쓸 수 도 있습니다.
+(defn hello-count [name & args]
+ (str "Hello " name ", you passed " (count args) " extra args"))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, you passed 3 extra args"
+
+
+; 맵(Maps)
+;;;;;;;;;;
+
+; 해쉬맵(hash map)과 배열맵(array map)은 공통된 인터페이스를 공유합니다.
+; 해쉬맵은 찾기가 빠르지만, 키의 순서가 유지되지 않습니다.
+(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
+(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
+
+; 배열맵은 여러 연산을 거쳐 자연스레 해쉬맵이 됩니다.
+; 만일 이게 커진다 하더라도, 걱정할 필요가 없습니다.
+
+; 맵은 해쉬가 가능한 타입이라면 어떠한 것이든 키로써 활용이 가능하지만, 보통 키워드를 이용하는 것이 가장 좋습니다.
+; 키워드(Keyword)는 문자열과 비슷하지만, 보다 효율적인 면이 있습니다.
+(class :a) ; => clojure.lang.Keyword
+
+(def stringmap {"a" 1, "b" 2, "c" 3})
+stringmap ; => {"a" 1, "b" 2, "c" 3}
+
+(def keymap {:a 1, :b 2, :c 3})
+keymap ; => {:a 1, :c 3, :b 2}
+
+; 여기서, 쉽표가 공백으로 취급되며, 아무 일도 하지 않는다는 것을 주목하시기 바랍니다.
+
+; 맵에서 값을 얻어오기 위해선, 함수로써 맵을 호출해야 합니다.
+(stringmap "a") ; => 1
+(keymap :a) ; => 1
+
+; 키워드 역시 맵에서 함수를 얻어올 때 사용할 수 있습니다!
+(:b keymap) ; => 2
+
+; 하지만, 문자열로는 하면 안됩니다.
+;("a" stringmap)
+; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
+
+; 없는 값을 얻어오고자 하면, nil이 반환됩니다.
+(stringmap "d") ; => nil
+
+; assoc 를 이용하여 해쉬맵에 새로운 키를 추가할 수 있습니다.
+(def newkeymap (assoc keymap :d 4))
+newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
+
+; 하지만, 변경할 수 없는(immutable) clojure 타입이라는 것을 기억해야 합니다!
+keymap ; => {:a 1, :b 2, :c 3}
+
+; dissoc 를 이용하여 키를 제거할 수 있습니다.
+(dissoc keymap :a :b) ; => {:c 3}
+
+; 쎗(Set:집합)
+;;;;;;
+
+(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
+(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
+
+; conj 로 항목을 추가할 수 있습니다.
+(conj #{1 2 3} 4) ; => #{1 2 3 4}
+
+; disj 로 제거할 수 도 있습니다.
+(disj #{1 2 3} 1) ; => #{2 3}
+
+; 존재하는지 확인할 목적으로, 쎗을 함수로 사용할 수 도 있습니다.
+(#{1 2 3} 1) ; => 1
+(#{1 2 3} 4) ; => nil
+
+; clojure.sets 네임스페이스(namespace)에는 더 많은 함수들이 있습니다.
+
+; 유용한 폼(forms)
+;;;;;;;;;;;;;;;;;
+
+; clojure에선, if 와 매크로(macro)를 가지고,
+; 다른 여러 논리 연산들을 만들 수 있습니다.
+(if false "a" "b") ; => "b"
+(if false "a") ; => nil
+
+; let 을 이용하여 임시적으로 바인딩(binding)을 구축할 수 있습니다.
+(let [a 1 b 2]
+ (> a b)) ; => false
+
+; do 로 문단을 묶을 수 도 있습니다.
+(do
+ (print "Hello")
+ "World") ; => "World" (prints "Hello")
+
+; 함수는 암시적으로 do 를 가지고 있습니다.
+(defn print-and-say-hello [name]
+ (print "Saying hello to " name)
+ (str "Hello " name))
+(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
+
+; let 역시 그러합니다.
+(let [name "Urkel"]
+ (print "Saying hello to " name)
+ (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
+
+; 모듈(Modules)
+;;;;;;;;;;;;;;;
+
+; "use" 를 이용하여 module에 있는 모든 함수들을 얻어올 수 있습니다.
+(use 'clojure.set)
+
+; 이제 쎗(set:집합)연산을 사용 할 수 있습니다.
+(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
+(difference #{1 2 3} #{2 3 4}) ; => #{1}
+
+; 함수들 중에 일 부분만을 가져올 수 도 있습니다.
+(use '[clojure.set :only [intersection]])
+
+; require 를 이용하여 모듈을 import할 수 있습니다.
+(require 'clojure.string)
+
+; / 를 이용하여 모듈에 있는 함수를 호출 할 수 있습니다.
+; 여기, clojure.string 라는 모듈에, blank? 라는 함수가 있습니다.
+(clojure.string/blank? "") ; => true
+
+; import시, 모듈에 짧은 이름을 붙여줄 수 있습니다.
+(require '[clojure.string :as str])
+(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
+; (#"" denotes a regular expression literal)
+
+; :require 를 이용하여, 네임스페이스에서 require 를 사용할 수 있습니다.
+; 아레와 같은 방법을 이용하면, 모듈을 quote하지 않아도 됩니다.
+(ns test
+ (:require
+ [clojure.string :as str]
+ [clojure.set :as set]))
+
+; Java
+;;;;;;;;;;;;;;;;;
+
+; Java는 유용한 많은 표준 라이브러리를 가지고 있으며,
+; 이를 어떻게 활용할 수 있는지 알아보도록 하겠습니다.
+
+; import 로 java 모듈을 불러올 수 있습니다.
+(import java.util.Date)
+
+; ns 와 함께 import 를 할 수 도 있습니다.
+(ns test
+ (:import java.util.Date
+ java.util.Calendar))
+
+; 새로운 인스턴스를 만들기 위해선, 클래스 이름 끝에 "."을 찍습니다.
+(Date.) ; <a date object>
+
+; . 을 이용하여 메소드를 호출할 수 있습니다.
+; 아니면, 줄여서 ".메소드"로도 호출 할 수 있습니다.
+(. (Date.) getTime) ; <a timestamp>
+(.getTime (Date.)) ; exactly the same thing.
+
+; / 를 이용하여 정적메소드를 호출 할 수 있습니다.
+(System/currentTimeMillis) ; <a timestamp> (system is always present)
+
+; doto 를 이용하여 상태가 변하는(mutable) 클래스들을 좀 더 편하게(tolerable) 다룰 수 있습니다.
+(import java.util.Calendar)
+(doto (Calendar/getInstance)
+ (.set 2000 1 1 0 0 0)
+ .getTime) ; => A Date. set to 2000-01-01 00:00:00
+
+; STM
+;;;;;;;;;;;;;;;;;
+
+; Software Transactional Memory 는 clojure가 영구적인(persistent) 상태를 다루는 방식입니다.
+; clojure가 이용하는 몇몇 자료형(construct)이 있습니다.
+
+; 가장 단순한 것은 atom 입니다. 초기 값을 넣어보도록 하겠습니다.
+(def my-atom (atom {}))
+
+; swap! 으로 atom을 갱신(update)할 수 있습니다!
+; swap! 은 함수를 인자로 받아, 그 함수에 대해 현재 atom에 들어있는 값을 첫번째 인자로,
+; 나머지를 두번째 인자로 하여 호출합니다.
+(swap! my-atom assoc :a 1) ; Sets my-atom to the result of (assoc {} :a 1)
+(swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2)
+
+; '@' 를 이용하여 atom을 역참조(dereference)하여 값을 얻을 수 있습니다.
+my-atom ;=> Atom<#...> (atom 객체가 반환됩니다.)
+@my-atom ; => {:a 1 :b 2}
+
+; 여기 atom을 이용한 단순한 카운터가 있습니다.
+(def counter (atom 0))
+(defn inc-counter []
+ (swap! counter inc))
+
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+
+@counter ; => 5
+
+; STM을 구성하는 다른 것들에는 ref 와 agent 가 있습니다.
+; Refs: http://clojure.org/refs
+; Agents: http://clojure.org/agents
+```
+
+### 읽어볼거리
+
+부족한 것이 많았지만, 다행히도 채울 수 있는 것들이 많이 있습니다.
+
+Clojure.org에 많은 문서들이 보관되어 있습니다:
+[http://clojure.org/](http://clojure.org/)
+
+Clojuredocs.org는 core 함수들에 대해 다양한 예제와 문서를 보유하고 있습니다:
+[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
+
+4Clojure는 clojure/FP 스킬을 올릴 수 있는 좋은 길입니다:
+[http://www.4clojure.com/](http://www.4clojure.com/)
+
+Clojure-doc.org는 많고 많은 문서들을 보유하고 있습니다:
+[http://clojure-doc.org/](http://clojure-doc.org/)
diff --git a/ko-kr/coffeescript-kr.html.markdown b/ko-kr/coffeescript-kr.html.markdown
new file mode 100644
index 00000000..f8ac8069
--- /dev/null
+++ b/ko-kr/coffeescript-kr.html.markdown
@@ -0,0 +1,58 @@
+---
+language: coffeescript
+category: language
+contributors:
+ - ["Tenor Biel", "http://github.com/L8D"]
+filename: coffeescript-kr.coffee
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+lang: ko-kr
+---
+
+``` coffeescript
+# 커피스크립트(CoffeeScript)는 최신 유행을 따르는 언어입니다.
+# 커피스크립트는 여러 현대 언어의 트렌드를 따르는데,
+# 그래서 주석을 작성할 때는 루비나 파이썬과 같이 해시를 씁니다.
+
+###
+블록 주석은 이처럼 작성하며, 자바스크립트 코드로 만들어지도록
+'/ *'와 '* /'로 직접적으로 변환됩니다.
+
+계속하기에 앞서 자바스크립트 시맨틱을 대부분 이해하고 있어야 합니다.
+###
+
+# 할당:
+number = 42 #=> var number = 42;
+opposite = true #=> var opposite = true;
+
+# 조건문:
+number = -42 if opposite #=> if(opposite) { number = -42; }
+
+# 함수:
+square = (x) -> x * x #=> var square = function(x) { return x * x; }
+
+# 범위:
+list = [1..5] #=> var list = [1, 2, 3, 4, 5];
+
+# 객체:
+math =
+ root: Math.sqrt
+ square: square
+ cube: (x) -> x * square x
+#=> var math = {
+# "root": Math.sqrt,
+# "square": square,
+# "cube": function(x) { return x * square(x); }
+#}
+
+# 가변 인자(splat):
+race = (winner, runners...) ->
+ print winner, runners
+
+# 존재 여부 확인:
+alert "I knew it!" if elvis?
+#=> if(typeof elvis !== "undefined" && elvis !== null) { alert("I knew it!"); }
+
+# 배열 조건 제시법(comprehensions):
+cubes = (math.cube num for num in list) #=> ...
+```
diff --git a/ko-kr/go-kr.html.markdown b/ko-kr/go-kr.html.markdown
new file mode 100644
index 00000000..3012c04f
--- /dev/null
+++ b/ko-kr/go-kr.html.markdown
@@ -0,0 +1,346 @@
+---
+name: Go
+category: language
+language: Go
+filename: learngo-kr.go
+contributors:
+ - ["Sonia Keys", "https://github.com/soniakeys"]
+ - ["Christopher Bess", "https://github.com/cbess"]
+ - ["Jesse Johnson", "https://github.com/holocronweaver"]
+ - ["Quint Guvernator", "https://github.com/qguv"]
+translators:
+ - ["Jongmin Kim", "http://github.com/atomaths"]
+ - ["Peter Lee", "http://github.com/ins429"]
+lang: ko-kr
+---
+
+Go는 어떤 일을 잘 끝낼 수 있도록 하기위해 만들어졌다. Go가 잘 알려진 최신의
+트렌드는 아니지만, 실세계의 문제들을 해결하기 위해서는 가장
+새롭고 빠른 방법이다.
+
+Go는 정적 타이핑(static typing)의 명령형 언어들(imperative languages)이
+갖고 있는 특징과 유사한 개념들을 가지고 있다. Go는 컴파일과 실행속도가
+빠르며, 오늘날의 멀티코어 CPU를 위해 이해하기 쉬운 동시성(concurrency)
+기능이 추가되었다. 그리고 큰 스케일의 프로그래밍에도 도움이 되는
+기능들을 가지고 있다.
+
+또한 Go에는 훌륭한 표준 라이브러리와 열정적인 커뮤니티가 있다.
+
+```go
+// 한 줄 주석
+/* 여러 줄
+ 주석 */
+
+// 모든 Go 소스 파일은 package로 시작한다.
+// 패키지 이름 중 main은 라이브러리가 아닌 실행파일을 선언하는 특별한 이름이다.
+package main
+
+// import는 이 Go 소스 파일 내에서 참조하는 라이브러리 패키지들을 선언한다.
+import (
+ "fmt" // Go 표준 라이브러리에 있는 패키지
+ "net/http" // 표준 라이브러리에는 웹 서버 패키지도 있다! (클라이언트도 있음)
+ "strconv" // 문자열 변환 패키지
+)
+
+// 함수 선언. main은 실행 프로그램에서 시작점이 되는 특별한 함수다.
+// 중괄호를 사용한다.
+func main() {
+ // Println은 표준 출력으로 개행을 출력한다.
+ // fmt 패키지를 통해 이용할 수 있다.
+ fmt.Println("Hello world!")
+
+ // 다른 함수를 호출한다.
+ beyondHello()
+}
+
+// 함수에 파라미터가 없더라도 빈 괄호는 있어야 한다.
+func beyondHello() {
+ var x int // 변수 선언. 변수는 사용하기 전에 선언해야 한다.
+ x = 3 // 변수에 값 할당.
+ // 짧은 선언(short declaration)으로 := 를 사용하는데,
+ // 이렇게 값을 할당하면 값의 타입에 따라 변수의 타입이 결정된다.
+ y := 4
+ sum, prod := learnMultiple(x, y) // 함수는 두 개 이상의 리턴 값을 줄 수 있다.
+ fmt.Println("sum:", sum, "prod:", prod) // 간단한 출력
+ learnTypes() // 잠시 후에 좀더 자세히!
+}
+
+// 함수는 파라미터들을 가질 수 있고, 복수개의 값을 리턴할 수 있다.
+func learnMultiple(x, y int) (sum, prod int) {
+ return x + y, x * y // 두 개의 값을 리턴.
+}
+
+// 내장 타입과 리터럴
+func learnTypes() {
+ // 짧은 선언은 유용하다.
+ s := "Learn Go!" // string 타입
+
+ s2 := `역따옴표 안의 string 리터럴은
+개행을 포함할 수 있다.` // 같은 string 타입
+
+ // non-ASCII 리터럴. Go 소스는 UTF-8로 작성해야 한다.
+ g := 'Σ' // 유니코드 코드 포인트를 담고 있고, int32 타입의 가칭(alias)인 rune 타입
+
+ f := 3.14195 // float64, an IEEE-754 64-bit 부동소수 타입
+ c := 3 + 4i // complex128, 내부적으로는 두 개의 float64 타입으로 표현됨
+
+ // 초기값과 함께 사용하는 var 키워드.
+ var u uint = 7 // unsigned, 하지만 int에 따른 구현의존적인 크기
+ var pi float32 = 22. / 7
+
+ // 짧은 선언으로 변환(conversion)하는 문법.
+ // Go에서는 type casting 이라고 하지않고 type conversion 이라고 함.
+ n := byte('\n') // byte는 uint8의 가칭(alias)
+
+ // 배열은 컴파일 시에 크기가 정해진다.
+ var a4 [4]int // 모두 0으로 초기화되는 int 타입 4개짜리 배열
+ a3 := [...]int{3, 1, 5} // 3, 1, 5로 초기화되는 int 타입 3개짜리 배열
+
+ // 슬라이스(slice)라고 하는 타입은 배열에 대한 가변 크기를 가진다.
+ // 배열, 슬라이스 각자 장점이 있지만, 슬라이스가 더 많이 사용된다.
+ s3 := []int{4, 5, 9} // 위의 a3와 비교해보면 생략부호(...)가 없다.
+ s4 := make([]int, 4) // 모두 0으로 초기화되는 int 4개에 대한 슬라이스를 할당.
+ var d2 [][]float64 // 여기에서는 선언만 있고 할당은 없다.
+ bs := []byte("a slice") // string 타입을 byte 슬라이스 타입으로 형변환(type conversion)
+
+ p, q := learnMemory() // int에 대한 포인터 타입인 p와 q를 선언
+ fmt.Println(*p, *q) // C에서처럼 *는 포인터를 따라가 값을 참조한다. 여기서는 두 개의 int를 출력.
+
+ // 맵(map)은 다른 언어의 해시(hash)나 딕셔너리(dictionary)처럼 가변의 연관배열 타입.
+ m := map[string]int{"three": 3, "four": 4}
+ m["one"] = 1
+
+ // 선언만 하고 사용하지 않는 변수가 있다면 Go에서는 컴파일 시 에러가 난다.
+ // 언더바를 이용해서 변수를 사용한 것처럼 하고 그 값은 무시해버릴 수 있다.
+ _, _, _, _, _, _, _, _, _ = s2, g, f, u, pi, n, a3, s4, bs
+ // 물론 출력을 하면 변수로 취급한다.
+ fmt.Println(s, c, a4, s3, d2, m)
+
+ learnFlowControl() // 잠시 후에 다시 나옴
+}
+
+// Go는 가비지 컬렉션 기능을 JVM 같은 곳이 아닌 실행파일 런타임에 포함하고 있다.
+// 그리고 포인터는 있지만, 포인터 연산(*p++ 같은)은 없다.
+// 그래서 nil 포인터 접근같은 것 때문에 실수를 할 수는 있지만
+// 포인터 연산으로 인한 실수는 없게 된다.
+func learnMemory() (p, q *int) {
+ // 지명된 리턴 값(named return value)인 p와 q는 int에 대한 포인터 타입이다.
+ p = new(int) // 내장함수인 new는 메모리를 할당해준다.
+ // 메모리 할당된 int는 0으로 초기화 되고, p는 이제 nil이 아니다.
+ s := make([]int, 20) // 메모리의 단일 블록으로 20개의 int 공간을 할당한다.
+ s[3] = 7 // 그중 하나에 값을 준다.
+ r := -2 // 또다른 로컬 변수를 선언한다.
+ return &s[3], &r // &는 어떤 대상체의 메모리 주소를 가져오게 된다.
+}
+
+func expensiveComputation() int {
+ return 1e6
+}
+
+func learnFlowControl() {
+ // if문에 중괄호는 필요하지만, 조건이 들어갈 곳에 소괄호는 쓰지 않는다.
+ if true {
+ fmt.Println("told ya")
+ }
+ // 모든 Go 소스의 코드 포맷팅은 "go fmt" 커맨드라인 명령으로 소스코드의 포맷을 맞춘다.
+ if false {
+ // pout
+ } else {
+ // gloat
+ }
+ // if-else 체인 형태보다 switch 사용이 권장된다.
+ x := 1
+ switch x {
+ case 0:
+ case 1:
+ // case 안에서는 break가 없어도 자동으로 다음 case로 내려가지 않는다.
+ // 자동으로 내려가게 하려면 fallthrough 키워드를 사용한다.
+ case 2:
+ // x는 1이므로 여기는 실행되지 않음.
+ }
+ // if 에서처럼 for 에서도 양쪽에 소괄호를 쓰지 않는다.
+ for x := 0; x < 3; x++ { // ++ 은 실행을 제어하는 하나의 구문(statement)이다.
+ fmt.Println("iteration", x)
+ }
+ // 여기서 x는 1이다. 위 for에서 x는 for 안의 블록 범위에 있기 때문.
+
+ // For is the only loop statement in Go, but it has alternate forms.
+ // for 는 Go에서 유일한 루프 구문이지만 다양한 형태로 조건을 주거나 while
+ // 처럼 쓸 수도 있다.
+ for { // 무한루프
+ break // 여기서 곧바로 break를 한 건 단지
+ continue // break, continue를 루프 안에서 쓸 수 있다는 것을 보여주기 위함.
+ }
+ // for 에서처럼 if 에서 := 를 사용하는것은 y에 먼저 값을 대입하고,
+ // 그리고 y > x를 검사한다는 의미.
+ if y := expensiveComputation(); y > x {
+ x = y
+ }
+ // 함수 리터럴은 클로저다.
+ xBig := func() bool {
+ return x > 100 // 위 switch 문 바로 위에 있는 x를 참조한다.
+ }
+ fmt.Println("xBig:", xBig()) // true (x에 1e6를 대입했었다.)
+ x /= 1e5 // x는 10이 된다.
+ fmt.Println("xBig:", xBig()) // 이제 xBig()의 결과는 false가 된다.
+
+ // `goto`가 필요하다면, 좋아하게 될지도...
+ goto love
+love:
+
+ learnDefer() // defer에 대해
+ learnInterfaces() // 곧이어서 좋은 기능에 대한 설명이 나올 거다.
+}
+
+func learnDefer() (ok bool) {
+ // deferred statements are executed just before the function returns.
+ // 연기된(deferred) 구문은 함수가 리턴하기 직전에 실행된다.
+ defer fmt.Println("deferred statements execute in reverse (LIFO) order.") // 연기된 구문은 LIFO순으로 실행된다.
+ defer fmt.Println("\nThis line is being printed first because") // 이 줄이 먼저 실행된다.
+ // defer는 주로 파일을 닫는데 사용된다.
+ // 파일을 닫는함수를 파일을 여는함수에 가까이 둘수 있다.
+ return true
+}
+
+// String 이라는 메서드 하나를 가진 Stringer 라는 인터페이스 타입을 정의하자.
+type Stringer interface {
+ String() string
+}
+
+// x와 y라는 이름의 int 타입 필드를 가진 pair라는 struct를 정의하자.
+type pair struct {
+ x, y int
+}
+
+// pair 타입에 메서드 String을 정의하자.
+// 이제 pair는 Stringer 인터페이스를 구현(implement)한 것이 되었다.
+func (p pair) String() string { // 여기서 p는 리시버(receiver)라고 부른다.
+ // Sprintf는 fmt 패키지 안에 있는 외부로 공개된(exported) 함수다.
+ // 점(.)으로 p의 필드들을 참조할 수 있다.
+ return fmt.Sprintf("(%d, %d)", p.x, p.y)
+}
+
+func learnInterfaces() {
+ // 중괄호 문법은 "구조체 리터럴(struct literal)"인데, 초기화된 구조체로
+ // 취급하게 해준다. := 문법으로 p를 이 구조체로 선언하고 초기화한다.
+ p := pair{3, 4}
+ fmt.Println(p.String()) // 타입 pair인 p의 String 메서드를 호출.
+ var i Stringer // Stringer 인터페이스 타입 i를 선언.
+ i = p // pair는 Stringer를 구현했기 때문에 이 대입은 유효하다.
+ // 타입 Stringer인 i의 String 메서드 호출. 결과는 위와 같다.
+ fmt.Println(i.String())
+
+ // fmt 패키지의 함수들을 통해 어떤 객체를 출력해보려고 할 때,
+ // fmt 패키지 내에서는 그 객체가 가진 String 메서드를 호출하도록 되어 있다.
+ fmt.Println(p) // 결과는 위와 같다. Println은 String 메서드를 호출한다.
+ fmt.Println(i) // 결과는 위와 같다.
+
+ learnVariadicParams("great", "learning", "here!")
+}
+
+// 함수는 가변 인수(variadic) 파라미터를 가질수 있다.
+func learnVariadicParams(myStrings ...interface{}) {
+ // 가변 인수를 차례로 반복한다.
+ // 여기서 언더바(언더스코어, `_`)는 배열의 인덱스 인수를 무시한다.
+ // The underbar here is ignoring the index argument of the array.
+ for _, param := range myStrings {
+ fmt.Println("param:", param)
+ }
+
+ // 가변 인수 값을 가변인수 파라미터로 보내기.
+ fmt.Println("params:", fmt.Sprintln(myStrings...))
+
+ learnErrorHandling()
+}
+
+func learnErrorHandling() {
+ // ", ok" (comma okay)표현은 무언가가 맞는 것인지 아닌지 확인하는데 사용된다.
+ m := map[int]string{3: "three", 4: "four"}
+ if x, ok := m[1]; !ok { // 이 map 안에 키가 1인 것은 없으므로 ok는 false가 된다.
+ fmt.Println("no one there")
+ } else {
+ fmt.Print(x) // 만일 1이 map에 있었다면 x는 키 1의 값이 들어가게 된다.
+ }
+
+ // Go에서는 함수가 복수 개의 리턴 값을 줄 수 있다는 점을 활용해 함수의 두 번째 리턴
+ // 값으로 error를 리턴해주고 그 error가 nil 인지 아닌지 확인하는 관례가 있다.
+ // 이때 이 error 값은 단지 위에서처럼 함수의 결과가 성공했는지 실패했는지를 확인하는
+ // 것뿐만 아니라 실패 시 어떤 문제가 있었는지 확인할 수 있는 수단도 된다.
+ if _, err := strconv.Atoi("non-int"); err != nil { // _ 는 값을 안 쓰고 버린다는 의미.
+ // "strconv.ParseInt: parsing "non-int": invalid syntax" 이런 에러가 출력된다.
+ fmt.Println(err)
+ }
+ // 인터페이스에 대해 잠시 후에 다시 잠깐 볼 것이다.
+ learnConcurrency()
+}
+
+// c는 goroutine 간의 통신을 위한 채널(channel)이다.
+func inc(i int, c chan int) {
+ c <- i + 1 // 채널이 <- 이 연산자 왼쪽에 온다면 그 채널로 데이터를 보낸다는 의미다.
+}
+
+// 우리는 어떤 숫자들을 동시에 증가시키기 위해 inc 함수를 사용할 것이다.
+func learnConcurrency() {
+ // make는 slice, map, channel 타입들에 대해 메모리를 할당하고 초기화를 한다.
+ // Go에는 메모리 할당 방법으로 new와 make가 있다.
+ c := make(chan int)
+ // 3개의 동시에 실행되는 goroutine를 시작한다. 만약 실행하고 있는 머신이
+ // 멀티코어 CPU를 가지고 있고 올바르게 설정되어(GOMAXPROCS) 있다면
+ // 숫자가 정말로 병렬적으로 증가하게 될 것이다.
+ go inc(0, c) // go는 새로운 goroutine을 시작하는 구문이다.
+ go inc(10, c)
+ go inc(-805, c)
+ // 채널로부터 3개의 결과를 읽어 출력한다.
+ // 결과가 어떤 순서로 오는지는 알 수 없다.
+ fmt.Println(<-c, <-c, <-c) // 채널이 <- 연산자 오른쪽에 있는 건, 채널로부터 데이터를 받는 연산이다.
+
+ cs := make(chan string) // string을 다루는 또 다른 채널
+ cc := make(chan chan string) // string 채널의 채널
+ go func() { c <- 84 }() // c 채널로 값을 보내는 goroutine 시작.
+ go func() { cs <- "wordy" }() // cs 채널로 값을 보내느 goroutine 시작.
+ // select 구문은 switch 문과 비슷하지만, case에서 채널 연산에 관한 일을 한다.
+ // select의 case들은 채널통신을 할 준비가 된 case 하나가 무작위로 선택되어
+ // 그 부분이 실행된다.
+ select {
+ case i := <-c: // 채널로부터 받아진 값은 변수에 대입할 수 있다.
+ fmt.Printf("it's a %T", i)
+ case <-cs: // 또는 받은 값을 그냥 버릴 수도 있다.
+ fmt.Println("it's a string")
+ case <-cc: // 통신할 준비가 되어 있지 않은 비어있는 채널.
+ fmt.Println("didn't happen.")
+ }
+ // 여기서는 c나 cs 채널로부터 값 하나를 받을 수 있다. 위에서 실행한 두 개의
+ // goroutine 중 하나가 완료되면 다른 하나는 블락된 상태로 있게 된다.
+
+ learnWebProgramming() // Go에서는 웹 서버쪽 개발도 쉽게 할 수 있다.
+}
+
+// http 패키지의 함수 하나로 웹 서버를 실행시킨다.
+func learnWebProgramming() {
+ // ListenAndServe의 첫 번째 파라미터는 listen 하기 위한 TCP 주소고,
+ // 두 번째 파라미터는 http.Handler 인터페이스다.
+ err := http.ListenAndServe(":8080", pair{})
+ fmt.Println(err) // don't ignore errors
+}
+
+// http.Handler의 하나 뿐인 메서드, ServeHTTP를 pair에서 구현한다.
+func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // http.ResponseWriter의 메서드로 클라이언트에게 데이터를 보낸다.
+ w.Write([]byte("You learned Go in Y minutes!"))
+}
+```
+
+## 더 읽어볼 것들
+
+Go에 대한 모든 것들은 [Go 공식 웹 사이트](http://golang.org/)를 참고하자.
+여기에는 따라해볼 튜토리얼, 웹 기반의 인터랙티브 실행환경과 많은 읽을거리들이 있다.
+
+Go 언어 자체에 대한 스펙도 읽어보기를 적극 추천한다. 읽기 쉽게 되어있고
+그리 길지는 않다.
+
+Go 소스코드에 대해 좀더 알아보고 싶다면 [Go 표준 라이브러리](http://golang.org/src/pkg/)를
+분석해보기 바란다. 이해하기 쉽게 문서화되어 있고, Go 스타일 그리고 Go에서의
+관례 배우기에 가장 좋은 방법일 것이다. 또는 [문서](http://golang.org/pkg/) 안에서
+함수 이름 하나를 클릭해보면 소스코드를 브라우저에서 살펴볼 수도 있다.
+
+Go를 배울수 있는 또하나의 좋은 방법은 [Go by example](https://gobyexample.com/).
diff --git a/ko-kr/java-kr.html.markdown b/ko-kr/java-kr.html.markdown
new file mode 100644
index 00000000..dc7a356f
--- /dev/null
+++ b/ko-kr/java-kr.html.markdown
@@ -0,0 +1,408 @@
+---
+language: java
+filename: java-kr.java
+category: language
+contributors:
+ - ["Jake Prather", "http://github.com/JakeHP"]
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+lang: ko-kr
+---
+
+자바는 일반 목적으로 사용할 수 있고 동시성을 지원하며, 클래스 기반의 객체지향 컴퓨터 프로그래밍 언어입니다.
+[더 자세한 사항](http://docs.oracle.com/javase/tutorial/java/index.html)
+
+```java
+// 한 줄짜리 주석은 //로 시작합니다.
+/*
+여러 줄 주석은 다음과 같은 형태입니다.
+*/
+/**
+자바독(JavaDoc) 주석은 이렇게 생겼습니다. 자바독 주석은 클래스나 클래스의
+다양한 속성을 기술하는 데 사용됩니다.
+*/
+
+// java.util 패키지 안에 있는 ArrayList 클래스를 임포트합니다.
+import java.util.ArrayList;
+// java.security 패키지 안에 있는 모든 클래스를 임포트합니다.
+import java.security.*;
+
+// 각 .java 파일에는 공용(public) 클래스가 들어 있으며, 클래스의 이름은
+// 파일명과 동일합니다.
+public class LearnJava {
+
+ // 프로그램에는 반드시 진입점 역할을 하는 main 메서드가 하나 있어야 합니다.
+ public static void main (String[] args) {
+
+ // System.out.println을 이용해 한 줄을 출력합니다.
+ System.out.println("Hello World!");
+ System.out.println(
+ "Integer: " + 10 +
+ " Double: " + 3.14 +
+ " Boolean: " + true);
+
+ // 줄바꿈 없이 뭔가를 출력하려면 System.out.print를 사용합니다.
+ System.out.print("Hello ");
+ System.out.print("World");
+
+
+ ///////////////////////////////////////
+ // 타입 & 변수
+ ///////////////////////////////////////
+
+ // <타입> <이름>과 같은 형태로 변수를 선언합니다.
+ // Byte - 부호가 있는 8비트 2의 보수 정수
+ // (-128 <= byte <= 127)
+ byte fooByte = 100;
+
+ // Short - 부호가 있는 16비트 2의 보수 정수
+ // (-32,768 <= short <= 32,767)
+ short fooShort = 10000;
+
+ // Integer - 부호가 있는 32비트 2의 보수 정수
+ // (-2,147,483,648 <= int <= 2,147,483,647)
+ int fooInt = 1;
+
+ // Long - 부호가 있는 64비트 2의 보수 정수
+ // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
+ long fooLong = 100000L;
+ // L은 이 변수의 값이 Long 타입임을 나타내는 데 사용됩니다.
+ // L이 없는 것들은 기본적으로 정수로 간주됩니다.
+
+ // 참고: 자바에는 부호 없는(unsigned) 타입이 없습니다.
+
+ // Float - 단정도 32비트 IEEE 754 부동 소수점 수
+ float fooFloat = 234.5f;
+ // f는 이 변수의 값이 float 타입임을 나타내는 데 사용됩니다.
+ // f를 지정하지 않으면 double로 간주됩니다.
+
+ // Double - 배정도 64비트 IEEE 754 부동 소수점 수
+ double fooDouble = 123.4;
+
+ // Boolean - 참(true) & 거짓(false)
+ boolean fooBoolean = true;
+ boolean barBoolean = false;
+
+ // Char - 단일 16비트 유니코드 문자
+ char fooChar = 'A';
+
+ // 변수를 변경할 수 없게 만들려면 final을 지정합니다.
+ final int HOURS_I_WORK_PER_WEEK = 9001;
+
+ // 문자열
+ String fooString = "My String Is Here!";
+
+ // \n은 새로운 줄을 시작하는 이스케이프 문자입니다.
+ String barString = "Printing on a new line?\nNo Problem!";
+ // \t는 탭 문자를 추가하는 이스케이프 문자입니다.
+ String bazString = "Do you want to add a tab?\tNo Problem!";
+ System.out.println(fooString);
+ System.out.println(barString);
+ System.out.println(bazString);
+
+ // 배열
+ // 배열의 크기는 반드시 선언할 때 결정해야 합니다.
+ // 배열을 선언하는 형식은 다음과 같습니다.
+ //<자료형> [] <변수명> = new <자료형>[<배열 크기>];
+ int [] intArray = new int[10];
+ String [] stringArray = new String[1];
+ boolean [] booleanArray = new boolean[100];
+
+ // 배열을 선언하고 초기화하는 또 다른 방법
+ int [] y = {9000, 1000, 1337};
+
+ // 배열 인덱스 - 요소에 접근
+ System.out.println("intArray @ 0: " + intArray[0]);
+
+ // 배열의 인덱스는 0에서부터 시작하며 변경 가능합니다.
+ intArray[1] = 1;
+ System.out.println("intArray @ 1: " + intArray[1]); // => 1
+
+ // 기타 참고할 만한 자료구조
+ // ArrayLists - 좀 더 많은 기능을 제공하고 크기를 변경 가능하다는 점을
+ // 제외하면 배열과 비슷합니다.
+ // LinkedLists
+ // Maps
+ // HashMaps
+
+ ///////////////////////////////////////
+ // 연산자
+ ///////////////////////////////////////
+ System.out.println("\n->Operators");
+
+ int i1 = 1, i2 = 2; // 다중 선언의 축약형
+
+ // 산술 연산은 이해하기 어렵지 않습니다.
+ System.out.println("1+2 = " + (i1 + i2)); // => 3
+ System.out.println("2-1 = " + (i2 - i1)); // => 1
+ System.out.println("2*1 = " + (i2 * i1)); // => 2
+ System.out.println("1/2 = " + (i1 / i2)); // => 0 (0.5를 잘라 버립니다)
+
+ // 나눗셈
+ System.out.println("11%3 = "+(11 % 3)); // => 2
+
+ // 비교 연산자
+ System.out.println("3 == 2? " + (3 == 2)); // => false
+ System.out.println("3 != 2? " + (3 != 2)); // => true
+ System.out.println("3 > 2? " + (3 > 2)); // => true
+ System.out.println("3 < 2? " + (3 < 2)); // => false
+ System.out.println("2 <= 2? " + (2 <= 2)); // => true
+ System.out.println("2 >= 2? " + (2 >= 2)); // => true
+
+ // 비트 연산자!
+ /*
+ ~ 단항 보수 연산
+ << 산술적 왼쪽 시프트
+ >> 산술적 오른쪽 시프트
+ >>> 논리적 오른쪽 시프트
+ & 비트 단위 논리곱(AND)
+ ^ 비트 단위 배타적 논리합(OR)
+ | 비트 단위 논리합(OR)
+ */
+
+ // 증감 연산자
+ int i = 0;
+ System.out.println("\n->Inc/Dec-rementation");
+ System.out.println(i++); //i = 1. 후치 증가 연산
+ System.out.println(++i); //i = 2. 전치 증가 연산
+ System.out.println(i--); //i = 1. 후치 감소 연산
+ System.out.println(--i); //i = 0. 전치 감소 연산
+
+ ///////////////////////////////////////
+ // 제어 구조
+ ///////////////////////////////////////
+ System.out.println("\n->Control Structures");
+
+ // if 문은 C 언어와 비슷합니다.
+ int j = 10;
+ if (j == 10){
+ System.out.println("I get printed");
+ } else if (j > 10) {
+ System.out.println("I don't");
+ } else {
+ System.out.println("I also don't");
+ }
+
+ // while 루프
+ int fooWhile = 0;
+ while(fooWhile < 100)
+ {
+ // System.out.println(fooWhile);
+ // 카운터를 증가
+ // 99번 반복, fooWhile 0->99
+ fooWhile++;
+ }
+ System.out.println("fooWhile Value: " + fooWhile);
+
+ // do-while 루프
+ int fooDoWhile = 0;
+ do
+ {
+ // System.out.println(fooDoWhile);
+ // 카운터를 증가
+ // 99번 반복, fooDoWhile 0->99
+ fooDoWhile++;
+ }while(fooDoWhile < 100);
+ System.out.println("fooDoWhile Value: " + fooDoWhile);
+
+ // for 루프
+ int fooFor;
+ // for 루프 구조 => for(<초기식>; <조건식>; <증감식>)
+ for(fooFor=0; fooFor<10; fooFor++){
+ // System.out.println(fooFor);
+ // 10번 반복, fooFor 0->9
+ }
+ System.out.println("fooFor Value: " + fooFor);
+
+ // switch-case 문
+ // switch는 byte, short, char, int 자료형을 대상으로 동작합니다.
+ // 아울러 열거형을 비롯해 String 클래스 및 원시 타입을 감싼 Character,
+ // Byte, Short, Integer와 같은 몇 가지 특별한 클래스에 대해서도 동작합니다.
+ int month = 3;
+ String monthString;
+ switch (month){
+ case 1:
+ monthString = "January";
+ break;
+ case 2:
+ monthString = "February";
+ break;
+ case 3:
+ monthString = "March";
+ break;
+ default:
+ monthString = "Some other month";
+ break;
+ }
+ System.out.println("Switch Case Result: " + monthString);
+
+
+ ///////////////////////////////////////
+ // 자료형 변환과 형변환
+ ///////////////////////////////////////
+
+ // 데이터 변환
+
+ // 문자열에서 정수로 변환
+ Integer.parseInt("123");// 정수 버전의 "123"을 반환
+
+ // 정수를 문자열로 변환
+ Integer.toString(123);// 문자열 버전의 123을 반환
+
+ // 다른 변환에 대해서는 아래 클래스를 확인해 보세요.
+ // Double
+ // Long
+ // String
+
+ // 형변환
+ // 자바 객체 또한 형변환할 수 있으며, 이와 관련해서 알아야 할 세부사항이
+ // 많을뿐더러 다소 중급 수준에 해당하는 개념들도 다뤄야 합니다.
+ // 이와 관련된 사항은 아래 링크를 참고하세요.
+ // http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
+
+
+ ///////////////////////////////////////
+ // 클래스와 함수
+ ///////////////////////////////////////
+
+ System.out.println("\n->Classes & Functions");
+
+ // (Bicycle 클래스의 정의)
+
+ // 클래스를 인스턴스화하려면 new를 사용합니다.
+ Bicycle trek = new Bicycle();
+
+ // 객체의 메서드를 호출합니다.
+ trek.speedUp(3); // 항상 설정자 메서드와 접근자 메서드를 사용해야 합니다.
+ trek.setCadence(100);
+
+ // 현재 객체의 값을 표시할 때는 관례적으로 toString을 사용합니다.
+ System.out.println("trek info: " + trek.toString());
+
+ } // main 메서드 끝
+} // LearnJava 클래스 끝
+
+
+// .java 파일 안에 다른 비공개 클래스를 포함할 수 있습니다.
+
+
+// 클래스 선언 문법:
+// <public/private/protected> class <클래스명>{
+// // 데이터 필드, 생성자, 함수가 모두 이곳에 들어갑니다.
+// // 자바에서는 함수를 메서드라고 부릅니다.
+// }
+
+class Bicycle {
+
+ // Bicycle의 필드와 변수
+ public int cadence; // Public: 어느 곳에서도 접근할 수 있습니다.
+ private int speed; // Private: 클래스 안에서만 접근할 수 있습니다.
+ protected int gear; // Protected: 현재 클래스와 하위 클래스에서 접근할 수 있습니다.
+ String name; // default: 현재 패키지 안에서만 접근할 수 있습니다.
+
+ // 생성자는 클래스를 생성하는 방법 중 하나입니다.
+ // 다음은 기본 생성자입니다.
+ public Bicycle() {
+ gear = 1;
+ cadence = 50;
+ speed = 5;
+ name = "Bontrager";
+ }
+
+ // 다음은 구체화된 생성자입니다(인자를 담고 있습니다)
+ public Bicycle(int startCadence, int startSpeed, int startGear, String name) {
+ this.gear = startGear;
+ this.cadence = startCadence;
+ this.speed = startSpeed;
+ this.name = name;
+ }
+
+ // 함수 문법:
+ // <public/private/protected> <반환형> <함수명>(<인자>)
+
+ // 자바 클래스는 필드에 대해 접근자 메서드와 설정자 메서드를 구현할 때가 많습니다.
+
+ // 메서드 선언 문법:
+ // <유효범위> <반환형> <메서드명>(<인자>)
+ public int getCadence() {
+ return cadence;
+ }
+
+ // void 메서드는 반환형이 필요하지 않습니다.
+ public void setCadence(int newValue) {
+ cadence = newValue;
+ }
+
+ public void setGear(int newValue) {
+ gear = newValue;
+ }
+
+ public void speedUp(int increment) {
+ speed += increment;
+ }
+
+ public void slowDown(int decrement) {
+ speed -= decrement;
+ }
+
+ public void setName(String newName) {
+ name = newName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ // 현재 객체의 속성값을 표시하는 메서드
+ @Override
+ public String toString() {
+ return "gear: " + gear +
+ " cadence: " + cadence +
+ " speed: " + speed +
+ " name: " + name;
+ }
+} // Bicycle 클래스의 끝
+
+// PennyFarthing은 Bicycle의 하위 클래스입니다.
+class PennyFarthing extends Bicycle {
+ // (페니 파딩은 앞바퀴가 굉장히 큰 자전거입니다. 기어가 없죠.)
+
+ public PennyFarthing(int startCadence, int startSpeed){
+ // super를 이용해 부모 생성자를 호출합니다.
+ super(startCadence, startSpeed, 0, "PennyFarthing");
+ }
+
+ // @annotation을 이용해 재정의하는 메서드를 표시해야 합니다.
+ // 애노테이션과 애노테이션의 용도에 관한 자세한 내용은 아래 링크를 참고하세요.
+ // 애노테이션: http://docs.oracle.com/javase/tutorial/java/annotations/
+ @Override
+ public void setGear(int gear) {
+ gear = 0;
+ }
+
+}
+
+```
+
+## 기타 참고자료
+
+다음 링크를 통해 다양한 주제를 이해하고 구글을 통해 구체적인 예제들을 찾아보세요.
+
+공부할 만한 기타 주제:
+
+* [썬/오라클의 자바 자습서](http://docs.oracle.com/javase/tutorial/index.html)
+
+* [자바 접근 제한자](http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html)
+
+* [객체 지향 프로그래밍 개념](http://docs.oracle.com/javase/tutorial/java/concepts/index.html):
+ * [상속(Inheritance)](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html)
+ * [다형성(Polymorphism)](http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html)
+ * [추상화(Abstraction)](http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)
+
+* [예외(Exceptions)](http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html)
+
+* [인터페이스(Interfaces)](http://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html)
+
+* [제네릭(Generics)](http://docs.oracle.com/javase/tutorial/java/generics/index.html)
+
+* [자바 코딩 관례(Java Code Conventions)](http://www.oracle.com/technetwork/java/codeconv-138413.html)
diff --git a/ko-kr/javascript-kr.html.markdown b/ko-kr/javascript-kr.html.markdown
new file mode 100644
index 00000000..9561e80c
--- /dev/null
+++ b/ko-kr/javascript-kr.html.markdown
@@ -0,0 +1,433 @@
+---
+language: javascript
+category: language
+contributors:
+ - ["Adam Brenecki", "http://adam.brenecki.id.au"]
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+filename: javascript-kr.js
+lang: ko-kr
+---
+
+자바스크립트는 넷스케이프의 브렌던 아이크(Brendan Eich)가 1995년에 만들었습니다.
+원래 자바스크립트는 웹사이트를 위한 단순한 스크립트 언어를 목표로 만들어졌는데,
+좀 더 복잡한 웹 애플리케이션을 만들기 위해 자바를 보완하는 역할이었지만
+웹 페이지와의 긴밀한 상호작용과 브라우저에 대한 지원 기능 덕분에 웹 프론트엔드에서
+자바보다 훨씬 더 보편적으로 쓰이게 됐습니다.
+
+그렇지만 자바스크립트는 웹 브라우저에만 국한되지 않습니다. 구글 크롬의 V8 자바스크립트
+엔진을 위한 독립형 런타임을 제공하는 Node.js는 점점 인기를 얻고 있습니다.
+
+피드백 주시면 대단히 감사하겠습니다! [@adambrenecki](https://twitter.com/adambrenecki)나
+[adam@brenecki.id.au](mailto:adam@brenecki.id.au)를 통해 저와 만나실 수 있습니다.
+
+```js
+// 주석은 C와 비슷합니다. 한 줄짜리 주석은 두 개의 슬래시로 시작하고,
+/* 여러 줄 주석은 슬래시 별표로 시작해서
+ 별표 슬래시로 끝납니다. */
+
+// 구문은 세미콜론(;)으로 끝낼 수 있습니다.
+doStuff();
+
+// 하지만 꼭 그럴 필요는 없는데, 특정 경우를 제외하고
+// 새 줄이 시작할 때마다 세미콜론이 자동으로 삽입되기 때문입니다.
+doStuff()
+
+// 여기서는 세미콜론을 생략하겠습니다. 세미콜론을 생략할지 여부는
+// 개인적인 취향이나 프로젝트의 스타일 가이드를 따릅니다.
+
+///////////////////////////////////
+// 1. 숫자, 문자열, 연산자
+
+// 자바스크립트에는 단 하나의 숫자 타입(64비트 IEEE 754 배정도 숫자)만이
+// 있습니다.
+3 // = 3
+1.5 // = 1.5
+
+// 모든 기초 산술 연산은 기대한 대로 동작합니다.
+1 + 1 // = 2
+8 - 1 // = 7
+10 * 2 // = 20
+35 / 5 // = 7
+
+// 나누어 떨어지지 않는 나눗셈도 포함됩니다.
+5 / 2 // = 2.5
+
+// 비트 연산도 지원됩니다. float을 대상으로 비트 연산을 수행하면
+// 32비트까지 부호가 있는 int로 변환됩니다.
+1 << 2 // = 4
+
+// 괄호를 이용하면 우선순위를 지정할 수 있습니다.
+(1 + 3) * 2 // = 8
+
+// 실제 숫자가 아닌 특별한 세 가지 값이 있습니다.
+Infinity // 1/0 1/0과 같은 연산의 결과
+-Infinity // -1/0과 같은 연산의 결과
+NaN // 0/0과 같은 연산의 결과
+
+// 불린 타입도 있습니다.
+true
+false
+
+// 문자열은 '나 "로 생성합니다.
+'abc'
+"Hello, world"
+
+// 부정 연산에는 ! 기호를 이용합니다.
+!true // = false
+!false // = true
+
+// 동일성 연산은 ==
+1 == 1 // = true
+2 == 1 // = false
+
+// 불일치 연산은 !=
+1 != 1 // = false
+2 != 1 // = true
+
+// 그 밖의 비교 연산
+1 < 10 // = true
+1 > 10 // = false
+2 <= 2 // = true
+2 >= 2 // = true
+
+// 문자열은 +로 연결할 수 있습니다.
+"Hello " + "world!" // = "Hello world!"
+
+// 그리고 <와 >로 비교할 수 있습니다.
+"a" < "b" // = true
+
+// 비교 시 타입 강제변환이 수행됩니다.
+"5" == 5 // = true
+
+// ===를 쓰지 않는다면 말이죠.
+"5" === 5 // = false
+
+// charAt을 이용하면 문자열 내의 문자에 접근할 수 있습니다.
+"This is a string".charAt(0)
+
+// null과 undefined도 있습니다.
+null // 의도적으로 값이 아님을 나타내는 데 사용합니다.
+undefined // 값이 아직 설정되지 않음을 나타내는 데 사용합니다.
+
+// null, undefinded, NaN, 0, ""은 거짓이며, 그 밖의 다른 모든 값은 참입니다.
+// 참고로 0은 거짓이며, "0"은 참입니다(심지어 0 == "0"이더라도).
+
+///////////////////////////////////
+// 2. 변수, 배열, 객체
+
+// 변수는 var 키워드로 선언합니다. 자바스크립트는 동적 타입 언어라서
+// 타입을 지정할 필요가 없습니다. 값을 할당할 때는 = 문자 하나를 사용합니다.
+var someVar = 5
+
+// var 키워드를 지정하지 않아도 오류는 발생하지 않습니다.
+someOtherVar = 10
+
+// 그렇지만 변수가 여러분이 정의한 유효범위가 아니라
+// 전역 유효범위에 생성됩니다.
+
+// 값을 할당하지 않은 채로 선언한 변수는 undefined로 설정됩니다.
+var someThirdVar // = undefined
+
+// 변수에 수학 연산을 수행하는 축약형 표현은 다음과 같습니다.
+someVar += 5 // someVar = someVar + 5;와 같음. 이제 someVar는 10.
+someVar *= 10 // somVar는 100
+
+// 1을 더하거나 빼는 훨씬 더 짧은 표현도 있습니다.
+someVar++ // 이제 someVar는 101
+someVar-- // 다시 100으로 되돌아감
+
+// 배열은 순차적인 임의 타입 값의 목록입니다.
+var myArray = ["Hello", 45, true]
+
+// 배열의 멤버는 대괄호로 둘러싼 인덱스를 이용해 접근할 수 있습니다.
+// 배열의 인덱스는 0부터 시작합니다.
+myArray[1] // = 45
+
+// 자바스크립트의 객체는 다른 언어의 '사전'이나 '맵'과 같습니다.
+// 즉, 키-값 쌍으로 구성된 비순차 컬렉션입니다.
+{key1: "Hello", key2: "World"}
+
+// 키는 문자열이지만 유효한 자바스크립트 식별자일 경우
+// 작은따옴표는 필요하지 않습니다. 값은 어떤 타입이든 사용할 수 있습니다.
+var myObj = {myKey: "myValue", "my other key": 4}
+
+// 객체 속성에도 인덱스를 이용해 접근할 수 있습니다.
+myObj["my other key"] // = 4
+
+// 또는 키가 유효한 식별자일 경우 점 표기법을 이용해 접근할 수 있습니다.
+myObj.myKey // = "myValue"
+
+// 객체는 변경 가능합니다. 즉, 값을 변경하거나 새 키를 추가할 수 있습니다.
+myObj.myThirdKey = true
+
+// 설정되지 않은 값에 접근하려고 하면 undefined가 반환됩니다.
+myObj.myFourthKey // = undefined
+
+///////////////////////////////////
+// 3. 로직과 제어 구조
+
+// if 구조는 여러분이 예상한 대로 동작합니다.
+var count = 1
+if (count == 3){
+ // count가 3일 경우 평가됨
+} else if (count == 4) {
+ // count가 4일 경우 평가됨
+} else {
+ // count가 3이나 4가 아닌 경우에 평가됨
+}
+
+// while도 마찬가지입니다.
+while (true) {
+ // 무한 루프!
+}
+
+// do-while 문은 항상 최소 한 번은 실행된다는 점을 제외하면
+// while 문과 비슷합니다.
+var input
+do {
+ input = getInput()
+} while (!isValid(input))
+
+// for 문은 C와 자바의 for 문과 같습니다.
+// 초기화식; 지속 조건; 증감식
+for (var i = 0; i < 5; i++){
+ // 5번 실행됨
+}
+
+// &&는 논리 and이고 ||는 논리 or입니다.
+if (house.size == "big" && house.colour == "blue"){
+ house.contains = "bear"
+}
+if (colour == "red" || colour == "blue"){
+ // 색은 빨강이거나 파랑
+}
+
+// &&와 ||은 "단축 평가"를 수행하는데, 기본값을 설정할 때 유용합니다.
+var name = otherName || "default"
+
+///////////////////////////////////
+// 4. 함수, 유효범위, 클로저
+
+// 자바스크립트 함수는 function 키워드로 선언합니다.
+function myFunction(thing){
+ return thing.toUpperCase()
+}
+myFunction("foo") // = "FOO"
+
+// 함수는 "익명"으로, 즉 이름 없이 정의할 수도 있습니다.
+function(thing){
+ return thing.toLowerCase()
+}
+// (함수를 가리키는 이름이 없기 때문에 함수를 호출할 수 없습니다)
+
+// 자바스크립트 함수는 일급 객체이므로 다른 변수에 재할당하고
+// 다른 함수에 인자로 전달할 수 있습니다. 가령, 이벤트 핸들러를 만들 경우
+function myFunction(){
+ // 이 코드는 5초 내에 호출됨
+}
+setTimeout(myFunction, 5000)
+
+// 다른 함수를 호출할 때 직접적으로 함수 구문을 작성할 수도 있습니다.
+
+setTimeout(function myFunction(){
+ // 이 코드는 5초 내에 호출됨
+}, 5000)
+
+// 자바스크립트에는 함수 유효범위가 있습니다.
+// 함수는 자체적인 유효범위를 가지지만 다른 블록은 유효범위를 가지지 않습니다.
+if (true){
+ var i = 5
+}
+i // = 5 - 블록 유효범위를 지원하는 언어에서는 undefined가 아닙니다.
+
+// 이것은 "즉시 실행되는 익명 함수"라는 공통 패턴으로 이어지는데,
+// 이 패턴은 임시 변수가 전역 유효범위로 유출되는 것을 방지합니다.
+(function(){
+ var temporary = 5
+ // '전역 객체'에 할당하는 식으로 전역 유효범위에 접근할 수 있는데,
+ // 브라우저에서 전역 객체는 항상 'window'입니다. 전역 객체는
+ // Node.js와 같은 브라우저가 아닌 환경에서는 다른 이름일 수도 있습니다.
+ window.permanent = 10
+ // 또는 앞에서 언급했다시피 var 키워드를 뺄 수도 있습니다.
+ permanent2 = 15
+})()
+temporary // ReferenceError 발생
+permanent // = 10
+permanent2 // = 15
+
+// 자바스크립트의 강력한 기능 중 하나는 클로저(closure)입니다.
+// 함수가 다른 함수 안에서 정의되면 안쪽에 정의된 함수는 바깥 함수의
+// 모든 변수에 접근할 수 있습니다.
+function sayHelloInFiveSeconds(name){
+ var prompt = "Hello, " + name + "!"
+ function inner(){
+ alert(prompt)
+ }
+ setTimeout(inner, 5000)
+ // setTimeout은 비동기적으로 동작하므로 이 함수는 5초 동안
+ // 기다리지 않고 실행을 마칩니다. 하지만 5초가 지나면 inner에서도
+ // prompt의 값에 접근할 수 있습니다.
+}
+sayHelloInFiveSeconds("Adam") // 5초 내로 "Hello, Adam!"이라고 적힌 팝업이 표시됨
+
+///////////////////////////////////
+// 5. 객체 심화; 생성자와 프로토타입
+
+// 객체는 함수를 포함할 수 있습니다.
+var myObj = {
+ myFunc: function(){
+ return "Hello world!"
+ }
+}
+myObj.myFunc() // = "Hello world!"
+
+// 객체에 포함된 함수가 호출되면 함수에서는 this 키워드를 이용해
+// 해당 함수가 포함된 객체에 접근할 수 있습니다.
+myObj = {
+ myString: "Hello world!",
+ myFunc: function(){
+ return this.myString
+ }
+}
+myObj.myFunc() // = "Hello world!"
+
+// 여기서 설정한 것은 함수가 정의된 곳이 아닌 함수가 호출되는
+// 방식과 관련이 있습니다. 그래서 아래 함수는 객체 컨텍스트에서
+// 호출되지 않으면 동작하지 않습니다.
+var myFunc = myObj.myFunc
+myFunc() // = undefined
+
+// 반대로 함수는 객체에 할당하고 this를 통해 해당 객체에 접근할 수 있습니다.
+// 함수를 정의할 때 객체에 추가되지 않았더라도 마찬가지입니다.
+var myOtherFunc = function(){
+ return this.myString.toUpperCase()
+}
+myObj.myOtherFunc = myOtherFunc
+myObj.myOtherFunc() // = "HELLO WORLD!"
+
+// new 키워드로 함수를 호출하면 새로운 객체가 생성되고 this를 통해
+// 함수에서 사용할 수 있게 됩니다. 이런 식으로 설계된 함수를 생성자라 합니다.
+
+var MyConstructor = function(){
+ this.myNumber = 5
+}
+myNewObj = new MyConstructor() // = {myNumber: 5}
+myNewObj.myNumber // = 5
+
+// 모든 자바스크립트 객체는 'prototype'을 가지고 있습니다. 어떤 객체에 대해
+// 실제 객체에는 존재하지 않는 프로퍼티에 접근하면 인터프리터는 프로로타입에서
+// 해당 프로퍼티를 찾습니다.
+
+// 일부 자바스크립트 구현체에서는 __proto__라는 마법의 프로퍼티로
+// 객체의 프로토타입에 접근하는 것을 허용하기도 합니다. 프로토타입을
+// 설명하기에는 이런 내용도 도움되겠지만 __proto__는 표준에 포함돼
+// 있지 않습니다. 나중에 프로토타입을 사용하는 표준 방법을 살펴보겠습니다.
+var myObj = {
+ myString: "Hello world!",
+}
+var myPrototype = {
+ meaningOfLife: 42,
+ myFunc: function(){
+ return this.myString.toLowerCase()
+ }
+}
+myObj.__proto__ = myPrototype
+myObj.meaningOfLife // = 42
+
+// 이 방법은 함수에도 통합니다.
+myObj.myFunc() // = "hello world!"
+
+// 물론 프로퍼티가 프로토타입에 존재하지 않으면
+// 프로토타입의 프로토타입을 찾는 식으로 진행됩니다.
+myPrototype.__proto__ = {
+ myBoolean: true
+}
+myObj.myBoolean // = true
+
+// 여기서 복사는 일어나지 않습니다. 각 객체에는 프로토타입에 대한
+// 참조가 보관돼 있습니다. 이는 프로토타입을 변경하면 변경사항이
+// 모든 곳에 반영된다는 의미입니다.
+myPrototype.meaningOfLife = 43
+myObj.meaningOfLife // = 43
+
+// 앞에서 __proto__가 표준에 포함돼 있지 않다고 이야기했는데,
+// 기존 객체의 프로토타입을 변경하는 표준 방법은 없습니다.
+// 하지만 특정 프로토타입을 가지고 새로운 객체를 생성하는 두 가지
+// 방법이 있습니다.
+
+// 첫 번째 방법은 Object.create를 이용하는 것인데,
+// Object.create는 최근에 자바스크립트에 추가된 것이라서 아직까지
+// 모든 구현체에서 이용할 수 있는 것은 아닙니다.
+var myObj = Object.create(myPrototype)
+myObj.meaningOfLife // = 43
+
+// 두 번째 방법은 어디서나 통하는 방법인데, 생성자와 관련이 있습니다.
+// 생성자에는 prototype이라는 프로퍼티가 있습니다. 이 프로퍼티는
+// 생성자 함수 자체의 프로토타입이 *아니고* 생성자와 new 키워드를 이용해
+// 객체가 생성될 때 새로운 객체가 받는 프로토타입입니다.
+myConstructor.prototype = {
+ getMyNumber: function(){
+ return this.myNumber
+ }
+}
+var myNewObj2 = new myConstructor()
+myNewObj2.getMyNumber() // = 5
+
+// 문자열과 숫자와 같은 내장 타입에도 동등한 래퍼 객체를
+// 생성하는 생성자가 있습니다.
+var myNumber = 12
+var myNumberObj = new Number(12)
+myNumber == myNumberObj // = true
+
+// 하지만 정확히 같지는 않습니다.
+typeof myNumber // = 'number'
+typeof myNumberObj // = 'object'
+myNumber === myNumberObj // = false
+if (0){
+ // 0은 거짓이라서 이 코드는 실행되지 않습니다.
+}
+
+// 하지만 래퍼 객체와 일반 내장 함수는 프로토타입을 공유하기 때문에
+// 가령 문자열에 실제로 기능을 추가할 수 있습니다.
+String.prototype.firstCharacter = function(){
+ return this.charAt(0)
+}
+"abc".firstCharacter() // = "a"
+
+// 이러한 사실은 기존 자바스크립트 버전에서 자바스크립트의
+// 새로운 기능을 구현하는 "폴리필(polyfilling)"에 자주 이용되므로
+// 오래된 버전의 브라우저와 같이 기존 환경에서 사용될 수 있습니다.
+
+// 예를 들어, Object.create가 모든 구현체에서 사용 가능한 것은 아니라고
+// 했지만 아래의 폴리필을 이용해 Object.create를 여전히 사용할 수 있습니다.
+if (Object.create === undefined){ // 이미 존재하면 덮어쓰지 않음
+ Object.create = function(proto){
+ // 올바른 프로토타입을 가지고 임시 생성자를 만듬
+ var Constructor = function(){}
+ Constructor.prototype = proto
+ // 그런 다음 임시 생성자를 이용해 새로운 적절한 프로토타입을
+ // 포함한 객체를 생성
+ return new Constructor()
+ }
+}
+```
+
+## 기타 참고 자료
+
+[모질라 개발자 네트워크](https://developer.mozilla.org/en-US/docs/Web/JavaScript)에서는
+자바스크립트에 대한 훌륭한 문서를 제공합니다. 더불어 위키 형식이라서 좀 더 많은 사항을
+배우게 되면 여러분만의 지식을 공유함으로써 다른 사람들에게 도움을 줄 수도 있습니다.
+
+MDN의 ['자바스크립트 재입문'](https://developer.mozilla.org/ko/docs/A_re-introduction_to_JavaScript)에서는
+여기서 다룬 개념의 상당수를 더욱 자세히 다루고 있습니다. 이 자료에서는 자바스크립트 언어 자체에
+대해서만 상당히 신중하게 다뤘습니다. 웹 페이지에서 자바스크립트를 사용하는 방법을 배우고 싶다면
+[문서 객체 모델(Document Object Model)](https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core)에
+관해 배우는 것으로 시작하길 바랍니다.
+
+[자바스크립트 가든](http://bonsaiden.github.io/JavaScript-Garden/)에서는 자바스크립트 언어에서
+직관에 어긋나는 모든 부분들을 심도 있게 다룹니다.
+
+더불어 이 글에 직접적으로 기여한 분들로, 내용 중 일부는 이 사이트에 있는
+루이 딘(Louie Dihn)의 파이썬 튜토리얼과 모질라 개발자 네트워크에 있는
+[자바스크립트 튜토리얼](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript)을 참고했습니다.
diff --git a/ko-kr/lua-kr.html.markdown b/ko-kr/lua-kr.html.markdown
new file mode 100644
index 00000000..b4a018ef
--- /dev/null
+++ b/ko-kr/lua-kr.html.markdown
@@ -0,0 +1,422 @@
+---
+language: Lua
+category: language
+contributors:
+ - ["Tyler Neylon", "http://tylerneylon.com/"]
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+lang: ko-kr
+filename: learnlua-kr.lua
+---
+
+```lua
+-- 대시 두 개는 한 줄짜리 주석을 의미합니다.
+
+--[[
+ [와 ]를 두 개씩 추가하면 여러 줄 주석이 됩니다.
+--]]
+
+----------------------------------------------------
+-- 1. 변수와 흐름 제어
+----------------------------------------------------
+
+num = 42 -- 모든 숫자는 double입니다.
+-- 놀랄 필요는 없습니다. 64비트 double은
+-- 정확한 int 값을 저장하기 위해 52비트로 구성돼
+-- 있습니다. 52비트 이하의 int 값에 대해서는
+-- 장비 정밀도와 관련된 문제가 생기지 않습니다.
+
+s = 'walternate' -- 파이썬과 같은 불변 문자열
+t = "큰따옴표를 써도 됩니다"
+u = [[ 이중 대괄호는
+ 여러 줄 문자열을
+ 나타냅니다.]]
+t = nil -- 미정의 t. 루아는 가비지 컬렉션을 지원합니다.
+
+-- 블록은 do/end와 같은 키워드로 나타냅니다:
+while num < 50 do
+ num = num + 1 -- ++나 += 유형의 연산자는 쓸 수 없습니다.
+end
+
+-- If 절:
+if num > 40 then
+ print('40 이상')
+elseif s ~= 'walternate' then -- ~=은 '같지 않다'입니다.
+ -- 동일성 검사는 파이썬과 마찬가지로 ==입니다.
+ -- 문자열에도 쓸 수 있습니다.
+ io.write('not over 40\n') -- 기본적으로 stdout에 씁니다.
+else
+ -- 변수는 기본적으로 전역 변수입니다.
+ thisIsGlobal = 5 -- 낙타 표기법이 일반적입니다.
+
+ -- 변수를 지역 변수로 만드는 방법은 다음과 같습니다:
+ local line = io.read() -- 다음 stdin 줄을 읽습니다
+
+ -- 문자열 연결에는 .. 연산자를 씁니다:
+ print('겨울이 오고 있습니다, ' .. line)
+end
+
+-- 미정의 변수는 nil을 반환합니다.
+-- 다음 코드를 실행해도 오류가 나지 않습니다:
+foo = anUnknownVariable -- 이제 foo는 nil입니다.
+
+aBoolValue = false
+
+-- nil과 false만이 거짓값입니다; 0과 ''은 참입니다!
+if not aBoolValue then print('twas false') end
+
+-- 'or'와 'and'는 단축 평가(short-circuit)됩니다.
+-- 다음 코드는 C/자바스크립트의 a?b:c 연산자와 비슷합니다:
+ans = aBoolValue and 'yes' or 'no' --> 'no'
+
+karlSum = 0
+for i = 1, 100 do -- 범위에는 마지막 요소도 포함됩니다.
+ karlSum = karlSum + i
+end
+
+-- 카운트 다운을 할 때는 "100, 1, -1"을 범위로 씁니다.
+fredSum = 0
+for j = 100, 1, -1 do fredSum = fredSum + j end
+
+-- 일반적으로 범위는 begin, end[, step]입니다.
+
+-- 또 다른 반복문 구문은 다음과 같습니다:
+repeat
+ print('미래의 방식')
+ num = num - 1
+until num == 0
+
+
+----------------------------------------------------
+-- 2. 함수
+----------------------------------------------------
+
+function fib(n)
+ if n < 2 then return n end
+ return fib(n - 2) + fib(n - 1)
+end
+
+-- 클로저와 익명 함수도 사용할 수 있습니다:
+function adder(x)
+ -- 반환된 함수는 adder가 호출될 때 생성되고 x의
+ -- 값이 유지됩니다:
+ return function (y) return x + y end
+end
+a1 = adder(9)
+a2 = adder(36)
+print(a1(16)) --> 25
+print(a2(64)) --> 100
+
+-- 반환문, 함수 호출, 할당문은 길이가 다른
+-- 값의 리스트에 대해서도 모두 동작합니다.
+-- 리스트에 값이 더 적을 때는 nil이 할당/반환되고
+-- 리스트에 값이 더 많을 때는 나머지 값은 버려집니다.
+
+x, y, z = 1, 2, 3, 4
+-- 이제 x = 1, y = 2, z = 3이고 4는 버려집니다.
+
+function bar(a, b, c)
+ print(a, b, c)
+ return 4, 8, 15, 16, 23, 42
+end
+
+x, y = bar('zaphod') --> "zaphod nil nil"가 출력
+-- 이제 x = 4, y = 8이고 15~42의 값은 버려집니다.
+
+-- 함수는 일급 객체이고, 지역/전역 유효범위를 가질
+-- 수 있습니다. 아래의 두 함수는 같습니다:
+function f(x) return x * x end
+f = function (x) return x * x end
+
+-- 그리고 아래의 두 함수도 마찬가지입니다:
+local function g(x) return math.sin(x) end
+local g; g = function (x) return math.sin(x) end
+-- 'local g'라고 선언하면 g를 지역 함수로 만듭니다.
+
+-- 그나저나 삼각 함수는 라디안 단위로 동작합니다.
+
+-- 함수를 호출할 때 문자열 매개변수를 하나만 전달한다면
+-- 괄호를 쓰지 않아도 됩니다:
+print 'hello' -- 잘 동작합니다.
+
+
+----------------------------------------------------
+-- 3. 테이블
+----------------------------------------------------
+
+-- 테이블 = 루아의 유일한 복합 자료구조로서, 연관 배열입니다.
+-- PHP의 배열이나 자바스크립트의 객체와 비슷하며,
+-- 리스트로도 사용할 수 있는 해시 기반의 딕셔너리입니다.
+
+-- 테이블을 딕셔너리/맵으로 사용하기:
+
+-- 딕셔너리 리터럴은 기본적으로 문자열 키를 가집니다:
+t = {key1 = 'value1', key2 = false}
+
+-- 문자열 키에는 자바스크립트와 유사한 점 표기법을 쓸 수 있습니다:
+print(t.key1) -- 'value1'을 출력.
+t.newKey = {} -- 새 키/값 쌍을 추가.
+t.key2 = nil -- 테이블에서 key2를 제거.
+
+-- (nil이 아닌) 값을 키로 사용하는 리터럴 표기법:
+u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
+print(u[6.28]) -- "tau"가 출력
+
+-- 키 매칭은 기본적으로 숫자와 문자열에 대해서는 값으로 하지만
+-- 테이블에 대해서는 식별자로 합니다.
+a = u['@!#'] -- Now a = 'qbert'.
+b = u[{}] -- We might expect 1729, but it's nil:
+a = u['@!#'] -- 이제 a는 'qbert'입니다.
+b = u[{}] -- 1729를 예상했겠지만 nil입니다:
+-- 탐색이 실패하기 때문에 b는 nil입니다. 탐색이 실패하는 이유는
+-- 사용된 키가 원본 값을 저장할 때 사용한 키와 동일한 객체가 아니기
+-- 때문입니다. 따라서 문자열 및 숫자가 좀 더 이식성 있는 키입니다.
+
+-- 테이블 하나를 매개변수로 취하는 함수를 호출할 때는 괄호가 필요하지 않습니다:
+function h(x) print(x.key1) end
+h{key1 = 'Sonmi~451'} -- 'Sonmi~451'를 출력.
+
+for key, val in pairs(u) do -- 테이블 순회
+ print(key, val)
+end
+
+-- _G는 모든 전역 멤버에 대한 특별한 테이블입니다.
+print(_G['_G'] == _G) -- 'true'가 출력
+
+-- 테이블을 리스트/배열로 사용하기:
+
+-- 리스트 리터럴은 암묵적으로 int 키로 설정됩니다:
+v = {'value1', 'value2', 1.21, 'gigawatts'}
+for i = 1, #v do -- #v는 리스트 v의 크기입니다.
+ print(v[i]) -- 인덱스가 1에서 시작합니다!! 제정신이 아닙니다!
+end
+-- 'list'는 실제 타입이 아닙니다. v는 연속된 정수형 키가 포함된
+-- 테이블이고 리스트로 취급될 뿐입니다.
+
+----------------------------------------------------
+-- 3.1 메타테이블과 메타메서드
+----------------------------------------------------
+
+-- 테이블은 테이블에 연산자 오버로딩을 가능하게 하는 메타테이블을
+-- 가질 수 있습니다. 나중에 메타테이블이 어떻게 자바스크립트
+-- 프로토타입과 같은 행위를 지원하는지 살펴보겠습니다.
+
+f1 = {a = 1, b = 2} -- 분수 a/b를 표현
+f2 = {a = 2, b = 3}
+
+-- 다음 코드는 실패합니다:
+-- s = f1 + f2
+
+metafraction = {}
+function metafraction.__add(f1, f2)
+ sum = {}
+ sum.b = f1.b * f2.b
+ sum.a = f1.a * f2.b + f2.a * f1.b
+ return sum
+end
+
+setmetatable(f1, metafraction)
+setmetatable(f2, metafraction)
+
+s = f1 + f2 -- f1의 메타테이블을 대상으로 __add(f1, f2)를 호출
+
+-- f1과 f2는 자바스크립트의 프로토타입과 달리 각 메타테이블에 대한
+-- 키가 없어서 getmetatable(f1)과 같이 받아와야 합니다.
+-- 메타테이블은 __add 같은 루아가 알고 있는 키가 지정된 일반 테이블입니다.
+
+-- 그렇지만 다음 줄은 s가 메타테이블을 가지고 있지 않기 때문에 실패합니다.
+-- t = s + s
+-- 아래와 같이 클래스와 유사한 패턴은 이러한 문제가 발생하지 않습니다.
+
+-- 메타테이블에 대한 __index는 점을 이용한 탐색을 오버로드합니다:
+defaultFavs = {animal = 'gru', food = 'donuts'}
+myFavs = {food = 'pizza'}
+setmetatable(myFavs, {__index = defaultFavs})
+eatenBy = myFavs.animal -- 동작합니다! 고마워요, 메타테이블!
+
+-- 직접적인 메타테이블 탐색이 실패할 경우 메타테이블의 __index 값을 이용해
+-- 재시도하고, 이런 과정이 반복됩니다.
+
+-- __index 값은 좀 더 세분화된 탐색을 위해 function(tbl, key)가
+-- 될 수도 있습니다.
+
+-- __index, __add, ...의 값을 메타메서드라고 합니다.
+-- 다음은 메타메서드를 가진 테이블의 전체 목록입니다.
+
+-- __add(a, b) for a + b
+-- __sub(a, b) for a - b
+-- __mul(a, b) for a * b
+-- __div(a, b) for a / b
+-- __mod(a, b) for a % b
+-- __pow(a, b) for a ^ b
+-- __unm(a) for -a
+-- __concat(a, b) for a .. b
+-- __len(a) for #a
+-- __eq(a, b) for a == b
+-- __lt(a, b) for a < b
+-- __le(a, b) for a <= b
+-- __index(a, b) <fn이나 테이블> for a.b
+-- __newindex(a, b, c) for a.b = c
+-- __call(a, ...) for a(...)
+
+----------------------------------------------------
+-- 3.2 클래스 형태의 테이블과 상속
+----------------------------------------------------
+
+-- 루아에는 클래스가 내장돼 있지 않으며, 테이블과 메타테이블을
+-- 이용해 클래스를 만드는 다양한 방법이 있습니다.
+
+-- 다음 예제에 대한 설명은 하단을 참조합니다.
+
+Dog = {} -- 1.
+
+function Dog:new() -- 2.
+ newObj = {sound = 'woof'} -- 3.
+ self.__index = self -- 4.
+ return setmetatable(newObj, self) -- 5.
+end
+
+function Dog:makeSound() -- 6.
+ print('I say ' .. self.sound)
+end
+
+mrDog = Dog:new() -- 7.
+mrDog:makeSound() -- 'I say woof' -- 8.
+
+-- 1. Dog는 클래스처럼 동작합니다. 실제로는 테이블입니다.
+-- 2. function 테이블명:fn(...)은
+-- function 테이블명.fn(self, ...)과 같습니다.
+-- :는 self라는 첫 번째 인자를 추가할 뿐입니다.
+-- self가 값을 어떻게 얻는지 궁금하다면 아래의 7과 8을 읽어보세요.
+-- 3. newObj는 Dog 클래스의 인스턴스가 됩니다.
+-- 4. self = 인스턴스화되는 클래스.
+-- 주로 self = Dog이지만 상속을 이용하면 이것을 바꿀 수 있습니다.
+-- newObj의 메타테이블과 self의 __index를 모두 self에 설정하면
+-- newObj가 self의 함수를 갖게 됩니다.
+-- 5. 참고: setmetatable은 첫 번째 인자를 반환합니다.
+-- 6. :는 2에서 설명한 것과 같이 동작하지만 이번에는 self가
+-- 클래스가 아닌 인스턴스라고 예상할 수 있습니다.
+-- 7. Dog.new(Dog)과 같으므로 new()에서는 self = Dog입니다.
+-- 8. mrDog.makeSound(mrDog)과 같으므로 self = mrDog입니다.
+
+----------------------------------------------------
+
+-- 상속 예제:
+
+LoudDog = Dog:new() -- 1.
+
+function LoudDog:makeSound()
+ s = self.sound .. ' ' -- 2.
+ print(s .. s .. s)
+end
+
+seymour = LoudDog:new() -- 3.
+seymour:makeSound() -- 'woof woof woof' -- 4.
+
+-- 1. LoudDog은 Dog의 메서드와 변수를 갖게 됩니다.
+-- 2. self는 new()에서 'sound' 키를 가집니다. 3을 참고하세요.
+-- 3. LoudDog.new(LoudDog)과 같고, LoudDog은 'new' 키가 없지만
+-- 메타테이블에서 __index = Dog이기 때문에 Dog.new(LoudDog)으로
+-- 변환됩니다.
+-- 결과: seymour의 메타테이블은 LoudDog이고 LoudDog.__index는
+-- LoudDog입니다. 따라서 seymour.key는 seymour.key,
+-- LoudDog.key, Dog.key와 같을 것이며, 지정한 키에 어떤 테이블이
+-- 오든 상관없을 것입니다.
+-- 4. 'makeSound' 키는 LoudDog에서 발견할 수 있습니다.
+-- 이것은 LoudDog.makeSound(seymour)와 같습니다.
+
+-- 필요할 경우, 하위 클래스의 new()는 기반 클래스의 new()와 유사합니다.
+function LoudDog:new()
+ newObj = {}
+ -- newObj를 구성
+ self.__index = self
+ return setmetatable(newObj, self)
+end
+
+----------------------------------------------------
+-- 4. 모듈
+----------------------------------------------------
+
+
+--[[ 여기서 주석을 제거하면 이 스크립트의 나머지 부분은
+-- 실행 가능한 상태가 됩니다.
+```
+
+```lua
+-- mod.lua 파일의 내용이 다음과 같다고 가정해 봅시다.
+local M = {}
+
+local function sayMyName()
+ print('이소룡')
+end
+
+function M.sayHello()
+ print('안녕하세요')
+ sayMyName()
+end
+
+return M
+
+-- 또 다른 파일에서는 mod.lua의 기능을 이용할 수 있습니다.
+local mod = require('mod') -- mod.lua 파일을 실행
+
+-- require는 모듈을 포함시키는 표준화된 방법입니다.
+-- require는 다음과 같이 동작합니다: (캐싱돼 있지 않을 경우. 하단 참조)
+-- mod.lua가 함수의 본문처럼 되므로 mod.lua 안의 지역 멤버는
+-- 밖에서 볼 수 없습니다.
+
+-- 다음 코드가 동작하는 것은 mod가 mod.lua의 M과 같기 때문입니다.
+mod.sayHello() -- 이소룡 씨에게 인사를 건넵니다.
+
+-- 다음 코드를 실행하면 오류가 발생합니다.
+-- sayMyName는 mod.lua 안에서만 존재하기 때문입니다:
+mod.sayMyName() -- 오류
+
+-- require의 반환값은 캐싱되므로 require를 여러 번 실행해도
+-- 파일은 최대 한 번만 실행됩니다.
+
+-- mod2.lua에 "print('Hi')"가 들어 있다고 가정해 봅시다.
+local a = require('mod2') -- Hi!를 출력
+local b = require('mod2') -- print를 실행하지 않음. a=b
+
+-- dofile은 require와 비슷하지만 캐싱을 하지 않습니다:
+dofile('mod2') --> Hi!
+dofile('mod2') --> Hi! (require와 달리 다시 한번 실행됨)
+
+-- loadfile은 루아 파일을 읽어들이지만 실행하지는 않습니다
+f = loadfile('mod2') -- f()를 호출해야 mod2.lua가 실행됩니다.
+
+-- loadstring은 문자열에 대한 loadfile입니다.
+g = loadstring('print(343)') -- 함수를 반환합니다.
+g() -- 343이 출력됩니다. 그전까지는 아무것도 출력되지 않습니다.
+
+--]]
+
+```
+
+## 참고자료
+
+루아를 배우는 일이 흥미진진했던 이유는 <a href="http://love2d.org/">Love 2D 게임 엔진</a>을 이용해
+게임을 만들 수 있었기 때문입니다. 이것이 제가 루아를 배운 이유입니다.
+
+저는 <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV의 "프로그래머를 위한 루아"</a>로
+시작했습니다. 그다음으로 공식 <a href="http://www.lua.org/pil/contents.html">"프로그래밍 루아"</a> 책을 읽었습니다.
+그렇게 루아를 배웠습니다.
+
+lua-users.org에 있는 <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">짧은 루아 레퍼런스</a>를
+읽어두면 도움될지도 모르겠습니다.
+
+여기서는 표준 라이브러리에 관해서는 다루지 않았습니다.
+
+* <a href="http://lua-users.org/wiki/StringLibraryTutorial">string 라이브러리</a>
+* <a href="http://lua-users.org/wiki/TableLibraryTutorial">table 라이브러리</a>
+* <a href="http://lua-users.org/wiki/MathLibraryTutorial">math 라이브러리</a>
+* <a href="http://lua-users.org/wiki/IoLibraryTutorial">io 라이브러리</a>
+* <a href="http://lua-users.org/wiki/OsLibraryTutorial">os 라이브러리</a>
+
+그나저나 이 파일 전체는 유효한 루아 프로그램입니다. 이 파일을
+learn.lua로 저장한 후 "lua learn.lua"를 실행해 보세요!
+
+이 글은 tylerneylon.com에 처음으로 써본 글이며,
+<a href="https://gist.github.com/tylerneylon/5853042">Github의 Gist</a>에서도 확인할 수 있습니다.
+루아로 즐거운 시간을 보내세요!
diff --git a/ko-kr/php-kr.html.markdown b/ko-kr/php-kr.html.markdown
new file mode 100644
index 00000000..1f53221f
--- /dev/null
+++ b/ko-kr/php-kr.html.markdown
@@ -0,0 +1,662 @@
+---
+language: PHP
+category: language
+contributors:
+ - ["Malcolm Fell", "http://emarref.net/"]
+ - ["Trismegiste", "https://github.com/Trismegiste"]
+filename: learnphp-kr.php
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+lang: ko-kr
+---
+
+이 문서에서는 PHP 5+를 설명합니다.
+
+
+```php
+<?php // PHP 코드는 반드시 <?php 태그로 감싸야 합니다.
+
+// php 파일에 PHP 코드만 들어 있다면 닫는 태그를 생략하는 것이 관례입니다.
+
+// 슬래시 두 개는 한 줄 주석을 의미합니다.
+
+# 해시(파운드 기호로도 알려진)도 같은 역할을 하지만 //이 더 일반적으로 쓰입니다.
+
+/*
+ 텍스트를 슬래시-별표와 별표-슬래시로 감싸면
+ 여러 줄 주석이 만들어집니다.
+*/
+
+// 출력결과를 표시하려면 "echo"나 "print"를 사용합니다.
+print('Hello '); // 줄바꿈 없이 "Hello "를 출력합니다.
+
+// ()는 print와 echo를 사용할 때 선택적으로 사용할 수 있습니다.
+echo "World\n"; // "World"를 출력한 후 줄바꿈합니다.
+// (모든 구문은 반드시 세미콜론으로 끝나야 합니다.)
+
+// <?php 태그 밖의 내용은 모두 자동으로 출력됩니다.
+?>
+Hello World Again!
+<?php
+
+
+/************************************
+ * 타입과 변수
+ */
+
+// 변수명은 $ 기호로 시작합니다.
+// 유효한 변수명은 문자나 밑줄(_)로 시작하고,
+// 이어서 임의 개수의 숫자나 문자, 밑줄이 옵니다.
+
+// 불린값은 대소문자를 구분합니다.
+$boolean = true; // 또는 TRUE나 True
+$boolean = false; // 또는 FALSE나 False
+
+// Integer
+$int1 = 12; // => 12
+$int2 = -12; // => -12
+$int3 = 012; // => 10 (a leading 0 denotes an octal number)
+$int4 = 0x0F; // => 15 (a leading 0x denotes a hex literal)
+
+// Float (doubles로도 알려짐)
+$float = 1.234;
+$float = 1.2e3;
+$float = 7E-10;
+
+// 산술 연산
+$sum = 1 + 1; // 2
+$difference = 2 - 1; // 1
+$product = 2 * 2; // 4
+$quotient = 2 / 1; // 2
+
+// 축약형 산술 연산
+$number = 0;
+$number += 1; // $number를 1만큼 증가
+echo $number++; // 1을 출력(평가 후 증가)
+echo ++$number; // 3 (평가 전 증가)
+$number /= $float; // 나눗셈 후 몫을 $number에 할당
+
+// 문자열은 작은따옴표로 감싸야 합니다.
+$sgl_quotes = '$String'; // => '$String'
+
+// 다른 변수를 포함할 때를 제외하면 큰따옴표 사용을 자제합니다.
+$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.'
+
+// 특수 문자는 큰따옴표에서만 이스케이프됩니다.
+$escaped = "This contains a \t tab character.";
+$unescaped = 'This just contains a slash and a t: \t';
+
+// 필요할 경우 변수를 중괄호로 감쌉니다.
+$money = "I have $${number} in the bank.";
+
+// PHP 5.3부터는 여러 줄 문자열을 생성하는 데 나우닥(nowdoc)을 사용할 수 있습니다.
+$nowdoc = <<<'END'
+Multi line
+string
+END;
+
+// 히어닥(heredoc)에서는 문자열 치환을 지원합니다.
+$heredoc = <<<END
+Multi line
+$sgl_quotes
+END;
+
+// 문자열을 연결할 때는 .을 이용합니다.
+echo 'This string ' . 'is concatenated';
+
+
+/********************************
+ * 상수
+ */
+
+// 상수는 define()을 이용해 정의되며,
+// 런타임 동안 절대 변경될 수 없습니다!
+
+// 유효한 상수명은 문자나 밑줄로 시작하고,
+// 이어서 임의 개수의 숫자나 문자, 밑줄이 옵니다.
+define("FOO", "something");
+
+// 상수명을 이용해 직접 상수에 접근할 수 있습니다.
+echo 'This outputs '.FOO;
+
+
+/********************************
+ * 배열
+ */
+
+// PHP의 모든 배열은 연관 배열(associative array, 해시맵)입니다.
+
+// 일부 언어에서 해시맵으로도 알려진 연관 배열은
+
+// 모든 PHP 버전에서 동작합니다.
+$associative = array('One' => 1, 'Two' => 2, 'Three' => 3);
+
+// PHP 5.4에서는 새로운 문법이 도입됐습니다.
+$associative = ['One' => 1, 'Two' => 2, 'Three' => 3];
+
+echo $associative['One']; // 1을 출력
+
+// 리스트 리터럴은 암시적으로 정수형 키를 할당합니다.
+$array = ['One', 'Two', 'Three'];
+echo $array[0]; // => "One"
+
+
+/********************************
+ * 출력
+ */
+
+echo('Hello World!');
+// 표준출력(stdout)에 Hello World!를 출력합니다.
+// 브라우저에서 실행할 경우 표준출력은 웹 페이지입니다.
+
+print('Hello World!'); // echo과 동일
+
+// echo는 실제로 언어 구성물에 해당하므로, 괄호를 생략할 수 있습니다.
+echo 'Hello World!';
+print 'Hello World!'; // 똑같이 출력됩니다.
+
+$paragraph = 'paragraph';
+
+echo 100; // 스칼라 변수는 곧바로 출력합니다.
+echo $paragraph; // 또는 변수의 값을 출력합니다.
+
+// 축약형 여는 태그를 설정하거나 PHP 버전이 5.4.0 이상이면
+// 축약된 echo 문법을 사용할 수 있습니다.
+?>
+<p><?= $paragraph ?></p>
+<?php
+
+$x = 1;
+$y = 2;
+$x = $y; // 이제 $x의 값은 $y의 값과 같습니다.
+$z = &$y;
+// $z는 이제 $y에 대한 참조를 담고 있습니다. $z의 값을 변경하면
+// $y의 값도 함께 변경되며, 그 반대도 마찬가지입니다.
+// $x는 $y의 원래 값을 그대로 유지합니다.
+
+echo $x; // => 2
+echo $z; // => 2
+$y = 0;
+echo $x; // => 2
+echo $z; // => 0
+
+
+/********************************
+ * 로직
+ */
+$a = 0;
+$b = '0';
+$c = '1';
+$d = '1';
+
+// assert는 인자가 참이 아닌 경우 경고를 출력합니다.
+
+// 다음과 같은 비교는 항상 참이며, 타입이 같지 않더라도 마찬가지입니다.
+assert($a == $b); // 동일성 검사
+assert($c != $a); // 불일치성 검사
+assert($c <> $a); // 또 다른 불일치성 검사
+assert($a < $c);
+assert($c > $b);
+assert($a <= $b);
+assert($c >= $d);
+
+// 다음과 같은 코드는 값과 타입이 모두 일치하는 경우에만 참입니다.
+assert($c === $d);
+assert($a !== $d);
+assert(1 == '1');
+assert(1 !== '1');
+
+// 변수는 어떻게 사용하느냐 따라 다른 타입으로 변환될 수 있습니다.
+
+$integer = 1;
+echo $integer + $integer; // => 2
+
+$string = '1';
+echo $string + $string; // => 2 (문자열이 강제로 정수로 변환됩니다)
+
+$string = 'one';
+echo $string + $string; // => 0
+// + 연산자는 'one'이라는 문자열을 숫자로 형변환할 수 없기 때문에 0이 출력됩니다.
+
+// 한 변수를 다른 타입으로 처리하는 데 형변환을 사용할 수 있습니다.
+
+$boolean = (boolean) 1; // => true
+
+$zero = 0;
+$boolean = (boolean) $zero; // => false
+
+// 대다수의 타입을 형변환하는 데 사용하는 전용 함수도 있습니다.
+$integer = 5;
+$string = strval($integer);
+
+$var = null; // 널 타입
+
+
+/********************************
+ * 제어 구조
+ */
+
+if (true) {
+ print 'I get printed';
+}
+
+if (false) {
+ print 'I don\'t';
+} else {
+ print 'I get printed';
+}
+
+if (false) {
+ print 'Does not get printed';
+} elseif(true) {
+ print 'Does';
+}
+
+// 사항 연산자
+print (false ? 'Does not get printed' : 'Does');
+
+$x = 0;
+if ($x === '0') {
+ print 'Does not print';
+} elseif($x == '1') {
+ print 'Does not print';
+} else {
+ print 'Does print';
+}
+
+
+
+// 다음과 같은 문법은 템플릿에 유용합니다.
+?>
+
+<?php if ($x): ?>
+This is displayed if the test is truthy.
+<?php else: ?>
+This is displayed otherwise.
+<?php endif; ?>
+
+<?php
+
+// 특정 로직을 표현할 때는 switch를 사용합니다.
+switch ($x) {
+ case '0':
+ print 'Switch does type coercion';
+ break; // break을 반드시 포함해야 하며, break를 생략하면
+ // 'two'와 'three' 케이스로 넘어갑니다.
+ case 'two':
+ case 'three':
+ // 변수가 'two'나 'three'인 경우에 실행될 코드를 작성합니다.
+ break;
+ default:
+ // 기본값으로 실행될 코드를 작성
+}
+
+// while과 do...while, for 문이 아마 더 친숙할 것입니다.
+$i = 0;
+while ($i < 5) {
+ echo $i++;
+}; // "01234"를 출력
+
+echo "\n";
+
+$i = 0;
+do {
+ echo $i++;
+} while ($i < 5); // "01234"를 출력
+
+echo "\n";
+
+for ($x = 0; $x < 10; $x++) {
+ echo $x;
+} // "0123456789"를 출력
+
+echo "\n";
+
+$wheels = ['bicycle' => 2, 'car' => 4];
+
+// foreach 문은 배영를 순회할 수 있습니다.
+foreach ($wheels as $wheel_count) {
+ echo $wheel_count;
+} // "24"를 출력
+
+echo "\n";
+
+// 키와 값을 동시에 순회할 수 있습니다.
+foreach ($wheels as $vehicle => $wheel_count) {
+ echo "A $vehicle has $wheel_count wheels";
+}
+
+echo "\n";
+
+$i = 0;
+while ($i < 5) {
+ if ($i === 3) {
+ break; // while 문을 빠져나옴
+ }
+ echo $i++;
+} // "012"를 출력
+
+for ($i = 0; $i < 5; $i++) {
+ if ($i === 3) {
+ continue; // 이번 순회를 생략
+ }
+ echo $i;
+} // "0124"를 출력
+
+
+/********************************
+ * 함수
+ */
+
+// "function"으로 함수를 정의합니다.
+function my_function () {
+ return 'Hello';
+}
+
+echo my_function(); // => "Hello"
+
+// 유효한 함수명은 문자나 밑줄로 시작하고, 이어서
+// 임의 개수의 문자나 숫자, 밑줄이 옵니다.
+
+function add ($x, $y = 1) { // $y는 선택사항이고 기본값은 1입니다.
+ $result = $x + $y;
+ return $result;
+}
+
+echo add(4); // => 5
+echo add(4, 2); // => 6
+
+// 함수 밖에서는 $result에 접근할 수 없습니다.
+// print $result; // 이 코드를 실행하면 경고가 출력됩니다.
+
+// PHP 5.3부터는 익명 함수를 선언할 수 있습니다.
+$inc = function ($x) {
+ return $x + 1;
+};
+
+echo $inc(2); // => 3
+
+function foo ($x, $y, $z) {
+ echo "$x - $y - $z";
+}
+
+// 함수에서는 함수를 반환할 수 있습니다.
+function bar ($x, $y) {
+ // 'use'를 이용해 바깥 함수의 변수를 전달합니다.
+ return function ($z) use ($x, $y) {
+ foo($x, $y, $z);
+ };
+}
+
+$bar = bar('A', 'B');
+$bar('C'); // "A - B - C"를 출력
+
+// 문자열을 이용해 이름이 지정된 함수를 호출할 수 있습니다.
+$function_name = 'add';
+echo $function_name(1, 2); // => 3
+// 프로그램 방식으로 어느 함수를 실행할지 결정할 때 유용합니다.
+// 아니면 call_user_func(callable $callback [, $parameter [, ... ]]);를 사용해도 됩니다.
+
+/********************************
+ * 인클루드
+ */
+
+<?php
+// 인클루드된 파일 내의 PHP 코드도 반드시 PHP 여는 태그로 시작해야 합니다.
+
+include 'my-file.php';
+// my-file.php 안의 코드는 이제 현재 유효범위에서 이용할 수 있습니다.
+// 파일을 인클루드할 수 없으면(예: 파일을 찾을 수 없음) 경고가 출력됩니다.
+
+include_once 'my-file.php';
+// my-file.php 안의 코드가 다른 곳에 인클루드됐다면 다시 인클루드되지는 않습니다.
+// 따라서 클래스 선언이 여러 번 되어 발생하는 문제가 일어나지 않습니다.
+
+require 'my-file.php';
+require_once 'my-file.php';
+// require()는 include()와 같지만 파일을 인클루드할 수 없을 경우
+// 치명적인 오류가 발생한다는 점이 다릅니다.
+
+// my-include.php의 내용
+<?php
+
+return 'Anything you like.';
+// 파일의 끝
+
+// include와 require는 값을 반환할 수도 있습니다.
+$value = include 'my-include.php';
+
+// 파일은 지정된 파일 경로를 토대로 인클루드되거나, 혹은 아무것도 명시하지 않은 경우
+// include_path라는 설정 지시지를 따릅니다. include_path에서 파일을 발견할 수 없으면
+// include는 마지막으로 실패하기 전에 호출 스크립트 자체의 디렉터리와 현재 작업 디렉터리를 확인합니다.
+/* */
+
+/********************************
+ * 클래스
+ */
+
+// 클래스는 class라는 키워드로 정의합니다.
+
+class MyClass
+{
+ const MY_CONST = 'value'; // 상수
+
+ static $staticVar = 'static';
+
+ // 프로퍼티에는 반드시 가시성을 선언해야 합니다.
+ public $property = 'public';
+ public $instanceProp;
+ protected $prot = 'protected'; // 이 클래스와 하위 클래스에서 접근할 수 있음
+ private $priv = 'private'; // 이 클래스 내에서만 접근 가능
+
+ // __construct로 생성자를 만듭니다.
+ public function __construct($instanceProp) {
+ // $this로 인스턴스 변수에 접근합니다.
+ $this->instanceProp = $instanceProp;
+ }
+
+ // 메서드는 클래스 안의 함수로서 선언됩니다.
+ public function myMethod()
+ {
+ print 'MyClass';
+ }
+
+ final function youCannotOverrideMe()
+ {
+ }
+
+ public static function myStaticMethod()
+ {
+ print 'I am static';
+ }
+}
+
+echo MyClass::MY_CONST; // 'value' 출력
+echo MyClass::$staticVar; // 'static' 출력
+MyClass::myStaticMethod(); // 'I am static' 출력
+
+// new를 사용해 클래스를 인스턴스화합니다.
+$my_class = new MyClass('An instance property');
+// 인자를 전달하지 않을 경우 괄호를 생략할 수 있습니다.
+
+// ->를 이용해 클래스 멤버에 접근합니다
+echo $my_class->property; // => "public"
+echo $my_class->instanceProp; // => "An instance property"
+$my_class->myMethod(); // => "MyClass"
+
+
+// "extends"를 이용해 클래스를 확장합니다.
+class MyOtherClass extends MyClass
+{
+ function printProtectedProperty()
+ {
+ echo $this->prot;
+ }
+
+ // 메서드 재정의
+ function myMethod()
+ {
+ parent::myMethod();
+ print ' > MyOtherClass';
+ }
+}
+
+$my_other_class = new MyOtherClass('Instance prop');
+$my_other_class->printProtectedProperty(); // => "protected" 출력
+$my_other_class->myMethod(); // "MyClass > MyOtherClass" 출력
+
+final class YouCannotExtendMe
+{
+}
+
+// "마법 메서드(magic method)"로 설정자 메서드와 접근자 메서드를 만들 수 있습니다.
+class MyMapClass
+{
+ private $property;
+
+ public function __get($key)
+ {
+ return $this->$key;
+ }
+
+ public function __set($key, $value)
+ {
+ $this->$key = $value;
+ }
+}
+
+$x = new MyMapClass();
+echo $x->property; // __get() 메서드를 사용
+$x->property = 'Something'; // __set() 메서드를 사용
+
+// 클래스는 추상화하거나(abstract 키워드를 사용해)
+// 인터페이스를 구현할 수 있습니다(implments 키워드를 사용해).
+// 인터페이스는 interface 키워드로 선언합니다.
+
+interface InterfaceOne
+{
+ public function doSomething();
+}
+
+interface InterfaceTwo
+{
+ public function doSomethingElse();
+}
+
+// 인터페이스는 확장할 수 있습니다.
+interface InterfaceThree extends InterfaceTwo
+{
+ public function doAnotherContract();
+}
+
+abstract class MyAbstractClass implements InterfaceOne
+{
+ public $x = 'doSomething';
+}
+
+class MyConcreteClass extends MyAbstractClass implements InterfaceTwo
+{
+ public function doSomething()
+ {
+ echo $x;
+ }
+
+ public function doSomethingElse()
+ {
+ echo 'doSomethingElse';
+ }
+}
+
+
+// 클래스에서는 하나 이상의 인터페이스를 구현할 수 있습니다.
+class SomeOtherClass implements InterfaceOne, InterfaceTwo
+{
+ public function doSomething()
+ {
+ echo 'doSomething';
+ }
+
+ public function doSomethingElse()
+ {
+ echo 'doSomethingElse';
+ }
+}
+
+
+/********************************
+ * 특성
+ */
+
+// 특성(trait)은 PHP 5.4.0부터 사용 가능하며, "trait"으로 선언합니다.
+
+trait MyTrait
+{
+ public function myTraitMethod()
+ {
+ print 'I have MyTrait';
+ }
+}
+
+class MyTraitfulClass
+{
+ use MyTrait;
+}
+
+$cls = new MyTraitfulClass();
+$cls->myTraitMethod(); // "I have MyTrait"을 출력
+
+
+/********************************
+ * 네임스페이스
+ */
+
+// 이 부분은 별도의 영역인데, 파일에서 처음으로 나타나는 문장은
+// 네임스페이스 선언이어야 하기 때문입니다. 여기서는 그런 경우가 아니라고 가정합니다.
+
+<?php
+
+// 기본적으로 클래스는 전역 네임스페이스에 존재하며,
+// 백슬래시를 이용해 명시적으로 호출할 수 있습니다.
+
+$cls = new \MyClass();
+
+
+
+// 파일에 대한 네임스페이스를 설정합니다.
+namespace My\Namespace;
+
+class MyClass
+{
+}
+
+// (다른 파일에 들어 있는 코드)
+$cls = new My\Namespace\MyClass;
+
+// 또는 다른 네임스페이스 내에서 접근하는 경우
+namespace My\Other\Namespace;
+
+use My\Namespace\MyClass;
+
+$cls = new MyClass();
+
+// 혹은 네임스페이스에 별칭을 붙일 수도 있습니다.
+
+namespace My\Other\Namespace;
+
+use My\Namespace as SomeOtherNamespace;
+
+$cls = new SomeOtherNamespace\MyClass();
+
+*/
+
+```
+
+## 더 자세한 정보
+
+레퍼런스와 커뮤니티 관련 내용은 [공식 PHP 문서](http://www.php.net/manual/)를 참고하세요.
+
+최신 모범 사례에 관심이 있다면 [PHP The Right Way](http://www.phptherightway.com/)를 참고하세요.
+
+PHP를 익히기 전에 다른 훌륭한 패키지 관리자를 지원하는 언어를 사용해본 적이 있다면 [컴포저(Composer)](http://getcomposer.org/)를 확인해 보세요.
+
+공통 표준이 궁금하다면 PHP 프레임워크 상호운용성 그룹의 [PSR 표준](https://github.com/php-fig/fig-standards)을 참고하세요.
diff --git a/ko-kr/python-kr.html.markdown b/ko-kr/python-kr.html.markdown
new file mode 100644
index 00000000..ed377a99
--- /dev/null
+++ b/ko-kr/python-kr.html.markdown
@@ -0,0 +1,484 @@
+---
+language: python
+category: language
+contributors:
+ - ["Louie Dinh", "http://ldinh.ca"]
+filename: learnpython-ko.py
+translators:
+ - ["wikibook", "http://wikibook.co.kr"]
+lang: ko-kr
+---
+
+파이썬은 귀도 반 로섬이 90년대에 만들었습니다. 파이썬은 현존하는 널리 사용되는 언어 중 하나입니다.
+저는 문법적 명료함에 반해 파이썬을 사랑하게 됐습니다. 파이썬은 기본적으로 실행 가능한 의사코드입니다.
+
+피드백 주시면 정말 감사하겠습니다! [@louiedinh](http://twitter.com/louiedinh)나
+louiedinh [at] [구글의 이메일 서비스]를 통해 저에게 연락하시면 됩니다.
+
+참고: 이 글은 구체적으로 파이썬 2.7에 해당하는 내용을 담고 있습니다만
+파이썬 2.x에도 적용할 수 있을 것입니다. 파이썬 3을 다룬 튜토리얼도 곧 나올 테니 기대하세요!
+
+```python
+# 한 줄짜리 주석은 해시로 시작합니다.
+""" 여러 줄 문자열은 "를 세 개 써서 시작할 수 있고,
+ 주석으로 자주 사용됩니다.
+"""
+
+####################################################
+## 1. 기본 자료형과 연산자
+####################################################
+
+# 숫자
+3 #=> 3
+
+# 수학 연산은 예상하신 대로입니다.
+1 + 1 #=> 2
+8 - 1 #=> 7
+10 * 2 #=> 20
+35 / 5 #=> 7
+
+# 나눗셈은 약간 까다롭습니다. 정수로 나눈 다음 결과값을 자동으로 내림합니다.
+5 / 2 #=> 2
+
+# 나눗셈 문제를 해결하려면 float에 대해 알아야 합니다.
+2.0 # 이것이 float입니다.
+11.0 / 4.0 #=> 2.75 훨씬 낫네요
+
+# 괄호를 이용해 연산자 우선순위를 지정합니다.
+(1 + 3) * 2 #=> 8
+
+# 불린(Boolean) 값은 기본형입니다.
+True
+False
+
+# not을 이용해 부정합니다.
+not True #=> False
+not False #=> True
+
+# 동일성 연산자는 ==입니다.
+1 == 1 #=> True
+2 == 1 #=> False
+
+# 불일치 연산자는 !=입니다.
+1 != 1 #=> False
+2 != 1 #=> True
+
+# 그밖의 비교 연산자는 다음과 같습니다.
+1 < 10 #=> True
+1 > 10 #=> False
+2 <= 2 #=> True
+2 >= 2 #=> True
+
+# 비교 연산을 연결할 수도 있습니다!
+1 < 2 < 3 #=> True
+2 < 3 < 2 #=> False
+
+# 문자열은 "나 '로 생성합니다.
+"This is a string."
+'This is also a string.'
+
+# 문자열도 연결할 수 있습니다!
+"Hello " + "world!" #=> "Hello world!"
+
+# 문자열은 문자로 구성된 리스트로 간주할 수 있습니다.
+"This is a string"[0] #=> 'T'
+
+# %는 다음과 같이 문자열을 형식화하는 데 사용할 수 있습니다:
+"%s can be %s" % ("strings", "interpolated")
+
+# 문자열을 형식화하는 새로운 방법은 format 메서드를 이용하는 것입니다.
+# 이 메서드를 이용하는 방법이 더 선호됩니다.
+"{0} can be {1}".format("strings", "formatted")
+# 자릿수를 세기 싫다면 키워드를 이용해도 됩니다.
+"{name} wants to eat {food}".format(name="Bob", food="lasagna")
+
+# None은 객체입니다.
+None #=> None
+
+# 객체와 None을 비교할 때는 동일성 연산자인 `==`를 사용해서는 안 됩니다.
+# 대신 `is`를 사용하세요.
+"etc" is None #=> False
+None is None #=> True
+
+# 'is' 연산자는 객체의 식별자를 검사합니다.
+# 기본형 값을 다룰 때는 이 연산자가 그다지 유용하지 않지만
+# 객체를 다룰 때는 매우 유용합니다.
+
+# None, 0, 빈 문자열/리스트는 모두 False로 평가됩니다.
+# 그밖의 다른 값은 모두 True입니다
+0 == False #=> True
+"" == False #=> True
+
+
+####################################################
+## 2. 변수와 컬렉션
+####################################################
+
+# 뭔가를 출력하는 것은 상당히 쉽습니다.
+print "I'm Python. Nice to meet you!"
+
+
+# 변수에 값을 할당하기 전에 변수를 반드시 선언하지 않아도 됩니다.
+some_var = 5 # 명명관례는 '밑줄이_포함된_소문자'입니다.
+some_var #=> 5
+
+# 미할당된 변수에 접근하면 예외가 발생합니다.
+# 예외 처리에 관해서는 '제어 흐름'을 참고하세요.
+some_other_var # 이름 오류가 발생
+
+# 표현식으로도 사용할 수 있습니다.
+"yahoo!" if 3 > 2 else 2 #=> "yahoo!"
+
+# 리스트는 순차 항목을 저장합니다.
+li = []
+# 미리 채워진 리스트로 시작할 수도 있습니다.
+other_li = [4, 5, 6]
+
+# append를 이용해 리스트 끝에 항목을 추가합니다.
+li.append(1) #li는 이제 [1]입니다.
+li.append(2) #li는 이제 [1, 2]입니다.
+li.append(4) #li는 이제 [1, 2, 4]입니다.
+li.append(3) #li는 이제 [1, 2, 4, 3]입니다.
+# pop을 이용해 끝에서부터 항목을 제거합니다.
+li.pop() #=> 3이 반환되고 li는 이제 [1, 2, 4]입니다.
+# 다시 넣어봅시다
+li.append(3) # li는 이제 다시 [1, 2, 4, 3]가 됩니다.
+
+# 배열에서 했던 것처럼 리스트에도 접근할 수 있습니다.
+li[0] #=> 1
+# 마지막 요소를 봅시다.
+li[-1] #=> 3
+
+# 범위를 벗어나서 접근하면 IndexError가 발생합니다.
+li[4] # IndexError가 발생
+
+# 슬라이스 문법을 통해 범위를 지정해서 값을 조회할 수 있습니다.
+# (이 문법을 통해 간편하게 범위를 지정할 수 있습니다.)
+li[1:3] #=> [2, 4]
+# 앞부분을 생략합니다.
+li[2:] #=> [4, 3]
+# 끝부분을 생략합니다.
+li[:3] #=> [1, 2, 4]
+
+# del로 임의의 요소를 제거할 수 있습니다.
+del li[2] # li is now [1, 2, 3]
+
+# 리스트를 추가할 수도 있습니다.
+li + other_li #=> [1, 2, 3, 4, 5, 6] - 참고: li와 other_li는 그대로 유지됩니다.
+
+# extend로 리스트를 연결합니다.
+li.extend(other_li) # 이제 li는 [1, 2, 3, 4, 5, 6]입니다.
+
+# in으로 리스트 안에서 특정 요소가 존재하는지 확인합니다.
+1 in li #=> True
+
+# len으로 길이를 검사합니다.
+len(li) #=> 6
+
+# 튜플은 리스트와 비슷하지만 불변성을 띱니다.
+tup = (1, 2, 3)
+tup[0] #=> 1
+tup[0] = 3 # TypeError가 발생
+
+# 튜플에 대해서도 리스트에서 할 수 있는 일들을 모두 할 수 있습니다.
+len(tup) #=> 3
+tup + (4, 5, 6) #=> (1, 2, 3, 4, 5, 6)
+tup[:2] #=> (1, 2)
+2 in tup #=> True
+
+# 튜플(또는 리스트)을 변수로 풀 수 있습니다.
+a, b, c = (1, 2, 3) # 이제 a는 1, b는 2, c는 3입니다
+# 괄호를 빼면 기본적으로 튜플이 만들어집니다.
+d, e, f = 4, 5, 6
+# 이제 두 값을 바꾸는 게 얼마나 쉬운지 확인해 보세요.
+e, d = d, e # 이제 d는 5이고 e는 4입니다.
+
+# 딕셔너리는 매핑을 저장합니다.
+empty_dict = {}
+# 다음은 값을 미리 채운 딕셔너리입니다.
+filled_dict = {"one": 1, "two": 2, "three": 3}
+
+# []를 이용해 값을 조회합니다.
+filled_dict["one"] #=> 1
+
+# 모든 키를 리스트로 구합니다.
+filled_dict.keys() #=> ["three", "two", "one"]
+# 참고 - 딕셔너리 키의 순서는 보장되지 않습니다.
+# 따라서 결과가 이와 정확히 일치하지 않을 수도 있습니다.
+
+# 모든 값을 리스트로 구합니다.
+filled_dict.values() #=> [3, 2, 1]
+# 참고 - 키 순서와 관련해서 위에서 설명한 내용과 같습니다.
+
+# in으로 딕셔너리 안에 특정 키가 존재하는지 확인합니다.
+"one" in filled_dict #=> True
+1 in filled_dict #=> False
+
+# 존재하지 않는 키를 조회하면 KeyError가 발생합니다.
+filled_dict["four"] # KeyError
+
+# get 메서드를 이용하면 KeyError가 발생하지 않습니다.
+filled_dict.get("one") #=> 1
+filled_dict.get("four") #=> None
+# get 메서드는 값이 누락된 경우 기본 인자를 지원합니다.
+filled_dict.get("one", 4) #=> 1
+filled_dict.get("four", 4) #=> 4
+
+# setdefault 메서드는 딕셔너리에 새 키-값 쌍을 추가하는 안전한 방법입니다.
+filled_dict.setdefault("five", 5) #filled_dict["five"]는 5로 설정됩니다.
+filled_dict.setdefault("five", 6) #filled_dict["five"]는 여전히 5입니다.
+
+
+# 세트는 집합을 저장합니다.
+empty_set = set()
+# 다수의 값으로 세트를 초기화합니다.
+some_set = set([1,2,2,3,4]) # 이제 some_set는 set([1, 2, 3, 4])입니다.
+
+# 파이썬 2.7부터는 {}를 세트를 선언하는 데 사용할 수 있습니다.
+filled_set = {1, 2, 2, 3, 4} # => {1 2 3 4}
+
+# 세트에 항목을 추가합니다.
+filled_set.add(5) # 이제 filled_set는 {1, 2, 3, 4, 5}입니다.
+
+# &을 이용해 교집합을 만듭니다.
+other_set = {3, 4, 5, 6}
+filled_set & other_set #=> {3, 4, 5}
+
+# |를 이용해 합집합을 만듭니다.
+filled_set | other_set #=> {1, 2, 3, 4, 5, 6}
+
+# -를 이용해 차집합을 만듭니다.
+{1,2,3,4} - {2,3,5} #=> {1, 4}
+
+# in으로 세트 안에 특정 요소가 존재하는지 검사합니다.
+2 in filled_set #=> True
+10 in filled_set #=> False
+
+
+####################################################
+## 3. 제어 흐름
+####################################################
+
+# 변수를 만들어 봅시다.
+some_var = 5
+
+# 다음은 if 문입니다. 파이썬에서는 들여쓰기가 대단히 중요합니다!
+# 다음 코드를 실행하면 "some_var is smaller than 10"가 출력됩니다.
+if some_var > 10:
+ print "some_var is totally bigger than 10."
+elif some_var < 10: # elif 절은 선택사항입니다.
+ print "some_var is smaller than 10."
+else: # 이 부분 역시 선택사항입니다.
+ print "some_var is indeed 10."
+
+
+"""
+for 루프는 리스트를 순회합니다.
+아래 코드는 다음과 같은 내용을 출력합니다:
+ dog is a mammal
+ cat is a mammal
+ mouse is a mammal
+"""
+for animal in ["dog", "cat", "mouse"]:
+ # %로 형식화된 문자열에 값을 채워넣을 수 있습니다.
+ print "%s is a mammal" % animal
+
+"""
+`range(number)`는 숫자 리스트를 반환합니다.
+이때 숫자 리스트의 범위는 0에서 지정한 숫자까지입니다.
+아래 코드는 다음과 같은 내용을 출력합니다:
+ 0
+ 1
+ 2
+ 3
+"""
+for i in range(4):
+ print i
+
+"""
+while 루프는 조건이 더는 충족되지 않을 때까지 진행됩니다.
+prints:
+ 0
+ 1
+ 2
+ 3
+"""
+x = 0
+while x < 4:
+ print x
+ x += 1 # x = x + 1의 축약형
+
+# try/except 블록을 이용한 예외 처리
+
+# 파이썬 2.6 및 상위 버전에서 동작하는 코드
+try:
+ # raise를 이용해 오류를 발생시킵니다
+ raise IndexError("This is an index error")
+except IndexError as e:
+ pass # pass는 단순 no-op 연산입니다. 보통 이곳에 복구 코드를 작성합니다.
+
+
+####################################################
+## 4. 함수
+####################################################
+
+# 새 함수를 만들 때 def를 사용합니다.
+def add(x, y):
+ print "x is %s and y is %s" % (x, y)
+ return x + y # return 문을 이용해 값을 반환합니다.
+
+# 매개변수를 전달하면서 함수를 호출
+add(5, 6) #=> "x is 5 and y is 6"가 출력되고 11이 반환됨
+
+# 함수를 호출하는 또 다른 방법은 키워드 인자를 지정하는 방법입니다.
+add(y=6, x=5) # 키워드 인자는 순서에 구애받지 않습니다.
+
+# 위치 기반 인자를 임의 개수만큼 받는 함수를 정의할 수 있습니다.
+def varargs(*args):
+ return args
+
+varargs(1, 2, 3) #=> (1,2,3)
+
+
+# 키워드 인자를 임의 개수만큼 받는 함수 또한 정의할 수 있습니다.
+def keyword_args(**kwargs):
+ return kwargs
+
+# 이 함수를 호출해서 어떤 일이 일어나는지 확인해 봅시다.
+keyword_args(big="foot", loch="ness") #=> {"big": "foot", "loch": "ness"}
+
+# 원한다면 한 번에 두 가지 종류의 인자를 모두 받는 함수를 정의할 수도 있습니다.
+def all_the_args(*args, **kwargs):
+ print args
+ print kwargs
+"""
+all_the_args(1, 2, a=3, b=4)를 실행하면 다음과 같은 내용이 출력됩니다:
+ (1, 2)
+ {"a": 3, "b": 4}
+"""
+
+# 함수를 호출할 때 varargs/kwargs와 반대되는 일을 할 수 있습니다!
+# *를 이용해 튜플을 확장하고 **를 이용해 kwargs를 확장합니다.
+args = (1, 2, 3, 4)
+kwargs = {"a": 3, "b": 4}
+all_the_args(*args) # foo(1, 2, 3, 4)와 같음
+all_the_args(**kwargs) # foo(a=3, b=4)와 같음
+all_the_args(*args, **kwargs) # foo(1, 2, 3, 4, a=3, b=4)와 같음
+
+# 파이썬에는 일급 함수가 있습니다
+def create_adder(x):
+ def adder(y):
+ return x + y
+ return adder
+
+add_10 = create_adder(10)
+add_10(3) #=> 13
+
+# 게다가 익명 함수도 있습니다.
+(lambda x: x > 2)(3) #=> True
+
+# 내장된 고차 함수(high order function)도 있습니다.
+map(add_10, [1,2,3]) #=> [11, 12, 13]
+filter(lambda x: x > 5, [3, 4, 5, 6, 7]) #=> [6, 7]
+
+# 맵과 필터에 리스트 조건 제시법(list comprehensions)을 사용할 수 있습니다.
+[add_10(i) for i in [1, 2, 3]] #=> [11, 12, 13]
+[x for x in [3, 4, 5, 6, 7] if x > 5] #=> [6, 7]
+
+####################################################
+## 5. 클래스
+####################################################
+
+# 클래스를 하나 만들기 위해 특정 객체의 하위 클래스를 만들 수 있습니다.
+class Human(object):
+
+ # 클래스 속성은 이 클래스의 모든 인스턴스에서 공유합니다.
+ species = "H. sapiens"
+
+ # 기본 초기화자
+ def __init__(self, name):
+ # 인자를 인스턴스의 name 속성에 할당합니다.
+ self.name = name
+
+ # 모든 인스턴스 메서드에서는 self를 첫 번째 인자로 받습니다.
+ def say(self, msg):
+ return "%s: %s" % (self.name, msg)
+
+ # 클래스 메서드는 모든 인스턴스에서 공유합니다.
+ # 클래스 메서드는 호출하는 클래스를 첫 번째 인자로 호출됩니다.
+ @classmethod
+ def get_species(cls):
+ return cls.species
+
+ # 정적 메서드는 클래스나 인스턴스 참조 없이도 호출할 수 있습니다.
+ @staticmethod
+ def grunt():
+ return "*grunt*"
+
+
+# 클래스 인스턴스화
+i = Human(name="Ian")
+print i.say("hi") # "Ian: hi"가 출력됨
+
+j = Human("Joel")
+print j.say("hello") # "Joel: hello"가 출력됨
+
+# 클래스 메서드를 호출
+i.get_species() #=> "H. sapiens"
+
+# 공유 속성을 변경
+Human.species = "H. neanderthalensis"
+i.get_species() #=> "H. neanderthalensis"
+j.get_species() #=> "H. neanderthalensis"
+
+# 정적 메서드를 호출
+Human.grunt() #=> "*grunt*"
+
+
+####################################################
+## 6. 모듈
+####################################################
+
+# 다음과 같이 모듈을 임포트할 수 있습니다.
+import math
+print math.sqrt(16) #=> 4
+
+# 모듈의 특정 함수를 호출할 수 있습니다.
+from math import ceil, floor
+print ceil(3.7) #=> 4.0
+print floor(3.7) #=> 3.0
+
+# 모듈의 모든 함수를 임포트할 수 있습니다.
+# Warning: this is not recommended
+from math import *
+
+# 모듈 이름을 축약해서 쓸 수 있습니다.
+import math as m
+math.sqrt(16) == m.sqrt(16) #=> True
+
+# 파이썬 모듈은 평범한 파이썬 파일에 불과합니다.
+# 직접 모듈을 작성해서 그것들을 임포트할 수 있습니다.
+# 모듈의 이름은 파일의 이름과 같습니다.
+
+# 다음과 같은 코드로 모듈을 구성하는 함수와 속성을 확인할 수 있습니다.
+import math
+dir(math)
+
+
+```
+
+## 더 배울 준비가 되셨습니까?
+
+### 무료 온라인 참고자료
+
+* [Learn Python The Hard Way](http://learnpythonthehardway.org/book/)
+* [Dive Into Python](http://www.diveintopython.net/)
+* [The Official Docs](http://docs.python.org/2.6/)
+* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
+* [Python Module of the Week](http://pymotw.com/2/)
+
+### 파이썬 관련 도서
+
+* [Programming Python](http://www.amazon.com/gp/product/0596158106/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596158106&linkCode=as2&tag=homebits04-20)
+* [Dive Into Python](http://www.amazon.com/gp/product/1441413022/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1441413022&linkCode=as2&tag=homebits04-20)
+* [Python Essential Reference](http://www.amazon.com/gp/product/0672329786/ref=as_li_tf_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0672329786&linkCode=as2&tag=homebits04-20)
diff --git a/ko-kr/racket-kr.html.markdown b/ko-kr/racket-kr.html.markdown
new file mode 100644
index 00000000..8d830279
--- /dev/null
+++ b/ko-kr/racket-kr.html.markdown
@@ -0,0 +1,640 @@
+---
+
+language: racket
+filename: learnracket-kr.rkt
+contributors:
+ - ["th3rac25", "https://github.com/voila"]
+ - ["Eli Barzilay", "https://github.com/elibarzilay"]
+ - ["Gustavo Schmidt", "https://github.com/gustavoschmidt"]
+ - ["Duong H. Nguyen", "https://github.com/cmpitg"]
+translators:
+ - ["KIM Taegyoon", "https://github.com/kimtg"]
+lang: ko-kr
+---
+
+Racket 은 Lisp/Scheme 계열의 일반 목적의, 다중 패러다임 프로그래밍 언어이다.
+
+```racket
+#lang racket ; 우리가 사용하는 언어를 정의한다.
+
+;;; 주석
+
+;; 한 줄 주석은 세미콜론으로 시작한다.
+
+#| 블록 주석
+ 은 여러 줄에 걸칠 수 있으며...
+ #|
+ 중첩될 수 있다!
+ |#
+|#
+
+;; S-expression 주석은 아래 식을 버리므로,
+;; 디버깅할 때 식을 주석화할 때 유용하다.
+#; (이 식은 버려짐)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 1. 근본 자료형과 연산자
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; 숫자
+9999999999999999999999 ; 정수
+#b111 ; 이진수 => 7
+#o111 ; 팔진수 => 73
+#x111 ; 16진수 => 273
+3.14 ; 실수
+6.02e+23
+1/2 ; 분수
+1+2i ; 복소수
+
+;; 함수 적용은 이렇게 쓴다: (f x y z ...)
+;; 여기에서 f는 함수이고 x, y, z는 피연산자이다.
+;; 글자 그대로의 데이터 리스트를 만들고 싶다면 평가를 막기 위해 '를 쓰시오.
+'(+ 1 2) ; => (+ 1 2)
+;; 이제, 산술 연산 몇 개
+(+ 1 1) ; => 2
+(- 8 1) ; => 7
+(* 10 2) ; => 20
+(expt 2 3) ; => 8
+(quotient 5 2) ; => 2
+(remainder 5 2) ; => 1
+(/ 35 5) ; => 7
+(/ 1 3) ; => 1/3
+(exact->inexact 1/3) ; => 0.3333333333333333
+(+ 1+2i 2-3i) ; => 3-1i
+
+;;; 불린
+#t ; 참
+#f ; 거짓 -- #f가 아닌 것은 참
+(not #t) ; => #f
+(and 0 #f (error "doesn't get here")) ; => #f
+(or #f 0 (error "doesn't get here")) ; => 0
+
+;;; 문자
+#\A ; => #\A
+#\λ ; => #\λ
+#\u03BB ; => #\λ
+
+;;; 문자열은 고정 길이의 문자 배열이다.
+"Hello, world!"
+"Benjamin \"Bugsy\" Siegel" ; 백슬래시는 탈출 문자이다.
+"Foo\tbar\41\x21\u0021\a\r\n" ; C 탈출 문자, 유니코드 포함
+"λx:(μα.α→α).xx" ; 유니코드 문자 포함 가능
+
+;; 문자열은 붙여질 수 있다!
+(string-append "Hello " "world!") ; => "Hello world!"
+
+;; 문자열은 문자의 리스트처럼 취급될 수 있다.
+(string-ref "Apple" 0) ; => #\A
+
+;; format은 문자열을 형식화하기 위해 사용된다:
+(format "~a can be ~a" "strings" "formatted")
+
+;; 인쇄는 쉽다.
+(printf "I'm Racket. Nice to meet you!\n")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 2. 변수
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; define으로 변수를 만든다.
+;; 변수명으로 다음 문자를 사용할 수 없다: ()[]{}",'`;#|\
+(define some-var 5)
+some-var ; => 5
+
+;; 유니코드 문자도 사용 가능하다.
+(define ⊆ subset?)
+(⊆ (set 3 2) (set 1 2 3)) ; => #t
+
+;; 앞에서 정의되지 않은 변수에 접근하면 예외가 발생한다.
+; x ; => x: undefined ...
+
+;; 지역 변수: `me'는 (let ...) 안에서만 "Bob"이다.
+(let ([me "Bob"])
+ "Alice"
+ me) ; => "Bob"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. 구조체(Struct)와 모음(Collection)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 구조체
+(struct dog (name breed age))
+(define my-pet
+ (dog "lassie" "collie" 5))
+my-pet ; => #<dog>
+(dog? my-pet) ; => #t
+(dog-name my-pet) ; => "lassie"
+
+;;; 쌍 (불변)
+;; `cons'는 쌍을 만들고, `car'와 `cdr'는 첫번째와
+;; 두번째 원소를 추출한다.
+(cons 1 2) ; => '(1 . 2)
+(car (cons 1 2)) ; => 1
+(cdr (cons 1 2)) ; => 2
+
+;;; 리스트
+
+;; 리스트는 연결-리스트 데이터 구조이며, `cons' 쌍으로 만들어지며
+;; `null' (또는 '()) 로 리스트의 끝을 표시한다.
+(cons 1 (cons 2 (cons 3 null))) ; => '(1 2 3)
+;; `list'는 편리한 가변인자 리스트 생성자이다.
+(list 1 2 3) ; => '(1 2 3)
+;; 글자 그대로의 리스트 값에는 인용부호를 쓴다.
+'(1 2 3) ; => '(1 2 3)
+
+;; 리스트의 앞에 항목을 추가하기 위하여 `cons'를 사용한다.
+(cons 4 '(1 2 3)) ; => '(4 1 2 3)
+
+;; 리스트들을 붙이기 위해 `append'를 사용한다.
+(append '(1 2) '(3 4)) ; => '(1 2 3 4)
+
+;; 리스트는 매우 기본적인 자료형이기 때문에, 리스트에 대해 적용되는 많은 기능들이 있다.
+;; 예를 들어:
+(map add1 '(1 2 3)) ; => '(2 3 4)
+(map + '(1 2 3) '(10 20 30)) ; => '(11 22 33)
+(filter even? '(1 2 3 4)) ; => '(2 4)
+(count even? '(1 2 3 4)) ; => 2
+(take '(1 2 3 4) 2) ; => '(1 2)
+(drop '(1 2 3 4) 2) ; => '(3 4)
+
+;;; 벡터
+
+;; 벡터는 고정 길이의 배열이다.
+#(1 2 3) ; => '#(1 2 3)
+
+;; `vector-append'를 사용하여 벡터들을 붙인다.
+(vector-append #(1 2 3) #(4 5 6)) ; => #(1 2 3 4 5 6)
+
+;;; 집합
+
+;; 리스트로부터 집합 만들기
+(list->set '(1 2 3 1 2 3 3 2 1 3 2 1)) ; => (set 1 2 3)
+
+;; 원소를 추가하려면 `set-add'를 사용한다.
+;; (함수적: 확장된 집합을 반환하며, 원래의 입력을 변경하지 않는다.)
+(set-add (set 1 2 3) 4) ; => (set 1 2 3 4)
+
+;; 원소를 삭제하려면 `set-remove'
+(set-remove (set 1 2 3) 1) ; => (set 2 3)
+
+;; 존재 여부를 조사하려면 `set-member?'
+(set-member? (set 1 2 3) 1) ; => #t
+(set-member? (set 1 2 3) 4) ; => #f
+
+;;; 해시
+
+;; 불변의 해시 테이블을 만든다. (가변 예제는 아래에)
+(define m (hash 'a 1 'b 2 'c 3))
+
+;; 값 꺼내기
+(hash-ref m 'a) ; => 1
+
+;; 없는 값을 꺼내는 것은 예외를 발생시킨다.
+; (hash-ref m 'd) => no value found
+
+;; 키가 없을 때 반환할 기본값을 지정할 수 있다.
+(hash-ref m 'd 0) ; => 0
+
+;; `hash-set'을 사용하여 불변의 해시 테이블을 확장
+;; (원래 것을 변경하지 않고 확장된 해시를 반환한다.)
+(define m2 (hash-set m 'd 4))
+m2 ; => '#hash((b . 2) (a . 1) (d . 4) (c . 3))
+
+;; 이 해시들은 불변이라는 점을 기억하시오!
+m ; => '#hash((b . 2) (a . 1) (c . 3)) <-- no `d'
+
+;; `hash-remove'로 키를 삭제 (이것도 함수적)
+(hash-remove m 'a) ; => '#hash((b . 2) (c . 3))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 3. 함수
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; `lambda'로 함수를 만든다.
+;; 함수는 항상 마지막 식을 반환한다.
+(lambda () "Hello World") ; => #<procedure>
+;; 유니코드 `λ'도 사용 가능
+(λ () "Hello World") ; => same function
+
+;; 모든 함수를 호출할 때는 괄호를 쓴다, lambda 식도 포함하여.
+((lambda () "Hello World")) ; => "Hello World"
+((λ () "Hello World")) ; => "Hello World"
+
+;; 변수에 함수를 할당
+(define hello-world (lambda () "Hello World"))
+(hello-world) ; => "Hello World"
+
+;; 문법적 설탕을 사용하여 함수 정의를 더 짧게할 수 있다:
+(define (hello-world2) "Hello World")
+
+;; 위에서 ()는 함수의 인자 리스트이다.
+(define hello
+ (lambda (name)
+ (string-append "Hello " name)))
+(hello "Steve") ; => "Hello Steve"
+;; ... 또는, 설탕 친 정의로:
+(define (hello2 name)
+ (string-append "Hello " name))
+
+;; 가변인자 함수에는 `case-lambda'를 사용한다.
+(define hello3
+ (case-lambda
+ [() "Hello World"]
+ [(name) (string-append "Hello " name)]))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+;; ... 또는 선택적 인자에 기본값 지정
+(define (hello4 [name "World"])
+ (string-append "Hello " name))
+
+;; 함수는 추가 인자를 리스트에 포장할 수 있다.
+(define (count-args . args)
+ (format "You passed ~a args: ~a" (length args) args))
+(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+;; ... 설탕 안 친 `lambda' 형식으로는:
+(define count-args2
+ (lambda args
+ (format "You passed ~a args: ~a" (length args) args)))
+
+;; 일반 인자와 포장된 인자를 섞을 수 있다.
+(define (hello-count name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args)))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, you passed 3 extra args"
+;; ... 설탕 안 친 것:
+(define hello-count2
+ (lambda (name . args)
+ (format "Hello ~a, you passed ~a extra args" name (length args))))
+
+;; 키워드 인자
+(define (hello-k #:name [name "World"] #:greeting [g "Hello"] . args)
+ (format "~a ~a, ~a extra args" g name (length args)))
+(hello-k) ; => "Hello World, 0 extra args"
+(hello-k 1 2 3) ; => "Hello World, 3 extra args"
+(hello-k #:greeting "Hi") ; => "Hi World, 0 extra args"
+(hello-k #:name "Finn" #:greeting "Hey") ; => "Hey Finn, 0 extra args"
+(hello-k 1 2 3 #:greeting "Hi" #:name "Finn" 4 5 6)
+ ; => "Hi Finn, 6 extra args"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 4. 동등성
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 숫자에는 `='를 사용하시오.
+(= 3 3.0) ; => #t
+(= 2 1) ; => #f
+
+;; 개체의 동등성에는 `eq?'를 사용하시오.
+(eq? 3 3) ; => #t
+(eq? 3 3.0) ; => #f
+(eq? (list 3) (list 3)) ; => #f
+
+;; 모음에는 `equal?'을 사용하시오.
+(equal? (list 'a 'b) (list 'a 'b)) ; => #t
+(equal? (list 'a 'b) (list 'b 'a)) ; => #f
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 5. 흐름 제어하기
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;; 조건
+
+(if #t ; 조사 식
+ "this is true" ; 그러면 식
+ "this is false") ; 아니면 식
+; => "this is true"
+
+;; 조건에서는 #f가 아니면 참으로 취급된다.
+(member 'Groucho '(Harpo Groucho Zeppo)) ; => '(Groucho Zeppo)
+(if (member 'Groucho '(Harpo Groucho Zeppo))
+ 'yep
+ 'nope)
+; => 'yep
+
+;; `cond'는 연속하여 조사하여 값을 선택한다.
+(cond [(> 2 2) (error "wrong!")]
+ [(< 2 2) (error "wrong again!")]
+ [else 'ok]) ; => 'ok
+
+;;; 양식 맞춤
+
+(define (fizzbuzz? n)
+ (match (list (remainder n 3) (remainder n 5))
+ [(list 0 0) 'fizzbuzz]
+ [(list 0 _) 'fizz]
+ [(list _ 0) 'buzz]
+ [_ #f]))
+
+(fizzbuzz? 15) ; => 'fizzbuzz
+(fizzbuzz? 37) ; => #f
+
+;;; 반복
+
+;; 반복은 (꼬리-) 재귀로 한다.
+(define (loop i)
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i))))
+(loop 5) ; => i=5, i=6, ...
+
+;; 이름 있는 let으로도...
+(let loop ((i 0))
+ (when (< i 10)
+ (printf "i=~a\n" i)
+ (loop (add1 i)))) ; => i=0, i=1, ...
+
+;; Racket은 매우 유연한 `for' 형식을 가지고 있다:
+(for ([i 10])
+ (printf "i=~a\n" i)) ; => i=0, i=1, ...
+(for ([i (in-range 5 10)])
+ (printf "i=~a\n" i)) ; => i=5, i=6, ...
+
+;;; 다른 Sequence들을 순회하는 반복
+;; `for'는 여러 가지의 sequence를 순회할 수 있다:
+;; 리스트, 벡터, 문자열, 집합, 해시 테이블 등...
+
+(for ([i (in-list '(l i s t))])
+ (displayln i))
+
+(for ([i (in-vector #(v e c t o r))])
+ (displayln i))
+
+(for ([i (in-string "string")])
+ (displayln i))
+
+(for ([i (in-set (set 'x 'y 'z))])
+ (displayln i))
+
+(for ([(k v) (in-hash (hash 'a 1 'b 2 'c 3 ))])
+ (printf "key:~a value:~a\n" k v))
+
+;;; 더 복잡한 반복
+
+;; 여러 sequence에 대한 병렬 순회 (가장 짧은 것 기준으로 중단)
+(for ([i 10] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x 1:y 2:z
+
+;; 중첩 반복
+(for* ([i 2] [j '(x y z)]) (printf "~a:~a\n" i j))
+; => 0:x, 0:y, 0:z, 1:x, 1:y, 1:z
+
+;; 조건
+(for ([i 1000]
+ #:when (> i 5)
+ #:unless (odd? i)
+ #:break (> i 10))
+ (printf "i=~a\n" i))
+; => i=6, i=8, i=10
+
+;;; 함축
+;; `for' 반복과 비슷하며, 결과만 수집한다.
+
+(for/list ([i '(1 2 3)])
+ (add1 i)) ; => '(2 3 4)
+
+(for/list ([i '(1 2 3)] #:when (even? i))
+ i) ; => '(2)
+
+(for/list ([i 10] [j '(x y z)])
+ (list i j)) ; => '((0 x) (1 y) (2 z))
+
+(for/list ([i 1000] #:when (> i 5) #:unless (odd? i) #:break (> i 10))
+ i) ; => '(6 8 10)
+
+(for/hash ([i '(1 2 3)])
+ (values i (number->string i)))
+; => '#hash((1 . "1") (2 . "2") (3 . "3"))
+
+;; 반복의 값을 수집하는 여러 가지 방법이 있다:
+(for/sum ([i 10]) (* i i)) ; => 285
+(for/product ([i (in-range 1 11)]) (* i i)) ; => 13168189440000
+(for/and ([i 10] [j (in-range 10 20)]) (< i j)) ; => #t
+(for/or ([i 10] [j (in-range 0 20 2)]) (= i j)) ; => #t
+;; 임의의 조합을 사용하려면 `for/fold'를 사용:
+(for/fold ([sum 0]) ([i '(1 2 3 4)]) (+ sum i)) ; => 10
+;; (이것은 명령형 반복문을 대체하기도 한다.)
+
+;;; 예외
+
+;; 예외를 잡으려면 `with-handlers' 형식을 사용
+(with-handlers ([exn:fail? (lambda (exn) 999)])
+ (+ 1 "2")) ; => 999
+(with-handlers ([exn:break? (lambda (exn) "no time")])
+ (sleep 3)
+ "phew") ; => "phew", but if you break it => "no time"
+
+;; 예외나 다른 값을 던지려면 `raise'를 사용
+(with-handlers ([number? ; catch numeric values raised
+ identity]) ; return them as plain values
+ (+ 1 (raise 2))) ; => 2
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 6. 변경
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 기존 변수에 새 값을 할당하려면 `set!'을 사용한다.
+(define n 5)
+(set! n (add1 n))
+n ; => 6
+
+;; 명시적인 가변 값을 사용하려면 box 사용 (다른 언어의 포인터나 참조와 비슷함)
+(define n* (box 5))
+(set-box! n* (add1 (unbox n*)))
+(unbox n*) ; => 6
+
+;; 많은 Racket 자료형은 불변이다 (쌍, 리스트 등). 그러나 어떤 것들은
+;; 가변과 불변형이 둘 다 있다. (string, vector, hash table 등)
+
+;; `vector'나 `make-vector'로 가변 벡터를 생성한다.
+(define vec (vector 2 2 3 4))
+(define wall (make-vector 100 'bottle-of-beer))
+;; 칸을 변경하려면 vector-set!을 사용한다.
+(vector-set! vec 0 1)
+(vector-set! wall 99 'down)
+vec ; => #(1 2 3 4)
+
+;; 비어 있는 가변 해시 테이블을 만들고 조작한다.
+(define m3 (make-hash))
+(hash-set! m3 'a 1)
+(hash-set! m3 'b 2)
+(hash-set! m3 'c 3)
+(hash-ref m3 'a) ; => 1
+(hash-ref m3 'd 0) ; => 0
+(hash-remove! m3 'a)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 7. 모듈
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 모듈은 코드를 여러 파일과 재사용 가능한 라이브러리로 조직하게 한다.
+;; 여기서 우리는 서브-모듈을 사용한다. 이 글이 만드는 전체 모듈("lang" 줄 부터 시작)에 포함된 모듈이다.
+
+(module cake racket/base ; racket/base 기반의 `cake' 모듈 정의
+
+ (provide print-cake) ; 모듈이 노출(export)시키는 함수
+
+ (define (print-cake n)
+ (show " ~a " n #\.)
+ (show " .-~a-. " n #\|)
+ (show " | ~a | " n #\space)
+ (show "---~a---" n #\-))
+
+ (define (show fmt n ch) ; 내부 함수
+ (printf fmt (make-string n ch))
+ (newline)))
+
+;; `require'를 사용하여 모듈에서 모든 `provide'된 이름을 사용한다.
+(require 'cake) ; '는 지역 지역 서브-모듈을 위한 것이다.
+(print-cake 3)
+; (show "~a" 1 #\A) ; => 에러, `show'가 export되지 않았음
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 8. 클래스와 개체
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 클래스 fish%를 생성한다. (-%는 클래스 정의에 쓰이는 관용구)
+(define fish%
+ (class object%
+ (init size) ; 초기화 인자
+ (super-new) ; 상위 클래스 초기화
+ ;; 필드
+ (define current-size size)
+ ;; 공용 메서드
+ (define/public (get-size)
+ current-size)
+ (define/public (grow amt)
+ (set! current-size (+ amt current-size)))
+ (define/public (eat other-fish)
+ (grow (send other-fish get-size)))))
+
+;; fish%의 인스턴스를 생성한다.
+(define charlie
+ (new fish% [size 10]))
+
+;; 개체의 메서드를 호출하기 위해 `send'를 사용한다.
+(send charlie get-size) ; => 10
+(send charlie grow 6)
+(send charlie get-size) ; => 16
+
+;; `fish%'는 보통의 "일급" 값이며, mixin을 줄 수 있다.
+(define (add-color c%)
+ (class c%
+ (init color)
+ (super-new)
+ (define my-color color)
+ (define/public (get-color) my-color)))
+(define colored-fish% (add-color fish%))
+(define charlie2 (new colored-fish% [size 10] [color 'red]))
+(send charlie2 get-color)
+;; 또는, 이름 없이:
+(send (new (add-color fish%) [size 10] [color 'red]) get-color)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 9. 매크로
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 매크로는 언어의 문법을 확장할 수 있게 한다.
+
+;; while 반복문을 추가하자.
+(define-syntax-rule (while condition body ...)
+ (let loop ()
+ (when condition
+ body ...
+ (loop))))
+
+(let ([i 0])
+ (while (< i 10)
+ (displayln i)
+ (set! i (add1 i))))
+
+;; 매크로는 위생적이다. 즉, 기존 변수를 침범할 수 없다.
+(define-syntax-rule (swap! x y) ; -!는 변경의 관용구
+ (let ([tmp x])
+ (set! x y)
+ (set! y tmp)))
+
+(define tmp 2)
+(define other 3)
+(swap! tmp other)
+(printf "tmp = ~a; other = ~a\n" tmp other)
+;; `tmp` 변수는 이름 충돌을 피하기 위해 `tmp_1`로 이름이 변경된다.
+;; (let ([tmp_1 tmp])
+;; (set! tmp other)
+;; (set! other tmp_1))
+
+;; 하지만 그것들은 단지 코드 변형일 뿐이다. 예를 들어:
+(define-syntax-rule (bad-while condition body ...)
+ (when condition
+ body ...
+ (bad-while condition body ...)))
+;; 이 매크로는 엉터리다: 무한 코드를 생성하며,
+;; 이것을 사용하려고 하면 컴파일러가 무한 반복에 빠진다.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 10. 계약(Contract)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; 계약은 모듈에서 노출된 값에 대해 제약을 부여한다.
+
+(module bank-account racket
+ (provide (contract-out
+ [deposit (-> positive? any)] ; 값은 양수여야 함
+ [balance (-> positive?)]))
+
+ (define amount 0)
+ (define (deposit a) (set! amount (+ amount a)))
+ (define (balance) amount)
+ )
+
+(require 'bank-account)
+(deposit 5)
+
+(balance) ; => 5
+
+;; 양수가 아닌 값을 예치하려고 하는 고객은 비난받는다.
+;; (deposit -5) ; => deposit: contract violation
+;; expected: positive?
+;; given: -5
+;; more details....
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 11. 입력과 출력
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Racket은 이 "port"라는 개념이 있다. 이것은 다른 언어의
+;; 파일 서술자 (file descriptor)와 매우 비슷하다.
+
+;; "/tmp/tmp.txt"를 열고 "Hello World"를 기록한다.
+;; 그 파일이 이미 있다면 에러를 발생시킨다.
+(define out-port (open-output-file "/tmp/tmp.txt"))
+(displayln "Hello World" out-port)
+(close-output-port out-port)
+
+;; "/tmp/tmp.txt"에 붙이기
+(define out-port (open-output-file "/tmp/tmp.txt"
+ #:exists 'append))
+(displayln "Hola mundo" out-port)
+(close-output-port out-port)
+
+;; 파일에서 다시 읽기
+(define in-port (open-input-file "/tmp/tmp.txt"))
+(displayln (read-line in-port))
+; => "Hello World"
+(displayln (read-line in-port))
+; => "Hola mundo"
+(close-input-port in-port)
+
+;; 다르게, call-with-output-file을 사용하면, 명시적으로 파일을 닫지 않아도 된다.
+(call-with-output-file "/tmp/tmp.txt"
+ #:exists 'update ; 내용을 다시 쓴다.
+ (λ (out-port)
+ (displayln "World Hello!" out-port)))
+
+;; call-with-input-file은 입력에 대해 같은 방식으로 작동한다.
+(call-with-input-file "/tmp/tmp.txt"
+ (λ (in-port)
+ (displayln (read-line in-port))))
+```
+
+## 더 읽을거리
+
+더 배우고 싶으면, [Getting Started with Racket](http://docs.racket-lang.org/getting-started/)도 보시오.