Skip to content

Commit 79e5030

Browse files
authored
More concepts documentation (#950)
More on #666
1 parent c8a8ba1 commit 79e5030

File tree

5 files changed

+159
-11
lines changed

5 files changed

+159
-11
lines changed

docs/api/stacktrace.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
basilisp.stacktrace
2+
===================
3+
4+
.. toctree::
5+
:maxdepth: 2
6+
:caption: Contents:
7+
8+
.. autonamespace:: basilisp.stacktrace
9+
:members:
10+
:undoc-members:

docs/concepts.rst

Lines changed: 138 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ Ratios are represented by Python's :external:py:class:`fractions.Fraction` type.
6262

6363
:ref:`arithmetic_division`
6464

65+
Arithmetic functions: :lpy:fn:`+`, :lpy:fn:`-`, :lpy:fn:`*`, :lpy:fn:`/`, :lpy:fn:`abs`, :lpy:fn:`mod`, :lpy:fn:`quot`, :lpy:fn:`rem`, :lpy:fn:`inc`, :lpy:fn:`dec`, :lpy:fn:`min`, :lpy:fn:`max`
66+
67+
Ratio functions: :lpy:fn:`numerator`, :lpy:fn:`denominator`
68+
6569
.. _strings_and_byte_strings:
6670

6771
Strings and Byte Strings
@@ -77,7 +81,7 @@ Python's byte string type :external:py:class:`bytes` is also supported.
7781

7882
.. seealso::
7983

80-
:lpy:ns:`basilisp.string` for an idiomatic string manipulation library
84+
:lpy:fn:`format`, :lpy:fn:`subs`, :lpy:ns:`basilisp.string` for an idiomatic string manipulation library
8185

8286
.. _keywords:
8387

@@ -298,6 +302,127 @@ Lazy seqs can be created using using the :lpy:fn:`lazy-seq` macro.
298302

299303
:lpy:fn:`lazy-seq`, :lpy:fn:`seq`, :lpy:fn:`first`, :lpy:fn:`rest`, :lpy:fn:`cons`, :lpy:fn:`next`, :lpy:fn:`second`, :lpy:fn:`seq?`, :lpy:fn:`nfirst`, :lpy:fn:`fnext`, :lpy:fn:`nnext`, :lpy:fn:`empty?`, :lpy:fn:`seq?`, :py:class:`basilisp.lang.interfaces.ISeq`, :py:class:`basilisp.lang.interfaces.ISeqable`
300304

305+
.. _working_with_seqs:
306+
307+
Working with Seqs
308+
^^^^^^^^^^^^^^^^^
309+
310+
A significant portion of Basilisp's core library operates on Seqs.
311+
Although most of these functions accept most or all of the builtin collection types, they typically call :lpy:fn:`seq` on the input collection argument and operate on the resulting Seq instance instead.
312+
313+
Many of these functions may accept Seqs and return another Seq, but still others accept a Seq and return some other concrete collection type.
314+
315+
Basilisp includes both the Clojure-compatible :lpy:fn:`apply` for applying a sequence as arguments to a function, but also the Python specific :lpy:fn:`apply-kw` for applying a map to Python functions accepting keyword arguments.
316+
The :lpy:fn:`apply-method` macro is another Basilisp extension which enables easier application of sequences to Python methods.
317+
318+
.. note::
319+
320+
When used alone, Seq library functions consume and produce Seqs.
321+
If multiple such functions are needed and used together, an intermediate Seq will be created for each function application.
322+
323+
As an alternative, many of the Seq functions in the core library support being used in a :ref:`transducer <transducers>`.
324+
Transducers can often be more efficient in these cases since they do not require creating an intermediate Seq for each step.
325+
326+
.. seealso::
327+
328+
Below is a non-exhaustive list of some of the built-in Seq library functions.
329+
330+
:lpy:fn:`iterate`, :lpy:fn:`range`, :lpy:fn:`reduce`, :lpy:fn:`reduce-kv`, :lpy:fn:`map`, :lpy:fn:`map-indexed`, :lpy:fn:`mapcat`, :lpy:fn:`filter`, :lpy:fn:`remove`, :lpy:fn:`keep`, :lpy:fn:`keep-indexed`, :lpy:fn:`take`, :lpy:fn:`take-while`, :lpy:fn:`drop`, :lpy:fn:`drop-while`, :lpy:fn:`drop-last`, :lpy:fn:`butlast`, :lpy:fn:`split-at`, :lpy:fn:`split-with`, :lpy:fn:`group-by`, :lpy:fn:`interpose`, :lpy:fn:`interleave`, :lpy:fn:`cycle`, :lpy:fn:`repeat`, :lpy:fn:`repeatedly`, :lpy:fn:`take-nth`, :lpy:fn:`partition`, :lpy:fn:`partition-all`, :lpy:fn:`partition-by`, :lpy:fn:`distinct`, :lpy:fn:`dedupe`, :lpy:fn:`flatten`, :lpy:fn:`take-last`, :lpy:fn:`for`
331+
332+
.. _other_useful_functions:
333+
334+
Other Useful Functions
335+
----------------------
336+
337+
The sections below detail various useful groups of functions provided by Basilisp.
338+
339+
However, not every group of functions in the core library is detailed below and, of those which are detailed, the included list of functions is not exhaustive.
340+
341+
.. _control_structures:
342+
343+
Control Structures
344+
^^^^^^^^^^^^^^^^^^
345+
346+
Basilisp features many variations on traditional programming control structures such as ``if`` and ``while`` loops thanks to the magic of :ref:`macros`.
347+
Using these control structure variants in preference to raw :lpy:form:`if` s can often help clarify the meaning of your code while also using reducing the amount of code you have to write.
348+
349+
In addition to the stalwart :lpy:fn:`condp`, :lpy:fn:`and`, and :lpy:fn:`or`, Basilisp also features threading macros which help writing clear and concise code.
350+
Threading macros can help transform deeply nested expressions into a much more readable pipeline of expressions whose source order matches the execution order at runtime.
351+
352+
.. seealso::
353+
354+
Control structures: :lpy:fn:`if-not`, :lpy:fn:`if-let`, :lpy:fn:`if-some`, :lpy:fn:`when`, :lpy:fn:`when-let`, :lpy:fn:`when-first`, :lpy:fn:`when-some`, :lpy:fn:`when-not`, :lpy:fn:`cond`, :lpy:fn:`and`, :lpy:fn:`or`, :lpy:fn:`not`, :lpy:fn:`dotimes`, :lpy:fn:`while`, :lpy:fn:`case`, :lpy:fn:`condp`, :lpy:fn:`with`, :lpy:fn:`doto`
355+
356+
Threading macros: :lpy:fn:`->`, :lpy:fn:`->>`, :lpy:fn:`some->`, :lpy:fn:`some->>`, :lpy:fn:`cond->`, :lpy:fn:`cond->>`, :lpy:fn:`as->`
357+
358+
.. _function_composition:
359+
360+
Function Composition
361+
^^^^^^^^^^^^^^^^^^^^
362+
363+
Basilisp core includes many functions which facilitate function composition, which are particularly helpful when dealing with higher-order functions.
364+
365+
In addition to the Clojure-compatible :lpy:fn:`partial` function for partial application, Basilisp includes :lpy:fn:`partial-kw` for working with Python functions which accept keyword arguments.
366+
367+
.. seealso::
368+
369+
:lpy:fn:`complement`, :lpy:fn:`constantly`, :lpy:fn:`comp`, :lpy:fn:`juxt`, :lpy:fn:`every?`, :lpy:fn:`every-pred`, :lpy:fn:`not-every?`, :lpy:fn:`some-fn`, :lpy:fn:`not-any?`, :lpy:fn:`trampoline`
370+
371+
.. _regular_expressions:
372+
373+
Regular Expressions
374+
^^^^^^^^^^^^^^^^^^^
375+
376+
Basilisp core includes support for regular expressions which are backed by Python's :external:py:mod:`re` module.
377+
Pattern literals can be created using the ``#"pattern"`` :ref:`reader macro <reader_macros>` syntax or via :lpy:fn:`re-pattern` if the pattern string is not a literal.
378+
Check for matches using :lpy:fn:`re-find`, :lpy:fn:`re-matches`, or :lpy:fn:`re-seq`.
379+
380+
.. code-block::
381+
382+
(re-matches #"$(\d+(?:\.\d{2})?)" "$123.60") ;; => nil
383+
(re-matches #"\$(\d+(?:\.\d{2})?)" "$123.60") ;; => ["$123.60" "123.60"]
384+
(re-matches #"\$(\d+(?:\.\d{2})?)" "I spent $123.60 today") ;; => nil
385+
(re-find #"\$(\d+(?:\.\d{2})?)" "I spent $123.60 today") ;; => ["$123.60" "123.60"]
386+
387+
.. seealso::
388+
389+
:lpy:fn:`re-pattern`, :lpy:fn:`re-find`, :lpy:fn:`re-matches`, :lpy:fn:`re-seq`
390+
391+
.. _futures:
392+
393+
Futures
394+
^^^^^^^
395+
396+
The Basilisp standard library includes support for futures executed on threads or processes backed by Python's :external:py:mod:`concurrent.futures` module.
397+
By default, futures are run on a thread-pool executor (bound to the dynamic Var :lpy:var:`*executor-pool*`).
398+
Callers can submit futures using either the :lpy:fn:`future` macro or the :lpy:fn:`future-call` function.
399+
400+
Users wishing to quickly parallelize work across multiple threads or processes can reach for :lpy:fn:`pmap` instead.
401+
Like the built-in :lpy:fn:`map`, ``pmap`` executes the provided function across the input collection(s) using ``future`` and, thus, using the current pool bound to ``*executor-pool*``.
402+
403+
.. note::
404+
405+
The default executor pool used by futures is a thread-pool, which is most appropriate for IO-bound work.
406+
Due to the Python GIL, the utility of a thread-pool for CPU bound work is extremely limited.
407+
408+
For CPU bound tasks, consider binding :lpy:var:`*executor-pool*` to a process pool worker (an instance of ``basilisp.lang.futures.ProcessPoolExecutor``).
409+
410+
.. seealso::
411+
412+
Using futures directly: :lpy:fn:`future`, :lpy:fn:`future-call`, :lpy:fn:`future-cancel`, :lpy:fn:`future?`, :lpy:fn:`future-cancelled?`, :lpy:fn:`future-done?`
413+
414+
Executing futures on a :ref:`Seq <seqs>`: :lpy:fn:`pmap`, :lpy:fn:`pcalls`, :lpy:fn:`pvalues`, :lpy:fn:`*pmap-cpu-count*`
415+
416+
.. _various_functions:
417+
418+
Various Functions
419+
^^^^^^^^^^^^^^^^^
420+
421+
- Functions for throwing and introspecting exceptions: :lpy:fn:`ex-info`, :lpy:fn:`ex-cause`, :lpy:fn:`ex-data`, :lpy:fn:`ex-message`, :lpy:ns:`basilisp.stacktrace`
422+
- Functions for generating random data: :lpy:fn:`rand`, :lpy:fn:`rand-int`, :lpy:fn:`rand-nth`, :lpy:fn:`random-uuid`, :lpy:fn:`random-sample`, :lpy:fn:`shuffle`
423+
- Functions which can be used to introspect the Python type hierarchy: :lpy:fn:`class`, :lpy:fn:`cast`, :lpy:fn:`bases`, :lpy:fn:`supers`, :lpy:fn:`subclasses`
424+
- Functions for parsing values from strings: :lpy:fn:`parse-double`, :lpy:fn:`parse-long`, :lpy:fn:`parse-boolean`, :lpy:fn:`parse-uuid`
425+
301426
.. _destructuring:
302427

303428
Destructuring
@@ -725,7 +850,7 @@ TBD
725850

726851
.. seealso::
727852

728-
:lpy:fn:`eduction`, :lpy:fn:`completing`, :lpy:fn:`halt-when`, :lpy:fn:`sequence`, :lpy:fn:`transduce`, :lpy:fn:`into`, :lpy:fn:`cat`
853+
:lpy:fn:`eduction`, :lpy:fn:`completing`, :lpy:fn:`halt-when`, :lpy:fn:`sequence`, :lpy:fn:`transduce`, :lpy:fn:`into`, :lpy:fn:`cat`, :lpy:fn:`reduced`, :lpy:fn:`reduced?`, :lpy:fn:`ensure-reduced`, :lpy:fn:`unreduced`
729854

730855
.. _multimethods:
731856

@@ -952,10 +1077,15 @@ Types may also optionally implement 0 or more Python `"dunder" methods <https://
9521077
9531078
(reify
9541079
^:abstract argparse/Action
955-
(__call__ [this]
1080+
(__call__ [this parser namespace values option-string]
9561081
;; ...
9571082
))
9581083
1084+
.. warning::
1085+
1086+
The Basilisp compiler is not currently able to verify that the signature of implemented methods matches the interface or superclass method signature.
1087+
Support for this feature is tracked in GitHub issue `#949 <https://github.com/basilisp-lang/basilisp/issues/949>`_.
1088+
9591089
.. _deftype:
9601090

9611091
``deftype``
@@ -970,7 +1100,11 @@ Attempting to set a field using :lpy:form:`set!` will result in a compile-time e
9701100
However, it is possible to mark a field as mutable by using the ``^:mutable`` metadata on a ``deftype`` field at compile time.
9711101
Mutable fields may be ``set!`` from within class methods.
9721102
Fields may be referred to freely by name from within method definitions as in Java (and unlike in Python where they must be qualified with ``self``).
973-
Fields may also specify defaults by providing the default value as a ``^:default`` metadata value.
1103+
1104+
.. note::
1105+
1106+
Fields may also specify defaults by providing the default value as a ``^:default`` metadata value.
1107+
Adding default values to ``deftype`` fields is a Basilisp extension which is not supported by Clojure.
9741108

9751109
.. warning::
9761110

docs/differencesfromclojure.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ Reader
9292

9393
* The reader will return the native Python data type corresponding to the Clojure type in functionality if the value is prefixed with ``#py``.
9494

95-
.. _regular_expressions:
95+
.. _regular_expression_differences:
9696

9797
Regular Expressions
9898
-------------------

docs/specialforms.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ Primary Special Forms
4545
While it is entirely legal to ``def`` a value within a function, the results of interning the Var within the function still apply to the current namespace.
4646
Within a function or method context, users should use the :lpy:form:`let` special form to bind a value to a name in that scope.
4747

48+
.. seealso::
49+
50+
:lpy:fn:`defn`, :lpy:fn:`defn-`, :lpy:fn:`defmacro`, :lpy:fn:`defasync`, :lpy:fn:`declare`, :lpy:fn:`defonce`
51+
4852
.. lpy:specialform:: (deftype name fields superclass+impls)
4953
5054
Define a new data type (a Python class) with the given set of fields which implement 0 or more Python interfaces and Basilisp protocols.
@@ -178,7 +182,7 @@ Primary Special Forms
178182

179183
.. seealso::
180184

181-
:ref:`accessing_object_methods_and_props`
185+
:ref:`accessing_object_methods_and_props`, :lpy:fn:`..`
182186

183187
.. lpy:specialform:: (.- obj attr)
184188
(.-attr obj)

src/basilisp/core.lpy

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,8 +1535,8 @@
15351535
"Return a set of subclasses of ``cls``\\.
15361536

15371537
This set is not guaranteed to be exhaustive because classes only retain a weak
1538-
reference to their subclasses, so it is possible subclasses of cls have been garbage
1539-
collected."
1538+
reference to their subclasses, so it is possible subclasses of ``cls`` have been
1539+
garbage collected."
15401540
[cls]
15411541
(set (.__subclasses__ cls)))
15421542

@@ -3388,9 +3388,9 @@
33883388
exprs)))
33893389

33903390
(defn memoize
3391-
"Retuns a fn that caches the results of the previous invocations of
3392-
`f`. The memoized fn keeps a cache of the mapping from arguments to
3393-
results."
3391+
"Retuns a fn that caches the results of the previous invocations of ``f``.
3392+
3393+
The memoized fn keeps a cache of the mapping from arguments to results."
33943394
[f]
33953395
(let [cache (atom {})]
33963396
(fn [& args]

0 commit comments

Comments
 (0)