Skip to content

Commit 26d6b4c

Browse files
committed
a bit more chapter 10
1 parent e8aa9c7 commit 26d6b4c

File tree

2 files changed

+31
-31
lines changed

2 files changed

+31
-31
lines changed

‎doc/source/10_trees_and_directed_acyclic_graphs.rst

+27-26
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ Let's now consider :class:`Terminal`. What does it need to set?
664664
:meth:`~object.__init__`
665665
The :term:`constructor` for :class:`Expression` assumes that an expression is
666666
defined by a series of operands. Terminals have an empty list of operands
667-
but do have something that other expressions lack, a value. In the case of
667+
but do have something that other expressions lack: a value. In the case of
668668
:class:`Number`, this is a number, while for :class:`Symbol` the value is a
669669
string (usually a single character). :class:`Terminal` therefore needs its
670670
own :meth:`__init__` which will take a value argument.
@@ -719,6 +719,24 @@ long as the right number of arguments are passed). A single dispatch function is
719719
not like this. Instead, calling a single function name causes different function
720720
code to execute, depending on the type of the first argument [#single]_.
721721

722+
:numref:`tree_evaluate` shows a single dispatch function for a visitor function
723+
which evaluates a :class:`Expression`. Start with lines 6-24. These define a
724+
function :func:`~example_code.expression_tools.evaluate` which will be used in
725+
the default case, that is, in the case where the :class:`type` of the first
726+
argument doesn't match any of the other implementations of
727+
:func:`~example_code.expression_tools.evaluate`. In this case, the first
728+
argument is the expression that we're evaluating, so if the type doesn't match
729+
then this means that we don't know how to evaluate this object, and the only
730+
course of action available is to throw an :term:`exception`.
731+
732+
The new feature that we haven't met before appears on line 5.
733+
:func:`functools.singledispatch` turns a function into
734+
a single dispatch function. The `@` symbol marks
735+
:func:`~functools.singledispatch` as a :term:`decorator`. We'll return to them
736+
in :numref:`decorators`. For the moment, we just need to know that
737+
`@singledispatch` turns the function it precedes into a single dispatch
738+
function.
739+
722740
.. _tree_evaluate:
723741

724742
.. code-block:: python3
@@ -743,7 +761,8 @@ code to execute, depending on the type of the first argument [#single]_.
743761
*o: numbers.Number
744762
The results of evaluating the operands of expr.
745763
**kwargs:
746-
Any keyword arguments required to evaluate specific types of expression.
764+
Any keyword arguments required to evaluate specific types of
765+
expression.
747766
symbol_map: dict
748767
A dictionary mapping Symbol names to numerical values, for example:
749768
@@ -787,46 +806,28 @@ code to execute, depending on the type of the first argument [#single]_.
787806
def _(expr, *o, **kwargs):
788807
return o[0] ** o[1]
789808
790-
:numref:`tree_evaluate` shows a single dispatch function for a visitor function
791-
which evaluates a :class:`Expression`. Start with lines 6-19. These define a
792-
function :func:`~example_code.expression_tools.evaluate` which will be used in
793-
the default case, that is, in the case where the :class:`type` of the first
794-
argument doesn't match any of the other implementations of
795-
:func:`~example_code.expression_tools.evaluate`. In this case, the first
796-
argument is the expression that we're evaluating, so if the type doesn't match
797-
then this means that we don't know how to evaluate this object, and the only
798-
course of action available is to throw an :term:`exception`.
799-
800-
The new feature that we haven't met before appears on line 5.
801-
:func:`functools.singledispatch` turns a function into
802-
a single dispatch function. The `@` symbol marks
803-
:func:`~functools.singledispatch` as a :term:`decorator`. We'll return to them
804-
in :numref:`decorators`. For the moment, we just need to know that
805-
`@singledispatch` turns the function it precedes into a single dispatch
806-
function.
807-
808809
Next we turn our attention to the implementation of evaluation for the different
809-
expression types. Look first at lines 26-28, which provide the evaluation of
810+
expression types. Look first at lines 27-29, which provide the evaluation of
810811
:class:`Number` nodes. The function body is trivial: the evaluation of a
811812
:class:`Number` is simply its value. The function interface is more interesting.
812813
Notice that the function name is given as `_`. This is the Python convention for
813814
a name which will never be used. This function will never be called by its
814-
declared name. Instead, look at the decorator on line 26. The single dispatch
815+
declared name. Instead, look at the decorator on line 27. The single dispatch
815816
function :func:`~example_code.expression_tools.evaluate` has a :term:`method`
816817
:meth:`register`. When used as a decorator, the :meth:`register` method of a
817818
single dispatch function registers the function that follows as implementation
818819
for the :keyword:`class` given as an argument to :meth:`register`. On this
819820
occasion, this is :class:`expressions.Number`.
820821

821-
Now look at lines 31-33. These contain the implementation of
822+
Now look at lines 32-34. These contain the implementation of
822823
:func:`~example_code.expression_tools.evaluate` for :class:`expressions.Symbol`.
823824
In order to evaluate a symbol, we depend on the mapping from symbol names to
824825
numerical values that has been passed in.
825826

826-
Finally, look at lines 36-38. These define the evaluation visitor for addition.
827+
Finally, look at lines 37-39. These define the evaluation visitor for addition.
827828
This works simply by adding the results of evaluating the two operands of
828-
:class:`expressions.Add`. The evaluation visitors for the other operators follow
829-
*mutatis mutandis*.
829+
:class:`expressions.Add`. The evaluation visitors for the other operators
830+
follow in an analogous manner.
830831

831832
An expanded tree visitor
832833
~~~~~~~~~~~~~~~~~~~~~~~~

‎example_code/expression_tools.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,13 @@ def postvisitor(expr, fn, **kwargs):
6868
The expression to be visited.
6969
fn: `function(node, *o, **kwargs)`
7070
A function to be applied at each node. The function should take the
71-
node to be visited as its first argument, and the results of visiting
72-
its operands as any further positional arguments. Any additional
73-
information that the visitor requires can be passed in as keyword
74-
arguments.
71+
node to be visited as its first argument, and the results of
72+
visiting its operands as any further positional arguments. Any
73+
additional information that the visitor requires can be passed in as
74+
keyword arguments.
7575
**kwargs:
7676
Any additional keyword arguments to be passed to fn.
7777
'''
78-
7978
return fn(expr,
8079
*(postvisitor(c, fn, **kwargs) for c in expr.operands),
8180
**kwargs)

0 commit comments

Comments
 (0)