# 11.3.5 Application

Charme supports two kinds of primitives: natural numbers and primitive procedures. If the expression is a number, it is a string of digits. The `is_number`

procedure evaluates to `True`

if and only if its input is a number:

return is_number(expr) or is_primitive_procedure(expr)

def is_number(expr):

return isinstance(expr, str) and expr.isdigit()

Here, we use the built-in function `isinstance`

to check if `expr`

is of type `str`

. The and expression in Python evaluates similarly to the Scheme `and`

special form: the left operand is evaluated first; if it evaluates to a false value, the value of the and expression is that false value. If it evaluates to a true value, the right operand is evaluated, and the value of the and expression is the value of its right operand. This evaluation rule means it is safe to use `expr.isdigit()`

in the right operand, since it is only evaluated if the left operand evaluated to a true value, which means `expr`

is a string.

Primitive procedures are defined using Python procedures. We define the procedure `is_primitive_procedure`

using `callable`

, a procedure that returns true only for callable objects such as procedures and methods:

return callable(expr)

The evaluation rule for a primitive is identical to the Scheme rule:

**Charme Evaluation Rule 1: Primitives.** A primitive expression evaluates to its pre-defined value.

We need to implement the *pre-defined* values in our Charme interpreter.

To evaluate a number primitive, we need to convert the string representation to a number of type `int`

. The `int(s)`

constructor takes a string as its input and outputs the corresponding integer:

if is_number(expr): return int(expr)

else: return expr

The `else`

clause means that all other primitives (in Charme, this is only primitive procedures and Boolean constants) self-evaluate: the value of evaluating a primitive is itself.

For the primitive procedures, we need to define Python procedures that implement the primitive procedure. For example, here is the `primitive_plus`

procedure that is associated with the `+`

primitive procedure:

if (len(operands) == 0): return 0

else: return operands[0] + primitive_plus (operands[1:])

The input is a list of operands. Since a procedure is applied only after all subexpressions are evaluated, there is no need to evaluate the operands: they are already the evaluated values. For numbers, the values are Python integers, so we can use the Python `+`

operator to add them. To provide the same behavior as the Scheme primitive `+`

procedure, we define our Charme primitive `+`

procedure to evaluate to `0`

when there are no operands, and otherwise to recursively add all of the operand values.

The other primitive procedures are defined similarly:

if (len(operands) == 0): return 1

else: return operands[0] * primitive_times (operands[1:])

if (len(operands) == 1): return -1 * operands[0]

elif len(operands) == 2: return operands[0] - operands[1]

else:

eval_error('- expects 1 or 2 operands, given %s: %s'

% (len(operands), str(operands)))

check_operands (operands, 2, '=')

return operands[0] == operands[1]

check_operands (operands, 2, '<')

return operands[0] < operands[1]

The `check_operands`

procedure reports an error if a primitive procedure is applied to the wrong number of operands:

if (len(operands) != num):

eval_error('Primitive %s expected %s operands, given %s: %s'

% (prim, num, len(operands), str(operands)))