Lichen

Change of docs/wiki/Design

861:f745d151a441
docs/wiki/Design
     1.1 --- a/docs/wiki/Design	Sat Jul 21 23:19:26 2018 +0200
     1.2 +++ b/docs/wiki/Design	Fri Aug 17 11:41:28 2018 +0200
     1.3 @@ -1,14 +1,28 @@
     1.4  = Design Decisions =
     1.5  
     1.6 -The Lichen language design involves some different choices to those taken in Python's design. Many of these choices are motivated by the following criteria:
     1.7 +The Lichen language design involves some different choices to those taken in
     1.8 +Python's design. Many of these choices are motivated by the following
     1.9 +criteria:
    1.10 +
    1.11 + * To simplify the language and to make what programs do easier to understand
    1.12 +   and to predict
    1.13 + * To make analysis of programs easier, particularly
    1.14 +   [[../Deduction|deductions]] about the nature of the code
    1.15 + * To simplify and otherwise reduce the [[../Representations|representations]]
    1.16 +   employed and the operations performed at run-time
    1.17  
    1.18 - * To simplify the language and to make what programs do easier to understand and to predict
    1.19 - * To make analysis of programs easier, particularly [[../Deduction|deductions]] about the nature of the code
    1.20 - * To simplify and otherwise reduce the [[../Representations|representations]] employed and the operations performed at run-time
    1.21 +Lichen is in many ways a restricted form of Python. In particular,
    1.22 +restrictions on the attribute names supported by each object help to clearly
    1.23 +define the object types in a program, allowing us to identify those objects
    1.24 +when they are used. Consequently, optimisations that can be employed in a
    1.25 +Lichen program become possible in situations where they would have been
    1.26 +difficult or demanding to employ in a Python program.
    1.27  
    1.28 -Lichen is in many ways a restricted form of Python. In particular, restrictions on the attribute names supported by each object help to clearly define the object types in a program, allowing us to identify those objects when they are used. Consequently, optimisations that can be employed in a Lichen program become possible in situations where they would have been difficult or demanding to employ in a Python program.
    1.29 -
    1.30 -Some design choices evoke memories of earlier forms of Python. Removing nested scopes simplifies the [[../Inspection|inspection]] of programs and run-time [[../Representations|representations]] and mechanisms. Other choices seek to remedy difficult or defective aspects of Python, notably the behaviour of Python's [[../Imports|import]] system.
    1.31 +Some design choices evoke memories of earlier forms of Python. Removing nested
    1.32 +scopes simplifies the [[../Inspection|inspection]] of programs and run-time
    1.33 +[[../Representations|representations]] and mechanisms. Other choices seek to
    1.34 +remedy difficult or defective aspects of Python, notably the behaviour of
    1.35 +Python's [[../Imports|import]] system.
    1.36  
    1.37  <<TableOfContents(2,3)>>
    1.38  
    1.39 @@ -32,7 +46,13 @@
    1.40  
    1.41  === Fixed Attribute Names ===
    1.42  
    1.43 -Attribute names are bound for classes through assignment in the class namespace, for modules in the module namespace, and for instances in methods through assignment to `self`. Class and instance attributes are propagated to descendant classes and instances of descendant classes respectively. Once bound, attributes can be modified, but new attributes cannot be bound by other means, such as the assignment of an attribute to an arbitrary object that would not already support such an attribute.
    1.44 +Attribute names are bound for classes through assignment in the class
    1.45 +namespace, for modules in the module namespace, and for instances in methods
    1.46 +through assignment to `self`. Class and instance attributes are propagated to
    1.47 +descendant classes and instances of descendant classes respectively. Once
    1.48 +bound, attributes can be modified, but new attributes cannot be bound by other
    1.49 +means, such as the assignment of an attribute to an arbitrary object that
    1.50 +would not already support such an attribute.
    1.51  
    1.52  {{{#!python numbers=disable
    1.53  class C:
    1.54 @@ -44,7 +64,10 @@
    1.55  C().y = 567 # not allowed (y not bound for C instances)
    1.56  }}}
    1.57  
    1.58 -Permitting the addition of attributes to objects would then require that such addition attempts be associated with particular objects, leading to a potentially iterative process involving object type deduction and modification, also causing imprecise results.
    1.59 +Permitting the addition of attributes to objects would then require that such
    1.60 +addition attempts be associated with particular objects, leading to a
    1.61 +potentially iterative process involving object type deduction and
    1.62 +modification, also causing imprecise results.
    1.63  
    1.64  === No Shadowing ===
    1.65  
    1.66 @@ -57,11 +80,15 @@
    1.67          self.a = 234 # not allowed (attribute shadows class attribute)
    1.68  }}}
    1.69  
    1.70 -Permitting this would oblige instances to support attributes that, when missing, are provided by consulting their classes but, when not missing, may also be provided directly by the instances themselves.
    1.71 +Permitting this would oblige instances to support attributes that, when
    1.72 +missing, are provided by consulting their classes but, when not missing, may
    1.73 +also be provided directly by the instances themselves.
    1.74  
    1.75  === No Dynamic Attributes ===
    1.76  
    1.77 -Instance attributes cannot be provided dynamically, such that any missing attribute would be supplied by a special method call to determine the attribute's presence and to retrieve its value.
    1.78 +Instance attributes cannot be provided dynamically, such that any missing
    1.79 +attribute would be supplied by a special method call to determine the
    1.80 +attribute's presence and to retrieve its value.
    1.81  
    1.82  {{{#!python numbers=disable
    1.83  class C:
    1.84 @@ -70,31 +97,41 @@
    1.85              return 123
    1.86  }}}
    1.87  
    1.88 -Permitting this would require object types to potentially support any attribute, undermining attempts to use attributes to identify objects.
    1.89 +Permitting this would require object types to potentially support any
    1.90 +attribute, undermining attempts to use attributes to identify objects.
    1.91  
    1.92  == Naming ==
    1.93  
    1.94  {{{#!table
    1.95  '''Lichen''' || '''Python''' || '''Rationale'''
    1.96  ==
    1.97 -Names may be local, global or built-in: nested namespaces must be initialised explicitly
    1.98 +Names may be local, global or built-in: nested namespaces must be initialised
    1.99 +explicitly
   1.100  || Names may also be non-local, permitting closures
   1.101  || Limited name scoping simplifies program inspection and run-time mechanisms
   1.102  ==
   1.103  `self` is a reserved name and is optional in method parameter lists
   1.104 -|| `self` is a naming convention, but the first method parameter must always refer to the accessed object
   1.105 -|| Reserving `self` assists deduction; making it optional is a consequence of the method binding behaviour
   1.106 +|| `self` is a naming convention, but the first method parameter must always
   1.107 +.. refer to the accessed object
   1.108 +|| Reserving `self` assists deduction; making it optional is a consequence of
   1.109 +.. the method binding behaviour
   1.110  ==
   1.111  Instance attributes can be initialised using `.name` parameter notation
   1.112 -|| [[https://stackoverflow.com/questions/1389180/automatically-initialize-instance-variables|Workarounds]] involving decorators and introspection are required for similar brevity
   1.113 +|| [[https://stackoverflow.com/questions/1389180/automatically-initialize-instance-variables|Workarounds]]
   1.114 +.. involving decorators and introspection are required for similar brevity
   1.115  || Initialiser notation eliminates duplication in program code and is convenient
   1.116  }}}
   1.117  
   1.118  === Traditional Local, Global and Built-In Scopes Only ===
   1.119  
   1.120 -Namespaces reside within a hierarchy within modules: classes containing classes or functions; functions containing other functions. Built-in names are exposed in all namespaces, global names are defined at the module level and are exposed in all namespaces within the module, locals are confined to the namespace in which they are defined.
   1.121 +Namespaces reside within a hierarchy within modules: classes containing
   1.122 +classes or functions; functions containing other functions. Built-in names are
   1.123 +exposed in all namespaces, global names are defined at the module level and
   1.124 +are exposed in all namespaces within the module, locals are confined to the
   1.125 +namespace in which they are defined.
   1.126  
   1.127 -However, locals are not inherited by namespaces from surrounding or enclosing namespaces.
   1.128 +However, locals are not inherited by namespaces from surrounding or enclosing
   1.129 +namespaces.
   1.130  
   1.131  {{{#!python numbers=disable
   1.132  def f(x):
   1.133 @@ -108,11 +145,16 @@
   1.134      return i
   1.135  }}}
   1.136  
   1.137 -Needing to access outer namespaces in order to access any referenced names complicates the way in which such dynamic namespaces would need to be managed. Although the default initialisation technique demonstrated above could be automated, explicit initialisation makes programs easier to follow and avoids mistakes involving globals having the same name.
   1.138 +Needing to access outer namespaces in order to access any referenced names
   1.139 +complicates the way in which such dynamic namespaces would need to be managed.
   1.140 +Although the default initialisation technique demonstrated above could be
   1.141 +automated, explicit initialisation makes programs easier to follow and avoids
   1.142 +mistakes involving globals having the same name.
   1.143  
   1.144  === Reserved Self ===
   1.145  
   1.146 -The `self` name can be omitted in method signatures, but in methods it is always initialised to the instance on which the method is operating.
   1.147 +The `self` name can be omitted in method signatures, but in methods it is
   1.148 +always initialised to the instance on which the method is operating.
   1.149  
   1.150  {{{#!python numbers=disable
   1.151  class C:
   1.152 @@ -120,11 +162,18 @@
   1.153          self.x = y # self is the instance
   1.154  }}}
   1.155  
   1.156 -The assumption in methods is that `self` must always be referring to an instance of the containing class or of a descendant class. This means that `self` cannot be initialised to another kind of value, which Python permits through the explicit invocation of a method with the inclusion of the affected instance as the first argument. Consequently, `self` becomes optional in the signature because it is not assigned in the same way as the other parameters.
   1.157 +The assumption in methods is that `self` must always be referring to an
   1.158 +instance of the containing class or of a descendant class. This means that
   1.159 +`self` cannot be initialised to another kind of value, which Python permits
   1.160 +through the explicit invocation of a method with the inclusion of the affected
   1.161 +instance as the first argument. Consequently, `self` becomes optional in the
   1.162 +signature because it is not assigned in the same way as the other parameters.
   1.163  
   1.164  === Instance Attribute Initialisers ===
   1.165  
   1.166 -In parameter lists, a special notation can be used to indicate that the given name is an instance attribute that will be assigned the argument value corresponding to the parameter concerned.
   1.167 +In parameter lists, a special notation can be used to indicate that the given
   1.168 +name is an instance attribute that will be assigned the argument value
   1.169 +corresponding to the parameter concerned.
   1.170  
   1.171  {{{#!python numbers=disable
   1.172  class C:
   1.173 @@ -132,7 +181,10 @@
   1.174          self.c = c # a traditional assignment using a parameter
   1.175  }}}
   1.176  
   1.177 -To use the notation, such dot-qualified parameters must appear only in the parameter lists of methods, not plain functions. The qualified parameters are represented as locals having the same name, and assignments to the corresponding instance attributes are inserted into the generated code.
   1.178 +To use the notation, such dot-qualified parameters must appear only in the
   1.179 +parameter lists of methods, not plain functions. The qualified parameters are
   1.180 +represented as locals having the same name, and assignments to the
   1.181 +corresponding instance attributes are inserted into the generated code.
   1.182  
   1.183  {{{#!python numbers=disable
   1.184  class C:
   1.185 @@ -147,7 +199,9 @@
   1.186          pass
   1.187  }}}
   1.188  
   1.189 -Naturally, `self`, being a reserved name in methods, can also be omitted from such parameter lists. Moreover, such initialising parameters can have default values.
   1.190 +Naturally, `self`, being a reserved name in methods, can also be omitted from
   1.191 +such parameter lists. Moreover, such initialising parameters can have default
   1.192 +values.
   1.193  
   1.194  {{{#!python numbers=disable
   1.195  class C:
   1.196 @@ -165,9 +219,13 @@
   1.197  {{{#!table
   1.198  '''Lichen''' || '''Python''' || '''Rationale'''
   1.199  ==
   1.200 -Class attributes are propagated to class hierarchy members during initialisation: rebinding class attributes does not affect descendant class attributes
   1.201 -|| Class attributes are propagated live to class hierarchy members and must be looked up by the run-time system if not provided by a given class
   1.202 -|| Initialisation-time propagation simplifies access operations and attribute table storage
   1.203 +Class attributes are propagated to class hierarchy members during
   1.204 +initialisation: rebinding class attributes does not affect descendant class
   1.205 +attributes
   1.206 +|| Class attributes are propagated live to class hierarchy members and must be
   1.207 +.. looked up by the run-time system if not provided by a given class
   1.208 +|| Initialisation-time propagation simplifies access operations and attribute
   1.209 +.. table storage
   1.210  ==
   1.211  Unbound methods must be bound using a special function taking an instance
   1.212  || Unbound methods may be called using an instance as first argument
   1.213 @@ -175,20 +233,24 @@
   1.214  ==
   1.215  Functions assigned to class attributes do not become unbound methods
   1.216  || Functions assigned to class attributes become unbound methods
   1.217 -|| Removing method assignment simplifies deduction: methods are always defined in place
   1.218 +|| Removing method assignment simplifies deduction: methods are always defined
   1.219 +.. in place
   1.220  ==
   1.221  Base classes must be well-defined
   1.222  || Base classes may be expressions
   1.223 -|| Well-defined base classes are required to establish a well-defined hierarchy of types
   1.224 +|| Well-defined base classes are required to establish a well-defined
   1.225 +.. hierarchy of types
   1.226  ==
   1.227  Classes may not be defined in functions
   1.228  || Classes may be defined in any kind of namespace
   1.229 -|| Forbidding classes in functions prevents the definition of countless class variants that are awkward to analyse
   1.230 +|| Forbidding classes in functions prevents the definition of countless class
   1.231 +.. variants that are awkward to analyse
   1.232  }}}
   1.233  
   1.234  === Inherited Class Attributes ===
   1.235  
   1.236 -Class attributes that are changed for a class do not change for that class's descendants.
   1.237 +Class attributes that are changed for a class do not change for that class's
   1.238 +descendants.
   1.239  
   1.240  {{{#!python numbers=disable
   1.241  class C:
   1.242 @@ -201,11 +263,20 @@
   1.243  print D.a # remains 123 in Lichen, becomes 456 in Python
   1.244  }}}
   1.245  
   1.246 -Permitting this requires indirection for all class attributes, requiring them to be treated differently from other kinds of attributes. Meanwhile, class attribute rebinding and the accessing of inherited attributes changed in this way is relatively rare.
   1.247 +Permitting this requires indirection for all class attributes, requiring them
   1.248 +to be treated differently from other kinds of attributes. Meanwhile, class
   1.249 +attribute rebinding and the accessing of inherited attributes changed in this
   1.250 +way is relatively rare.
   1.251  
   1.252  === Unbound Methods ===
   1.253  
   1.254 -Methods are defined on classes but are only available via instances: they are instance methods. Consequently, acquiring a method directly from a class and then invoking it should fail because the method will be unbound: the "context" of the method is not an instance. Furthermore, the Python technique of supplying an instance as the first argument in an invocation to bind the method to an instance, thus setting the context of the method, is not supported. See [[#ReservedSelf|"Reserved Self"]] for more information.
   1.255 +Methods are defined on classes but are only available via instances: they are
   1.256 +instance methods. Consequently, acquiring a method directly from a class and
   1.257 +then invoking it should fail because the method will be unbound: the "context"
   1.258 +of the method is not an instance. Furthermore, the Python technique of
   1.259 +supplying an instance as the first argument in an invocation to bind the
   1.260 +method to an instance, thus setting the context of the method, is not
   1.261 +supported. See [[#Reserved Self|"Reserved Self"]] for more information.
   1.262  
   1.263  {{{#!python numbers=disable
   1.264  class C:
   1.265 @@ -217,13 +288,24 @@
   1.266          get_using(C.f, self)(123) # binds C.f to self, then the result is called
   1.267  }}}
   1.268  
   1.269 -Binding methods to instances occurs when acquiring methods via instances or explicitly using the `get_using` built-in. The built-in checks the compatibility of the supplied method and instance. If compatible, it provides the bound method as its result.
   1.270 +Binding methods to instances occurs when acquiring methods via instances or
   1.271 +explicitly using the `get_using` built-in. The built-in checks the
   1.272 +compatibility of the supplied method and instance. If compatible, it provides
   1.273 +the bound method as its result.
   1.274  
   1.275 -Normal functions are callable without any further preparation, whereas unbound methods need the binding step to be performed and are not immediately callable. Were functions to become unbound methods upon assignment to a class attribute, they would need to be invalidated by having the preparation mechanism enabled on them. However, this invalidation would only be relevant to the specific case of assigning functions to classes and this would need to be tested for. Given the added complications, such functionality is arguably not worth supporting.
   1.276 +Normal functions are callable without any further preparation, whereas unbound
   1.277 +methods need the binding step to be performed and are not immediately
   1.278 +callable. Were functions to become unbound methods upon assignment to a class
   1.279 +attribute, they would need to be invalidated by having the preparation
   1.280 +mechanism enabled on them. However, this invalidation would only be relevant
   1.281 +to the specific case of assigning functions to classes and this would need to
   1.282 +be tested for. Given the added complications, such functionality is arguably
   1.283 +not worth supporting.
   1.284  
   1.285  === Assigning Functions to Class Attributes ===
   1.286  
   1.287 -Functions can be assigned to class attributes but do not become unbound methods as a result.
   1.288 +Functions can be assigned to class attributes but do not become unbound
   1.289 +methods as a result.
   1.290  
   1.291  {{{#!python numbers=disable
   1.292  class C:
   1.293 @@ -238,11 +320,18 @@
   1.294  C().f(123) # permitted: f has merely been exposed via C.f
   1.295  }}}
   1.296  
   1.297 -Methods are identified as such by their definition location, they contribute information about attributes to the class hierarchy, and they employ certain structure details at run-time to permit the binding of methods. Since functions can defined in arbitrary locations, no class hierarchy information is available, and a function could combine `self` with a range of attributes that are not compatible with any class to which the function might be assigned.
   1.298 +Methods are identified as such by their definition location, they contribute
   1.299 +information about attributes to the class hierarchy, and they employ certain
   1.300 +structure details at run-time to permit the binding of methods. Since
   1.301 +functions can defined in arbitrary locations, no class hierarchy information
   1.302 +is available, and a function could combine `self` with a range of attributes
   1.303 +that are not compatible with any class to which the function might be
   1.304 +assigned.
   1.305  
   1.306  === Well-Defined Base Classes ===
   1.307  
   1.308 -Base classes must be clearly identifiable as well-defined classes. This facilitates the cataloguing of program objects and further analysis on them.
   1.309 +Base classes must be clearly identifiable as well-defined classes. This
   1.310 +facilitates the cataloguing of program objects and further analysis on them.
   1.311  
   1.312  {{{#!python numbers=disable
   1.313  class C:
   1.314 @@ -255,11 +344,19 @@
   1.315      pass
   1.316  }}}
   1.317  
   1.318 -If base class identification could only be done reliably at run-time, class relationship information would be very limited without running the program or performing costly and potentially unreliable analysis. Indeed, programs employing such dynamic base classes are arguably resistant to analysis, which is contrary to the goals of a language like Lichen.
   1.319 +If base class identification could only be done reliably at run-time, class
   1.320 +relationship information would be very limited without running the program or
   1.321 +performing costly and potentially unreliable analysis. Indeed, programs
   1.322 +employing such dynamic base classes are arguably resistant to analysis, which
   1.323 +is contrary to the goals of a language like Lichen.
   1.324  
   1.325  === Class Definitions and Functions ===
   1.326  
   1.327 -Classes may not be defined in functions because functions provide dynamic namespaces, but Lichen relies on a static namespace hierarchy in order to clearly identify the principal objects in a program. If classes could be defined in functions, despite seemingly providing the same class over and over again on every invocation, a family of classes would, in fact, be defined.
   1.328 +Classes may not be defined in functions because functions provide dynamic
   1.329 +namespaces, but Lichen relies on a static namespace hierarchy in order to
   1.330 +clearly identify the principal objects in a program. If classes could be
   1.331 +defined in functions, despite seemingly providing the same class over and over
   1.332 +again on every invocation, a family of classes would, in fact, be defined.
   1.333  
   1.334  {{{#!python numbers=disable
   1.335  def f(x):
   1.336 @@ -268,7 +365,9 @@
   1.337      return f
   1.338  }}}
   1.339  
   1.340 -Moreover, issues of namespace nesting also arise, since the motivation for defining classes in functions would surely be to take advantage of local state to parameterise such classes.
   1.341 +Moreover, issues of namespace nesting also arise, since the motivation for
   1.342 +defining classes in functions would surely be to take advantage of local state
   1.343 +to parameterise such classes.
   1.344  
   1.345  == Modules and Packages ==
   1.346  
   1.347 @@ -276,25 +375,33 @@
   1.348  '''Lichen''' || '''Python''' || '''Rationale'''
   1.349  ==
   1.350  Modules are independent: package hierarchies are not traversed when importing
   1.351 -|| Modules exist in hierarchical namespaces: package roots must be imported before importing specific submodules
   1.352 -|| Eliminating module traversal permits more precise imports and reduces superfluous code
   1.353 +|| Modules exist in hierarchical namespaces: package roots must be imported
   1.354 +.. before importing specific submodules
   1.355 +|| Eliminating module traversal permits more precise imports and reduces
   1.356 +.. superfluous code
   1.357  ==
   1.358 -Only specific names can be imported from a module or package using the `from` statement
   1.359 +Only specific names can be imported from a module or package using the `from`
   1.360 +statement
   1.361  || Importing "all" from a package or module is permitted
   1.362 -|| Eliminating "all" imports simplifies the task of determining where names in use have come from
   1.363 +|| Eliminating "all" imports simplifies the task of determining where names in
   1.364 +.. use have come from
   1.365  ==
   1.366  Modules must be specified using absolute names
   1.367  || Imports can be absolute or relative
   1.368  || Using only absolute names simplifies the import mechanism
   1.369  ==
   1.370 -Modules are imported independently and their dependencies subsequently resolved
   1.371 +Modules are imported independently and their dependencies subsequently
   1.372 +resolved
   1.373  || Modules are imported as import statements are encountered
   1.374 -|| Statically-initialised objects can be used declaratively, although an initialisation order may still need establishing
   1.375 +|| Statically-initialised objects can be used declaratively, although an
   1.376 +.. initialisation order may still need establishing
   1.377  }}}
   1.378  
   1.379  === Independent Modules ===
   1.380  
   1.381 -The inclusion of modules in a program affects only explicitly-named modules: they do not have relationships implied by their naming that would cause such related modules to be included in a program.
   1.382 +The inclusion of modules in a program affects only explicitly-named modules:
   1.383 +they do not have relationships implied by their naming that would cause such
   1.384 +related modules to be included in a program.
   1.385  
   1.386  {{{#!python numbers=disable
   1.387  from compiler import consts # defines consts
   1.388 @@ -305,11 +412,15 @@
   1.389  consts # is defined
   1.390  }}}
   1.391  
   1.392 -Where modules should have relationships, they should be explicitly defined using `from` and `import` statements which target the exact modules required. In the above example, `compiler` is not routinely imported because modules within the `compiler` package have been requested.
   1.393 +Where modules should have relationships, they should be explicitly defined
   1.394 +using `from` and `import` statements which target the exact modules required.
   1.395 +In the above example, `compiler` is not routinely imported because modules
   1.396 +within the `compiler` package have been requested.
   1.397  
   1.398  === Specific Name Imports Only ===
   1.399  
   1.400 -Lichen, unlike Python, also does not support the special `__all__` module attribute.
   1.401 +Lichen, unlike Python, also does not support the special `__all__` module
   1.402 +attribute.
   1.403  
   1.404  {{{#!python numbers=disable
   1.405  from compiler import * # not permitted
   1.406 @@ -318,11 +429,22 @@
   1.407  interpreter # undefined in compiler (yet it might be thought to reside there) and in this module
   1.408  }}}
   1.409  
   1.410 -The `__all__` attribute supports `from ... import *` statements in Python, but without identifying the module or package involved and then consulting `__all__` in that module or package to discover which names might be involved (which might require the inspection of yet other modules or packages), the names imported cannot be known. Consequently, some names used elsewhere in the module performing the import might be assumed to be imported names when, in fact, they are unknown in both the importing and imported modules. Such uncertainty hinders the inspection of individual modules.
   1.411 +The `__all__` attribute supports `from ... import *` statements in Python, but
   1.412 +without identifying the module or package involved and then consulting
   1.413 +`__all__` in that module or package to discover which names might be involved
   1.414 +(which might require the inspection of yet other modules or packages), the
   1.415 +names imported cannot be known. Consequently, some names used elsewhere in the
   1.416 +module performing the import might be assumed to be imported names when, in
   1.417 +fact, they are unknown in both the importing and imported modules. Such
   1.418 +uncertainty hinders the inspection of individual modules.
   1.419  
   1.420  === Modules Imported Independently ===
   1.421  
   1.422 -When indicating an import using the `from` and `import` statements, the [[../Toolchain|toolchain]] does not attempt to immediately import other modules. Instead, the imports act as declarations of such other modules or names from other modules, resolved at a later stage. This permits mutual imports to a greater extent than in Python.
   1.423 +When indicating an import using the `from` and `import` statements, the
   1.424 +[[../Toolchain|toolchain]] does not attempt to immediately import other
   1.425 +modules. Instead, the imports act as declarations of such other modules or
   1.426 +names from other modules, resolved at a later stage. This permits mutual
   1.427 +imports to a greater extent than in Python.
   1.428  
   1.429  {{{#!python numbers=disable
   1.430  # Module M
   1.431 @@ -344,7 +466,10 @@
   1.432  import N
   1.433  }}}
   1.434  
   1.435 -Such flexibility is not usually needed, and circular importing usually indicates issues with program organisation. However, declarative imports can help to decouple modules and avoid combining import declaration and module initialisation order concerns.
   1.436 +Such flexibility is not usually needed, and circular importing usually
   1.437 +indicates issues with program organisation. However, declarative imports can
   1.438 +help to decouple modules and avoid combining import declaration and module
   1.439 +initialisation order concerns.
   1.440  
   1.441  == Syntax and Control-Flow ==
   1.442  
   1.443 @@ -353,11 +478,14 @@
   1.444  ==
   1.445  If expressions and comprehensions are not supported
   1.446  || If expressions and comprehensions are supported
   1.447 -|| Omitting such syntactic features simplifies program inspection and translation
   1.448 +|| Omitting such syntactic features simplifies program inspection and
   1.449 +.. translation
   1.450  ==
   1.451  The `with` statement is not supported
   1.452 -|| The `with` statement offers a mechanism for resource allocation and deallocation using context managers
   1.453 -|| This syntactic feature can be satisfactorily emulated using existing constructs
   1.454 +|| The `with` statement offers a mechanism for resource allocation and
   1.455 +.. deallocation using context managers
   1.456 +|| This syntactic feature can be satisfactorily emulated using existing
   1.457 +.. constructs
   1.458  ==
   1.459  Generators are not supported
   1.460  || Generators are supported
   1.461 @@ -369,12 +497,16 @@
   1.462  ==
   1.463  All parameters must be specified
   1.464  || Catch-all parameters (`*` and `**`) are supported
   1.465 -|| Omitting catch-all parameter population simplifies generic invocation handling
   1.466 +|| Omitting catch-all parameter population simplifies generic invocation
   1.467 +.. handling
   1.468  }}}
   1.469  
   1.470  === No If Expressions or Comprehensions ===
   1.471  
   1.472 -In order to support the classic [[WikiPedia:?:|ternary operator]], a construct was [[https://www.python.org/dev/peps/pep-0308/|added]] to the Python syntax that needed to avoid problems with the existing grammar and notation. Unfortunately, it reorders the components from the traditional form:
   1.473 +In order to support the classic [[WikiPedia:?:|ternary operator]], a construct
   1.474 +was [[https://www.python.org/dev/peps/pep-0308/|added]] to the Python syntax
   1.475 +that needed to avoid problems with the existing grammar and notation.
   1.476 +Unfortunately, it reorders the components from the traditional form:
   1.477  
   1.478  {{{#!python numbers=disable
   1.479  # Not valid in Lichen, only in Python.
   1.480 @@ -386,7 +518,9 @@
   1.481  true_result if (inner_true_result if condition else inner_false_result) else false_result
   1.482  }}}
   1.483  
   1.484 -Since if expressions may participate within expressions, they cannot be rewritten as if statements. Nor can they be rewritten as logical operator chains in general.
   1.485 +Since if expressions may participate within expressions, they cannot be
   1.486 +rewritten as if statements. Nor can they be rewritten as logical operator
   1.487 +chains in general.
   1.488  
   1.489  {{{#!python numbers=disable
   1.490  # Not valid in Lichen, only in Python.
   1.491 @@ -399,9 +533,17 @@
   1.492  a = x and 0 or 1 # not valid
   1.493  }}}
   1.494  
   1.495 -But in any case, it would be more of a motivation to support the functionality if a better syntax could be adopted instead. However, if expressions are not particularly important in Python, and despite enhancement requests over many years, everybody managed to live without them.
   1.496 +But in any case, it would be more of a motivation to support the functionality
   1.497 +if a better syntax could be adopted instead. However, if expressions are not
   1.498 +particularly important in Python, and despite enhancement requests over many
   1.499 +years, everybody managed to live without them.
   1.500  
   1.501 -List and generator comprehensions are more complicated but share some characteristics of if expressions: their syntax contradicts the typical conventions established by the rest of the Python language; they create implicit state that is perhaps most appropriately modelled by a separate function or similar object. Since Lichen does not support generators at all, it will obviously not support generator expressions.
   1.502 +List and generator comprehensions are more complicated but share some
   1.503 +characteristics of if expressions: their syntax contradicts the typical
   1.504 +conventions established by the rest of the Python language; they create
   1.505 +implicit state that is perhaps most appropriately modelled by a separate
   1.506 +function or similar object. Since Lichen does not support generators at all,
   1.507 +it will obviously not support generator expressions.
   1.508  
   1.509  Meanwhile, list comprehensions quickly encourage barely-readable programs:
   1.510  
   1.511 @@ -412,11 +554,21 @@
   1.512  a = [z for y in x if y for z in y if z]
   1.513  }}}
   1.514  
   1.515 -Supporting the creation of temporary functions to produce list comprehensions, while also hiding temporary names from the enclosing scope, adds complexity to the toolchain for situations where programmers would arguably be better creating their own functions and thus writing more readable programs.
   1.516 +Supporting the creation of temporary functions to produce list comprehensions,
   1.517 +while also hiding temporary names from the enclosing scope, adds complexity to
   1.518 +the toolchain for situations where programmers would arguably be better
   1.519 +creating their own functions and thus writing more readable programs.
   1.520  
   1.521  === No With Statement ===
   1.522  
   1.523 -The [[https://docs.python.org/2.7/reference/compound_stmts.html#the-with-statement|with statement]] introduced the concept of [[https://docs.python.org/2.7/reference/datamodel.html#context-managers|context managers]] in Python 2.5, with such objects supporting a [[https://docs.python.org/2.7/library/stdtypes.html#typecontextmanager|programming interface]] that aims to formalise certain conventions around resource management. For example:
   1.524 +The
   1.525 +[[https://docs.python.org/2.7/reference/compound_stmts.html#the-with-statement|with
   1.526 +statement]] introduced the concept of
   1.527 +[[https://docs.python.org/2.7/reference/datamodel.html#context-managers|context
   1.528 +managers]] in Python 2.5, with such objects supporting a
   1.529 +[[https://docs.python.org/2.7/library/stdtypes.html#typecontextmanager|programming
   1.530 +interface]] that aims to formalise certain conventions around resource
   1.531 +management. For example:
   1.532  
   1.533  {{{#!python numbers=disable
   1.534  # Not valid in Lichen, only in Python.
   1.535 @@ -426,7 +578,11 @@
   1.536          cursor.execute(query, args)
   1.537  }}}
   1.538  
   1.539 -Although this makes for readable code, it must be supported by objects which define the `__enter__` and `__exit__` special methods. Here, the `connect` method invoked in the first `with` statement must return such an object; similarly, the `cursor` method must also provide an object with such characteristics.
   1.540 +Although this makes for readable code, it must be supported by objects which
   1.541 +define the `__enter__` and `__exit__` special methods. Here, the `connect`
   1.542 +method invoked in the first `with` statement must return such an object;
   1.543 +similarly, the `cursor` method must also provide an object with such
   1.544 +characteristics.
   1.545  
   1.546  However, the "pre-with" solution is as follows:
   1.547  
   1.548 @@ -442,11 +598,23 @@
   1.549      connection.close()
   1.550  }}}
   1.551  
   1.552 -Although this seems less readable, its behaviour is more obvious because magic methods are not being called implicitly. Moreover, any parameterisation of the acts of resource deallocation or closure can be done in the `finally` clauses where such parameterisation would seem natural, rather than being specified through some kind of context manager initialisation arguments that must then be propagated to the magic methods so that they may take into consideration contextual information that is readily available in the place where the actual resource operations are being performed.
   1.553 +Although this seems less readable, its behaviour is more obvious because magic
   1.554 +methods are not being called implicitly. Moreover, any parameterisation of the
   1.555 +acts of resource deallocation or closure can be done in the `finally` clauses
   1.556 +where such parameterisation would seem natural, rather than being specified
   1.557 +through some kind of context manager initialisation arguments that must then
   1.558 +be propagated to the magic methods so that they may take into consideration
   1.559 +contextual information that is readily available in the place where the actual
   1.560 +resource operations are being performed.
   1.561  
   1.562  === No Generators ===
   1.563  
   1.564 -[[https://www.python.org/dev/peps/pep-0255/|Generators]] were [[https://docs.python.org/release/2.3/whatsnew/section-generators.html|added]] to Python in the 2.2 release and became fully part of the language in the 2.3 release. They offer a convenient way of writing iterator-like objects, capturing execution state instead of obliging the programmer to manage such state explicitly.
   1.565 +[[https://www.python.org/dev/peps/pep-0255/|Generators]] were
   1.566 +[[https://docs.python.org/release/2.3/whatsnew/section-generators.html|added]]
   1.567 +to Python in the 2.2 release and became fully part of the language in the 2.3
   1.568 +release. They offer a convenient way of writing iterator-like objects,
   1.569 +capturing execution state instead of obliging the programmer to manage such
   1.570 +state explicitly.
   1.571  
   1.572  {{{#!python numbers=disable
   1.573  # Not valid in Lichen, only in Python.
   1.574 @@ -477,11 +645,20 @@
   1.575      i += 1
   1.576  }}}
   1.577  
   1.578 -However, generators make additional demands on the mechanisms provided to support program execution. The encapsulation of the above example generator in a separate class illustrates the need for state that persists outside the execution of the routine providing the generator's results. Generators may look like functions, but they do not necessarily behave like them, leading to potential misunderstandings about their operation even if the code is superficially tidy and concise.
   1.579 +However, generators make additional demands on the mechanisms provided to
   1.580 +support program execution. The encapsulation of the above example generator in
   1.581 +a separate class illustrates the need for state that persists outside the
   1.582 +execution of the routine providing the generator's results. Generators may
   1.583 +look like functions, but they do not necessarily behave like them, leading to
   1.584 +potential misunderstandings about their operation even if the code is
   1.585 +superficially tidy and concise.
   1.586  
   1.587  === Positional and Keyword Arguments Only ===
   1.588  
   1.589 -When invoking callables, only positional arguments and keyword arguments can be used. Python also supports `*` and `**` arguments which respectively unpack sequences and mappings into the argument list, filling the list with sequence items (using `*`) and keywords (using `**`).
   1.590 +When invoking callables, only positional arguments and keyword arguments can
   1.591 +be used. Python also supports `*` and `**` arguments which respectively unpack
   1.592 +sequences and mappings into the argument list, filling the list with sequence
   1.593 +items (using `*`) and keywords (using `**`).
   1.594  
   1.595  {{{#!python numbers=disable
   1.596  def f(a, b, c, d):
   1.597 @@ -494,11 +671,15 @@
   1.598  f(2, 4, **m) # not permitted
   1.599  }}}
   1.600  
   1.601 -While convenient, such "unpacking" arguments obscure the communication between callables and undermine the safety provided by function and method signatures. They also require run-time support for the unpacking operations.
   1.602 +While convenient, such "unpacking" arguments obscure the communication between
   1.603 +callables and undermine the safety provided by function and method signatures.
   1.604 +They also require run-time support for the unpacking operations.
   1.605  
   1.606  === Positional Parameters Only ===
   1.607  
   1.608 -Similarly, signatures may only contain named parameters that correspond to arguments. Python supports `*` and `**` in parameter lists, too, which respectively accumulate superfluous positional and keyword arguments.
   1.609 +Similarly, signatures may only contain named parameters that correspond to
   1.610 +arguments. Python supports `*` and `**` in parameter lists, too, which
   1.611 +respectively accumulate superfluous positional and keyword arguments.
   1.612  
   1.613  {{{#!python numbers=disable
   1.614  def f(a, b, *args, **kw): # not permitted
   1.615 @@ -508,4 +689,11 @@
   1.616  f(1, 2, c=3, d=4)
   1.617  }}}
   1.618  
   1.619 -Such accumulation parameters can be useful for collecting arbitrary data and applying some of it within a callable. However, they can easily proliferate throughout a system and allow erroneous data to propagate far from its origin because such parameters permit the deferral of validation until the data needs to be accessed. Again, run-time support is required to marshal arguments into the appropriate parameter of this nature, but programmers could just write functions and methods that employ general sequence and mapping parameters explicitly instead.
   1.620 +Such accumulation parameters can be useful for collecting arbitrary data and
   1.621 +applying some of it within a callable. However, they can easily proliferate
   1.622 +throughout a system and allow erroneous data to propagate far from its origin
   1.623 +because such parameters permit the deferral of validation until the data needs
   1.624 +to be accessed. Again, run-time support is required to marshal arguments into
   1.625 +the appropriate parameter of this nature, but programmers could just write
   1.626 +functions and methods that employ general sequence and mapping parameters
   1.627 +explicitly instead.