Skip to content

function

tuprolog.solve.function

Logic functions: functions evaluated in arithmetic expressions, e.g. by is/2.

Prolog evaluates arithmetic expressions only in some predicates, e.g. X is 1 + 2 or X > 2: elsewhere, 1 + 2 is just a term. Each operation in an expression (e.g. +/2, sqrt/1) is a logic function, receiving the (evaluated) arguments, and returning a term. The standard ones are in tuprolog.solve.stdlib.function; libraries add others (see tuprolog.solve.library).

Functions receive a compute request (ComputeRequest: the function's signature, its arguments, and the solver's context), and return a compute response (ComputeResponse, holding the result).

Main types and functions:

  • function: creates a logic function from a Python function on Python values;
  • logic_function: creates a logic function from a Python function on requests;
  • LogicFunction, ComputeRequest, ComputeResponse, AbstractLogicFunction;
  • eval_as_expression and eval_as_arithmetic_expression: evaluate expressions in primitives.

Examples:

>>> from tuprolog.solve.library import library
>>> from tuprolog.solve.prolog import prolog_solver
>>> hypot = function(lambda x, y: (x**2 + y**2) ** 0.5)
>>> solver = prolog_solver(libraries=library("my.math", functions={"hypot/2": hypot}))
>>> solver.solve_once("X is hypot(3, 4) + 1")["X"]
6.0
See Also

LogicFunction module-attribute

LogicFunction = _function.LogicFunction

A logic function: computes the result of an operation in arithmetic expressions.

Its only method is compute(request), taking a ComputeRequest and returning a ComputeResponse. Create logic functions with function or logic_function, or by subclassing AbstractLogicFunction.

Compute module-attribute

Compute = _function.Compute

The JVM base class of compute requests and responses.

It nests them as Compute.Request (ComputeRequest) and Compute.Response (ComputeResponse).

ArithmeticUtilsKt module-attribute

ArithmeticUtilsKt = _function.ArithmeticUtilsKt

The JVM class of 2P-Kt's expression evaluation functions.

Its static methods are wrapped by eval_as_expression and eval_as_arithmetic_expression.

ComputeRequest module-attribute

ComputeRequest = Compute.Request

A request to compute a logic function.

Members: signature, arguments (the evaluated arguments, a list of terms), context (the tuprolog.solve.ExecutionContext of the solver), query (the expression, i.e. the struct of the signature and arguments), request_issuing_instant, execution_max_duration (in milliseconds), and reply_with(result), returning the ComputeResponse with result. Create requests with compute_request.

ComputeResponse module-attribute

ComputeResponse = Compute.Response

The response of a logic function, holding its result, a term.

Create responses with compute_response, or ComputeRequest.reply_with.

AbstractLogicFunction

A base class for logic functions written in Python: subclasses implement compute.

Examples:

>>> from tuprolog.core import integer
>>> from tuprolog.solve.library import library
>>> from tuprolog.solve.prolog import prolog_solver
>>> class Arity(AbstractLogicFunction):
...     def compute(self, request):
...         return request.reply_with(integer(len(request.arguments)))
>>> solver = prolog_solver(libraries=library("my.lib", functions={"arity/3": Arity()}))
>>> solver.solve_once("X is arity(1, 2, 3)")["X"]  # arguments are evaluated: numbers
3

compute

compute(request: ComputeRequest) -> ComputeResponse

Computes the result of the function for request.

Parameters:

Name Type Description Default
request ComputeRequest

The compute request, with the evaluated arguments.

required

Returns:

Type Description
ComputeResponse

The compute response, holding the result.

Raises:

Type Description
NotImplementedError

Unless overridden by subclasses.

logic_function

logic_function(
    callable: Callable[[ComputeRequest], ComputeResponse],
) -> LogicFunction

Creates a logic function from a Python function on compute requests.

Unlike function, the Python function sees the whole request, including the solver's context, and works on terms. The exceptions it raises become logic errors (see tuprolog.solve.primitive.python_error): 2P-Kt's are kept, any other one becomes a system_error, which catch/3 can handle.

Parameters:

Name Type Description Default
callable Callable[[ComputeRequest], ComputeResponse]

A function taking a ComputeRequest, and returning a ComputeResponse (e.g. via request.reply_with(result)).

required

Returns:

Type Description
LogicFunction

The logic function.

Examples:

