Skip to content

Commit

Permalink
Burninate the synonyms true, false, and nil
Browse files Browse the repository at this point in the history
Per the straw poll in #908, as an alternative to #1147.

Now you must use `True`, `False`, and `None`, as in Python. Or just assign `true` to `True`, etc.; the old synonyms aren't reserved words anymore.
  • Loading branch information
Kodiologist committed Nov 24, 2016
1 parent f644dda commit ed8e37d
Show file tree
Hide file tree
Showing 23 changed files with 186 additions and 255 deletions.
18 changes: 7 additions & 11 deletions docs/language/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ Some example usage:

.. code-block:: clj
=> (if true
=> (if True
... (do (print "Side effects rock!")
... (print "Yeah, really!")))
Side effects rock!
Expand Down Expand Up @@ -589,7 +589,7 @@ Parameters may have the following keywords in front of them:
=> (apply compare ["lisp" "python"]
... {"keyfn" (fn [x y]
... (reduce - (map (fn [s] (ord (first s))) [x y])))
... "reverse" true})
... "reverse" True})
4
.. code-block:: python
Expand Down Expand Up @@ -922,16 +922,16 @@ if / if* / if-not
if-not

``if / if* / if-not`` respect Python *truthiness*, that is, a *test* fails if it
evaluates to a "zero" (including values of ``len`` zero, ``nil``, and
``false``), and passes otherwise, but values with a ``__bool__`` method
evaluates to a "zero" (including values of ``len`` zero, ``None``, and
``False``), and passes otherwise, but values with a ``__bool__`` method
(``__nonzero__`` in Python 2) can overrides this.

The ``if`` macro is for conditionally selecting an expression for evaluation.
The result of the selected expression becomes the result of the entire ``if``
form. ``if`` can select a group of expressions with the help of a ``do`` block.

``if`` takes any number of alternating *test* and *then* expressions, plus an
optional *else* expression at the end, which defaults to ``nil``. ``if`` checks
optional *else* expression at the end, which defaults to ``None``. ``if`` checks
each *test* in turn, and selects the *then* corresponding to the first passed
test. ``if`` does not evaluate any expressions following its selection, similar
to the ``if/elif/else`` control structure from Python. If no tests pass, ``if``
Expand All @@ -944,7 +944,7 @@ generally no reason to use it directly.
``if-not`` is similar to ``if*`` but the second expression will be executed
when the condition fails while the third and final expression is executed when
the test succeeds -- the opposite order of ``if*``. The final expression is
again optional and defaults to ``nil``.
again optional and defaults to ``None``.

Example usage:

Expand Down Expand Up @@ -974,7 +974,7 @@ lif and lif-not
lif-not

