diff --git a/README.rst b/README.rst index 089383c..474202a 100644 --- a/README.rst +++ b/README.rst @@ -134,7 +134,7 @@ The ``FactBaseBulider`` provides a decorator that registers the predicate class with the builder. Once a predicate class is registered the builder will use this class to try and unify against Clingo symbols. It also ensures that the fact base is built with the appropriate indexes as specified by ``index=True`` for -the field. The the example, the ``driver`` field is indexed allowing for faster +the field. In the example, the ``driver`` field is indexed allowing for faster queries when searching for specific drivers. As with a traditional database indexing improves query performance but should be used sparingly. @@ -158,11 +158,14 @@ Next we generate a problem instance by generating a lists of ``Driver`` and items = [ Item(name="item{}".format(i)) for i in range(1,6) ] instance = FactBase(drivers + items) -The ``Driver`` and ``Item`` constructors require named parameters that match the -declared field names; you cannot use "normal" Python list arguments. +The ``Driver`` and ``Item`` constructors use named parameters that match the +declared field names. Note: while you can use positional arguments to initialise +instances, doing so will potentially make the code harder to refactor. So in +general you should avoid using positional arguments except for a few cases (eg., +simple pairs where the order is unlikely to change). -Now, the facts can now be added to the control object and the combined ASP -program grounded. +These facts can now be added to the control object and the combined ASP program +grounded. .. code-block:: python @@ -170,8 +173,8 @@ program grounded. ctrl.ground([("base",[])]) Next we run the solver to generate solutions. The solver is run with a callback -function that is called each time a solution is found. Note: the solution of an -ASP program is typically called an *answer set* or simply a *model*. +function that is called each time a solution (technically an *answer set* or +simply a *model*) is found. .. code-block:: python @@ -254,11 +257,10 @@ use Clorm see the `documentation `_. Other Clorm Features -------------------- -The ORM interface is the heart of Clorm. However, beyond the basics outlined -above there are other useful features that build on the ORM interface. These -include: +Beyond the basic features outlined above there are many other features of the +Clorm library. These include: -* You can define new sub-classes of ``RawField`` for specific data +* You can define new sub-classes of ``RawField`` for custom data conversions. For example, you can define a ``DateField`` that represents dates in clingo in YYYY-MM-DD format and then use it in a predicate definition. @@ -298,10 +300,10 @@ include: * Field definitions can be specified as part of a function signature to perform automatic type conversion for writing Python functions that can be called from - an ASP program using @-syntax. + an ASP program using the @-syntax. Here function ``add`` is decorated with an automatic data conversion signature - to add two integers and return the resulting integer. + that accepts two input integers and expects an output integer. .. code-block:: python @@ -312,13 +314,16 @@ include: f(@add(5,6)). % grounds to f(11). -* Function signatures follow the functionality of the clingo API (so can deal - with tuples and functions that return list of items). However, the behaviour - of the clingo API is ad-hoc when it comes to automatic data conversion. That - is it can automatically convert numbers and strings but not other types such - as constants or more complex terms. The Clorm conversion signatures provide a - more principled and transparent approach, since all data conversions are - specified as part of the signature. +* Function signatures follow the functionality of the clingo API (so you can + specify tuples and provide functions that return list of items). + + However, the behaviour of the clingo API is ad-hoc when it comes to automatic + data conversion. That is, it will automatically convert numbers and strings, + but cannot deal with other types such as constants or more complex terms. + + The Clorm mechanism of a data conversion signatures provide a more principled + and transparent approach; it can deal with arbitrary conversions and all data + conversions are clear since they are specified as part of the signature. Development diff --git a/docs/clorm/factbase.rst b/docs/clorm/factbase.rst index 86e9365..3ba3891 100644 --- a/docs/clorm/factbase.rst +++ b/docs/clorm/factbase.rst @@ -56,12 +56,12 @@ Querying -------- An important motivation for providing a specialised container class for storing -facts, instead of simply using a Python ``list`` or ``set`` object, is to -support a rich mechanism to query the contents of a fact base. +facts, as opposed to simply using a Python ``list`` or ``set`` object, is to +support a rich mechanism for querying the contents of a fact base. When an ASP model is returned by the solver the application developer needs to process the model in order to extract the relevant facts. The simplest mechanism -to do this to simply loop through the facts in the model. This loop will +to do this is to simply loop through the facts in the model. This loop will typically contain a number of conditional statements to determine what action to take for the given fact; and to store it if some sort of matching needs to take place. @@ -85,8 +85,8 @@ can create ``Select`` query objects: A query object needs to be executed in order to return the results. There are three member functions to execute a query: ``get()``, ``get_unique()``, and ``count()``. ``get()`` returns a list of results, while ``get_unique()`` returns -exactly one results and will raise a ``ValueError`` if there is not exactly one -result. Finally, ``count()`` returns the number of matching entries. +exactly one result and will raise a ``ValueError`` if this is not the +case. Finally, ``count()`` returns the number of matching entries. .. code-block:: python diff --git a/docs/clorm/predicate.rst b/docs/clorm/predicate.rst index e54369e..8205391 100644 --- a/docs/clorm/predicate.rst +++ b/docs/clorm/predicate.rst @@ -249,17 +249,17 @@ encoded string into an actual ``datetime.date`` object: nyedate = datetime.datetime.strptime(str(nyepart.date), "%Y%m%d") -However, the problem with the above code is that the process of creating and -using the date in the ``Booking`` object is cumbersome and error-prone. You have -to remember to make the correct translation both in creating and reading the +The problem with the above code is that the process of creating and using the +date in the ``Booking`` object is cumbersome and error-prone. You have to +remember to make the correct translation both in creating and reading the date. Furthermore the places in the code where these translations are made may be far apart, leading to potential problems when code needs to be refactored. The solution to this problem is to create a sub-class of ``RawField`` that -performs the appropriate data conversion. However, sub-classing -``Rawfield``directly requires dealing with raw Clingo ``Symbol`` objects. A -better alternative is to sub-class the ``StringField`` class and then you can -deal with the string to date conversion directly. +performs the appropriate data conversion. However, sub-classing ``Rawfield`` +directly requires dealing with raw Clingo ``Symbol`` objects. A better +alternative is to sub-class the ``StringField`` class so you need to only deal +with the string to date conversion. .. code-block:: python @@ -304,7 +304,7 @@ Restricted Sub-class of a Field Definition ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Another reason to sub-class a field definition is to restrict the set of values -that a field can hold. For example if you have an application where an argument +that the field can hold. For example if you have an application where an argument of a predicate is restricted to a specific set of constants, such as the days of the week. @@ -529,8 +529,8 @@ tuple as part of an event predicate. e2 = Event(edt=EnumDate(idx=5, dt=datetime.date(2018, 10, 5)), details="Holidays") Here the index associated with the date could be used to capture a sequence of -dates and used to calcuate the number of days between certain dates (which is -information that does not arise directly from the date encoded string). +dates and used to calculate the number of days between two dates (note: this +information cannot be easily extracted from the date encoded string). In any case, the two generated Event objects will correspond to the ASP facts: @@ -540,9 +540,10 @@ In any case, the two generated Event objects will correspond to the ASP facts: event((5,"20181005"), "Holidays"). Now, declaring and using the ``EnumDate`` class can be quite cumbersome, -considering that it really corresponds to a very simple tuple. Clorm supports a -special syntax, using a tuple of field definitions, for dealing with cases of -simple tuples. The above Python code could be replaced with: +considering that it really corresponds to a very simple tuple. Consequently, +Clorm supports a modified syntax, using a tuple of field definitions, for +dealing with cases of simple tuples. The above Python code could be replaced +with: .. code-block:: python @@ -559,8 +560,8 @@ simple tuples. The above Python code could be replaced with: Internally, Clorm will generate an anonymously named complex term class that is declared similarly to ``EnumDate``. The fields of this class will be given automatically generated names ``arg1`` and ``arg2`` (up to ``arg`` for a -tuple of arity n), although in maybe more convenient to access the values using -positional arguments. +tuple of arity n), although in this case it may be more convenient to access the +values using positional arguments. .. code-block:: python diff --git a/docs/clorm/quickstart.rst b/docs/clorm/quickstart.rst index ae7ac0d..e77d864 100644 --- a/docs/clorm/quickstart.rst +++ b/docs/clorm/quickstart.rst @@ -164,12 +164,13 @@ Next we generate a problem instance by generating a lists of ``Driver`` and items = [ Item(name="item{}".format(i)) for i in range(1,6) ] instance = FactBase(drivers + items) -The ``Driver`` and ``Item`` constructors require named parameters that match the -declared term names. Note, a design decision was taken to disallow "normal" -Python positional arguments as it would make it too easy to write brittle code; -for example, the code would break if the order of the fields was changed. +The ``Driver`` and ``Item`` constructors use named parameters that match the +declared field names. Note: while you can use positional arguments to initialise +instances, doing so will potentially make the code harder to refactor. So in +general you should avoid using positional arguments except for a few cases (eg., +simple pairs where the order is unlikely to change). -The facts can now be added to the control object and the combined ASP program +These facts can now be added to the control object and the combined ASP program grounded. .. code-block:: python @@ -265,7 +266,7 @@ Python data model to the defined ASP predicates. However, beyond the basics outlined above there are other useful features that build on the ORM interface. These include: -* You can define new sub-classes of ``RawField`` for specific data +* You can define new sub-classes of ``RawField`` for custom data conversions. For example, you can define a ``DateField`` that represents dates in clingo in YYYY-MM-DD format and then use it in a predicate definition. @@ -305,10 +306,10 @@ interface. These include: * Field definitions can be specified as part of a function signature to perform automatic type conversion for writing Python functions that can be called from - an ASP program using @-syntax. + an ASP program using the @-syntax. Here function ``add`` is decorated with an automatic data conversion signature - to add two integers and return the resulting integer. + that accepts two input integers and expects an output integer. .. code-block:: python @@ -319,11 +320,14 @@ interface. These include: f(@add(5,6)). % grounds to f(11). -* Function signatures follow the functionality of the clingo API (so can deal - with tuples and functions that return list of items). However, the behaviour - of the clingo API is ad-hoc when it comes to automatic data conversion. That - is it can automatically convert numbers and strings but not other types such - as constants or more complex terms. The Clorm conversion signatures provide a - more principled and transparent approach, since all data conversions are - specified as part of the signature. +* Function signatures follow the functionality of the clingo API (so you can + specify tuples and provide functions that return list of items). + + However, the behaviour of the clingo API is ad-hoc when it comes to automatic + data conversion. That is, it will automatically convert numbers and strings, + but cannot deal with other types such as constants or more complex terms. + + The Clorm mechanism of a data conversion signatures provide a more principled + and transparent approach; it can deal with arbitrary conversions and all data + conversions are clear since they are specified as part of the signature.