├── .github
└── workflows
│ ├── deploy.yaml
│ └── release-pdf.yaml
├── .gitignore
├── Boot
├── boot.adoc
├── build.boot
├── build.boot.sample
├── docinfo.html
└── script
├── Collections-and-Sequences
├── collections-and-sequences.adoc
├── docinfo.html
└── subs
│ └── zipper.adoc
├── Design-Patterns
├── coderay-asciidoctor.css
├── design-patterns.adoc
├── docinfo.html
└── sub
│ ├── clojure-and-gof-design-patterns.adoc
│ └── translation.txt
├── Destructuring
├── destructuring.adoc
└── docinfo.html
├── Development-Environments
├── atom.adoc
├── development-environments.adoc
├── docinfo.html
├── emacs.adoc
├── img
│ ├── atom-ink-install.png
│ ├── atom-proto-repl-install.png
│ ├── emacs-clojure-mode.png
│ ├── intellij-cursive-install.png
│ ├── intellij-eval-in-edit.png
│ ├── intellij-eval-in-repl.png
│ ├── intellij-ns-change.png
│ ├── intellij-ns-eval.png
│ ├── intellij-open-new-jdk.png
│ ├── intellij-open-project.png
│ ├── intellij-plugins.png
│ ├── intellij-repl-register-1.png
│ ├── intellij-repl-register-2.png
│ ├── intellij-repl-run.png
│ ├── intellij-select-jdk.png
│ ├── lighttable.png
│ ├── vscode-calva-install.png
│ ├── vscode-eval-in-edit.png
│ ├── vscode-eval-in-repl.png
│ ├── vscode-file-eval.png
│ ├── vscode-repl-connect.png
│ ├── vscode-repl-namespace.png
│ ├── vscode-repl-start.png
│ ├── vscode-start.png
│ ├── windows-appdata-no-show.png
│ └── windows-appdata-show.png
├── intellij.adoc
└── vscode.adoc
├── Flow-Controls
├── docinfo.html
└── flow-controls.adoc
├── Functional-Programming
├── docinfo.html
└── functional-programming.adoc
├── Java-Interoperability
├── docinfo.html
└── java-interoperability.adoc
├── Namespaces-and-Libraries
├── docinfo.html
└── namespaces-and-libraries.adoc
├── Preface
├── docinfo.html
└── preface.adoc
├── README.adoc
├── Simple-Values
├── docinfo.html
├── simple-values.adoc
└── sub
│ ├── numbers.adoc
│ └── strings.adoc
├── Start
├── docinfo.html
└── start.adoc
├── Testing
├── docinfo.html
└── testing.adoc
├── asciidoctor-theme
└── notosansmono-cjk-kr
│ ├── .DS_Store
│ ├── fonts
│ ├── LICENSE
│ ├── notosansmono-cjk-kr-bold.ttf
│ ├── notosansmono-cjk-kr-bold_italic.ttf
│ ├── notosansmono-cjk-kr-italic.ttf
│ └── notosansmono-cjk-kr-normal.ttf
│ └── themes
│ ├── LICENSE
│ ├── LICENSE-asciidoctor-pdf
│ ├── LICENSE-asciidoctor-pdf-cjk-kai_gen_gothic
│ ├── default-ext-notosansmono-cjk-kr-pdf-1-theme.yml
│ ├── default-ext-notosansmono-cjk-kr-theme.yml
│ ├── default-notosansmono-cjk-kr-pdf-1-theme.yml
│ ├── default-notosansmono-cjk-kr-theme.yml
│ ├── notosansmono-cjk-kr-pdf-1-theme.yml
│ └── notosansmono-cjk-kr-theme.yml
├── asciidoctor.css
├── clojure-complete-html.adoc
├── clojure-complete-pdf.adoc
├── coderay-asciidoctor.css
├── docinfo.html
├── guide
├── asciidoctor.adoc
├── asciidoctor.css
├── asciidoctor.pdf
├── asciidoctor.pdfmarks
├── chores.rb
├── coderay-asciidoctor.css
├── demo.adoc
├── docinfo.html
└── to-html.sh
├── my-asciidoctor.css
├── src
└── java-interop
│ ├── .gitignore
│ ├── .idea
│ ├── .name
│ ├── compiler.xml
│ ├── copyright
│ │ └── profiles_settings.xml
│ ├── encodings.xml
│ ├── libraries
│ │ ├── Leiningen__args4j_2_0_26.xml
│ │ ├── Leiningen__cider_cider_nrepl_0_10_0.xml
│ │ ├── Leiningen__clojure_complete_0_2_3.xml
│ │ ├── Leiningen__com_cemerick_piggieback_0_2_1.xml
│ │ ├── Leiningen__com_google_code_findbugs_jsr305_1_3_9.xml
│ │ ├── Leiningen__com_google_code_gson_gson_2_2_4.xml
│ │ ├── Leiningen__com_google_guava_guava_18_0.xml
│ │ ├── Leiningen__com_google_javascript_closure_compiler_externs_v20150126.xml
│ │ ├── Leiningen__com_google_javascript_closure_compiler_v20150126.xml
│ │ ├── Leiningen__com_google_protobuf_protobuf_java_2_5_0.xml
│ │ ├── Leiningen__com_google_truth_truth_0_24.xml
│ │ ├── Leiningen__criterium_0_4_3.xml
│ │ ├── Leiningen__http_kit_2_1_18.xml
│ │ ├── Leiningen__junit_4_10.xml
│ │ ├── Leiningen__org_clojure_clojure_1_7_0.xml
│ │ ├── Leiningen__org_clojure_clojurescript_0_0_3165.xml
│ │ ├── Leiningen__org_clojure_data_json_0_2_6.xml
│ │ ├── Leiningen__org_clojure_google_closure_library_0_0_20140718_946a7d39.xml
│ │ ├── Leiningen__org_clojure_google_closure_library_third_party_0_0_20140718_946a7d39.xml
│ │ ├── Leiningen__org_clojure_tools_nrepl_0_2_12.xml
│ │ ├── Leiningen__org_clojure_tools_reader_0_8_16.xml
│ │ ├── Leiningen__org_hamcrest_hamcrest_core_1_1.xml
│ │ ├── Leiningen__org_mozilla_rhino_1_7R5.xml
│ │ ├── Leiningen__org_tcrawley_dynapath_0_2_3.xml
│ │ ├── Leiningen__prismatic_schema_1_0_3.xml
│ │ └── Leiningen__weasel_0_7_0.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── workspace.xml
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── java-interop.iml
│ ├── project.clj
│ ├── src
│ └── java_interop
│ │ ├── Example3.clj
│ │ ├── Example4.clj
│ │ ├── Example5.clj
│ │ ├── Example6.clj
│ │ ├── example1.clj
│ │ ├── example2.clj
│ │ ├── test1.clj
│ │ ├── test2.clj
│ │ ├── test3.clj
│ │ ├── test4.clj
│ │ ├── test5.clj
│ │ └── test6.clj
│ └── test
│ └── java_interop
│ └── core_test.clj
├── to-html.sh
└── to-pdf.sh
/.github/workflows/deploy.yaml:
--------------------------------------------------------------------------------
1 | name: Build and deploy GH Pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build:
10 | name: Publish site
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: checkout
14 | uses: actions/checkout@v4
15 |
16 | - name: build_and_deploy
17 | env:
18 | GITHUB_TOKEN: ${{ github.token }}
19 | run: |
20 | GITHUB_HOSTNAME="github.com"
21 | TARGET_REPOSITORY=${GITHUB_REPOSITORY}
22 | remote_repo="https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@${GITHUB_HOSTNAME}/${TARGET_REPOSITORY}.git"
23 | remote_branch="gh-pages"
24 |
25 | sudo apt-get install -y asciidoctor
26 | sudo gem install coderay
27 | ./to-html.sh
28 |
29 | echo "Pushing artifacts to ${TARGET_REPOSITORY}:$remote_branch"
30 |
31 | cd public
32 | git init
33 | git config user.name "GitHub Actions"
34 | git config user.email "github-actions-bot@users.noreply.${GITHUB_HOSTNAME}"
35 | git add .
36 |
37 | git commit -m "Deploy ${TARGET_REPOSITORY} to ${TARGET_REPOSITORY}:$remote_branch"
38 | git push --force "${remote_repo}" master:"${remote_branch}"
39 |
40 | echo "Deploy complete"
41 |
--------------------------------------------------------------------------------
/.github/workflows/release-pdf.yaml:
--------------------------------------------------------------------------------
1 | name: Release PDF
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | release:
10 | name: Write Release Page
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 |
16 | - name: Get Tagname
17 | ## ref: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/
18 | ## echo "::set-output name={name}::{value}" (deprecated)
19 | ## echo "{name}={value}" >> $GITHUB_OUTPUT (updated)
20 | id: tag_name
21 | run: |
22 | echo "current_version"="${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
23 | shell: bash
24 |
25 | - name: Release
26 | id: create_release
27 | uses: actions/create-release@v1
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 | with:
31 | draft: false
32 | prerelease: false
33 | release_name: ${{ github.ref }}
34 | tag_name: ${{ github.ref }}
35 | body: ""
36 |
37 | outputs:
38 | upload_url: ${{ steps.create_release.outputs.upload_url }}
39 |
40 | build:
41 | needs: release
42 | name: Build and upload pdf
43 | runs-on: ubuntu-latest
44 | steps:
45 | - name: checkout
46 | uses: actions/checkout@v4
47 |
48 | - name: generate pdf
49 | env:
50 | GITHUB_TOKEN: ${{ github.token }}
51 | run: |
52 | echo "=== install dependencies"
53 | sudo apt-get install -y asciidoctor
54 | sudo gem install asciidoctor-pdf
55 | sudo gem install coderay
56 | ./to-pdf.sh
57 |
58 | - name: Upload Asset
59 | uses: actions/upload-release-asset@v1
60 | env:
61 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
62 | with:
63 | upload_url: ${{ needs.release.outputs.upload_url }}
64 | asset_path: ./clojure-complete.pdf
65 | asset_name: clojure-complete.pdf
66 | asset_content_type: application/octet-stream
67 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | prj/target
2 | prj/classes
3 | prj/checkouts
4 | prj/pom.xml
5 | prj/pom.xml.asc
6 | *.jar
7 | *.class
8 | *.pdf
9 | *.pdfmarks
10 |
11 | prj/.lein-*
12 | prj/.nrepl-port
13 |
14 | *~
15 | *#
16 | .#*
17 |
18 | ## asciidoctor
19 | /public/
20 |
21 | ## temp
22 |
23 | /.clj-kondo/
24 | /.lsp/
25 |
--------------------------------------------------------------------------------
/Boot/build.boot:
--------------------------------------------------------------------------------
1 | ;; source
2 | ;; github.com/magomimmo/modern-cljs/blob/master/doc/second-edition/tutorial-16.md
3 |
4 | (set-env!
5 | :source-paths #{"src/clj" "src/cljs" "src/cljc"}
6 | :resource-paths #{"html"}
7 | :target-path "target"
8 |
9 | :dependencies '[
10 | [org.clojure/clojure "1.7.0"] ;; add CLJ
11 | [org.clojure/clojurescript "1.7.170"] ;; add CLJS
12 | [adzerk/boot-cljs "1.7.170-3"]
13 | [pandeiro/boot-http "0.7.0"]
14 | [adzerk/boot-reload "0.4.2"]
15 | [adzerk/boot-cljs-repl "0.3.0"] ;; add bREPL
16 | [com.cemerick/piggieback "0.2.1"] ;; needed by bREPL
17 | [weasel "0.7.0"] ;; needed by bREPL
18 | [org.clojure/tools.nrepl "0.2.12"] ;; needed by bREPL
19 | [org.clojars.magomimmo/domina "2.0.0-SNAPSHOT"]
20 | [hiccups "0.3.0"]
21 | [compojure "1.4.0"] ;; for routing
22 | [org.clojars.magomimmo/shoreleave-remote-ring "0.3.1"]
23 | [org.clojars.magomimmo/shoreleave-remote "0.3.1"]
24 | [javax.servlet/servlet-api "2.5"]
25 | [org.clojars.magomimmo/valip "0.4.0-SNAPSHOT"]
26 | [enlive "1.1.6"]
27 | [adzerk/boot-test "1.0.7"]
28 | [crisptrutski/boot-cljs-test "0.2.1-SNAPSHOT"]
29 | ])
30 |
31 | (require '[adzerk.boot-cljs :refer [cljs]]
32 | '[pandeiro.boot-http :refer [serve]]
33 | '[adzerk.boot-reload :refer [reload]]
34 | '[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
35 | '[adzerk.boot-test :refer [test]]
36 | '[crisptrutski.boot-cljs-test :refer [test-cljs]]
37 | )
38 |
39 | (def defaults {:test-dirs #{"test/cljc" "test/clj" "test/cljs"}
40 | :output-to "main.js"
41 | :testbed :phantom
42 | :target "target"
43 | :namespaces '#{modern-cljs.shopping.validators-test
44 | modern-cljs.login.validators-test}})
45 |
46 | (deftask add-source-paths
47 | "Add paths to :source-paths environment variable"
48 | [t dirs PATH #{str} ":source-paths"]
49 | (merge-env! :source-paths dirs)
50 | identity)
51 |
52 | (deftask tdd
53 | "Launch a customizable TDD Environment"
54 | [e testbed ENGINE kw "the JS testbed engine (default phantom)"
55 | k httpkit bool "Use http-kit web server (default jetty)"
56 | n namespaces NS #{sym} "the set of namespace symbols to run tests in"
57 | o output-to NAME str "the JS output file name for test (default main.js)"
58 | O optimizations LEVEL kw "the optimization level (default none)"
59 | p port PORT int "the web server port to listen on (default 3000)"
60 | t dirs PATH #{str} "test paths (default test/clj test/cljs test/cljc)"
61 | v verbose bool "Print which files have changed (default false)"]
62 | (let [dirs (or (:test-dirs defaults))
63 | output-to (or output-to (:output-to defaults))
64 | testbed (or testbed (:testbed defaults))
65 | namespaces (or namespaces (:namespaces defaults))]
66 | (comp
67 | (serve ;:dir "target"
68 | :handler 'modern-cljs.core/app
69 | :resource-root (:target defaults)
70 | :reload true
71 | :httpkit httpkit
72 | :port port)
73 | (add-source-paths :dirs dirs)
74 | (watch :verbose verbose)
75 | (reload)
76 | (cljs-repl)
77 | (test-cljs :out-file output-to
78 | :js-env testbed
79 | :namespaces namespaces
80 | :optimizations optimizations)
81 | (test :namespaces namespaces))))
82 |
83 | (deftask dev
84 | "Launch immediate feedback dev environment"
85 | []
86 | (comp
87 | (serve :handler 'modern-cljs.core/app ;; ring hanlder
88 | :resource-root (:target defaults) ;; root classpath
89 | :reload true) ;; reload ns
90 | (watch)
91 | (reload)
92 | (cljs-repl) ;; before cljs
93 | (cljs)))
94 |
--------------------------------------------------------------------------------
/Boot/build.boot.sample:
--------------------------------------------------------------------------------
1 | (set-env!
2 | :source-paths #{"src"} ;; compiled by cljs task
3 | :resource-paths #{"resources"} ;; copied to the target dir by target task
4 | :dependencies '[[org.clojure/clojure "1.8.0"]
5 | [org.clojure/clojurescript "1.9.229"]
6 | [adzerk/boot-cljs "2.0.0" :scope "test"] ;; cljs source complie
7 | [adzerk/boot-cljs-repl "0.3.3" :scope "test"] ;; add bREPL
8 | [org.clojure/tools.nrepl "0.2.13" :scope "test"] ;; needed by bREPL
9 | [com.cemerick/piggieback "0.2.1" :scope "test"] ;; needed by bREPL
10 | [weasel "0.7.0" :scope "test"] ;; needed by bREPL
11 | [adzerk/boot-reload "0.5.1" :scope "test"] ;; live reload for browser
12 | [philoskim/debux "0.2.1"] ])
13 |
14 | (require
15 | '[adzerk.boot-cljs :refer [cljs]]
16 | '[adzerk.boot-cljs-repl :refer [cljs-repl start-repl]]
17 | '[adzerk.boot-reload :refer [reload]])
18 |
19 | (deftask prod []
20 | (comp (cljs :ids #{"main"}
21 | :optimizations :simple)
22 | (cljs :ids #{"renderer"}
23 | :optimizations :advanced)))
24 |
25 | (deftask dev []
26 | (comp ;; Audio feedback about warnings etc. =======================
27 | (speak)
28 | (watch)
29 | ;; Inject REPL and reloading code into renderer build =======
30 | (cljs-repl :ids #{"renderer"})
31 | (reload :ids #{"renderer"}
32 | :ws-host "localhost"
33 | :on-jsload 'app.renderer/init
34 | :target-path "target")
35 | ;; Compile renderer =========================================
36 | (cljs :ids #{"renderer"})
37 | ;; Compile JS for main process ==============================
38 | ;; path.resolve(".") which is used in CLJS's node shim
39 | ;; returns the directory `electron` was invoked in and
40 | ;; not the directory our main.js file is in.
41 | ;; Because of this we need to override the compilers `:asset-path option`
42 | ;; See http://dev.clojure.org/jira/browse/CLJS-1444 for details.
43 | (cljs :ids #{"main"}
44 | :compiler-options {:asset-path "target/main.out"
45 | :closure-defines {'app.main/dev? true}})
46 | (target)))
47 |
--------------------------------------------------------------------------------
/Boot/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Boot/script:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env boot
2 |
3 | (set-env! :dependencies '[[clj-time "0.11.0"]])
4 |
5 | (require '[clojure.string :as str]
6 | '[clj-time.core :as time])
7 |
8 | (defn -main [& args]
9 | (println (str/upper-case "hello, world! The time is") (time/now))
10 | (System/exit 0))
11 |
--------------------------------------------------------------------------------
/Collections-and-Sequences/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Collections-and-Sequences/subs/zipper.adoc:
--------------------------------------------------------------------------------
1 | = 지퍼(Zipper)
2 | :source-highlighter: coderay
3 | :source-language: clojure
4 | :sectnums:
5 | :icons: font
6 |
7 | == 트리
8 |
9 | 내용을 채워넣을 것.
10 |
11 |
--------------------------------------------------------------------------------
/Design-Patterns/coderay-asciidoctor.css:
--------------------------------------------------------------------------------
1 | /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
2 | /*pre.CodeRay {background-color:#f7f7f8;}*/
3 | .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
4 | .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
5 | .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
6 | table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
7 | table.CodeRay td{vertical-align: top;line-height:1.45}
8 | table.CodeRay td.line-numbers{text-align:right}
9 | table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
10 | table.CodeRay td.code{padding:0 0 0 .5em}
11 | table.CodeRay td.code>pre{padding:0}
12 | .CodeRay .debug{color:#fff !important;background:#000080 !important}
13 | .CodeRay .annotation{color:#007}
14 | .CodeRay .attribute-name{color:#000080}
15 | .CodeRay .attribute-value{color:#700}
16 | .CodeRay .binary{color:#509}
17 | .CodeRay .comment{color:#998;font-style:italic}
18 | .CodeRay .char{color:#04d}
19 | .CodeRay .char .content{color:#04d}
20 | .CodeRay .char .delimiter{color:#039}
21 | .CodeRay .class{color:#458;font-weight:bold}
22 | .CodeRay .complex{color:#a08}
23 | .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
24 | .CodeRay .color{color:#099}
25 | .CodeRay .class-variable{color:#369}
26 | .CodeRay .decorator{color:#b0b}
27 | .CodeRay .definition{color:#099}
28 | .CodeRay .delimiter{color:#000}
29 | .CodeRay .doc{color:#970}
30 | .CodeRay .doctype{color:#34b}
31 | .CodeRay .doc-string{color:#d42}
32 | .CodeRay .escape{color:#666}
33 | .CodeRay .entity{color:#800}
34 | .CodeRay .error{color:#808}
35 | .CodeRay .exception{color:inherit}
36 | .CodeRay .filename{color:#099}
37 | .CodeRay .function{color:#900;font-weight:bold}
38 | .CodeRay .global-variable{color:#008080}
39 | .CodeRay .hex{color:#058}
40 | .CodeRay .integer,.CodeRay .float{color:#099}
41 | .CodeRay .include{color:#555}
42 | .CodeRay .inline{color:#000}
43 | .CodeRay .inline .inline{background:#ccc}
44 | .CodeRay .inline .inline .inline{background:#bbb}
45 | .CodeRay .inline .inline-delimiter{color:#d14}
46 | .CodeRay .inline-delimiter{color:#d14}
47 | .CodeRay .important{color:#555;font-weight:bold}
48 | .CodeRay .interpreted{color:#b2b}
49 | .CodeRay .instance-variable{color:#008080}
50 | .CodeRay .label{color:#970}
51 | .CodeRay .local-variable{color:#963}
52 | .CodeRay .octal{color:#40e}
53 | .CodeRay .predefined{color:#369}
54 | .CodeRay .preprocessor{color:#579}
55 | .CodeRay .pseudo-class{color:#555}
56 | .CodeRay .directive{font-weight:bold}
57 | .CodeRay .type{font-weight:bold}
58 | .CodeRay .predefined-type{color:inherit}
59 | .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
60 | .CodeRay .key{color:#808}
61 | .CodeRay .key .delimiter{color:#606}
62 | .CodeRay .key .char{color:#80f}
63 | .CodeRay .value{color:#088}
64 | .CodeRay .regexp .delimiter{color:#808}
65 | .CodeRay .regexp .content{color:#808}
66 | .CodeRay .regexp .modifier{color:#808}
67 | .CodeRay .regexp .char{color:#d14}
68 | .CodeRay .regexp .function{color:#404;font-weight:bold}
69 | .CodeRay .string{color:#d20}
70 | .CodeRay .string .string .string{background:#ffd0d0}
71 | .CodeRay .string .content{color:#d14}
72 | .CodeRay .string .char{color:#d14}
73 | .CodeRay .string .delimiter{color:#d14}
74 | .CodeRay .shell{color:#d14}
75 | .CodeRay .shell .delimiter{color:#d14}
76 | .CodeRay .symbol{color:#990073}
77 | .CodeRay .symbol .content{color:#a60}
78 | .CodeRay .symbol .delimiter{color:#630}
79 | .CodeRay .tag{color:#008080}
80 | .CodeRay .tag-special{color:#d70}
81 | .CodeRay .variable{color:#036}
82 | .CodeRay .insert{background:#afa}
83 | .CodeRay .delete{background:#faa}
84 | .CodeRay .change{color:#aaf;background:#007}
85 | .CodeRay .head{color:#f8f;background:#505}
86 | .CodeRay .insert .insert{color:#080}
87 | .CodeRay .delete .delete{color:#800}
88 | .CodeRay .change .change{color:#66f}
89 | .CodeRay .head .head{color:#f4f}
--------------------------------------------------------------------------------
/Design-Patterns/design-patterns.adoc:
--------------------------------------------------------------------------------
1 | = Design Patterns
2 | :source-highlighter: coderay
3 | :source-language: clojure
4 | :sectnums:
5 | :icons: font
6 | :imagesdir: ../img
7 | :linkcss:
8 | :stylesdir: ../
9 | :stylesheet: my-asciidoctor.css
10 | :docinfo1:
11 | :toc: right
12 |
13 |
14 | == Pattern and Functional Programming
15 |
--------------------------------------------------------------------------------
/Design-Patterns/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Destructuring/destructuring.adoc:
--------------------------------------------------------------------------------
1 | = 구조분해(Destructuring)
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: ../img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 | 클로저는 데이터를 직접 다룬다. 데이터들은 주로 맵이나 벡터같은 컬렉션으로 구조화되어
13 | 사용되는데, 컬렉션들은 추상 인터페이스를 통해서 개별 데이터에 접근하는 방법을
14 | 제공한다. 예를 들어, 벡터의 경우 값을 가져올 때 다음과 같이 한다.
15 |
16 | [source]
17 | ....
18 | (def v [42 "foo" 99.2 [5 12]])
19 |
20 | (first v) ;=> 42
21 | (second v) ;=> "foo"
22 | (last v) ;=> [5 12]
23 | (nth v 2) ;=> 99.2 ;; 1
24 | (v 2) ;=> 99.2 ;; 2
25 | (.get v 2) ;=> 99.2 ;; 3
26 | ....
27 |
28 | `first`, `second`, `last`, `nth` 같은 이러한 함수들은 벡터나 맵같은 컬렉션들이 제공하는
29 | 추상 인터페이스이다. 개개의 컬렉션들의 구체적인 구현에 상관없이 이러한 추상 인터페이스를
30 | 기반으로 해서 컬렉션에 접근하는 것이 가능하기 때문에, 컬렉션을 처리하는 클로저의 모든 코어
31 | 함수들은 그 구현이 단순해지며, 또한 서로 레고 블럭처럼 조립 가능하게 된다.
32 |
33 | 하지만 컬렉션의 여러 요소에 접근할 때는 추상 인터페이스가 제공하는 이러한 함수들을
34 | 이용하는 것이 상당히 번거로워진다.
35 |
36 | [source]
37 | ....
38 | (+ (first v) (v 2)) ;=> (+ 42 99.2) => 141.2
39 | (+ (first v) (first (last v))) ;=> (+ 42 (first [5 12])) => (+ 42 5) => 47
40 | ....
41 |
42 |
43 | 클로저는 이러한 문제를 해결하기 위해 구조분해라는 매우 유용한 기능을 제공한다. 구조분해는
44 | 컬렉션과 같은 추상 데이터 구조에서 원하는 값만 손쉽게 뽑아서 바인딩하는 기법이다.
45 |
46 | 구조분해는 기본적으로 `let` 바인딩 리스트에서 사용되지만, `let` 바인딩을 내부적으로
47 | 사용하는 `fn`, `defn`, `loop` 등에서도 사용될 수 있다. 구조분해에는 벡터 구조분해와 맵
48 | 구조분해가 있다.
49 |
50 |
51 | == 벡터 구조분해
52 |
53 | 벡터 구조분해는 ``nth`를 지원하는 모든 시퀀스들에 대해 적용된다.
54 |
55 | 이러한 컬렉션은 아래와 같다.
56 |
57 | * 클로저의 리스트, 벡터, seqs
58 | * java.util.List 인터페이스를 구현한 컬렉션들. 즉 ArrayList, LinkedList 등
59 | * java.util.RandomAccess 인터페이스를 구현한 클래스
60 | * 자바 CharSequence
61 | * 자바 java.util.regex.Matcher
62 | * 자바 String
63 |
64 |
65 | === 기본 시퀀스 구조분해
66 |
67 | 다음은 간단한 시퀀스 구조분해이다.
68 |
69 | [source]
70 | ....
71 | (def v [42 "foo" 99.2 [5 12]])
72 |
73 | (let [[x y z] v]
74 | (+ x z))
75 | ;=> 141.2
76 | ....
77 |
78 | `let` 바인딩 벡터는 이름-값 쌍의 나열이다. 위 코드에서는 이름이 ``[x y z]``이고, 값은
79 | ``v``인 쌍 하나만 있다. 값 ``v``는 하나의 심볼이 아닌 ``[x y z]``라는 심볼 시퀀스로
80 | 바인딩되기 위해 구조분해 되어야 한다. 물론 ``v``가 시퀀스 구조분해되기 위해서는 `v` 자체가
81 | 시퀀스여야 한다. 시퀀스 구조분해는 자리별로 바인딩된다. 즉 ``v``의 첫 요소는 `x`, 둘째
82 | 요소는 `y`, 세째 요소는 ``z``로 바인딩된다.
83 |
84 | 사실 위의 코드는 아래 코드와 같은 일을 하는 것이다.
85 |
86 | [source]
87 | ....
88 | (let [x (nth v 0)
89 | y (nth v 1)
90 | z (nth v 2)]
91 | (+ x z))
92 | ;=> 141.2
93 | ....
94 |
95 |
96 | === 내부 시퀀스 구조분해
97 |
98 | 다음은 구조분해가 내부 벡터에 적용되는 예이다.
99 |
100 | [source]
101 | ....
102 | (let [[x _ _ [y z]] v]
103 | (+ x y z))
104 | ;=> 59
105 | ....
106 |
107 |
108 | ==== 시퀀스 구조분해는 자리별 분해
109 |
110 | 구조분해는 자리별로 서로 매칭되어 분해되서 바인딩되는 것이다.
111 |
112 | [source]
113 | ....
114 | [x y z]
115 | [42 "foo" 99.2 [5 12]]
116 | ....
117 |
118 | 위의 내부 시퀀스 구조분해는 다음과 같이 자리별 매칭이 된다.
119 |
120 | [source]
121 | ....
122 | [x _ _ [y z ]]
123 | [42 "foo" 99.2 [5 12]]
124 | ....
125 |
126 |
127 | === 나머지 구조분해
128 |
129 | ``&``를 사용하면 나머지 요소들을 시퀀스로 구조분해 할 수 있다.
130 |
131 | [source]
132 | ....
133 | (let [[x & rest] v]
134 | rest)
135 | ;=> ("foo" 99.2 [5 12])
136 | ....
137 |
138 | 이것은 전형적인 시퀀스 구조분해이다. 이런 구조분해는 특히 ``loop``등 재귀 호출에서 많이
139 | 사용된다. 한가지 주의할 점은 ``rest``가 벡터가 아니라 시퀀스라는 점이다.
140 |
141 |
142 | === 원본 구조분해
143 |
144 | 때로는 원래의 값을 그대로 유지하고 싶을 수도 있다. 그럴 때는 `:as` 키워드를 사용한다.
145 |
146 | [source]
147 | ....
148 | (let [[x _ z :as org] v]
149 | (conj org (+ x z)))
150 | ;=> [42 "foo" 99.2 [5 12] 141.2]
151 | ....
152 |
153 | 이것이 유용할 때는 ``v``가 함수일 경우이다. 함수의 결과값을 구조분해했지만 결과값 전체를
154 | 지시하는 심볼이 없어 함수를 다시 호출하지 않기 위해서이다. 다음 코드를 보자.
155 |
156 |
157 | [source]
158 | ....
159 | (defn f []
160 | [1 2 3])
161 |
162 | (let [[x y] (f)]
163 | (conj (f) (+ x y))) ;; f 함수가 2번 호출된다.
164 | ;=> [1 2 3 3]
165 |
166 | (let [[x y :as all] (f)]
167 | (conj all (+ x y))) ;; f 함수의 결과값을 심볼 all로 받아 사용한다.
168 | ;=> [1 2 3 3]
169 | ....
170 |
171 | 다음은 나머지 구조분해와 원본 구조분해를 같이 사용하는 예이다.
172 |
173 | [source]
174 | ....
175 | (let [[a b c & more :as all] (range 10)]
176 | (println "a b c are: " a b c)
177 | (println "more is: " more)
178 | (println "all is: " all))
179 | ;>> a b c are: 0 1 2
180 | ;>> more is: (3 4 5 6 7 8 9)
181 | ;>> all is: (0 1 2 3 4 5 6 7 8 9)
182 | ;=> nil
183 | ....
184 |
185 |
186 | == 맵 구조분해
187 |
188 | === 맵 구조분해의 대상
189 |
190 | 맵 구조분해의 대상은 다음과 같다.
191 |
192 | * 클로저 hash-map, array-map, record
193 | * java.util.Map 인터페이스를 구현한 컬렉션
194 | * 인덱스를 키로하는 get 함수를 지원하는 클래스
195 | * 클로저 벡터
196 | * 스트링
197 | * Array
198 |
199 |
200 | === 기본 맵 구조분해
201 |
202 | 다음은 기본적인 맵 구조분해이다.
203 |
204 | [source]
205 | ....
206 | (def m {:a 5 :b 6
207 | :c [7 8 9]
208 | :d {:e 10 :f 11}
209 | "foo" 88
210 | 42 false})
211 |
212 | (let [{a :a b :b} m]
213 | (+ a b))
214 | ;=> 11
215 | ....
216 |
217 | 위 코드에서 `let` 바인딩 벡터는 구조분해를 위해 맵을 사용하여, ``m``의 `:a` 값인 ``5``를
218 | ``a``에, ``m``의 `:b` 값인 ``6``을 ``b``에 바인딩한다.
219 |
220 |
221 | === 맵 구조분해는 키별 분해
222 |
223 | 맵은 키-값 쌍을 요소로 하기 때문에 다음과 같이 키에 따른 분해가 된다고 생각할 수 있다.
224 |
225 | [source]
226 | ....
227 | {a :a b :b}
228 | {:a 5 :b 6}
229 | ....
230 |
231 | 맵의 키는 키워드 외에 다른 것이 올 수도 있기 때문에 다음 코드도 가능하다.
232 |
233 | [source]
234 | ....
235 | (let [{f "foo"} m]
236 | (+ f 12))
237 | ;=> 100
238 | ....
239 |
240 | [source]
241 | ....
242 | (let [{v 42} m]
243 | (if v 1 0))
244 | ;=> 0
245 | ....
246 |
247 |
248 | === 벡터에 대한 맵 구조분해
249 |
250 | 맵 구조분해에서 벡터나 스트링의 인덱스는 키로 사용될 수 있다. 다음은 벡터를 맵
251 | 구조분해하는 예이다.
252 |
253 | [source]
254 | ....
255 | (let [{x 3 y 8} [12 0 0 -18 44 6 0 0 1]]
256 | (+ x y))
257 | ;=> -17
258 | ....
259 |
260 | 벡터를 맵 구조분해하는 장점은 특정 자리만을 골라서 구조분해할 수 있다는 점이다.
261 |
262 | 벡터는 위치 인덱스를 키로 하는 맵이다.
263 |
264 |
265 | === 내부 맵 구조분해
266 |
267 | 다음은 내부 맵에 대한 구조분해이다.
268 |
269 | [source]
270 | ....
271 | (let [{{e :e} :d} m]
272 | (* 2 e))
273 | ;=> 20
274 | ....
275 |
276 |
277 | ``:d``에 의해 ``m``의 내부 맵 ``{:e 10 :f 11}``이 선택되고, 다시 ``:e``에 의해 ``10``이
278 | 선택된다.
279 |
280 |
281 | === 시퀀스 구조분해와 맵 구조분해 같이 사용하기
282 |
283 | 맵 구조분해와 시퀀스 구조분해가 같이 사용되면 우아한 코드가 된다.
284 |
285 | [source]
286 | ....
287 | (let [{[x _ y] :c} m]
288 | (+ x y))
289 | ;=> 16
290 | ....
291 |
292 | [source]
293 | ....
294 | (def map-in-vector ["James" {:birthday (java.util.Date. 73 1 6)}])
295 |
296 | (let [[name {bd :birthday}] map-in-vector]
297 | (str name " was born on " bd))
298 | ;=> "James was born on Thu Feb 06 00:00:00 EST 1973"
299 | ....
300 |
301 |
302 | === 원본 구조분해
303 |
304 | 시퀀스 구조분해에서처럼 ``:as``를 사용하면 구조분해되는 맵 자체를 바인딩할 수 있다.
305 |
306 | [source]
307 | ....
308 | (let [{r1 :x r2 :y :as randoms}
309 | (zipmap [:x :y :z] (repeatedly (partial rand-int 10)))]
310 | (assoc randoms :sum (+ r1 r2)))
311 | ;=> {:sum 17, :z 3, :y 8, :x 9}
312 | ....
313 |
314 | === 기본값 설정
315 |
316 | 구조분해 문구에서 피구조분해 맵에는 없는 키를 사용했을 때, 기본 맵을 제공하여 해당 키의
317 | 값을 설정할 수 있다.
318 |
319 | [source]
320 | ....
321 | (let [{k :unknown x :a :or {k 50}} m]
322 | (+ k x))
323 | ;=> 55
324 | ....
325 |
326 | 아래 코드는 같은 결과를 낸다.
327 |
328 | [source]
329 | ....
330 | (let [{k :unknown x :a} m
331 | k (or k 50)]
332 | (+ k x))
333 | ;=> 55
334 | ....
335 |
336 | 하지만 ``:or``는 피구조분해의 해당 키 값이 ``false``이거나 ``nil``일 때도 동작한다.
337 |
338 | [source]
339 | ....
340 | (let [{opt1 :option} {:option false}
341 | opt1 (or opt1 true)
342 | {opt2 :option :or {opt2 true}} {:option false}]
343 | {:opt1 opt1 :opt2 opt2})
344 | ;=> {:opt1 true, :opt2 false}
345 | ....
346 |
347 |
348 | === 맵키 이름 구조분해
349 |
350 | 맵의 키는 그 자체로 데이터의 성격을 드러내는 경우, 맵 구조분해 이후에도 그 키의 이름을
351 | 그대로 사용하는 것이 좋은데, 다음과 같이 같은 이름들이 반복되게 된다.
352 |
353 | [source]
354 | ....
355 | (def kildong {:name "KilDong" :age 24 :location "west"})
356 |
357 | (let [{name :name age :age location :location} kildong]
358 | (format "%s is %s years old and lives in %s." name age location))
359 | ;=> "KilDong is 24 old years and lives in west."
360 | ....
361 |
362 | 이런 반복을 하지 않기 위해 ``:keys``를 사용하여 피구조분해 맵의 각 키의 이름으로
363 | 바인딩한다.
364 |
365 | [source]
366 | ....
367 | (def kildong {:name "KilDong" :age 24 :location "west"})
368 |
369 | (let [{:keys [name age location]} kildong]
370 | (format "%s is %s years old and lives in %s." name age location))
371 | ;=> "KilDong is 24 old years and lives in west."
372 | ....
373 |
374 | 피구조분해 맵이 키로 스트링이나 심볼을 사용하는 경우는 ``:strs``과 ``:syms``를 사용한다.
375 |
376 |
377 | [source]
378 | ....
379 | (def kildong {"name" "KilDong" "age" 24 "location" "west"})
380 |
381 | (let [{:strs [name age location]} kildong]
382 | (format "%s is %s years old and lives in %s." name age location))
383 | ;=> "KilDong is 24 old years and lives in west."
384 | ....
385 |
386 | [source]
387 | ....
388 | (def kildong {'name "KilDong" 'age 24 'location "west"})
389 |
390 | (let [{:syms [name age location]} kildong]
391 | (format "%s is %s years old and lives in %s." name age location))
392 | ;=> "KilDong is 24 old years and lives in west."
393 | ....
394 |
395 |
396 | === 나머지 시퀀스를 키-값 쌍으로 구조분해
397 |
398 | 시퀀스 구조분해서는 ``&``를 사용하여 나머지 요소를 시퀀스로 바인딩할 수 있었다. 키-값 쌍이
399 | 튜플로 있는 벡터에 대해서는 튜플들을 맵으로 구조분해할 수 있다.
400 |
401 | [source]
402 | ....
403 | (def movie ["Les Miserables" 2012 :director "Tom Hooper" :rating 8.0])
404 |
405 | (let [[movie-name year & rest] movie
406 | {:keys [director rating]} (apply hash-map rest)]
407 | (format "%s is made by %s in %s, rating %.1f" movie-name year director rating))
408 | ....
409 |
410 | 이 코드에서는 시퀀스 구조분해에서 받은 ``rest``를 맵 구조분해하기 위해 ``hash-map``을
411 | 적용하고 있다. 이것은 다음과 같이 간단하게 처리될 수 있다.
412 |
413 | [source]
414 | ....
415 | (let [[movie-name year & {:keys [director rating]}] movie]
416 | (format "%s is made by %s in %s, rating %s" movie-name year director rating))
417 | ....
418 |
419 | `rest` 자리에 직접 맵 구조분해 문구를 바로 적용할 수 있다.
420 |
421 | === 맵을 시퀀스 구조분해할 수는 없다
422 |
423 | 위에서 시퀀스를 맵 구조분해 할 수 있음을 보았다. 그것은 시퀀스도 맵 구조분해가 요구하는
424 | `get` 메소드를 지원하기 때문이다. 하지만 반대로 맵을 시퀀스 구조분해할 수는 없는데, 맵은
425 | 시퀀스 구조분해가 요구하는 ``nth``를 지원하지 않기 때문이다.
426 |
427 | 특히 주의할 점은 집합은 값(Value)를 키(Key)로 하는 맵이기 때문에 시퀀스 구조분해가 되지
428 | 않는다.
429 |
430 | [source]
431 | ....
432 | (let [[a & r] #{1 2 3}]
433 | a)
434 | ;>> UnsupportedOperationException nth not supported on this type: PersistentHashSet...
435 | ....
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
--------------------------------------------------------------------------------
/Destructuring/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Development-Environments/atom.adoc:
--------------------------------------------------------------------------------
1 | = Atom editor + proto-repl 설치
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 | == Atom editor 설치
13 |
14 | . link:https://atom.io/[]를 방문해 아톰 윈도우즈 최신 버전(여기서는 `AtomSetup-x64.exe`
15 | 파일)을 다운로드 받는다.
16 |
17 | . 다운받은 `AtomSetup-x64.exe` 파일을 실행해. 아톰 편집기 설치를 마친다.
18 |
19 |
20 | == ink 플러그인 설치
21 |
22 | 먼저 ink 플러그인을 설치한다. 이 플러그인에 대한 자세한 설명은
23 | link:https://github.com/JunoLab/atom-ink[]를 참조한다.
24 |
25 | * [Files -- Settings -- Install] 버튼을 클릭한 후, 텍스트 입력 상자에 `ink` 라고 입력한 후
26 | `install` 버튼을 클릭한다.
27 | +
28 | image:atom-ink-install.png[]
29 |
30 |
31 | == proto-repl 플러그인 설치
32 |
33 | * 위와 같은 요령으로 [Files -- Settings -- Install] 버튼을 클릭한 후, 텍스트 입력 상자에 `proto-repl` 이라고 입력한 후 `install` 버튼을 클릭한다.
34 | +
35 | image:atom-proto-repl-install.png[]
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Development-Environments/development-environments.adoc:
--------------------------------------------------------------------------------
1 | = 개발 환경 설정
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 |
13 | 이 장에서는 `Windows 10` (64비트 버전)에 클로저 개발 환경을 설치하는 예를 보여준다. 다른
14 | OS의 경우에는 이 장의 내용을 참고해서 약간 변용하면 설치가 가능할 것이다.
15 |
16 |
17 | == Java JDK 설치
18 |
19 | . 클로저는 JVM(Java Virtual Machine) 상에서 실행되는 언어이므로, 먼저 JDK(Java
20 | Development Kit)를 설치해야 한다. 클로저는 JDK 1.6.0 이상의 버전에서 돌아가지만,
21 | 특별한 요구 사항이 없다면 최신 버전의 JDK를 설치하도록 한다.
22 |
23 | . http://www.oracle.com/technetwork/java/javase/downloads/index.html[]를 방문해 'Java SE
24 | 11 (LTS)'의 'Oracle JDK DOWNLOAD' 버튼을 클릭한 후, 자신의 OS에 맞는 최신 버전의 JDK을 내려
25 | 받는다. 여기에서는 `Windows` (64비트 버전) 상에서 JDK를 설치하는 예를 보이겠다. 따라서
26 | Java SE Development Kit 11 중에서 Windows x64 버전의 jdk-11_windows-x64_bin.exe 파일을
27 | 다운로드 받는다.
28 | +
29 | CAUTION: JRE(Java Runtime Environment)가 아니라 JDK를 다운로드 받아야 한다.
30 |
31 | . 내려 받은 파일을 실행해, JDK 설치를 시작한다. 기본 설정 값대로 진행해 설치를 마친다.
32 |
33 | . Windows 'Path' 환경 변수 설정하기 [[environment-variables]]
34 | ** 화면 좌측 최하단의 ['시작' 버튼 -- 'Windows 시스템' -- '제어판'] 을 선택한다.
35 | ** ['시스템 및 보안' -- '시스템' -- '고급 시스템 설정' -- '고급' -- '환경변수' -- '시스템
36 | 변수' -- 'Path'] 항목을 클릭한다.
37 | ** ['편집' -- '새로 만들기'] 클릭 후, 입력 상자에 `C:\Program Files\java\jdk-11\bin` 를 입력
38 | 후, '확인' 버튼을 누른다.
39 |
40 | . Java SDK 설치 확인
41 | ** 화면 좌측 최하단의 ['시작' 버튼 -- 'Windows 시스템' -- '명령 프람프트'] 를 선택한다.
42 | ** 명령창에서 다음과 같이 실행해 메시지가 출력되면, Java JDK 버전 설치에 성공한 것이다.
43 | +
44 | [listing]
45 | ----
46 | C:\> java -version
47 | java version "11" 2018-09-25
48 | Java(TM) SE Runtime Environment 18.9 (build 11+28)
49 | Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11+28, mixed mode)
50 |
51 | C:\>
52 | ----
53 |
54 | == wget 설치
55 |
56 | 클로저 프로젝트 관리 도구인 Leiningen이 라이브러리를 내려받을 때 wget 프로그램을 필요로
57 | 하므로, 이 프로그램을 미리 설치해 두어야 한다.
58 |
59 | . https://eternallybored.org/misc/wget[]을 방문해, 최신 버전을 다운로드 받는다. 여기에서는
60 | 64비트 버전인 wget-1.19.4-win64.zip 파일을 다운로드 받는 것으로 한다.
61 |
62 | . 압축을 푼 후에, `wget.exe` 파일을 자신이 원하는 폴더로 복사한다. 여기에서는
63 | `C:\dev\bin\` 폴더에 복사하는 것으로 한다.
64 |
65 | . 환경 변수 ``Path``에 `wget.exe` 파일이 위치한 폴더의 경로를 추가한다:
66 | (<>)
67 | ** [시스템 변수]에서 [Path] 변수 선택 후, ['편집' -- '새로 만들기'] 클릭 후, 입력 상자에
68 | `C:\dev\bin` 경로를 추가한 후, '확인' 버튼을 클릭한다.
69 |
70 | . wget 설치 확인
71 | ** 화면 좌측 최하단의 ['시작' 버튼 -- 'Windows 시스템' -- '명령 프람프트'] 를 선택한다.
72 | ** 명령창에서 다음과 같이 실행해 메시지가 출력되면, wget 설치에 성공한 것이다.
73 | +
74 | [listing]
75 | ----
76 | C:\> wget
77 | wget: Missing URL
78 | Usage: wget [OPTION]... [URL]...
79 |
80 | Try `wget --help' for more options.
81 |
82 | C:\>
83 | ----
84 |
85 | == Leiningen 설치
86 |
87 | Leiningen(라이닝언)은 클로저 프로젝트 관리를 위한 기본 도구이다.
88 |
89 | . 다음과 같이 wget을 이용해 leiningen을 다운로드한다. 여기서는 leiningen을 `C:\dev\bin\`
90 | 폴더 아래에 설치하는 것으로 한다.
91 | +
92 | [listing]
93 | ----
94 | C:\> cd dev\bin
95 |
96 | C:\dev\bin> wget --no-check-certificate https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein.bat
97 | ----
98 |
99 | . 환경 변수 ``LEIN_HOME`` 추가 (<>)
100 | +
101 | 환경 변수 ``LEIN_HOME``을 새로 만들고, ``lein.bat``을 포함하고 있는 폴더의 경로를
102 | 입력한다.
103 |
104 | * [시스템 변수 -- 새로 만들기] 선택 후, [변수 이름] 란에 LEIN_HOME으로, [변수 값] 란에는
105 | ``C:\dev\bin``을 입력한다.
106 |
107 | . 이후 같은 명령창에서 다음과 같이 입력해 leiningen 본체를 설치하려 하면, 다음과 같은 에러가 날 것이다.
108 |
109 | +
110 | [listing]
111 | ----
112 | C:\dev\bin> lein self-install
113 | Downloading Leiningen now...
114 | "2"개의 인수가 있는 "DownloadFile"을(를) 호출하는 동안 예외가 발생했습니다.
115 | "요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다." ......
116 | ----
117 | +
118 | 이 에러는 link:https://github.com/technomancy/leiningen/issues/2412[]에 이미 보고되어
119 | 있다. lein 다음 버전에는 이 문제가 해결될 것으로 보인다. 하지만 당장은 임시방편으로
120 | 위의 사이트에 나와 있는 대로, 다운 받은 `lein.bat` 파일의 내용 중 다음 라인을
121 | +
122 | [listing]
123 | ----
124 | powershell -Command "& {param($a,$f) $client = New-Object System.Net.WebClient; $client.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials; $client.DownloadFile($a, $f)}" ""%2"" ""%1""
125 | ----
126 | +
127 | 다음 라인으로 직접 대체해서 해결하도록 한다.
128 | +
129 | [listing]
130 | ----
131 | powershell -Command "& {param($a,$f) $client = New-Object System.Net.WebClient; [Net.ServicePointManager]::SecurityProtocol = 'tls12' ; $client.Proxy.Credentials =[System.Net.CredentialCache]::DefaultNetworkCredentials; $client.DownloadFile($a, $f)}" ""%2"" ""%1""
132 | ----
133 | +
134 | `lein.bat` 파일을 위와 같이 수정한 후, 다음 명령을 재실행해 leiningen 본체의 설치를 마친다.
135 | +
136 | [listing]
137 | ----
138 | C:\dev\bin> lein self-install
139 | ----
140 | +
141 | 위 명령이 실행된 후에, ``LEIN_HOME``에 지정되어 있는 폴더에 `self-installs` 폴더가 생성되고 그
142 | 아래에 ``leiningen-2.8.1-standalone.jar``가 설치된 것을 확인할 수 있다.
143 | +
144 | [listing]
145 | ----
146 | C:\dev\bin> tree /a /f
147 | | lein.bat
148 | | wget.exe
149 | |
150 | \---self-installs
151 | leiningen-2.8.1-standalone.jar
152 | ----
153 |
154 | . Leiningen 설치 확인
155 | +
156 | 다음과 같이 실행해 메시지가 출력되면, Leiningen이 제대로 설지된 것이다.
157 | +
158 | [listing]
159 | ----
160 | C:\> lein version
161 | Leiningen 2.8.1 on Java 11 Java HotSpot(TM) 64-Bit Server VM
162 | ----
163 |
164 | == 예제 프로젝트 만들기
165 |
166 | 여기서는 ``sample``이라는 이름의 프로젝트를 만들 것이다. 이 프로젝트를 아래의 `IDE 설치`
167 | 절에서 읽어 들여 실행해 볼 것이다.
168 |
169 | . 먼저 명령창에서 다음의 명령을 실행해 `C:\dev\projects` 폴더를 만들어 놓는다.
170 | +
171 | [listing]
172 | ----
173 | C:\> cd dev
174 |
175 | C:\dev> mkdir projects
176 |
177 | C:\dev> cd projects
178 |
179 | C:\dev\projects>
180 | ----
181 |
182 | . 다음을 실행해 ``sample``이라는 이름의 프로젝트를 만든다. 그러면 `sample`
183 | 폴더 아래에 이 프로젝트에 기본적으로 필요한 여러 개의 폴더와 파일이 만들어질 것이다.
184 | +
185 | [listing]
186 | ----
187 | C:\dev\projects> lein new sample
188 | Generating a project called sample based on the 'default' template.
189 | The default template is intended for library projects, not applications.
190 | To see other templates (app, plugin, etc), try `lein help new`.
191 |
192 | C:\dev\projects> cd sample
193 |
194 | C:\dev\projects\sample> dir
195 |
196 | C:\dev\projects\sample 디렉터리
197 |
198 | 2018-10-10 오후 08:12 .
199 | 2018-10-10 오후 08:12 ..
200 | 2018-10-10 오후 08:12 110 .gitignore
201 | 2018-10-10 오후 08:12 134 .hgignore
202 | 2018-10-10 오후 08:12 790 CHANGELOG.md
203 | 2018-10-10 오후 08:12 doc
204 | 2018-10-10 오후 08:12 11,433 LICENSE
205 | 2018-10-10 오후 08:12 272 project.clj
206 | 2018-10-10 오후 08:12 246 README.md
207 | 2018-10-10 오후 08:12 resources
208 | 2018-10-10 오후 08:12 src
209 | 2018-10-10 오후 08:12 test
210 | 6개 파일 12,985 바이트
211 | 6개 디렉터리 11,568,414,720 바이트 남음
212 | ----
213 |
214 | . 만들어진 파일들 중에서 `project.clj` 파일을 편집기로 열어, 다음과 같이 수정한다.
215 | +
216 | [source]
217 | .project.clj
218 | ....
219 | (defproject sample "0.1.0-SNAPSHOT"
220 | :dependencies [[org.clojure/clojure "1.10.0-RC1"]])
221 | ....
222 |
223 | . 다음과 같이 실행해, 의존 라이브러리들을 미리 다운로드 받아 놓는다.
224 | +
225 | [listing]
226 | ----
227 | C:\dev\projects\sample> lein deps
228 | Retrieving org/clojure/clojure/1.10.0-beta2/clojure-1.10.0-RC1.pom from central
229 | Retrieving org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.pom from central
230 | Retrieving org/clojure/pom.contrib/0.2.2/pom.contrib-0.2.2.pom from central
231 | ......
232 |
233 | C:\dev\projects\sample>
234 | ----
235 |
236 |
237 | == IDE 설치
238 |
239 | 클로저 프로그래밍을 위한 IDE(Intergrated Development Environment)는 여러가지가
240 | 있다. 다음에는 설치와 사용이 수월한 것에서 어려운 순서대로 나열하였다. 자신에게 익숙하고
241 | 편리한 IDE를 골라 설치하도록 한다.
242 |
243 |
244 | * link:vscode.adoc[Visual Studio Code + Calva 설치]
245 | * link:intellij.adoc[IntelliJ + Cursive 설치]
246 | // * link:emacs.adoc[Emacs + Cider 설치]
--------------------------------------------------------------------------------
/Development-Environments/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Development-Environments/emacs.adoc:
--------------------------------------------------------------------------------
1 | = Emacs + Cider 설치
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 | == Emacs 설치
13 |
14 | * link:http://ftp.gnu.org/gnu/emacs/windows[] 페이지를 방문해, 64 비트 Windows용 최신
15 | emacs 버전을 내려 받는다. 여기서는 `emacs-26/emacs-26.1-x86_64.zip` 파일을 내려 받는
16 | 것으로 한다.
17 |
18 | * 내려 받는 압축 파일을 푼 후, 자신이 원하는 폴더로 통쨰로 옮긴다. 여기서는
19 | `C:\dev\bin\emacs` 폴더로 옮기는 것으로 한다.
20 | +
21 | [listing]
22 | ----
23 | C:\> cd dev\bin\emacs
24 |
25 | C:\dev\bin\emacs> dir
26 | C 드라이브의 볼륨에는 이름이 없습니다.
27 | 볼륨 일련 번호: 8059-3BAA
28 |
29 | C:\dev\bin\emacs 디렉터리
30 |
31 | 2018-10-18 오후 06:38 .
32 | 2018-10-18 오후 06:38 ..
33 | 2018-10-18 오후 06:37 bin
34 | 2018-10-18 오후 06:37 etc
35 | 2018-10-18 오후 06:37 include
36 | 2018-10-18 오후 06:38 lib
37 | 2018-10-18 오후 06:38 libexec
38 | 2018-10-18 오후 06:38 share
39 | 2018-10-18 오후 06:38 ssl
40 | 0개 파일 0 바이트
41 | 9개 디렉터리 9,383,415,808 바이트 남음
42 |
43 | C:\dev\bin\emacs>
44 | ----
45 |
46 | * `bin` 폴더 아래에 있는 `runemacs.exe` 파일을 더블 클릭하면 emacs가 실행된다.
47 |
48 |
49 | == `init.el` 파일 만들기
50 |
51 | * emacs가 실행되면, 먼저 ``init.el``이라는 파일을 읽어 들여, 실행에 필요한 초기화 작업을
52 | 수행한다.
53 |
54 | * 이 `init.el` 파일은 일반적으로 `사용자\<자신의 사용자 아이디>\AppData\Roaming\.emacs.d\`
55 | 폴더에 위치한다.
56 |
57 | * 그런데 `사용자\<자신의 사용자 아이디>` 폴더에 들어가 보아도 ``AppData``라는 폴더는
58 | 아래의 화면에서처럼 일반적으로 보이지 않게 설정되어 있다.
59 | +
60 | image:windows-appdata-no-show.png[]
61 |
62 | * 이 ``AppData`` 폴더를 보이게 하려면, '파일 탐색기'를 실행한 후, [파일 -- 폴더 및 검색
63 | 옵션 변경 -- 보기 -- 고급 설정 -- 숨김 파일 및 폴더 -- 숨김 파일, 폴더 및 드라이브 표시]
64 | 메뉴를 선택해 주고 `확인` 버튼을 눌러 준다.
65 |
66 | * 이제 `사용자\<자신의 사용자 아이디>` 폴더를 다시 확인해 보면, 다음과 같이 `AppData`
67 | 폴더가 보일 것이다.
68 | +
69 | image:windows-appdata-show.png[]
70 |
71 | * `AppData\Roaming\.emacs.d` 폴더의 위치에 `init.el` 파일을 만들어 준 후, 다음의 내용을
72 | 입력한 후 저장한다.
73 | +
74 | [listing]
75 | ----
76 | ;; Hangul
77 | (set-language-environment "Korean")
78 | (prefer-coding-system 'utf-8)
79 | (setq input-method-verbose-flag nil)
80 |
81 | ;; melpa 관련 설정
82 | (require 'package)
83 | (add-to-list 'package-archives
84 | '("melpa-stable" . "https://stable.melpa.org/packages/") t)
85 | ----
86 |
87 |
88 | == Cider 설치
89 |
90 | * emacs를 실행한다.
91 |
92 | *
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/Development-Environments/img/atom-ink-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/atom-ink-install.png
--------------------------------------------------------------------------------
/Development-Environments/img/atom-proto-repl-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/atom-proto-repl-install.png
--------------------------------------------------------------------------------
/Development-Environments/img/emacs-clojure-mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/emacs-clojure-mode.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-cursive-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-cursive-install.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-eval-in-edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-eval-in-edit.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-eval-in-repl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-eval-in-repl.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-ns-change.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-ns-change.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-ns-eval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-ns-eval.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-open-new-jdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-open-new-jdk.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-open-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-open-project.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-plugins.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-plugins.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-repl-register-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-repl-register-1.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-repl-register-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-repl-register-2.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-repl-run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-repl-run.png
--------------------------------------------------------------------------------
/Development-Environments/img/intellij-select-jdk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/intellij-select-jdk.png
--------------------------------------------------------------------------------
/Development-Environments/img/lighttable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/lighttable.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-calva-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-calva-install.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-eval-in-edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-eval-in-edit.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-eval-in-repl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-eval-in-repl.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-file-eval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-file-eval.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-repl-connect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-repl-connect.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-repl-namespace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-repl-namespace.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-repl-start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-repl-start.png
--------------------------------------------------------------------------------
/Development-Environments/img/vscode-start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/vscode-start.png
--------------------------------------------------------------------------------
/Development-Environments/img/windows-appdata-no-show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/windows-appdata-no-show.png
--------------------------------------------------------------------------------
/Development-Environments/img/windows-appdata-show.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/Development-Environments/img/windows-appdata-show.png
--------------------------------------------------------------------------------
/Development-Environments/intellij.adoc:
--------------------------------------------------------------------------------
1 | = IntelliJ + Cursive 설치
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 |
13 | * IntelliJ에 Cursive 플러그인을 추가하면 소스 브라우징, 리팩토링, 디버깅 등을 디폴트로
14 | 이용할 수 있어 편리하다.
15 |
16 | * Cursive plugin에 대한 자세한 설명은 link:https://cursive-ide.com/userguide[] 페이지를
17 | 참조한다.
18 |
19 |
20 | == IntelliJ 설치
21 |
22 | * https://www.jetbrains.com/idea/download/[]에서 윈도우즈 버전의 Community Edition을
23 | 내려받아 설치한다.
24 |
25 |
26 | == Cursive 플러그인 추가
27 |
28 | * 설치한 IntelliJ를 실행한다.
29 |
30 | * 다음과 같은 화면이 나오면 ``[Configure -- Plugins]``을 선택한다.
31 | +
32 | image:intellij-plugins.png[]
33 |
34 | * ``[Browse repositories...]`` 버튼을 선택한 후, 다음 화면에서처럼 텍스트 입력상자에
35 | ``cursive``라고 입력한 후 `install` 버튼을 눌러 ``Cursive plugin`` 설치를 마친다.
36 | +
37 | image:intellij-cursive-install.png[]
38 |
39 | * IntelliJ를 재실행한다.
40 |
41 |
42 | == Project 열기
43 |
44 | * Intellij를 재실행해서 다음과 같은 화면이 나오면, ``Import project``를 선택한다.
45 |
46 | * 그후에 앞에서 미리 만들어 두었던 ``C:\dev\projects\sample\project.clj`` 파일을 선택한
47 | 후, `OK` 버튼을 눌러 진행한다.
48 | +
49 | image:intellij-open-project.png[]
50 |
51 | * 계속해서 `Next` 버튼을 눌러 나가다가, 다음과 같은 ``Please select project JDK`` 창을
52 | 만나면 바로 아래 `+` 버튼을 눌러 준 후, ``JDK``를 선택하고 `Next` 버튼을 눌러 준다.
53 | +
54 | image:intellij-open-new-jdk.png[]
55 |
56 | * 그후에 JDK가 default로 설치된 `C:\Program Files\Java\JDK-11` 경로를 다음과 같이 선택해
57 | 준 후, `OK` 버튼을 누른다. 이후 계속해서 `Next` 버튼을 눌러 프로젝트 열기를 마친다.
58 | +
59 | image:intellij-select-jdk.png[]
60 |
61 |
62 | == REPL 등록하기
63 |
64 | Cursive에서는 REPL을 따로 등록해 주어야 한다.
65 |
66 | * [`Run -- Edit configurations...`] 메뉴를 선택하면 다음과 같은 화면이 나온다. 이때 [pass:q[+
67 | -- Clojure REPL -- Local]]을 선택한 후, `OK` 버튼을 눌러 준다.
68 | +
69 | image:intellij-repl-register-1.png[]
70 |
71 | * 다음과 같은 화면이 나오면, `Name` 란에 자신이 원하는 REPL 이름을 입력한 후 `OK` 버튼을
72 | 누른다. 여기서는 편의상 ``My REPL``로 명명하기로 한다.
73 | +
74 | image:intellij-repl-register-2.png[]
75 |
76 |
77 | == Cursive REPL 실행 예
78 |
79 | === REPL 구동하기
80 |
81 | * 다음 화면의 우측 상단의 ``우측 화살표`` 모양을 클릭하면 REPL이 구동된다.
82 |
83 | * REPL의 구동이 끝난 후, 우측 하단의 창에 `(+ 2 3)` 코드를 입력하고 `Shift-` 키를
84 | 누르면, 그 실행 결과가 우측 중앙의 REPL 창에 나타난다.
85 | +
86 | image:intellij-repl-run.png[]
87 |
88 |
89 | === namespace 전환하기
90 |
91 | * `core.clj` 편집창에 커서를 위치 시킨 후, `Alt-Shift-r` 키를 눌러 주면 REPL내의
92 | namespace를 변경할 수 있다. REPL 창에 `(in-ns 'sample.core)` 코드가 실행된 결과, 우측
93 | 상단에 ``Local sample.core``가 표시되어 namespace가 전환되었다는 사실을 확인할 수 있다.
94 | +
95 | image:intellij-ns-change.png[]
96 |
97 |
98 | === 파일 전체 평가하기
99 |
100 | * `core.clj` 편집창에 커서를 위치 시킨 후, `Alt-Shift-l` 키를 눌러 주면, `core.clj`
101 | 파일 전체가 평가된다. 그 사실이 `REPL` 창에 표시되어 있다.
102 | +
103 | image:intellij-ns-eval.png[]
104 |
105 |
106 | === REPL 창에서 코드 실행하기
107 |
108 | * 이제 우측 하단의 창에서 `(foo "Clojure")` 코드를 입력한 후 `Shift-` 키를 누르면,
109 | 그 결과가 우측 중앙의 REPL 창에 보인다.
110 | +
111 | image:intellij-eval-in-repl.png[]
112 |
113 |
114 | === 편집창에서 코드 실행하기
115 |
116 | * `core.clj` 편집창에 커서를 위치시킨 후, 아래와 같이 `(+ 10 20)` 코드를 입력해 보자. 닫는
117 | 괄호 뒤에 커서를 위치 시킨 후, `Alt-Shift-p` 키를 누르면, 그 실행 결과가 `REPL` 창에
118 | 다음과 같이 표시된다
119 | +
120 | image:intellij-eval-in-edit.png[]
121 |
--------------------------------------------------------------------------------
/Development-Environments/vscode.adoc:
--------------------------------------------------------------------------------
1 | = Visual Studio Code + Calva 설치
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 | == Visual Studio Code 설치
13 |
14 | * link:https://code.visualstudio.com/Download[] 페이지를 방문해 Windows용 VS Code(여기서는
15 | User Installer 64 bit: VSCodeUserSetup-x64-1.28.1.exe)를 내려 받는다.
16 |
17 | * 내려 받은 파일을 실행해 설치를 마친 후, VS Code를 실행한다.
18 |
19 |
20 | == Calva extension 설치
21 |
22 | * `[File -- Preferences -- Extensions]` 메뉴를 선택한다.
23 |
24 | * 다음과 같이 텍스트 입력상자에 ``calva``를 입력한 후 `install` 버튼을 눌러 Calva
25 | extension을 설치한다.
26 | +
27 | image:vscode-calva-install.png[]
28 |
29 | * 설치를 마친 후, VS Code를 재실행한다.
30 |
31 |
32 | == Calva REPL 실행 예
33 |
34 | * Calva에 대한 자세한 내용은 link:https://github.com/BetterThanTomorrow/calva[]를 참조하기
35 | 바란다.
36 |
37 |
38 | === 프로젝트 열기
39 |
40 | * VS Code를 실행한 후, `[File -- Open Folder...]` 메뉴를 선택해, 위에서 만든
41 | `C:\dev\projects\sample` 폴더를 열고, `src\sample\core.clj` 파일을 아래와 같이 연다.
42 | +
43 | image:vscode-start.png[]
44 |
45 |
46 | === REPL 실행하기
47 |
48 | * `[Termianl -- New Terminal]` 메뉴를 선택해 새 터미널 창을 연 후, 아래와 같이 `lein repl`
49 | 명령을 실행한다.
50 | +
51 | NOTE: Calva는 아직 자동으로 repl을 실행해 주지 못해서, 수동으로 이와같이 실행해 주어야
52 | 한다. 하지만 이렇게 최초에 한 번 실행해 주면, 추후에 vscode를 재실행해 줄 때에는 이
53 | 단계를 거치지 않아도 된다.
54 | +
55 | image:vscode-repl-start.png[]
56 |
57 |
58 | === REPL 연결하기
59 |
60 | * 맨 아래 상태줄에 있는 `nREPL` 부분을 클릭하면, 다음과 같이 `localhost:<포트번호>`
61 | 형식으로 작은 창이 하나 뜰 것이다. 이 상태에서 `` 키를 눌러주면 nREPL에
62 | 연결된다.
63 | +
64 | NOTE: 이렇게 최초에 한 번 연결시켜 주면, 추후에 vscode를 재실행할 때에는 이 단계를 거치지
65 | 않아도 된다.
66 | +
67 | image:vscode-repl-connect.png[]
68 |
69 |
70 | === namespace 전환하기
71 |
72 | * `core.clj` 편집창에 커서를 위치 시킨 후, `Ctrl-Alt-v n` 키를 눌러 주면 `TERMINAL` 탭의
73 | namespace가 pass:q[`user=>`]에서 pass:q[`sample.core=>`]로 바뀐다.
74 | +
75 | image:vscode-repl-namespace.png[]
76 |
77 |
78 | === 파일 전체 평가하기
79 |
80 | * `core.clj` 편집창에 커서를 위치 시킨 후, `Ctrl-Alt-v ` 키를 눌러 주면, `core.clj`
81 | 파일 전체가 평가된다. 그 사실이 `OUTPUT` 탭에 표시되어 있다.
82 | +
83 | image:vscode-file-eval.png[]
84 |
85 |
86 | === 터미널 창에서 코드 실행하기
87 |
88 | * 이제 `TERMINAL` 탭에서 `(foo "Clojure")` 코드를 입력한 후 `` 키를 입력해 다음과
89 | 같이 실행하면 그 결과가 `TERMINAL` 탭에 보일 것이다.
90 | +
91 | image:vscode-eval-in-repl.png[]
92 |
93 |
94 | === 편집창에서 코드 실행하기
95 |
96 | * `core.clj` 편집창에 커서를 위치시킨 후, 아래와 같이 `(+ 10 20)` 코드를 입력해 보자. 닫는
97 | 괄호 뒤에 커서를 위치 시킨 후, `Ctrl-Alt-v e` 키를 누르면, 그 실행 결과가 `OUTPUT` 탭에
98 | 다음과 같이 표시된다
99 | +
100 | image:vscode-eval-in-edit.png[]
101 |
--------------------------------------------------------------------------------
/Flow-Controls/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Functional-Programming/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Java-Interoperability/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Namespaces-and-Libraries/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Preface/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Preface/preface.adoc:
--------------------------------------------------------------------------------
1 | = Preface
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :linkcss:
5 | :stylesdir: ../
6 | :stylesheet: my-asciidoctor.css
7 | :docinfo1:
8 | :toc: right
9 |
10 | [preface]
11 |
12 | == 소스코드 예제 표기법
13 |
14 | 소스 코드를 실행한 결과를 표시할 때, 다음의 표기법을 사용했다. 참고로 아래에서 `;` 기호는
15 | 클로저의 주석 처리 기호로, 소스 코드를 Copy & Paste해서 실행할 때 불편이 없게 했다.
16 |
17 | [source]
18 | ....
19 | (defn get-name []
20 | (println "Enter Your Name:")
21 | (let [name (read-line)]
22 | (println "Hello," name)
23 | name))
24 |
25 | (get-name)
26 | ;>> Enter Your Name: ; <1>
27 | ;<< Mr. Kim ; <2>
28 | ;>> Hello, Mr. Kim
29 | ;=> "Mr. Kim" ; <3>
30 | ....
31 | <1> ;>> 화면에 출력된 내용을 표시한다.
32 | <2> ;<< 키보드로 입력한 내용을 표시한다.
33 | <3> ;pass:macros[=>] 함수의 반환값을 표시한다.
34 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | = Clojure Complete (클로저 완전정복)
2 | :bookseries: Clojure
3 | :doctype: book
4 | :source-language: clojure
5 | :source-highlighter: coderay
6 | //:stem: latexmath
7 | :icons: font
8 | :imagesdir: ./img
9 | :linkcss:
10 | :stylesdir: ../
11 | :stylesheet: my-asciidoctor.css
12 |
13 |
14 | === Version: 2015-12-31
15 |
16 | [sidebar]
17 | ****
18 | commit은 수시로 이루어지지만, 버전 번호는 큰 변화가 있다고 판단될 때(예를 들어, 새로운
19 | 장을 마쳤을 때)에만 올라 갑니다.
20 | ****
21 |
22 | == [small]#문서 보기 안내#
23 |
24 | github가 asciidoc 형식의 문서 내용 중 일부를 html 형식으로 제대로 변환하지 못하는 문제가
25 | 발견되었습니다. 따라서 앞으로 이곳은 문서를 보관하는 용도로만 사용하고, 실제 이 책의
26 | 내용을 열람하실 떄에는 https://clojure-kr.github.io/clojure-complete/[]에서 보시기를 권합니다.
27 |
28 |
29 | === Table of Contents
30 |
31 | 다음의 목차에서 링크가 아직 걸려 있지 않은 장은 앞으로 채워 나갈 예정입니다.
32 |
33 | :leveloffset: 1
34 |
35 | . link:Preface/preface.adoc[서문]
36 | . 왜 클로저인가?
37 | . link:Development-Environments/development-environments.adoc[개발 환경]
38 | . link:Start/start.adoc[클로저 시작하기]
39 | . link:Simple-Values/simple-values.adoc[단순값]
40 | . link:Flow-Controls/flow-controls.adoc[제어 구조]
41 | . link:Collections-and-Sequences/collections-and-sequences.adoc[컬렉션과 시퀀스]
42 | . 함수형 프로그래밍
43 | . link:Destructuring/destructuring.adoc[구조분해(Destructuring)]
44 | . 변환자(Transducers)
45 | . link:Java-Interoperability/java-interoperability.adoc[자바 코드 가져다쓰기(Java Interoperability)]
46 | . link:Namespaces-and-Libraries/namespaces-and-libraries.adoc[이름공간과 라이브러리]
47 | . 상태 관리와 동시성
48 | . core.async
49 | . 멀티메소드와 상속
50 | . 프로토콜과 레코드
51 | . 매크로
52 | . 수학
53 | . 날짜와 시간
54 | . 입출력: 파일과 디렉토리
55 | . 프로젝트 관리
56 | . 예외 처리
57 | . link:Testing/testing.adoc[테스팅]
58 | . 타입 검사
59 | . 데이타베이스 프로그래밍
60 | . 통신 및 웹 프로그래밍
61 | . 파서
62 | . 문자 인코딩
63 | . GUI 프로그래밍
64 | . link:Boot/boot.adoc[Boot 사용하기]
65 |
66 | //. link:Why-Clojure/why-clojure.adoc[Why Clojure?]
67 | //. link:Collections-and-Sequences/collections-and-sequences.adoc[Collections and Sequences]
68 | //. link:Functional-Programming/functional-programming.adoc[함수형 프로그래밍]
69 | //. link:Transducers/transducers.adoc[Transducers]
70 | //. link:Metadata/metadata.adoc[Metadata]
71 | //. link:State-Management-and-Parallel-Programming/state-management-and-parallel-programming.adoc[State Management and Parallel Programming]
72 | //. link:Core-Async/core-async.adoc[core.async]
73 | //. link:Multimedthos-and-Hierarchies/multimedthos-and-hierarchies.adoc[Multimedthos and Hierarchies]
74 | //. link:Protocols-Records-and-Types/protocols-records-and-types.adoc[Protocols, Records and Types]
75 | //. link:Macros/macros.adoc[Macros]
76 | //. link:Numerics and Mathematics/numerics-and-mathematics.adoc[Numerics and Mathematics]
77 | //. link:Project-Management/project-management.adoc[Project Management]
78 | //. link:Testing/testing.adoc[Testing]
79 | //. link:Type-Checking/type-checking.adoc[Type Checking]
80 | //. link:Database-Programming/database-programming.adoc[Database Programming]
81 | //. link:Web-Programming/web-programming.adoc[Web Programming]
82 | //. link:index.asciidoc[Index]
83 | //. link:colo.asciidoc[Colophon]
84 |
85 |
86 | :leveloffset: 0
87 |
88 | === Copyright
89 |
90 | Copyright (C) 2015. All rights reserved.
91 |
92 | 이 책의 저작권은 https://creativecommons.org/licenses/by-nc-sa/4.0/[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)]을 따른다.
93 |
94 | 즉, 다음의 조건을 준수하는 한 이 책의 자유로운 복제, 수정 및 배포가 가능하다.
95 |
96 | * 이 책의 내용을 기반으로 2차 저작물을 만들 경우 원작자를 표시하여야 한다.
97 | * 상업적 목적으로 이용할 수 없다.
98 | * 2차 저작물의 경우 위와 동일한 저작권을 사용해야 한다.
99 |
100 |
101 | === Contributing
102 |
103 | 이 책의 집필에 함께 참여하고자 하는 분들을 환영합니다. 참여를 원하시는 분은
104 | https://github.com/[github]에 먼저 사용자 계정을 만드신 후, 이 repository를 자신의
105 | 계정으로 fork합니다. 그리고 문서를 작성하신 후에 pull request를 보내 주십시오. 몇 차례의
106 | pull request가 받아들여지고, 문서의 집필에 기여하신 분의 이름이 Contributors 명단에 등록된
107 | 이후부터 자유로운 commit이 가능해집니다.
108 |
109 | 이 책의 문서 형식은 asciidoc이고, http://asciidoctor.org/[asciidoctor]를 이용해
110 | 관리됩니다. 문서 관리에 필요한 asciidoctor 프로그램 설치 정보는 link:guide[] 디렉토리
111 | 아래에 있는 문서를 참고하시기 바라며, asciidoc 문서 작성 요령은
112 | http://asciidoctor.org/docs/user-manual/[Asciidoctor User Manual]에 자세히 나와 있습니다.
113 |
114 | 보내 주신 문서는 문서의 통일성과 완결성을 위해 필요에 따라 내용의 첨삭/편집/재배치 과정을
115 | 거칠 수 있음을 미리 밝힙니다.
116 |
117 |
118 | === Contributors
119 |
120 | * 김영태 (philos99@gmail.com) Main editor
121 | * 박상규 (psk810@gmail.com)
122 | * 김만명 (manmyung@gmail.com)
123 |
124 |
--------------------------------------------------------------------------------
/Simple-Values/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Simple-Values/simple-values.adoc:
--------------------------------------------------------------------------------
1 | = Simple Values
2 | :source-highlighter: coderay
3 | :source-language: clojure
4 | :sectnums:
5 | :icons: font
6 | :imagesdir: ../img
7 | :linkcss:
8 | :stylesdir: ../
9 | :stylesheet: my-asciidoctor.css
10 | :docinfo1:
11 | :toc: right
12 |
13 |
14 | == Clojure Data Type Diagram
15 |
16 | 다음의 도표는 클로저의 모든 자료형들을 한 눈에 살펴볼 수 있도록 일목요연하게 정리한
17 | 것이다. 먼저 전체적인 지도를 마음 속에 두고 각 부분을 자세하게 살펴 나가는 것이 클로저를
18 | 빠르고 정확하게 이해하는 지름길이다. 각 자료형 옆에는 실제로 구현되어 있는 자바 클래스를
19 | 병기했다. 이 장에서는 단순 자료형(Simple values)들을 중심으로 살펴보고, 다음 장에서 복합
20 | 자료형인 Collection들을 살펴 보겠다.
21 |
22 | [[clojure-data-type-diagram]]
23 |
24 |
25 | [cols="1,1,^.^2,^.^6", width="70%", options="header"]
26 | |===
27 | | | ^| 클로저 타입 ^| 자바 클래스
28 |
29 | .13+^.^v|Immutables
30 | (= Values)
31 |
32 | .9+^.^|Simple values
33 | ^.^| Integers
34 | ^v| java.lang.Long
35 | clojure.lang.BigInt
36 |
37 | ^.^| Floats
38 | ^v| java.lang.Double +
39 | java.math.BigDecimal
40 |
41 | ^.^| Ratios ^| clojure.lang.Ratio
42 |
43 | ^.^| Strings ^| java.lang.String
44 |
45 | ^.^| Characters ^| java.lang.Character
46 |
47 | ^.^| Symbols ^| clojure.lang.Symbol
48 |
49 | ^.^| Keywords ^| clojure.lang.Keyword
50 |
51 | ^.^| Booleans ^| java.lang.Boolean
52 |
53 | ^| nil ^| null
54 |
55 |
56 | .4+^.^|Collections
57 | ^| Lists | clojure.lang.PersistentList
58 |
59 | ^| Vectors ^| clojure.lang.PersistentVector
60 |
61 | ^.^| Maps
62 | ^v| array-map: clojure.lang.PersistentArrayMap
63 | hash-map: clojure.lang.PersistentHashMap
64 | sorted-map: clojure.lang.PersistentTreeMap
65 |
66 | ^.^| Sets
67 | ^v| hash-set: clojure.lang.PersistentHashSet
68 | sorted-set: clojure.lang.PersistentTreeSet
69 |
70 | .4+^.^v|Mutables
71 | (= References)
72 |
73 | .4+^.^|Identities
74 | ^| Atoms ^| clojure.lang.Atom
75 |
76 | ^| Refs ^| clojure.lang.Ref
77 |
78 | ^| Agents ^| clojure.lang.Agent
79 |
80 | ^| Vars ^| clojure.lang.Var
81 |
82 | |===
83 |
84 |
85 | :leveloffset: 1
86 |
87 | include::sub/numbers.adoc[]
88 |
89 | :leveloffset: 0
90 |
91 |
92 | indexterm:[nil]
93 |
94 | == nil
95 |
96 | 클로저의 ``nil``은 자기 자신으로 평가되는 값이다. 자바의 `null`, 루비의 `nil`, 파이썬의
97 | ``None``과 같이 값의 부재를 표현한다.
98 |
99 | [source]
100 | ....
101 | nil ;=> nil
102 |
103 | (type nil) ;=> nil
104 | ....
105 |
106 | ``nil``은 클로저에서 논리적인 거짓(logically false)으로 취급된다. 클로저에서는 ``false``와
107 | ``nil``만을 논리적 거짓으로 판단하고, 그 이외의 모든 값은 논리적 참(logically true)으로
108 | 판단한다. 예를 들어 ``0``이나 빈 문자열 `""`, 빈 백터 `[]` 등도 논리적 참으로 취급된다.
109 |
110 | [source]
111 | ....
112 | (if nil 10 20) ;=> 20
113 | (if false 10 20) ;=> 20
114 |
115 | (if 0 10 20) ;=> 10
116 | (if "" 10 20) ;=> 10
117 | (if [] 10 20) ;=> 10
118 | ....
119 |
120 | `nil?` 함수는 주어진 인수가 ``nil``인지 판별한다. indexterm:[nil?]
121 |
122 | [source]
123 | ....
124 | (nil? nil) ;=> true
125 |
126 | (nil? false) ;=> false
127 | (nil? 0) ;=> false
128 | (nil? "") ;=> false
129 | (nil? []) ;=> false
130 | ....
131 |
132 | `some?` 함수는 주어진 인수가 ``nil``이 아닌지 판별한다. ``(not (nil? x)`` 와 같다.
133 |
134 | CAUTION: `some?` 함수는 클로저 버전 1.6부터 도입되었다. core 함수치고 꽤 늦게 도입된 것인데, 그 아래 버전에서는 컴파일 예외 발생하니 사용시 버전 주의.
135 |
136 | [source]
137 | ....
138 | (some? nil) ;=> false
139 |
140 | (some? false) ;=> true
141 | (some? 0) ;=> true
142 | (some? "") ;=> true
143 | (some? []) ;=> true
144 | ....
145 |
146 | == 불린(Booleans)
147 |
148 | 불린값으로는 ``true``와 ``false``가 있고, 역시 자기 자신으로 평가되는 값이다.
149 |
150 | [source]
151 | ....
152 | true ;=> true
153 | false ;=> false
154 |
155 | (type true) ;=> java.lang.Boolean
156 | (type false) ;=> java.lang.Boolean
157 | ....
158 |
159 | indexterm:[true?] indexterm:[false?]
160 |
161 | `true?` 함수는 주어진 인수가 '실제로 ``true``'footnote:[논리적 참(logically true)과는
162 | 다르다는 점에 주의하자.]인지 판별한다. 즉, 주어진 인자가 ``true``로 평가될 때에만
163 | ``true``를 반환한다. 그리고 `false?` 함수는 주어진 인수가 실제로 ``false``인지
164 | 판별한다. 즉, 주어진 인자가 ``false``로 평가될 때에만 ``true``를 반환한다.
165 |
166 | [source]
167 | ....
168 | (true? true) ;=> true
169 | (true? (= 1 1)) ;=> true
170 |
171 | (true? "hello") ;=> false
172 | (true? 1) ;=> false
173 |
174 | (false? false) ;=> true
175 | (false? (= 1 2)) ;=> true
176 |
177 | (false? nil) ;=> false
178 | (false? "foo") ;=> false
179 | (false? 1) ;=> false
180 | ....
181 |
182 |
183 | == 키워드(Keywords)
184 |
185 | 키워드는 임의의 식별자 앞에 콜론(`:`) 기호를 붙여 만든다. 자기 자신으로 평가되는 값으로
186 | 클로저에서 아주 많이 사용된다.
187 |
188 | indexterm:[keyword?] indexterm:[keyword]
189 |
190 | [source]
191 | ....
192 | :city ;=> :city
193 |
194 | (type :city) ;=> clojure.lang.Keyword
195 |
196 | (keyword? :city) ;=> true
197 |
198 | ;; keyword함수는 문자열을 키워드로 바꾸어 준다.
199 | (keyword "city") ;=> :city
200 | (= :city (keyword "city")) ;=> true
201 | ....
202 |
203 |
204 | 콜론은 키워드를 만들기 위한 문법적 기능을 수행하기 위한 것이지 키워드의 이름은 아니다.
205 |
206 | [source]
207 | ....
208 | (= :seoul (keyword "seoul"))
209 | (= :seoul (keyword ":seoul"))
210 | ....
211 |
212 | 키워드는 특히 키/값 쌍으로 이루어진 맵 자료형의 키로 많이 사용된다.
213 |
214 | [source]
215 | ....
216 | (def person {:name "Sandra Cruz"
217 | :city "Portland, ME"})
218 | ....
219 |
220 | 식별자 앞에 콜론을 두 개 붙이면 해당 이름공간을 가진 키워드로 확장된다. 예를 들어, 현재의
221 | 이름공간이 ``user``일 때 다음을 실행하면, ``user`` 이름공간이 붙은 키워드로 확장되는 것을
222 | 볼 수 있다.
223 |
224 | [source]
225 | ....
226 | ::address ;=> :user/address
227 | ....
228 |
229 | 이때 `namespace` 함수와 `name` 함수로, 이름공간과 키워드명 부분만을 알아낼 수
230 | 있다. indexterm:[namespce] indexterm:[name]
231 |
232 | [source]
233 | ....
234 | (name :user/address) ;=> "address"
235 | (name ::address) ;=> "address"
236 |
237 | (namespace ::address) ;=> "user"
238 | (namespace :user/address) ;=> "user"
239 |
240 | (namespace :address) ;=> nil
241 | ....
242 |
243 |
244 | == 심볼(Symbols)
245 |
246 | 클로저의 심볼은 다른 언어들에서의 식별자(identifiers)와 유사한 개념이다. 심볼은 숫자가
247 | 아닌 문자로 시작해야 하고, 그 뒤에 `*`, `+`, `-`, `=`, `?`, `!`, `$`, `%`, `&`, `_`, `|`,
248 | `<`, `>` 같은 기호와 문자들이 올 수 있다.
249 |
250 | [source]
251 | ....
252 | (def *+-=?!$%&_|<> "이런 심볼도 가능") ;=> "이런 심볼도 가능"
253 | ....
254 |
255 |
256 | 심볼은 유니코드를 지원한다.
257 |
258 | [source]
259 | ....
260 | (def 심볼1 "한글도 가능") ;=> "한글도 가능"
261 | ....
262 |
263 |
264 | 심볼은 일반적으로 어떤 값을 가리킨다. 그래서 심볼이 평가되면 가리키던 값을 반환하게
265 | 된다.
266 |
267 | [source]
268 | ....
269 | ;; 전역 심볼 a를 정의한다.
270 | (def a 10)
271 |
272 | ;; 전역 심볼 a를 평가하면, 가리키던 값 10을 반환한다.
273 | a ;=> 10
274 |
275 | ;; 지역 심볼 a를 정의한다. let 안에서 지역 심볼 a는 전역 심볼 a을 가린다(shadowing).
276 | (let [a 20]
277 | (+ 100 a))
278 | ;=> 120
279 |
280 | ;; 전역 심볼 a는 여전히 10을 가리키고 있다.
281 | a ;=> 10
282 | ....
283 |
284 |
285 | `name` 함수는 심볼을 문자열로 바꾼다. indexterm:[name]
286 |
287 | [source]
288 | ....
289 | (name 'a) ;=> "a"
290 | ....
291 |
292 |
293 | `symbol` 함수는 문자열을 심볼로 만든다. indexterm:[symbol]
294 |
295 |
296 | [source]
297 | ....
298 | (symbol "a") ;=> a
299 | (symbol "my-namespace" "a") ;=> my-namespace/a
300 | ....
301 |
302 |
303 | `symbol?` 함수는 심볼인지 여부를 확인한다. indexterm:[symbol?]
304 |
305 |
306 | [source]
307 | ....
308 | (def a 1) ;=> 1
309 | (symbol? 'a) ;=> true
310 | (symbol? a) ;=> false
311 |
312 | (symbol? "a") ;=> false
313 | (symbol? :a) ;=> false
314 | (symbol? 1) ;=> false
315 | ....
316 |
317 |
318 | == 문자(Characters)
319 |
320 | 문자는 역슬래쉬(`\`) 기호 뒤에 한 개의 문자를 덧붙여 표현한다.
321 |
322 | [source]
323 | ....
324 | \a ;=> \a
325 | \가 ;=> \가
326 |
327 | (type \a) ;=> java.lang.Character
328 | (char? \a) ;=> true
329 | ....
330 |
331 | `\u` 뒤에 16진법 숫자 4개를 덧붙여 유니코드를 직접 표현할 수도 있다. ``\o``footnote:[숫자
332 | ``0``이 아니라 알파벳 ``o``임에 주의하자.] 뒤에 8진법 숫자를 붙여 표현할 수도 있는데,
333 | `\o0` ~ `\o377` (즉, `0` ~ `255`) 사이의 숫자만 허용한다.
334 |
335 | [source]
336 | ....
337 | \u03bb ;=> \λ
338 | \o101 ;=> \A
339 | ....
340 |
341 | 이름을 갖는 특별한 문자들이 다음과 같이 정의되어 있다.
342 |
343 | * `\space`
344 | * `\newline`
345 | * `\formfeed`
346 | * `\return`
347 | * `\backspace`
348 | * `\tab`
349 |
350 |
351 | `char`함수는 정수를 문자로 바꾼다. indexterm:[char]
352 |
353 | [source]
354 | ....
355 | (char 97) ;=> \a
356 | ....
357 |
358 |
359 | `char?`는 문자인지를 판별한다. indexterm:[char?]
360 |
361 | [source]
362 | ....
363 | (char? \a) ;=> true
364 | (char? 97) ;=> false
365 | (char? "a") ;=> false
366 | ....
367 |
368 | :leveloffset: 1
369 |
370 | include::sub/strings.adoc[]
371 |
372 | :leveloffset: 0
373 |
--------------------------------------------------------------------------------
/Simple-Values/sub/strings.adoc:
--------------------------------------------------------------------------------
1 | = 문자열(Strings)
2 | :source-highlighter: coderay
3 | :source-language: clojure
4 | :sectnums:
5 | :icons: font
6 |
7 | 클로저에서 문자열 역시 자기 자신으로 평가되는 값(value)으로, 쌍따옴표(`"`)로 둘러싸 표현한다.
8 |
9 | indexterm:[string?]
10 |
11 | [source]
12 | ....
13 | "Welcome to Clojure!" ;=> "Welcome to Clojure!"
14 |
15 | (type "functional language") ;=> java.lang.String
16 | (string? "hello") ;=> true
17 | ....
18 |
19 | 자바의 `java.lang.String` 클래스를 그대로 이용하므로, `String` 클래스의 메소드도 이용할 수
20 | 있다.
21 |
22 | [source]
23 | ....
24 | (.toUpperCase "modern lisp") ;=> "MODERN LISP"
25 | ....
26 |
27 | 여러 줄의 입력도 가능하다.
28 |
29 | [source]
30 | ....
31 | "multiline strings
32 | are allowed too."
33 | ;=> "multiline strings\nare allowed too."
34 | ....
35 |
36 | `str` 함수는 주어진 인수들을 문자열로 변환한 후, 공백 없이 연결된 문자열을 반환한다. 단,
37 | ``nil``은 빈 문자열(`""`)로 변환된다. indexterm:[str]
38 |
39 | [source]
40 | ....
41 | (str) ;=> ""
42 | (str nil) ;=> ""
43 |
44 | (str 1) ;=> "1"
45 | (str 1 2 nil 3) ;=> "123"
46 |
47 | (str [1 2 3]) ;=> "[1 2 3]"
48 |
49 | (str 1 'symbol :keyword) ;=> "1symbol:keyword"
50 | (str "Hello, " "World!") ;=> "Hello, World!"
51 | ....
52 |
53 | indexterm:[format]
54 |
55 | `format` 함수는 `java.lang.String.format` 함수를 그대로 이용한다. 자세한 포맷 서식은
56 | `java.util.Formatter`
57 | http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html[관련 문서]를
58 | 참조하도록 한다.
59 |
60 | [source]
61 | ....
62 | (format "Hello there, %s" "Bob")
63 | ;=> "Hello there, Bob"
64 |
65 | (format "%5d" 3)
66 | ;=> " 3"
67 |
68 | (format "Pad with leading zeros %07d" 5432)
69 | ;=> "Pad with leading zeros 0005432"
70 |
71 | (format "Left justified :%-7d:" 5432)
72 | ;=> "Left justified :5432 :"
73 | ....
74 |
75 | indexterm:[subs]
76 |
77 | `subs` 함수는 주어진 문자열의 '시작 index(포함)'에서 '종료 index(불포함)'까지의 부분
78 | 문자열(substring)을 반환한다. index는 0부터 시작하고, '종료 index'가 주어지지 않으면,
79 | 문자열의 마지막까지 반환한다.
80 |
81 | [source]
82 | ....
83 | (subs "Clojure" 1 3) ;=> "lo"
84 | (subs "Clojure" 1) ;=> "lojure"
85 | ....
86 |
87 | == println-str/print-str/prn-str/pr-str 함수
88 |
89 | indexterm:[println-str] indexterm:[print-str] indexterm:[prn-str] indexterm:[pr-str]
90 | indexterm:[println] indexterm:[print] indexterm:[prn] indexterm:[pr]
91 |
92 | 이 함수들은 `println`/`print`/`prn`/`pr` 함수들과 관계가 있다. 함수명에 `-str`이 붙지 않은
93 | 이 함수들은, 문자열을 '반환'하는 함수가 아니라, 문자열을 stdout(표준 출력, 일반적으로
94 | 디스플레이 화면)에 '출력'하는 함수이다.
95 |
96 | [source]
97 | ....
98 | (println "Hello world.")
99 | ;>> Hello world.
100 | ;=> nil
101 |
102 | (println-str "Hello world.")
103 | ;=> "Hello world.\n"
104 | ....
105 |
106 | 위 두 함수의 출력 결과를 표시할 때, 표기 방식이 약간 다르다는 점에 먼저 주목할 필요가
107 | 있다. ``;>> `` 기호는 그 뒤의 문자열이 '화면'에 출력되었다는 것을 나타내고, `pass:c[;=>]`
108 | 기호는 이 함수의 반환값이 ``nil``이라는 것을 표시하고 있다. 즉, `println` 함수는 side
109 | effect(부수 효과)를 수행하는 함수이다. 그리고 클로저에서 부수 효과를 실행하는 함수들은
110 | 대개 `nil` 값을 반환한다.
111 |
112 | 반면에 `println-str` 함수는, ``println``을 사용했다면 화면에 출력되었어야 할 문자열을,
113 | 화면에 출력하지 않고 함수의 반환값으로 리턴한다. ``-str``이 붙고 붙지 않은 나머지 함수들의
114 | 관계도 마찬가지이다.
115 |
116 | `println` 함수는 개행 문자(newline)를 맨마지막에 추가하는 반면, `print` 함수는 개행 문자를
117 | 추가하지 않는다.
118 |
119 | [source]
120 | ....
121 | (println "foo") (println "foo")
122 | ;>> foo
123 | ;>> foo
124 | ;=> nil
125 |
126 | (print "foo") (print "foo")
127 | ;>> foofoo
128 | ;=> nil
129 | ....
130 |
131 | `prn` 함수와 `pr` 함수의 관계도 `println` 함수와 `print` 함수의 관계와 같다. 즉,
132 | 개행문자를 추가하는지 여부의 차이이다.
133 |
134 | [source]
135 | ....
136 | (prn "foo") (prn "foo")
137 | ;>> "foo"
138 | ;>> "foo"
139 | ;=> nil
140 |
141 | (pr "foo") (pr "foo")
142 | ;>> "foo""foo"
143 | ;=> nil
144 | ....
145 |
146 | 이번에는 ``println``과 ``prn``의 차이를 알아보자. 이 두 함수는 '문자열'과 '문자'를 출력할
147 | 때에만 차이가 있다.
148 |
149 | [source]
150 | ....
151 | (println 10 "foo\nbar" \A :keyword [1 2 3])
152 | ;>> 10 foo
153 | ;>> bar A :keyword [1 2 3]
154 | ;=> nil
155 |
156 | (prn 10 "foo\nbar" \A :keyword [1 2 3])
157 | ;>> 10 "foo\nbar" \A :keyword [1 2 3]
158 | ;=> nil
159 | ....
160 |
161 | 즉, 문자열 자료형을 출력할 때, `println` 함수는 '사람이 읽기 쉬운' 형태로 출력한다. 그래서
162 | 출력할 때, 겹따옴표(`"`)를 제거하고 개행 문자 ``\n``도 실제 개행을 한 결과를
163 | 보여준다. 그리고 문자 자료형인 경우에는 역슬래시(`\`) 기호를 제거한 상태로 출력해 준다.
164 | 이 두 자료형을 제외한 나머지 자료형들의 경우에는, 두 함수 모두 출력한 결과에 차이가 없다.
165 |
166 | 반면에 ``prn`` 함수는 클로저의 리더(reader) 함수인 ``read``나 `read-string` 함수가
167 | 다시 읽어 들일 수 있는 형태로 출력해 준다.
168 |
169 | [source]
170 | ....
171 | (prn "hello")
172 | ;>> "hello"
173 | ;=> nil
174 |
175 | (println "hello")
176 | ;>> hello
177 | ;=> nil
178 |
179 | (prn-str "hello")
180 | ;>> "\"hello\"\n"
181 |
182 | (println-str "hello")
183 | ;>> "hello\n"
184 | ....
185 |
186 | 다음에서 `"hello"` 문자열이 인수로 주어졌지만, 첫 번째 줄은 문자열 ``"hello"``를 반환한
187 | 반면에, 두 번째 줄은 심볼 ``hello``를 반환했다. 그래서 출력한 문자열을 문자열 그대로 클로저
188 | 리더 함수로 다시 읽어 들이고 싶다면 `prn-str` 또는 `pr-str` 함수를 사용해야 한다.
189 |
190 | [source]
191 | ....
192 | (read-string (prn-str "hello")) ;=> "hello"
193 | (read-string (println-str "hello")) ;=> hello
194 | ....
195 |
196 |
197 | == `clojure.string` 이름 공간의 문자열 처리 함수들
198 |
199 | `clojure.string` 이름 공간에는 문자열 처리시 유용한 함수들이 많다. 그 중 몇 개만
200 | 소개한다.
201 |
202 | indexterm:[upper-case] indexterm:[lower-case]
203 |
204 | ``upper-case``와 `lower-case` 함수는 각각 주어진 문자열을 대문자와 소문자로 바꾼다.
205 |
206 | [source]
207 | ....
208 | (require '[clojure.string :as str])
209 |
210 | (str/upper-case "Clojure User Groups")
211 | ;=> "CLOJURE USER GROUPS"
212 |
213 | (str/lower-case "Clojure User Groups")
214 | ;=> "clojure user groups"
215 | ....
216 |
217 | indexterm:[split]
218 |
219 | `split` 함수는 문자열과 정규식 패턴을 받아, 분할된 문자열의 벡터를 반환한다. 클로저에서
220 | 정규식은 문자열 앞에 `#` 기호를 붙여 표시하는데, 자바의 정규식 표현을 따른다.
221 |
222 | [source]
223 | ....
224 | (str/split "Clojure is awesome!" #" ")
225 | ;=> ["Clojure" "is" "awesome!"]
226 |
227 | (str/split "q1w2e3r4t5y6u7i8o9p0" #"\d+")
228 | ;=> ["q" "w" "e" "r" "t" "y" "u" "i" "o" "p"]
229 | ....
230 |
231 | 정규식 인수 뒤에 숫자를 지정하면, 해당하는 숫자만큼의 문자열들을 반환한다.
232 |
233 | [source]
234 | ....
235 | (str/split "q1w2e3r4t5y6u7i8o9p0" #"\d+" 5)
236 | ;=> ["q" "w" "e" "r" "t5y6u7i8o9p0"]
237 | ....
238 |
239 | indexterm:[join]
240 |
241 | ``join`` 함수는 인수로 주어진 컬렉션을, 문자열로 변환환 후 연결해 반환한다.
242 |
243 | [source]
244 | ....
245 | (str/join [1 2 3])
246 | ;=> "123"
247 | ....
248 |
249 | 연결할 떄 사용할 문자열을 컬렉션 앞에 지정해 주는 것이 일반적이다.
250 |
251 | [source]
252 | ....
253 | (str/join ", " ["spam" "eggs" "spam"])
254 | ;=> "spam, eggs, spam"
255 |
256 | (str/join ", " ["spam" "" "eggs" nil "spam"])
257 | ;=> "spam, , eggs, , spam"
258 |
259 | (str/join "\n" (str/split "The Quick Brown Fox" #"\s"))
260 | ;=> "The\nQuick\nBrown\nFox"
261 | ....
262 |
263 | indexterm:[trim] indexterm:[triml] indexterm:[trimr]
264 |
265 | `trim` 함수는 주어진 문자열의 좌우 끝에 있는 공백 문자들을 모두 제거한 문자열을
266 | 반환한다. ``triml``과 `trimr` 함수는 각각 주어진 문자열의 좌측과 우측 끝에 있는 공백
267 | 문자들을 제거한 문자열을 반환한다.
268 |
269 | 이 세 함수 모두 문자열 중간에 있는 공백 문자들은 제거하지 않는다.
270 |
271 | [source]
272 | ....
273 | (str/trim " my string ")
274 | ;=> "my string"
275 |
276 | (str/triml " my string ")
277 | ;=> "my string "
278 |
279 | (str/trimr " my string ")
280 | ;=> " my string"
281 | ....
282 |
283 |
284 |
285 |
--------------------------------------------------------------------------------
/Start/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Start/start.adoc:
--------------------------------------------------------------------------------
1 | = 클로저 시작하기
2 | :sectnums:
3 | :source-language: clojure
4 | :source-highlighter: coderay
5 | :linkcss:
6 | :stylesdir: ../
7 | :stylesheet: my-asciidoctor.css
8 | :docinfo1:
9 | :toc: right
10 |
11 |
12 | == 클로저 코드의 특징들
13 |
14 | 컴퓨터 언어의 역사에서 Lisp 계열 언어들(Common Lisp, Scheme, Racket, Clojure, ...)은 Algol
15 | 계열 언어들과는 다른 계보를 형성해 왔다. 오늘날의 주류 언어들(C, C++, C#, Java,
16 | JavaScript, Python, Ruby, Perl, ...)이 모두 알골계 언어들인데 반해, 클로저는 리습 계열
17 | 언어여서 실제 코드를 본 후 아마도 생소한 느낌을 갖는 사람들이 많았을 것이다. 따라서 클로저
18 | 언어를 본격적으로 익히기에 앞서, 다른 언어들과의 두드러진 차이점 몇 가지를 먼저 소개한다.
19 |
20 |
21 | === 괄호의 사용
22 |
23 | 클로저 코드를 처음 접한 사람들은 아마도 그 많은 괄호에 강한 거부감을 느꼈을 것이다. 그런
24 | 느낌은 이 글을 쓰고 있는 필자들의 경우도 예외는 아니었다. 하지만 그 형태가 아니라, 괄호가
25 | 있음으로 인해 가지게 되는 막강한 효용에 눈뜨기 시작할 때부터, 거부감의 대상이던 그
26 | 괄호들이 아름답게 보이기 시작한다. 이것은 단순한 주관적인 느낌이 아니라, 리습 언어를
27 | 알아가는 사람들의 공통된 심리적 패턴이다.
28 |
29 | 괄호가 있어서 얻을 수 있는 첫 번째 이점은, 코드의 의미가 명확해져 연산자 우선 순위를 따로
30 | 외울 필요가 없다는 점이다. 다음의 두 코드를 보면 어느 것의 의미가 명확한지는 자명하다.
31 |
32 | .C
33 | [source,c]
34 | ....
35 | a > b + c * d && e
36 | ....
37 |
38 | .Clojure
39 | [source]
40 | ....
41 | (and (> a (+ b (* c d))) e)
42 | ....
43 |
44 | 하지만, 괄호를 사용하는 진정한 위력은 매크로를 작성할 때 나온다. 리습 언어가 Programmable
45 | Programming Language라고 불리는 이유는 매크로를 통해 코드를 조작할 수 있기 때문인데, 이
46 | 괄호가 있음으로 해서 코드 조작이 수월해진다. 위의 클로저 코드를 잘 살펴보면, 이미 코드
47 | 형태 자체가 구문 트리(Syntax Tree)의 형식이어서, 이 코드를 변형하기 위해 별도의
48 | 파싱(parsing) 과정을 거칠 필요가 없기 때문이다. 지금 당장은 잘 이해가 안되더라도 매크로를
49 | 작성하다 보면 그 가치를 깨닫게 된다. 그리고 바로 그 순간부터 괄호가 아름답게 보이기
50 | 시작한다. 사실 괄호가 있음으로 해서 좀더 강력하면서도 간결한 프로그래밍이 가능해진다면,
51 | 괄호가 많다는 것이 무슨 그리 큰 대수이겠는가?
52 |
53 |
54 | === 전위 표기법(Prefix Notation)
55 |
56 | 리습 언어들에서는 연산자와 함수명이 괄호 내의 맨 앞 자리(전위 표기법: Prefix Notation)에
57 | 온다. 사실 함수명의 경우에는 C 언어나 클로저나 큰 차이가 없다. 단지 함수 이름이 괄호 밖에
58 | 있는가 안에 있는가의 차이와, 함수의 인수들 사이에 콤마를 찍느냐 마느냐의 차이밖에는
59 | 없다. 함수명의 경우에는, 약간의 차이만 있을 뿐 C 언어도 이미 전위 표기법을 사용하고 있다는
60 | 말이다.
61 |
62 | .C
63 | [source,c]
64 | ....
65 | printf("ASCII value = %d, Character = %c\n", ch , ch);
66 | ....
67 |
68 | .Clojure
69 | [source]
70 | ....
71 | (printf "ASCII value = %d, Character = %c%n" ch ch)
72 | ....
73 |
74 | 차이가 있다면 연산자의 경우인데, C 언어에서는 중위 표기법(Infix Notation)을 사용하고
75 | 클로저에서는 함수명과 마찬가지로 전위 표기법을 사용한다.
76 |
77 | .C
78 | [source,c]
79 | ....
80 | a + b + c + d + e;
81 | ....
82 |
83 | .Clojure
84 | [source]
85 | ....
86 | (+ a b c d e)
87 | ....
88 |
89 | 클로저의 경우에는 전위 표기법을 사용함으로써, 연산항이 많을 때 `+` 기호를 반복할 필요가
90 | 없다는 장점이 있다.
91 |
92 | 리습 계열 언어에서는 연산자와 함수가 다른 취급을 받지 않는다. 연산자의 경우, 수학에서 이미
93 | 중위 표기법을 사용하고 있어 대부분의 언어가 그것을 답습하고 있을 뿐, 프로그래밍에서는 굳이
94 | 그것을 구분해 처리하지 않는 것이 오히려 일관되고 편리하다. 연산자가 중간에 위치하게 되면
95 | 컴파일러에서는 이를 따로 파싱해야하는 수고를 한 번 더 거쳐야 하기 때문이다.
96 |
97 | 예를 들어, C 언어에서 `**` 연산자를 거듭제곱 연산자로 여러분이 언어에 추가하고 싶다고
98 | 가정해 보자. 그러자면 우선 C 표준을 다루는 위원회에 제안을 해야 할 것이다. 물론 이 제안이
99 | 받아들여진다는 보장도 없지만, 이 위원회가 그 타당성을 인정해 새로운 C 언어 표준에
100 | 반영하기로 했다고 가정해 보자. 그러면 그 후에 모든 C 컴파일러를 이 새로운 표준에 맞춰 다시
101 | 작성해야 할 것이고, 이 연산자를 이용해 작성한 C 소스는 구 버전의 컴파일러에서는 제대로
102 | 컴파일이 되지도 않을 것이다. 이 상황을 클로저에 적용해 보면 일은 너무도 간단해진다. 클로저
103 | 프로그래머는 다음과 같이 코드를 작성하면 된다.
104 |
105 | [source]
106 | ....
107 | (defn ** [a b]
108 | (Math/pow a b))
109 |
110 | (** 2 8) ; => 256.0
111 | ....
112 |
113 | 얼마나 간단한가? 연산자와 함수를 구별할 필요가 없는 데서 오는 편리함이다. 함수 추가하듯이
114 | 연산자를 추가하면 된다. 엄밀하게 말하자면, 클로저에는 다른 언어들에서의 연산자라는 개념이
115 | 따로 없다. 함수의 이름으로 기호를 사용할 수 있어서 오직 함수만이 존재할 뿐이다. 연산자의 중위
116 | 표기법을 과감하게 버림으로써, 다른 언어에서 언어의 표준 위원회에서나 결정할 수 있는 일을
117 | 개발자가 직접 할 수 있게 된 것이다.
118 |
119 |
120 | === 모든 것이 식(expression)이다.
121 |
122 | 클로저는 리습 계열의 언어이다. 따라서 클로저가 갖는 리습 언어로서의 특징을 먼저 이해해야
123 | 한다. 클로저에서는 모든 것이 식이다. 즉, 어떤 코드의 일부를 실행하든 전체를 실행하든
124 | 반드시 어떤 값(value)을 반환한다. 다른 언어들에서의 문(statement)이라는 개념이 클로저에는
125 | 없다.
126 |
127 | 이해를 돕기 위해, C 언어에서의 삼항 연산자(`? :`)와 `if` 문을 예로 들어 보자.
128 |
129 | 아래의 삼항 연산자는 식(expression)이어서, 이 연산자 자체가 ``10``이나 ``20``을 반환한 후
130 | 그 결과값이 ``result``에 저장된다.
131 |
132 | [source,c]
133 | ....
134 | result = a > b ? 10 : 20;
135 | ....
136 |
137 | 하지만 아래의 `if` 문은 식(expression)이 아니라 문(statement)이어서, `if` 문 자체가
138 | ``10``이나 ``20``을 반환하는 것이 아니라, `if` 문의 내부에서 `result` 변수의 상태를
139 | 변경하고 있다.
140 |
141 | [source,c]
142 | ....
143 | if (a > b) {
144 | result = 10;
145 | } else {
146 | result = 20;
147 | }
148 | ....
149 |
150 | 만약 C의 ``if``가 식이였다면 다음의 코드가 작동해야 한다(물론, 다음의 코드는 적법한 C
151 | 코드가 아니다).
152 |
153 | [source,c]
154 | ....
155 | result = if (a > b) 10 else 20;
156 | ....
157 |
158 |
159 | 이와 같이 문(statement)은 주로 어떤 명령을 수행해서 부수 효과(side effect)를 내기 위한
160 | 용도로 주로 쓰인다. 반면에 식(expression)은 코드가 어떤 값을 반환하느냐 하는 것에 관심이
161 | 있을 때 쓰인다.
162 |
163 | 그러면 이것이 왜 중요한가? 모든 코드가 식으로 구성되면, 코드의 표현력이 늘어나고 아울러
164 | 코드의 조합력이 증가한다. 왜냐하면 코드가 부수 효과 없이 어떤 값만을 반환하다면, 코드는
165 | 참조 투명성(referential transparency)이 보장되며, 또한 일급 객체(first citizen)로 다루어질
166 | 수 있어서 함수의 파라미터로 사용될 수 있기 때문이다.
167 |
168 | ``if``가 문이 아니라 식일 때, 코드의 표현력이 어떻게 증가하는지 다음의 실제 예제를 통해
169 | 살펴보자.
170 |
171 | 다음의 버전 1은, 우리가 흔히 사용하는 `if` 문의 예이다. ``n``이 참이면, ``-n``만큼
172 | 이동하고, 거짓이면 ``-1``만큼 이동한다.
173 |
174 | .Version 1
175 | [source]
176 | ....
177 | (if n ; condition
178 | (move (- n)) ; then-part
179 | (move -1)) ; else-part
180 | ....
181 |
182 | ``if``가 식이 아니라 문인 언어에 익숙해져 있는 사람들에게는 위의 코드를 별도의 함수를
183 | 사용하지 않고 더 간결하게 표현할 수 있다는 생각 자체가 떠오르지 않을 것이다. 하지만 리습
184 | 언어로 사고하는 사람들은 문제점을 발견한다. 즉, 위 코드의 문제점은 `move` 호출이 두
185 | 번씩이나 중복되어 있다는 것이다. ``if``가 식인 언어에서는, 이를 수학에서 인수분해할 때
186 | 공통 인수 뽑아내듯이 더 간단하게 다음과 같이 줄일 수 있다.
187 |
188 | .Version 2
189 | [source]
190 | ....
191 | (move (if n (- n) -1))
192 | ....
193 |
194 | 위의 코드가 C 언어에서 동작할 수 없는 이유는, `move` 함수의 첫 번째 인수 자리에 놓인 `if`
195 | 문이 어떤 값도 반환할 수 없기 때문이다. 하지만 리습 계열 언어에서는 모든 것이 식이이서,
196 | ``if``조차도 값을 반환할 수 있어 위와 같은 표현이 가능해진다.
197 |
198 | 한 걸음 더 나아가 ``-``도 한 번 더 공통 인수로 뽑아낼 수 있다.
199 |
200 | .Version 3
201 | [source]
202 | ....
203 | (move (- (if n n 1)))
204 | ....
205 |
206 | ``if``를 ``or`` 로 대치하면 더 간결해 진다.
207 |
208 | .Version 4
209 | [source]
210 | ....
211 | (move (- (or n 1)))
212 | ....
213 |
214 |
215 | 클로저에서는 반복문조차도 값을 반환한다.
216 |
217 | [source]
218 | ....
219 | (for [n [1 2 3 4 5]]
220 | (* 2 n))
221 | ; => (2 4 6 8 10)
222 | ....
223 |
224 | stdout에 결과를 출력(이것도 일종의 부수 효과이다)하기 위한 함수 ``println``조자도
225 | ``nil``이라는 값을 반환한다footnote:[참고로, 클로저에서 부수 효과를 수행하는 함수들은
226 | 대체로 ``nil``을 반환한다.]. 아래에서 `;>>` 기호는 stdout 출력 결과를, pass:q[`;=>`]
227 | 기호는 함수의 반환 결과를 표시한다.
228 |
229 | [source]
230 | ....
231 | (println "Hello" "world!")
232 | ;>> Hello world!
233 | ;=> nil
234 |
235 | ....
236 |
237 | 위와 같이 클로저와 같은 리습 계열 언어에서는 코드의 일부 또는 전체가 모두 식으로 구성되어
238 | 있다. 그래서 모든 리습 계열 언어에서는 코드를 '실행(execution)'한다고 하지 않고
239 | '평가(evaluation)'한다고 표현하는데, 그 이유는 evaluation이라는 말 자체가 접두어 e-(out)와
240 | value(값)의 합성어로, 어떤 값을 내놓는다, 즉 평가한다는 의미를 갖고 있기 때문이다. 다시
241 | 말해, 비리습 계열 언어에서의 실행한다는 말 속에는 실행 결과가 어떤 값을 내놓지 않을 수도
242 | 있다는 의미가 함축되어 있기 때문에, 리습 계열 언어에서는 평가한다는 말을 주로 사용한다.
243 |
244 | 아울러 모든 코드가 식이라는 사실은, 나중에 배우게 될 매크로(Macros)의 구현에도 대단히
245 | 중요한 의미를 지닌다.
246 |
247 |
248 | === return 문이 없다
249 |
250 | 클로저에는 값을 반환하기 위한 `return` 문이 별도로 존재하지 않는다. 마지막에 위치해 있는
251 | 식이 평가된 결과가 곧 반환값이 된다.
252 |
253 | [source]
254 | ....
255 | (defn my-add [a b]
256 | (println "LOG: Computing...")
257 | (+ a b))
258 |
259 | (my-add 1 2)
260 | ;>> LOG: Computing...
261 | ;=> 3
262 | ....
263 |
264 | 아울러 `return` 문이 아예 존재하지 않으므로, 함수 실행 도중에 함수의 실행을 종료할 수
265 | 없다. 일단 함수가 실행되면 함수의 끝에 도달해야 함수가 종료된다. 이것은 함수형 언어의
266 | 일반적인 특징이기도 하다.
267 |
268 |
269 | == 주석(Comment)
270 |
271 | 클로저에서 주석을 표현하는 방식에는 세 가지가 있다.
272 |
273 | * `;` reader macro
274 | * `comment` macro
275 | * `#_` reader macro
276 |
277 |
278 | === `;` 주석 문자
279 |
280 | 클로저에서 라인 단위 주석 문자는 ``;``이다. 이 주석 문자가 나온 부분부터 라인의 끝까지
281 | 주석으로 처리된다. 참고로, 리습 계열 언어들은 일반적으로 ``;`` 문자를 라인 주석 문자로
282 | 사용한다.
283 |
284 | 리습 계열 언어에서는 주석을 달 때 일반적으로 다음과 같은 관행을 따른다. 반드시 따라야 하는
285 | 것은 아니지만, 참고로 알아 두자.
286 |
287 | * 패키지 또는 이름공간 수준의 주석은 `;` 기호 4개를 사용한다.
288 | * 여러 개의 함수에 공통적으로 해당되는 주석은 `;` 기호 3개를 사용한다.
289 | * 함수 한 개에 대한 설명(예를 들면, 구현 알고리즘)이나, 함수 내 코드 블럭에 대한 주석은
290 | `;` 기호 2개를 사용한다. 함수 내 코드 블럭에 대한 주석인 경우에는, 주석을 코드 블럭 앞에
291 | 두고, 코드 블럭에 맞게 들여쓰기를 맞춘다.
292 | * 코드 뒤에 주석을 달 때는 `;` 기호 1개를 사용한다.
293 |
294 | 다음은 위의 관행을 따른 예제이다.
295 |
296 | [source]
297 | ....
298 | ;;;; frob namespace
299 | (ns my-project.frob)
300 |
301 | ;;; The next 20 functions do various sorts of frobbing
302 |
303 | ;; frob1 function
304 | (defn frob1 [num]
305 | ;; return double frob of num
306 | (let [tmp (ran-int num)] ; breaks if 0, fix!
307 | (double-frob tmp num :with-good-luck true)))
308 |
309 | ;; frob2 function
310 | (defn frob2 [lst]
311 | (frob-aux (first lst)))
312 | ....
313 |
314 |
315 | === `comment` 매크로
316 |
317 | `comment` 매크로는 여러 개의 최상위(top level) 코드들을 한꺼번에 모두 주석 처리하고 싶을
318 | 때 주로 사용한다.
319 |
320 | [source]
321 | ....
322 | (comment
323 | (def greeting "Hello, World!")
324 |
325 | ;; The first version of main function.
326 | ;; TODO: delete if a new version completes.
327 | (defn -main []
328 | "I can say 'Hello World'."
329 | (println greeting))
330 | )
331 |
332 | (defn hello-world [] (println "Hello, World!"))
333 |
334 | (defn -main []
335 | "I can call a function, which prints 'Hello World'."
336 | (hello-world))
337 | ....
338 |
339 | `comment` 매크로는 괄호로 둘러 싸인 부분을 주석으로 처리한 후, 반환값으로 항상 ``nil``을
340 | 반환한다. 따라서 다음과 같은 곳에서 이 매크로를 사용하면 안된다.
341 |
342 | [source]
343 | ....
344 | ;; 다음의 코드는 결과적으로 (+ 10 20 nil 30)을 계산하게 된다.
345 | ;; 이때 + 함수는 nil을 대상으로 연산을 수행할 수 없으므로 예외가 발생한다.
346 | (+ 10 20 (comment (* 2 3)) 30)
347 | ;>> NullPointerException clojure.lang.Numbers.ops
348 | ....
349 |
350 | 아울러 `comment` 매크로로 둘러싸인 코드는, 클로저 문법에 맞는 코드이어야 한다. 다음의
351 | 코드는 클로저가 읽어 들일 수 없는 코드이므로 예외가 발생했다.
352 |
353 | [source]
354 | ....
355 | (comment
356 | a : b
357 | )
358 | ;>> RuntimeException Invalid token: :
359 | ....
360 |
361 |
362 | === `#_` reader 매크로
363 |
364 | `#_` reader 매크로는 그 뒤에 나오는 형식(form) 한 개만을 주석 처리한다.
365 |
366 | CAUTION: `pass:[#_]` reader 매크로는 그 다음에 나오는 형식(form)의 소스 코드를 클로저
367 | 자료형으로 아예 읽어 들이지 않고 무시한다. 반면에 `comment` 일반 매크로는 괄호로 둘러 싸인
368 | 소스 코드를 클로저 자료형으로 일단 읽어 들인 후 무시한다는 점에서 `#_` reader 매크로와
369 | 다르다. 그래서 ``comment``의 경우에는 소스 코드를 읽어 들이는 과정에서 오류가 없어야 한다.
370 |
371 | [source]
372 | ....
373 | ;; 아래의 코드는 (+ 10 20 30)과 동일하다.
374 | (+ 10 20 #_ (* 2 3) 30) ;=> 60
375 |
376 | ;; 아래의 코드는 (+ 20 30)과 동일하다.
377 | (+ #_ 10 20 #_ (* 2 3) 30) ;=> 50
378 | ....
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
--------------------------------------------------------------------------------
/Testing/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/Testing/testing.adoc:
--------------------------------------------------------------------------------
1 | = Testing
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: ../img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 | 프로그램을 개발하는데 있어, TDD(Test Driven Development) 방법론은, 테스트와 프로그램
13 | 개발을 병행함으로써, 이미 작성된 모든 프로그램 코드의 무결성을 그때 그때 확인해 가며
14 | 개발을 진행할 수 있기 때문에, 나중에 발견될 수도 있는 버그 처리 과정을 미리 방지하게 해
15 | 준다. 아울러 테스트 코드 자체가 프로그램 코드의 훌륭한 실행 예제를 제공하므로, 해당 API의
16 | 문서화의 효과도 볼 수 있다.
17 |
18 | 언뜻 생각하기에는, 프로그램 코드와 테스트 코드를 둘 다 작성하다 보면, 시간이 더 걸리는 것
19 | 아니냐는 생각을 할 수도 있는데, 실제의 경험상으로는 그 반대다. 테스트 코드를 작성하며
20 | 코딩을 진행하면, 본 코드를 작성할 때 테스트를 염두에 두고 코드를 짜게 된다. 그 결과
21 | 테스트에 용이한 보다 단순하고 논리적인 코드를 작성하게 되어, 프로그램의 유지/보수에 더
22 | 용이한 생산적인 코드를 낳게 된다. 아울러 코드를 개선할 때마다 테스트 코드를 실행함으로써,
23 | 이전에 작성한 모든 코드들과의 호환성을 미리 검증하는 과정을 매번 거치치 되므로, 버그를
24 | 미연에 방지해 주는 효과까지 곁들어지게 되어, 결과적으로는 프로젝트를 더 짧은 시간 안에
25 | 완료할 수 있게 해 즌다. 코딩하는 시간보다 디버깅하는 시간이 훨씬 더 많이 든다는 것을 이미
26 | 경험해 본 프로그래머라면 위의 주장이 쉽게 납득되리라 본다.
27 |
28 | 클로저는 `clojure.test` 패키지에 TDD를 지원하는 기능이 준비되어 있다.
29 |
30 | == deftest & is
31 |
32 | 대부분의 테스트 코드는 `deftest` 매크로와 `is` 매크로를 이용해 작성한다.
33 |
34 | .deftest 매크로
35 | [listing]
36 | ----
37 | (deftest name expr+)
38 | name := test name을 지정한다.
39 | expr := 실제 test 코드가 작성되는 자리.
40 | ----
41 |
42 | .is 매크로
43 | [listing]
44 | ----
45 | (is predicate message?)
46 | predicate := 참 또는 거짓을 반환하는 form.
47 | message := predicate이 거짓을 반환할 경우, 출력할 메시지.
48 | ----
49 |
50 | `is` 매크로는, 테스트 실패시 출력할 메시지를, 두 번째 인수에 지정할 수도 있다.
51 |
52 | [source]
53 | ....
54 | ;; file: myproject/test/myproject/core_test.clj
55 | (ns myproject.core-test
56 | (:use [clojure.test]))
57 |
58 | (deftest add
59 | (is (= 4 (+ 2 2)))
60 | (is (= 2 (+ 2 0)) "adding zero doesn't change value"))
61 | ....
62 |
63 | `lein test` 명령을 내리면, `myproject/test` 폴더 아래의 모든 테스트 파일들을 읽어 들여
64 | 실행한다. 각 테스트 파일 안의 모든 `deftest` 문을 실행한 후, 그 결과를 보고한다.
65 |
66 | [listing]
67 | ----
68 | $ lein test
69 |
70 | lein test myproject.core-test
71 |
72 | Ran 1 tests containing 2 assertions.
73 | 0 failures, 0 errors.
74 | ----
75 |
76 | 위에서는 test 1건, assertion 2건을 처리해 실패 0건, 에러 0건이 발생했음을 보고하고 있다.
77 |
78 | 이번에는 의도적으로 테스트 실패를 유도해 보자.
79 |
80 | [source]
81 | ....
82 | (ns myproject.core-test
83 | (:use [clojure.test]))
84 |
85 | (deftest add
86 | (is (= 4 (+ 2 2)))
87 | (is (= 2 (+ 2 0)) "adding zero doesn't change value")
88 | (is (= 9 (+ 4 4))) ; error here
89 | (is (= 7 (+ 2 4)) "2 + 4 should return 6")) ; error here
90 | ....
91 |
92 | [listing]
93 | ----
94 | $ lein test
95 |
96 | lein test myproject.core-test
97 |
98 | lein test :only myproject.core-test/add
99 |
100 | FAIL in (add) (core_test.clj:7)
101 | expected: (= 9 (+ 4 4))
102 | actual: (not (= 9 8))
103 |
104 | lein test :only myproject.core-test/add
105 |
106 | FAIL in (add) (core_test.clj:8)
107 | 2 + 4 should return 6
108 | expected: (= 7 (+ 2 4))
109 | actual: (not (= 7 6))
110 |
111 | Ran 1 tests containing 4 assertions.
112 | 2 failures, 0 errors.
113 | Tests failed.
114 | ----
115 |
116 |
117 | == are
118 |
119 | .are 매크로
120 | [listing]
121 | ----
122 | (are argv expr arg*)
123 | ----
124 |
125 | ``clojure.test``는 `is` 매크로 외에도 `are` 매크로를 제공한다. 이름을 통해 예상할 수
126 | 있겠지만, 하나의 `are` 매크로는 여러 개의 `is` 매크로를 대신할 수 있다.
127 |
128 | 방금 전에 든 예를, `are` 매크로를 사용해 재작성해 보면 다음과 같다.
129 |
130 | [source]
131 | ....
132 | (ns myproject.core-test
133 | (:use [clojure.test]))
134 |
135 | (deftest add
136 | (are [sum x y] (= sum (+ x y))
137 | 4 2 2
138 | 2 2 0
139 | 9 4 4
140 | 7 2 4))
141 | ....
142 |
143 | 즉, ``sum``에 4, ``x``에 2, ``y``에 2가 각각 대입된 후, ``(= sum (+ x y))``가 수행됨을 알
144 | 수 있다.
145 |
146 | [listing]
147 | ----
148 | $ lein test
149 |
150 | lein test myproject.core-test
151 |
152 | lein test :only myproject.core-test/add
153 |
154 | FAIL in (add) (core_test.clj:5)
155 | expected: (= 9 (+ 4 4))
156 | actual: (not (= 9 8))
157 |
158 | lein test :only myproject.core-test/add
159 |
160 | FAIL in (add) (core_test.clj:5)
161 | expected: (= 7 (+ 2 4))
162 | actual: (not (= 7 6))
163 |
164 | Ran 1 tests containing 4 assertions.
165 | 2 failures, 0 errors.
166 | Tests failed.
167 | ----
168 |
169 | `are` 매크로는, 실제로는 여러 개의 `is` 매크로로 확장된다. 확장된 모습을 살펴보자.
170 |
171 | [source]
172 | ....
173 | (macroexpand '(are [sum x y] (= sum (+ x y))
174 | 4 2 2
175 | 2 2 0
176 | 9 4 4
177 | 7 2 4))
178 | ; => (do
179 | ; (clojure.test/is (= 4 (+ 2 2)))
180 | ; (clojure.test/is (= 2 (+ 2 0)))
181 | ; (clojure.test/is (= 9 (+ 4 4)))
182 | ; (clojure.test/is (= 7 (+ 2 4))))
183 | ....
184 |
185 | `is` 매크로로 모두 확장된 것을 직접 확인할 수 있다.
186 |
187 |
188 | == testing
189 |
190 | .testing 매크로
191 | [listing]
192 | ----
193 | (testing string expr+)
194 | ----
195 |
196 | `testing` 매크로는, 테스트를 그룹화하기 위한 용도로 사용되고, 테스트가 실패할 경우 출력할
197 | 메시지를 지정할 수 있다. `deftest` 매크로 안에서 사용되어야 하며, 중첩될 수 있다.
198 |
199 | [source]
200 | ....
201 | (ns myproject.core-test
202 | (:use [clojure.test]))
203 |
204 | (deftest arithmetic
205 | (testing "Addition"
206 | (testing "with positive integers"
207 | (is (= 4 (+ 2 2)))
208 | (is (= 7 (+ 3 4))))
209 | (testing "with negative integers"
210 | (is (= -5 (+ -2 -2))) ; error here
211 | (is (= -1 (+ 3 -4))) )))
212 | ....
213 |
214 | [listing]
215 | ----
216 | $ lein test
217 |
218 | lein test myproject.core-test
219 |
220 | lein test :only myproject.core-test/arithmetic
221 |
222 | FAIL in (arithmetic) (core_test.clj:10)
223 | Addition with negative integers
224 | expected: (= -5 (+ -2 -2))
225 | actual: (not (= -5 -4))
226 |
227 | Ran 1 tests containing 4 assertions.
228 | 1 failures, 0 errors.
229 | Tests failed.
230 | ----
231 |
232 |
233 | == exception 테스트
234 |
235 | ``form``에서 던진 예외가, ``exception-class``와 일치하고, 함께 전달된 메시지가
236 | ``message``와 일치하면 테스트를 통과하고, 그렇지 않으면 테스트가 실패한다.
237 |
238 | [listing]
239 | ----
240 | (thrown? exception-class form)
241 | (thrown? exception-class message form)
242 |
243 | exception-class := form에서 발생이 예상되는 예외 클래스명
244 | message := 예외가 발생할 떄, 함께 전달되는 메시지, 정규식 문자열로 표시
245 | form := 예외를 발생하는 form
246 | ----
247 |
248 | `is` 매크로 내에서, 예외가 실제로 발생하는 지를 테스트할 수 있다.
249 |
250 | [source]
251 | ....
252 | (ns myproject.core-test
253 | (:use [clojure.test]))
254 |
255 | (deftest divide-by-zero
256 | ;; ArithmeticException 예외를 발생하므로, 테스트 통과
257 | (is (thrown? ArithmeticException (/ 1 0)))
258 |
259 | ;; ArithmeticException 예외를 발생하지 않으므로, 테스트 실패
260 | (is (thrown? ArithmeticException (/ 1 2)))
261 |
262 | ;; ArithmeticException 예외를 발생하고, 이때 전달되는 메시지가 일치하므로
263 | ;; 테스트 통과
264 | (is (thrown-with-msg? ArithmeticException #"Divide by zero"
265 | (/ 2 0) ))
266 |
267 | ;; ArithmeticException 예외가 발생하지만, 이때 전달되는 메시지가 일치 안하므로
268 | ;; 테스트 실패
269 | (is (thrown-with-msg? ArithmeticException #"Incorrect message"
270 | (/ 2 0) ))
271 |
272 | ;; ArithmeticException 예외를 발생하지 않으므로, 테스트 실패
273 | (is (thrown-with-msg? ArithmeticException #"Divide by zero"
274 | (/ 1 3) )))
275 | ....
276 |
277 | [listing]
278 | ----
279 | $ lein test
280 |
281 | lein test myproject.core-test
282 |
283 | lein test :only myproject.core-test/divide-by-zero
284 |
285 | FAIL in (divide-by-zero) (core_test.clj:9)
286 | expected: (thrown? ArithmeticException (/ 1 2))
287 | actual: nil
288 |
289 | lein test :only myproject.core-test/divide-by-zero
290 |
291 | FAIL in (divide-by-zero) (core_test.clj:18)
292 | expected: (thrown-with-msg? ArithmeticException #"Incorrect message" (/ 2 0))
293 | actual: #error {
294 | :cause "Divide by zero"
295 | :via
296 | [{:type java.lang.ArithmeticException
297 | :message "Divide by zero"
298 | :at [clojure.lang.Numbers divide "Numbers.java" 158]}]
299 | :trace
300 | [[clojure.lang.Numbers divide "Numbers.java" 158]
301 | [clojure.lang.Numbers divide "Numbers.java" 3808]
302 | [myproject.core_test$fn__194$fn__202 invoke "core_test.clj" 19]
303 | [myproject.core_test$fn__194 invoke "core_test.clj" 18]
304 | [clojure.test$test_var$fn__7670 invoke "test.clj" 704]
305 | ......]}
306 |
307 | lein test :only myproject.core-test/divide-by-zero
308 |
309 | FAIL in (divide-by-zero) (core_test.clj:22)
310 | expected: (thrown-with-msg? ArithmeticException #"Divide by zero" (/ 1 3))
311 | actual: nil
312 |
313 | Ran 1 tests containing 5 assertions.
314 | 3 failures, 0 errors.
315 | Tests failed.
316 | ----
317 |
318 |
319 | == fixture 사용하기
320 |
321 | 테스트 코드를 작성하다 보면, 테스트 실행 직전 또는 직후에 실행되어야 하는 코드가
322 | 있을 수 있다. 이때 필요한 것이 바로 fixture이다.
323 |
324 | [listing]
325 | ----
326 | (use-fixtures :once fixture+)
327 | (use-fixtures :each fixture+)
328 |
329 | :once := 테스트 파일 전체에 걸쳐, fixture들을 지정된 순서대로 딱 한번만 수행한다.
330 | :each := deftest 문을 실행할 떄마다, fixture들을 지정된 순서대로 메번 수행한다.
331 | ----
332 |
333 | `:once` 옵션의 경우를 먼저 살펴보자.
334 |
335 | [source]
336 | ....
337 | (ns myproject.core-test
338 | (:use [clojure.test]))
339 |
340 | (defn fixture-1 [f]
341 | (println ":once fixutre-1 started.")
342 | ; other codes here ...
343 | (f)
344 | (println ":once fixutre-1 ended.")
345 | ; another codes here ...
346 | )
347 |
348 | (defn fixture-2 [f]
349 | (println ":once fixture-2 started.")
350 | ; other codes here ...
351 | (f)
352 | (println ":once fixture-2 ended.")
353 | ; another codes here ...
354 | )
355 |
356 | (use-fixtures :once fixture-1 fixture-2)
357 |
358 | (deftest add
359 | (is (= 3 (+ 1 2)))
360 | (is (= 8 (+ 3 5))))
361 |
362 | (deftest subtract
363 | (is (= 5 (- 10 5)))
364 | (is (= 2 (- 7 5))))
365 | ....
366 |
367 | [listing]
368 | ----
369 | $ lein test
370 |
371 | lein test myproject.core-test
372 | :once fixutre-1 started.
373 | :once fixture-2 started.
374 | :once fixture-2 ended.
375 | :once fixutre-1 ended.
376 |
377 | Ran 2 tests containing 4 assertions.
378 | 0 failures, 0 errors.
379 | ----
380 |
381 | 테스트 종료시, 지정한 fixture 함수의 순서가 역순으로 실행되는 것에 주의하라.
382 |
383 | 이번에는 `:each` 옵션의 경우를 살펴보자.
384 |
385 | [source]
386 | ....
387 | (ns myproject.core-test
388 | (:use [clojure.test]))
389 |
390 | (defn fixture-1 [f]
391 | (println ":each fixutre-1 started.")
392 | ; other codes here ...
393 | (f)
394 | (println ":each fixutre-1 ended.")
395 | ; another codes here ...
396 | )
397 |
398 | (defn fixture-2 [f]
399 | (println ":each fixture-2 started.")
400 | ; other codes here ...
401 | (f)
402 | (println ":each fixture-2 ended.")
403 | ; another codes here ...
404 | )
405 |
406 | (use-fixtures :each fixture-1 fixture-2)
407 |
408 | (deftest add
409 | (is (= 3 (+ 1 2)))
410 | (is (= 8 (+ 3 5))))
411 |
412 | (deftest subtract
413 | (is (= 5 (- 10 5)))
414 | (is (= 2 (- 7 5))))
415 | ....
416 |
417 | [listing]
418 | ----
419 | $ lein test
420 |
421 | lein test myproject.core-test
422 | :each fixutre-1 started.
423 | :each fixture-2 started.
424 | :each fixture-2 ended.
425 | :each fixutre-1 ended.
426 | :each fixutre-1 started.
427 | :each fixture-2 started.
428 | :each fixture-2 ended.
429 | :each fixutre-1 ended.
430 |
431 | Ran 2 tests containing 4 assertions.
432 | 0 failures, 0 errors.
433 | ----
434 |
435 | `deftest` 문이 실행될 때마다, `:each` 옵션 뒤에 지정한 fixture들이 지정된 순서대로
436 | 실행되는 것을 확인할 수 있다.
437 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/asciidoctor-theme/notosansmono-cjk-kr/.DS_Store
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/fonts/LICENSE:
--------------------------------------------------------------------------------
1 | This Font Software is licensed under the SIL Open Font License,
2 | Version 1.1.
3 |
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 | -----------------------------------------------------------
8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
9 | -----------------------------------------------------------
10 |
11 | PREAMBLE
12 | The goals of the Open Font License (OFL) are to stimulate worldwide
13 | development of collaborative font projects, to support the font
14 | creation efforts of academic and linguistic communities, and to
15 | provide a free and open framework in which fonts may be shared and
16 | improved in partnership with others.
17 |
18 | The OFL allows the licensed fonts to be used, studied, modified and
19 | redistributed freely as long as they are not sold by themselves. The
20 | fonts, including any derivative works, can be bundled, embedded,
21 | redistributed and/or sold with any software provided that any reserved
22 | names are not used by derivative works. The fonts and derivatives,
23 | however, cannot be released under any other type of license. The
24 | requirement for fonts to remain under this license does not apply to
25 | any document created using the fonts or their derivatives.
26 |
27 | DEFINITIONS
28 | "Font Software" refers to the set of files released by the Copyright
29 | Holder(s) under this license and clearly marked as such. This may
30 | include source files, build scripts and documentation.
31 |
32 | "Reserved Font Name" refers to any names specified as such after the
33 | copyright statement(s).
34 |
35 | "Original Version" refers to the collection of Font Software
36 | components as distributed by the Copyright Holder(s).
37 |
38 | "Modified Version" refers to any derivative made by adding to,
39 | deleting, or substituting -- in part or in whole -- any of the
40 | components of the Original Version, by changing formats or by porting
41 | the Font Software to a new environment.
42 |
43 | "Author" refers to any designer, engineer, programmer, technical
44 | writer or other person who contributed to the Font Software.
45 |
46 | PERMISSION & CONDITIONS
47 | Permission is hereby granted, free of charge, to any person obtaining
48 | a copy of the Font Software, to use, study, copy, merge, embed,
49 | modify, redistribute, and sell modified and unmodified copies of the
50 | Font Software, subject to the following conditions:
51 |
52 | 1) Neither the Font Software nor any of its individual components, in
53 | Original or Modified Versions, may be sold by itself.
54 |
55 | 2) Original or Modified Versions of the Font Software may be bundled,
56 | redistributed and/or sold with any software, provided that each copy
57 | contains the above copyright notice and this license. These can be
58 | included either as stand-alone text files, human-readable headers or
59 | in the appropriate machine-readable metadata fields within text or
60 | binary files as long as those fields can be easily viewed by the user.
61 |
62 | 3) No Modified Version of the Font Software may use the Reserved Font
63 | Name(s) unless explicit written permission is granted by the
64 | corresponding Copyright Holder. This restriction only applies to the
65 | primary font name as presented to the users.
66 |
67 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
68 | Software shall not be used to promote, endorse or advertise any
69 | Modified Version, except to acknowledge the contribution(s) of the
70 | Copyright Holder(s) and the Author(s) or with their explicit written
71 | permission.
72 |
73 | 5) The Font Software, modified or unmodified, in part or in whole,
74 | must be distributed entirely under this license, and must not be
75 | distributed under any other license. The requirement for fonts to
76 | remain under this license does not apply to any document created using
77 | the Font Software.
78 |
79 | TERMINATION
80 | This license becomes null and void if any of the above conditions are
81 | not met.
82 |
83 | DISCLAIMER
84 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
85 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
86 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
87 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
88 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
89 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
90 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
91 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
92 | OTHER DEALINGS IN THE FONT SOFTWARE.
93 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-bold.ttf
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-bold_italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-bold_italic.ttf
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-italic.ttf
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-normal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/asciidoctor-theme/notosansmono-cjk-kr/fonts/notosansmono-cjk-kr-normal.ttf
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 life888888
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/LICENSE-asciidoctor-pdf:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (C) 2014-present OpenDevise Inc. and the Asciidoctor Project
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/LICENSE-asciidoctor-pdf-cjk-kai_gen_gothic:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Rei
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/default-ext-notosansmono-cjk-kr-pdf-1-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 1.x
2 | extends: default-with-fallback-font
3 | font:
4 | catalog:
5 | merge: true
6 | Noto Sans Mono CJK KR:
7 | normal: notosansmono-cjk-kr-normal.ttf
8 | bold: notosansmono-cjk-kr-bold.ttf
9 | italic: notosansmono-cjk-kr-italic.ttf
10 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
11 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
12 | base_font_family: Noto Sans Mono CJK KR
13 | base_align: left
14 |
15 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/default-ext-notosansmono-cjk-kr-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 2.x
2 | extends: default-with-font-fallbacks
3 | font:
4 | catalog:
5 | merge: true
6 | Noto Sans Mono CJK KR:
7 | normal: notosansmono-cjk-kr-normal.ttf
8 | bold: notosansmono-cjk-kr-bold.ttf
9 | italic: notosansmono-cjk-kr-italic.ttf
10 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
11 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
12 | base_font_family: Noto Sans Mono CJK KR
13 | base_align: left
14 |
15 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/default-notosansmono-cjk-kr-pdf-1-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 1.x
2 | # Modify from Asciidoctor-PDF 1.6.2 (default + default-with-fallback-font) - Copyright (C) 2014-present OpenDevise Inc. and the Asciidoctor Project - MIT License
3 | # merge KaiGenGothicTW-theme.yml - Copyright (c) 2015 Rei - MIT License (https://github.com/chloerei/asciidoctor-pdf-cjk-kai_gen_gothic)
4 | font:
5 | catalog:
6 | # notosansmono-cjk-kr-normal.ttf Fonts supports languages in Taiwan, Hong Kong and Macau that use the Traditional Chinese variant of the Han ideograms. It also supports Hiragana, Katakana, Latin, Cyrillic, Greek and Hangul.
7 | Noto Sans Mono CJK KR:
8 | normal: notosansmono-cjk-kr-normal.ttf
9 | bold: notosansmono-cjk-kr-bold.ttf
10 | italic: notosansmono-cjk-kr-italic.ttf
11 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
12 | # M+ 1mn supports ASCII and the circled numbers used for conums
13 | M+ 1mn:
14 | normal: mplus1mn-regular-subset.ttf
15 | bold: mplus1mn-bold-subset.ttf
16 | italic: mplus1mn-italic-subset.ttf
17 | bold_italic: mplus1mn-bold_italic-subset.ttf
18 | # Add Fallback
19 | M+ 1p Fallback: mplus1p-regular-fallback.ttf
20 | Noto Emoji: notoemoji-subset.ttf
21 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
22 | page:
23 | background_color: FFFFFF
24 | layout: portrait
25 | initial_zoom: FitH
26 | margin: [0.5in, 0.67in, 0.67in, 0.67in]
27 | # margin_inner and margin_outer keys are used for recto/verso print margins when media=prepress
28 | margin_inner: 0.75in
29 | margin_outer: 0.59in
30 | size: A4
31 | base:
32 | # ORG
33 | # align: justify
34 | # 20221012 KaiGenGothicTW ADD
35 | align: left
36 | # color as hex string (leading # is optional)
37 | font_color: 333333
38 | # color as RGB array
39 | #font_color: [51, 51, 51]
40 | # color as CMYK array (approximated)
41 | #font_color: [0, 0, 0, 0.92]
42 | #font_color: [0, 0, 0, 92%]
43 | font_family: Noto Sans Mono CJK KR
44 | # choose one of these font_size/line_height_length combinations
45 | #font_size: 14
46 | #line_height_length: 20
47 | #font_size: 11.25
48 | #line_height_length: 18
49 | #font_size: 11.2
50 | #line_height_length: 16
51 | font_size: 10.5
52 | #line_height_length: 15
53 | # correct line height for Noto Serif metrics
54 | # ORG
55 | #line_height_length: 12
56 | # 20221012 KaiGenGothicTW ADD
57 | line_height_length: 15
58 | #font_size: 11.25
59 | #line_height_length: 18
60 | line_height: $base_line_height_length / $base_font_size
61 | font_size_large: round($base_font_size * 1.25)
62 | font_size_small: round($base_font_size * 0.85)
63 | font_size_min: $base_font_size * 0.75
64 | font_style: normal
65 | border_color: EEEEEE
66 | border_radius: 4
67 | border_width: 0.5
68 | role:
69 | line-through:
70 | text_decoration: line-through
71 | underline:
72 | text_decoration: underline
73 | big:
74 | font_size: $base_font_size_large
75 | small:
76 | font_size: $base_font_size_small
77 | subtitle:
78 | font_size: 0.8em
79 | font_color: 999999
80 | # FIXME vertical_rhythm is weird; we should think in terms of ems
81 | #vertical_rhythm: $base_line_height_length * 2 / 3
82 | # correct line height for Noto Serif metrics (comes with built-in line height)
83 | vertical_rhythm: $base_line_height_length
84 | horizontal_rhythm: $base_line_height_length
85 | # QUESTION should vertical_spacing be block_spacing instead?
86 | vertical_spacing: $vertical_rhythm
87 | link:
88 | font_color: 428BCA
89 | # literal is currently used for inline monospaced in prose and table cells
90 | literal:
91 | font_color: B12146
92 | font_family: M+ 1mn
93 | button:
94 | content: "[\u2009%s\u2009]"
95 | font_style: bold
96 | key:
97 | background_color: F5F5F5
98 | border_color: CCCCCC
99 | border_offset: 2
100 | border_radius: 2
101 | border_width: 0.5
102 | font_family: $literal_font_family
103 | separator: "\u202f+\u202f"
104 | mark:
105 | background_color: FFFF00
106 | border_offset: 1
107 | menu:
108 | caret_content: " \u203a "
109 | heading:
110 | align: left
111 | font_color: $base_font_color
112 | # 20221012 KaiGenGothicTW ADD
113 | font_family: $base_font_family
114 | font_style: bold
115 | # h1 is used for part titles (book doctype) or the doctitle (article doctype)
116 | h1_font_size: floor($base_font_size * 2.6)
117 | # h2 is used for chapter titles (book doctype only)
118 | h2_font_size: floor($base_font_size * 2.15)
119 | h3_font_size: round($base_font_size * 1.7)
120 | h4_font_size: $base_font_size_large
121 | h5_font_size: $base_font_size
122 | h6_font_size: $base_font_size_small
123 | #line_height: 1.4
124 | # correct line height for Noto Serif metrics (comes with built-in line height)
125 | # ORG
126 | # line_height: 1
127 | # 20221012 KaiGenGothicTW ADD
128 | line_height: 1.2
129 | # ORG
130 | # margin_top: $vertical_rhythm * 0.4
131 | # 20221012 KaiGenGothicTW ADD
132 | margin_top: $vertical_rhythm * 0.2
133 | # ORG
134 | # margin_bottom: $vertical_rhythm * 0.9
135 | # 20221012 KaiGenGothicTW ADD
136 | margin_bottom: $vertical_rhythm * 0.8
137 | min_height_after: $base_line_height_length * 1.5
138 | title_page:
139 | align: right
140 | logo:
141 | top: 10%
142 | title:
143 | top: 55%
144 | font_size: $heading_h1_font_size
145 | font_color: 999999
146 | line_height: 0.9
147 | subtitle:
148 | font_size: $heading_h3_font_size
149 | font_style: bold_italic
150 | line_height: 1
151 | authors:
152 | margin_top: $base_font_size * 1.25
153 | font_size: $base_font_size_large
154 | font_color: 181818
155 | revision:
156 | margin_top: $base_font_size * 1.25
157 | block:
158 | # ORG
159 | # margin_top: 0
160 | # ORG
161 | # margin_bottom: $vertical_rhythm
162 | # 20221012 KaiGenGothicTW ADD
163 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25]
164 | caption:
165 | align: left
166 | font_size: $base_font_size * 0.95
167 | font_style: italic
168 | # FIXME perhaps set line_height instead of / in addition to margins?
169 | # ORG
170 | # margin_inside: $vertical_rhythm / 3
171 | # 20221012 KaiGenGothicTW ADD
172 | margin_inside: $vertical_rhythm * 0.25
173 | # margin_inside: $vertical_rhythm / 4
174 | margin_outside: 0
175 | lead:
176 | font_size: $base_font_size_large
177 | line_height: 1.4
178 | abstract:
179 | font_color: 5C6266
180 | font_size: $lead_font_size
181 | line_height: $lead_line_height
182 | font_style: italic
183 | first_line_font_style: bold
184 | title:
185 | align: center
186 | font_color: $heading_font_color
187 | font_size: $heading_h4_font_size
188 | font_style: $heading_font_style
189 | admonition:
190 | # 20221012 KaiGenGothicTW ADD
191 | border_color: $base_border_color
192 | # 20221012 KaiGenGothicTW ADD
193 | border_width: $base_border_width
194 | column_rule_color: $base_border_color
195 | column_rule_width: $base_border_width
196 | padding: [0, $horizontal_rhythm, 0, $horizontal_rhythm]
197 | #icon:
198 | # tip:
199 | # name: far-lightbulb
200 | # stroke_color: 111111
201 | # size: 24
202 | label:
203 | text_transform: uppercase
204 | font_style: bold
205 | blockquote:
206 | # 20221012 KaiGenGothicTW ADD
207 | font_color: $base_font_color
208 | font_size: $base_font_size_large
209 | border_color: $base_border_color
210 | # ORG
211 | # border_width: 0
212 | # 20221012 KaiGenGothicTW ADD
213 | border_width: 5
214 | border_left_width: 5
215 | # FIXME disable negative padding bottom once margin collapsing is implemented
216 | padding: [0, $horizontal_rhythm, $block_margin_bottom * -0.75, $horizontal_rhythm + $blockquote_border_left_width / 2]
217 | cite_font_size: $base_font_size_small
218 | cite_font_color: 999999
219 | verse:
220 | font_size: $blockquote_font_size
221 | border_color: $blockquote_border_color
222 | border_width: $blockquote_border_width
223 | border_left_width: $blockquote_border_left_width
224 | padding: $blockquote_padding
225 | cite_font_size: $blockquote_cite_font_size
226 | cite_font_color: $blockquote_cite_font_color
227 | # code is used for source blocks (perhaps change to source or listing?)
228 | code:
229 | font_color: $base_font_color
230 | font_family: $literal_font_family
231 | font_size: ceil($base_font_size)
232 | padding: $code_font_size
233 | line_height: 1.25
234 | # line_gap is an experimental property to control how a background color is applied to an inline block element
235 | line_gap: 3.8
236 | background_color: F5F5F5
237 | border_color: CCCCCC
238 | border_radius: $base_border_radius
239 | border_width: 0.75
240 | conum:
241 | font_family: $literal_font_family
242 | font_color: $literal_font_color
243 | font_size: $base_font_size
244 | line_height: 4 / 3
245 | glyphs: circled
246 | example:
247 | border_color: $base_border_color
248 | border_radius: $base_border_radius
249 | border_width: 0.75
250 | # ORG
251 | # background_color: $page_background_color
252 | # 20221012 KaiGenGothicTW ADD
253 | background_color: transparent
254 | # FIXME reenable padding bottom once margin collapsing is implemented
255 | padding: [$vertical_rhythm, $horizontal_rhythm, 0, $horizontal_rhythm]
256 | image:
257 | align: left
258 | # 20221012 KaiGenGothicTW ADD
259 | scaled_width_default: 0.5
260 | prose:
261 | margin_top: $block_margin_top
262 | margin_bottom: $block_margin_bottom
263 | sidebar:
264 | background_color: EEEEEE
265 | # ORG
266 | # border_color: E1E1E1
267 | # 20221012 KaiGenGothicTW ADD
268 | border_color: FFFFFF
269 | border_radius: $base_border_radius
270 | border_width: $base_border_width
271 | # FIXME reenable padding bottom once margin collapsing is implemented
272 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, 0, $vertical_rhythm * 1.25]
273 | title:
274 | align: center
275 | font_color: $heading_font_color
276 | font_size: $heading_h4_font_size
277 | font_style: $heading_font_style
278 | # 20221012 KaiGenGothicTW ADD
279 | font_family: $heading_font_family
280 | thematic_break:
281 | border_color: $base_border_color
282 | border_style: solid
283 | border_width: $base_border_width
284 | margin_top: $vertical_rhythm * 0.5
285 | margin_bottom: $vertical_rhythm * 1.5
286 | description_list:
287 | # ORG
288 | # term_font_style: bold
289 | # 20221012 KaiGenGothicTW ADD
290 | term_font_style: italic
291 | term_spacing: $vertical_rhythm / 4
292 | description_indent: $horizontal_rhythm * 1.25
293 | outline_list:
294 | indent: $horizontal_rhythm * 1.5
295 | #marker_font_color: 404040
296 | # NOTE outline_list_item_spacing applies to list items that do not have complex content
297 | item_spacing: $vertical_rhythm / 2
298 | table:
299 | background_color: $page_background_color
300 | border_color: DDDDDD
301 | border_width: $base_border_width
302 | # ORG
303 | # cell_padding: 3
304 | # 20221012 KaiGenGothicTW ADD
305 | # HACK accounting for line-height
306 | # 20221012 KaiGenGothicTW ADD
307 | cell_padding: [3, 3, 6, 3]
308 | head:
309 | font_style: bold
310 | border_bottom_width: $base_border_width * 2.5
311 | body:
312 | stripe_background_color: F9F9F9
313 | # 20221012 KaiGenGothicTW ADD
314 | even_row_background_color: F9F9F9
315 | #odd_row_background_color:
316 | foot:
317 | background_color: F0F0F0
318 | toc:
319 | indent: $horizontal_rhythm
320 | line_height: 1.4
321 | dot_leader:
322 | #content: ". "
323 | # ORG
324 | # font_color: A9A9A9
325 | # 20221012 KaiGenGothicTW ADD
326 | font_color: DDDDDD
327 | #levels: 2 3
328 | footnotes:
329 | font_size: round($base_font_size * 0.75)
330 | item_spacing: $outline_list_item_spacing / 2
331 | header:
332 | font_size: $base_font_size_small
333 | line_height: 1
334 | vertical_align: middle
335 | footer:
336 | font_size: $base_font_size_small
337 | # 20221012 KaiGenGothicTW ADD
338 | font_color: $base_font_color
339 | # NOTE if background_color is set, background and border will span width of page
340 | border_color: DDDDDD
341 | border_width: 0.25
342 | height: $base_line_height_length * 2.5
343 | line_height: 1
344 | padding: [$base_line_height_length / 2, 1, 0, 1]
345 | vertical_align: top
346 | recto:
347 | #columns: "<50% =0% >50%"
348 | right:
349 | content: '{page-number}'
350 | verso:
351 | #columns: $footer_recto_columns
352 | left:
353 | # OTG
354 | # content: $footer_recto_right_content
355 | # 20221012 KaiGenGothicTW ADD
356 | content: '{page-number}'
357 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/default-notosansmono-cjk-kr-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 2.x
2 | # Modify from Asciidoctor-PDF 2.1.6 (default + default-with-font-fallbacks ) - Copyright (C) 2014-present OpenDevise Inc. and the Asciidoctor Project - MIT License
3 | # merge KaiGenGothicTW-theme.yml - Copyright (c) 2015 Rei - MIT License (https://github.com/chloerei/asciidoctor-pdf-cjk-kai_gen_gothic)
4 | font:
5 | catalog:
6 | # notosansmono-cjk-kr-normal.ttf Fonts supports languages in Taiwan, Hong Kong and Macau that use the Traditional Chinese variant of the Han ideograms. It also supports Hiragana, Katakana, Latin, Cyrillic, Greek and Hangul.
7 | Noto Sans Mono CJK KR:
8 | normal: notosansmono-cjk-kr-normal.ttf
9 | bold: notosansmono-cjk-kr-bold.ttf
10 | italic: notosansmono-cjk-kr-italic.ttf
11 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
12 | # M+ 1mn supports ASCII and the circled numbers used for conums
13 | M+ 1mn:
14 | normal: mplus1mn-regular-subset.ttf
15 | bold: mplus1mn-bold-subset.ttf
16 | italic: mplus1mn-italic-subset.ttf
17 | bold_italic: mplus1mn-bold_italic-subset.ttf
18 | # Add Fallback
19 | M+ 1p Fallback: mplus1p-regular-fallback.ttf
20 | Noto Emoji: notoemoji-subset.ttf
21 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
22 | page:
23 | background_color: FFFFFF
24 | layout: portrait
25 | initial_zoom: FitH
26 | margin: [0.5in, 0.67in, 0.67in, 0.67in]
27 | # margin_inner and margin_outer keys are used for recto/verso print margins when media=prepress
28 | margin_inner: 0.75in
29 | margin_outer: 0.59in
30 | size: A4
31 | base:
32 | text_align: left
33 | # color as hex string (leading # is optional)
34 | font_color: 333333
35 | # color as RGB array
36 | #font_color: [51, 51, 51]
37 | # color as CMYK array (approximated)
38 | #font_color: [0, 0, 0, 0.92]
39 | #font_color: [0, 0, 0, 92%]
40 | font_family: Noto Sans Mono CJK KR
41 | # choose one of these font_size/line_height_length combinations
42 | #font_size: 14
43 | #line_height_length: 20
44 | #font_size: 11.25
45 | #line_height_length: 18
46 | #font_size: 11.2
47 | #line_height_length: 16
48 | font_size: 10.5
49 | #line_height_length: 15
50 | # correct line height for Noto Serif metrics
51 | # ORIG
52 | # line_height_length: 12
53 | # 20221002 KaiGenGothicTW ADD
54 | line_height_length: 15
55 | #font_size: 11.25
56 | #line_height_length: 18
57 | line_height: $base_line_height_length / $base_font_size
58 | font_size_large: round($base_font_size * 1.25)
59 | font_size_small: round($base_font_size * 0.85)
60 | font_size_min: $base_font_size * 0.75
61 | font_style: normal
62 | border_color: EEEEEE
63 | border_radius: 4
64 | border_width: 0.5
65 | # 20221002 KaiGenGothicTW ADD
66 | align: left
67 | role:
68 | lead:
69 | font_size: $base_font_size_large
70 | line-through:
71 | text_decoration: line-through
72 | underline:
73 | text_decoration: underline
74 | big:
75 | font_size: $base_font_size_large
76 | small:
77 | font_size: $base_font_size_small
78 | subtitle:
79 | font_color: 999999
80 | font_size: 0.8em
81 | font_style: normal_italic
82 | # FIXME vertical_rhythm is weird; we should think in terms of ems
83 | #vertical_rhythm: $base_line_height_length * 2 / 3
84 | # correct line height for Noto Serif metrics (comes with built-in line height)
85 | vertical_rhythm: $base_line_height_length
86 | horizontal_rhythm: $base_line_height_length
87 | link:
88 | font_color: 428BCA
89 | # codespan is currently used for monospaced phrases and table cells
90 | codespan:
91 | font_color: B12146
92 | font_family: M+ 1mn
93 | # 20221002 KaiGenGothicTW NOT USE THIS
94 | # TODO: Use SansMono ???
95 | # font_family: Roboto Mono
96 | button:
97 | content: "[\u2009%s\u2009]"
98 | font_style: bold
99 | kbd:
100 | background_color: F5F5F5
101 | border_color: CCCCCC
102 | border_offset: 2
103 | border_radius: 2
104 | border_width: 0.5
105 | font_family: $codespan_font_family
106 | separator: "\u202f+\u202f"
107 | mark:
108 | background_color: FFFF00
109 | border_offset: 1
110 | menu:
111 | caret_content: " \u203a "
112 | font_style: bold
113 | heading:
114 | text_align: left
115 | font_color: $base_font_color
116 | font_style: bold
117 | # 20221002 KaiGenGothicTW ADD
118 | font_family: $base_font_family
119 | # h1 is used for part titles (book doctype) or the doctitle (article doctype)
120 | h1_font_size: floor($base_font_size * 2.6)
121 | # h2 is used for chapter titles (book doctype only)
122 | h2_font_size: floor($base_font_size * 2.15)
123 | h3_font_size: round($base_font_size * 1.7)
124 | h4_font_size: $base_font_size_large
125 | h5_font_size: $base_font_size
126 | h6_font_size: $base_font_size_small
127 | #line_height: 1.4
128 | # correct line height for Noto Serif metrics (comes with built-in line height)
129 | # ORIGIN
130 | # line_height: 1
131 | # 20221002 KaiGenGothicTW ADD
132 | line_height: 1.2
133 | # ORIGIN
134 | # margin_top: $vertical_rhythm * 0.4
135 | # 20221002 KaiGenGothicTW ADD
136 | margin_top: $vertical_rhythm * 0.2
137 | # ORIGIN
138 | # margin_bottom: $vertical_rhythm * 0.9
139 | # 20221002 KaiGenGothicTW ADD
140 | margin_bottom: $vertical_rhythm * 0.8
141 | min_height_after: $base_line_height_length * 1.5
142 | title_page:
143 | text_align: right
144 | logo:
145 | top: 10%
146 | title:
147 | top: 55%
148 | font_size: $heading_h1_font_size
149 | font_color: $role_subtitle_font_color
150 | line_height: 0.9
151 | subtitle:
152 | font_size: $heading_h3_font_size
153 | font_style: bold_italic
154 | line_height: 1
155 | authors:
156 | margin_top: $base_font_size * 1.25
157 | font_size: $base_font_size_large
158 | font_color: 181818
159 | revision:
160 | margin_top: $base_font_size * 1.25
161 | block:
162 | margin_bottom: $vertical_rhythm
163 | # 20221002 KaiGenGothicTW ADD
164 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25]
165 | caption:
166 | align: left
167 | font_size: $base_font_size * 0.95
168 | font_style: italic
169 | # FIXME perhaps set line_height instead of / in addition to margins?
170 | # ORIGIN
171 | # margin_inside: $vertical_rhythm / 3
172 | # 20221002 KaiGenGothicTW ADD
173 | margin_inside: $vertical_rhythm * 0.25
174 | margin_outside: 0
175 | abstract:
176 | font_color: 5C6266
177 | font_size: $role_lead_font_size
178 | line_height: 1.4
179 | font_style: italic
180 | first_line_font_style: bold
181 | title:
182 | text_align: center
183 | font_color: $heading_font_color
184 | font_size: $heading_h4_font_size
185 | font_style: $heading_font_style
186 | admonition:
187 | column_rule_color: $base_border_color
188 | column_rule_width: $base_border_width
189 | padding: [$vertical_rhythm / 3.0, $horizontal_rhythm, $vertical_rhythm / 3.0, $horizontal_rhythm]
190 | #icon:
191 | # tip:
192 | # name: far-lightbulb
193 | # stroke_color: 111111
194 | # size: 24
195 | label:
196 | text_transform: uppercase
197 | font_style: bold
198 | quote:
199 | font_size: $base_font_size_large
200 | # 20221002 KaiGenGothicTW ADD
201 | font_color: $base_font_color
202 | border_color: $base_border_color
203 | # ORIGIN
204 | # border_width: 0
205 | border_width: 5
206 | border_left_width: $horizontal_rhythm / 3
207 | padding: [$vertical_rhythm / 4, $horizontal_rhythm, $vertical_rhythm / 4, $horizontal_rhythm + $quote_border_left_width / 2]
208 | cite:
209 | font_size: $base_font_size_small
210 | font_color: $role_subtitle_font_color
211 | verse:
212 | font_size: $quote_font_size
213 | border_color: $quote_border_color
214 | border_width: $quote_border_width
215 | border_left_width: $quote_border_left_width
216 | padding: $quote_padding
217 | cite:
218 | font_size: $quote_cite_font_size
219 | font_color: $quote_cite_font_color
220 | # code is used for literal, listing, and source blocks and literal table cells
221 | code:
222 | font_color: $base_font_color
223 | font_family: $codespan_font_family
224 | font_size: ceil($base_font_size)
225 | padding: $code_font_size
226 | line_height: 1.25
227 | # line_gap is an experimental property to control how a background color is applied to an inline block element
228 | line_gap: 3.8
229 | background_color: F5F5F5
230 | border_color: CCCCCC
231 | border_radius: $base_border_radius
232 | border_width: 0.75
233 | conum:
234 | font_family: $codespan_font_family
235 | font_color: $codespan_font_color
236 | font_size: $base_font_size
237 | line_height: 4 / 3
238 | glyphs: circled
239 | example:
240 | border_color: $base_border_color
241 | border_radius: $base_border_radius
242 | border_width: 0.75
243 | # ORIGIN
244 | # background_color: $page_background_color
245 | # 20221002 KaiGenGothicTW ADD
246 | background_color: transparent
247 | padding: [$vertical_rhythm, $horizontal_rhythm, $vertical_rhythm, $horizontal_rhythm]
248 | image:
249 | align: left
250 | # 20221002 KaiGenGothicTW ADD
251 | align_default: left
252 | # 20221002 KaiGenGothicTW ADD
253 | scaled_width_default: 0.5
254 | prose:
255 | margin_bottom: $block_margin_bottom
256 | sidebar:
257 | background_color: EEEEEE
258 | border_color: E1E1E1
259 | border_radius: $base_border_radius
260 | border_width: $base_border_width
261 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25]
262 | title:
263 | text_align: center
264 | font_color: $heading_font_color
265 | font_size: $heading_h4_font_size
266 | font_style: $heading_font_style
267 | # 20221002 KaiGenGothicTW ADD
268 | font_family: $heading_font_family
269 | thematic_break:
270 | border_color: $base_border_color
271 | border_style: solid
272 | border_width: $base_border_width
273 | padding: [$vertical_rhythm * 0.5, 0]
274 | # 20221002 KaiGenGothicTW ADD
275 | margin_top: $vertical_rhythm * 0.5
276 | # 20221002 KaiGenGothicTW ADD
277 | margin_bottom: $vertical_rhythm * 1.5
278 | list:
279 | indent: $horizontal_rhythm * 1.5
280 | #marker_font_color: 404040
281 | # NOTE list_item_spacing only applies to list items that do not have complex content
282 | item_spacing: $vertical_rhythm / 2
283 | description_list:
284 | # ORIGIN
285 | # term_font_style: bold
286 | # 20221002 KaiGenGothicTW ADD
287 | term_font_style: italic
288 | term_spacing: $vertical_rhythm / 4
289 | description_indent: $horizontal_rhythm * 1.25
290 | callout_list:
291 | margin_top_after_code: -$block_margin_bottom / 2
292 | table:
293 | background_color: $page_background_color
294 | border_color: DDDDDD
295 | border_width: $base_border_width
296 | grid_width: $base_border_width
297 | # ORIGIN
298 | # cell_padding: 3
299 | # 20221002 KaiGenGothicTW ADD
300 | # HACK accounting for line-height
301 | cell_padding: [3, 3, 6, 3]
302 | head:
303 | font_style: bold
304 | border_bottom_width: $base_border_width * 2.5
305 | body:
306 | stripe_background_color: F9F9F9
307 | # 20221002 KaiGenGothicTW ADD
308 | even_row_background_color: F9F9F9
309 | foot:
310 | background_color: F0F0F0
311 | toc:
312 | indent: $horizontal_rhythm
313 | line_height: 1.4
314 | dot_leader:
315 | #content: ". "
316 | # ORIGIN
317 | # font_color: A9A9A9
318 | # 20221002 KaiGenGothicTW ADD
319 | font_color: DDDDDD
320 | #levels: 2 3
321 | footnotes:
322 | font_size: round($base_font_size * 0.75)
323 | item_spacing: $list_item_spacing / 2
324 | index:
325 | column_gap: $vertical_rhythm
326 | header:
327 | font_size: $base_font_size_small
328 | line_height: 1
329 | vertical_align: middle
330 | footer:
331 | font_size: $base_font_size_small
332 | # 20221002 KaiGenGothicTW ADD
333 | font_color: $base_font_color
334 | # NOTE if background_color is set, background and border will span width of page
335 | border_color: DDDDDD
336 | border_width: 0.25
337 | height: $base_line_height_length * 2.5
338 | line_height: 1
339 | padding: [$base_line_height_length / 2, 1, 0, 1]
340 | vertical_align: top
341 | recto:
342 | right:
343 | content: '{page-number}'
344 | verso:
345 | left:
346 | # ORIGIN
347 | # content: $footer_recto_right_content
348 | # 20221002 KaiGenGothicTW ADD
349 | content: '{page-number}'
350 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/notosansmono-cjk-kr-pdf-1-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 1.x
2 | # Modify from KaiGenGothicTW-theme.yml - Copyright (c) 2015 Rei - MIT License (https://github.com/chloerei/asciidoctor-pdf-cjk-kai_gen_gothic)
3 | font:
4 | catalog:
5 | Noto Sans Mono CJK KR:
6 | normal: notosansmono-cjk-kr-normal.ttf
7 | bold: notosansmono-cjk-kr-bold.ttf
8 | italic: notosansmono-cjk-kr-italic.ttf
9 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
10 | # M+ 1mn supports ASCII and the circled numbers used for conums
11 | M+ 1mn:
12 | normal: mplus1mn-regular-subset.ttf
13 | bold: mplus1mn-bold-subset.ttf
14 | italic: mplus1mn-italic-subset.ttf
15 | bold_italic: mplus1mn-bold_italic-subset.ttf
16 | # Add Fallback
17 | M+ 1p Fallback: mplus1p-regular-fallback.ttf
18 | Noto Emoji: notoemoji-subset.ttf
19 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
20 | page:
21 | background_color: ffffff
22 | layout: portrait
23 | # NOTE multiply inches by 72 to get pt values
24 | #margin: [0.5 * 72, 0.67 * 72, 0.67 * 72, 0.67 * 72]
25 | margin: [0.5in, 0.67in, 0.67in, 0.67in]
26 | # size can be a named size (e.g., A4) or custom dimensions (e.g., [8.25in, 11.69in])
27 | size: Letter
28 | base:
29 | # color as hex string (leading # is optional)
30 | font_color: 333333
31 | # color as RGB array
32 | #font_color: [51, 51, 51]
33 | # color as CMYK array (approximated)
34 | #font_color: [0, 0, 0, 0.92]
35 | #font_color: [0, 0, 0, 92%]
36 | font_family: Noto Sans Mono CJK KR
37 | # choose one of these font_size/line_height_length combinations
38 | #font_size: 14
39 | #line_height_length: 20
40 | #font_size: 11.25
41 | #line_height_length: 18
42 | #font_size: 11.2
43 | #line_height_length: 16
44 | font_size: 10.5
45 | #line_height_length: 15
46 | # correct line height for Noto Serif metrics
47 | line_height_length: 15
48 | #font_size: 11.25
49 | #line_height_length: 18
50 | line_height: $base_line_height_length / $base_font_size
51 | font_size_large: round($base_font_size * 1.25)
52 | font_size_small: round($base_font_size * 0.85)
53 | font_size_min: $base_font_size * 0.75
54 | font_style: normal
55 | align: left
56 | border_radius: 4
57 | border_width: 0.5
58 | border_color: eeeeee
59 | # FIXME vertical_rhythm is weird; we should think in terms of ems
60 | #vertical_rhythm: $base_line_height_length * 2 / 3
61 | # correct line height for Noto Serif metrics
62 | vertical_rhythm: $base_line_height_length
63 | horizontal_rhythm: $base_line_height_length
64 | link:
65 | font_color: 428bca
66 | # literal is currently used for inline monospaced in prose and table cells
67 | literal:
68 | font_color: b12146
69 | font_family: Roboto Mono
70 | heading:
71 | #font_color: 181818
72 | font_color: $base_font_color
73 | font_family: $base_font_family
74 | # h1 is used for part titles
75 | h1_font_size: floor($base_font_size * 2.6)
76 | # h2 is used for chapter titles
77 | h2_font_size: floor($base_font_size * 2.15)
78 | h3_font_size: round($base_font_size * 1.7)
79 | h4_font_size: $base_font_size_large
80 | h5_font_size: $base_font_size
81 | h6_font_size: $base_font_size_small
82 | font_style: bold
83 | #line_height: 1.4
84 | # correct line height for Noto Serif metrics
85 | line_height: 1.2
86 | margin_top: $vertical_rhythm * 0.2
87 | margin_bottom: $vertical_rhythm * 0.8
88 | title_page:
89 | align: right
90 | title_top: 55%
91 | title_font_size: $heading_h1_font_size
92 | title_font_color: 999999
93 | title_line_height: 0.9
94 | subtitle_font_size: $heading_h3_font_size
95 | subtitle_font_style: bold_italic
96 | subtitle_line_height: 1
97 | authors_margin_top: $base_font_size * 1.25
98 | authors_font_size: $base_font_size_large
99 | authors_font_color: 181818
100 | revision_margin_top: $base_font_size * 1.25
101 | #prose:
102 | # margin_top: 0
103 | # margin_bottom: $vertical_rhythm
104 | block:
105 | #margin_top: 0
106 | #margin_bottom: $vertical_rhythm
107 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25]
108 | # code is used for source blocks (perhaps change to source or listing?)
109 | caption:
110 | font_style: italic
111 | align: left
112 | # FIXME perhaps set line_height instead of / in addition to margins?
113 | margin_inside: $vertical_rhythm * 0.25
114 | margin_outside: 0
115 | code:
116 | font_color: $base_font_color
117 | #font_family: Liberation Mono
118 | #font_size: floor($base_font_size * 0.9)
119 | #font_size: 10
120 | #padding: [9.5, 9.5, 9.5, 9.5]
121 | # LiberationMono carries extra gap below line
122 | #padding: [10, 10, 7.5, 10]
123 | #line_height: 1.45
124 | font_family: $literal_font_family
125 | font_size: ceil($base_font_size)
126 | #padding: [$base_font_size, $code_font_size, $base_font_size, $code_font_size]
127 | padding: $code_font_size
128 | line_height: 1.25
129 | background_color: f5f5f5
130 | border_color: cccccc
131 | border_radius: $base_border_radius
132 | border_width: 0.75
133 | blockquote:
134 | font_color: $base_font_color
135 | font_size: $base_font_size_large
136 | border_width: 5
137 | border_color: $base_border_color
138 | cite_font_size: $base_font_size_small
139 | cite_font_color: 999999
140 | sidebar:
141 | border_color: $page_background_color
142 | border_radius: $base_border_radius
143 | border_width: $base_border_width
144 | background_color: eeeeee
145 | title_font_color: $heading_font_color
146 | title_font_family: $heading_font_family
147 | title_font_size: $heading_h4_font_size
148 | title_font_style: $heading_font_style
149 | title_align: center
150 | example:
151 | border_color: $base_border_color
152 | border_radius: $base_border_radius
153 | border_width: 0.75
154 | background_color: transparent
155 | admonition:
156 | border_color: $base_border_color
157 | border_width: $base_border_width
158 | conum:
159 | font_family: $literal_font_family
160 | font_color: $literal_font_color
161 | font_size: $base_font_size
162 | line_height: 4 / 3
163 | image:
164 | align_default: left
165 | scaled_width_default: 0.5
166 | lead:
167 | # QUESTION what about $base_font_size_large?
168 | #font_size: floor($base_line_height_length * 0.8)
169 | #font_size: floor($base_font_size * 1.15)
170 | #line_height: 1.3
171 | font_size: $base_font_size_large
172 | line_height: 1.4
173 | abstract:
174 | #font_color: 404040
175 | font_color: 5c6266
176 | font_size: $lead_font_size
177 | line_height: $lead_line_height
178 | font_style: italic
179 | thematic_break:
180 | border_color: $base_border_color
181 | margin_top: $vertical_rhythm * 0.5
182 | margin_bottom: $vertical_rhythm * 1.5
183 | description_list:
184 | term_font_style: italic
185 | description_indent: $horizontal_rhythm * 1.25
186 | outline_list:
187 | indent: $horizontal_rhythm * 1.5
188 | # NOTE item_spacing applies to list items that do not have complex content
189 | item_spacing: $vertical_rhythm / 2
190 | #marker_font_color: 404040
191 | table:
192 | background_color: $page_background_color
193 | #head_background_color:
194 | #head_font_color: $base_font_color
195 | even_row_background_color: f9f9f9
196 | #odd_row_background_color:
197 | foot_background_color: f0f0f0
198 | border_color: dddddd
199 | border_width: $base_border_width
200 | # HACK accounting for line-height
201 | cell_padding: [3, 3, 6, 3]
202 | toc:
203 | indent: $horizontal_rhythm
204 | dot_leader_color: dddddd
205 | #dot_leader_content: ". "
206 | line_height: 1.4
207 | # NOTE In addition to footer, header is also supported
208 | footer:
209 | font_size: $base_font_size_small
210 | font_color: $base_font_color
211 | # NOTE if background_color is set, background and border will span width of page
212 | border_color: dddddd
213 | border_width: 0.25
214 | height: $base_line_height_length * 2.5
215 | padding: [$base_line_height_length / 2, 1, 0, 1]
216 | valign: top
217 | #image_valign: or
218 | # additional attributes for content:
219 | # * {page-count}
220 | # * {page-number}
221 | # * {document-title}
222 | # * {document-subtitle}
223 | # * {chapter-title}
224 | # * {section-title}
225 | # * {section-or-chapter-title}
226 | recto_content:
227 | #right: '{section-or-chapter-title} | {page-number}'
228 | #right: '{document-title} | {page-number}'
229 | right: '{page-number}'
230 | #center: '{page-number}'
231 | verso_content:
232 | #left: '{page-number} | {chapter-title}'
233 | left: '{page-number}'
234 | #center: '{page-number}'
235 |
--------------------------------------------------------------------------------
/asciidoctor-theme/notosansmono-cjk-kr/themes/notosansmono-cjk-kr-theme.yml:
--------------------------------------------------------------------------------
1 | # FOR Asciidoctor-PDF 2.x
2 | # Modify from KaiGenGothicTW-theme.yml - Copyright (c) 2015 Rei - MIT License (https://github.com/chloerei/asciidoctor-pdf-cjk-kai_gen_gothic)
3 | font:
4 | catalog:
5 | Noto Sans Mono CJK KR:
6 | normal: notosansmono-cjk-kr-normal.ttf
7 | bold: notosansmono-cjk-kr-bold.ttf
8 | italic: notosansmono-cjk-kr-italic.ttf
9 | bold_italic: notosansmono-cjk-kr-bold_italic.ttf
10 | # M+ 1mn supports ASCII and the circled numbers used for conums
11 | M+ 1mn:
12 | normal: mplus1mn-regular-subset.ttf
13 | bold: mplus1mn-bold-subset.ttf
14 | italic: mplus1mn-italic-subset.ttf
15 | bold_italic: mplus1mn-bold_italic-subset.ttf
16 | # Add Fallback
17 | M+ 1p Fallback: mplus1p-regular-fallback.ttf
18 | Noto Emoji: notoemoji-subset.ttf
19 | fallbacks: [M+ 1p Fallback, Noto Emoji, Noto Sans Mono CJK KR]
20 | page:
21 | background_color: ffffff
22 | layout: portrait
23 | # NOTE multiply inches by 72 to get pt values
24 | #margin: [0.5 * 72, 0.67 * 72, 0.67 * 72, 0.67 * 72]
25 | margin: [0.5in, 0.67in, 0.67in, 0.67in]
26 | # size can be a named size (e.g., A4) or custom dimensions (e.g., [8.25in, 11.69in])
27 | size: A4
28 | base:
29 | # color as hex string (leading # is optional)
30 | font_color: 333333
31 | # color as RGB array
32 | #font_color: [51, 51, 51]
33 | # color as CMYK array (approximated)
34 | #font_color: [0, 0, 0, 0.92]
35 | #font_color: [0, 0, 0, 92%]
36 | font_family: Noto Sans Mono CJK KR
37 | # choose one of these font_size/line_height_length combinations
38 | #font_size: 14
39 | #line_height_length: 20
40 | #font_size: 11.25
41 | #line_height_length: 18
42 | #font_size: 11.2
43 | #line_height_length: 16
44 | font_size: 10.5
45 | #line_height_length: 15
46 | # correct line height for Noto Serif metrics
47 | line_height_length: 15
48 | #font_size: 11.25
49 | #line_height_length: 18
50 | line_height: $base_line_height_length / $base_font_size
51 | font_size_large: round($base_font_size * 1.25)
52 | font_size_small: round($base_font_size * 0.85)
53 | font_size_min: $base_font_size * 0.75
54 | font_style: normal
55 | align: left
56 | border_radius: 4
57 | border_width: 0.5
58 | border_color: eeeeee
59 | # FIXME vertical_rhythm is weird; we should think in terms of ems
60 | #vertical_rhythm: $base_line_height_length * 2 / 3
61 | # correct line height for Noto Serif metrics
62 | vertical_rhythm: $base_line_height_length
63 | horizontal_rhythm: $base_line_height_length
64 | link:
65 | font_color: 428bca
66 | # literal is currently used for inline monospaced in prose and table cells
67 | # [INFO] asciidoctor: WARN: the literal theme category is deprecated; use the codespan category instead
68 | # literal:
69 | # 20221002 FIX
70 | codespan:
71 | font_color: b12146
72 | font_family: M+ 1mn
73 | heading:
74 | #font_color: 181818
75 | font_color: $base_font_color
76 | font_family: $base_font_family
77 | # h1 is used for part titles
78 | h1_font_size: floor($base_font_size * 2.6)
79 | # h2 is used for chapter titles
80 | h2_font_size: floor($base_font_size * 2.15)
81 | h3_font_size: round($base_font_size * 1.7)
82 | h4_font_size: $base_font_size_large
83 | h5_font_size: $base_font_size
84 | h6_font_size: $base_font_size_small
85 | font_style: bold
86 | #line_height: 1.4
87 | # correct line height for Noto Serif metrics
88 | line_height: 1.2
89 | margin_top: $vertical_rhythm * 0.2
90 | margin_bottom: $vertical_rhythm * 0.8
91 | title_page:
92 | align: right
93 | title_top: 55%
94 | title_font_size: $heading_h1_font_size
95 | title_font_color: 999999
96 | title_line_height: 0.9
97 | subtitle_font_size: $heading_h3_font_size
98 | subtitle_font_style: bold_italic
99 | subtitle_line_height: 1
100 | authors_margin_top: $base_font_size * 1.25
101 | authors_font_size: $base_font_size_large
102 | authors_font_color: 181818
103 | revision_margin_top: $base_font_size * 1.25
104 | #prose:
105 | # margin_top: 0
106 | # margin_bottom: $vertical_rhythm
107 | block:
108 | #margin_top: 0
109 | #margin_bottom: $vertical_rhythm
110 | padding: [$vertical_rhythm, $vertical_rhythm * 1.25, $vertical_rhythm, $vertical_rhythm * 1.25]
111 | # code is used for source blocks (perhaps change to source or listing?)
112 | caption:
113 | font_style: italic
114 | align: left
115 | # FIXME perhaps set line_height instead of / in addition to margins?
116 | margin_inside: $vertical_rhythm * 0.25
117 | margin_outside: 0
118 | code:
119 | font_color: $base_font_color
120 | #font_family: Liberation Mono
121 | #font_size: floor($base_font_size * 0.9)
122 | #font_size: 10
123 | #padding: [9.5, 9.5, 9.5, 9.5]
124 | # LiberationMono carries extra gap below line
125 | #padding: [10, 10, 7.5, 10]
126 | #line_height: 1.45
127 | #font_family: $literal_font_family
128 | # 20221002 FIX literal to codespan
129 | font_family: $codespan_font_family
130 | font_size: ceil($base_font_size)
131 | #padding: [$base_font_size, $code_font_size, $base_font_size, $code_font_size]
132 | padding: $code_font_size
133 | line_height: 1.25
134 | background_color: f5f5f5
135 | border_color: cccccc
136 | border_radius: $base_border_radius
137 | border_width: 0.75
138 | # # [INFO] asciidoctor: WARN: the blockquote theme category is deprecated; use the quote category instead
139 | # blockquote:
140 | # 20221002 FIX
141 | quote:
142 | font_color: $base_font_color
143 | font_size: $base_font_size_large
144 | border_width: 5
145 | border_color: $base_border_color
146 | cite_font_size: $base_font_size_small
147 | cite_font_color: 999999
148 | sidebar:
149 | border_color: $page_background_color
150 | border_radius: $base_border_radius
151 | border_width: $base_border_width
152 | background_color: eeeeee
153 | title_font_color: $heading_font_color
154 | title_font_family: $heading_font_family
155 | title_font_size: $heading_h4_font_size
156 | title_font_style: $heading_font_style
157 | title_align: center
158 | example:
159 | border_color: $base_border_color
160 | border_radius: $base_border_radius
161 | border_width: 0.75
162 | background_color: transparent
163 | admonition:
164 | border_color: $base_border_color
165 | border_width: $base_border_width
166 | conum:
167 | #font_family: $literal_font_family
168 | # 20221002 FIX literal to codespan
169 | font_family: $codespan_font_family
170 | # 20221002 FIX literal to codespan
171 | #font_color: $literal_font_color
172 | font_color: $codespan_font_color
173 | font_size: $base_font_size
174 | line_height: 4 / 3
175 | image:
176 | align_default: left
177 | scaled_width_default: 0.5
178 | lead:
179 | # QUESTION what about $base_font_size_large?
180 | #font_size: floor($base_line_height_length * 0.8)
181 | #font_size: floor($base_font_size * 1.15)
182 | #line_height: 1.3
183 | font_size: $base_font_size_large
184 | line_height: 1.4
185 | abstract:
186 | #font_color: 404040
187 | font_color: 5c6266
188 | font_size: $lead_font_size
189 | line_height: $lead_line_height
190 | font_style: italic
191 | thematic_break:
192 | border_color: $base_border_color
193 | margin_top: $vertical_rhythm * 0.5
194 | margin_bottom: $vertical_rhythm * 1.5
195 | description_list:
196 | term_font_style: italic
197 | description_indent: $horizontal_rhythm * 1.25
198 | # [INFO] asciidoctor: WARN: the outline-list theme category is deprecated; use the list category instead
199 | # outline_list:
200 | # 20221002 FIX
201 | list:
202 | indent: $horizontal_rhythm * 1.5
203 | # NOTE item_spacing applies to list items that do not have complex content
204 | item_spacing: $vertical_rhythm / 2
205 | #marker_font_color: 404040
206 | table:
207 | background_color: $page_background_color
208 | #head_background_color:
209 | #head_font_color: $base_font_color
210 | even_row_background_color: f9f9f9
211 | #odd_row_background_color:
212 | foot_background_color: f0f0f0
213 | border_color: dddddd
214 | border_width: $base_border_width
215 | # HACK accounting for line-height
216 | cell_padding: [3, 3, 6, 3]
217 | toc:
218 | indent: $horizontal_rhythm
219 | dot_leader_color: dddddd
220 | #dot_leader_content: ". "
221 | line_height: 1.4
222 | # NOTE In addition to footer, header is also supported
223 | footer:
224 | font_size: $base_font_size_small
225 | font_color: $base_font_color
226 | # NOTE if background_color is set, background and border will span width of page
227 | border_color: dddddd
228 | border_width: 0.25
229 | height: $base_line_height_length * 2.5
230 | padding: [$base_line_height_length / 2, 1, 0, 1]
231 | valign: top
232 | #image_valign: or
233 | # additional attributes for content:
234 | # * {page-count}
235 | # * {page-number}
236 | # * {document-title}
237 | # * {document-subtitle}
238 | # * {chapter-title}
239 | # * {section-title}
240 | # * {section-or-chapter-title}
241 | recto_content:
242 | #right: '{section-or-chapter-title} | {page-number}'
243 | #right: '{document-title} | {page-number}'
244 | right: '{page-number}'
245 | #center: '{page-number}'
246 | verso_content:
247 | #left: '{page-number} | {chapter-title}'
248 | left: '{page-number}'
249 | #center: '{page-number}'
250 |
--------------------------------------------------------------------------------
/clojure-complete-html.adoc:
--------------------------------------------------------------------------------
1 | = Clojure Complete (클로저 완전정복)
2 | :bookseries: Clojure
3 | :doctype: book
4 | :source-language: clojure
5 | :source-highlighter: coderay
6 | //:stem: latexmath
7 | :linkcss:
8 | :icons: font
9 | :imagesdir: ./img
10 | :docinfo1:
11 |
12 | * github 저장소: https://github.com/clojure-kr/clojure-complete[]
13 |
14 | == [small]#Version: 2015-12-31#
15 |
16 | [sidebar]
17 | ****
18 | commit은 수시로 이루어지지만, 버전 번호는 큰 변화가 있다고 판단될 때(예를 들어, 새로운
19 | 장을 마쳤을 때)에만 올라 갑니다.
20 | ****
21 |
22 | :leveloffset: 1
23 |
24 | 다음의 목차에서 링크가 아직 걸려 있지 않은 장은 앞으로 채워 나갈 예정입니다.
25 |
26 | .Table of Contents
27 | [sidebar]
28 | ****
29 | . <>
30 | . 왜 클로저인가?
31 | . <>
32 | . <>
33 | . <>
34 | . <>
35 | . <>
36 | . 함수형 프로그래밍
37 | . <>
38 | . 변환자(Transducers)
39 | . <>
40 | . <>
41 | . 상태 관리와 동시성
42 | . core.async
43 | . 멀티메소드와 상속
44 | . 프로토콜과 레코드
45 | . 매크로
46 | . 수학
47 | . 날짜와 시간
48 | . 입출력: 파일과 디렉토리
49 | . 프로젝트 관리
50 | . 예외 처리
51 | . <>
52 | . 타입 검사
53 | . 데이타베이스 프로그래밍
54 | . 통신 및 웹 프로그래밍
55 | . 파서
56 | . 문자 인코딩
57 | . GUI 프로그래밍
58 | . <>
59 | ****
60 |
61 | //. <>
62 | //. <>
63 | //. <>
64 | //. <>
65 | //. <>
66 | //. <>
67 | //. <>
68 | //. <>
69 | //. <>
70 | //. <>
71 | //. <>
72 | //. <>
73 | //. <>
74 | //. <>
75 | //. <>
76 |
77 |
78 | :leveloffset: 0
79 |
80 | == [small]#Copyright#
81 |
82 | Copyright (C) 2015. All rights reserved.
83 |
84 | 이 책의 저작권은 https://creativecommons.org/licenses/by-nc-sa/4.0/[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)]을 따른다.
85 |
86 | 즉, 다음의 조건을 준수하는 한 이 책의 자유로운 복제, 수정 및 배포가 가능하다.
87 |
88 | * 이 책의 내용을 기반으로 2차 저작물을 만들 경우 원작자를 표시하여야 한다.
89 | * 상업적 목적으로 이용할 수 없다.
90 | * 2차 저작물의 경우 위와 동일한 저작권을 사용해야 한다.
91 |
92 |
93 | == [small]#Contributing#
94 |
95 | 이 책의 집필에 함께 참여하고자 하는 분들을 환영합니다. 참여를 원하시는 분은
96 | https://github.com/[github]에 먼저 사용자 계정을 만드신 후, github의
97 | https://github.com/clojure-kr/clojure-complete[clojure-complete 저장소]를 자신의 계정으로
98 | fork합니다. 그리고 문서를 작성하신 후에 pull request를 보내 주십시오. 몇 차례의 pull
99 | request가 받아들여지고, 문서의 집필에 기여하신 분의 이름이 Contributors 명단에 등록된
100 | 이후부터 자유로운 commit이 가능해집니다.
101 |
102 | 이 책의 문서 형식은 asciidoc이고, http://asciidoctor.org/[asciidoctor]를 이용해
103 | 관리됩니다. 문서 관리에 필요한 asciidoctor 프로그램 설치 정보는 <>디렉토리
104 | 아래에 있는 문서를 참고하시기 바라며, asciidoc 문서 작성 요령은
105 | http://asciidoctor.org/docs/user-manual/[Asciidoctor User Manual]에 자세히 나와 있습니다.
106 |
107 | 보내 주신 문서는 문서의 통일성과 완결성을 위해 필요에 따라 내용의 첨삭/편집/재배치 과정을
108 | 거칠 수 있음을 미리 밝힙니다.
109 |
110 |
111 | == [small]#Contributors#
112 |
113 | * 김영태 (philos99@gmail.com) Main editor
114 | * 박상규 (psk810@gmail.com)
115 | * 김만명 (manmyung@gmail.com)
116 |
--------------------------------------------------------------------------------
/clojure-complete-pdf.adoc:
--------------------------------------------------------------------------------
1 | = Clojure Complete (클로저 완전정복)
2 | :bookseries: Clojure
3 | :doctype: book
4 | :source-language: clojure
5 | :source-highlighter: coderay
6 | //:stem: latexmath
7 | :icons: font
8 | :imagesdir: ./img
9 | :toc:
10 | :toclevels: 1
11 |
12 | [colophon]
13 | == Copyright
14 |
15 | 이 책의 저작권은 https://creativecommons.org/licenses/by-nc-sa/4.0/[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)]을 따른다.
16 |
17 | 즉, 다음의 조건을 준수하는 한 이 책의 자유로운 복제, 수정 및 배포가 가능하다.
18 |
19 | * 이 책의 내용을 기반으로 2차 저작물을 만들 경우 원작자를 표시하여야 한다.
20 | * 상업적 목적으로 이용할 수 없다.
21 | * 2차 저작물의 경우 위와 동일한 저작권을 사용해야 한다.
22 |
23 |
24 | == Contributing
25 |
26 | 이 책의 집필에 함께 참여하고자 하는 분들을 환영합니다. 참여를 원하시는 분은
27 | https://github.com/[github]에 먼저 사용자 계정을 만드신 후, 이 repository를 자신의
28 | 계정으로 fork합니다. 그리고 문서를 작성하신 후에 pull request를 보내 주시면 됩니다. 최초
29 | pull request가 받아들여진 후에 Contributors 명단에 문서의 집필에 기여하신 분의 이름이
30 | 등재될 것입니다.
31 |
32 | 이 책의 문서 형식은 asciidoc이고, http://asciidoctor.org/[asciidoctor]를 이용해
33 | 관리됩니다. 문서 관리에 필요한 asciidoctor 프로그램 설치 정보는 internal 디렉토리 밑에
34 | 있으니 참고하기 바라며, asciidoc 문서 작성 요령은
35 | http://asciidoctor.org/docs/user-manual/[Asciidoctor User Manual]에 자세히 나와 있습니다.
36 |
37 | 보내 주신 문서는 문서의 통일성과 완결성을 위해 필요에 따라 편집과 재배치의 과정을 거칠 수
38 | 있음을 미리 밝힙니다.
39 |
40 |
41 | == Contributors
42 |
43 | * 김영태 (philos99@gmail.com) Main editor
44 | * 박상규 (psk810@gmail.com)
45 | * 김만명 (manmyung@gmail.com)
46 |
47 |
48 | :leveloffset: 1
49 |
50 | include::Preface/preface.adoc[]
51 |
52 | :sectnums:
53 |
54 | //include::Development-Environments/development-environments.adoc[]
55 |
56 | //include::Leiningen/leiningen.adoc[]
57 |
58 | //include::Start/start.adoc[]
59 |
60 | //include::Simple-Data-Types/simple-data-types.adoc[]
61 |
62 | //include::Flow-Controls/flow-controls.adoc[]
63 |
64 | //include::Collections-and-Sequences/collections-and-sequences.adoc[]
65 |
66 | //include::Functions-and-Functional-Programming/functions-and-functional-programming.adoc[]
67 |
68 | //include::Destructuring/destructuring.adoc[]
69 |
70 | //include::Recursions/recursions.adoc[]
71 |
72 | //include::Transducers/transducers.adoc[]
73 |
74 | //include::Java-Interoperability/java-interoperability.adoc[]
75 |
76 | //include::Metadata/metadata.adoc[]
77 |
78 | include::Namespaces-and-Libraries/namespaces-and-libraries.adoc[]
79 |
80 | //include::State-Management-and-Parallel-Programming/state-management-and-parallel-programming.adoc[]
81 |
82 | //include::Core-Async/core-async.adoc[]
83 |
84 | //include::Multimedthos-and-Hierarchies/multimedthos-and-hierarchies.adoc[]
85 |
86 | //include::Protocols-Records-and-Types/protocols-records-and-types.adoc[]
87 |
88 | //include::Macros/macros.adoc[]
89 |
90 | //include::Numerics and Mathematics/numerics-and-mathematics.adoc[]
91 |
92 | //include::Project-Management/project-management.adoc[]
93 |
94 | //include::Testing/testing.adoc[]
95 |
96 | //include::Type-Checking/type-checking.adoc[]
97 |
98 | //include::Database-Programming/database-programming.adoc[]
99 |
100 | //include::Web-Programming/web-programming.adoc[]
101 |
102 | //include::index.asciidoc[]
103 |
104 | //include::colo.asciidoc[]
105 |
106 | :leveloffset: 0
107 |
108 |
--------------------------------------------------------------------------------
/coderay-asciidoctor.css:
--------------------------------------------------------------------------------
1 | /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
2 | /*pre.CodeRay {background-color:#f7f7f8;}*/
3 | .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
4 | .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
5 | .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
6 | table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
7 | table.CodeRay td{vertical-align: top;line-height:1.45}
8 | table.CodeRay td.line-numbers{text-align:right}
9 | table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
10 | table.CodeRay td.code{padding:0 0 0 .5em}
11 | table.CodeRay td.code>pre{padding:0}
12 | .CodeRay .debug{color:#fff !important;background:#000080 !important}
13 | .CodeRay .annotation{color:#007}
14 | .CodeRay .attribute-name{color:#000080}
15 | .CodeRay .attribute-value{color:#700}
16 | .CodeRay .binary{color:#509}
17 | .CodeRay .comment{color:#998;font-style:italic}
18 | .CodeRay .char{color:#04d}
19 | .CodeRay .char .content{color:#04d}
20 | .CodeRay .char .delimiter{color:#039}
21 | .CodeRay .class{color:#458;font-weight:bold}
22 | .CodeRay .complex{color:#a08}
23 | .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
24 | .CodeRay .color{color:#099}
25 | .CodeRay .class-variable{color:#369}
26 | .CodeRay .decorator{color:#b0b}
27 | .CodeRay .definition{color:#099}
28 | .CodeRay .delimiter{color:#000}
29 | .CodeRay .doc{color:#970}
30 | .CodeRay .doctype{color:#34b}
31 | .CodeRay .doc-string{color:#d42}
32 | .CodeRay .escape{color:#666}
33 | .CodeRay .entity{color:#800}
34 | .CodeRay .error{color:#808}
35 | .CodeRay .exception{color:inherit}
36 | .CodeRay .filename{color:#099}
37 | .CodeRay .function{color:#900;font-weight:bold}
38 | .CodeRay .global-variable{color:#008080}
39 | .CodeRay .hex{color:#058}
40 | .CodeRay .integer,.CodeRay .float{color:#099}
41 | .CodeRay .include{color:#555}
42 | .CodeRay .inline{color:#000}
43 | .CodeRay .inline .inline{background:#ccc}
44 | .CodeRay .inline .inline .inline{background:#bbb}
45 | .CodeRay .inline .inline-delimiter{color:#d14}
46 | .CodeRay .inline-delimiter{color:#d14}
47 | .CodeRay .important{color:#555;font-weight:bold}
48 | .CodeRay .interpreted{color:#b2b}
49 | .CodeRay .instance-variable{color:#008080}
50 | .CodeRay .label{color:#970}
51 | .CodeRay .local-variable{color:#963}
52 | .CodeRay .octal{color:#40e}
53 | .CodeRay .predefined{color:#369}
54 | .CodeRay .preprocessor{color:#579}
55 | .CodeRay .pseudo-class{color:#555}
56 | .CodeRay .directive{font-weight:bold}
57 | .CodeRay .type{font-weight:bold}
58 | .CodeRay .predefined-type{color:inherit}
59 | .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
60 | .CodeRay .key{color:#808}
61 | .CodeRay .key .delimiter{color:#606}
62 | .CodeRay .key .char{color:#80f}
63 | .CodeRay .value{color:#088}
64 | .CodeRay .regexp .delimiter{color:#808}
65 | .CodeRay .regexp .content{color:#808}
66 | .CodeRay .regexp .modifier{color:#808}
67 | .CodeRay .regexp .char{color:#d14}
68 | .CodeRay .regexp .function{color:#404;font-weight:bold}
69 | .CodeRay .string{color:#d20}
70 | .CodeRay .string .string .string{background:#ffd0d0}
71 | .CodeRay .string .content{color:#d14}
72 | .CodeRay .string .char{color:#d14}
73 | .CodeRay .string .delimiter{color:#d14}
74 | .CodeRay .shell{color:#d14}
75 | .CodeRay .shell .delimiter{color:#d14}
76 | .CodeRay .symbol{color:#990073}
77 | .CodeRay .symbol .content{color:#a60}
78 | .CodeRay .symbol .delimiter{color:#630}
79 | .CodeRay .tag{color:#008080}
80 | .CodeRay .tag-special{color:#d70}
81 | .CodeRay .variable{color:#036}
82 | .CodeRay .insert{background:#afa}
83 | .CodeRay .delete{background:#faa}
84 | .CodeRay .change{color:#aaf;background:#007}
85 | .CodeRay .head{color:#f8f;background:#505}
86 | .CodeRay .insert .insert{color:#080}
87 | .CodeRay .delete .delete{color:#800}
88 | .CodeRay .change .change{color:#66f}
89 | .CodeRay .head .head{color:#f4f}
--------------------------------------------------------------------------------
/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/guide/asciidoctor.adoc:
--------------------------------------------------------------------------------
1 | = asciidoctor 사용법
2 | :linkcss:
3 | :sectnums:
4 | :stylesdir: ../
5 | :stylesheet: my-asciidoctor.css
6 |
7 | == ruby 설치
8 |
9 | asciidoctor는 루비 언어로 작성되어 있으므로, 먼저 ruby를 설치한다. 다음은 리눅스
10 | Ubuntu에서 설치한 예이다.
11 |
12 | $ sudo apt-get install ruby
13 |
14 |
15 | == asciidoctor 설치
16 |
17 | asciidoctor gem을 설치한다. 참고로, 루비에서는 라이브러리를 gem이라 부른다.
18 |
19 | $ sudo gem install asciidoctor
20 |
21 |
22 | == coderay 설치
23 |
24 | syntax highlighting을 위해 coderay gem을 설치한다.
25 |
26 | $ sudo gem install coderay
27 |
28 |
29 | == asciidoctor-pdf 설치
30 |
31 | pdf 변환을 위해 asciidoctor-pdf gem을 설치한다.
32 |
33 | $ sudo gem install --pre asciidoctor-pdf
34 |
35 |
36 | == asciidoctor-pdf-cjk-kai_gen_gothic 설치
37 |
38 | asciidoctor-pdf만으로 pdf를 만들면 한글이 제대로 출력되지 않는다. 따라서
39 | asciidoctor-pdf-cjk-kai_gen_gothic gem을 추가로 설치해 주어야 한다.
40 |
41 | $ sudo gem install asciidoctor-pdf-cjk-kai_gen_gothic
42 |
43 |
44 | == asciidoctor-pdf-cjk-kai_gen_gothic-install 실행
45 |
46 | 다음을 실행해 pdf 생성에 필요한 폰트 파일을 다운로드 받는다. 한 번만 실행해 주면 된다.
47 |
48 | $ sudo asciidoctor-pdf-cjk-kai_gen_gothic-install
49 |
50 |
51 | == pdf 만들기
52 |
53 | $ asciidoctor-pdf -r asciidoctor-pdf-cjk-kai_gen_gothic -a pdf-style=KaiGenGothicKR sample.adoc
54 |
55 | WARNING: 위의 방식으로 pdf를 생성할 때, mathjax를 이용한 수식 처리는 아직 제대로 되지 않는다는 점에
56 | 주의한다.
57 |
58 |
59 | == install asciidoctor-mathematical
60 |
61 | * 참고: https://github.com/asciidoctor/asciidoctor-mathematical
62 |
63 | $ sudo apt install ruby-dev
64 | $ sudo apt install bison flex libffi-dev libxml2-dev libgdk-pixbuf2.0-dev \
65 | libcairo2-dev libpango1.0-dev ttf-lyx
66 |
67 | $ sudo add-apt-repository ppa:george-edison55/cmake-3.x
68 | $ sudo apt-get update
69 | $ sudo apt-get install cmake
70 |
71 | $ sudo gem install asciidoctor-mathematical
72 |
73 | $ asciidoctor-pdf -r asciidoctor-pdf-cjk-kai_gen_gothic -r asciidoctor-mathematical \
74 | -a pdf-style=KaiGenGothicKR sample.adoc
75 |
76 |
77 | == Chrome plugin asciidoctor.js 설치
78 |
79 | asciidoctor.js Chrome plugin을 설치한 후 크롬 브라우저 상에서 asciidoctor 문서를 열면,
80 | 문서를 저장할 때마다 실시간(실제로는 2초 간격)으로 변경된 내용이 반영되어 나타나므로
81 | 설치하는 것이 편리하다.
82 |
83 |
--------------------------------------------------------------------------------
/guide/asciidoctor.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure-kr/clojure-complete/eb11771112b54c0b8bbe337a8718e50271a2f09a/guide/asciidoctor.pdf
--------------------------------------------------------------------------------
/guide/asciidoctor.pdfmarks:
--------------------------------------------------------------------------------
1 | [ /Title
2 | /Author null
3 | /Subject null
4 | /Keywords null
5 | /ModDate (D:20150904205714)
6 | /CreationDate (D:20150904205714)
7 | /Creator (Asciidoctor PDF 1.5.0.alpha.9, based on Prawn 2.0.2)
8 | /Producer null
9 | /DOCINFO pdfmark
10 |
--------------------------------------------------------------------------------
/guide/chores.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | $dirs = %w(Why-Clojure Development-Environments Leiningen Start Basic-Data-Types
4 | Flow-Controls Collections-and-Data-Structures Functions-and-Functional-Programming
5 | Destructuring Recursions Transducers Java-Interoperability Metadata
6 | Namespaces-and-Libraries State-Management-and-Parallel-Programming Core-Async
7 | Multimedthos-and-Hierarchies Protocols-Records-and-Types Macros
8 | Numerics-and-Mathematics Project-Management Testing Type-Checking
9 | Database-Programming Web-Programming)
10 |
11 | def init_dirs ()
12 | $dirs.each do |dir|
13 | `rm -rf #{dir}`
14 | `mkdir #{dir}`
15 | `touch "#{dir}/#{dir.downcase}.adoc"`
16 | end
17 | end
18 |
19 | def remove_htmls ()
20 | $dirs.each do |dir|
21 | `rm "#{dir}/#{dir.downcase}.html"`
22 | end
23 | end
24 |
25 | # remove_htmls
26 |
27 |
28 |
--------------------------------------------------------------------------------
/guide/coderay-asciidoctor.css:
--------------------------------------------------------------------------------
1 | /* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
2 | /*pre.CodeRay {background-color:#f7f7f8;}*/
3 | .CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
4 | .CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
5 | .CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
6 | table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
7 | table.CodeRay td{vertical-align: top;line-height:1.45}
8 | table.CodeRay td.line-numbers{text-align:right}
9 | table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
10 | table.CodeRay td.code{padding:0 0 0 .5em}
11 | table.CodeRay td.code>pre{padding:0}
12 | .CodeRay .debug{color:#fff !important;background:#000080 !important}
13 | .CodeRay .annotation{color:#007}
14 | .CodeRay .attribute-name{color:#000080}
15 | .CodeRay .attribute-value{color:#700}
16 | .CodeRay .binary{color:#509}
17 | .CodeRay .comment{color:#998;font-style:italic}
18 | .CodeRay .char{color:#04d}
19 | .CodeRay .char .content{color:#04d}
20 | .CodeRay .char .delimiter{color:#039}
21 | .CodeRay .class{color:#458;font-weight:bold}
22 | .CodeRay .complex{color:#a08}
23 | .CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
24 | .CodeRay .color{color:#099}
25 | .CodeRay .class-variable{color:#369}
26 | .CodeRay .decorator{color:#b0b}
27 | .CodeRay .definition{color:#099}
28 | .CodeRay .delimiter{color:#000}
29 | .CodeRay .doc{color:#970}
30 | .CodeRay .doctype{color:#34b}
31 | .CodeRay .doc-string{color:#d42}
32 | .CodeRay .escape{color:#666}
33 | .CodeRay .entity{color:#800}
34 | .CodeRay .error{color:#808}
35 | .CodeRay .exception{color:inherit}
36 | .CodeRay .filename{color:#099}
37 | .CodeRay .function{color:#900;font-weight:bold}
38 | .CodeRay .global-variable{color:#008080}
39 | .CodeRay .hex{color:#058}
40 | .CodeRay .integer,.CodeRay .float{color:#099}
41 | .CodeRay .include{color:#555}
42 | .CodeRay .inline{color:#000}
43 | .CodeRay .inline .inline{background:#ccc}
44 | .CodeRay .inline .inline .inline{background:#bbb}
45 | .CodeRay .inline .inline-delimiter{color:#d14}
46 | .CodeRay .inline-delimiter{color:#d14}
47 | .CodeRay .important{color:#555;font-weight:bold}
48 | .CodeRay .interpreted{color:#b2b}
49 | .CodeRay .instance-variable{color:#008080}
50 | .CodeRay .label{color:#970}
51 | .CodeRay .local-variable{color:#963}
52 | .CodeRay .octal{color:#40e}
53 | .CodeRay .predefined{color:#369}
54 | .CodeRay .preprocessor{color:#579}
55 | .CodeRay .pseudo-class{color:#555}
56 | .CodeRay .directive{font-weight:bold}
57 | .CodeRay .type{font-weight:bold}
58 | .CodeRay .predefined-type{color:inherit}
59 | .CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
60 | .CodeRay .key{color:#808}
61 | .CodeRay .key .delimiter{color:#606}
62 | .CodeRay .key .char{color:#80f}
63 | .CodeRay .value{color:#088}
64 | .CodeRay .regexp .delimiter{color:#808}
65 | .CodeRay .regexp .content{color:#808}
66 | .CodeRay .regexp .modifier{color:#808}
67 | .CodeRay .regexp .char{color:#d14}
68 | .CodeRay .regexp .function{color:#404;font-weight:bold}
69 | .CodeRay .string{color:#d20}
70 | .CodeRay .string .string .string{background:#ffd0d0}
71 | .CodeRay .string .content{color:#d14}
72 | .CodeRay .string .char{color:#d14}
73 | .CodeRay .string .delimiter{color:#d14}
74 | .CodeRay .shell{color:#d14}
75 | .CodeRay .shell .delimiter{color:#d14}
76 | .CodeRay .symbol{color:#990073}
77 | .CodeRay .symbol .content{color:#a60}
78 | .CodeRay .symbol .delimiter{color:#630}
79 | .CodeRay .tag{color:#008080}
80 | .CodeRay .tag-special{color:#d70}
81 | .CodeRay .variable{color:#036}
82 | .CodeRay .insert{background:#afa}
83 | .CodeRay .delete{background:#faa}
84 | .CodeRay .change{color:#aaf;background:#007}
85 | .CodeRay .head{color:#f8f;background:#505}
86 | .CodeRay .insert .insert{color:#080}
87 | .CodeRay .delete .delete{color:#800}
88 | .CodeRay .change .change{color:#66f}
89 | .CodeRay .head .head{color:#f4f}
--------------------------------------------------------------------------------
/guide/demo.adoc:
--------------------------------------------------------------------------------
1 | =
2 | :source-language: clojure
3 | :source-highlighter: coderay
4 | :sectnums:
5 | :imagesdir: ../img
6 | :linkcss:
7 | :stylesdir: ../
8 | :stylesheet: my-asciidoctor.css
9 | :docinfo1:
10 | :toc: right
11 |
12 |
--------------------------------------------------------------------------------
/guide/docinfo.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/guide/to-html.sh:
--------------------------------------------------------------------------------
1 | asciidoctor clojure-complete.adoc **/*.adoc
2 |
--------------------------------------------------------------------------------
/my-asciidoctor.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);
2 | @import url("asciidoctor.css");
3 |
4 | html{font-family: 'Nanum Gothic', serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
5 |
6 | body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family: 'Nanum Gothic', serif;;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
7 |
8 | h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#000;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
9 |
--------------------------------------------------------------------------------
/src/java-interop/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 | .hgignore
11 | .hg/
12 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/.name:
--------------------------------------------------------------------------------
1 | java-interop
--------------------------------------------------------------------------------
/src/java-interop/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__args4j_2_0_26.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__cider_cider_nrepl_0_10_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__clojure_complete_0_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_cemerick_piggieback_0_2_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_code_findbugs_jsr305_1_3_9.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_code_gson_gson_2_2_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_guava_guava_18_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_javascript_closure_compiler_externs_v20150126.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_javascript_closure_compiler_v20150126.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_protobuf_protobuf_java_2_5_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__com_google_truth_truth_0_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__criterium_0_4_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__http_kit_2_1_18.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__junit_4_10.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_clojure_1_7_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_clojurescript_0_0_3165.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_data_json_0_2_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_google_closure_library_0_0_20140718_946a7d39.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_google_closure_library_third_party_0_0_20140718_946a7d39.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_tools_nrepl_0_2_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_clojure_tools_reader_0_8_16.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_hamcrest_hamcrest_core_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_mozilla_rhino_1_7R5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__org_tcrawley_dynapath_0_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__prismatic_schema_1_0_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/libraries/Leiningen__weasel_0_7_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/java-interop/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/java-interop/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 | All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
3 |
4 | ## [Unreleased][unreleased]
5 | ### Changed
6 | - Add a new arity to `make-widget-async` to provide a different widget shape.
7 |
8 | ## [0.1.1] - 2015-12-08
9 | ### Changed
10 | - Documentation on how to make the widgets.
11 |
12 | ### Removed
13 | - `make-widget-sync` - we're all async, all the time.
14 |
15 | ### Fixed
16 | - Fixed widget maker to keep working when daylight savings switches over.
17 |
18 | ## 0.1.0 - 2015-12-08
19 | ### Added
20 | - Files from the new template.
21 | - Widget maker public API - `make-widget-sync`.
22 |
23 | [unreleased]: https://github.com/your-name/java-interop/compare/0.1.1...HEAD
24 | [0.1.1]: https://github.com/your-name/java-interop/compare/0.1.0...0.1.1
25 |
--------------------------------------------------------------------------------
/src/java-interop/LICENSE:
--------------------------------------------------------------------------------
1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and
10 | documentation distributed under this Agreement, and
11 |
12 | b) in the case of each subsequent Contributor:
13 |
14 | i) changes to the Program, and
15 |
16 | ii) additions to the Program;
17 |
18 | where such changes and/or additions to the Program originate from and are
19 | distributed by that particular Contributor. A Contribution 'originates' from
20 | a Contributor if it was added to the Program by such Contributor itself or
21 | anyone acting on such Contributor's behalf. Contributions do not include
22 | additions to the Program which: (i) are separate modules of software
23 | distributed in conjunction with the Program under their own license
24 | agreement, and (ii) are not derivative works of the Program.
25 |
26 | "Contributor" means any person or entity that distributes the Program.
27 |
28 | "Licensed Patents" mean patent claims licensable by a Contributor which are
29 | necessarily infringed by the use or sale of its Contribution alone or when
30 | combined with the Program.
31 |
32 | "Program" means the Contributions distributed in accordance with this
33 | Agreement.
34 |
35 | "Recipient" means anyone who receives the Program under this Agreement,
36 | including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants
41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
42 | reproduce, prepare derivative works of, publicly display, publicly perform,
43 | distribute and sublicense the Contribution of such Contributor, if any, and
44 | such derivative works, in source code and object code form.
45 |
46 | b) Subject to the terms of this Agreement, each Contributor hereby grants
47 | Recipient a non-exclusive, worldwide, royalty-free patent license under
48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
49 | transfer the Contribution of such Contributor, if any, in source code and
50 | object code form. This patent license shall apply to the combination of the
51 | Contribution and the Program if, at the time the Contribution is added by the
52 | Contributor, such addition of the Contribution causes such combination to be
53 | covered by the Licensed Patents. The patent license shall not apply to any
54 | other combinations which include the Contribution. No hardware per se is
55 | licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other
60 | intellectual property rights of any other entity. Each Contributor disclaims
61 | any liability to Recipient for claims brought by any other entity based on
62 | infringement of intellectual property rights or otherwise. As a condition to
63 | exercising the rights and licenses granted hereunder, each Recipient hereby
64 | assumes sole responsibility to secure any other intellectual property rights
65 | needed, if any. For example, if a third party patent license is required to
66 | allow Recipient to distribute the Program, it is Recipient's responsibility
67 | to acquire that license before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license
71 | set forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under
76 | its own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title
84 | and non-infringement, and implied warranties or conditions of merchantability
85 | and fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on
96 | or through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within
105 | the Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution,
108 | if any, in a manner that reasonably allows subsequent Recipients to identify
109 | the originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a
117 | manner which does not create potential liability for other Contributors.
118 | Therefore, if a Contributor includes the Program in a commercial product
119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend
120 | and indemnify every other Contributor ("Indemnified Contributor") against any
121 | losses, damages and costs (collectively "Losses") arising from claims,
122 | lawsuits and other legal actions brought by a third party against the
123 | Indemnified Contributor to the extent caused by the acts or omissions of such
124 | Commercial Contributor in connection with its distribution of the Program in
125 | a commercial product offering. The obligations in this section do not apply
126 | to any claims or Losses relating to any actual or alleged intellectual
127 | property infringement. In order to qualify, an Indemnified Contributor must:
128 | a) promptly notify the Commercial Contributor in writing of such claim, and
129 | b) allow the Commercial Contributor tocontrol, and cooperate with the
130 | Commercial Contributor in, the defense and any related settlement
131 | negotiations. The Indemnified Contributor may participate in any such claim
132 | at its own expense.
133 |
134 | For example, a Contributor might include the Program in a commercial product
135 | offering, Product X. That Contributor is then a Commercial Contributor. If
136 | that Commercial Contributor then makes performance claims, or offers
137 | warranties related to Product X, those performance claims and warranties are
138 | such Commercial Contributor's responsibility alone. Under this section, the
139 | Commercial Contributor would have to defend claims against the other
140 | Contributors related to those performance claims and warranties, and if a
141 | court requires any other Contributor to pay any damages as a result, the
142 | Commercial Contributor must pay those damages.
143 |
144 | 5. NO WARRANTY
145 |
146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
151 | appropriateness of using and distributing the Program and assumes all risks
152 | associated with its exercise of rights under this Agreement , including but
153 | not limited to the risks and costs of program errors, compliance with
154 | applicable laws, damage to or loss of data, programs or equipment, and
155 | unavailability or interruption of operations.
156 |
157 | 6. DISCLAIMER OF LIABILITY
158 |
159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
166 | OF SUCH DAMAGES.
167 |
168 | 7. GENERAL
169 |
170 | If any provision of this Agreement is invalid or unenforceable under
171 | applicable law, it shall not affect the validity or enforceability of the
172 | remainder of the terms of this Agreement, and without further action by the
173 | parties hereto, such provision shall be reformed to the minimum extent
174 | necessary to make such provision valid and enforceable.
175 |
176 | If Recipient institutes patent litigation against any entity (including a
177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
178 | (excluding combinations of the Program with other software or hardware)
179 | infringes such Recipient's patent(s), then such Recipient's rights granted
180 | under Section 2(b) shall terminate as of the date such litigation is filed.
181 |
182 | All Recipient's rights under this Agreement shall terminate if it fails to
183 | comply with any of the material terms or conditions of this Agreement and
184 | does not cure such failure in a reasonable period of time after becoming
185 | aware of such noncompliance. If all Recipient's rights under this Agreement
186 | terminate, Recipient agrees to cease use and distribution of the Program as
187 | soon as reasonably practicable. However, Recipient's obligations under this
188 | Agreement and any licenses granted by Recipient relating to the Program shall
189 | continue and survive.
190 |
191 | Everyone is permitted to copy and distribute copies of this Agreement, but in
192 | order to avoid inconsistency the Agreement is copyrighted and may only be
193 | modified in the following manner. The Agreement Steward reserves the right to
194 | publish new versions (including revisions) of this Agreement from time to
195 | time. No one other than the Agreement Steward has the right to modify this
196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
197 | Eclipse Foundation may assign the responsibility to serve as the Agreement
198 | Steward to a suitable separate entity. Each new version of the Agreement will
199 | be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the
201 | Agreement under which it was received. In addition, after a new version of
202 | the Agreement is published, Contributor may elect to distribute the Program
203 | (including its Contributions) under the new version. Except as expressly
204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
205 | licenses to the intellectual property of any Contributor under this
206 | Agreement, whether expressly, by implication, estoppel or otherwise. All
207 | rights in the Program not expressly granted under this Agreement are
208 | reserved.
209 |
210 | This Agreement is governed by the laws of the State of New York and the
211 | intellectual property laws of the United States of America. No party to this
212 | Agreement will bring a legal action under this Agreement more than one year
213 | after the cause of action arose. Each party waives its rights to a jury trial
214 | in any resulting litigation.
215 |
--------------------------------------------------------------------------------
/src/java-interop/README.md:
--------------------------------------------------------------------------------
1 | # java-interop
2 |
3 | A Clojure library designed to ... well, that part is up to you.
4 |
5 | ## Usage
6 |
7 | FIXME
8 |
9 | ## License
10 |
11 | Copyright © 2015 FIXME
12 |
13 | Distributed under the Eclipse Public License either version 1.0 or (at
14 | your option) any later version.
15 |
--------------------------------------------------------------------------------
/src/java-interop/doc/intro.md:
--------------------------------------------------------------------------------
1 | # Introduction to java-interop
2 |
3 | TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)
4 |
--------------------------------------------------------------------------------
/src/java-interop/java-interop.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/java-interop/project.clj:
--------------------------------------------------------------------------------
1 | (defproject java-interop "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 | :dependencies [[org.clojure/clojure "1.7.0"]]
7 | :aot [java-interop.example1 java-interop.example2
8 | java-interop.Example3 java-interop.Example4
9 | java-interop.Example5 java-interop.Example6])
10 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/Example3.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.Example3
2 | (:gen-class
3 | :implements [clojure.lang.IDeref]))
4 |
5 | (defn -deref
6 | [this]
7 | "Hello, World!")
8 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/Example4.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.Example4
2 | (:gen-class
3 | :extends java_interop.Example3))
4 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/Example5.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.Example5
2 | (:gen-class
3 | :implements [clojure.lang.IDeref]
4 | :state state
5 | :init init
6 | :constructors {[String] []}))
7 |
8 | (defn -init
9 | [message]
10 | [[] (atom message)])
11 |
12 | (defn -deref
13 | [this]
14 | @(.state this))
15 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/Example6.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.Example6
2 | (:gen-class
3 | :methods [^:static [greet [] String]
4 | [greetMessage [String] String]]))
5 |
6 | (defn -greet
7 | []
8 | "Hello, World!")
9 |
10 | (defn -greetMessage
11 | [this msg]
12 | (str "Hello, " msg "!"))
13 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/example1.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.example1)
2 |
3 | (gen-class
4 | :name java_interop.example1.MyClass)
5 |
6 | (defn -toString
7 | [this]
8 | "Hello, World!")
9 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/example2.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.example2)
2 |
3 | (gen-class
4 | :name java_interop.example1.MyClassA
5 | :prefix classA-)
6 |
7 | (gen-class
8 | :name java_interop.example1.MyClassB
9 | :prefix classB-)
10 |
11 | (defn classA-toString
12 | [this]
13 | "I'm an A.")
14 |
15 | (defn classB-toString
16 | [this]
17 | "I'm a B.")
18 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test1.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test1
2 | (:import java_interop.example1.MyClass))
3 |
4 | (.toString (MyClass.)) ;=> "Hello, World!"
5 |
6 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test2.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test2
2 | (:import (java_interop.example1 MyClassA MyClassB))
3 |
4 | (.toString (MyClassA.)) ;=> "I'm an A."
5 | (.toString (MyClassB.)) ;=> "I'm an B."
6 |
7 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test3.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test3
2 | (:import java_interop.Example3))
3 |
4 | @(Example3.) ;=> "Hello, World!"
5 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test4.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test4
2 | (:import java_interop.Example4))
3 |
4 | @(Example4.) ;=> "Hello, World!"
5 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test5.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test5
2 | (:import java_interop.Example5))
3 |
4 | (def o (Example5. "Hello, there!"))
5 |
6 | @o ;=> "Hallo, there!"
7 |
8 | (reset! (.state o) "Good morning, everybody!")
9 |
10 | @o ;=> "Good morning, everybody!"
11 |
12 |
--------------------------------------------------------------------------------
/src/java-interop/src/java_interop/test6.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.test6
2 | (:import java_interop.Example6))
3 |
4 | (Example6/greet)
5 | ;=> "Hello, World!"
6 |
7 | (.greetMessage (Example6.) "Rich Hickey")
8 | ;=> "Hello, Rich Hickey!"
9 |
10 |
--------------------------------------------------------------------------------
/src/java-interop/test/java_interop/core_test.clj:
--------------------------------------------------------------------------------
1 | (ns java-interop.core-test
2 | (:require [clojure.test :refer :all]
3 | [java-interop.core :refer :all]))
4 |
5 | (deftest a-test
6 | (testing "FIXME, I fail."
7 | (is (= 0 1))))
8 |
--------------------------------------------------------------------------------
/to-html.sh:
--------------------------------------------------------------------------------
1 | mkdir -p public
2 | asciidoctor -R . -D public -a stylesheet=my-asciidoctor.css clojure-complete-html.adoc **/*.adoc
3 | mv public/clojure-complete-html.html public/index.html
4 | cp asciidoctor.css public
5 | cp coderay-asciidoctor.css public
6 | cp my-asciidoctor.css public
7 |
8 | #asciidoctor clojure-complete-html.adoc **/*.adoc
9 | #mv clojure-complete-html.html index.html
10 |
--------------------------------------------------------------------------------
/to-pdf.sh:
--------------------------------------------------------------------------------
1 | # asciidoctor-pdf -r asciidoctor-pdf-cjk-kai_gen_gothic -a pdf-style=KaiGenGothicKR -o clojure-programming.pdf -o clojure-complete.pdf clojure-complete-pdf.adoc
2 | asciidoctor-pdf -a pdf-theme=asciidoctor-theme/notosansmono-cjk-kr/themes/default-ext-notosansmono-cjk-kr-theme.yml -a pdf-fontsdir=asciidoctor-theme/notosansmono-cjk-kr/fonts -o clojure-programming.pdf -o clojure-complete.pdf clojure-complete-pdf.adoc
3 |
--------------------------------------------------------------------------------