├── .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 | 4 | {{page.title}} | Clojure Documentation | Clojure Docs 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 31 | 32 | 33 | 34 | 66 | 67 |
68 |
69 |
70 |
71 | 72 |
73 |
74 |
75 | 78 | 79 |
80 | {{ content }} 81 |
82 |
83 |
84 |
85 | 86 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{page.title}} | Clojure Documentation | Clojure Docs 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 31 | 32 | 33 | 34 | 66 | 67 | 68 |
69 | {{ content }} 70 |
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 | $('