├── .github
├── issue_template.md
└── pull_request_template.md
├── .gitignore
├── Gemfile
├── Gemfile.lock
├── README-tools.md
├── README.md
├── _config.yml
├── _layouts
├── article.html
└── default.html
├── _plugins
└── last_modified_date_hook.rb
├── articles
├── about.md
├── content.md
├── cookbooks
│ ├── data_structures.md
│ ├── date_and_time.md
│ ├── files_and_directories.md
│ ├── math.md
│ ├── middleware.md
│ └── strings.md
├── ecosystem
│ ├── books.md
│ ├── community.md
│ ├── core_typed
│ │ ├── filters.md
│ │ ├── function_types.md
│ │ ├── home.md
│ │ ├── limitations.md
│ │ ├── loops.md
│ │ ├── mm_protocol_datatypes.md
│ │ ├── poly_fn.md
│ │ ├── quick_guide.md
│ │ ├── rationale.md
│ │ ├── start
│ │ │ ├── annotations.md
│ │ │ └── introduction_and_motivation.md
│ │ ├── types.md
│ │ └── user_documentation.md
│ ├── data_processing.md
│ ├── generating_documentation.md
│ ├── java_jdbc
│ │ ├── connection_pooling.md
│ │ ├── home.md
│ │ ├── name_mapping.md
│ │ ├── reusing_connections.md
│ │ ├── using_ddl.md
│ │ └── using_sql.md
│ ├── libraries_authoring.md
│ ├── libraries_directory.md
│ ├── maven.md
│ ├── running_cljug.md
│ ├── user_groups.md
│ └── web_development.md
├── language
│ ├── collections_and_sequences.md
│ ├── concurrency_and_parallelism.md
│ ├── core_overview.md
│ ├── functions.md
│ ├── glossary.md
│ ├── interop.md
│ ├── laziness.md
│ ├── macros.md
│ ├── namespaces.md
│ └── polymorphism.md
└── tutorials
│ ├── basic_web_development.md
│ ├── eclipse.md
│ ├── emacs.md
│ ├── example-code
│ └── growing_a_dsl_with_clojure.clj
│ ├── getting_started.md
│ ├── growing_a_dsl_with_clojure.md
│ ├── introduction.md
│ ├── parsing_xml_with_zippers.md
│ └── vim_fireplace.md
├── assets
├── images
│ └── language
│ │ └── concurrency_and_parallelism
│ │ ├── atom_state1.png
│ │ ├── atom_state2.png
│ │ └── identity_value.png
├── javascripts
│ ├── bootstrap-dropdown.js
│ ├── bootstrap.min.js
│ ├── jquery-1.9.1.min.js
│ └── toc.js
├── omnigraffle
│ └── language
│ │ └── Concurrency and Parallelism.graffle
└── stylesheets
│ ├── bootstrap-docs.css
│ ├── bootstrap.min.css
│ ├── pygments.css
│ └── styles.css
└── index.html
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 | Since we are no longer able to update the server that runs clojure-doc.org, the content
2 | is now available at https://clojure-doc.github.io and you can create Issues against that
3 | new site over at https://github.com/clojure-doc/clojure-doc.github.io/issues -- thank you!
4 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | Since we are no longer able to update the server that runs clojure-doc.org, the content is now available at https://clojure-doc.github.io and you can
2 | submit Pull Requests against that new site over at https://github.com/clojure-doc/clojure-doc.github.io/pulls -- thank you!
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bundle
2 | .DS_Store
3 | .rvmrc
4 | .ruby-version
5 | _site
6 | bin
7 | source/tmp/*
8 | _site/*
9 | .sass-cache/*
10 | *.sassc
11 | *\#*
12 | ~*
13 | _source/*
14 | deploy.sh
15 | repl*
16 | _cache/*
17 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | gem "jekyll", "~> 3.4.0"
4 | # with Ruby 2.0 on OS X, you may need to install
5 | # it manually with --with-iconv-dir:
6 | #
7 | # gem install iconv -- --with-iconv-dir=~/.rvm/usr
8 | gem "iconv"
9 | gem "albino"
10 | gem "redcarpet"
11 | gem "rouge"
12 | gem "rake", "~> 12.0"
13 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | addressable (2.5.1)
5 | public_suffix (~> 2.0, >= 2.0.2)
6 | albino (1.3.3)
7 | posix-spawn (>= 0.3.6)
8 | colorator (1.1.0)
9 | ffi (1.9.18)
10 | forwardable-extended (2.6.0)
11 | iconv (1.0.4)
12 | jekyll (3.4.3)
13 | addressable (~> 2.4)
14 | colorator (~> 1.0)
15 | jekyll-sass-converter (~> 1.0)
16 | jekyll-watch (~> 1.1)
17 | kramdown (~> 1.3)
18 | liquid (~> 3.0)
19 | mercenary (~> 0.3.3)
20 | pathutil (~> 0.9)
21 | rouge (~> 1.7)
22 | safe_yaml (~> 1.0)
23 | jekyll-sass-converter (1.5.0)
24 | sass (~> 3.4)
25 | jekyll-watch (1.5.0)
26 | listen (~> 3.0, < 3.1)
27 | kramdown (1.13.2)
28 | liquid (3.0.6)
29 | listen (3.0.8)
30 | rb-fsevent (~> 0.9, >= 0.9.4)
31 | rb-inotify (~> 0.9, >= 0.9.7)
32 | mercenary (0.3.6)
33 | pathutil (0.14.0)
34 | forwardable-extended (~> 2.6)
35 | posix-spawn (0.3.11)
36 | public_suffix (2.0.5)
37 | rake (12.3.0)
38 | rb-fsevent (0.9.8)
39 | rb-inotify (0.9.8)
40 | ffi (>= 0.5.0)
41 | redcarpet (3.3.2)
42 | rouge (1.11.1)
43 | safe_yaml (1.0.4)
44 | sass (3.4.23)
45 |
46 | PLATFORMS
47 | ruby
48 |
49 | DEPENDENCIES
50 | albino
51 | iconv
52 | jekyll (~> 3.4.0)
53 | rake (~> 12.0)
54 | redcarpet
55 | rouge
56 |
57 | BUNDLED WITH
58 | 1.16.1
59 |
--------------------------------------------------------------------------------
/README-tools.md:
--------------------------------------------------------------------------------
1 | # Tools Used to Create CDS
2 |
3 | CDS reuses the [ClojureWerkz docslate](http://github.com/clojurewerkz/docslate) toolchain.
4 | The clojure-doc.org site is generated using jekyll. To run the site generator yourself, you'll need to first have Ruby installed. Python is also required, as syntax-highlighting of code blocks is handled by pygments.
5 |
6 | If installing Ruby from source, a prerequisite is the libyaml dev package.
7 |
8 |
9 | ## Install Tools & Dependencies
10 |
11 | Install [Bundler](http://gembundler.com). Ruby 1.9.3 or JRuby are recommended:
12 |
13 | gem install bundler
14 |
15 | Then install dependencies (Jekyll, GitHub-flavored Markdown processors, etc) with Bundler
16 | by running the following in the CDS repository root:
17 |
18 | bundle install --binstubs
19 |
20 | > As an alternative to bundler, if you like you can manually
21 | > (via `gem install`) install all the dependencies listed in
22 | > path/to/cds/Gemfile, and then later (from the cds directory)
23 | > run the gem-installed `jekyll` to view your local version of
24 | > the site.
25 |
26 |
27 | ## How To Run A Development Server
28 |
29 | Before you run `jekyll` the first time, you will need to create an empty folder called
30 | `_site` in the CDS repository root.
31 |
32 | mkdir -p _site
33 | ./bin/jekyll serve --watch
34 |
35 | The server will be started at [localhost:4000](http://localhost:4000).
36 |
37 |
38 | ## How To Regenerate The Site
39 |
40 | To regenerate the entire site, use
41 |
42 | ./bin/jekyll build
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CDS: A Clojure Doc Site
2 |
3 | **NOTE: Since we are no longer able to update the server running clojure-doc.org, the Clojure Guides have been copied to https://github.com/clojure-doc/clojure-doc.github.io and you can view the new site at https://clojure-doc.github.io -- please feel free to use that GitHub repository for Discussions, filing Issues, and submitting Pull Requests.**
4 |
5 | An assorted collection of tutorials, guides, and other documentation
6 | (by various authors) for the Clojure programming language and its
7 | ecosystem. [Read the guides online](http://clojure-doc.org).
8 |
9 |
10 | ## Goals
11 |
12 | The goal is to produce quality technical documentation with limited
13 | duplication between guides, and eventually have these documents hosted
14 | at doc.clojure.org.
15 |
16 |
17 | What's *not* here:
18 |
19 | * Cheatsheets. Those can be found at
20 | [clojure.org/cheatsheet](http://clojure.org/cheatsheet), or with
21 | tooltips at
22 | [jafingerhut.github.com](http://jafingerhut.github.com). There is also an unofficial [ClojureScript cheatsheet](https://github.com/fogus/clojurescript-cheatsheet) available for download and contribution.
23 | * API reference docs. Those can currently be found (with examples)
24 | at [Clojuredocs](http://clojuredocs.org/).
25 |
26 | Clojuredocs needs a lot of work and redesign
27 | (as in, the way it works) which will take a while. CDS is not concerned with providing the API reference; only tutorials, guides, and
28 | linking to other relevant resources.
29 |
30 |
31 |
32 | ## Structure
33 |
34 | CDS is structured as a number of guides. They broadly fall into 4 categories:
35 |
36 | * Tutorials
37 | * Language guides
38 | * Tool guides
39 | * Cookbooks
40 |
41 |
42 | ### Tutorials
43 |
44 | These guides are for complete newcomers and should include a lot of hand holding. They don't assume any
45 | previous familiarity with Clojure, the JVM, the JVM tool ecosystem, functional programming, immutability, and so on.
46 |
47 | Target audience: newcomers to the language.
48 |
49 |
50 | ### Language guides
51 |
52 | These guides are more in-depth, focused on various aspects of the language and interoperability.
53 | Examples of such guides include:
54 |
55 | * Sequences
56 | * Interoperability
57 | * Reference types
58 | * Laziness
59 | * Macros and compilation
60 |
61 | Target audience: from developers who already have some familiarity with the language to those who have been using it for
62 | a while.
63 |
64 |
65 | ### Tools & Ecosystem guides
66 |
67 | These guides cover key Clojure ecosystem tools such as [Leiningen](http://leiningen.org), [Clojars](http://clojars.org), [REPLy](https://github.com/trptcolin/reply),
68 | nREPL, Emacs clojure-mode, VimClojure, Counterclockwise, La Clojure, etc. It also covers important ecosystem projects that are not tools: books,
69 | ClojureSphere, ClojureWerkz, Flatland and so on.
70 |
71 | Target audience: all developers using or interested in the language.
72 |
73 |
74 |
75 | ### Cookbooks
76 |
77 | Concise Clojure example code, categorized by subject.
78 |
79 |
80 |
81 |
82 | ## How To Contribute
83 |
84 | First of all: you **can** contribute to Clojure documentation even if you have 15 minutes to spare a day. To give you an example,
85 | here's what 2 people could produce in about 6 months in their spare time:
86 |
87 | * [Monger documentation](http://clojuremongodb.info)
88 | * [Neocons documentation](http://clojureneo4j.info)
89 | * [Welle documentation](http://clojureriak.info)
90 | * [Elastisch documentation](http://clojureelasticsearch.info)
91 | * [Langohr documentation](http://clojurerabbitmq.info)
92 | * [Quartzite documentation](http://clojurequartz.info)
93 |
94 | No contribution is too small: feel free to suggest grammar improvements, better code examples, submit pull requests with just
95 | one new paragraph or even a couple of spelling corrections. Editing and proof-reading is also a great way to contribute.
96 |
97 | If you found a mistake you'd like to report and do not want to make edits and go through the pull request process,
98 | please post your findings on the [Clojure mailing list](https://groups.google.com/group/clojure),
99 | or else find us on `#clojure-doc` (IRC) at freenode.
100 |
101 | Thank you!
102 |
103 |
104 | ### Toolchain
105 |
106 | [README-tools.md](https://github.com/clojuredocs/cds/blob/master/README-tools.md) covers development
107 | environment setup and how to run a local server.
108 |
109 |
110 | ### Contributing To Existing Guides
111 |
112 | First, pick a topic that sounds interesting. Writing documentation takes some effort and
113 | working on something that is interesting to you will motivate you. Next, find the article you want
114 | to contribute to under `./articles/`. It is a Markdown file with inline code snippets.
115 |
116 | At the top of each article you will usually find what it is supposed to cover. Please stick
117 | to that list.
118 |
119 | Then fork the repository, create a [topic branch](http://git-scm.com/book/en/Git-Branching-Branching-Workflows), and
120 | start writing.
121 |
122 | When writing, periodically view results in the browser (see the [Toolchain readme](cds/blob/master/README-tools.md) about running a local server) and make
123 | sure code examples are rendered correctly and that there are no serious formatting issues. If you are not a Markdown or CSS guru,
124 | it's OK, but submitting changes that seriously break formatting and force maintainers to work on fixing them is not
125 | very productive (or nice).
126 |
127 | After making the changes you want, run them by a fellow developer, edit them a couple
128 | of times and *submit a pull request on GitHub*. Please be patient. It may take a while for
129 | CDS maintainers to get to your pull request, read your changes, and suggest improvements.
130 |
131 | Don't get discouraged if asked to make more edits or even completely rewrite some parts from scratch.
132 | All good documentation out there is a result of dozens of edits, corrections, and sometimes ground-up
133 | rewrites. This is normal. We want Clojure documentation to be high quality just like the language and
134 | `clojure.core`.
135 |
136 | For some guidance on writing great documentation, see .
137 |
138 |
139 |
140 | ### Contributing New Guides
141 |
142 | If you feel there may be a guide missing, please run your idea by other CDS contributors on the [Clojure mailing list](https://groups.google.com/group/clojure).
143 |
144 |
145 | ### What You Must Not Do
146 |
147 | Please respect copyright of other Clojure-related content out there. **You must not** copy content from clojure.org, books on Clojure, blogs and
148 | other sources unless you are the primary author of them and understand the implications.
149 |
150 |
151 |
152 | ### Contributors Policy
153 |
154 | If you are the primary author of a substantial document, you are
155 | encouraged to include your name in a `## Contributors` section near the
156 | end of it, noting that you are the original author. If you have made
157 | substantial contributions to an existing document, you might add your
158 | name to the `## Contributors` section.
159 |
160 | If you have at least one non-trivial (e.g. not just typo fixes) pull request merged, you can ask
161 | to be added to the repository as a collaborator. We still encourage contributors to use pull requests for content
162 | review and discussions for new content, but you will be able to push small improvements directly.
163 |
164 | [GitHub contributors page](https://github.com/clojuredocs/cds/graphs/contributors) lists key contributors to the project.
165 |
166 |
167 | ## License
168 |
169 | All the content is distributed under the
170 | [CC BY 3.0](http://creativecommons.org/licenses/by/3.0/) license
171 | and are copyright their respective primary author(s).
172 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | source: .
2 | destination: ./_site
3 | plugins_dir: ./_plugins
4 | exclude: [bin, CNAME, Gemfile, Gemfile.lock, README.md]
5 | permalink: /:title
6 | highlighter: rouge
7 | markdown: redcarpet
8 | redcarpet:
9 | extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"]
10 |
--------------------------------------------------------------------------------
/_layouts/article.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
71 |
72 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/_plugins/last_modified_date_hook.rb:
--------------------------------------------------------------------------------
1 | Jekyll::Hooks.register :pages, :pre_render do |page, payload|
2 |
3 | # get the current page last modified time
4 | modification_time = File.mtime(page.path)
5 |
6 | # inject modification_time in page's datas.
7 | payload['page']['last-modified-date'] = modification_time
8 |
9 | end
10 |
--------------------------------------------------------------------------------
/articles/about.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "About"
3 | layout: article
4 | ---
5 |
6 | CDS (Clojure Documentation Site) is a community documentation project for the Clojure programming language. It is not affiliated with
7 | `Clojure/core`, does not require going through the Clojure Contributor Agreement, and is developed [on GitHub](http://github.com/clojuredocs).
8 |
9 | ## Rationale
10 |
11 | The rationale is explained in more detail in the [announcement blog post](http://blog.clojurewerkz.org/blog/2012/10/10/announcing-a-new-clojure-documentation-project/).
12 |
13 | ## History
14 |
15 | CDS was started in early October, 2012, by several active members of the Clojure community due to their dissatisfaction
16 | with the state of documentation and documentation contribution process (that involved mailing Clojure Contributor Agreement in paper).
17 |
18 |
19 | ## Goals
20 |
21 | The goal is to produce quality technical documentation for Clojure users and potential adopters with various expertise levels.
22 |
23 | CDS strives to cover all aspects of Clojure: from tutorials and language guides to overview of the ecosystem, how
24 | libraries are developed and published, topics operations engineers will be interested in, JVM ecosystem tools
25 | and so on.
26 |
27 | Adopting a language always takes more than just reading a book or a few tutorials about language features. Understanding
28 | design goals, the ecosystem and operations is just as important. CDS will try to address this.
29 |
30 |
31 | ### What CDS is Not
32 |
33 | What's *not* here:
34 |
35 | * Cheatsheets. The official [Clojure cheatsheet](http://clojure.org/cheatsheet) is very good. There is also an unofficial [ClojureScript cheatsheet](https://github.com/fogus/clojurescript-cheatsheet) available for download and contribution.
36 | * API reference docs. Those can currently be found (with examples) at [Clojuredocs](http://clojuredocs.org/).
37 |
38 | Clojuredocs needs a lot of work and redesign (as in, the way it works) which will take a while. CDS is not concerned with providing the API reference;
39 | only tutorials, guides, and linking to other relevant resources.
40 |
41 |
42 |
43 | ## Structure
44 |
45 | CDS is structured as a number of guides. They broadly fall into 4 categories:
46 |
47 | * [Tutorials](content.html#clojure_tutorials)
48 | * [Language guides](content.html#clojure_language_guides)
49 | * [Tool guides](content.html#the_clojure_ecosystem)
50 | * [Cookbooks](content.html#cookbooks)
51 |
52 |
53 | ### Tutorials
54 |
55 | These guides are for complete newcomers and should include a lot of hand holding. They don't assume any
56 | previous familiarity with Clojure, the JVM, the JVM tool ecosystem, functional programming, immutability, and so on.
57 |
58 | Target audience: newcomers to the language.
59 |
60 |
61 | ### Language guides
62 |
63 | These guides are more in-depth, focused on various aspects of the language and interoperability.
64 | Examples of such guides include:
65 |
66 | * Sequences
67 | * Interoperability
68 | * Reference types
69 | * Laziness
70 | * Macros and compilation
71 |
72 | Target audience: from developers who already have some familiarity with the language to those who have been using it for
73 | a while.
74 |
75 |
76 | ### Tools & Ecosystem guides
77 |
78 | These guides cover key Clojure ecosystem tools such as [Leiningen](http://leiningen.org), [Clojars](http://clojars.org), [REPLy](https://github.com/trptcolin/reply),
79 | [nREPL](https://github.com/clojure/tools.nrepl), [Emacs clojure-mode](https://github.com/technomancy/clojure-mode), VimClojure, [Counterclockwise](https://code.google.com/p/counterclockwise/), [La Clojure](http://plugins.jetbrains.com/plugin?pluginId=4050), etc. It also covers important ecosystem projects that are not tools: books,
80 | [ClojureSphere](http://www.clojuresphere.com/), [ClojureWerkz](http://clojurewerkz.org/), [Flatland](https://github.com/flatland) and so on.
81 |
82 | Target audience: all developers using or interested in the Clojure programming language.
83 |
84 |
85 |
86 | ### Cookbooks
87 |
88 | Concise [Clojure example code](content.html#cookbooks), categorized by subject.
89 |
90 |
91 |
92 | ## Mailing List
93 |
94 | CDS [currently uses Clojure mailing list](https://groups.google.com/group/clojure) for discussions. Feel free to join it and ask any questions you may have.
95 |
96 |
97 | ## News & Announcements on Twitter
98 |
99 | News and announcements are posted [on Twitter](http://twitter.com/clojuredocs).
100 |
101 |
102 |
103 | ## Reporting Issues
104 |
105 | If you find a mistake, poor grammar, an important topic not covered, or an outdated example, please [file an issue](http://github.com/clojuredocs/guides/issues) on Github.
106 |
107 |
108 | ## Contributing
109 |
110 | CDS uses [ClojureWerkz Docslate](https://github.com/clojurewerkz/docslate). All tutorials and guides are written in Markdown.
111 |
112 | The toolchain and setup process are described [in the README](https://github.com/clojuredocs/guides/blob/master/README-tools.md).
113 |
114 | To submit changes, create a branch and make your changes on it. Once you are done with your changes and all tests pass, submit a pull request
115 | on GitHub.
116 |
--------------------------------------------------------------------------------
/articles/content.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Table of Contents"
3 | layout: article
4 | ---
5 |
6 | [The content](https://github.com/clojuredocs/guides) is a categorized and
7 | manifold collection of documentation guides for the Clojure programming language and
8 | its ecosystem.
9 |
10 | We recognize that different Clojure users have different level of expertise
11 | and separates content into several groups:
12 |
13 | * [Essentials](#essentials)
14 | * [Core language guides](#language-guides)
15 | * [The Ecosystem](#the-clojure-ecosystem) (tools, libraries, community, books) guides
16 | * [Tutorials & Cookbooks](#tutorials-and-cookbooks)
17 |
18 |
19 | ## Essentials
20 |
21 | Note that the editing environments are listed in alphabetical order and indicate no preference or endorsement. The last
22 | ["State of the Union" Clojure survey](http://blog.cognitect.com/blog/2017/1/31/state-of-clojure-2016-results) indicated
23 | that Emacs is still the most popular editing environment, followed by Cursive, Vim, and Atom.
24 |
25 |
26 | ### [Getting Started](/articles/tutorials/getting_started.html)
27 |
28 | If you're new to Clojure, this is a good place to start.
29 |
30 |
31 | ### [Introduction](/articles/tutorials/introduction.html)
32 |
33 | A swift introduction to the Clojure language, covering most of the
34 | basics.
35 |
36 | ### [Atom for Clojure Development](https://atom.io/packages/proto-repl)
37 |
38 | The ProtoREPL package for Clojure development in Atom.
39 |
40 | ### [Cursive for Clojure Development](https://cursive-ide.com/userguide/)
41 |
42 | The user guide for Cursive, the Clojure plugin for IntelliJ.
43 |
44 | ### [Eclipse for Clojure Development](/articles/tutorials/eclipse.html)
45 |
46 | A brief introduction to Counterclockwise, a Clojure plugin for Eclipse.
47 |
48 | ### [Emacs for Clojure Development](/articles/tutorials/emacs.html)
49 |
50 | A brief introduction to Emacs, Clojure mode, CIDER and Clojure development workflow with Emacs.
51 |
52 | ### [Vim for Clojure Development](/articles/tutorials/vim_fireplace.html)
53 |
54 | A brief introduction to Clojure development in Vim with fireplace.vim.
55 |
56 |
57 |
58 |
59 |
60 | ## Language Guides
61 |
62 | ### [Functions](/articles/language/functions.html)
63 |
64 | Functions are at the heart of Clojure.
65 |
66 | This guide covers:
67 |
68 | * How to define functions
69 | * How to invoke functions
70 | * Multi-arity functions
71 | * Variadic functions
72 | * Higher order functions
73 | * Other topics related to functions
74 |
75 |
76 | ### [clojure.core Overview](/articles/language/core_overview.html) (incomplete)
77 |
78 | `clojure.core` is the core Clojure library.
79 |
80 | This guide covers:
81 |
82 | * Key functions of `clojure.core`
83 | * Key macros of `clojure.core`
84 | * Key vars of `clojure.core`
85 |
86 |
87 | ### [Interoperability with Java](/articles/language/interop.html)
88 |
89 | The Clojure language implementation is symbiotic with its host
90 | platform (the JVM), providing direct interoperability.
91 |
92 | This guide covers:
93 |
94 | * How to instantiate Java classes
95 | * How to invoke Java methods
96 | * How to extend Java classes with proxy
97 | * How to implement Java interfaces with reify
98 | * How to generate Java classes with gen-class
99 | * Other topics related to interop
100 |
101 |
102 | ### [Namespaces](/articles/language/namespaces.html)
103 |
104 | Namespaces organize Clojure functions.
105 |
106 | This guide covers:
107 |
108 | * An overview of Clojure namespaces
109 | * How to define a namespace
110 | * How to use functions in other namespaces
111 | * `require`, `refer` and `use`
112 | * How to Look up and invoke a function by name
113 | * Common compilation exceptions and their causes
114 | * How code compilation works in Clojure
115 |
116 |
117 | ### [Polymorphism: Protocols and Multimethods](/articles/language/polymorphism.html)
118 |
119 | This guide covers:
120 |
121 | * What are polymorphic functions
122 | * Type-based polymorphism with protocols
123 | * Ad-hoc polymorphism with multimethods
124 | * How to create your own data types that behave like core Clojure data types
125 |
126 |
127 | ### [Collections and Sequences](/articles/language/collections_and_sequences.html)
128 |
129 | This guide covers:
130 |
131 | * Collections in Clojure
132 | * Sequences in Clojure
133 | * Core collection types
134 | * Key operations on collections and sequences
135 | * Other topics related to collections and sequences
136 |
137 |
138 | ### [Concurrency & Parallelism](/articles/language/concurrency_and_parallelism.html)
139 |
140 | This guide covers:
141 |
142 | * An overview of concurrency hazards
143 | * Clojure's approach to state and identity
144 | * Immutable data structures
145 | * Reference types (atoms, vars, agents, refs)
146 | * Using Clojure functions with `java.util.concurrent` abstractions
147 | * The Reducers framework (Clojure 1.5+)
148 | * Other topics related to concurrency and runtime parallelism
149 |
150 |
151 | ### [Macros and Metaprogramming](/articles/language/macros.html)
152 |
153 | This guide covers:
154 |
155 | * Clojure macros
156 | * Clojure compilation process
157 | * Other topics related to metaprogramming
158 |
159 |
160 | ### [Laziness and Lazy Sequences](/articles/language/laziness.html) (incomplete)
161 |
162 | This guide covers:
163 |
164 | * What are lazy sequences
165 | * How to create functions that produce lazy sequences
166 | * How to force evaluation
167 | * Pitfalls with lazy sequences
168 |
169 |
170 | ### [Glossary](/articles/language/glossary.html)
171 |
172 | This guide includes definitons of various Clojure-related terminology.
173 |
174 |
175 |
176 | ## The Clojure Ecosystem
177 |
178 | ### [Books](/articles/ecosystem/books.html)
179 |
180 | This guide covers:
181 |
182 | * Books on Clojure
183 | * Books on ClojureScript
184 |
185 |
186 | ### [Getting Started with Leiningen](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md)
187 |
188 | This guide covers:
189 |
190 | * What is Leiningen and what it can do for you
191 | * How to create a project with Leiningen
192 | * How to manage project dependencies
193 | * Accessing the REPL
194 | * How to run tests for your project
195 | * How to run the app
196 | * How to compile your code and dependencies into a single JAR for deployment ("überjar")
197 | * How to share (publish) a library
198 |
199 | ### [Maven for Clojure Development](/articles/ecosystem/maven.html)
200 |
201 | This guide covers:
202 |
203 | * An overview of Apache Maven
204 | * Maven Clojure plugin
205 |
206 | ### [Clojure Library Directory](/articles/ecosystem/libraries_directory.html)
207 |
208 | A curated and highly opinionated categorized directory of available Clojure libraries and tools.
209 |
210 | ### [Clojure Community](/articles/ecosystem/community.html)
211 |
212 | This guide covers:
213 |
214 | * Planet Clojure, mailing lists, IRC channel
215 | * Clojure conferences
216 | * Local Clojure user groups
217 | * Other Clojure community resources
218 |
219 | ### [core.typed](/articles/ecosystem/core_typed/home.html)
220 |
221 | * What is Clojure core.typed
222 | * core.typed documentation, tutorials, and guides.
223 |
224 |
225 | ### [java.jdbc](/articles/ecosystem/java_jdbc/home.html)
226 |
227 | This guide covers:
228 |
229 | * An overview of Clojure's JDBC wrapper
230 | * Setting up a data source
231 | * Manipulating data with SQL
232 | * Manipulating tables with DDL
233 | * How to use connection pooling
234 | * How to use some common DSLs with java.jdbc
235 | * Where to go beyond java.jdbc
236 |
237 |
238 | ### [Library Development and Distribution](/articles/ecosystem/libraries_authoring.html)
239 |
240 | This guide covers:
241 |
242 | * Basic setup for library development
243 | * How to publish a library to Clojars
244 |
245 |
246 | ### [Leiningen Profiles](https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md)
247 |
248 | This guide covers:
249 |
250 | * What are Leiningen profiles
251 | * How to use them
252 |
253 |
254 | ### [Distributing Libraries with Leiningen](https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md)
255 |
256 | This guide covers:
257 |
258 | * How Clojure libraries are distributed
259 | * How to publish Clojure libraries to clojars.org
260 | * How to publish Clojure libraries to Maven Central
261 | * How to publish Clojure libraries to your own Maven repository
262 |
263 |
264 | ### [Writing Leiningen Plugins](https://github.com/technomancy/leiningen/blob/master/doc/PLUGINS.md)
265 |
266 | This guide covers:
267 |
268 | * What Leiningen plugins can do
269 | * How to install Leiningen plugins
270 | * How to develop plugins
271 | * How to distribute plugins
272 |
273 |
274 | ### [Documentation Tools](/articles/ecosystem/generating_documentation.html)
275 |
276 | * Tools for generating documentation from docstrings and other project
277 | metadata.
278 |
279 |
280 | ### [Data Processing (Overview)](/articles/ecosystem/data_processing.html) (TBD)
281 |
282 | This guide covers:
283 |
284 | * An overview of why Clojure is an excellent choice for data processing
285 | * Popular tools and libraries in the area
286 |
287 |
288 |
289 | ### [Clojure User Groups](/articles/ecosystem/user_groups.html)
290 |
291 | This guide covers:
292 |
293 | * Clojure User Groups (CLJUGs) around the world
294 |
295 |
296 |
297 | ## Tutorials and Cookbooks
298 |
299 | ### [Basic Web Development](/articles/tutorials/basic_web_development.html)
300 |
301 | A brief tutorial/walkthrough of building a small web app using Ring,
302 | Compojure, Hiccup, and H2.
303 |
304 | ### [Parsing XML in Clojure](/articles/tutorials/parsing_xml_with_zippers.html)
305 |
306 | This guide covers:
307 |
308 | * How to parse XML in Clojure with zippers (`clojure.data.zip`)
309 |
310 | ### [Growing a DSL with Clojure](/articles/tutorials/growing_a_dsl_with_clojure.html)
311 |
312 | How to create a simple DSL with Clojure.
313 |
314 | Includes introductions to:
315 |
316 | * Multimethods
317 | * Hierarchies
318 | * Metaprogramming and the "Code as data" philosophy
319 |
320 |
321 | ### [Strings](/articles/cookbooks/strings.html)
322 |
323 | This cookbook covers:
324 |
325 | * How to work with strings
326 | * How to work with characters
327 | * How to work with regular expressions
328 | * How to work with context-free grammars
329 | * How to format text
330 |
331 | ### [Mathematics](/articles/cookbooks/math.html)
332 |
333 | Includes coverage of facilities for doing math with Clojure.
334 |
335 |
336 | ### [Data Structures](/articles/cookbooks/data_structures.html) (TBD)
337 |
338 | This cookbook covers:
339 |
340 | * Vectors
341 | * Maps
342 | * Lists
343 | * Sets
344 | * Generic operations on sequences
345 |
346 | ### [Files and Directories](/articles/cookbooks/files_and_directories.html)
347 |
348 | This cookbook covers:
349 |
350 | * Reading and writing text and binary files
351 | * Listing directory contents
352 | * Creating files and directories
353 | * Moving files and directories
354 | * Removing files and directories
355 | * Accessing file metadata
356 | * Other operations on files and directories
357 |
358 |
359 | ### [Date and Time](/articles/cookbooks/date_and_time.html) (TBD)
360 |
361 | This guide covers:
362 |
363 | * Working with JDK dates
364 | * Working with Joda Time and `clj-time`
365 | * Instant literals (Clojure 1.4+)
366 |
367 |
368 |
369 | ### [Middleware](/articles/cookbooks/middleware.html) (incomplete)
370 |
371 | This guide covers:
372 |
373 | * What middleware is and how it works
374 | * Creating middleware for a client function
375 | * Combining middleware to create a new client
376 |
377 |
378 | ## License
379 |
380 | All the content is distributed under the
381 | [CC BY 3.0](http://creativecommons.org/licenses/by/3.0/) license
382 | and are copyright their respective primary author(s).
383 |
384 |
385 | ## Tell Us What You Think!
386 |
387 | Please take a moment to tell us what you think about this guide [on Twitter](https://twitter.com/clojuredocs) or the [Clojure mailing list](https://groups.google.com/group/clojure).
388 |
389 | Let us know what was unclear or what has not been covered. Maybe you do not like the guide style or grammar or discover spelling mistakes.
390 | Reader feedback is key to making the documentation better.
391 |
--------------------------------------------------------------------------------
/articles/cookbooks/data_structures.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Data Structures"
3 | layout: article
4 | ---
5 |
6 | This cookbook covers working with core Clojure data structures.
7 |
8 | This work is licensed under a Creative Commons
10 | Attribution 3.0 Unported License (including images &
11 | stylesheets). The source is available [on
12 | Github](https://github.com/clojuredocs/guides).
13 |
14 |
15 |
16 | ## Todo
17 |
18 | todo
19 |
--------------------------------------------------------------------------------
/articles/cookbooks/date_and_time.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Date and Time"
3 | layout: article
4 | ---
5 |
6 | This cookbook covers working with date and time values in Clojure.
7 |
8 | This work is licensed under a Creative Commons
10 | Attribution 3.0 Unported License (including images &
11 | stylesheets). The source is available [on
12 | Github](https://github.com/clojuredocs/guides).
13 |
14 |
15 |
16 | ## Todo
17 |
18 | todo
19 |
--------------------------------------------------------------------------------
/articles/cookbooks/files_and_directories.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Working with Files and Directories in Clojure"
3 | layout: article
4 | ---
5 |
6 | This cookbook covers working with files and directories from Clojure,
7 | using functions in the `clojure.java.io` namespace as well as parts of
8 | the JDK via interoperability.
9 |
10 | This work is licensed under a Creative Commons
12 | Attribution 3.0 Unported License (including images &
13 | stylesheets). The source is available [on
14 | Github](https://github.com/clojuredocs/guides).
15 |
16 |
17 | ## Preliminaries
18 |
19 | Note that for the examples below, "io" is an alias for
20 | clojure.java.io. That is, it's assumed your `ns` macro contains:
21 |
22 | ``` clojure
23 | (:require [clojure.java.io :as io])
24 | ```
25 |
26 | or else in the repl you've loaded it:
27 |
28 | ``` clojure
29 | (require '[clojure.java.io :as io])
30 | ```
31 |
32 |
33 |
34 | ## Recipes
35 |
36 |
37 | ### Read a file into one long string
38 |
39 | ``` clojure
40 | (def a-long-string (slurp "foo.txt"))
41 | ```
42 |
43 | Note, you can pass urls to `slurp` as well. See also [slurp at
44 | Clojuredocs](http://clojuredocs.org/clojure_core/clojure.core/slurp).
45 |
46 |
47 | ### Read a file one line at a time
48 |
49 | Suppose you'd like to call `my-func` on every line in a file,
50 | and return the resulting sequence:
51 |
52 | ``` clojure
53 | (with-open [rdr (io/reader "foo.txt")]
54 | (doall (map my-func (line-seq rdr))))
55 | ```
56 |
57 | The `doall` is needed because the `map` call is lazy. The lines that
58 | `line-seq` gives you have no trailing newlines (and empty lines in the
59 | file will yield empty strings ("")).
60 |
61 |
62 | ### Write a long string out to a new file
63 |
64 | ``` clojure
65 | (spit "foo.txt"
66 | "A long
67 | multi-line string.
68 | Bye.")
69 | ```
70 |
71 | Overwrites the file if it already exists. To append, use
72 |
73 | ``` clojure
74 | (spit "foo.txt" "file content" :append true)
75 | ```
76 |
77 |
78 | ### Write a file one line at a time
79 |
80 | Suppose you'd like to write out every item in a vector, one item per
81 | line:
82 |
83 | ``` clojure
84 | (with-open [wrtr (io/writer "foo.txt")]
85 | (doseq [i my-vec]
86 | (.write wrtr (str i "\n"))))
87 | ```
88 |
89 |
90 | ### Check if a file exists
91 |
92 | ``` clojure
93 | (.exists (io/file "filename.txt"))
94 | ```
95 |
96 | Is it a directory? :
97 |
98 | ``` clojure
99 | (.isDirectory (io/file "path/to/something"))
100 | ```
101 |
102 | An io/file is a java.io.File object (a file or a directory). You can
103 | call a number of functions on it, including:
104 |
105 | exists Does the file exist?
106 | isDirectory Is the File object a directory?
107 | getName The basename of the file.
108 | getParent The dirname of the file.
109 | getPath Filename with directory.
110 | mkdir Create this directory on disk.
111 |
112 | To read about more available methods, see [the java.io.File
113 | docs](http://docs.oracle.com/javase/7/docs/api/java/io/File.html).
114 |
115 |
116 | ### Get a list of the files and dirs in a given directory
117 |
118 | As `File` objects:
119 |
120 | ``` clojure
121 | (.listFiles (io/file "path/to/some-dir"))
122 | ```
123 |
124 | Same, but just the *names* (strings), not File objects:
125 |
126 | ``` clojure
127 | (.list (io/file "path/to/some-dir"))
128 | ```
129 |
130 | The results of those calls are seqable.
131 |
132 |
133 | ## See also
134 |
135 | *
136 | * the I/O section of the [cheatsheet](http://clojure.org/cheatsheet)
137 |
--------------------------------------------------------------------------------
/articles/cookbooks/math.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Mathematics with Clojure"
3 | layout: article
4 | ---
5 |
6 | This cookbook covers working with mathematics in Clojure, using
7 | built-in functions, contrib libraries, and parts of the JDK via
8 | interoperability.
9 |
10 | This work is licensed under a Creative Commons
12 | Attribution 3.0 Unported License (including images &
13 | stylesheets). The source is available [on
14 | Github](https://github.com/clojuredocs/guides).
15 |
16 |
17 | ## Preliminaries
18 |
19 | Some examples herein make use of the
20 | [math.numeric-tower](https://github.com/clojure/math.numeric-tower)
21 | and
22 | [math.combinatorics](https://github.com/clojure/math.combinatorics)
23 | contrib libraries. It's assumed that either you have the following in
24 | your source code's `ns` macro:
25 |
26 | ``` clojure
27 | (:require [clojure.math.numeric-tower :as math]
28 | [clojure.math.combinatorics :as combo])
29 | ```
30 |
31 | or else in the repl you've loaded them like so:
32 |
33 | ``` clojure
34 | (require '[clojure.math.numeric-tower :as math])
35 | (require '[clojure.math.combinatorics :as combo])
36 | ```
37 |
38 |
39 |
40 | ## Recipes
41 |
42 | ### Simple Math
43 |
44 | ``` clojure
45 | (+ 3 4) ;=> 7
46 | (- 3 4) ;=> -1
47 | (* 3 4) ;=> 12
48 | (/ 3 4) ;=> 3/4 (an exact ratio)
49 | (/ 3.0 4) ;=> 0.75
50 |
51 | (inc 5) ;=> 6
52 | (dec 5) ;=> 4
53 | ```
54 |
55 | For doing integer division and getting remainders (modulus), see the
56 | docs for
57 | [quot](http://clojuredocs.org/clojure_core/clojure.core/quot),
58 | [rem](http://clojuredocs.org/clojure_core/clojure.core/rem), and
59 | [mod](http://clojuredocs.org/clojure_core/clojure.core/mod).
60 |
61 | For exponents, square roots, rounding, ceiling, floor, absolute value,
62 | and greatest/least common multiples, see the [docs for
63 | math.numeric-tower](http://clojure.github.com/math.numeric-tower/).
64 |
65 | ### Trigonometry
66 |
67 | Use what the Java platform provides, for example:
68 |
69 | ``` clojure
70 | Math/PI ;=> 3.14159...
71 | (Math/sin x)
72 | (Math/cos x)
73 | (Math/tan x)
74 | ```
75 |
76 | There are many more functions available, which you can read about in
77 | the [docs for
78 | java.lang.Math](http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html).
79 |
80 |
81 | ### Combinatorics
82 |
83 | For combinatoric functions (such as `combinations` and
84 | `permutations`), see the [docs for
85 | math.combinatorics](http://clojure.github.com/math.combinatorics/).
86 |
--------------------------------------------------------------------------------
/articles/cookbooks/middleware.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Middleware in Clojure"
3 | layout: article
4 | ---
5 |
6 | This work is licensed under a Creative Commons
8 | Attribution 3.0 Unported License (including images &
9 | stylesheets). The source is available [on
10 | Github](https://github.com/clojuredocs/guides).
11 |
12 |
13 | ## What is Middleware?
14 |
15 | Middleware in Clojure is a common design pattern for threading a
16 | *request* through a series of functions designed to operate on it as
17 | well as threading the *response* through the same series of functions.
18 |
19 | Middleware is used in many Clojure projects such as
20 | [Ring](https://github.com/mmcgrana/ring),
21 | [clj-http](https://github.com/dakrone/clj-http) and
22 | [something else here](TODO).
23 |
24 | ## The `client` function
25 |
26 | The base of all middleware in Clojure is the `client` function, which
27 | takes a request object (usually a Clojure map) and returns a response
28 | object (also usually a Clojure map).
29 |
30 | For example, let's use a `client` function that pulls some keys out of
31 | a map request and does an HTTP GET on a site:
32 |
33 | ``` clojure
34 | (ns middleware.example
35 | (:require [clj-http.client :as http]))
36 |
37 | (defn client [request]
38 | (http/get (:site request) (:options request)))
39 | ```
40 |
41 | To use the client method, call it like so (response shortened to fit
42 | here):
43 |
44 | ``` clojure
45 | (client {:site "http://www.aoeu.com" :options {}})
46 | ;; ⇒ {:status 200, :headers {...}, :request-time 3057, :body "..."}
47 | ```
48 |
49 | Now that a client function exists, middleware can be wrapped around it
50 | to change the *request*, the *response*, or both.
51 |
52 | Let's start with a middleware function that doesn't do anything. We'll
53 | call it the `no-op` middleware:
54 |
55 | ``` clojure
56 | ;; It is standard convention to name middleware wrap-
57 | (defn wrap-no-op
58 | ;; the wrapping function takes a client function to be used...
59 | [client-fn]
60 | ;; ...and returns a function that takes a request...
61 | (fn [request]
62 | ;; ...that calls the client function with the request
63 | (client-fn request)))
64 | ```
65 |
66 | So how is this middleware used? First, it must be 'wrapped' around the
67 | existing client function:
68 |
69 | ``` clojure
70 | (def new-client (wrap-no-op client))
71 |
72 | ;; Now new-client can be used just like the client function:
73 | (new-client {:site "http://www.aoeu.com" :options {}})
74 | ;; ⇒ {:status 200, :headers {...}, :request-time 3057, :body "..."}
75 | ```
76 |
77 | It works! Now it's not very exiting because it doesn't do anything
78 | yet, so let's add another middleware wrapper that does something more
79 | exiting.
80 |
81 | Let's add a middleware function that automatically changes all "HTTP"
82 | requests into "HTTPS" requests. Again, we need a function that returns
83 | another function, so we can end up with a new method to call:
84 |
85 | ``` clojure
86 | (defn wrap-https
87 | [client-fn]
88 | (fn [request]
89 | (let [site (:site request)
90 | new-site (.replaceAll site "http:" "https:")
91 | new-request (assoc request :site new-site)]
92 | (client-fn new-request))))
93 | ```
94 |
95 | The `wrap-https` middleware can be tested again by creating a new
96 | client function:
97 |
98 | ``` clojure
99 | (def https-client (wrap-https client))
100 |
101 | ;; Notice the :trace-redirects key shows that HTTPS was used instead
102 | ;; of HTTP
103 | (https-client {:site "http://www.google.com" :options {}})
104 | ;; ⇒ {:trace-redirects ["https://www.google.com"],
105 | ;; :status 200,
106 | ;; :headers {...},
107 | ;; :request-time 3057,
108 | ;; :body "..."}
109 | ```
110 |
111 | Middleware can be tested independently of the client function by
112 | providing the identity function (or any other function that returns a
113 | map). For example, we can see the `wrap-https` middleware returns the
114 | clojure map with the :site changed from 'http' to 'https':
115 |
116 | ``` clojure
117 | ((wrap-https identity) {:site "http://www.example.com"})
118 | ;; ⇒ {:site "https://www.example.com"}
119 | ```
120 |
121 | ## Combining middleware
122 |
123 | In the previous example, we showed how to create and use middleware,
124 | but what about using multiple middleware functions? Let's define one
125 | more middleware so we have a total of three to work with. Here's the
126 | source for a middleware function that adds the current data to the
127 | response map:
128 |
129 | ``` clojure
130 | (defn wrap-add-date
131 | [client]
132 | (fn [request]
133 | (let [response (client request)]
134 | (assoc response :date (java.util.Date.)))))
135 | ```
136 |
137 | And again, we can test it without using any other functions using
138 | `identity` as the client function:
139 |
140 | ``` clojure
141 | ((wrap-add-date identity) {})
142 | ;; ⇒ {:date #inst "2012-11-09T12:41:05.171-00:00"}
143 | ```
144 |
145 | Middleware is useful on its own, but where it becomes truly more
146 | useful is in combining middleware together. Here's what a new client
147 | function looks like combining all the middleware:
148 |
149 | ``` clojure
150 | (def my-client (wrap-add-date (wrap-https (wrap-no-op client))))
151 |
152 | (my-client {:site "http://www.google.com"})
153 | ;; ⇒ {:date #inst "2012-11-09T12:43:39.451-00:00",
154 | ;; :cookies {...},
155 | ;; :trace-redirects ["https://www.google.com/"],
156 | ;; :request-time 1634,
157 | ;; :status 200,
158 | ;; :headers {...},
159 | ;; :body "..."}
160 | ```
161 |
162 | (The response map has been edited to take less space where you see
163 | '...')
164 |
165 | Here we can see that the `wrap-https` middleware has successfully
166 | turned the request for http://www.google.com into one for
167 | https://www.google.com, additionally the `wrap-add-date` middleware
168 | has added the :date key with the date the request happened. (the
169 | `wrap-no-op` middleware did execute, but since it didn't do anything,
170 | there's no output to tell)
171 |
172 | This is a good start, but adding middleware can be expressed in a much
173 | cleaner and clearer way by using Clojure's threading macro, `->`. The
174 | `my-client` definition from above can be expressed like this:
175 |
176 | ``` clojure
177 | (def my-client
178 | (-> client
179 | wrap-no-op
180 | wrap-https
181 | wrap-add-date))
182 |
183 | (my-client {:site "http://www.google.com"})
184 | ;; ⇒ {:date #inst "2012-11-09T12:47:32.130-00:00",
185 | ;; :cookies {...},
186 | ;; :trace-redirects ["https://www.google.com/"],
187 | ;; :request-time 1630,
188 | ;; :status 200,
189 | ;; :headers {...},
190 | ;; :body "..."}
191 | ```
192 |
193 | Something else to keep in mind is that middleware expressed in this
194 | way will be executed _from the bottom up_, so in this case,
195 | `wrap-add-date` will call `wrap-https`, which in turn calls
196 | `wrap-no-op`, which finally calls the `client` function.
197 |
198 | For an example of combining a large amount of middleware, see
199 | [clj-http's
200 | client.clj](https://github.com/dakrone/clj-http/blob/5534950b5ed48e3bc7285f0e956444ea832399da/src/clj_http/client.clj#L542-567)
201 | file
202 |
--------------------------------------------------------------------------------
/articles/cookbooks/strings.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Strings"
3 | layout: article
4 | ---
5 |
6 | This cookbook covers working with strings in Clojure using built-in
7 | functions, standard and contrib libraries, and parts of the JDK via
8 | interoperability.
9 |
10 | This work is licensed under a Creative Commons
12 | Attribution 3.0 Unported License (including images &
13 | stylesheets). The source is available [on
14 | Github](https://github.com/clojuredocs/guides).
15 |
16 |
17 | ## Overview
18 |
19 | * Strings are [plain Java
20 | strings](http://docs.oracle.com/javase/7/docs/api/java/lang/String.html).
21 | You can use anything which operates on them.
22 | * Java strings are immutable, so they're convenient to use in Clojure.
23 | * You can't add metadata to Java strings.
24 | * Clojure supports some convenient notations:
25 |
26 | ```
27 | "foo" java.lang.String
28 | #"\d" java.util.regex.Pattern (in this case, one which matches a single digit)
29 | \f java.lang.Character (in this case, the letter 'f')
30 | ```
31 |
32 | * **Caveat:** Human brains and electronic computers are rather different
33 | devices. So Java strings (sequences of [UTF-16
34 | characters](http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#unicode))
35 | don't always map nicely to user-perceived characters. For example, a
36 | single Unicode "code point" doesn't necessarily equal a user-perceived
37 | character. (Like Korean Hangul Jamo, where user-perceived characters
38 | are composed from two or three Unicode code points.) Also, a Unicode
39 | code point may sometimes require 2 UTF-16 characters to encode it.
40 |
41 |
42 | ## Preliminaries
43 |
44 | Some examples use
45 | [clojure.string](http://clojure.github.io/clojure/clojure.string-api.html),
46 | [clojure.edn](https://github.com/edn-format/edn) and
47 | [clojure.pprint](http://clojure.github.io/clojure/clojure.pprint-api.html). We'll
48 | assume your `ns` macro contains:
49 |
50 | ``` clojure
51 | (:require [clojure.string :as str]
52 | [clojure.edn :as edn]
53 | [clojure.pprint :as pp])
54 | ```
55 |
56 | or else in the repl you've loaded it:
57 |
58 | ``` clojure
59 | (require '[clojure.string :as str])
60 | (require '[clojure.edn :as edn])
61 | (require '[clojure.pprint :as pp])
62 | ```
63 |
64 |
65 | ## Recipes
66 |
67 | ### Basics
68 |
69 | ``` clojure
70 | ;; Size measurements
71 | (count "0123") ;=> 4
72 | (empty? "0123") ;=> false
73 | (empty? "") ;=> true
74 | (str/blank? " ") ;=> true
75 |
76 | ;; Concatenate
77 | (str "foo" "bar") ;=> "foobar"
78 | (str/join ["0" "1" "2"]) ;=> "012"
79 | (str/join "." ["0" "1" "2"]) ;=> "0.1.2"
80 |
81 | ;; Matching using plain Java methods.
82 | ;;
83 | ;; You might prefer regexes for these. For instance, failure returns
84 | ;; -1, which you have to test for. And characters like \o are
85 | ;; instances of java.lang.Character, which you may have to convert to
86 | ;; int or String.
87 | (.indexOf "foo" "oo") ;=> 1
88 | (.indexOf "foo" "x") ;=> -1
89 | (.lastIndexOf "foo" (int \o)) ;=> 2
90 |
91 | ;; Substring
92 | (subs "0123" 1) ;=> "123"
93 | (subs "0123" 1 3) ;=> "12"
94 | (str/trim " foo ") ;=> "foo"
95 | (str/triml " foo ") ;=> "foo "
96 | (str/trimr " foo ") ;=> " foo"
97 |
98 | ;; Multiple substrings
99 | (seq "foo") ;=> (\f \o \o)
100 | (str/split "foo/bar/quux" #"/") ;=> ["foo" "bar" "quux"]
101 | (str/split "foo/bar/quux" #"/" 2) ;=> ["foo" "bar/quux"]
102 | (str/split-lines "foo
103 | bar") ;=> ["foo" "bar"]
104 |
105 | ;; Case
106 | (str/lower-case "fOo") ;=> "foo"
107 | (str/upper-case "fOo") ;=> "FOO"
108 | (str/capitalize "fOo") ;=> "Foo"
109 |
110 | ;; Escaping
111 | (str/escape "foo|bar|quux" {\| "||"}) ;=> "foo||bar||quux"
112 |
113 | ;; Get byte array of given encoding.
114 | ;; (The output will likely have a different number than "3c3660".)
115 | (.getBytes "foo" "UTF-8") ;=> #
116 |
117 | ;; Parsing keywords
118 | (keyword "foo") ;=> :foo
119 |
120 | ;; Parsing numbers
121 | (bigint "20000000000000000000000000000") ;=> 20000000000000000000000000000N
122 | (bigdec "20000000000000000000.00000000") ;=> 20000000000000000000.00000000M
123 | (Integer/parseInt "2") ;=> 2
124 | (Float/parseFloat "2") ;=> 2.0
125 |
126 | ;; Parsing edn, a subset of Clojure forms.
127 | (edn/read-string "0xffff") ;=> 65535
128 |
129 | ;; The sledgehammer approach to reading Clojure forms.
130 | ;;
131 | ;; SECURITY WARNING: Ensure *read-eval* is false when dealing with
132 | ;; strings you don't 100% trust. Even though *read-eval* is false by
133 | ;; default since Clojure 1.5, be paranoid and set it to false right
134 | ;; before you use it, because anything could've re-bound it to true.
135 | (binding [*read-eval* false]
136 | (read-string "#\"[abc]\""))
137 | ;=> #"[abc]"
138 | ```
139 |
140 |
141 | ### Parsing complex strings
142 |
143 | #### Regexes
144 |
145 | Regexes offer a boost in string-matching power. You can express ideas
146 | like repetition, alternatives, etc.
147 |
148 | [Regex
149 | reference.](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html)
150 |
151 | **Groups:** Regex groups are useful, when we want to match more than
152 | one substring. (Or refer to matches later.) In the regex `#"(group-1)
153 | (group-2)"`, the 0th group is the whole match. The 1st group is
154 | started by the left-most `(`, the 2nd group is started by the
155 | second-left-most `(`, etc. You can even nest groups. You can refer to
156 | groups later using `$0`, `$1`, etc.
157 |
158 | **Matching**
159 |
160 | ```clojure
161 | ;; Simple matching
162 | (re-find #"\d+" "foo 123 bar") ;=> "123"
163 |
164 | ;; What happens when a match fails.
165 | (re-find #"\d+" "foobar") ;=> nil
166 |
167 | ;; Return only the first groups which satisfy match.
168 | (re-matches #"(@\w+)\s([.0-9]+)%"
169 | "@shanley 19.8%")
170 | ;=>["@shanley 19.8%" "@shanley" "19.8"]
171 |
172 | ;; Return seq of all matching groups which occur in string.
173 | (re-seq #"(@\w+)\s([.0-9]+)%"
174 | "@davidgraeber 12.3%,@shanley 19.8%")
175 | ;=> (["@davidgraeber 12.3%" "@davidgraeber" "12.3"]
176 | ; ["@shanley 19.8%" "@shanley" "19.8"])
177 | ```
178 |
179 | **Replacing**
180 |
181 | We use `str/replace`. Aside from the first arg (the initial string),
182 | the next two args are match and replacement:
183 |
184 | ```
185 | match / replacement can be:
186 | string / string
187 | char / char
188 | pattern / (string or function of match).
189 | ```
190 |
191 | ```clojure
192 | ;; In the replacement string, $0, $1, etc refer to matched groups.
193 | (str/replace "@davidgraeber 12.3%,@shanley 19.8%"
194 | #"(@\S+)\s([.0-9]+)%"
195 | "$2 ($1)")
196 | ;=> "12.3 (@davidgraeber),19.8 (@shanley)"
197 |
198 | ;; Using a function to replace text gives us power.
199 | (println
200 | (str/replace "@davidgraeber 12.3%,@shanley 19.8%"
201 | #"(@\w+)\s([.0-9]+)%,?"
202 | (fn [[_ person percent]]
203 | (let [points (-> percent Float/parseFloat (* 100) Math/round)]
204 | (str person "'s followers grew " points " points.\n")))))
205 | ;print=> @davidgraeber's followers grew 1230 points.
206 | ;print=> @shanley's followers grew 1980 points.
207 | ;print=>
208 | ```
209 |
210 |
211 | #### Context-free grammars
212 |
213 | Context-free grammars offer yet another boost in expressive matching
214 | power, compared to regexes. You can express ideas like nesting.
215 |
216 | We'll use [Instaparse](https://github.com/Engelberg/instaparse) on
217 | [JSON's grammar](http://www.json.org/). (This example isn't seriously
218 | tested nor a featureful parser. Use
219 | [data.json](https://github.com/clojure/data.json) instead.)
220 |
221 | ``` clojure
222 | ;; Your project.clj should contain this (you may need to restart your JVM):
223 | ;; :dependencies [[instaparse "1.2.4"]]
224 | ;;
225 | ;; We'll assume your ns macro contains:
226 | ;; (:require [instaparse.core :as insta])
227 | ;; or else in the repl you've loaded it:
228 | ;; (require '[instaparse.core :as insta])
229 |
230 | (def barely-tested-json-parser
231 | (insta/parser
232 | "object = <'{'> (members )* <'}'>
233 | = pair ( <','> members)*
234 | = string <':'> value
235 | = string | number | object | array | 'true' | 'false' | 'null'
236 | array = <'['> elements* <']'>
237 | = value (<','> elements)*
238 | number = int frac? exp?
239 | = '-'? digits
240 | = '.' digits
241 | = e digits
242 | = ('e' | 'E') (<'+'> | '-')?
243 | = #'[0-9]+'
244 | (* First sketched state machine; then it was easier to figure out
245 | regex syntax and all the maddening escape-backslashes. *)
246 | string = <'\\\"'> #'([^\"\\\\]|\\\\.)*' <'\\\"'>
247 | = #'\\s+'"))
248 |
249 | (barely-tested-json-parser "{\"foo\": {\"bar\": 99.9e-9, \"quux\": [1, 2, -3]}}")
250 | ;=> [:object
251 | ; [:string "foo"]
252 | ; [:object
253 | ; [:string "bar"]
254 | ; [:number "99" "." "9" "e" "-" "9"]
255 | ; [:string "quux"]
256 | ; [:array [:number "1"] [:number "2"] [:number "-" "3"]]]]
257 |
258 | ;; That last output is a bit verbose. Let's process it further.
259 | (->> (barely-tested-json-parser "{\"foo\": {\"bar\": 99.9e-9, \"quux\": [1, 2, -3]}}")
260 | (insta/transform {:object hash-map
261 | :string str
262 | :array vector
263 | :number (comp edn/read-string str)}))
264 | ;=> {"foo" {"quux" [1 2 -3], "bar" 9.99E-8}}
265 |
266 |
267 | ;; Now we can appreciate what those were all about.
268 | ;;
269 | ;; When to the right of the grammar's =, it totally hides the enclosed
270 | ;; thing in the output. For example, we don't care about whitespace,
271 | ;; so we hide it with .
272 | ;;
273 | ;; When to the left of the grammar's =, it merely prevents a level of
274 | ;; nesting in the output. For example, "members" is a rather
275 | ;; artificial entity, so we prevent a pointless level of nesting with
276 | ;; .
277 | ```
278 |
279 |
280 | ### Building complex strings
281 |
282 | #### Redirecting streams
283 |
284 | `with-out-str` provides a simple way to build strings. It redirects
285 | standard output (`*out*`) to a fresh `StringWriter`, then returns the
286 | resulting string. So you can use functions like `print`, *even in
287 | nested functions*, and get the resulting string at the end.
288 |
289 | ``` clojure
290 | (let [shrimp-varieties ["shrimp-kabobs" "shrimp creole" "shrimp gumbo"]]
291 | (with-out-str
292 | (print "We have ")
293 | (doseq [name (str/join ", " shrimp-varieties)]
294 | (print name))
295 | (print "...")))
296 | ;=> "We have shrimp-kabobs, shrimp creole, shrimp gumbo..."
297 | ```
298 |
299 | #### Format strings
300 |
301 | Java's templating mini-language helps you build many strings
302 | conveniently. [Reference.](http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html)
303 |
304 | ``` clojure
305 | ;; %s is most commonly used to print args. Escape %'s with %%.
306 | (format "%s enjoyed %s%%." "Mozambique" 19.8) ;=> "Mozambique enjoyed 19.8%."
307 |
308 | ;; The 1$ prefix allows you to keep referring to the first arg.
309 | (format "%1$tY-%1$tm-%1$td" #inst"2000-01-02T00:00:00") ;=> "2000-01-02"
310 |
311 | ;; Again, 1$, 2$, etc prefixes let us refer to args in arbitrary orders.
312 | (format "New year: %2$tY. Old year: %1$tY"
313 | #inst"2000-01-02T00:00:00"
314 | #inst"3111-12-31T00:00:00")
315 | ;=> "New year: 3111. Old year: 2000"
316 | ```
317 |
318 |
319 | #### CL-Format
320 |
321 | `cl-format` is a port of Common Lisp's notorious, powerful string
322 | formatting mini-language. For example, you can build strings from
323 | sequences. (As well as oddities like print numbers in English or two
324 | varieties of Roman numerals.) However, it's weaker than plain `format`
325 | with printing dates and referring to args in arbitrary order.
326 |
327 | Remember that `cl-format` represents a (potentially unreadable)
328 | language which your audience didn't sign up to learn. If you're the
329 | sort of person who likes it, try to only use it in sweetspots where it
330 | provides clarity for little complexity.
331 |
332 | [Tutorial](http://www.gigamonkeys.com/book/a-few-format-recipes.html)
333 | in Practical Common
334 | Lisp. [Reference](http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm)
335 | in Common Lisp's Hyperspec.
336 |
337 | ``` clojure
338 | ;; The first param prints to *out* if true. To string if false.
339 | ;; To a stream if it's a stream.
340 | (pp/cl-format true "~{~{~a had ~s percentage point~:p.~}~^~%~}"
341 | {"@davidgraeber" 12.3
342 | "@shanley" 19.8
343 | "@tjgabbour" 1})
344 | ;print=> @davidgraeber had 12.3 percentage points.
345 | ;print=> @tjgabbour had 1 percentage point.
346 | ;print=> @shanley had 19.8 percentage points.
347 |
348 | (def format-string "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}")
349 | (pp/cl-format nil format-string [])
350 | ;=> ""
351 | (pp/cl-format nil format-string ["@shanley"])
352 | ;=> "@shanley"
353 | (pp/cl-format nil format-string ["@shanley", "@davidgraeber"])
354 | ;=> "@shanley and @davidgraeber"
355 | (pp/cl-format nil format-string ["@shanley", "@davidgraeber", "@sarahkendzior"])
356 | ;=> "@shanley, @davidgraeber, and @sarahkendzior"
357 | ```
358 |
359 | ## Contributors
360 |
361 | Tj Gabbour , 2013 (original author)
362 |
--------------------------------------------------------------------------------
/articles/ecosystem/community.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Clojure Community"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * The Official Clojure mailing lists
9 | * IRC channel
10 | * Documentation sites
11 | * Clojure User Groups around the globe
12 | * Conferences about or related to Clojure
13 | * Various Community sites about Clojure (subreddit, etc)
14 |
15 | This work is licensed under a Creative Commons Attribution 3.0 Unported License
16 | (including images & stylesheets). The source is available [on Github](https://github.com/clojuredocs/guides).
17 |
18 |
19 | ## Clojure Mailing Lists
20 |
21 | * [Clojure user mailing list](https://groups.google.com/forum/?fromgroups#!forum/clojure)
22 | * [Clojure development mailing list](https://groups.google.com/forum/?fromgroups#!forum/clojure-dev)
23 |
24 |
25 | ## Clojure IRC Channels
26 |
27 | ### Main Channel
28 |
29 | `#clojure` on `irc.freenode.net`.
30 |
31 | Channel logs are available at [clojure-log.n01se.net](http://clojure-log.n01se.net/) and [www.raynes.me/logs/irc.freenode.net/clojure/](http://www.raynes.me/logs/irc.freenode.net/clojure/).
32 |
33 |
34 | ### Documentation Channel
35 |
36 | `#clojure-doc` on `irc.freenode.net`.
37 |
38 |
39 | ## Documentation
40 |
41 | * [Clojuredocs](http://clojuredocs.org/): Clojure API reference, with examples
42 | * [Clojure API Cheatsheet](http://jafingerhut.github.io/cheatsheet/clojuredocs/cheatsheet-tiptip-no-cdocs-summary.html)
43 | * [Clojure Koans](http://clojurekoans.com/)
44 | * [GetClojure](http://www.getclojure.org): Tens of thousands of searchable Clojure examples mined from all over the internet.
45 | * [Grimoire](http://grimoire.arrdem.com/)
46 |
47 |
48 | ## Courses
49 |
50 | * [Udemy's 19 part series on Clojure](http://www.udemy.com/clojure-code)
51 | * [Functional Programming with Clojure](http://mooc.cs.helsinki.fi/clojure)
52 |
53 |
54 | ## User Groups
55 |
56 | * The list of [Clojure User Groups](/articles/ecosystem/user_groups.html) around the world
57 | * [How to run your own Clojure User Group](/articles/ecosystem/running_cljug.html)
58 |
59 |
60 | ## Videos About Clojure
61 |
62 | Videos of talks about Clojure are often made available on [InfoQ](http://www.infoq.com/clojure), and [Clojure YouTube channel](https://www.youtube.com/user/ClojureTV).
63 |
64 | * [Full Disclojure](http://vimeo.com/channels/fulldisclojure/videos) is a series of screencasts about Clojure
65 | * [Clojure Concurrency Tutorial](http://pluralsight.com/training/Courses/TableOfContents/clojure-concurrency-tutorial)
66 | * [Clojure Inside Out](http://shop.oreilly.com/product/0636920030409.do) from O'Reilly
67 | * [Clojure Koans Walkthroughs](http://www.youtube.com/playlist?list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt)
68 | * [Clojure Fundamentals](http://pluralsight.com/training/courses/TableOfContents?courseName=clojure-fundamentals-part-one)
69 | * [LispCast](http://www.purelyfunctional.tv/)
70 | * [Clojure Tutorials by Tim Baldridge](https://tbaldridge.pivotshare.com/)
71 |
72 |
73 | ## Podcasts About Clojure
74 |
75 | * [Mostly λazy… a Clojure podcast](http://mostlylazy.com/) by Chas Emerick
76 | * [Cognicast](http://cognitect.com/podcast) by Craig Andera often discusses topics relevant to Clojure and ClojureScript.
77 |
78 |
79 | ## Code Repositories
80 |
81 | Most folks host their projects at
82 | [GitHub](https://github.com/languages/Clojure), and most pure Clojure
83 | library distributions (with the exception of contrib) are available at
84 | [Clojars](https://clojars.org/).
85 |
86 |
87 | ## Websites
88 |
89 | * [Clojure.org](http://clojure.org/): the official website
90 | * [Planet Clojure](http://planet.clojure.in/): aggregator of selected Clojure-related blog posts
91 | * [Clojure at Rosetta Code](http://rosettacode.org/wiki/Category:Clojure)
92 | * [Clojure Confluence wiki](http://dev.clojure.org/dashboard.action)
93 | * [The Clojure Toolbox](http://www.clojure-toolbox.com/): a categorized directory of libraries and tools for Clojure
94 | * [4Clojure](https://www.4clojure.com/): Clojure exercise problems
95 | * [Exercism.io](http://exercism.io/): Peer-reviewed Clojure exercises
96 |
97 |
98 | ## Forums
99 |
100 | * [r/Clojure subreddit](http://www.reddit.com/r/clojure)
101 |
102 |
103 | ## Conferences
104 |
105 | In no particular order:
106 |
107 | * [Clojure/conj](http://clojure-conj.org/), aka "the Conj"
108 | * [EuroClojure](http://euroclojure.com/)
109 | * [Clojure/West](http://clojurewest.org/)
110 | * [StrangeLoop](https://thestrangeloop.com/) (not about Clojure but often has strong Clojure community presence)
111 | * [Lambda Jam](http://lambdajam.com/) (also not about Clojure but has strong Clojure community presence)
112 |
113 |
114 | ## Email Newsletters
115 |
116 | * [Clojure Gazette](http://www.clojuregazette.com/)
117 | * [(def newsletter)](http://defnewsletter.com/)
118 |
119 |
120 | ## Workshops
121 |
122 | * [ClojureBridge](http://www.clojurebridge.org/)
123 | * [Lambda Next](http://lambdanext.eu/)
124 |
125 |
126 | ## Core development
127 |
128 | See the [Clojure Confluence wiki](http://dev.clojure.org/display/design/Home) for full details on
129 | how core development is handled.
130 |
131 | Coordination of development efforts happen on the development mailing list, on the Confluence wiki,
132 | and make use of the [JIRA bug and issue tracker](http://dev.clojure.org/jira/browse/CLJ).
133 |
134 | Although Clojure and the contrib libraries all have homes [at GitHub](http://github.com/clojure),
135 | **pull-requests are not accepted**. All core development happens via JIRA, patches and the Confluence wiki.
136 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/filters.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Filters"
3 | layout: article
4 | ---
5 |
6 | core.typed includes an implementation of occurrence typing, which helps the type
7 | checker refine types according to control flow.
8 |
9 | Occurrence typing helps core.typed infer a very accurate type for this expression
10 | by recognising the semantics of predicates like `symbol?` and `number?`.
11 |
12 | ```clojure
13 | clojure.core.typed=> (cf (let [a (ann-form 1 Any)]
14 | (cond
15 | (symbol? a) a
16 | (number? a) a)))
17 | (U clojure.lang.Symbol java.lang.Number nil)
18 | ```
19 |
20 | ## Filters
21 |
22 | core.typed collects more information than just types for each expression.
23 |
24 | A structure called a filter set is also inferred. A filter set is a collection
25 | of two filters:
26 |
27 | - a filter that is true if the expression is a true value, called the `then` filter
28 | - a filter that is true if the expression is a false value, called the `else` filter
29 |
30 | ### Trivial Filters
31 |
32 | There are two trivial filters:
33 |
34 | - `tt`, the trivially true filter
35 | - `ff`, the impossible filter
36 |
37 | We can use `cf` to check the filters of expressions.
38 |
39 | ```clojure
40 | clojure.core.typed=> (cf 1)
41 | [(Value 1) {:then tt, :else ff}]
42 | ```
43 |
44 | The second place of the result vector is the filter set inferred for the expression.
45 | `{:then tt, :else ff}` reads: the expression could be a true value, but it is impossible
46 | for it to be a false value. This of course aligns with the semantics of numbers in Clojure.
47 |
48 | False values are never true:
49 |
50 | ```clojure
51 | clojure.core.typed=> (cf nil)
52 | [nil {:then ff, :else tt}]
53 | ```
54 |
55 | ### Positive and Negative Type Filters
56 |
57 | Filters can hold information relating bindings to types.
58 |
59 | A positive type filter refines a local binding to be a type.
60 |
61 | This filter says that the local binding `a` is of type `Number`.
62 |
63 | ```clojure
64 | (is Number a)
65 | ```
66 |
67 | A negative type filter refines a local binding to *not* be a type.
68 |
69 | This filter says that the local binding `a` is *not* of type `Number`.
70 |
71 | ```clojure
72 | (! Number a)
73 | ```
74 |
75 | ### Latent Filters
76 |
77 | Filters almost never need to be written directly in normal code. *Latent* filters
78 | however are very useful, and provide the most useful information to core.typed.
79 |
80 | A *latent filter set* is a filter set attached to a function type. It is latent
81 | because it is not used directly: instead when a function with a latent filter set
82 | is called, the filter set is instantiated in a way that makes sense in the current
83 | context before it is used like a normal filter.
84 |
85 | ### Predicates
86 |
87 | A very common place for a latent filters are in the types for predicates.
88 |
89 | The type for `symbol?`, is
90 |
91 | ```clojure
92 | [Any -> Boolean :filters {:then (is Symbol 0), :else (! Symbol 0)}]
93 | ```
94 |
95 | First, notice that latent type predicates can also take an integer as an identifier.
96 | The `0` represents the first argument of the function the latent filter set is attached to.
97 |
98 | So the latent `then` filter `(is Symbol 0)` says the first argument to `symbol?` is of type `Symbol`
99 | if the whole expression is a true value. To retrieve a non-latent filter, the `0` is instantiated to
100 | the appropriate local binding.
101 |
102 | ```
103 | Note: Use `clojure.core.typed/print-filterset` to print the filter set of an expression.
104 | ```
105 |
106 | ```clojure
107 | clojure.core.typed=> (cf (let [a (ann-form 1 Any)]
108 | (print-filterset "symbol filters"
109 | (symbol? a))))
110 | "symbol filters"
111 | {:then (is clojure.lang.Symbol a), :else (! clojure.lang.Symbol a)}
112 | empty-object
113 | Flow tt
114 | boolean
115 | ```
116 |
117 | By printing the filter set of `(symbol? a)` we can see this in work, which
118 | has a non-latent filter set of `{:then (is clojure.lang.Symbol a), :else (! clojure.lang.Symbol a)}`.
119 |
120 | ### Paths and Objects
121 |
122 | TODO
123 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/function_types.md:
--------------------------------------------------------------------------------
1 | - Function types are quite different from Typed Racket
2 | - anything can implement the `IFn` interface
3 | - In core.typed the `Function` type is more a special type than the type for lambdas
4 |
5 | Common things that are `IFn`s:
6 | ```clojure
7 | - clojure.lang.Function
8 | - c.l.Keyword
9 | - [Any -> Any]
10 | - (c.l.PersistentHashMap k v)
11 | - (All [x]
12 | (Fn [Any -> (U nil v)]
13 | [Any x -> (U x v)]))
14 | - (c.l.PersistentHashSet v)
15 | - (All [x]
16 | (Fn [Any -> (U nil v)]))
17 | - c.l.Symbol
18 | - [Any -> Any]
19 | - (Value :a)
20 | - (All [x]
21 | [Any -> x :filters {:then (is {:a x} 0)}])
22 | - (Value sym)
23 | - (All [x] [Any -> (U nil v)])
24 | ```
25 |
26 | The `IFn` class might be parameterised by a `Function` type.
27 | The immediate problem is intersections allows us to have more
28 | than one function type.
29 |
30 | eg. What function type is this?
31 |
32 | ```clojure
33 | (I (Value :a)
34 | (All [x]
35 | [Any -> x :filters {:then (is {:a x} 0)}])
36 | ```
37 |
38 | Even `(Value :a)` inherits two function types:
39 | - that for c.l.Keyword
40 | - that for `(Value :a)`
41 |
42 | `(Value :a) <: (IFn x)` infers `x` to be:
43 |
44 | ```clojure
45 | (I [Any -> Any]
46 | (All [x]
47 | [Any -> x :filters {:then (is {:a x} 0)}])
48 | ```
49 |
50 | The second member of the intersection is more specific,
51 | thus can be simplified to:
52 |
53 | ```clojure
54 | (All [x]
55 | [Any -> x :filters {:then (is {:a x} 0)}])
56 | ```
57 |
58 | Does this work in general? As long as there is a subtyping relationship
59 | between the possible `Function` types, we can infer the most useful
60 | one.
61 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/home.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "core.typed User Documentation Home"
3 | layout: article
4 | ---
5 |
6 | core.typed is an optional type system for Clojure.
7 |
8 | ## Quickstart
9 |
10 | `(clojure.core.typed/ann v t)` gives var `v` the static type `t`.
11 |
12 | `(clojure.core.typed/ann-form f t)` ensures form `f` is of the static type `t`.
13 |
14 | `(clojure.core.typed/check-ns)` type checks the current namespace.
15 |
16 | `(clojure.core.typed/cf t)` type checks the form `t`.
17 |
18 | See the [Quick Guide](quick_guide.html).
19 |
20 | ## [Rationale](rationale.html)
21 |
22 | Why core.typed exists, what can it do for you?
23 |
24 | ## Getting Started Guide
25 |
26 | If you are new to core.typed, gradual type systems, or even types in general, and want to learn how
27 | core.typed can help verify your programs, start here.
28 |
29 | ### [Introduction and Motivation](start/introduction_and_motivation.html)
30 |
31 | We discuss some theory and design goals of core.typed.
32 |
33 | ### [Annotations](start/annotations.html)
34 |
35 | Where and how to annotate your code to help core.typed check your code.
36 |
37 | ### [Types](types.html)
38 |
39 | Syntax and descriptions of core.typed types.
40 |
41 | ### [Polymorphic Functions, Bounds and Higher-kinded Variables](poly_fn.html)
42 |
43 | ### [Filters](filters.html)
44 |
45 | An overview of filters for occurrence typing.
46 |
47 | ### [Datatypes and Protocols](mm_protocol_datatypes.html)
48 |
49 | Typing definitions and usages of Clojure datatypes and protocols.
50 |
51 | ### [Looping constructs](loops.html)
52 |
53 | core.typed provides several wrapper macros for common looping constructs.
54 |
55 | ### Dotted Functions
56 | ### Java Classes, Arrays and Interop
57 |
58 | ## Miscellaneous Tutorials
59 |
60 | ### [Hole-Driven Development](https://github.com/clojure/core.typed/blob/master/src/test/clojure/clojure/core/typed/test/hole.clj)
61 |
62 | A fun diversion playing with holes.
63 | - Requires some knowledge of Haskell.
64 |
65 | ## Examples
66 |
67 | ### [IRC Bot](https://github.com/frenchy64/Parjer)
68 |
69 | ## [Limitations](limitations.html) - Known issues
70 |
71 | ## Documentation Contributors
72 |
73 | Ambrose Bonnaire-Sergeant (@ambrosebs)
74 |
75 | Copyright 2013, Ambrose Bonnaire-Sergeant
76 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/limitations.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "core.typed User Documentation Home"
3 | layout: article
4 | ---
5 |
6 | ## Namespace management
7 |
8 | Typed dependencies NYI.
9 |
10 | ## Destructuring
11 |
12 | Only map destructuring *without* options is supported.
13 |
14 | Other forms of destructuring require equality filters.
15 |
16 | ## Shadowing bindings
17 |
18 | If an argument is shadowed and the shadowed binding is referenced
19 | in filters or object then the shadow is indistinguishable from the parameter
20 | and parameter will be incorrectly abstracted.
21 |
22 | eg.
23 | ```clojure
24 | (fn [a]
25 | (if (= a 1)
26 | (let [a 'foo] ; here this shadows the argument, impossible to recover filters
27 | a) ; in fact any new filters about a will be incorrectly assumed to be the argument
28 | false))
29 | ```
30 |
31 | (See `abstract-result` in `typed/test.clj`)
32 |
33 | ## Dotted Functions
34 |
35 | A dotted function contains a dotted variable in its function type.
36 |
37 | eg. map's type:
38 | `(All [c a b ...]
39 | [[a b ... b -> c] (U nil (Seqable a)) (U nil (Seqable b)) ... b -> (Seqable c)]))`
40 |
41 | We can't currently check the definitions of functions with dotted rest arguments.
42 |
43 | ## Rest Arguments
44 |
45 | Currently cannot check the definition of functions with rest arguments,
46 | but usage checking should work.
47 |
48 | ## Using `filter`
49 |
50 | Not everything can be inferred from a `filter`. A common example is
51 | `(filter identity coll)` does not work. The reason is `identity` only
52 | gives negative information when its result is true: that the argument is *not*
53 | `(U nil false)`.
54 |
55 | This idiom must be converted to this syntax `(fn [a] a)` and then annotated with
56 | positive propositions.
57 |
58 | ```clojure
59 | ;eg.
60 |
61 | (filter (ann-form (fn [a] a)
62 | [(U nil Number) -> (U nil Number) :filters {:then (is Number 0)}])
63 | [1 nil 2])
64 | ; :- (Seqable Number)
65 | ```
66 |
67 | Positive information infers just fine, like `(filter number? coll)`.
68 | The above idiom is useful when you are filtering something like a `(Seqable (U nil x))` and there is no
69 | predicate to test for `x`, so you can only test if something isn't `nil`.
70 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/loops.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Looping constructs"
3 | layout: article
4 | ---
5 |
6 | Due to limitations in core.typed's inference, we require using "typed" versions
7 | of several core forms.
8 |
9 | # loop
10 |
11 | Usages of `loop` should be replaced with `clojure.core.typed/loop>`.
12 |
13 | The syntax is identical except each loop variable requires a type annotation.
14 |
15 | ```clojure
16 | (loop> [[a :- Number] 1
17 | [b :- (U nil Number)] nil]
18 | ...)
19 | ```
20 |
21 | # Named fn's
22 |
23 | Named `fn`'s require full annotation for accurate recursive calls inside the `fn` body.
24 |
25 | ```clojure
26 | clojure.core.typed=> (cf (ann-form (fn a [n] (+ (a 1) n))
27 | [Number -> Number]))
28 | (Fn [java.lang.Number -> java.lang.Number])
29 | ```
30 |
31 | # for
32 |
33 | Use `clojure.core.typed/for>` instead of `for`.
34 |
35 | `for>` requires annotations for the return type of the body
36 | of the for, and the left hand side of each binding form.
37 |
38 | ```clojure
39 | (for> :- Number
40 | [[a :- (U nil AnyInteger)] [1 nil 2 3]
41 | :when a]
42 | (inc a))
43 | ```
44 |
45 | # doseq
46 |
47 | Use `clojure.core.typed/doseq>` instead of `doseq`.
48 |
49 | `doseq>` requires annotations for the left hand side of each binding form.
50 |
51 | ```clojure
52 | (doseq> [[a :- (U nil AnyInteger)] [1 nil 2 3]
53 | :when a]
54 | (inc a))
55 | ```
56 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/mm_protocol_datatypes.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "core.typed User Documentation Home"
3 | layout: article
4 | ---
5 |
6 | ## Annotating Protocols
7 |
8 | `clojure.core.typed/ann-protocol` annotates protocols.
9 |
10 | Takes a name and a optionally a :methods keyword argument mapping
11 | method names to expected types.
12 |
13 | Protocol definitions should use `clojure.core.typed/defprotocol>` (identical syntax to `defprotocol`).
14 |
15 | ```clojure
16 | (ann-protocol IUnifyWithLVar
17 | unify-with-lvar [Term LVar ISubstitutions -> (U ISubstitutions Fail)])
18 |
19 | (defprotocol> IUnifyWithLVar
20 | (unify-with-lvar [v u s]))
21 | ```
22 |
23 | Each protocol method argument (including the first) is explicit in the type annotation.
24 | Often, the the first argument (aka. `this`) will just be the protocol, but in some cases
25 | it is convenient to add more general types.
26 |
27 | ## Annotating datatypes
28 |
29 | `clojure.core.typed/ann-datatype` annotates datatypes.
30 |
31 | Takes a name and a vector of fieldname/type type entries.
32 |
33 | ```clojure
34 | (ann-datatype Pair [lhs :- Term
35 | rhs :- Term])
36 |
37 | (deftype Pair [lhs rhs]
38 | ...)
39 | ```
40 |
41 | Each protocol extended in `deftype` must have an annotated expected type with `ann-protocol`.
42 |
43 | The types for Java interface method are inferred from their corresponding Java type.
44 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/poly_fn.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Polymorphic Functions"
3 | layout: article
4 | ---
5 |
6 | core.typed supports polymorphic function types. They allow us to specify
7 | function types which are both general and accurate.
8 |
9 | # All
10 |
11 | The primitive `All` constructor creates a polymorphic binder and scopes
12 | type variables in a type.
13 |
14 | The identity function has a simple polymorphic type:
15 |
16 | ```clojure
17 | (All [x]
18 | [x -> x])
19 | ```
20 |
21 | Read: for all types `x`, a function that takes an `x` and returns an `x`.
22 |
23 | Polymorphic types are introduced with annotations, but where are they eliminated?
24 | We use local type inference to infer type variable types based on how they are used.
25 |
26 | ```clojure
27 | (identity :a)
28 | ```
29 |
30 | In the above example, we infer `x` to be `Keyword`, and instantiate the polymorphic
31 | type as `[Keyword -> Keyword]`.
32 |
33 | ## Bounds
34 |
35 | Type variables support upper and lower type bounds, which default to `Any` and `Nothing`
36 | respectively.
37 |
38 | Equivalently, the type:
39 |
40 | ```clojure
41 | (All [x] ...)
42 | ```
43 |
44 | is shorthand for:
45 |
46 | ```clojure
47 | (All [[x :> Nothing :< Any]] ...)
48 | ```
49 |
50 | We use bounds to ensure a type variable can only be instantiated to a particular type.
51 |
52 | The type of an identity function that only accepts `Number`s can be written:
53 |
54 | ```clojure
55 | (All [[x :< Number]]
56 | [x -> x])
57 | ```
58 |
59 | Bounds do not seem as useful in core.typed as languages like Java or Scala.
60 | Often, combinations of ordered function intersections and unions are more useful.
61 |
62 | Bounds are also recursive: a bound can refer to the variable it's bounding.
63 | Type variables to the left of the type variable being bounded in the same binder are in scope in a bound.
64 |
65 | ## Higher-kinded variables
66 |
67 | Note: Experimental feature
68 |
69 | A type variable can be of a higher-kind.
70 |
71 | ```clojure
72 | (def-alias AnyMonad
73 | (TFn [[m :kind (TFn [[x :variance :covariant]] Any)]]
74 | '{:m-bind (All [x y]
75 | [(m x) [x -> (m y)] -> (m y)])
76 | :m-result (All [x]
77 | [x -> (m x)])
78 | :m-zero (U (All [x] (m x)) Undefined)
79 | :m-plus (U (All [x]
80 | [(m x) * -> (m x)])
81 | Undefined)}))
82 | ```
83 |
84 | In this type, `x` is a type function taking a type and returning a type.
85 | For those familiar with Haskell, `x` is of kind `* -> *`.
86 |
87 | The type function is also covariant, which further ensures `x` is instantiated
88 | to a covariant type function.
89 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/quick_guide.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "core.typed Quick Guide"
3 | layout: article
4 | ---
5 |
6 | ## Design choices
7 |
8 | ### All vars must have annotated static types
9 |
10 | Use `clojure.core.typed/ann` to assign types to vars
11 |
12 | eg. Assign `my-fn` in the current namespace the type `[Any -> Any]` (a function of one argument).
13 |
14 | ```clojure
15 | (ann my-fn [Any -> Any])
16 | ```
17 |
18 | ### Type checking is separate to compilation and must be explicitly run
19 |
20 | Use `clojure.core.typed/check-ns` to type check the current namespace.
21 | This can be done at the REPL.
22 |
23 | Note: Global annotations like `ann` are only valid when found in a namespace currently being
24 | checked with `check-ns`, or wrapped in a `cf`. A raw `ann` in a REPL has *no effect*.
25 | Global annotations should be top-level forms or inside a (possibly nested) top-level `do`.
26 |
27 | ### All function arguments need to be annotated, or default to `Any`
28 |
29 | Use `clojure.core.typed/ann-form` to annotate a function.
30 |
31 | eg.
32 |
33 | ```clojure
34 | (ann-form #(+ 1 %) [Number -> Number])
35 | ```
36 |
37 | ### Everything is type checked, but core.typed can ignore certain expressions
38 |
39 | core.typed is early in development and there are Clojure idioms it cannot
40 | currently type check. Wrap top-level expressions in `clojure.core.typed/tc-ignore`
41 | to ignore them.
42 |
43 | Suggestion: If porting a namespace to core.typed, initially use `tc-ignore` liberally to ignore problematic
44 | code while determining the types for expressions. Once most vars are annotated, revisit
45 | these sites to determine the issue.
46 |
47 | ## Debugging
48 |
49 | ### `print-env` is your friend
50 |
51 | `clojure.core.typed/print-env` takes a debug string and prints the local type environment at the current expression.
52 |
53 | ### Use `cf` to experiment at the REPL
54 |
55 | `clojure.core.typed/cf` takes an expression and optionally an expected type and type checks the expression,
56 | returning its inferred type.
57 |
58 | eg.
59 |
60 | ```clojure
61 | clojure.core.typed=> (cf (fn [a]
62 | {:pre [(number? a)]}
63 | (inc a)))
64 | [(Fn [Any -> java.lang.Number]) {:then tt, :else ff}]
65 | ```
66 |
67 | If `cf` returns a vector of results, the first element is the static type.
68 |
69 | ### Use `ann-form` to ensure expressions are particular types
70 |
71 | `clojure.core.typed/ann-form` can be used as a kind of static `assert`.
72 |
73 | ```clojure
74 | clojure.core.typed=> (cf (let [a (+ 1 2)
75 | _ (ann-form a clojure.lang.Symbol)]
76 | a))
77 | #
79 | ```
80 |
81 | ### core.typed understands assertions and conditionals
82 |
83 | Normal "untyped" Clojure code often use type predicates combined with assertions or conditionals to direct control flow.
84 | core.typed uses them to gain type information about the current environment.
85 |
86 | ```clojure
87 | (let [a (ann-form 1 Number)
88 | _ (print-env "before assert")
89 | _ (assert (integer? a))
90 | _ (print-env "after assert")])
91 | ; "before assert"{:env {a java.lang.Number},
92 | ; :props ()}
93 | ; "after assert"{:env {_28338 nil, _ nil, a clojure.core.typed/AnyInteger},
94 | ; :props ((is clojure.core.typed/AnyInteger a) (when (! (U false nil) _) ff) (when (! (U false nil) _) ff) (when (! (U false nil) _28338) ff))}
95 | ```
96 |
97 | The `:env` map is maps local bindings to their current types.
98 | `:props` is a list of propositions currently in scope (can usually be ignored, mostly useful for internal debugging purposes).
99 |
100 | Notice the local binding `a` has a more accurate type after the `assert` expression.
101 |
102 | Note: core.typed operates on a hygienic AST, so shadowed bindings will have gensymed names.
103 |
104 | ## Typing core constructs
105 |
106 | ### core.typed understands datatype definitions
107 |
108 | Use `clojure.core.typed/ann-datatype` to give a datatype an expected type.
109 |
110 | ### Use `defprotocol>` instead of `defprotocol`
111 |
112 | core.typed currently cannot understand protocol definitions. Simply replace references to `defprotocol`
113 | with `clojure.core.typed/defprotocol>`
114 |
115 | ### core.typed understands simple multimethods
116 |
117 | core.typed can infer accurate types for multimethods that dispatch on simple things like keywords or `class`.
118 | Just assign an expected type to the multimethod's var with `ann` and core.typed will use it to infer accurate
119 | types in each `defmethod`.
120 |
121 | If in doubt whether a multimethod is being inferred properly, use the debugging techniques to double check.
122 | core.typed may not throw an exception if the dispatch is too complex to type check currently.
123 |
124 | ### Macros & Macro Definitions
125 |
126 | Macro definitions are ignored. The type checker operates on the macroexpanded form from
127 | the Compiler's analysis phase.
128 |
129 | ## Type Syntax
130 |
131 | ### Types use the current global scope of the namespace
132 |
133 | Simply adding an `(:import ...)` to the `ns` declaration as usual in Clojure brings the class name into scope.
134 | Otherwise, refers to classes via their fully qualified name.
135 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/rationale.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Rationale"
3 | layout: article
4 | ---
5 |
6 | Static typing has well known benefits. For example, statically typed languages catch many common
7 | programming errors at the earliest time possible: compile time.
8 | Types also serve as an excellent form of (machine checkable) documentation that
9 | almost always augment existing hand-written documentation.
10 |
11 | Languages without static type checking (dynamically typed) bring other benefits.
12 | Without the strict rigidity of mandatory static typing, they can provide more flexible and forgiving
13 | idioms that can help in rapid prototyping.
14 | Often the benefits of static type checking are desired as the program grows.
15 |
16 | This work adds static type checking (and some of its benefits) to Clojure, a dynamically typed language,
17 | while still preserving idioms that characterise the language.
18 | It allows static and dynamically typed code to be mixed so the programmer can use whichever
19 | is more appropriate.
20 |
21 | (For a detailed treatment, see my Honours Dissertation, [A Practical Optional Type System for Clojure](https://github.com/downloads/frenchy64/papers/ambrose-honours.pdf))
22 |
23 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/start/annotations.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Annotations"
3 | layout: article
4 | ---
5 |
6 | core.typed requires a moderate amount of assistance from the user to help infer types.
7 |
8 | There are two main things that need annotating:
9 |
10 | 1. All vars must be annotated
11 | 2. All function parameters must be annotated, or default to `Any`.
12 |
13 | From the provided annotations, core.typed uses local type inference to infer
14 | the types for local bindings, interop calls, and other expressions, mostly
15 | without further assistance.
16 |
17 | ## Vars
18 |
19 | When core.typed finds a var reference, `def`, `binding`, or some other var-related construct
20 | that relys on the derefereced value of a var, it requires an expected type.
21 |
22 | ```clojure
23 | clojure.core.typed=> (declare abc)
24 | #'clojure.core.typed/abc
25 | clojure.core.typed=> (cf abc)
26 | #
28 | ```
29 |
30 | ### Vars in current namespace
31 |
32 | Use `clojure.core.typed/ann` to associate a static type with a var.
33 |
34 | ```clojure
35 | clojure.core.typed=> (cf (ann abc Number))
36 | [clojure.core.typed/abc java.lang.Number]
37 | clojure.core.typed=> (cf (def abc 1))
38 | clojure.lang.Var
39 | clojure.core.typed=> (cf abc)
40 | java.lang.Number
41 | ```
42 |
43 | `ann` qualifies the var in the current namespace if unqualified.
44 |
45 | ### Vars in other namespaces
46 |
47 | Sometimes vars from other namespaces need annotation. Just qualify the var as you
48 | would in the current namespace (aliases are recognised) to associate it with a static type.
49 |
50 | ```clojure
51 | clojure.core.typed=> (cf clojure.core/*compile-path*)
52 | #
54 | clojure.core.typed=> (cf (ann clojure.core/*compile-path* String))
55 | [clojure.core/*compile-path* java.lang.String]
56 | clojure.core.typed=> (cf clojure.core/*compile-path*)
57 | java.lang.String
58 | ```
59 |
60 | ### Unchecked Vars
61 |
62 | We can instruct core.typed to ignore certain var definitions by adding `:nocheck` metadata
63 | to `ann` forms.
64 |
65 | ```clojure
66 | (ns typed.nocheck
67 | (:require [clojure.core.typed :refer [ann-nocheck ann check-ns]]))
68 |
69 | (ann ^:nocheck foo [Number -> Number])
70 | (defn foo [a]
71 | 'a)
72 |
73 | (ann bar [Number -> Number])
74 | (defn bar [b]
75 | (+ 2 (foo b)))
76 | ```
77 |
78 | ### Var Warnings
79 |
80 | After type checking has been performed, core.typed warns about vars that have been assigned types
81 | but have no corresponding checked `def` form. The `def` must at least make a binding,
82 | so it would be a warning if the var was only `declare`d.
83 |
84 | ```clojure
85 | (ns clojure.core.typed.test.nocheck
86 | (:require [clojure.core.typed :refer [ann-nocheck ann check-ns]]))
87 |
88 | (ann ^:nocheck foo [Number -> Number])
89 | (defn foo [a]
90 | 'a)
91 |
92 | (ann bar [Number -> Number])
93 | (defn bar [b]
94 | (+ 2 (foo b)))
95 |
96 | ;(check-ns)
97 | ; ...
98 | ; WARNING: Var clojure.core.typed.test.var-usage/foo used without checking definition
99 | ;=> nil
100 | ```
101 |
102 | ## Functions
103 |
104 | There are several ways to annotate a function type.
105 |
106 | ### Partial annotation with `fn>`
107 |
108 | To annotate just the arguments of a `fn`, use the `fn>` wrapper. It is exactly like `fn`,
109 | except each argument is wrapped in a vector which includes its static type.
110 |
111 | ```clojure
112 | clojure.core.typed=> (cf (fn> [[a :- Number]] (+ a 1)))
113 | [(Fn [java.lang.Number -> java.lang.Number]) {:then tt, :else ff}]
114 | ```
115 |
116 | All the usual destructuring is supported.
117 |
118 | ```clojure
119 | clojure.core.typed=> (cf (fn> [[{:keys [a b c]} :- '{:a Number :b Long :c Double}]]
120 | [a b c]))
121 | [(Fn ['{:a java.lang.Number, :b java.lang.Long, :c java.lang.Double} -> '[java.lang.Number java.lang.Long java.lang.Double]])
122 | {:then tt, :else ff}]
123 | ```
124 |
125 | ### Full annotation with `ann-form`
126 |
127 | Often it is more useful to provide a full function type as a `fn`'s annotation. This
128 | especially works well with Clojure's anonymous function syntax.
129 |
130 | ```clojure
131 | clojure.core.typed=> (cf (ann-form #(inc %)
132 | [Number -> Number]))
133 | (Fn [java.lang.Number -> java.lang.Number])
134 | ```
135 |
136 | This way, you can also assign anonymous functions ordered intersection function types.
137 |
138 | ```clojure
139 | clojure.core.typed=> (cf (fn [a]
140 | (cond
141 | (number? a) 1
142 | (symbol? a) 'a))
143 | (Fn [Number -> Number]
144 | [Symbol -> Symbol]))
145 | (Fn [java.lang.Number -> java.lang.Number]
146 | [clojure.lang.Symbol -> clojure.lang.Symbol])
147 | ```
148 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/start/introduction_and_motivation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Getting Started: Introduction and Motivation"
3 | layout: article
4 | ---
5 |
6 | core.typed is an optional type system for Clojure. If you are interesting in how core.typed
7 | can help you verify your programs as correct, read on.
8 |
9 | ## "I use Clojure to avoid types!"
10 |
11 | Many programmers use Clojure as relief from popular typed languages such as Java or C#.
12 | Java's verbosity and redundant type annotations help make the move to Clojure feel liberating
13 | and enjoyable: so why go back to types?
14 |
15 | core.typed has a different story to tell:
16 | - type checking is optional
17 | - only use the type system where you need it
18 | - local type inference is used to infer local bindings
19 | - locals rarely need type annotations
20 | - it can type check (mostly) normal Clojure code
21 | - the Clojure you know and love!
22 |
23 | If Java has driven you away from types, core.typed could be pleasant surprise.
24 | It might even become one of your go-to tools for code verification in Clojure.
25 |
26 | ## What are types?
27 |
28 | This is a good question, especially in the context of a dynamically-typed (DT) language
29 | where we don't have "types".
30 |
31 | We use the term "type" to mean static type and "tag" for runtime tags.
32 | Types only exist at compile time and are used by the static type system to model runtime
33 | invariants and properties.
34 |
35 | Thinking of compile-time and runtime as distinct phases in terms of types often helps.
36 | The type system uses types to reason about the runtime behaviour of code, which can
37 | also include tag invariants.
38 |
39 | There are no types in Clojure, only tags. We can also say that Clojure has exactly one type: `Any` (subtype of all types).
40 | The closest equivalent to types we have
41 | are ad-hoc comments or doc-strings which describe the input/output behaviour
42 | of functions.
43 |
44 | For example, the `number?` predicate returns true if its (runtime) argument
45 | has a tag that is a subtype of `java.lang.Number`, otherwise false. In core.typed
46 | we use a type to model these invariants.
47 | The tag of `number?` might be `IFn`, while its type is `[Any -> boolean :filters {:then (is Number 0) :else (! Number 0)}]`.
48 |
49 | In summary:
50 | - types only exist at compile time
51 | - tags only exist at runtime
52 |
53 | ## Why types?
54 |
55 | Why use types at all? A static type checker gives earlier and often clearer type errors.
56 |
57 | For example, you might observe:
58 | - fewer "Boolean is not an ISeq" errors without line numbers in production
59 | - more "Cannot pass Boolean to second argument of map" with line numbers at compile time in development.
60 |
61 | Types, when coupled with an appropriate doc-string, are excellent machine checkable documentation.
62 | They never go out of date, and are often invaluable as a quick reminder of what a function does.
63 |
64 | Types are useful when a program grows, especially when there are multiple contributors.
65 | If a contribution passes the type system, we know that it is type correct (type errors are amongst
66 | the most common user errors in programming).
67 |
68 | ## Great, types are the answer!
69 |
70 | Not quite. Types can help verify that a program is basically correct, but not if it does the right thing.
71 | Use as many verification techniques as you can: core.typed works great coupled with unit testing or
72 | generative testing.
73 |
74 | Clojure simply is not built with static typing in mind. It is impractical to expect core.typed alone
75 | to prevent as many user errors as say Haskell's type system: core.typed either needs to choose some
76 | subset of Clojure optimised for user error prevention, or attempt to check all Clojure code
77 | while making some compromises (it does the latter).
78 |
79 | This might seem discouraging, but in practice core.typed will catch all type errors in your code.
80 | The problem is some Clojure idioms are so flexible it is often impossible to distinguish
81 | between intended and unintended usage.
82 |
83 | A small example: `map` accepts either `nil` or a `Seqable` as a second argument. It is perfectly
84 | valid to provide an argument that is always `nil`, but it's probably not what the user intended.
85 |
86 | So for best results, couple core.typed with all the usual testing/verification techniques.
87 |
88 | ## Before we begin
89 |
90 | There are some details to keep in mind when using core.typed before you jump in to use it.
91 |
92 | Read the [Quick Guide](../Quick Guide.html), and keep a copy handy when you follow along the rest of the tutorial.
93 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/types.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "core.typed Types"
3 | layout: article
4 | ---
5 |
6 | ## Common types
7 |
8 | ### Any and Nothing
9 |
10 | Every type is a subtype to `Any`, written `x <: Any` for all types `x`. Equivalently, any place that `Any` is valid,
11 | any other type can be used. `Any` is also known as the "Top" type.
12 |
13 | Conversely, there are no types that are subtypes to `Nothing`. However for all types `x`
14 | it holds that `Nothing <: x`. Put another way, `Nothing` is a valid type to give use
15 | in positions expecting any other type. In practice, `Nothing` is not as useful as `Any`,
16 | and is usually used internally to detect dead code and other code properties.
17 |
18 | ### Functions
19 |
20 | core.typed has a special function type, which is an *ordered intersection* of arities.
21 | It allows us to specify fine grained function invariants.
22 |
23 | Starting simply,
24 |
25 | ```clojure
26 | (Fn [Any -> Any])
27 | ```
28 |
29 | is a function taking one argument of type `Any`. `[Any -> Any]`
30 | is an equivalent shorthand for single-arity function types.
31 |
32 | #### Multiple arities
33 |
34 | We can specify multiple arities:
35 |
36 | ```clojure
37 | (Fn [Any -> Any]
38 | [Any Any -> Any])
39 | ```
40 |
41 | Here we can call a function of this type with either one or two arguments.
42 | In this case, the ordered intersection type acts as a simple overloading on arity.
43 |
44 | Finer invariants can be expressed by specifying multiple signatures of the same arity:
45 |
46 | ```clojure
47 | (Fn [Symbol -> Number]
48 | [Number -> Symbol])
49 | ```
50 |
51 | This function returns a `Number` if passed a `Symbol`, and returns a `Symbol` if passed a `Number`.
52 |
53 | The exact return type for a function application expression involving multiple arities
54 | is chosen by matching the actual types provided with each arities, top-to-bottom
55 | (this explains why our functions are "ordered" intersections).
56 | In this case, each arity is disjoint because no combination of arguments could
57 | potentially trigger both arities. More concretely, there is no type that is both
58 | a `Symbol` and a `Number`, so at most one arity triggers for any given arguments.
59 |
60 | Overlapping arities hints at the power of ordered intersections.
61 |
62 | ```clojure
63 | (Fn [Long -> Symbol]
64 | [Number -> Keyword])
65 | ```
66 |
67 | This type always returns a `Symbol` for `Long` arguments.
68 |
69 | Beware, swapping the arities produces different results!
70 |
71 | ```clojure
72 | (Fn [Number -> Keyword]
73 | [Long -> Symbol])
74 | ```
75 |
76 | The first arity always "wins" because `Number` is strictly more general than `Long`.
77 | Arities are usually ordered from more-specific parameters to less-specific parameters.
78 |
79 | What about arities that have partially overlapping parameters?
80 | Consider:
81 |
82 | ```clojure
83 | (Fn [Long Any -> Keyword]
84 | [Any Number -> Symbol])
85 | ```
86 |
87 | Calling with `Long` `Long` arguments gives `Keyword`, and `Number` `Long` gives `Symbol`.
88 |
89 | Flipping the arities gives different results:
90 |
91 | ```clojure
92 | (Fn [Any Number -> Symbol]
93 | [Long Any -> Keyword])
94 | ```
95 |
96 | Now `Long` `Long` gives `Symbol`, and `Number` `Long` gives `Symbol`.
97 | Partially overlapping arities can be tricky and can unexpectedly trigger earlier arities,
98 | so care must be taken here.
99 |
100 | Finally, a common idiom is to provide a base arity, which has arguments at least as general
101 | as the ones above it.
102 |
103 | For example, we might want our function of type `(Fn [Long -> Symbol] [Number -> Keyword])` to handle the case where
104 | the argument is *either* a `Long` or a `Number`.
105 | We can express this by using a union (to express a least-upper-bound of `Long` and `Number`).
106 |
107 | ```clojure
108 | (Fn [Long -> Symbol]
109 | [Number -> Keyword]
110 | [(U Long Number) -> (U Symbol Keyword)])
111 | ```
112 |
113 | Note the result type is sufficiently general to show the result type is either a `Symbol` or `Keyword`.
114 |
115 | #### Rest parameters
116 |
117 | Rest parameters are specified using a `*`.
118 |
119 | eg.
120 |
121 | ```clojure
122 | (Fn [Any Number * -> Any])
123 | ```
124 |
125 | is a function taking at least one parameter, and any number of parameters after it
126 | of type `Number`.
127 |
128 | #### Keyword parameters
129 |
130 | Keyword parameters are specified using `&` after the fixed domain.
131 |
132 | eg.
133 |
134 | ```clojure
135 | (Fn [Any & {:a Number} -> Any])
136 | ```
137 |
138 | is a function that takes a fixed parameter and an optional keyword argument `:a`, of
139 | type `Number`.
140 |
141 | We can also specify mandatory keyword parameters:
142 |
143 | ```clojure
144 | (Fn [Any & {} :mandatory {:a Number} -> Any])
145 | ```
146 |
147 | is the same function, except the keyword argumetn `:a` now must be present when calling.
148 |
149 | We can express finer grained invariants by combining keyword types and ordered
150 | function intersection types:
151 |
152 | ```clojure
153 | (Fn [Any & {} :mandatory {:a Number :b Number} -> Number]
154 | [Any & {:a Number :b Number} -> Any])
155 | ```
156 |
157 | This function type returns a `Number` if provided both `:a` and `:b` parameters,
158 | otherwise returns `Any` if some other combination of `:a` and `:b` is provided.
159 |
160 | ### Java Classes
161 |
162 | core.typed reuses Java and clojure.lang.* classes. The normal scoping rules apply in types,
163 | e.g., use `:import` to bring classes into scope.
164 |
165 | Note: `java.lang.*` classes are implicitly in scope in Clojure namespaces.
166 |
167 | ### Numbers, Strings and other Java types
168 |
169 | core.typed follows the normal rules that apply to Clojure code.
170 |
171 | ```clojure
172 | clojure.core.typed=> (cf 1 Long)
173 | java.lang.Long
174 | clojure.core.typed=> (cf 1.1 Double)
175 | java.lang.Double
176 | clojure.core.typed=> (cf "a" String)
177 | java.lang.String
178 | clojure.core.typed=> (cf \a Character)
179 | java.lang.Character
180 | ```
181 |
182 | ### Symbols and Keywords
183 |
184 | Symbols and Keywords are instances of their corresponding clojure.lang classes.
185 |
186 | ```clojure
187 | clojure.core.typed=> (cf 'a clojure.lang.Symbol)
188 | clojure.lang.Symbol
189 | clojure.core.typed=> (cf :a clojure.lang.Keyword)
190 | clojure.lang.Keyword
191 | ```
192 |
193 | ### Seqables
194 |
195 | Seqables extend `(Seqable a)`, which is covariant in its argument.
196 | Types that extend `(Seqable a`) are capable of creating a sequence
197 | (aka. an `(ISeq a)`) representation of itself via functions like `seq`.
198 |
199 | ```clojure
200 | clojure.core.typed=> (cf {'a 2 'b 3} (Seqable (IMapEntry Symbol Number)))
201 | (clojure.lang.Seqable (clojure.lang.IMapEntry clojure.lang.Symbol java.lang.Number))
202 | clojure.core.typed=> (cf [1 2 3] (Seqable Number))
203 | (clojure.lang.Seqable java.lang.Number)
204 | clojure.core.typed=> (cf '#{a b c} (Seqable Symbol))
205 | (clojure.lang.Seqable clojure.lang.Symbol)
206 | ```
207 |
208 | ### Seqs
209 |
210 | Seqs extend `(ISeq a)`, which is covariant in its argument.
211 |
212 | ```clojure
213 | clojure.core.typed=> (cf (seq [1 2]) (ISeq Number))
214 | (clojure.lang.ISeq java.lang.Number)
215 | ```
216 |
217 | ### Lists
218 |
219 | Lists extend `(IPersistentList a)`, which is covariant in its argument.
220 |
221 | ```clojure
222 | clojure.core.typed=> (cf '(1 2) (IPersistentList Number))
223 | (clojure.lang.IPersistentList java.lang.Number)
224 | ```
225 |
226 | ### Vectors
227 |
228 | Vectors extend `(IPersistentVector a)`, which is covariant in its argument.
229 |
230 | ```clojure
231 | clojure.core.typed=> (cf [1 2] (IPersistentVector Number))
232 | (clojure.lang.IPersistentVector java.lang.Number)
233 | ```
234 |
235 | ### Maps
236 |
237 | Maps extend `(IPersistentMap a b)`, which is covariant in both its arguments.
238 |
239 | ```clojure
240 | clojure.core.typed=> (cf {'a 1 'b 3} (IPersistentMap Symbol Long))
241 | (clojure.lang.IPersistentMap clojure.lang.Symbol java.lang.Long)
242 | ```
243 |
244 | ### Sets
245 |
246 | Sets extend `(IPersistentSet a)`, which is covariant in its argument.
247 |
248 | ```clojure
249 | clojure.core.typed=> (cf #{1 2 3} (IPersistentSet Number))
250 | (clojure.lang.IPersistentSet java.lang.Number)
251 | ```
252 |
253 | ### Atoms
254 |
255 | An Atom of type `(Atom w r)` can accept values of type `w` and provide values of type `r`.
256 | It is contravariant in `w` and covariant in `r`.
257 |
258 | Usually `w` and `r` are identical, so an alias `(clojure.core.typed/Atom1 wr)` is provided,
259 | which is equivalent to `(Atom wr wr)`.
260 |
261 | ```clojure
262 | clojure.core.typed=> (cf (atom {}) (Atom1 (IPersistentMap Symbol Number)))
263 | (clojure.core.typed/Atom1 (clojure.lang.IPersistentMap clojure.lang.Symbol java.lang.Number))
264 | ```
265 |
266 | ## Type Grammar
267 |
268 | A rough grammar for core.typed types.
269 |
270 | ```
271 | Type := nil
272 | | true
273 | | false
274 | | (U Type*)
275 | | (I Type+)
276 | | FunctionIntersection
277 | | (Value CONSTANT-VALUE)
278 | | (Rec [Symbol] Type)
279 | | (All [Symbol+] Type)
280 | | (All [Symbol* Symbol ...] Type)
281 | | (HMap {Keyword Type*}) ;eg (HMap {:a (Value 1), :b nil})
282 | | '{Keyword Type*} ;eg '{:a (Value 1), :b nil}
283 | | (Vector* Type*)
284 | | '[Type*]
285 | | (Seq* Type*)
286 | | (List* Type*)
287 | | Symbol ;class/protocol/free resolvable in context
288 |
289 | FunctionIntersection := ArityType
290 | | (Fn ArityType+)
291 |
292 | ArityType := [FixedArgs -> Type]
293 | | [FixedArgs RestArgs * -> Type]
294 | | [FixedArgs DottedType ... Symbol -> Type]
295 |
296 | FixedArgs := Type*
297 | RestArgs := Type
298 | DottedType := Type
299 | ```
300 |
301 | ## Types
302 |
303 | ### Value shorthands
304 |
305 | `nil`, `true` and `false` resolve to the respective singleton types for those values
306 |
307 | ### Intersections
308 |
309 | `(I Type+)` creates an intersection of types.
310 |
311 |
312 | ### Unions
313 |
314 | `(U Type*)` creates a union of types.
315 |
316 | ### Functions
317 |
318 | A function type is an ordered intersection of arity types.
319 |
320 | There is a vector sugar for functions of one arity.
321 |
322 | ### Heterogeneous Maps
323 |
324 | *Warning*: Heterogeneous maps are alpha and their design is subject to change.
325 |
326 | A heterogeneous map type represents a map that has at least a particular set of keyword keys.
327 |
328 | ```clojure
329 | clojure.core.typed=> (cf {:a 1})
330 | [(HMap {:a (Value 1)}) {:then tt, :else ff}]
331 | ```
332 | This type can also be written `'{:a (Value 1)}`.
333 |
334 | Lookups of known keys infer accurate types.
335 |
336 | ```clojure
337 | clojure.core.typed=> (cf (-> {:a 1} :a))
338 | (Value 1)
339 | ```
340 |
341 | Currently, they are limited (but still quite useful):
342 | - the presence of keys is recorded, but not their absence
343 | - only keyword value keys are allowed.
344 |
345 | These rules have several implications.
346 |
347 | #### Absent keys
348 |
349 | Looking up keys that are not recorded as present give inaccurate types
350 |
351 | ```clojure
352 | clojure.core.typed=> (cf (-> {:a 1} :b))
353 | Any
354 | ```
355 |
356 | #### Non-keyword keys
357 |
358 | Literal maps without keyword keys are inferred as `APersistentMap`.
359 |
360 | ```clojure
361 | clojure.core.typed=> (cf {(inc 1) 1})
362 | [(clojure.lang.APersistentMap clojure.core.typed/AnyInteger (Value 1)) {:then tt, :else ff}]
363 | ```
364 |
365 |
366 |
367 | Optional keys can be defined either by constructing a union of map types, or by passing
368 | the `HMap` type constructor an `:optional` keyword argument with a map of optional keys.
369 |
370 | ### Heterogeneous Vectors
371 |
372 | `(Vector* (Value 1) (Value 2))` is a IPersistentVector of length 2, essentially
373 | representing the value `[1 2]`. The type `'[(Value 1) (Value 2)]` is identical.
374 |
375 | ### Polymorphism
376 |
377 | The binding form `All` introduces a number of free variables inside a scope.
378 |
379 | Optionally scopes a dotted variable by adding `...` after the last symbol in the binder.
380 |
381 | eg. The identity function: `(All [x] [x -> x])`
382 | eg. Introducing dotted variables: `(All [x y ...] [x y ... y -> x])
383 |
384 | ### Recursive Types
385 |
386 | `Rec` introduces a recursive type. It takes a vector of one symbol and a type.
387 | The symbol is scoped to represent the entire type in the type argument.
388 |
389 | ```clojure
390 | ; Type for {:op :if
391 | ; :test {:op :var, :var #'A}
392 | ; :then {:op :nil}
393 | ; :else {:op :false}}
394 | (Rec [x]
395 | (U (HMap {:op (Value :if)
396 | :test x
397 | :then x
398 | :else x})
399 | (HMap {:op (Value :var)
400 | :var clojure.lang.Var})
401 | (HMap {:op (Value :nil)})
402 | (HMap {:op (Value :false)})))))
403 | ```
404 |
--------------------------------------------------------------------------------
/articles/ecosystem/core_typed/user_documentation.md:
--------------------------------------------------------------------------------
1 | # Usage
2 |
3 | ## Type Aliases
4 |
5 | `clojure.core.typed/def-alias` defines a type alias.
6 |
7 | ```clojure
8 | (def-alias Term (I IUnifyTerms
9 | IUnifyWithNil
10 | IUnifyWithObject
11 | IUnifyWithLVar
12 | IUnifyWithSequential
13 | IUnifyWithMap
14 | IUnifyWithSet
15 | IReifyTerm
16 | IWalkTerm
17 | IOccursCheckTerm
18 | IBuildTerm))
19 | ```
20 |
21 | ## Primitive Java Arrays
22 |
23 | "Typed" arrays can be created with `into-array>`, which has a 2 and 3 arity version.
24 |
25 | The correspondence between core.typed types and Java types is subtle here. Usually
26 | `into-array>` accepts a core.typed type as its first argument, followed by a collection (as `clojure.core/into-array`).
27 |
28 | ```clojure
29 | ;; `int` is the primitive int in Java. This creates a primitive array.
30 | (class (into-array> int [1]))
31 | ;=> [I
32 |
33 | ;; This is a Number array with nullable elements.
34 | (class (into-array> (U nil Number) [1]))
35 | ;=> [Ljava.lang.Number;
36 |
37 | ;; This is a Number array with non-nullable elements.
38 | ;; Notice this generates the same type as before as Java does not distinguish
39 | ;; non-/nullable arrays. core.typed statically disallows nil to be added
40 | ;; as an element from any Clojure it checks.
41 | (class (into-array> Number [1]))
42 | ;=> [Ljava.lang.Number;
43 |
44 | ;; An array of nullable primitive ints does not make sense in Java,
45 | ;; so it is generalised to an array of Objects.
46 | (class (into-array> (U nil int) [1]))
47 | ;=> [Ljava.lang.Object;
48 |
49 | ;; Unions are often generalised to Object
50 | (class (into-array> (U clojure.lang.Symbol Number) [1]))
51 | ;=> [Ljava.lang.Object;
52 | ```
53 |
54 | When more control is needed of the Java type, the 3 arity version of `into-array>` accepts
55 | the Java type (in core.typed syntax) as first argument, followed by the Clojure type, and the collection.
56 |
57 | ```clojure
58 | ;; Generalising to Number instead of Object.
59 | (class (into-array> Number (U Integer Number) [1]))
60 | ;=> [Ljava.lang.Number;
61 | ```
62 |
63 | The Clojure element type should be a subtype to the Java element type.
64 |
65 | ## Declarations
66 |
67 | `clojure.core.typed/declare-types`, `clojure.core.typed/declare-names` and `clojure.core.typed/declare-protocols` are similar
68 | to `declare` in that they allow you to use types before they are defined.
69 |
70 | ```clojure
71 | (declare-datatypes Substitutions)
72 | (declare-protocols LVar)
73 | (declare-names MyAlias)
74 | ```
75 |
76 | ## Checking typed namespaces
77 |
78 | `clojure.core.typed/check-ns` checks the namespace that its symbol argument represents.
79 |
80 | ```clojure
81 | (check-ns 'my.ns)
82 | ```
83 |
84 | ## Debugging
85 |
86 | `clojure.core.typed/print-env` prints the current environment.
87 |
88 | ```clojure
89 | (let [a 1]
90 | (print-env "Env:")
91 | a)
92 | ; Prints: "Env:" {:env {a (Value 1)}, ....}
93 | ```
94 |
95 | `clojure.core.typed/cf` (pronounced "check form") can be used at the REPL to return the type of a form.
96 |
97 | ```clojure
98 | (cf 1)
99 | ;=> [(Value 1) {:then [top-filter], :else [bot-filter]} empty-object]
100 | ```
101 |
102 | ## Macros & Macro Definitions
103 |
104 | Macro definitions are ignored. The type checker operates on the macroexpanded form from
105 | the Compiler's analysis phase.
106 |
107 |
--------------------------------------------------------------------------------
/articles/ecosystem/data_processing.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Data Processing (Overview)"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * An overview of why Clojure is an excellent choice for data processing
9 | * Popular tools and libraries in the area
10 |
11 | This work is licensed under a Creative Commons
13 | Attribution 3.0 Unported License (including images &
14 | stylesheets). The source is available [on
15 | Github](https://github.com/clojuredocs/guides).
16 |
17 |
18 |
19 | ## What Version of Clojure Does This Guide Cover?
20 |
21 | This guide covers Clojure 1.4.
22 |
23 |
24 |
25 | ## Todo
26 |
27 | todo
28 |
29 |
30 |
31 | ## Contributors
32 |
33 | todo
34 |
--------------------------------------------------------------------------------
/articles/ecosystem/generating_documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Generating Documentation"
3 | layout: article
4 | ---
5 |
6 | This guide notes some commonly-used tools for generating project
7 | documentation.
8 |
9 | This work is licensed under a Creative Commons
11 | Attribution 3.0 Unported License (including images &
12 | stylesheets). The source is available [on
13 | Github](https://github.com/clojuredocs/guides).
14 |
15 |
16 |
17 | ## What Version of Clojure Does This Guide Cover?
18 |
19 | This guide covers Clojure 1.4.
20 |
21 |
22 |
23 | ## Overview
24 |
25 | Projects commonly (hopefully?) have at least two types of
26 | documentation:
27 |
28 | * standalone
29 | [markdown](http://en.wikipedia.org/wiki/Markdown)-formatted docs
30 | in the project's doc directory
31 | * docstrings
32 |
33 | There are a number of tools for generating handsome API docs from
34 | docstrings and other project metadata.
35 |
36 |
37 | ## Codox
38 |
39 | If you'd like to generate nice-looking html API docs for your library,
40 | use [codox](https://github.com/weavejester/codox). Usage instructions
41 | are in the codox readme. Running codox (it's a lein plug-in and is run
42 | via `lein codox` in your project) will create a "doc" subdirectory
43 | containing the resulting html.
44 |
45 |
46 |
47 | ## Marginalia
48 |
49 | If you'd like to render API docs side-by-side with the source code
50 | it's documenting, use [the marginalia lein
51 | plug-in](https://github.com/fogus/lein-marginalia). Usage instructions
52 | are in the readme.
53 |
54 |
55 |
56 | ## Cadastre
57 |
58 | If you'd like to generate copious raw data from a project (which
59 | includes docstrings as well as other metadata), have a look at
60 | [cadastre](https://github.com/dakrone/cadastre).
61 |
--------------------------------------------------------------------------------
/articles/ecosystem/java_jdbc/connection_pooling.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Connection Pooling"
3 | layout: article
4 | ---
5 |
6 | This page has been moved to [Reusing Connections](reusing_connections.html).
7 |
--------------------------------------------------------------------------------
/articles/ecosystem/java_jdbc/home.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using java.jdbc"
3 | layout: article
4 | ---
5 |
6 | This guide is intended to help you use Clojure's JDBC wrapper, the `java.jdbc`
7 | Contrib library.
8 |
9 | ## Contents
10 |
11 | * [Overview][overview]
12 | * [Using SQL][using-sql]
13 | * [Using DDL][using-ddl]
14 | * [Reusing Connections][reusing-connections]
15 |
16 | ## Overview
17 |
18 | `java.jdbc` is intended to be a low-level Clojure wrapper around various Java
19 | JDBC drivers and supports a wide range of databases. The [`java.jdbc` source is
20 | on GitHub][github] and there is a dedicated [java.jdbc mailing
21 | list][mailing-list]. The detailed [`java.jdbc` reference][reference] is
22 | automatically generated from the `java.jdbc` source.
23 |
24 | Generally, when using `java.jdbc`, you will set up a data source as a "database
25 | spec" and pass that to the various CRUD (create, read, update, delete)
26 | functions that `java.jdbc` provides. These operations are detailed within the
27 | [Using SQL][using-sql] page, but a quick overview is provided by the
28 | walkthrough below.
29 |
30 | By default, each operation opens a connection and executes the SQL inside a
31 | transaction. You can also run multiple operations against the same connection,
32 | either within a transaction or via connection pooling, or just with a shared
33 | connection. You can read more about reusing connections on the [Reusing
34 | Connections][reusing-connections] page.
35 |
36 | ## Higher-level DSL and migration libraries
37 |
38 | If you need more abstraction than the `java.jdbc` wrapper provides, you may want
39 | to consider using a library that provides a DSL. All of the following libraries
40 | are built on top of `java.jdbc` and provide such abstraction:
41 |
42 | * [HoneySQL](https://github.com/jkk/honeysql)
43 | * [SQLingvo](https://github.com/r0man/sqlingvo)
44 | * [Korma][korma]
45 | * [Walkable](https://github.com/walkable-server/walkable)
46 |
47 | In particular, [Korma][korma] goes beyond a SQL DSL to provide "entities" and
48 | "relationships" (in the style of classical Object-Relational Mappers, but
49 | without the pain).
50 |
51 | Another common need with SQL is for database migration libraries. Some of the
52 | more popular options are:
53 |
54 | * [Drift](https://github.com/macourtney/drift)
55 | * [Migratus](https://github.com/pjstadig/migratus)
56 | * [Ragtime](https://github.com/weavejester/ragtime)
57 |
58 | ## A brief `java.jdbc` walkthrough
59 |
60 | ### Setting up a data source
61 |
62 | A "database spec" is a Clojure map that specifies how to access the data
63 | source. Most commonly, you specify the database type, the database name,
64 | and the username and password. For example,
65 |
66 | ```clojure
67 | (def db-spec
68 | {:dbtype "mysql"
69 | :dbname "mydb"
70 | :user "myaccount"
71 | :password "secret"})
72 | ```
73 |
74 | See [**Database Support**](#database-support) below for a complete list of
75 | databases and drivers supported by `java.jdbc` out of the box.
76 |
77 | ### A "Hello World" Query
78 |
79 | Querying the database can be as simple as:
80 |
81 | ```clojure
82 | (ns dbexample
83 | (:require [clojure.java.jdbc :as jdbc]))
84 |
85 | (def db-spec ... ) ;; see above
86 |
87 | (jdbc/query db-spec ["SELECT 3*5 AS result"])
88 | => {:result 15}
89 | ```
90 |
91 | Of course, we will want to do more with our database than have it perform
92 | simple calculations. Once we can successfully connect to it, we will likely
93 | want to create tables and manipulate data.
94 |
95 | ### Creating tables
96 |
97 | `java.jdbc` provides `create-table-ddl` and `drop-table-ddl` to generate basic
98 | `CREATE TABLE` and `DROP TABLE` DDL strings. Anything beyond that can be
99 | constructed manually as a string.
100 |
101 | ```clojure
102 | (ns dbexample
103 | (:require [clojure.java.jdbc :as jdbc]))
104 |
105 | (def db-spec ... ) ;; see above
106 |
107 | (def fruit-table-ddl
108 | (jdbc/create-table-ddl :fruit
109 | [[:name "varchar(32)"]
110 | [:appearance "varchar(32)"]
111 | [:cost :int]
112 | [:grade :real]]))
113 | ```
114 |
115 | We can use the function `db-do-commands` to create our table and indexes in a
116 | single transaction:
117 |
118 | ```clojure
119 | (jdbc/db-do-commands db-spec
120 | [fruit-table-ddl
121 | "CREATE INDEX name_ix ON fruit ( name );"])
122 | ```
123 |
124 | For more details on DDL functionality within `java.jdbc`, see the [Using DDL and
125 | Metadata Guide][using-ddl].
126 |
127 | ### Querying the database
128 |
129 | The four basic CRUD operations `java.jdbc` provides are:
130 |
131 | ```clojure
132 | (jdbc/insert! db-spec :table {:col1 42 :col2 "123"}) ;; Create
133 | (jdbc/query db-spec ["SELECT * FROM table WHERE id = ?" 13]) ;; Read
134 | (jdbc/update! db-spec :table {:col1 77 :col2 "456"} ["id = ?" 13]) ;; Update
135 | (jdbc/delete! db-spec :table ["id = ?" 13]) ;; Delete
136 | ```
137 |
138 | The table name can be specified as a string or a keyword.
139 |
140 | `insert!` takes a single record in hash map form to insert. `insert!` can also
141 | take a vector of column names (as strings or keywords), followed by a vector of
142 | column values to insert into those respective columns, much like an `INSERT`
143 | statement in SQL. Entries in the map that have the value `nil` will cause
144 | `NULL` values to be inserted into the corresponding columns.
145 |
146 | If you wish to insert multiple rows (in hash map form) at once, you can use
147 | `insert-multi!`; however, `insert-multi!` will write a separate insertion
148 | statement for each row, so it is suggested you use the column-based form of
149 | `insert-multi!` over the row-based form. Passing multiple column values to
150 | `insert-multi!` will generate a single batched insertion statement and yield
151 | better performance.
152 |
153 | `query` allows us to run selection queries on the database. Since you provide
154 | the query string directly, you have as much flexibility as you like to perform
155 | complex queries.
156 |
157 | `update!` takes a map of columns to update, with their new values, and a SQL
158 | clause used to select which rows to update (prepended by `WHERE` in the
159 | generated SQL). As with `insert!`, `nil` values in the map cause the
160 | corresponding columns to be set to `NULL`.
161 |
162 | `delete!` takes a SQL clause used to select which rows to delete, similar to
163 | `update!`.
164 |
165 | By default, the table name and column names are converted to strings
166 | corresponding to the keyword names in the underlying SQL. We can control how we
167 | transform keywords into SQL names using an optional `:entities` argument which
168 | is described in more detail in the [Using SQL][using-sql] section.
169 |
170 | ### Dropping our tables
171 |
172 | To clean out the database from our example, we can generate a the command to
173 | drop the fruit table:
174 |
175 | ```clojure
176 | (def drop-fruit-table-ddl (jdbc/drop-table-ddl :fruit))
177 | ```
178 |
179 | Ensure you tear down your tables and indexes in the opposite order of creation:
180 |
181 | ```clojure
182 | (jdbc/db-do-commands db-spec
183 | ["DROP INDEX name_ix;"
184 | drop-fruit-table-ddl])
185 | ```
186 |
187 | These are all the commands we need to write a simple migration for our database!
188 |
189 | ## Database Support
190 |
191 | Out of the box, `java.jdbc` understands the following `:dbtype` values (with
192 | their default class names):
193 |
194 | * `"derby"` - `org.apache.derby.jdbc.EmbeddedDriver`
195 | * `"h2"` - `org.h2.Driver`
196 | * `"h2:mem"` - `org.h2.Driver`
197 | * `"hsqldb"` or `"hsql"` - `org.hsqldb.jdbcDriver`
198 | * `"jtds:sqlserver"` or `"jtds"` - `net.sourceforge.jtds.jdbc.Driver`
199 | * `"mysql"` - `com.mysql.jdbc.Driver`
200 | * `"oracle:oci"` - `oracle.jdbc.OracleDriver`
201 | * `"oracle:thin"` or `"oracle"` - `oracle.jdbc.OracleDriver`
202 | * `"postgresql"` or `"postgres"` - `org.postgresql.Driver`
203 | * `"pgsql"` - `com.impossibl.postgres.jdbc.PGDriver`
204 | * `"redshift"` - `com.amazon.redshift.jdbc.Driver`
205 | * `"sqlite"` - `org.sqlite.JDBC`
206 | * `"sqlserver"` - `"mssql"` - `com.microsoft.sqlserver.jdbc.SQLServerDriver`
207 |
208 | You must specify the appropriate JDBC driver dependency in your project -- these
209 | drivers are not included with `java.jdbc`.
210 |
211 | You can overide the default class name by specifying `:classname` as well as
212 | `:dbtype`.
213 |
214 | For databases that require a hostname or IP address, `java.jdbc` assumes
215 | `"127.0.0.1"` but that can be overidden with the `:host` option.
216 |
217 | For databases that require a port, `java.jdbc` has the following defaults,
218 | which can be overridden with the `:port` option:
219 |
220 | * Microsoft SQL Server - 1433
221 | * MySQL - 3306
222 | * Oracle - 1521
223 | * PostgreSQL - 5432
224 |
225 | Some databases require a different format for the "database spec". Here is an example
226 | that was required for an in-memory [H2 database](http://www.h2database.com) prior
227 | to `java.jdbc` release 0.7.6:
228 |
229 | ```clojure
230 | (def db-spec
231 | {:classname "org.h2.Driver"
232 | :subprotocol "h2:mem" ; the prefix `jdbc:` is added automatically
233 | :subname "demo;DB_CLOSE_DELAY=-1" ; `;DB_CLOSE_DELAY=-1` very important!!!
234 | ; http://www.h2database.com/html/features.html#in_memory_databases
235 | :user "sa" ; default "system admin" user
236 | :password "" ; default password => empty string
237 | })
238 | ```
239 |
240 | This is the most general form of database spec, that allows you to control each
241 | piece of the JDBC connection URL that would be created.
242 |
243 | Note: as of `java.jdbc` 0.7.6, in-memory H2 databases are supported directly
244 | via the simple spec form:
245 |
246 | ```clojure
247 | (def db-spec
248 | {:dbtype "h2:mem"
249 | :dbname "mydb"})
250 | ```
251 |
252 | For file-based databases, such as H2, Derby, SQLite etc, the `:dbname` will
253 | specify the filename:
254 |
255 | ```clojure
256 | (def db-spec
257 | {:dbtype "h2"
258 | :dbname "/path/to/my/database"})
259 | ```
260 |
261 | ## More detailed `java.jdbc` documentation
262 |
263 | * [Using SQL:][using-sql] a more detailed guide on using SQL with `java.jdbc`
264 | * [Using DDL:][using-ddl] how to create your tables using the `java.jdbc` DDL
265 | * [Reusing Connections:][reusing-connections] how to reuse your database
266 | connections
267 |
268 | [github]: https://github.com/clojure/java.jdbc/
269 | [mailing-list]: https://groups.google.com/forum/#!forum/clojure-java-jdbc
270 | [reference]: http://clojure.github.io/java.jdbc/
271 | [korma]: http://sqlkorma.com
272 |
273 | [overview]: home.html
274 | [using-sql]: using_sql.html
275 | [using-ddl]: using_ddl.html
276 | [reusing-connections]: reusing_connections.html
277 |
--------------------------------------------------------------------------------
/articles/ecosystem/java_jdbc/name_mapping.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "(outdated article)"
3 | layout: article
4 | ---
5 |
6 | This information has been moved to [Using SQL](using_sql.html#clojure-identifiers-and-sql-entities).
7 |
--------------------------------------------------------------------------------
/articles/ecosystem/java_jdbc/reusing_connections.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "How to reuse database connections"
3 | layout: article
4 | ---
5 |
6 | ## Contents
7 |
8 | * [Overview][overview]
9 | * [Using SQL][using-sql]
10 | * [Using DDL][using-ddl]
11 | * [Reusing Connections][reusing-connections]
12 |
13 | ## Reusing Connections
14 |
15 | Since you rarely want every database operation to create a new connection,
16 | there are two ways to reuse connections:
17 |
18 | * Grouping Operations using `with-db-connection`: If you don't want to deal
19 | with a connection pooling library, you can use this macro to automatically open a
20 | connection and maintain it for a body of code, with each operation executed in its
21 | own transaction, then close the connection.
22 | * Grouping Operations using `with-db-transaction`: If you want to execute multiple
23 | operations in a single transaction, you can use this macro to automatically open a
24 | connection, start a transaction, execute multiple operations, commit the transaction,
25 | and then close the connection.
26 | * Connection Pooling: This is the recommended approach and is fairly
27 | straightforward, with a number of connection pooling libraries available. See
28 | *How To Use Connection Pooling* below for more information.
29 |
30 | ## Using `with-db-connection`
31 |
32 | This macro provides the simplest way to reuse connections, without having to
33 | add a dependency on an external connection pooling library:
34 |
35 | ```clojure
36 | (ns dbexample
37 | (:require [clojure.java.jdbc :as jdbc]))
38 |
39 | (def db-spec ... ) ;; see above
40 |
41 | (jdbc/with-db-connection [db-con db-spec]
42 | (let [;; fetch some rows using this connection
43 | rows (jdbc/query db-con ["SELECT * FROM table WHERE id = ?" 42])]
44 | ;; insert a copy of the first row using the same connection
45 | (jdbc/insert! db-con :table (dissoc (first rows) :id))))
46 | ```
47 |
48 | The `query` and the `insert!` are each run in their own transaction and committed
49 | if they succeed. If you want to run multiple operations in a single transaction
50 | see the next section about `with-db-transaction`.
51 |
52 | ## Using `with-db-transaction`
53 |
54 | This macro provides a way to reuse connections, committing or rolling back
55 | multiple operations in a single transaction:
56 |
57 | ```clojure
58 | (ns dbexample
59 | (:require [clojure.java.jdbc :as jdbc]))
60 |
61 | (def db-spec ... ) ;; see above
62 |
63 | (jdbc/with-db-transaction [t-con db-spec]
64 | (let [;; fetch some rows using this connection
65 | rows (jdbc/query t-con ["SELECT * FROM table WHERE id = ?" 42])]
66 | ;; insert a copy of the first row using the same connection
67 | (jdbc/insert! t-con :table (dissoc (first rows) :id))))
68 | ```
69 |
70 | If any operation inside `with-db-transaction` fails (throws an exception), then
71 | all of the operations performed so far are rolled back. If all the operations
72 | succeed, then the entire transaction is committed.
73 |
74 | Transactions are not nested (since not all databases support that) so if this is
75 | used another active transaction, the outer transaction (and connection) are used
76 | as-is. If the isolation levels of the outer and inner transaction do not match
77 | you will get an `IllegalStateException`.
78 |
79 | See also `db-set-rollback-only!`, `db-unset-rollback-only!`, and `db-is-rollback-only`
80 | for additional control over the commit/rollback behavior of the enclosing transaction.
81 |
82 | ## Using Connection Pooling
83 |
84 | `java.jdbc` does not provide connection pooling directly but it is relatively
85 | easy to add to your project. There are several connection pooling libraries out
86 | there, but here we will provide instructions for the popular `c3p0` library.
87 |
88 | The basic idea is to add your chosen connection pooling library to your
89 | project, import the appropriate class(es), define a function that consumes a
90 | "database spec" and produces a map containing a `:datasource` key whose value
91 | is the constructed pooled `DataSource` object, then use that hash map in place of your
92 | bare `db-spec` variable. You are responsible for creating the pooled data
93 | source object and passing the map containing it into any functions that need a
94 | database connection.
95 |
96 | ### Using the c3p0 library
97 |
98 | For more information on c3p0, consult the [c3p0
99 | documentation](http://www.mchange.com/projects/c3p0/).
100 |
101 | If you're using Leiningen, you can add the following to your dependencies:
102 |
103 | ```clojure
104 | [com.mchange/c3p0 "0.9.5.2"] ;; check the documentation for latest version
105 | ```
106 |
107 | For a Maven-based project, you would add:
108 |
109 | ```xml
110 |
111 | com.mchange
112 | c3p0
113 | 0.9.5.2
114 |
115 | ```
116 |
117 | ### Create the pooled datasource from your db-spec
118 |
119 | Define your `db-spec` using the long form, for example (for MySQL):
120 |
121 | ```clojure
122 | (def db-spec
123 | {:classname "com.mysql.jdbc.Driver"
124 | :subprotocol "mysql"
125 | :subname "//127.0.0.1:3306/mydb"
126 | :user "myaccount"
127 | :password "secret"})
128 | ```
129 |
130 | We have to use the long form here because c3p0 operates on the class name, subprotocol,
131 | and subname elements. Of course, you don't really need to define a `db-spec` here
132 | because you're not going to use it with `java.jdbc` directly, only with c3p0.
133 |
134 | Import the c3p0 class as part of your namespace declaration, for example:
135 |
136 | ```clojure
137 | (ns example.db
138 | (:import (com.mchange.v2.c3p0 ComboPooledDataSource)))
139 | ```
140 |
141 | Define a function that creates a pooled datasource:
142 |
143 | ```clojure
144 | (defn pool
145 | [spec]
146 | (let [cpds (doto (ComboPooledDataSource.)
147 | (.setDriverClass (:classname spec))
148 | (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
149 | (.setUser (:user spec))
150 | (.setPassword (:password spec))
151 | ;; expire excess connections after 30 minutes of inactivity:
152 | (.setMaxIdleTimeExcessConnections (* 30 60))
153 | ;; expire connections after 3 hours of inactivity:
154 | (.setMaxIdleTime (* 3 60 60)))]
155 | {:datasource cpds}))
156 | ```
157 |
158 | Now you can create a single connection pool:
159 |
160 | ```clojure
161 | (def pooled-db (delay (pool db-spec)))
162 |
163 | (defn db-connection [] @pooled-db)
164 | ```
165 |
166 | And then call `(db-connection)` wherever you need access to it. If you're using
167 | a [component](https://github.com/stuartsierra/component) lifecycle for your
168 | application, you won't need `pooled-db` or `db-connection`. You'll just create
169 | `(pool db-spec)` as part of your application's initialization and pass it
170 | around as part of your system configuration.
171 |
172 | [overview]: home.html
173 | [using-sql]: using_sql.html
174 | [using-ddl]: using_ddl.html
175 | [reusing-connections]: reusing_connections.html
176 |
--------------------------------------------------------------------------------
/articles/ecosystem/java_jdbc/using_ddl.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Using DDL and Metadata"
3 | layout: article
4 | ---
5 |
6 | ## Contents
7 |
8 | * [Overview][overview]
9 | * [Using SQL][using-sql]
10 | * [Using DDL][using-ddl]
11 | * [Reusing Connections][reusing-connections]
12 |
13 | ## Using DDL
14 |
15 | DDL operations can be executed using the `db-do-commands` function. The general
16 | approach is:
17 |
18 | ```clojure
19 | (jdbc/db-do-commands db-spec [sql-command-1 sql-command-2 .. sql-command-n])
20 | ```
21 |
22 | The commands are executed as a single, batched statement, wrapped in a
23 | transaction. If you want to avoid the transaction, use this approach:
24 |
25 | ```clojure
26 | (jdbc/db-do-commands db-spec false [sql-command-1 sql-command-2 .. sql-command-n])
27 | ```
28 |
29 | This is necessary for some databases that do not allow DDL operations to be
30 | wrapped in a transaction.
31 |
32 | ### Creating tables
33 |
34 | For the common operations of creating and dropping tables, `java.jdbc` provides a
35 | little assistance that recognizes `:entities` so you can use keywords (or
36 | strings) and have your chosen naming strategy applied, just as you can for
37 | several of the SQL functions.
38 |
39 | ```clojure
40 | (jdbc/create-table-ddl :fruit
41 | [[:name "varchar(32)" :primary :key]
42 | [:appearance "varchar(32)"]
43 | [:cost :int]
44 | [:grade :real]]
45 | {:table-spec "ENGINE=InnoDB"
46 | :entities clojure.string/upper-case})
47 | ```
48 | This will generate:
49 |
50 | ```clojure
51 | CREATE TABLE FRUIT
52 | (NAME varchar(32) primary key,
53 | APPEARANCE varchar(32),
54 | COST int,
55 | GRADE real) ENGINE=InnoDB
56 | ```
57 |
58 | which you can pass to `db-do-commands`.
59 |
60 | `create-table-ddl` also supports a `conditional?` option which can be a simple
61 | `Boolean`, which, if `true`, will add `IF NOT EXISTS` before the table name. If
62 | that syntax doesn't work for your database, you can pass a string that will be
63 | used instead. If that isn't enough, you can pass a function of two arguments:
64 | the first argument will be the table name and the second argument will be the
65 | DDL string (this approach is needed for Microsoft SQL Server).
66 |
67 | ### Dropping tables
68 |
69 | Similarly there is a `drop-table-ddl` function which takes a table name and an
70 | optional `:entities` option to generate DDL to drop a table.
71 |
72 | ```clojure
73 | (jdbc/drop-table-ddl :fruit) ; drop table fruit
74 | (jdbc/drop-table-ddl :fruit {:entities clojure.string/upper-case}) ; drop table FRUIT
75 | ```
76 |
77 | This will generate:
78 |
79 | ```clojure
80 | DROP TABLE FRUIT
81 | ```
82 |
83 | `drop-table-ddl` also supports a `conditional?` option which can be a simple
84 | `Boolean`, which, if `true`, will add `IF EXISTS` before the table name. If
85 | that syntax doesn't work for your database, you can pass a string that will be
86 | used instead. If that isn't enough, you can pass a function of two arguments:
87 | the first argument will be the table name and the second argument will be the
88 | DDL string (this approach is needed for Microsoft SQL Server).
89 |
90 | ## Accessing metadata
91 |
92 | `java.jdbc` provides two functions for working with database metadata:
93 |
94 | * `with-db-metadata` for creating an active metadata object backed by an open
95 | connection
96 | * `metadata-result` for turning metadata results into Clojure data structures
97 |
98 | For example:
99 |
100 | ```clojure
101 | (jdbc/with-db-metadata [md db-spec]
102 | (jdbc/metadata-result (.getTables md nil nil nil (into-array ["TABLE" "VIEW"]))))
103 | ```
104 |
105 | This returns a sequence of maps describing all the tables and views in the
106 | current database. `metadata-result` only transforms `ResultSet` objects, other
107 | results are returned as-is. `metadata-result` can also accept an options map
108 | containing `:identifiers` and `:as-arrays?`, like the `query` function,
109 | and those options control how the metatadata is transformed and/or returned.
110 |
111 | Both `with-db-metadata` and `metadata-result` can accept an options hash map
112 | which will be passed through various `java.jdbc` functions (`get-connections`
113 | for the former and `result-set-seq` for the latter).
114 |
115 | [overview]: home.html
116 | [using-sql]: using_sql.html
117 | [using-ddl]: using_ddl.html
118 | [reusing-connections]: reusing_connections.html
119 |
--------------------------------------------------------------------------------
/articles/ecosystem/libraries_authoring.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Library Development and Distribution"
3 | layout: article
4 | ---
5 |
6 | This short guide covers how to create your own typical pure Clojure
7 | library and distribute it to the community via Clojars. It uses
8 | Clojure 1.4 and Leiningen 2.0-previewX, and requires you have git
9 | installed (though very little familiarity with git is required).
10 |
11 | It's assumed that you're already somewhat familiar with Clojure. If
12 | not, see the [Getting Started](getting_started.html) and
13 | [Introduction](introduction.html) guides.
14 |
15 | For the purposes of this guide, the library we'll be making is named
16 | "[trivial-library-example](https://clojars.org/trivial-library-example)".
17 |
18 | This work is licensed under a Creative Commons
20 | Attribution 3.0 Unported License (including images &
21 | stylesheets). The source is available [on
22 | Github](https://github.com/clojuredocs/guides).
23 |
24 |
25 |
26 |
27 | ## Create the Project
28 |
29 | Create your new library project. Names are usually hyphen-separated
30 | lowercase words:
31 |
32 | lein new trivial-library-example
33 | cd trivial-library-example
34 |
35 | Typical lein usage is `lein new `, but if you
36 | leave out `` (as we've done above), lein defaults to
37 | creating a library project for you.
38 |
39 | Our trivial library example project will have a dependency on
40 | [flatland's "useful"](https://clojars.org/org.flatland/useful)
41 | library.
42 |
43 | Open up our new project.clj file and make a few changes:
44 |
45 | 1. Add our dependency (`[org.flatland/useful "0.9.0"]`) to the `:dependencies` vector.
46 | 2. Remove "-SNAPSHOT" from version string.
47 | 3. Write a short description.
48 | 4. Add a url (if not a homepage, then where it's source is hosted online).
49 | 5. If you're using a different license, change the value for `:license`.
50 |
51 | Regarding your choice of license, probably the three most common for
52 | Clojure libs (along with a grossly oversimplified blurb (by this
53 | author) for each) are:
54 |
55 | * The [Eclipse Public License] (the default).
56 | * The [LGPL](http://www.gnu.org/licenses/lgpl.html) (focused most on
57 | code and additions always being free; includes language addressing
58 | s/w patent concerns). See the [FSF's recommendations] and their
59 | [instructions for use].
60 | * The [MIT] License (focused most on the user's freedom to do what
61 | they want with the code). The FSF calls this the ["Expat"
62 | License](http://directory.fsf.org/wiki/License:Expat).
63 |
64 | [Eclipse Public License]: http://directory.fsf.org/wiki/License:EPLv1.0
65 | [GPL]: http://www.gnu.org/licenses/gpl.html
66 | [FSF's recommendations]: http://www.gnu.org/licenses/license-recommendations.html
67 | [instructions for use]: http://www.gnu.org/licenses/gpl-howto.html
68 | [MIT]: http://opensource.org/licenses/MIT
69 |
70 | Whichever one you choose, update your project.clj (if necessary) to
71 | reflect that choice and save the text of the license as a file named
72 | "LICENSE" or "COPYING" in your project directory.
73 |
74 |
75 | ### A Note Regarding Project Naming
76 |
77 | The top line of your project.clj includes something like `defproject
78 | my-project-name`. This means that your project has an *artifact-id*
79 | of "my-project-name", but it also implies a *group-id* of
80 | "my-project-name" (group-id = artifact-id).
81 |
82 | The artifact-id is the name of your project. The group-id is used for
83 | namespacing (not the same thing as Clojure namespaces) --- it
84 | identifies to which group/organization a project belongs. Some
85 | examples of group-id's: clojurewerkz, sonian, and org.*your-domain*.
86 |
87 | You may choose to explicitly use a group-id for your project, if you
88 | like. For example:
89 |
90 | (defproject org.my-domain/my-project-name ...
91 | ...)
92 |
93 | The maintainers of Clojars
94 | [require that new libs be published using verified groups](https://github.com/clojars/clojars-web/wiki/Verified-Group-Names),
95 | such as org.my-domain.
96 |
97 | Read more about groups at
98 | .
99 |
100 |
101 | ## Update the README
102 |
103 | Aside from providing a good overview, rationale, and introduction at
104 | the top, you're encouraged to provide some usage examples as well. A
105 | link to the lib's (future) Clojars page (which we'll get to below)
106 | might also be appreciated. Add acknowledgements near the end, if
107 | appropriate. Adjust the copyright and license info at the bottom of
108 | the README as needed.
109 |
110 | Lein provides you with a doc directory and a starter doc/intro.md
111 | file. If you find that you have more to say than will comfortably fit
112 | into the README.md, consider moving content into the doc dir.
113 |
114 | Other goodies you might include in your README.md or doc/\*.md files:
115 | tutorial, news, bugs, limitations, alternatives, troubleshooting,
116 | configuration.
117 |
118 | Note that you generally won't add hand-written API documentation into
119 | your readme or other docs, as there are tools for creating that
120 | directly from your source (discussed later).
121 |
122 |
123 |
124 |
125 | ## Create your project's local git repository
126 |
127 | Before going much further, you probably want to get your project under
128 | version control. Make sure you've got git installed and configured to
129 | know your name and email address (i.e., that at some point you've run
130 | `git config --global user.name "Your Name"` and `git config --global
131 | user.email "your-email@somewhere.org"`).
132 |
133 | Then, in your project dir, run:
134 |
135 | git init
136 | git add .
137 | git commit -m "The initial commit."
138 |
139 | At any time after you've made changes and want to inspect them and
140 | commit them to the repository:
141 |
142 | git diff
143 | git add -p
144 | git commit -m "The commit message."
145 |
146 |
147 |
148 |
149 |
150 | ## Write Tests
151 |
152 | In test/trivial_library_example/core_test.clj, add tests as needed.
153 | An example is provided in there to get you started.
154 |
155 |
156 |
157 |
158 | ## Write Code
159 |
160 | Write code to make your tests pass.
161 |
162 | Remember to add a note at the top of each file indicating copyright
163 | and the license under which the code is distributed.
164 |
165 |
166 |
167 |
168 | ## Run Tests
169 |
170 | In your project dir:
171 |
172 | lein test
173 |
174 |
175 |
176 |
177 | ## Commit any remaining changes
178 |
179 | Before continuing to the next step, make sure all tests pass and
180 | you've committed all your changes. Check to see the status of your
181 | repo at any time with `git status` and view changes with `git diff`.
182 |
183 |
184 |
185 |
186 | ## Create github project and Upload there
187 |
188 | This guide makes use of [github](https://github.com/) to host your
189 | project code. If you don't already have a github account, create one,
190 | then log into it. Github provides good documentation on how to [get
191 | started](https://help.github.com/articles/set-up-git) and how to
192 | [create an SSH key
193 | pair](https://help.github.com/articles/generating-ssh-keys). If you
194 | haven't already done so, get that set up before continuing.
195 |
196 | Create a new repo there for your project using the icon/button/link
197 | near the top-right.
198 |
199 | > You will have your local repository, and also a remote duplicate of
200 | > it at github.
201 |
202 | For the repository name, use the same name as your project directory.
203 | Provide a one-line description and hit "Create repository".
204 |
205 | Once this remote repo has been created, follow the instructions on the
206 | resulting page to "Push an existing repository from the command
207 | line". You'll of course run the `git` commands from your project
208 | directory:
209 |
210 | git remote add origin git@github.com:uvtc/trivial-library-example.git
211 | git push -u origin master
212 |
213 | You can now access your online repo. For this tutorial, it's
214 | .
215 |
216 | Any changes you commit to your local repository can now be pushed
217 | to the remote one at github:
218 |
219 | ```bash
220 | # work work work
221 | git add -p
222 | git commit -m "commit message here"
223 | git push
224 | ```
225 |
226 |
227 | ## Create a GPG key for signing your releases
228 |
229 | You'll need to create a [gpg](http://www.gnupg.org/) key pair, which
230 | will be used by lein to sign any release you make to Clojars. Make
231 | sure you've got gpg installed and kick the tires:
232 |
233 | gpg --list-keys
234 |
235 | (The first time that command is run, you'll see some notices about
236 | it creating necessary files in your home dir.)
237 |
238 | To create a key pair:
239 |
240 | gpg --gen-key
241 |
242 | Take the default key type (RSA and RSA), and default key size (2048).
243 | When asked for how long the key should remain valid, choose a year or
244 | two. Give it your real name and email address. When it prompts you for
245 | a comment, you might add one as it can be helpful if you have multiple
246 | keys to keep track of. When prompted for a passphrase, come up with one
247 | that is different from the one used with your ssh key.
248 |
249 | When gpg has completed generating your keypair, you can have it list
250 | what keys it knows about:
251 |
252 | gpg --list-keys
253 |
254 | We'll use that public key in the next section.
255 |
256 |
257 |
258 |
259 | ## Upload to Clojars
260 |
261 | If you don't already have an account at , create
262 | one. After doing so, you'll need to supply your ssh and gpg public
263 | keys to Clojars. For the ssh public key, you can use the same one as
264 | used with github. For the gpg public key, get it by running:
265 |
266 | gpg --export -a
267 |
268 | where `` is in the output of `gpg --list-keys` (the
269 | 8-character part following the forward slash on the line starting with
270 | "pub"). Copy/paste that output (including the "-----BEGIN PGP PUBLIC
271 | KEY BLOCK-----" and "-----END PGP PUBLIC KEY BLOCK-----") into the
272 | form on your Clojars profile page.
273 |
274 | For more info on working with Clojars, see [the Clojars
275 | wiki](https://github.com/clojars/clojars-web/wiki/About).
276 |
277 | Once your Clojars account is all set up, and it has your public keys,
278 | upload your library to Clojars like so:
279 |
280 | lein deploy clojars
281 |
282 | You will be asked for your (Clojars) username and password.
283 |
284 | Then you'll be asked for your gpg passphrase. (You won't be asked for
285 | your ssh passphrase because `lein deploy clojars` uses http rather
286 | than scp --- though Clojars supports both.)
287 |
288 | You should now be able to see your lib's Clojars page: for example,
289 | !
290 |
291 |
292 |
293 |
294 |
295 | ## Generate API docs (optional)
296 |
297 | For larger library projects, you may want to automatically generate
298 | API docs (from your docstrings). See
299 | [codox](https://github.com/weavejester/codox). If your library project
300 | is hosted at github, you can use [github
301 | pages](http://pages.github.com/) to host the resulting docs.
302 |
303 |
304 |
305 |
306 |
307 | ## Announce (optional)
308 |
309 | You're welcome to announce the availability of your new library
310 | on the [Clojure Mailing List](https://groups.google.com/forum/?fromgroups#!forum/clojure).
311 |
312 |
313 |
314 |
315 | ## Make Updates to your library
316 |
317 | Making updates to your lib follows the same pattern as described above:
318 |
319 | ```bash
320 | # work test work test
321 | # update version string in project.clj
322 | git add -p
323 | git commit
324 | git push
325 | lein deploy clojars
326 | ```
327 |
328 | And optionally announce the release on the ML.
329 |
330 |
331 |
332 | ### Merging pull-requests
333 |
334 | Note that if you receive a pull-request at github, you can easily
335 | merge those changes into your project (right there, via the web page
336 | describing the pull-request). Afterwards, update your local repo to
337 | grab those changes as well:
338 |
339 | git pull
340 |
341 |
342 |
343 | ## See Also
344 |
345 | For more detailed documentation on various aspects of the procedures
346 | described here, see:
347 |
348 | * the [Clojars wiki](https://github.com/clojars/clojars-web/wiki)
349 | * the
350 | [Leiningen tutorial](https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md)
351 | and [deploy
352 | guide](https://github.com/technomancy/leiningen/blob/master/doc/DEPLOY.md)
353 |
354 |
355 |
356 | ## Contributors
357 |
358 | John Gabriele (original author)
359 |
--------------------------------------------------------------------------------
/articles/ecosystem/running_cljug.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Running a Clojure User Group"
3 | layout: article
4 | ---
5 |
6 | ## About this tutorial
7 |
8 | This guide covers:
9 |
10 | * Starting a user group
11 | * Tips for keeping it going
12 | * Meeting ideas
13 |
14 | This work is licensed under a Creative Commons Attribution 3.0 Unported License
15 | (including images & stylesheets). The source is available [on Github](https://github.com/clojuredocs/guides).
16 |
17 | ## Starting a user group
18 |
19 | Learning Clojure is easier (and more fun) if you can do it with others. Some of the essentials you will need to work out before your first meeting:
20 |
21 | ### Meeting time
22 |
23 | If you have a handful of interested parties, it's best to run a quick poll with some options for day of the week to find the most promising candidates and then unilaterally pick one. If evenings are challenging, consider a breakfast or lunch get together!
24 |
25 | ### Location
26 |
27 | Location can sometimes be the hardest part of creating a new group. Some ideas:
28 |
29 | * Ask a software, consulting, or recruiting company in the area. Hosting a group is a great way for potential hires to learn about a company.
30 | * Many libraries and public spaces can be reserved for meetings.
31 | * A get together at a local bar or coffee shop can be enough at the beginning.
32 |
33 | ### Meeting format
34 |
35 | Most Clojure user groups follow one of three models:
36 |
37 | * Talk with a speaker
38 | * Coding exercises (dojo, swarm coding, pairing, etc)
39 | * Informal chat
40 |
41 | ### Speakers
42 |
43 | If you have trouble getting speakers, try assigning a topic (a Clojure feature, library, etc) to someone to present at the next meeting.
44 |
45 | ### Meeting organization
46 |
47 | By far the two most popular ways to organize your group are [Meetup](http://meetup.com) (use discount code "clojure" for 50% off!) or Google group mailing lists.
48 | Also consider creating a GitHub organization where attendees can find each others' code repos.
49 |
50 | ## Keeping it going
51 |
52 | Once you get the first meeting or two under your belt, you have to worry about how to keep it going. Consistency is one of the most important things in getting a group going - as much as possible try to stick to a stable meeting date and location.
53 |
54 | When the group is young you’ll need to spend some effort marketing to help it grow — this is one of the reasons that Meetup.com shines. If there are local calendars, get your group listed.
55 |
56 | Create a web site! Domain names and hosting are cheap — it’s totally worth creating a blog site dedicated to the group on your own domain name.
57 |
58 | Create a Twitter account for the group and post info related to the group as well as specific to your topic. Ask all attendees to post about meetings on Twitter and blogs. Record your talks and put them on the net.
59 |
60 | Consider using a private mailing list for those that attend the meetings. This is a somewhat unusual choice these days but having the limited membership means that you generally know the people that write on the mailing list and having it closed means that people can be a bit more free in asking newbie questions. Both factors contribute to a closer-knit feeling of local community.
61 |
62 | Once you get to a certain size (or if you are fortunate to have good companies involved), you can find sponsors that provide food for your group.
63 |
64 | ## Meeting ideas
65 |
66 | Looking for meeting ideas? Here's some ideas....
67 |
68 | * Work through through the [Clojure Koans](https://github.com/functional-koans/clojure-koans)
69 | * Work through problems from [4Clojure](http://www.4clojure.com/)
70 | * Run a session on getting set up on Emacs with Clojure (or Vim, or ...)
71 | * Work through [Project Euler](http://projecteuler.net/) problems
72 | * Work through a [Code Kata](http://codekata.pragprog.com/)
73 | * Implement a game (Tic-Tac-Toe, Rock-Paper-Scissors, Checkers, Othello, etc)
74 | * Build a web site for your group in Clojure and deploy it to Heroku!
75 | * Review and expand [Clojure documentation](http://clojure-doc.org) guides
76 | * Look through the [Clojure JIRA](http://dev.clojure.org/jira/secure/Dashboard.jspa) for bugs to work on
77 |
78 | And some tips:
79 |
80 | * [Running a Clojure dojo](http://otfrom.wordpress.com/2012/07/04/how-to-run-a-london-clojure-dojo-in-20ish-easy-steps/)
81 | * [Swarm coding how-to](http://www.infoq.com/presentations/Swarm-Coding)
82 |
83 | ## Troubleshooting
84 |
85 | ### I can't find enough people for a group
86 |
87 | You might think of broadening the scope to pull in people that are interested in something similar but not exactly the same. If you can't find enough
88 | people for a Clojure user group, maybe a functional programming group would capture other people interested in Erlang, Scala, Haskell, F#, etc.
89 |
90 | ## Contributors
91 |
92 | Alex Miller (original author)
93 |
--------------------------------------------------------------------------------
/articles/ecosystem/user_groups.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Clojure User Groups"
3 | layout: article
4 | ---
5 |
6 | This guide covers Clojure User Groups (CLJUGs) around the world. If you want to add a new user group,
7 | please see our [How to Contribute](https://github.com/clojuredocs/guides#how-to-contribute) guide.
8 |
9 | If you are looking to start a new Clojure User Group (CLJUG), see [How to run your own Clojure User Group](/articles/ecosystem/running_cljug.html)
10 | and feel free to submit a link to your CLJUG site or mailing list once you have it going.
11 |
12 |
13 | ## North America
14 |
15 | * [Atlanta Clojure User Group](http://www.meetup.com/Atl-Clj/)
16 | * [Austin Clojure Meetup](http://www.meetup.com/Austin-Clojure-Meetup/)
17 | * [Boston Clojure User Group](http://www.meetup.com/Boston-Clojure-Group/)
18 | * [Charlotte Clojure User Group](http://www.meetup.com/Charlotte-Clojure-Users-Group/)
19 | * [Chicago Clojure User Group](http://www.meetup.com/Chicago-Clojure/)
20 | * [Clojure DC User Group](http://clojuredc.org/)
21 | * [Columbus Clojure User Group](http://www.columbusclojure.com/)
22 | * [Dallas/Fort Worth Clojure User Group](http://www.meetup.com/DFW-Clojure/)
23 | * [Denver Clojure User Group](http://www.meetup.com/Denver-Clojure-Meetup/)
24 | * [Detroit Clojure User Group](http://groups.google.com/group/detroit-clojure)
25 | * [Houston Clojure User Group](http://groups.google.com/group/clj-houston)
26 | * [Los Angeles Clojure User Group](http://clj-la.org/)
27 | * [MadClojure (Madison Clojure User Group)](http://www.meetup.com/Madison-Clojure/)
28 | * [Minnesota Clojure User Group](http://clojure.mn/)
29 | * [Montréal Clojure User Group](https://groups.google.com/forum/#!forum/montreal-clojure-user-group)
30 | * [National Capital Area Clojure User Group](http://www.meetup.com/Cap-Clug/)
31 | * [New York City Clojure User Group](http://www.meetup.com/Clojure-NYC/)
32 | * [Philadelphia Clojure User Group](http://groups.google.com/group/phl-clojure-language-club)
33 | * [Phoenix Clojure User Group](http://clj-phx.wikispaces.com/)
34 | * [Pittsburgh Clojure User Group](http://www.meetup.com/Clojure-PGH/)
35 | * [San Francisco Bay Area Clojure User Group](http://www.meetup.com/The-Bay-Area-Clojure-User-Group/)
36 | * [Santa Barbara Clojure User Group](http://www.meetup.com/Santa-Barbara-Clojure-Users-Group/)
37 | * [Seattle Clojure User Group, Seajure](http://seajure.github.com/)
38 | * [St. Louis Clojure Meetup](http://www.meetup.com/stl-clojure/)
39 | * [TriClojure Meetup](http://meetup.com/TriClojure/)
40 | * [Western Mass. Developer Group](http://wmassdevs.com/)
41 |
42 |
43 | ## Europe
44 |
45 | * [Aarhus Clojure User Group](http://www.clojure.dk/)
46 | * [Amsterdam Clojurians](http://ams-clj.github.com/), [@amsclj](http://twitter.com/cmsclj)
47 | * [Berlin Clojure User Group](http://www.meetup.com/Clojure-Berlin/), [@cljugb](http://twitter.com/cljugb)
48 | * [Bratislava Clojure User Group](http://groups.google.com/group/bratislava-clojure/)
49 | * [Budapest Clojure User Group](http://www.meetup.com/Budapest-Clojure-User-Group/)
50 | * [Cambridge Clojurians](http://www.meetup.com/Cambridge-Clojurians/)
51 | * [Clojure Finland](https://groups.google.com/forum/#%21forum/clojure-finland)
52 | * [Clojure Finland](https://groups.google.com/forum/?fromgroups#!forum/clojure-finland)
53 | * [Cologne Clojure User Group](http://www.meetup.com/clojure-cologne/)
54 | * [Copenhagen Clojure User Group](http://www.ative.dk/om-ative/arrangementer.aspx)
55 | * [French Riviera Clojure/Scala Meetup](http://www.meetup.com/riviera-scala-clojure), [@riviera_func](http://twitter.com/riviera_func)
56 | * [Göteborg Clojure User Group](http://www.meetup.com/got-clj/), [@Gotclj](https://twitter.com/Gotclj)
57 | * [Hamburg Clojure User Group](http://www.meetup.com/ClojureUserGroupHH/)
58 | * [Italian Clojure User Group](http://groups.google.com/group/clojure-italy)
59 | * [Lithuanian Clojure User Group](https://groups.google.com/forum/#!forum/clojure-lt)
60 | * [London Clojurians](http://londonclojurians.org/)
61 | * [Lyon Clojure User Group](http://clojure-lyon.eventbrite.fr/)
62 | * [Manchester Clojure Dojo](http://manchester.clojuredojo.com/)
63 | * [München Clojure User Group](http://www.meetup.com/clj-muc/), [@cljmuc](http://twitter.com/cljmuc)
64 | * [Prague](http://www.meetup.com/Lambda-Meetup-Group/)
65 | * [Rotterdam/The Hague](http://www.meetup.com/ehrd-clj)
66 | * [Stockholm Clojure User Group](http://groups.google.com/group/stockholm-clojure-user-group), [@sclojug](http://twitter.com/sclojug)
67 | * [Zürich](http://www.meetup.com/zh-clj-Zurich-Clojure-User-Group/)
68 |
69 | ## South America
70 |
71 | TBD
72 |
73 |
74 | ## Middle East, Asia & Pacific
75 |
76 | * [Bangalore Clojure User Group](http://groups.google.com/group/bangalore-clj)
77 | * [Chinese Clojure User Group](https://groups.google.com/group/cn-clojure)
78 | * [Melbourne Clojure User Group](http://www.meetup.com/clj-melb/)
79 | * [Sydney Clojure User Group](http://www.meetup.com/clj-syd/)
80 | * [Tel Aviv Clojure User Group](http://www.meetup.com/Clojure-Israel/)
81 |
82 | ## Africa
83 |
84 | * [Cape Town Clojure User Group](https://twitter.com/clj_ug_ct)
85 |
--------------------------------------------------------------------------------
/articles/ecosystem/web_development.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Web Development (Overview)"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * popular tools and libraries for web development
9 |
10 | This work is licensed under a Creative Commons
12 | Attribution 3.0 Unported License (including images &
13 | stylesheets). The source is available [on
14 | Github](https://github.com/clojuredocs/guides).
15 |
16 |
17 |
18 | ## What Version of Clojure Does This Guide Cover?
19 |
20 | This guide covers Clojure 1.4.
21 |
22 |
23 |
24 | ## Some Options
25 |
26 | Below are some of the various options available for web development
27 | with Clojure, listed roughly by size.
28 |
29 |
30 |
31 | ### Ring and Compojure
32 |
33 | Perhaps the simplest and most minimal setup is to use only Ring and
34 | Compojure. To get started, see the [basic web development
35 | tutorial](/articles/tutorials/basic_web_development.html).
36 |
37 |
38 |
39 | ### lib-noir
40 |
41 | In addition to Ring and Compojure, you might also make use of
42 | [lib-noir](https://github.com/noir-clojure/lib-noir).
43 |
44 |
45 |
46 | ### Luminus
47 |
48 | [Luminus](http://www.luminusweb.net/) is [a lein
49 | template](https://github.com/yogthos/luminus-template) for creating
50 | batteries-included web applications. It makes use of Ring, Compojure,
51 | lib-noir, and optionally (as described in its documentation) other
52 | libraries.
53 |
54 |
55 |
56 | ## Templating Libraries
57 |
58 | Clojure has many options for building HTML.
59 |
60 |
61 | ### Hiccup
62 |
63 | [Hiccup](https://github.com/weavejester/hiccup) represents HTML as
64 | Clojure data structures, allowing you to create and manipulate your
65 | HTML easily.
66 |
67 | [Tinsel](https://github.com/davidsantiago/tinsel) is a library that
68 | extends Hiccup with selectors and transformers, so that you can write
69 | a template separate from the insertion of your data into the template.
70 |
71 |
72 | ### Mustache
73 |
74 | [Clostache](https://github.com/fhd/clostache) implements the
75 | [Mustache](http://mustache.github.com/) templating language for
76 | Clojure.
77 |
78 | [Stencil](https://github.com/davidsantiago/stencil) is another
79 | implementation of Mustache.
80 |
81 |
82 | ### Fleet
83 |
84 | [Fleet](https://github.com/Flamefork/fleet) embeds Clojure inside HTML
85 | templates, much like Java's JSPs, or Ruby's ERb.
86 |
87 |
88 | ### Clabango
89 |
90 | [Clabango](https://github.com/danlarkin/clabango) is modeled after the
91 | [Django templating system](https://docs.djangoproject.com/en/1.4/topics/templates/). It
92 | embeds special tags and filters inside HTML templates to insert and
93 | manipulate data.
94 |
95 |
96 | ### Selmer
97 | [Selmer](https://github.com/yogthos/Selmer) is also modeled after the Django
98 | templating system with a primary goal of performance.
99 |
100 |
101 | ### Enlive and Laser
102 |
103 | [Enlive](https://github.com/cgrand/enlive) and
104 | [Laser](https://github.com/Raynes/laser) are similar libraries. They
105 | both manipulate plain HTML, and can be used for screen scraping as
106 | well as templating. They work with HTML templates with no special
107 | embedded tags or code. They use selector functions to find pieces of
108 | HTML and transformation function to change the HTML into the way you
109 | want.
110 |
111 | See the
112 | [Laser guide](https://github.com/Raynes/laser/blob/master/docs/guide.md)
113 | to see if this style of templating works for you. It is powerful, but
114 | different from most other languages' templating libraries.
115 |
116 |
117 |
118 | ## See Also
119 |
120 | * the [web development section of the library
121 | directory](/articles/ecosystem/libraries_directory.html#web_development).
122 |
123 | * [The Clojure Web Stack and the CRUD Stack](http://brehaut.net/blog/2012/clojure_web_and_the_crud_stack)
124 |
125 | * [A Brief Overview of the Clojure Web Stack](http://brehaut.net/blog/2011/ring_introduction)
126 |
127 |
128 |
129 | ## Contributors
130 |
131 | * John Gabriele
132 | * Clinton Dreisbach
133 |
--------------------------------------------------------------------------------
/articles/language/laziness.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Laziness in Clojure"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * What are lazy sequences
9 | * Pitfalls with lazy sequences
10 | * How to create functions that produce lazy sequences
11 | * How to force evaluation
12 |
13 | This work is licensed under a Creative Commons
15 | Attribution 3.0 Unported License (including images &
16 | stylesheets). The source is available [on
17 | Github](https://github.com/clojuredocs/guides).
18 |
19 |
20 |
21 | ## What Version of Clojure Does This Guide Cover?
22 |
23 | This guide covers Clojure 1.5.
24 |
25 |
26 |
27 | ## Overview
28 |
29 | Clojure is not a [lazy language](http://en.wikipedia.org/wiki/Lazy_evaluation).
30 |
31 | However, Clojure supports *lazily evaluated sequences*. This means that sequence elements are not
32 | available ahead of time and produced as the result of a computation. The computation
33 | is performed as needed. Evaluation of lazy sequences is known as *realization*.
34 |
35 | Lazy sequences can be infinite (e.g. the sequence of Fibonacci numbers, a sequence of
36 | dates with a particular interval between them, and so on). If a lazy sequence is finite,
37 | when its computation is completed, it becomes *fully realized*.
38 |
39 | When it is necessary to fully realize a lazy sequence, Clojure provides a way to
40 | *force evaluation* (force realization).
41 |
42 |
43 | ## Benefits of Lazy Sequences
44 |
45 | Lazy sequences have two main benefits:
46 |
47 | * They can be infinite
48 | * Full realization of interim results can be avoided
49 |
50 |
51 | ## Producing Lazy Sequences
52 |
53 | Lazy sequences are produced by functions. Such functions either use the `clojure.core/lazy-seq` macro
54 | or other functions that produce lazy sequences.
55 |
56 | `clojure.core/lazy-seq` accepts one or more forms that produce a sequence of `nil` (when the sequence
57 | is fully realized) and returns a seqable data structure that invokes the body the first time
58 | the value is needed and then caches the result.
59 |
60 | For example, the following function produces a lazy sequence of random UUIDs strings:
61 |
62 | ``` clojure
63 | (import java.util.UUID)
64 |
65 | (defn uuid-seq
66 | []
67 | (lazy-seq
68 | (cons (str (UUID/randomUUID))
69 | (uuid-seq))))
70 | ```
71 |
72 | Another example:
73 |
74 | ``` clojure
75 | (defn fib-seq
76 | "Returns a lazy sequence of Fibonacci numbers"
77 | ([]
78 | (fib-seq 0 1))
79 | ([a b]
80 | (lazy-seq
81 | (cons b (fib-seq b (+ a b))))))
82 | ```
83 |
84 | Both examples use `clojure.core/cons` which prepends an element to a sequence. The sequence
85 | can in turn be lazy, which both of the examples rely on.
86 |
87 | Even though both of these sequences are infinite, taking first N elements from each does
88 | return successfully:
89 |
90 | ``` clojure
91 | (take 3 (uuid-seq))
92 | ;= ("8da1b70e-7d4d-4972-b4af-48ed248c5568" "b0bc5c2c-f5ff-4733-b3ce-b0499a1a0ccc" "26d52a65-cde5-4d57-bf7f-97e3440fb3a5")
93 |
94 | (take 10 (fib-seq))
95 | l= (1 1 2 3 5 8 13 21 34 55)
96 |
97 | (take 20 (fib-seq))
98 | ;= (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
99 | ```
100 |
101 | ## Realizing Lazy Sequences (Forcing Evaluation)
102 |
103 | Lazy sequences can be forcefully realized with `clojure.core/dorun` and
104 | `clojure.core/doall`. The difference between the two is that `dorun`
105 | throws away all results and is supposed to be used for side effects,
106 | while `doall` returns computed values:
107 |
108 | ``` clojure
109 | (dorun (map inc [1 2 3 4]))
110 | ;= nil
111 |
112 | (doall (map inc [1 2 3 4]))
113 | ;= (2 3 4 5)
114 | ```
115 |
116 |
117 | ## Commonly Used Functions That Produce Lazy Sequences
118 |
119 | Multiple frequently used `clojure.core` functions return lazy sequences,
120 | most notably:
121 |
122 | * `map`
123 | * `filter`
124 | * `remove`
125 | * `range`
126 | * `take`
127 | * `take-while`
128 | * `drop`
129 | * `drop-while`
130 |
131 | The following example uses several of these functions to return 10 first
132 | even numbers in the range of [0, n):
133 |
134 | ``` clojure
135 | (take 10 (filter even? (range 0 100)))
136 | ;= (0 2 4 6 8 10 12 14 16 18)
137 | ```
138 |
139 | Several functions in `clojure.core` are designed to produce lazy
140 | sequences:
141 |
142 | * `repeat`
143 | * `iterate`
144 | * `cycle`
145 |
146 | For example:
147 |
148 | ``` clojure
149 | (take 3 (repeat "ha"))
150 | ;= ("ha" "ha" "ha")
151 |
152 | (take 5 (repeat "ha"))
153 | ;= ("ha" "ha" "ha" "ha" "ha")
154 |
155 | (take 3 (cycle [1 2 3 4 5]))
156 | ;= (1 2 3)
157 |
158 | (take 10 (cycle [1 2 3 4 5]))
159 | ;= (1 2 3 4 5 1 2 3 4 5)
160 |
161 | (take 3 (iterate (partial + 1) 1))
162 | ;= (1 2 3)
163 |
164 | (take 5 (iterate (partial + 1) 1))
165 | ;= (1 2 3 4 5)
166 | ```
167 |
168 |
169 | ## Lazy Sequences Chunking
170 |
171 | There are two fundamental strategies for implementing lazy sequences:
172 |
173 | * Realize elements one-by-one
174 | * Realize elements in groups (chunks, batches)
175 |
176 | In Clojure 1.1+, lazy sequences are *chunked* (realized in chunks).
177 |
178 | For example, in the following code
179 |
180 | ``` clojure
181 | (take 10 (range 1 1000000000000))
182 | ```
183 |
184 | one-by-one realization would realize one element 10 times. With chunked sequences,
185 | elements are realized ahead of time in chunks (32 elements at a time).
186 |
187 | This reduces the number of realizations and, for many common workloads, improves
188 | efficiency of lazy sequences.
189 |
190 |
191 | ## Contributors
192 |
193 | Michael Klishin , 2013 (original author)
194 |
--------------------------------------------------------------------------------
/articles/language/polymorphism.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Polymorphism in Clojure: Protocols and Multimethods"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * What are polymorphic functions
9 | * Type-based polymorphism with protocols
10 | * Ad-hoc polymorphism with multimethods
11 | * How to create your own data types that behave like core Clojure data types
12 |
13 | This work is licensed under a Creative Commons Attribution 3.0 Unported License
14 | (including images & stylesheets). The source is available [on Github](https://github.com/clojuredocs/guides).
15 |
16 | ## What Version of Clojure Does This Guide Cover?
17 |
18 | This guide covers Clojure 1.5.
19 |
20 |
21 | ## Overview
22 |
23 | According to Wikipedia,
24 |
25 | > In computer science, polymorphism is a programming language feature that allows values of different data types to be handled using a uniform interface.
26 |
27 | Polymorphism is not at all unique to object-oriented programming languages. Clojure has excellent support for
28 | polymorphism.
29 |
30 | For example, when a function can be used on multiple data types or behave differently based on additional argument
31 | (often called *dispatch value*), that function is *polymorphic*. A simple example of such function is a function that
32 | serializes its input to JSON (or other format).
33 |
34 | Ideally, developers would like to use the same function regardless of the input, and be able to extend
35 | it to new inputs, without having to change the original source. Inability to do so is known as the [Expression Problem](http://en.wikipedia.org/wiki/Expression_problem).
36 |
37 | In Clojure, there are two approaches to polymorphism:
38 |
39 | * Data type-oriented. More efficient (modern JVMs optimize this case very well), less flexible.
40 | * So called "ad-hoc polymorphism" where the exact function implementation is picked at runtime based on a special argument (*dispatch value*).
41 |
42 | The former is implemented using *protocols*, a feature first introduced in Clojure 1.2. The latter is available via
43 | *multimethods*, a feature that was around in Clojure since the early days.
44 |
45 |
46 | ## Type-based Polymorphism With Protocols
47 |
48 | It is common for polymorphic functions to *dispatch* (pick implementation) on the type of the first argument. For example,
49 | in Java or Ruby, when calling `#toString` or `#to_s` on an object, the exact implementation is located using that object's
50 | type.
51 |
52 | Because this is a common case and because JVM can optimize this dispatch logic very well, Clojure 1.2 introduced a new
53 | feature called *protocols*. Protocols are simply groups of functions. Each of the functions can have different
54 | implementations for different data types.
55 |
56 | Protocols are defined using the `clojure.core/defprotocol` special form. The example below defines a protocol for working with URLs and URIs.
57 | While URLs and URIs are not the same thing, some operations make sense for both:
58 |
59 | ``` clojure
60 | (defprotocol URLLike
61 | "Unifies operations on URLs and URIs"
62 | (^String protocol-of [input] "Returns protocol of given input")
63 | (^String host-of [input] "Returns host of given input")
64 | (^String port-of [input] "Returns port of given input")
65 | (^String user-info-of [input] "Returns user information of given input")
66 | (^String path-of [input] "Returns path of given input")
67 | (^String query-of [input] "Returns query string of given input")
68 | (^String fragment-of [input] "Returns fragment of given input"))
69 | ```
70 |
71 | `clojure.core/defprotocol` takes the name of the protocol and one or more lists of
72 | **function name**, **argument list**, **documentation string**:
73 |
74 | ``` clojure
75 | (^String protocol-of [input] "Returns protocol of given input")
76 | (^String host-of [input] "Returns host of given input")
77 | ```
78 |
79 | The example above uses return type hints. This makes sense in the example but is not necessary. It could have been written
80 | it as
81 |
82 | ``` clojure
83 | (defprotocol URLLike
84 | "Unifies operations on URLs and URIs"
85 | (protocol-of [input] "Returns protocol of given input")
86 | (host-of [input] "Returns hostname of given input")
87 | (port-of [input] "Returns port of given input")
88 | (user-info-of [input] "Returns user information (username:password) of given input")
89 | (path-of [input] "Returns path of given input")
90 | (query-of [input] "Returns query string of given input")
91 | (fragment-of [input] "Returns fragment of given input"))
92 | ```
93 |
94 | There are 3 ways URIs and URLs are commonly represented on the JVM:
95 |
96 | * `java.net.URI` instances
97 | * `java.net.URL` instances
98 | * Strings
99 |
100 | When a new protocol imlementation is added for a type, it is called **extending the protocol**. The most common way to extend
101 | a protocol is via the `clojure.core/extend-protocol`:
102 |
103 | ``` clojure
104 | (import java.net.URI)
105 | (import java.net.URL)
106 |
107 | (extend-protocol URLLike
108 | URI
109 | (protocol-of [^URI input]
110 | (when-let [s (.getScheme input)]
111 | (.toLowerCase s)))
112 | (host-of [^URI input]
113 | (-> input .getHost .toLowerCase))
114 | (port-of [^URI input]
115 | (.getPort input))
116 | (user-info-of [^URI input]
117 | (.getUserInfo input))
118 | (path-of [^URI input]
119 | (.getPath input))
120 | (query-of [^URI input]
121 | (.getQuery input))
122 | (fragment-of [^URI input]
123 | (.getFragment input))
124 |
125 | URL
126 | (protocol-of [^URL input]
127 | (protocol-of (.toURI input)))
128 | (host-of [^URL input]
129 | (host-of (.toURI input)))
130 | (port-of [^URL input]
131 | (.getPort input))
132 | (user-info-of [^URL input]
133 | (.getUserInfo input))
134 | (path-of [^URL input]
135 | (.getPath input))
136 | (query-of [^URL input]
137 | (.getQuery input))
138 | (fragment-of [^URL input]
139 | (.getRef input)))
140 | ```
141 |
142 | Protocol functions are used just like regular Clojure functions:
143 |
144 | ``` clojure
145 | (protocol-of (URI. "http://clojure-doc.org")) ;= "http"
146 | (protocol-of (URL. "http://clojure-doc.org")) ;= "http"
147 |
148 | (path-of (URL. "http://clojure-doc.org/articles/content.html")) ;= "/articles/content.html"
149 | (path-of (URI. "http://clojure-doc.org/articles/content.html")) ;= "/articles/content.html"
150 | ```
151 |
152 | ### Using Protocols From Different Namespaces
153 |
154 | Protocol functions are required and used the same way as regular protocol functions. Consider a
155 | namespace that looks like this
156 |
157 | ``` clojure
158 | (ns superlib.url-like
159 | (:import [java.net URL URI]))
160 |
161 | (defprotocol URLLike
162 | "Unifies operations on URLs and URIs"
163 | (^String protocol-of [input] "Returns protocol of given input")
164 | (^String host-of [input] "Returns host of given input")
165 | (^String port-of [input] "Returns port of given input")
166 | (^String user-info-of [input] "Returns user information of given input")
167 | (^String path-of [input] "Returns path of given input")
168 | (^String query-of [input] "Returns query string of given input")
169 | (^String fragment-of [input] "Returns fragment of given input"))
170 |
171 | (extend-protocol URLLike
172 | URI
173 | (protocol-of [^URI input]
174 | (when-let [s (.getScheme input)]
175 | (.toLowerCase s)))
176 | (host-of [^URI input]
177 | (-> input .getHost .toLowerCase))
178 | (port-of [^URI input]
179 | (.getPort input))
180 | (user-info-of [^URI input]
181 | (.getUserInfo input))
182 | (path-of [^URI input]
183 | (.getPath input))
184 | (query-of [^URI input]
185 | (.getQuery input))
186 | (fragment-of [^URI input]
187 | (.getFragment input))
188 |
189 | URL
190 | (protocol-of [^URL input]
191 | (protocol-of (.toURI input)))
192 | (host-of [^URL input]
193 | (host-of (.toURI input)))
194 | (port-of [^URL input]
195 | (.getPort input))
196 | (user-info-of [^URL input]
197 | (.getUserInfo input))
198 | (path-of [^URL input]
199 | (.getPath input))
200 | (query-of [^URL input]
201 | (.getQuery input))
202 | (fragment-of [^URL input]
203 | (.getRef input)))
204 | ```
205 |
206 | To use `superlib.url-like/path-of` and other functions, you require them as regular functions:
207 |
208 | ``` clojure
209 | (ns myapp
210 | (:require [superlib.url-like] :refer [host-of scheme-of]))
211 |
212 | (host-of (java.net.URI. "https://twitter.com/cnn/"))
213 | ```
214 |
215 |
216 | ### Extending Protocols For Core Clojure Data Types
217 |
218 | TBD
219 |
220 |
221 | ### Protocols and Custom Data Types
222 |
223 | TBD: cover extend-type, extend
224 |
225 |
226 | ### Partial Implementation of Protocols
227 |
228 | With protocols, it is possible to only implement certain functions for certain types.
229 |
230 |
231 | ## Ad-hoc Polymorphism with Multimethods
232 |
233 | ### First Example: Shapes
234 |
235 | Lets start with a simple problem definition. We have 3 shapes: square, circle and triangle, and
236 | need to provide an polymorphic function that calculates the area of the given shape.
237 |
238 | In total, we need 4 functions:
239 |
240 | * A function that calculates area of a square
241 | * A function that calculates area of a circle
242 | * A function that calculates area of a triangle
243 | * A polymorphic function that acts as a "unified frontend" to the functions above
244 |
245 | we will start with the latter and define a *multimethod* (not related to methods on Java objects or object-oriented programming):
246 |
247 | ``` clojure
248 | (defmulti area (fn [shape & _]
249 | shape))
250 | ```
251 |
252 | Our multimethod has a name and a *dispatch function* that takes arguments passed to the multimethod and returns
253 | a value. The returned value will define what implementation of multimethod is used. In Java or Ruby, method implementation
254 | is picked by traversing the class hierarchy. With multimethods, the logic can be anything you need. That's why it is
255 | called *ad-hoc polymorphism*.
256 |
257 | An alternative way of doing the same thing is to pass `clojure.core/first` instead of an anonymous function:
258 |
259 | ``` clojure
260 | (defmulti area first)
261 | ```
262 |
263 | Next lets implement our area multimethod for squares:
264 |
265 | ``` clojure
266 | (defmulti area (fn [shape & _]
267 | shape))
268 |
269 | (defmethod area :square
270 | [_ side]
271 | (* side side))
272 | ```
273 |
274 | Here `defmethod` defines a particular implementation of the multimethod `area`, the one that will be used if dispatch function
275 | returns `:square`. Lets try it out. Multimethods are invoked like regular Clojure functions:
276 |
277 | ``` clojure
278 | (area :square 4) ;= 16
279 | ```
280 |
281 | In this case, we pass dispatch value as the first argument, our dispatch function returns it unmodified and
282 | that's how the exact implementation is looked up.
283 |
284 | Implementation for circles looks very similar, we choose `:circle` as a reasonable dispatch value:
285 |
286 | ``` clojure
287 | (defmethod area :circle
288 | [_ radius]
289 | (* radius radius Math/PI))
290 |
291 | (area :circle 3) ;= 28.274333882308138
292 | ```
293 |
294 | For the record, `Math/PI` in this example refers to `java.lang.Math/PI`, a field that stores the value of Pi.
295 |
296 | Finally, an implementation for triangles. Here you can see that exact implementations can take different number of
297 | arguments. To calculate the area of a triangle, we multiple base by height and divide it by 2:
298 |
299 | ``` clojure
300 | (defmethod area :triangle
301 | [_ b h]
302 | (* 1/2 b h))
303 |
304 | (area :triangle 3 5) ;= 15/2
305 | ```
306 |
307 | In this example we used **Clojure ratio** data type. We could have used doubles as well.
308 |
309 | Putting it all together:
310 |
311 | ``` clojure
312 | (defmulti area (fn [shape & _]
313 | shape))
314 |
315 | (defmethod area :square
316 | [_ side]
317 | (* side side))
318 |
319 | (defmethod area :circle
320 | [_ radius]
321 | (* radius radius Math/PI))
322 |
323 | (defmethod area :triangle
324 | [_ b h]
325 | (* 1/2 b h))
326 |
327 | (area :square 4) ;= 16
328 | (area :circle 3) ;= 28.274333882308138
329 | (area :triangle 3 5) ;= 15/2
330 | ```
331 |
332 |
333 | ### Second Example: TBD
334 |
335 | TBD: an example that demonstrates deriving
336 |
337 |
338 | ## How To Create Custom Data Type That Core Functions Can Work With
339 |
340 | TBD: [How to Contribute](https://github.com/clojuredocs/guides#how-to-contribute)
341 |
342 |
343 | ## Wrapping Up
344 |
345 | TBD: [How to Contribute](https://github.com/clojuredocs/guides#how-to-contribute)
346 |
--------------------------------------------------------------------------------
/articles/tutorials/eclipse.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Starting with Eclipse and Counterclockwise For Clojure Development"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * Installing Eclipse
9 | * Installing Counterclockwise, the Clojure plugin for Eclipse
10 | * Creating a sample project
11 |
12 | This work is licensed under a Creative Commons Attribution 3.0 Unported License
13 | (including images & stylesheets). The source is available [on Github](https://github.com/clojuredocs/guides).
14 |
15 | ## What Version of Clojure Does This Guide Cover?
16 |
17 | This guide covers Clojure 1.4.
18 |
19 |
20 | ## Installing Eclipse
21 |
22 | 1. Download the latest release of Eclipse from the [official site](http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/junor).
23 | 2. Install Counterclockwise plugin.
24 | 1. navigate to the "Install new Software" tab under the help menu
25 | 2. paste in the CCW update URL: http://ccw.cgrand.net/updatesite in the "Work with:" text field
26 | 3. check the "Clojure Programming" checkbox and hit the "Next" button
27 | 3. Follow the instructions on the screen and restart Eclipse for changes to take effect.
28 |
29 | Counterclockwise takes care of setting up Clojure and Leiningen for you. And once the plugin is installed, you will be
30 | able to create a new Clojure project or a new Leiningen project.
31 |
32 | Clojure project will use Eclipse to manage dependencies, while the Leiningen project will pull dependencies from the
33 | `project.clj` in the root folder of the project.
34 |
35 | At this point you should have Eclipse with CCW up and running. Navigate to File->new->project in Eclipse menu.
36 | Then select Leiningen->Leiningen project. Here you'll see the default Leiningen Template filled in.
37 | And only thing you have to do is provide a project name. Give the project a name and hit the finish button.
38 |
39 | You should now see a new project in your Package Explorer view on the left. If you created a project called
40 | `myproject` then the project template will have a src folder which will contain the package folder named myproject.
41 |
42 | Note that since Java cannot use dashes in names, all the dashes in package folders for namespaces get converted to underscores.
43 | The package will contain a core.clj file, and its contents should look like the following:
44 |
45 | ```clojure
46 | (ns myproject.core)
47 |
48 | (defn foo
49 | "I don't do a whole lot."
50 | [x]
51 | (println x "Hello, World!"))
52 | ```
53 |
54 | Let's open it and then hit the run button. You should see a REPL pop up momentarily on the bottom of the IDE.
55 | If all went well, your project should be ready to work on (if it failed, see the [troubleshooting section](#troubleshooting)). The code that's in the file will have already been
56 | loaded up in the REPL when we hit run, and we should now be able to call our foo function.
57 |
58 | To do that, let's write the code which calls foo below it:
59 |
60 | ```clojure
61 | (foo "Test: ")
62 | ```
63 |
64 | Then navigate the cursor inside the call body and hit CTRL+ENTER on Linux/Windows or CMD+ENTER on OS X.
65 | You should see "Hello, World!" printed in the REPL view on the bottom. We can now change the behavior of the
66 | `foo` function and after reloading it the new behavior will be available next time it's called.
67 |
68 | It's also recommended to enable the "strict/paredit" mode under Preferences->Clojure->Editor section.
69 | This will allow the editor to keep track of balancing the parens for you.
70 |
71 | Another useful feature of the editor is the ability to select code by expression.
72 | If you navigate inside a function and press ALT+SHIFT+UP (use CMD instead of ALT in OS X), then inner
73 | body of the expression will be selected, pressing it again, will select the expression, and then the outer body,
74 | and so on. Conversely pressing ALT+SHIFT+DOWN will narrow the selection. This allows you to quickly navigate nested
75 | structures, and select code by chunks of logic as opposed to simply selecting individual lines.
76 |
77 | ## Managing dependencies
78 |
79 | ### Eclipse Dependencies
80 |
81 | 1. Right click on the project navigate to properties.
82 | 2. Under properties select "Java Build Path"
83 | 3. Under Libraries select "Add External JARs..."
84 | 4. Click OK
85 |
86 | The library will show up under "Referenced Libraries" in Package Explorer.
87 |
88 | ### Leiningen
89 |
90 | You will also see a `project.`clj` file in the root of the project. This file should look like the following:
91 |
92 | ```clojure
93 | (defproject myproject "0.1.0-SNAPSHOT"
94 | :description "FIXME: write description"
95 | :url "http://example.com/FIXME"
96 | :license {:name "Eclipse Public License"
97 | :url "http://www.eclipse.org/legal/epl-v10.html"}
98 | :dependencies [[org.clojure/clojure "1.4.0"]])
99 | ```
100 |
101 | You can add new dependencies to your project by adding them to the dependencies vector.
102 | For example, if we wanted to add an HTTP client, head to [ClojureSphere](http://clojuresphere.herokuapp.com/)
103 | and navigate to the clj-http page.
104 |
105 | From there follow the link to Clojars and copy the following:
106 |
107 | ```clojure
108 | [clj-http "0.6.4"]
109 | ```
110 |
111 | now we'll simply paste it under dependencies in our `project.clj`:
112 |
113 | ```clojure
114 | :dependencies [[org.clojure/clojure "1.4.0"]
115 | [clj-http "0.6.4"]]
116 | ```
117 |
118 | In the package explorer view on the left expand "Leiningen dependencies"
119 | and see that the clj-http jar included there. You will now have to kill our current REPL
120 | if it is running. To do that navigate to the terminal view next to it and press the stop button.
121 | When we start a new instance of the REPL, the library will be available for use.
122 |
123 | In the core file we can now require the library in the namespace definition:
124 |
125 | ```clojure
126 | (ns myproject.core
127 | (:require [clj-http.client :as client]))
128 | ```
129 |
130 | and test using the client by typing
131 |
132 | ```clojure
133 | (client/get "http://google.com")
134 | ```
135 |
136 | and running it as we did earlier.
137 |
138 |
139 | ## Troubleshooting
140 |
141 | If when you attempt to run your code for the first time, you are asked
142 | to select a way to run your project, rather than it just running, you
143 | can try right clicking on the root project folder and then selecting
144 | Leiningen->Reset Project Configuration.
145 |
--------------------------------------------------------------------------------
/articles/tutorials/example-code/growing_a_dsl_with_clojure.clj:
--------------------------------------------------------------------------------
1 | (ns dsl-test.core)
2 |
3 |
4 | (defmacro with-implementation
5 | [impl & body]
6 | `(binding [*current-implementation* ~impl]
7 | ~@body))
8 |
9 | (defmacro script [form]
10 | `(emit '~form))
11 |
12 |
13 | (def ^{:dynamic true}
14 | ;; The current script language implementation to generate
15 | *current-implementation*)
16 |
17 | (derive ::bash ::common)
18 |
19 |
20 | (defmulti emit
21 | (fn [form]
22 | [*current-implementation* (class form)]))
23 |
24 | (defmethod emit [::common java.lang.String]
25 | [form]
26 | form)
27 |
28 | (defmethod emit [::common java.lang.Long]
29 | [form]
30 | (str form))
31 |
32 | (defmethod emit [::common java.lang.Double]
33 | [form]
34 | (str form))
35 |
36 | (defmethod emit [::bash clojure.lang.PersistentList]
37 | [form]
38 | (case (name (first form))
39 | "println" (str "echo " (second form))
40 | nil))
41 |
42 |
43 | (defn -main
44 | [& args]
45 |
46 | (println (with-implementation ::bash (script
47 |
48 | (println "a")
49 |
50 | )))
51 |
52 | )
53 |
54 |
--------------------------------------------------------------------------------
/articles/tutorials/getting_started.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Getting Started with Clojure"
3 | layout: article
4 | ---
5 |
6 | This guide covers:
7 |
8 | * prerequisites (such as Leiningen) and installing
9 | * running the REPL
10 | * creating a project
11 | * interactive development
12 |
13 | This work is licensed under a Creative Commons
15 | Attribution 3.0 Unported License (including images &
16 | stylesheets). The source is available [on
17 | Github](https://github.com/clojuredocs/guides).
18 |
19 |
20 | ## Overview
21 |
22 | Clojure is a wonderfully simple language and you are going to love
23 | it.
24 |
25 | To quickly get started, first make sure you've got Java installed.
26 |
27 | Then install the [Leiningen](http://leiningen.org/) project management
28 | tool.
29 |
30 | > This author (jg) recommends always installing by downloading the
31 | > script directly (as described in the instructions at leiningen.org),
32 | > rather than using your OS's package manager. This will ensure that
33 | > you get the latest lein version 2.
34 |
35 | Clojure programs are typically developed inside their own project
36 | directory, and Leiningen manages projects for you. Lein takes care of
37 | pulling in dependencies (including Clojure itself), running the REPL,
38 | running your program and its tests, packaging your program for
39 | distribution, and other administrative tasks. Run `lein help` to
40 | see the list of all the tasks in can perform.
41 |
42 | > Again, there's no need to "install" Clojure, per se. Lein
43 | > will take care of fetching it for you.
44 |
45 |
46 | ## Trying out the REPL
47 |
48 | Although lein facilitates managing your projects, you can also run it
49 | on its own (outside of any particular project directory). Once you
50 | have the `lein` tool installed, run it from anywhere you like to get a
51 | repl:
52 |
53 | $ lein repl
54 |
55 | You should be greeted with a "`user=>`" prompt. Try it out:
56 |
57 | ``` clojure
58 | user=> (+ 1 1)
59 | ;; ⇒ 2
60 | user=> (distinct [:a :b :a :c :a :d])
61 | ;; ⇒ (:a :b :c :d)
62 | user=> (dotimes [i 3]
63 | #_=> (println (rand-nth ["Fabulous!" "Marvelous!" "Inconceivable!"])
64 | #_=> i))
65 | ;; Marvelous! 0
66 | ;; Inconceivable! 1
67 | ;; Fabulous! 2
68 | ;; ⇒ nil
69 | ```
70 |
71 |
72 | ## Your first project
73 |
74 | Create your first Clojure program like so:
75 |
76 | ``` bash
77 | lein new app my-proj
78 | cd my-proj
79 | # Have a look at the "-main" function in src/my_proj/core.clj.
80 | lein run
81 | ```
82 |
83 | and see the output from that `println` function call in
84 | my_proj/core.clj!
85 |
86 |
87 | ## Interactive Development
88 |
89 | In your project directory, start up a repl (`lein repl`) and
90 | run your `-main` function to see its output in the repl:
91 |
92 | $ lein repl
93 | ...
94 | my-proj.core=> (-main)
95 | Hello, World!
96 | nil
97 |
98 | (The prompt is now "my-proj.core=>" instead of "user=>" because lein
99 | has started the repl in an app project. More about that ("namespaces")
100 | in the topical guides.)
101 |
102 | From elsewhere, open up your my-proj/src/my_proj/core.clj file
103 | in your editor. Modify the text in that `println` call.
104 |
105 | Back in the repl, reload your source file and run `-main` again:
106 |
107 | my-proj.core=> (require 'my-proj.core :reload)
108 | my-proj.core=> (-main)
109 |
110 | to see your changes.
111 |
112 |
113 | ## See Also
114 |
115 | Other getting started documentation you might find useful:
116 |
117 | * [Clojure Distilled](http://yogthos.github.io/ClojureDistilled.html):
118 | introduction to core concepts necessary for working with Clojure
119 | * [A Brief Beginner's Guide to
120 | Clojure](http://www.unexpected-vortices.com/clojure/brief-beginners-guide/index.html):
121 | contains a bit more overview and background material for learning your way
122 | around the landscape.
123 | * [Starting Clojure screencast](http://cemerick.com/2012/05/02/starting-clojure/):
124 | an extensive getting-started screencast using Eclipse to develop a webapp project.
125 |
126 |
127 | ## Next Stop
128 |
129 | Next stop: [the basic Clojure language tutorial](/articles/tutorials/introduction.html).
130 |
131 |
132 |
133 | ## Contributors
134 |
135 | John Gabriele (original author)
136 |
--------------------------------------------------------------------------------
/assets/images/language/concurrency_and_parallelism/atom_state1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojuredocs/guides/070173c945f2c45fb641d604ba56021bfd1391ec/assets/images/language/concurrency_and_parallelism/atom_state1.png
--------------------------------------------------------------------------------
/assets/images/language/concurrency_and_parallelism/atom_state2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojuredocs/guides/070173c945f2c45fb641d604ba56021bfd1391ec/assets/images/language/concurrency_and_parallelism/atom_state2.png
--------------------------------------------------------------------------------
/assets/images/language/concurrency_and_parallelism/identity_value.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojuredocs/guides/070173c945f2c45fb641d604ba56021bfd1391ec/assets/images/language/concurrency_and_parallelism/identity_value.png
--------------------------------------------------------------------------------
/assets/javascripts/bootstrap-dropdown.js:
--------------------------------------------------------------------------------
1 | /* ============================================================
2 | * bootstrap-dropdown.js v2.3.2
3 | * http://twitter.github.com/bootstrap/javascript.html#dropdowns
4 | * ============================================================
5 | * Copyright 2012 Twitter, Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | * ============================================================ */
19 |
20 |
21 | !function ($) {
22 |
23 | "use strict"; // jshint ;_;
24 |
25 |
26 | /* DROPDOWN CLASS DEFINITION
27 | * ========================= */
28 |
29 | var toggle = '[data-toggle=dropdown]'
30 | , Dropdown = function (element) {
31 | var $el = $(element).on('click.dropdown.data-api', this.toggle)
32 | $('html').on('click.dropdown.data-api', function () {
33 | $el.parent().removeClass('open')
34 | })
35 | }
36 |
37 | Dropdown.prototype = {
38 |
39 | constructor: Dropdown
40 |
41 | , toggle: function (e) {
42 | var $this = $(this)
43 | , $parent
44 | , isActive
45 |
46 | if ($this.is('.disabled, :disabled')) return
47 |
48 | $parent = getParent($this)
49 |
50 | isActive = $parent.hasClass('open')
51 |
52 | clearMenus()
53 |
54 | if (!isActive) {
55 | if ('ontouchstart' in document.documentElement) {
56 | // if mobile we we use a backdrop because click events don't delegate
57 | $('').insertBefore($(this)).on('click', clearMenus)
58 | }
59 | $parent.toggleClass('open')
60 | }
61 |
62 | $this.focus()
63 |
64 | return false
65 | }
66 |
67 | , keydown: function (e) {
68 | var $this
69 | , $items
70 | , $active
71 | , $parent
72 | , isActive
73 | , index
74 |
75 | if (!/(38|40|27)/.test(e.keyCode)) return
76 |
77 | $this = $(this)
78 |
79 | e.preventDefault()
80 | e.stopPropagation()
81 |
82 | if ($this.is('.disabled, :disabled')) return
83 |
84 | $parent = getParent($this)
85 |
86 | isActive = $parent.hasClass('open')
87 |
88 | if (!isActive || (isActive && e.keyCode == 27)) {
89 | if (e.which == 27) $parent.find(toggle).focus()
90 | return $this.click()
91 | }
92 |
93 | $items = $('[role=menu] li:not(.divider):visible a', $parent)
94 |
95 | if (!$items.length) return
96 |
97 | index = $items.index($items.filter(':focus'))
98 |
99 | if (e.keyCode == 38 && index > 0) index-- // up
100 | if (e.keyCode == 40 && index < $items.length - 1) index++ // down
101 | if (!~index) index = 0
102 |
103 | $items
104 | .eq(index)
105 | .focus()
106 | }
107 |
108 | }
109 |
110 | function clearMenus() {
111 | $('.dropdown-backdrop').remove()
112 | $(toggle).each(function () {
113 | getParent($(this)).removeClass('open')
114 | })
115 | }
116 |
117 | function getParent($this) {
118 | var selector = $this.attr('data-target')
119 | , $parent
120 |
121 | if (!selector) {
122 | selector = $this.attr('href')
123 | selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
124 | }
125 |
126 | $parent = selector && $(selector)
127 |
128 | if (!$parent || !$parent.length) $parent = $this.parent()
129 |
130 | return $parent
131 | }
132 |
133 |
134 | /* DROPDOWN PLUGIN DEFINITION
135 | * ========================== */
136 |
137 | var old = $.fn.dropdown
138 |
139 | $.fn.dropdown = function (option) {
140 | return this.each(function () {
141 | var $this = $(this)
142 | , data = $this.data('dropdown')
143 | if (!data) $this.data('dropdown', (data = new Dropdown(this)))
144 | if (typeof option == 'string') data[option].call($this)
145 | })
146 | }
147 |
148 | $.fn.dropdown.Constructor = Dropdown
149 |
150 |
151 | /* DROPDOWN NO CONFLICT
152 | * ==================== */
153 |
154 | $.fn.dropdown.noConflict = function () {
155 | $.fn.dropdown = old
156 | return this
157 | }
158 |
159 |
160 | /* APPLY TO STANDARD DROPDOWN ELEMENTS
161 | * =================================== */
162 |
163 | $(document)
164 | .on('click.dropdown.data-api', clearMenus)
165 | .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
166 | .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
167 | .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
168 |
169 | }(window.jQuery);
170 |
--------------------------------------------------------------------------------
/assets/javascripts/toc.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | var $toc = $('#toc');
3 |
4 | function format (item) {
5 | if (item.children && item.children.length > 0) {
6 | return "