>>> from tuprolog.core import integer
>>> from tuprolog.solve.library import library
>>> from tuprolog.solve.prolog import prolog_solver
>>> def count_arguments(request):
...     return request.reply_with(integer(len(request.arguments)))
>>> count = logic_function(count_arguments)
>>> solver = prolog_solver(libraries=library("my.lib", functions={"count/2": count}))
>>> solver.solve_once("X is count(1, 2) * 10")["X"]
20

function

function(callable: Callable) -> LogicFunction

Creates a logic function from a Python function on Python values.

Parameters:

Name Type Description Default
callable Callable

A function taking the evaluated arguments, converted to Python values (see tuprolog.core.to_python), and returning a Python value or a term (converted by tuprolog.core.to_term).

required

Returns:

Type Description
LogicFunction

The logic function.

Note

Exceptions raised by callable become logic errors, as in logic_function.

Examples:

>>> from tuprolog.solve.library import library
>>> from tuprolog.solve.prolog import prolog_solver
>>> solver = prolog_solver(
...     libraries=library("my.lib", functions={"twice/1": function(lambda x: 2 * x)})
... )
>>> solver.solve_once("X is twice(21)")["X"]
42

compute_request

compute_request(
    signature: Signature,
    arguments: Iterable[Term],
    context: ExecutionContext,
    issuing_instant: int | None = None,
    max_duration: int = MAX_TIMEOUT,
) -> ComputeRequest

Creates a compute request, e.g. to test logic functions.

Parameters:

Name Type Description Default
signature Signature

The signature of the function.

required
arguments Iterable[Term]

The arguments, as many as the arity of signature (or more, if variadic).

required
context ExecutionContext

The execution context of the solver.

required
issuing_instant int | None

When the request is issued, in milliseconds (see tuprolog.solve.current_time_instant); now, by default.

None
max_duration int

The maximum duration of the computation, in milliseconds; none by default.

MAX_TIMEOUT

Returns:

Type Description
ComputeRequest

The compute request.

Raises:

Type Description
IllegalArgumentException

If the number of arguments does not match the arity.

compute_response

compute_response(result: Term) -> ComputeResponse

Creates a compute response, holding the result of a logic function.

Parameters:

Name Type Description Default
result Term

The result.

required

Returns:

Type Description
ComputeResponse

The compute response.

Examples:

>>> from tuprolog.core import integer
>>> compute_response(integer(1)).result
1

eval_as_expression

eval_as_expression(
    term: Term,
    request: SolveRequest,
    index: int | None = None,
) -> Term

Evaluates a term as an expression, with the functions of the solver, in a primitive.

Variables are left as they are; any other non-evaluable term raises an error.

Parameters:

Name Type Description Default
term Term

The term to evaluate, e.g. an argument of the request.

required
request SolveRequest

The request of the primitive (see tuprolog.solve.primitive).

required
index int | None

The (0-based) index of the argument term comes from, mentioned by errors.

None

Returns:

Type Description
Term

The value of the expression.

Raises:

Type Description
TypeError

If a sub-term is not evaluable.

eval_as_arithmetic_expression

eval_as_arithmetic_expression(
    term: Term,
    request: SolveRequest,
    index: int | None = None,
) -> Term

Evaluates a term as an arithmetic expression, as is/2 does, in a primitive.

Parameters:

Name Type Description Default
term Term

The term to evaluate, e.g. an argument of the request.

required
request SolveRequest

The request of the primitive (see tuprolog.solve.primitive).

required
index int | None

The (0-based) index of the argument term comes from, mentioned by errors.

None

Returns:

Type Description
Term

The number the expression evaluates to (a tuprolog.core.Numeric).

Raises:

Type Description
LogicError

If the expression is not instantiated or not evaluable, or does not evaluate to a number.

Examples:

>>> from tuprolog.core import integer, substitution
>>> from tuprolog.solve.library import library
>>> from tuprolog.solve.primitive import primitive
>>> from tuprolog.solve.prolog import prolog_solver
>>> @primitive
... def double(request):
...     value = eval_as_arithmetic_expression(request.arguments[0], request, 0)
...     result = integer(value.int_value * 2)
...     yield request.reply_success(substitution({request.arguments[1]: result}))
>>> solver = prolog_solver(libraries=library("my.lib", primitives={"double/2": double}))
>>> solver.solve_once("double(1 + 2, X)")["X"]
6