You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/cookbooks/files_and_directories/index.html
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -109,7 +109,7 @@ <h2>Working with Files and Directories in Clojure</h2>
109
109
getParent The dirname of the file.
110
110
getPath Filename with directory.
111
111
mkdir Create this directory on disk.
112
-
</code></pre><p>To read about more available methods, see <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/File.html">the <code>java.io.File</code>
112
+
</code></pre><p>To read about more available methods, see <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/io/File.html">the <code>java.io.File</code>
113
113
docs</a>.</p><h3id="get-a-list-of-the-files-and-dirs-in-a-given-directory">Get a list of the files and dirs in a given directory</h3><p>As <code>File</code> objects:</p><pre><codeclass="clojure">(.listFiles (io/file "path/to/some-dir"))
114
114
</code></pre><p>Same, but just the <em>names</em> (strings), not File objects:</p><pre><codeclass="clojure">(.list (io/file "path/to/some-dir"))
115
115
</code></pre><p>The results of those calls are seqable.</p><h2id="see-also">See also</h2><ul><li><ahref="https://github.com/clj-commons/fs">https://github.com/clj-commons/fs</a></li><li>the I/O section of the <ahref="https://clojure.org/api/cheatsheet">cheatsheet</a></li></ul>
Copy file name to clipboardExpand all lines: articles/cookbooks/strings/index.html
+4-4Lines changed: 4 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -77,13 +77,13 @@ <h2>Strings</h2>
77
77
interoperability.</p><p>This work is licensed under a <arel="license" href="https://creativecommons.org/licenses/by/3.0/">Creative Commons
78
78
Attribution 3.0 Unported License</a> (including images &
79
79
stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on
80
-
Github</a>.</p><h2id="overview">Overview</h2><ul><li>Strings are <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html">plain Java
80
+
Github</a>.</p><h2id="overview">Overview</h2><ul><li>Strings are <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/String.html">plain Java
81
81
strings</a>.
82
82
You can use anything which operates on them.</li><li>Java strings are immutable, so they're convenient to use in Clojure.</li><li>You can't add metadata to Java strings.</li><li>Clojure supports some convenient notations:</li></ul><pre><code> "foo" java.lang.String
83
83
#"\d" java.util.regex.Pattern (in this case, one which matches a single digit)
84
84
\f java.lang.Character (in this case, the letter 'f')
85
85
</code></pre><ul><li><strong>Caveat:</strong> Human brains and electronic computers are rather different
86
-
devices. So Java strings (sequences of <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Character.html#unicode">UTF-16
86
+
devices. So Java strings (sequences of <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Character.html#unicode">UTF-16
87
87
characters</a>)
88
88
don't always map nicely to user-perceived characters. For example, a
89
89
single Unicode "code point" doesn't necessarily equal a user-perceived
@@ -179,7 +179,7 @@ <h2>Strings</h2>
179
179
(read-string "#\"[abc]\""))
180
180
;=> #"[abc]"
181
181
</code></pre><h3id="parsing-complex-strings">Parsing complex strings</h3><h4id="regexes">Regexes</h4><p>Regexes offer a boost in string-matching power. You can express ideas
182
-
like repetition, alternatives, etc.</p><p><ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html">Regex
182
+
like repetition, alternatives, etc.</p><p><ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/regex/Pattern.html">Regex
183
183
reference.</a></p><p><strong>Groups:</strong> Regex groups are useful, when we want to match more than
184
184
one substring. (Or refer to matches later.) In the regex <code>#"(group-1) (group-2)"</code>, the 0th group is the whole match. The 1st group is
185
185
started by the left-most <code>(</code>, the 2nd group is started by the
@@ -291,7 +291,7 @@ <h2>Strings</h2>
291
291
(print "...")))
292
292
;=> "We have shrimp-kabobs, shrimp creole, shrimp gumbo..."
293
293
</code></pre><h4id="format-strings">Format strings</h4><p>Java's templating mini-language helps you build many strings
294
-
conveniently. <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Formatter.html">Reference.</a></p><pre><codeclass="clojure">;; %s is most commonly used to print args. Escape %'s with %%.
294
+
conveniently. <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Formatter.html">Reference.</a></p><pre><codeclass="clojure">;; %s is most commonly used to print args. Escape %'s with %%.
Copy file name to clipboardExpand all lines: articles/ecosystem/community/index.html
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ <h2>Clojure Community</h2>
63
63
</div>
64
64
65
65
<p>This guide covers:</p><ul><li>Online Communities</li><li>The Official Clojure mailing lists</li><li>IRC channel</li><li>Documentation sites</li><li>Clojure User Groups around the globe</li><li>Conferences about or related to Clojure</li><li>Various Community sites about Clojure (subreddit, etc)</li></ul><p>This work is licensed under a <arel="license" href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
66
-
(including images & stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2id="online-communities">Online Communities</h2><ul><li><ahref="https://clojurians.slack.com">Clojurians Slack</a> -- currently the most active online community, generously sponsored by Salesforce (owners of Slack) -- <ahref="http://clojurians.net">self-signup at clojurians.net</a> -- <ahref="https://clojurians-log.clojureverse.org/">partial archive of channels</a> (via <code>@logbot</code> on Slack)</li><li><ahref="https://clojurians.zulipchat.com/">Clojurians Zulip</a> -- free, open source community, includes an archive of most channels from the Clojurians Slack (via <code>@zulip-mirror-bot</code> on Slack)</li><li><ahref="https://www.reddit.com/r/Clojure/">Clojure SubReddit</a> -- r/Clojure -- the right-hand sidebar has links to many Clojure resources</li><li><ahref="https://clojureverse.org">ClojureVerse</a> -- online forum</li><li><ahref="https://ask.clojure.org/">Clojure Q&A</a> -- the official Clojure question and answer site</li><li><ahref="https://discord.gg/discljord">Clojurians Discord</a></li><li><ahref="https://clj.social/">clj.social</a> -- a Clojure-specific Mastodon instance</li><li><ahref="https://clojure.camp/">Clojure Camp</a> -- aimed at Clojure beginners, this offers a fun community of mentors and fellow learners, via Discord, Meetup.com, and offers study groups, pairing, and 1:1 mentoring</li><li>See also the <ahref="https://clojure.org/community/resources">Clojure Discussion section on clojure.org</a> for more online communities</li></ul><h2id="clojure-mailing-list">Clojure Mailing List</h2><ul><li><ahref="https://groups.google.com/g/clojure">Clojure users mailing list</a> -- this is the original and still occasionally active mailing list for Clojure users</li></ul><h2id="clojure-irc-channels">Clojure IRC Channels</h2><ul><li><code>#clojure</code> on <ahref="https://libera.chat">Libera.Chat</a></li></ul><h2id="documentation">Documentation</h2><ul><li>Official <ahref="https://clojure.org/guides/getting_started">clojure.org Guides</a></li><li>Official <ahref="https://clojure.org/reference/reader">clojure.org Reference documentation</a></li><li>Official <ahref="https://clojure.org/api/api">clojure.org API documentation</a></li><li><ahref="https://clojuredocs.org/">ClojureDocs</a>: Clojure API reference, with examples</li><li><ahref="https://clojure-doc.org/">Clojure-Doc</a>: Clojure tutorials, cookbooks, etc</li><li><ahref="https://clojure.org/api/cheatsheet">Clojure API Cheatsheet</a> (hosted on clojure.org)</li><li>Community <ahref="https://guide.clojure.style/">Clojure Style Guide</a></li><li><ahref="http://clojurekoans.com/">Clojure Koans</a></li><li><ahref="http://www.getclojure.org">GetClojure</a>: Tens of thousands of searchable Clojure examples mined from all over the internet.</li></ul><h2id="books">Books</h2><ul><li>See the list of <ahref="https://clojure.org/community/books">books on clojure.org</a></li></ul><h2id="courses">Courses</h2><ul><li>See the list of <ahref="https://www.clojure.org/community/training">courses and training on clojure.org</a></li></ul><h2id="user-groups">User Groups</h2><ul><li>The list of <ahref="https://clojure.org/community/user_groups">Clojure User Groups</a> around the world</li><li><ahref="https://clojure.org/community/start_group">How to run your own Clojure User Group</a></li></ul><h2id="videos-about-clojure">Videos About Clojure</h2><p>Videos of talks about Clojure are often made available on <ahref="https://www.infoq.com/clojure">InfoQ</a>, and <ahref="https://www.youtube.com/user/ClojureTV">Clojure YouTube channel</a>. In addition, here are some other video learning resources:</p><ul><li><ahref="https://vimeo.com/channels/fulldisclojure/videos">Full Disclojure</a> is a series of screencasts about Clojure</li><li><ahref="https://pluralsight.com/training/Courses/TableOfContents/clojure-concurrency-tutorial">Clojure Concurrency Tutorial</a></li><li><ahref="https://www.oreilly.com/library/view/clojure-inside-out/9781449368647/">Clojure Inside Out</a> from O'Reilly</li><li><ahref="https://www.youtube.com/playlist?list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt">Clojure Koans Walkthroughs</a></li><li><ahref="https://ericnormand.me/">Eric Normand</a></li><li><ahref="https://tbaldridge.pivotshare.com/">Clojure Tutorials by Tim Baldridge</a></li><li><ahref="https://www.youtube.com/practicalli">Practicalli YouTube Channel</a> -- including <ahref="https://www.youtube.com/playlist?list=PLpr9V-R8ZxiDjyU7cQYWOEFBDR1t7t0wv">Learning Clojure with Practicalli</a></li></ul><h2id="podcasts-about-clojure">Podcasts About Clojure</h2><ul><li><ahref="https://cognitect.com/cognicast/">Cognicast</a> by Craig Andera often discusses topics relevant to Clojure and ClojureScript.</li><li><ahref="https://clojuredesign.club/">Clojure Design Club</a> by Christoph Neumann and Nate Jones -- Functional Design in Clojure: Group therapy for recovering object-oriented developers.</li><li><ahref="https://clojure.stream/podcast">ClojureStream</a> by Jacek Schae -- Explore unusually expressive programming language with Lisp roots that runs on JavaScript, Java Virtual Machine, and CLR.</li><li><ahref="https://www.therepl.net/episodes/">The REPL</a> by Daniel Compton -- A weekly newsletter and podcast diving into Clojure programs and libraries.</li><li><ahref="https://podcasters.spotify.com/pod/show/lostinlambduhhs/">Lost In Lambduhhs</a> by Jordan Miller -- Featuring interviews with a myriad of guests from all sectors of tech with a special focus on the languages Clojure and Clojurescript</li><li><ahref="https://www.parens-of-the-dead.com/">Parens of the Dead</a> by Magnar Sveen and Christian Johansen -- A screencast series of zombie-themed games written with Clojure and ClojureScript</li></ul><h2id="code-repositories">Code Repositories</h2><p>Most folks host their projects at
66
+
(including images & stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2id="online-communities">Online Communities</h2><ul><li><ahref="https://clojurians.slack.com">Clojurians Slack</a> -- currently the most active online community, generously sponsored by Salesforce (owners of Slack) -- <ahref="http://clojurians.net">self-signup at clojurians.net</a> -- <ahref="https://clojurians-log.clojureverse.org/">partial archive of channels</a> (via <code>@logbot</code> on Slack)</li><li><ahref="https://clojurians.zulipchat.com/">Clojurians Zulip</a> -- free, open source community, includes an archive of most channels from the Clojurians Slack (via <code>@zulip-mirror-bot</code> on Slack)</li><li><ahref="https://www.reddit.com/r/Clojure/">Clojure SubReddit</a> -- r/Clojure -- the right-hand sidebar has links to many Clojure resources</li><li><ahref="https://clojureverse.org">ClojureVerse</a> -- online forum</li><li><ahref="https://ask.clojure.org/">Clojure Q&A</a> -- the official Clojure question and answer site</li><li><ahref="https://discord.gg/discljord">Clojurians Discord</a></li><li><ahref="https://clj.social/">clj.social</a> -- a Clojure-specific Mastodon instance</li><li><ahref="https://clojure.camp/">Clojure Camp</a> -- aimed at Clojure beginners, this offers a fun community of mentors and fellow learners, via Discord, Meetup.com, and offers study groups, pairing, and 1:1 mentoring</li><li>See also the <ahref="https://clojure.org/community/resources">Clojure Discussion section on clojure.org</a> for more online communities</li></ul><h2id="clojure-mailing-list">Clojure Mailing List</h2><ul><li><ahref="https://groups.google.com/g/clojure">Clojure users mailing list</a> -- this is the original and still occasionally active mailing list for Clojure users</li></ul><h2id="clojure-irc-channels">Clojure IRC Channels</h2><ul><li><code>#clojure</code> on <ahref="https://libera.chat">Libera.Chat</a></li></ul><h2id="documentation">Documentation</h2><ul><li>Official <ahref="https://clojure.org/guides/getting_started">clojure.org Guides</a></li><li>Official <ahref="https://clojure.org/reference/reader">clojure.org Reference documentation</a></li><li>Official <ahref="https://clojure.org/api/api">clojure.org API documentation</a></li><li><ahref="https://clojuredocs.org/">ClojureDocs</a>: Clojure API reference, with examples</li><li><ahref="https://clojure-doc.org/">Clojure-Doc</a>: Clojure tutorials, cookbooks, etc</li><li><ahref="https://clojure.org/api/cheatsheet">Clojure API Cheatsheet</a> (hosted on clojure.org)</li><li>Community <ahref="https://guide.clojure.style/">Clojure Style Guide</a></li><li><ahref="http://clojurekoans.com/">Clojure Koans</a></li><li><ahref="http://www.getclojure.org">GetClojure</a>: Tens of thousands of searchable Clojure examples mined from all over the internet.</li></ul><h2id="books">Books</h2><ul><li>See the list of <ahref="https://clojure.org/community/books">books on clojure.org</a></li></ul><h2id="courses">Courses</h2><ul><li>See the list of <ahref="https://clojure.org/community/training">courses and training on clojure.org</a></li></ul><h2id="user-groups">User Groups</h2><ul><li>The list of <ahref="https://clojure.org/community/user_groups">Clojure User Groups</a> around the world</li><li><ahref="https://clojure.org/community/start_group">How to run your own Clojure User Group</a></li></ul><h2id="videos-about-clojure">Videos About Clojure</h2><p>Videos of talks about Clojure are often made available on <ahref="https://www.infoq.com/clojure">InfoQ</a>, and <ahref="https://www.youtube.com/user/ClojureTV">Clojure YouTube channel</a>. In addition, here are some other video learning resources:</p><ul><li><ahref="https://vimeo.com/channels/fulldisclojure/videos">Full Disclojure</a> is a series of screencasts about Clojure</li><li><ahref="https://pluralsight.com/training/Courses/TableOfContents/clojure-concurrency-tutorial">Clojure Concurrency Tutorial</a></li><li><ahref="https://www.oreilly.com/library/view/clojure-inside-out/9781449368647/">Clojure Inside Out</a> from O'Reilly</li><li><ahref="https://www.youtube.com/playlist?list=PL1p6TgkbKXqyOwq6iSkce_EY5YWFHciHt">Clojure Koans Walkthroughs</a></li><li><ahref="https://ericnormand.me/">Eric Normand</a></li><li><ahref="https://tbaldridge.pivotshare.com/">Clojure Tutorials by Tim Baldridge</a></li><li><ahref="https://www.youtube.com/practicalli">Practicalli YouTube Channel</a> -- including <ahref="https://www.youtube.com/playlist?list=PLpr9V-R8ZxiDjyU7cQYWOEFBDR1t7t0wv">Learning Clojure with Practicalli</a></li></ul><h2id="podcasts-about-clojure">Podcasts About Clojure</h2><ul><li><ahref="https://cognitect.com/cognicast/">Cognicast</a> by Craig Andera often discusses topics relevant to Clojure and ClojureScript.</li><li><ahref="https://clojuredesign.club/">Clojure Design Club</a> by Christoph Neumann and Nate Jones -- Functional Design in Clojure: Group therapy for recovering object-oriented developers.</li><li><ahref="https://clojure.stream/podcast">ClojureStream</a> by Jacek Schae -- Explore unusually expressive programming language with Lisp roots that runs on JavaScript, Java Virtual Machine, and CLR.</li><li><ahref="https://www.therepl.net/episodes/">The REPL</a> by Daniel Compton -- A weekly newsletter and podcast diving into Clojure programs and libraries.</li><li><ahref="https://podcasters.spotify.com/pod/show/lostinlambduhhs/">Lost In Lambduhhs</a> by Jordan Miller -- Featuring interviews with a myriad of guests from all sectors of tech with a special focus on the languages Clojure and Clojurescript</li><li><ahref="https://www.parens-of-the-dead.com/">Parens of the Dead</a> by Magnar Sveen and Christian Johansen -- A screencast series of zombie-themed games written with Clojure and ClojureScript</li></ul><h2id="code-repositories">Code Repositories</h2><p>Most folks host their projects at
67
67
<ahref="https://github.com/search?l=Clojure&q=clojure&type=Repositories">GitHub</a>, and most pure Clojure
68
68
library distributions (with the exception of Contrib) are available at
69
69
<ahref="https://clojars.org/">Clojars</a>.</p><h2id="websites">Websites</h2><ul><li><ahref="https://clojure.org/">Clojure.org</a>: the official website</li><li><ahref="https://planet.clojure.in/">Planet Clojure</a>: aggregator of selected Clojure-related blog posts</li><li><ahref="https://www.clojure-toolbox.com/">The Clojure Toolbox</a>: a categorized directory of libraries and tools for Clojure</li><li><ahref="https://4clojure.oxal.org/">4Clojure</a>: Clojure exercise problems</li><li><ahref="https://exercism.io/">Exercism.io</a>: Peer-reviewed Clojure exercises</li></ul><h2id="conferences">Conferences</h2><p>See <ahref="https://clojure.org/community/resources#_conferences">Community > Resources > Conferences on clojure.org</a>.</p><h2id="email-newsletters">Email Newsletters</h2><ul><li><ahref="http://www.clojuregazette.com/">Clojure Gazette</a></li><li><ahref="http://defnewsletter.com/">(def newsletter)</a></li></ul><h2id="workshops">Workshops</h2><ul><li><ahref="http://www.clojurebridge.org/">ClojureBridge</a></li></ul><h2id="core-development">Core development</h2><p>See the <ahref="https://clojure.org/dev/dev">Clojure > Development on clojure.org</a> for full details on
Copy file name to clipboardExpand all lines: articles/language/collections_and_sequences/index.html
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -201,7 +201,7 @@ <h2>Language: Collections and Sequences</h2>
201
201
collection implementation details and won't be the same for vectors and lists.</p><p>In general, Clojure design emphasizes that operations on collections and sequences should be uniform and
202
202
follow the principle of least surprise. In real world projects, however, the difference between
203
203
algorithmic complexity and other runtime characteristics of various collection types often cannot
204
-
be ignored. Keep this in mind.</p><p>You can find more information in the <ahref="/articles/language/core_overview/">clojure.core Overview</a> and <ahref="http://clojure.org/cheatsheet">Clojure cheatsheet</a>.</p><h3id="count">count</h3><p>Returns a count of the number of items in a collection. An argument of nil returns 0.</p><pre><codeclass="klipse-clojure nohighlight">(count "Hello")
204
+
be ignored. Keep this in mind.</p><p>You can find more information in the <ahref="/articles/language/core_overview/">clojure.core Overview</a> and <ahref="https://clojure.org/cheatsheet">Clojure cheatsheet</a>.</p><h3id="count">count</h3><p>Returns a count of the number of items in a collection. An argument of nil returns 0.</p><pre><codeclass="klipse-clojure nohighlight">(count "Hello")
@@ -416,8 +416,8 @@ <h2>Language: Collections and Sequences</h2>
416
416
;; Execution error (ClassCastException)...
417
417
;; class java.lang.Double cannot be cast to class java.lang.String
418
418
</code></pre><p>In order to do more complicated sorting, we can create our own <code>Comparator</code>. There's a wealth of information
419
-
about comparators in the <ahref="https://www.clojure.org/guides/comparators">clojure.org comparators guide</a>, but for now, one possible comparator is a
420
-
function that takes two arguments and returns a negative, positive, or zero integer when the first argument is 'less than', 'greater than', or equal to (respectively) the second argument.</p><pre><codeclass="klipse-clojure nohighlight">(letfn [(strings-before-numbers
419
+
about comparators in the <ahref="https://clojure.org/guides/comparators">clojure.org comparators guide</a>, but for now, one possible comparator is a
420
+
function that takes two arguments and returns a negative, positive, or zero integer when the first argument is 'less than', 'greater than', or equal to (respectively) the second argument.</p><pre><codeclass="klipse-clojure nohighlight">(letfn [(strings-before-numbers
</code></pre><p>To demonstrate this graphically, initial atom state looks like this:</p><p><imgsrc="/assets/images/language/concurrency_and_parallelism/atom_state1.png" alt="Atom state 1" /></p><p>and then we mutated it with <code>swap!</code>:</p><p><imgsrc="/assets/images/language/concurrency_and_parallelism/atom_state2.png" alt="Atom state 2" /></p><p>For the readers familiar with the atomic types from the <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package,
151
+
</code></pre><p>To demonstrate this graphically, initial atom state looks like this:</p><p><imgsrc="/assets/images/language/concurrency_and_parallelism/atom_state1.png" alt="Atom state 1" /></p><p>and then we mutated it with <code>swap!</code>:</p><p><imgsrc="/assets/images/language/concurrency_and_parallelism/atom_state2.png" alt="Atom state 2" /></p><p>For the readers familiar with the atomic types from the <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package,
152
152
this should sound very familiar. The only difference is that instead of setting a value, atoms are mutated
153
153
with a function. This is both because Clojure is a functional language and because with this approach,
154
154
<code>clojure.core/swap!</code> can <em>retry the operation</em> safely. This implies that the function you provide to
@@ -548,7 +548,7 @@ <h2>Language: Concurrency and Parallelism</h2>
548
548
l)
549
549
;; ⇒ [10]
550
550
</code></pre><p>Note that for immutable Clojure data structures, explicit locking is effectively
551
-
not necessary.</p><p><em>This section will need revisiting when Virtual Threads become more common.</em></p><h3id="synchronization-on-clojure-record-fields">Synchronization on Clojure Record Fields</h3><p><em>TBD</em></p><h2id="reducers-clojure-15">Reducers (Clojure 1.5+)</h2><ul><li>The <ahref="https://www.clojure.org/news/2012/05/08/reducers">original blog post introducing reducers</a></li><li>The <ahref="https://clojure.org/reference/reducers">official <code>clojure.org</code> reference on reducers</a></li><li>The <ahref="https://clojure.github.io/clojure/clojure.core-api.html#clojure.core.reducers">official API docs for the <code>clojure.core.reducers</code> namespace</a></li></ul><h2id="javautilconcurrent">java.util.concurrent</h2><h3id="overview-2">Overview</h3><p><code>java.util.concurrent</code> (sometimes abbreviated as <code>j.u.c.</code>) is a group of
551
+
not necessary.</p><p><em>This section will need revisiting when Virtual Threads become more common.</em></p><h3id="synchronization-on-clojure-record-fields">Synchronization on Clojure Record Fields</h3><p><em>TBD</em></p><h2id="reducers-clojure-15">Reducers (Clojure 1.5+)</h2><ul><li>The <ahref="https://clojure.org/news/2012/05/08/reducers">original blog post introducing reducers</a></li><li>The <ahref="https://clojure.org/reference/reducers">official <code>clojure.org</code> reference on reducers</a></li><li>The <ahref="https://clojure.github.io/clojure/clojure.core-api.html#clojure.core.reducers">official API docs for the <code>clojure.core.reducers</code> namespace</a></li></ul><h2id="javautilconcurrent">java.util.concurrent</h2><h3id="overview-2">Overview</h3><p><code>java.util.concurrent</code> (sometimes abbreviated as <code>j.u.c.</code>) is a group of
552
552
<em>concurrency utilities</em> in the JDK. Originally introduced in JDK 5 in 2004,
553
553
they are developed and maintained by some of the experts in concurrency.
554
554
<code>j.u.c.</code> is a mature library that has been heavily battle tested for
@@ -612,10 +612,10 @@ <h2>Language: Concurrency and Parallelism</h2>
612
612
perform some computation and so on.</p><p>Because when threads are executed concurrently (or in parallel), the order of their execution is not
613
613
guaranteed, we see 4 being added to the vector before 3 in the result.</p><p>Countdown latches are commonly used with initial value of 1 to "block and wait until this operation in
614
614
a different thread is done".</p><h3id="concurrent-collections">Concurrent Collections</h3><p>Most of the Java collections are mutable and were not designed for concurrency. <code>java.util.concurrent</code> includes a number of collections that
615
-
are thread safe and can be used for passing data structures between threads.</p><h3id="atomic-variables">Atomic Variables</h3><p>The <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package provides
615
+
are thread safe and can be used for passing data structures between threads.</p><h3id="atomic-variables">Atomic Variables</h3><p>The <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/atomic/package-summary.html">java.util.concurrent.atomic</a> package provides
616
616
a number of data structures that support lock-free thread-safe programming on a single variable (identity). They support
617
-
conditional atomic update operation (<em>compared-and-swap</em> aka <em>CAS</em>).</p><p>Some of the more popular atomic types in the <code>j.u.c.atomic</code> package are <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html">AtomicBoolean</a>,
618
-
<ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html">AtomicLong</a> and <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicReference.html">AtomicReference</a>.</p><p>Atomic references are pretty well covered in Clojure with atoms but occasionally may be used by
617
+
conditional atomic update operation (<em>compared-and-swap</em> aka <em>CAS</em>).</p><p>Some of the more popular atomic types in the <code>j.u.c.atomic</code> package are <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html">AtomicBoolean</a>,
618
+
<ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html">AtomicLong</a> and <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/concurrent/atomic/AtomicReference.html">AtomicReference</a>.</p><p>Atomic references are pretty well covered in Clojure with atoms but occasionally may be used by
619
619
other libraries. An example to demonstrate how to use an atomic long for a thread-safe counter:</p><pre><codeclass="clojure">(let [l (AtomicLong.)]
Copy file name to clipboardExpand all lines: articles/language/functions/index.html
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -306,7 +306,7 @@ <h2>Language: Functions</h2>
306
306
(if (countries :in)
307
307
(comment Implement positive case)
308
308
(comment Implement negative case))
309
-
</code></pre><p>because everything but <code>false</code> and <code>nil</code> evaluates to <code>true</code> in Clojure.</p><h2id="clojure-functions-as-comparators">Clojure Functions As Comparators</h2><p>Clojure functions implement the <ahref="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Comparator.html">java.util.Comparator</a>
309
+
</code></pre><p>because everything but <code>false</code> and <code>nil</code> evaluates to <code>true</code> in Clojure.</p><h2id="clojure-functions-as-comparators">Clojure Functions As Comparators</h2><p>Clojure functions implement the <ahref="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Comparator.html">java.util.Comparator</a>
310
310
interface and can be used as comparators.</p><p>See <ahref="https://clojure.org/guides/comparators">the official Clojure guide to Comparators</a> for more details.</p><h2id="wrapping-up">Wrapping Up</h2><p>Functions are at the heart of Clojure. They are defined using the <code>defn</code> macro, can have multiple arities,
311
311
be variadic and support parameter destructuring. Function arguments and return value can optionally be
312
312
type hinted.</p><p>Functions are first class values and can be passed to other functions (called Higher Order Functions or HOFs).
Copy file name to clipboardExpand all lines: articles/language/interop/index.html
+54-19Lines changed: 54 additions & 19 deletions
Original file line number
Diff line number
Diff line change
@@ -64,7 +64,7 @@ <h2>Language: Java Interop</h2>
64
64
65
65
<p>This guide covers:</p><ul><li>How to instantiate Java classes</li><li>How to invoke Java methods</li><li>How to extend Java classes with proxy</li><li>How to implement Java interfaces with reify</li><li>How to generate Java classes with gen-class</li><li>Other topics related to interop</li></ul><p>This guide does not cover how to include Java files in Clojure projects.
66
66
For that, head to <ahref="/articles/cookbooks/cli_build_projects/#including-java-code-in-a-clojure-project">including Java code in a Clojure project</a></p><p>This work is licensed under a <arel="license" href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported License</a>
67
-
(including images & stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.11.</p><h2id="overview">Overview</h2><p>Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, JS, CLR and so on).
67
+
(including images & stylesheets). The source is available <ahref="https://github.com/clojure-doc/clojure-doc.github.io">on Github</a>.</p><h2id="what-version-of-clojure-does-this-guide-cover">What Version of Clojure Does This Guide Cover?</h2><p>This guide covers Clojure 1.12.</p><h2id="overview">Overview</h2><p>Clojure was designed to be a hosted language that directly interoperates with its host platform (JVM, JS, CLR and so on).
68
68
Clojure code is compiled to JVM bytecode. For method calls on Java objects, the Clojure compiler
69
69
will try to emit the same bytecode <code>javac</code> would produce.</p><p>It is possible to implement interfaces, and to extend and generate Java classes in Clojure.</p><p>Clojure also provides convenient functions and macros that make consuming Java libraries
70
70
easier and often more concise than it would be in Java code.</p><p>See also the <ahref="https://clojure.org/reference/java_interop">official Java interop reference</a> on clojure.org.</p><h2id="imports">Imports</h2><p>Java classes can be referenced either using their fully-qualified names (FQNs) such as
</code></pre><p>It is possible to use fully qualified names (e.g. <code>java.util.Date</code>) or short names with imports:</p><pre><codeclass="clojure">(import java.util.Date)
103
103
104
104
(Date.) ; ⇒ #inst "2012-10-09T21:24:27.229-00:00"
105
-
</code></pre><p>An example with constructor arguments:</p><pre><codeclass="clojure">(java.net.URI. "http://clojure.org")
</code></pre><h2id="how-to-invoke-java-methods">How to Invoke Java Methods</h2><h3id="instance-methods">Instance Methods</h3><p>Instance methods are invoked using the <code>.</code> special form:</p><pre><codeclass="clojure">(let [d (java.util.Date.)]
108
120
(. d getTime)) ; ⇒ 1349819873183
109
121
</code></pre><p>Just like with object instantiation, it is much more common to see an alternative version:</p><pre><codeclass="clojure">(let [d (java.util.Date.)]
110
122
(.getTime d)) ; ⇒ 1349819873183
123
+
</code></pre><p>In Clojure 1.12, <code>SomeClass/.methodName</code> is a "function value" and can be treated like
124
+
a regular Clojure function:</p><pre><codeclass="clojure">;; assuming (import java.util.Date):
</code></pre><h3id="static-methods">Static Methods</h3><p>Static methods can be invoked with the same <code>.</code> special form:</p><pre><codeclass="clojure">(. Math floor 5.677) ; ⇒ 5.0
112
128
</code></pre><p>or (typically) the sugared version, <code>ClassName/methodName</code>:</p><pre><codeclass="clojure">(Math/floor 5.677) ; ⇒ 5.0
113
129
114
130
(Boolean/valueOf "false") ; ⇒ false
115
131
(Boolean/valueOf "true") ; ⇒ true
132
+
</code></pre><p>In Clojure 1.12, <code>SomeClass/.methodName</code> is a "function value" and can be treated like
133
+
a regular Clojure function:</p><pre><codeclass="clojure">(map Boolean/valueOf ["true" "false" "what?"])
134
+
;;⇒ (true false false)
116
135
</code></pre><h3id="chained-calls-with-the-double-dot-form">Chained Calls With The Double Dot Form</h3><p>It is possible to chain method calls using the <code>..</code> special form:</p><pre><codeclass="clojure">(.. (java.util.Date.) getTime toString) ; ⇒ "1693344712616"
117
136
</code></pre><h3id="multiple-calls-on-the-same-object">Multiple Calls On the Same Object</h3><p>If you need to call several methods on the same (mutable) object, you
118
137
can use the <code>doto</code> macro:</p><pre><codeclass="clojure">(doto (java.util.Stack.)
</code></pre><p>Each method is called on the original object -- the first argument
136
155
to <code>doto</code> -- and it returns that same object as the result.</p><h2id="how-to-access-java-fields">How to Access Java Fields</h2><p>Public mutable fields are not common in Java libraries but sometimes you need to access them.
</code></pre><h2id="how-to-get-a-java-class-reference-by-name">How To Get a Java Class Reference By Name</h2><p>To obtain a class reference by its string name (fully qualified), use <code>Class/forName</code> via Java interop:</p><pre><codeclass="clojure">(Class/forName "java.util.Date") ; ⇒ java.util.Date
180
199
</code></pre><h3id="array-types-primitives">Array Types, Primitives</h3><p>JVM has what is called <strong>primitive types</strong> (numerics, chars, booleans) that are not "real" objects.
181
-
In addition, array types have pretty obscure internal names.</p><p>An array of <code>String</code>, has a name of <code>"[Ljava.lang.String;"</code>.
200
+
In addition, array types have pretty obscure internal names.</p><p>An array of <code>String</code>, has an internal name of <code>"[Ljava.lang.String;"</code>.
182
201
You can construct an array of <code>String</code> using <code>into-array</code>:</p><pre><codeclass="clojure">(class (into-array String ["foo" "bar" "baz"]))
183
-
;; ⇒ [Ljava.lang.String;
184
-
</code></pre><p>If you need to obtain a reference to
185
-
an array of primitives, for example longs, pass <code>"[J"</code> to <code>Class/forName</code>. Below is the full table:</p><tableclass="table-striped table-bordered table"><thead><tr><th>Internal JVM class name</th><th>Array of ? (type)</th></tr></thead><tbody><tr><td><pre>"[S"</pre></td><td>short</td></tr><tr><td><pre>"[I"</pre></td><td>integer</td></tr><tr><td><pre>"[J"</pre></td><td>long</td></tr><tr><td><pre>"[F"</pre></td><td>float</td></tr><tr><td><pre>"[D"</pre></td><td>double</td></tr><tr><td><pre>"[B"</pre></td><td>byte</td></tr><tr><td><pre>"[C"</pre></td><td>char</td></tr><tr><td><pre>"[Z"</pre></td><td>boolean</td></tr></tbody></table><p>For convenience, Clojure has <code>*-array</code> functions for each of the above
202
+
;;=> java.lang.String/1 ; Clojure 1.12
203
+
;; but in earlier versions of Clojure:
204
+
;;⇒ [Ljava.lang.String;
205
+
</code></pre><p>In Clojure 1.12, you can <code>SomeClass/N</code> to get a class reference to an N-dimensional array of the class,
206
+
but prior to 1.12, you had to use <code>Class/forName</code> and the internal name of the array type:</p><tableclass="table-striped table-bordered table"><thead><tr><th>Internal JVM class name</th><th>Array of ? (type)</th><th>Clojure 1.12 type</th></tr></thead><tbody><tr><td><pre>"[S"</pre></td><td>short</td><td>short/1</td></tr><tr><td><pre>"[I"</pre></td><td>integer</td><td>integer/1</td></tr><tr><td><pre>"[J"</pre></td><td>long</td><td>long/1</td></tr><tr><td><pre>"[F"</pre></td><td>float</td><td>float/1</td></tr><tr><td><pre>"[D"</pre></td><td>double</td><td>double/1</td></tr><tr><td><pre>"[B"</pre></td><td>byte</td><td>byte/1</td></tr><tr><td><pre>"[C"</pre></td><td>char</td><td>char/1</td></tr><tr><td><pre>"[Z"</pre></td><td>boolean/1</td></tr></tbody></table><p>For convenience, Clojure has <code>*-array</code> functions for each of the above
186
207
types that help you create an array of primitive values:</p><pre><codeclass="clojure">user=> (char-array [\h \e \l \l \o])
</code></pre><p>In Clojure 1.12, a Java interface that is declared <code>@FunctionalInterface</code> can
252
+
be inferred from from the context and can be satisfied with a regular Clojure
253
+
function. <code>java.io.FilenameFilter</code> is such an interface, so you can pass a
254
+
Clojure function directly to a Java method that expects a <code>FilenameFilter</code>:</p><pre><codeclass="clojure">(seq (.list (java.io.File. ".") #(str/starts-with? %2 ".")))
</code></pre><p>In earlier versions of Clojure, you would have to use <code>reify</code> for that:</p><pre><codeclass="clojure">(seq (.list (java.io.File. ".")
</code></pre><h3id="reify-parameter-destructuring-and-varargs">reify, Parameter Destructuring and Varargs</h3><p><code>reify</code> does not support destructuring or variadic arguments in method signatures. You will not always get an error from the compiler if you try to use them, but the resulting code will not work the way you expect.
231
262
For example:</p><pre><codeclass="clojure">(reify java.io.FilenameFilter
</code></pre><p>We have used <code>clojure.string/ends-with?</code> so that no type hints
260
-
are required: unlike in the "inline" implementation (above),
261
-
the Clojure compiler would not be able to infer the types of
262
-
<code>_dir</code> and <code>name</code> parameters in the function that does the filtering.
263
-
When methods are implemented "inline", types can be inferred from
264
-
method signatures in the interface.</p><h2id="extending-java-classes-with-proxy">Extending Java Classes With proxy</h2><p><code>proxy</code> is one of two ways to generate instances of anonymous classes in Clojure.
290
+
</code></pre><p>As above, in Clojure 1.12, because <code>java.io.FilenameFilter</code> is a functional interface, you can pass a Clojure function directly:</p><pre><codeclass="clojure">(import java.io.File)
291
+
292
+
;; a file filter implementation that keeps only .edn files
293
+
(let [^java.io.FilenameFilter
294
+
f (fn [_dir name]
295
+
(str/ends-with? name ".edn"))
296
+
dir (File. "/home/sean/oss/clojure-doc.github.io/")]
297
+
(into [] (.listFiles dir f)))
298
+
</code></pre><blockquote><p>Note: we need the type hint on <code>f</code> here because <code>.listFiles</code> has multiple overloads for the same arity, and we need to distinguish a <code>FilenameFilter</code> from a <code>FileFilter</code>.</p></blockquote><h2id="extending-java-classes-with-proxy">Extending Java Classes With proxy</h2><p><code>proxy</code> is one of two ways to generate instances of anonymous classes in Clojure.
265
299
<code>proxy</code> takes two vectors: one listing its superclass and (optional) interfaces, the other listing constructor signatures, as well as
266
300
zero or more
267
301
method implementations. Method implementations are identical to <code>reify</code> except that the <code>this</code> argument is
(publish this (json/json-str { :group job-group }) "quartz.scheduler.jobs-resumed"))
429
463
</code></pre><h3id="inspecting-class-signatures">Inspecting Class Signatures</h3><p>When using <code>gen-class</code> for interoperability purposes, sometimes it is necessary to inspect the API
430
464
of the class generated by <code>gen-class</code>.</p><p>It can be inspected
431
-
using <ahref="https://docs.oracle.com/en/java/javase/17/docs/specs/man/javap.html">javap</a>. Given the
465
+
using <ahref="https://docs.oracle.com/en/java/javase/21/docs/specs/man/javap.html">javap</a>. Given the
432
466
following Clojure namespace:</p><pre><codeclass="clojure">(ns genclassy.core
or simply <em>monitor</em>). While very rarely necessary, Clojure provides support for
511
545
operations that acquire intrinsic lock of a mutable Java object.</p><p>This is covered in the <ahref="/articles/language/concurrency_and_parallelism/#using-intrinsic-locks-synchronized-in-clojure">Concurrency and Parallelism guide</a>.</p><h2id="wrapping-up">Wrapping Up</h2><p>TBD: <ahref="https://github.com/clojure-doc/clojure-doc.github.io#how-to-contribute">How to Contribute</a></p><h2id="contributors">Contributors</h2><p>Michael Klishin <ahref="mailto:michael@defprotocol.org">michael@defprotocol.org</a> (original author)
512
546
Lee Hinman <ahref="mailto:lee@writequit.org">lee@writequit.org</a>
from being a great organizational aide, it also handily includes links
123
123
to the relevant <ahref="http://clojuredocs.org/">Clojuredocs</a> pages where you
124
124
can find docs for and examples of the various Clojure functions.</p><p>In the REPL, at any time you can see the documentation for a given
@@ -387,12 +387,12 @@ <h2>Introduction to Clojure</h2>
387
387
(disj s :a) ; ⇒ #{:b}
388
388
389
389
s ; ⇒ is still #{:a :b}
390
-
</code></pre><p>See the <ahref="http://clojure.org/cheatsheet">cheatsheet</a> for much more
390
+
</code></pre><p>See the <ahref="https://clojure.org/cheatsheet">cheatsheet</a> for much more
391
391
you can do with these core data structures.</p><h2id="regular-expressions">Regular Expressions</h2><p>As you've seen, Clojure provides a handy literal syntax for regular
392
392
expressions: <code>#"regex here"</code>. Clojure uses the same regular expression
393
393
syntax as Java, which is nearly the same as what Perl 5 (and Python,
394
394
and Ruby) uses. You can read more about the specifics in the Java
docs</a>.</p><p>Clojure provides a number of functions for working with strings, and a
397
397
number of those can make use of regexes. See the next section for some
398
398
examples.</p><h2id="functions-for-working-with-strings">Functions For Working With Strings</h2><p>There are a number of functions for working with strings listed in the
@@ -467,7 +467,7 @@ <h2>Introduction to Clojure</h2>
467
467
if you don't have "variables" and can't change anything, it will
468
468
become clear as we continue.</p><h2id="control-structures">Control Structures</h2><p>Clojure has most of the usual control structures you'd expect to find,
469
469
for example: <code>if</code>, <code>and</code>, <code>or</code>, and <code>cond</code>. You can find them listed
470
-
in the <ahref="http://clojure.org/cheatsheet">Cheatsheet</a>.</p><p>Note that they are all <em>expressions</em> in Clojure, and evaluate to
470
+
in the <ahref="https://clojure.org/cheatsheet">Cheatsheet</a>.</p><p>Note that they are all <em>expressions</em> in Clojure, and evaluate to
471
471
something. So, for example, this <code>if</code> expression:</p><pre><codeclass="clojure">(if motor-turning?
0 commit comments