For those that prefer a more Lispy ``if`` clause, we have
``lif``. This *only* considers ``None`` / ``nil`` to be false! All other
``lif``. This *only* considers ``None`` to be false! All other
"false-ish" Python values are considered true. Conversely, we have
``lif-not`` in parallel to ``if`` and ``if-not`` which
reverses the comparison.
Expand All @@ -988,12 +988,8 @@ reverses the comparison.
"true"
=> (lif 0 "true" "false")
"true"
=> (lif nil "true" "false")
"false"
=> (lif None "true" "false")
"false"
=> (lif-not nil "true" "false")
"true"
=> (lif-not None "true" "false")
"true"
=> (lif-not False "true" "false")
Expand Down
54 changes: 12 additions & 42 deletions docs/language/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Checks whether *foo* is a :ref:`cons cell <hycons>`.
=> (cons? a)
True
=> (cons? nil)
=> (cons? None)
False
=> (cons? [1 2 3])
Expand Down Expand Up @@ -137,7 +137,7 @@ is ``True``, the function prints Python code instead.
body=[
Expr(value=Call(func=Name(id='print'), args=[Str(s='Hello World!')], keywords=[], starargs=None, kwargs=None))])
=> (disassemble '(print "Hello World!") true)
=> (disassemble '(print "Hello World!") True)
print('Hello World!')
Expand Down Expand Up @@ -595,36 +595,6 @@ Returns ``True`` if *x* is less than zero. Raises ``TypeError`` if
=> (neg? 0)
False
.. _nil?-fn:

nil?
----

Usage: ``(nil? x)``

Returns ``True`` if *x* is ``nil`` / ``None``.

.. code-block:: hy
=> (nil? nil)
True
=> (nil? None)
True
=> (nil? 0)
False
=> (setf x nil)
=> (nil? x)
True
=> ;; list.append always returns None
=> (nil? (.append [1 2 3] 4))
True
.. _none?-fn:

none?
Expand Down Expand Up @@ -656,10 +626,10 @@ Returns ``True`` if *x* is ``None``.
nth
---

Usage: ``(nth coll n &optional [default nil])``
Usage: ``(nth coll n &optional [default None])``

Returns the *n*-th item in a collection, counting from 0. Return the
default value, ``nil``, if out of bounds (unless specified otherwise).
default value, ``None``, if out of bounds (unless specified otherwise).
Raises ``ValueError`` if *n* is negative.

.. code-block:: hy
Expand All @@ -670,7 +640,7 @@ Raises ``ValueError`` if *n* is negative.
=> (nth [1 2 4 7] 3)
7
=> (nil? (nth [1 2 4 7] 5))
=> (none? (nth [1 2 4 7] 5))
True
=> (nth [1 2 4 7] 5 "default")
Expand Down Expand Up @@ -807,23 +777,23 @@ some
Usage: ``(some pred coll)``

Returns the first logically-true value of ``(pred x)`` for any ``x`` in
*coll*, otherwise ``nil``. Return ``nil`` if *coll* is empty.
*coll*, otherwise ``None``. Return ``None`` if *coll* is empty.

.. code-block:: hy
=> (some even? [2 4 6])
True
=> (nil? (some even? [1 3 5]))
=> (none? (some even? [1 3 5]))
True
=> (nil? (some identity [0 "" []]))
=> (none? (some identity [0 "" []]))
True
=> (some identity [0 "non-empty-string" []])
'non-empty-string'
=> (nil? (some even? []))
=> (none? (some even? []))
True
Expand Down Expand Up @@ -898,12 +868,12 @@ as an example of how to use some of these functions.
(defn fib []
(setv a 0)
(setv b 1)
(while true
(while True
(yield a)
(setv (, a b) (, b (+ a b)))))
Note the ``(while true ...)`` loop. If we run this in the REPL,
Note the ``(while True ...)`` loop. If we run this in the REPL,

.. code-block:: hy
Expand Down Expand Up @@ -1140,7 +1110,7 @@ if *from-file* ends before a complete expression can be parsed.
=> ; (print "hyfriends!")
=> (with [f (open "example.hy")]
... (try
... (while true
... (while True
... (let [exp (read f)]
... (do
... (print "OHY" exp)
Expand Down
8 changes: 4 additions & 4 deletions docs/language/internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ expressions are made of Python lists wrapped in a
``HyExpression``. However, the ``HyCons`` mimics the behavior of
"usual" Lisp variants thusly:

- ``(cons something nil)`` is ``(HyExpression [something])``
- ``(cons something None)`` is ``(HyExpression [something])``
- ``(cons something some-list)`` is ``((type some-list) (+ [something]
some-list))`` (if ``some-list`` inherits from ``list``).
- ``(get (cons a b) 0)`` is ``a``
Expand Down Expand Up @@ -288,7 +288,7 @@ Second Stage Expression-Dispatch

The only special case is the ``HyExpression``, since we need to create different
AST depending on the special form in question. For instance, when we hit an
``(if true true false)``, we need to generate a ``ast.If``, and properly
``(if True True False)``, we need to generate a ``ast.If``, and properly
compile the sub-nodes. This is where the ``@builds()`` with a String as an
argument comes in.

Expand Down Expand Up @@ -321,7 +321,7 @@ In Python, doing something like:
features, such as ``if``, ``for``, or ``while`` are statements.

Since they have no "value" to Python, this makes working in Hy hard, since
doing something like ``(print (if true true false))`` is not just common, it's
doing something like ``(print (if True True False))`` is not just common, it's
expected.

As a result, we auto-mangle things using a ``Result`` object, where we offer
Expand All @@ -331,7 +331,7 @@ assignment to things while running.

As example, the Hy::

(print (if true true false))
(print (if True True False))

Will turn into::

Expand Down
4 changes: 2 additions & 2 deletions docs/style-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,13 @@ Coding Style
(def *limit* 400000)
(defn fibs [a b]
(while true
(while True
(yield a)
(setv (, a b) (, b (+ a b)))))
;; Bad (and not preferred)
(defn fibs [a b]
(while true
(while True
(yield a)
(def (, a b) (, b (+ a b)))))
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,14 @@ In Hy, you would do:
(print "That variable is too big!")]
[(< somevar 10)
(print "That variable is too small!")]
[true
[True
(print "That variable is jussssst right!")])
What you'll notice is that ``cond`` switches off between a statement
that is executed and checked conditionally for true or falseness, and
then a bit of code to execute if it turns out to be true. You'll also
notice that the ``else`` is implemented at the end simply by checking
for ``true`` -- that's because ``true`` will always be true, so if we get
for ``True`` -- that's because ``True`` will always be true, so if we get
this far, we'll always run that one!

You might notice above that if you have code like:
Expand Down
3 changes: 1 addition & 2 deletions hy/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ def load_stdlib():
# are assignable in Python 2.* but become
# keywords in Python 3.*
def _is_hy_builtin(name, module_name):
extras = ['True', 'False', 'None',
'true', 'false', 'nil']
extras = ['True', 'False', 'None']
if name in extras or keyword.iskeyword(name):
return True
# for non-Hy modules, check for pre-existing name in
Expand Down
2 changes: 1 addition & 1 deletion hy/contrib/walk.hy
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
((type form) (outer (HyExpression (map inner form))))]
[(coll? form)
(walk inner outer (list form))]
[true (outer form)]))
[True (outer form)]))

(defn postwalk [f form]
"Performs depth-first, post-order traversal of form. Calls f on each
Expand Down
Loading

0 comments on commit ed8e37d

Please sign in to comment.