In this paper, we propose a high-level approach to this problem. The idea is based on extending recursive definitions with some evolutionary features, which we call evolving recursive definitions. This idea comes from the recent important work called Computability Logic(CoL). See for its details.
2 Two Interpretations of
There are two different ways to interpret
where is an expressions.
The interpretation is the following: the above is true if it is true for all terms, i.e.,
The interpretation is the following: the above is true if it is true independent of . This is a subtle concept and can be viewed as an parallel interpretation. Note that this definition cannot be expanded.
In the sequel, we use instead of to denote parallel universal quantifier. Now the difference is the following:
Evaluating with respect to has the following intended semantics: create , evaluate and then discard .
In contrast, evaluating with respect to has the following intended semantics: create , evaluate and then do not discard .
Thus, definitions are evolving and intended to perform automatic memoization. This is a novel feature which is not present in traditional recursive definitions. On the other hand, the blind interpretation is the one that is used in traditional recursive definition.
3 Fibonacci with Memoization
In the traditional approach, function evaluation is based
on the blind quantification.
For example, a function is specified as:
Note that the third definition is a blind-quantified definition in  – means that it is true independent of .
Now, to compute , our machine temporarily creates the following new instances in the course of evaluation and discards them after.
To support (top-down) automatic memoization, all we have to do is to replace by .
In the sense of , PUQ definitions require to generates new instances of the existing function definitions and adds them permanently in front of the program. These new instances play a role similar to automatic memoization.
For example, a function can be specified as:
Note that the third definition is compressed
and needs to be expanded during execution.
For example, to compute , the above definition evolves/expands to the following
One consequence of our approach is that it supports dynamic programming.
4 The Language
The language is a version of the core functional languages — also one of recursive functions — with PUQ expressions. It is described by - and -rules given by the abstract syntax as follows: In the abstract syntax, and denote the expressions and the definitions, respectively. In the rules above, is a constant, is a variable, is a term which is either a variable or a constant. is called a program in this language.
Following the traditional approach for defining semantics , we will present the semantics of this language, essentially an interpreter for the language, as a set of rules in Definition 1. The evaluation strategy assumed by these rules is an eager evaluation. Note that execution alternates between two phases: the evaluation phase defined by eval and the backchaining phase by bc.
In the evaluation phase, denoted by , the machine tries to evaluate an expression from the program to get a value and an evolved definition . The rules (7) – (10) are related to this phase. For instance, if is a function call , the machine first evaluates all of its arguments and then looks for a definition of in the program in the backchaining mode (Rule 6).
The rules (1) – (6) describe the backchaining mode, denoted by . In the backchaining mode, the machine tries to evaluate a function call by using the function definition in the program . is the value after evaluation and is what evolves to. takes care of the BQ definitions and takes care of the PUQ ones.
Definition 1. Let be an expression and let be a program. Then the notion of evaluating to a value and getting a new definition — — is defined as follows:
if % switch to evaluation mode.
if % memoization.
if % memoization.
if . provided that is the first matching declaration.
if . % argument passing to and . % blind quantification
if % argument passing to and . % parallel universal quantification
if . % switch to backchaining by making a copy of for a function call.
if and . % evaluate the arguments first.
. % is always a success.
. % A success if is a constant.
5 Object-Oriented Programming
Evolving definitions in the previous section perform sequential search for a function definition. This is a slow process! We can speed up this search by permitting locations for a set of function definitions. The addition of locations makes it possible to provide a direct lookup of a function.
For example, assume that
is stored at a location . Then can be
Now consider an expression . The
machine creates two instances at run time.
Note that the above is nothing but an object-oriented programming in a distilled form. That is, in object-oriented terms, are regular objects and is a class object. Our language has some interesting features:
Instances are created lazily and automatically.
As we will see later, it supports nested objects.
Class is not a primary means for creating an object: objects can be created without introducing its class.
Finally, note that adding imperative features to our languages poses no problem, still leading to a very concise code.
6 Nested objects
Consider an object definition of the form
For speedup, the method within an object can be further refined to
Now each call to must be of the form . Note that our language supports a novel nested object-oriented programming. Nested objects are quite useful for further speedup as well as clustering objects. We will look into this in the future.
-  G. Japaridze, “Introduction to computability logic”, Annals of Pure and Applied Logic, vol.123, pp.1–99, 2003.
-  G. Japaridze, “Sequential operators in computability logic”, Information and Computation, vol.206, No.12, pp.1443-1475, 2008.
D. Miller, “A logical analysis of modules in logic programming”, Journal of Logic Programming, vol.6, pp.79–108, 1989.