Next: Internals, Previous: Example Definitions, Up: Lisp Definitions

A later section (see Internals) gives a full description of
Calc's internal Lisp functions. It's not hard to call Calc from
inside your programs, but the number of these functions can be daunting.
So Calc provides one special “programmer-friendly” function called
`calc-eval`

that can be made to do just about everything you
need. It's not as fast as the low-level Calc functions, but it's
much simpler to use!

It may seem that `calc-eval`

itself has a daunting number of
options, but they all stem from one simple operation.

In its simplest manifestation, ‘`(calc-eval "1+2")`’ parses the
string `"1+2"`

as if it were a Calc algebraic entry and returns
the result formatted as a string: `"3"`

.

Since `calc-eval`

is on the list of recommended `autoload`

functions, you don't need to make any special preparations to load
Calc before calling `calc-eval`

the first time. Calc will be
loaded and initialized for you.

All the Calc modes that are currently in effect will be used when evaluating the expression and formatting the result.

`calc-eval`

If the input string parses to a list of expressions, Calc returns
the results separated by `", "`

. You can specify a different
separator by giving a second string argument to `calc-eval`

:
‘`(calc-eval "1+2,3+4" ";")`’ returns `"3;7"`

.

The “separator” can also be any of several Lisp symbols which
request other behaviors from `calc-eval`

. These are discussed
one by one below.

You can give additional arguments to be substituted for
‘`$`’, ‘`$$`’, and so on in the main expression. For
example, ‘`(calc-eval "$/$$" nil "7" "1+1")`’ evaluates the
expression `"7/(1+1)"`

to yield the result `"3.5"`

(assuming Fraction mode is not in effect). Note the `nil`

used as a placeholder for the item-separator argument.

If `calc-eval`

encounters an error, it returns a list containing
the character position of the error, plus a suitable message as a
string. Note that ‘`1 / 0`’ is *not* an error by Calc's
standards; it simply returns the string `"1 / 0"`

which is the
division left in symbolic form. But ‘`(calc-eval "1/")`’ will
return the list ‘`(2 "Expected a number")`’.

If you bind the variable `calc-eval-error`

to `t`

using a `let`

form surrounding the call to `calc-eval`

,
errors instead call the Emacs `error`

function which aborts
to the Emacs command loop with a beep and an error message.

If you bind this variable to the symbol `string`

, error messages
are returned as strings instead of lists. The character position is
ignored.

As a courtesy to other Lisp code which may be using Calc, be sure
to bind `calc-eval-error`

using `let`

rather than changing
it permanently with `setq`

.

Sometimes it is preferable to treat ‘`1 / 0`’ as an error
rather than returning a symbolic result. If you pass the symbol
`num`

as the second argument to `calc-eval`

, results
that are not constants are treated as errors. The error message
reported is the first `calc-why`

message if there is one,
or otherwise “Number expected.”

A result is “constant” if it is a number, vector, or other object that does not include variables or function calls. If it is a vector, the components must themselves be constants.

If the first argument to `calc-eval`

is a list whose first
element is a formula string, then `calc-eval`

sets all the
various Calc modes to their default values while the formula is
evaluated and formatted. For example, the precision is set to 12
digits, digit grouping is turned off, and the Normal language
mode is used.

This same principle applies to the other options discussed below.
If the first argument would normally be `x`, then it can also
be the list ‘`( x)`’ to use the default mode settings.

If there are other elements in the list, they are taken as
variable-name/value pairs which override the default mode
settings. Look at the documentation at the front of the
`calc.el` file to find the names of the Lisp variables for
the various modes. The mode settings are restored to their
original values when `calc-eval`

is done.

For example, ‘`(calc-eval '("$+$$" calc-internal-prec 8) 'num a b)`’
computes the sum of two numbers, requiring a numeric result, and
using default mode settings except that the precision is 8 instead
of the default of 12.

It's usually best to use this form of `calc-eval`

unless your
program actually considers the interaction with Calc's mode settings
to be a feature. This will avoid all sorts of potential “gotchas”;
consider what happens with ‘`(calc-eval "sqrt(2)" 'num)`’
when the user has left Calc in Symbolic mode or No-Simplify mode.

As another example, ‘`(equal (calc-eval '("$<$$") nil a b) "1")`’
checks if the number in string ‘`a`’ is less than the one in
string ‘`b`’. Without using a list, the integer 1 might
come out in a variety of formats which would be hard to test for
conveniently: `"1"`

, `"8#1"`

, `"00001"`

. (But
see “Predicates” mode, below.)

Normally all input and output for `calc-eval`

is done with strings.
You can do arithmetic with, say, ‘`(calc-eval "$+$$" nil a b)`’
in place of ‘`(+ a b)`’, but this is very inefficient since the
numbers must be converted to and from string format as they are passed
from one `calc-eval`

to the next.

If the separator is the symbol `raw`

, the result will be returned
as a raw Calc data structure rather than a string. You can read about
how these objects look in the following sections, but usually you can
treat them as “black box” objects with no important internal
structure.

There is also a `rawnum`

symbol, which is a combination of
`raw`

(returning a raw Calc object) and `num`

(signaling
an error if that object is not a constant).

You can pass a raw Calc object to `calc-eval`

in place of a
string, either as the formula itself or as one of the ‘`$`’
arguments. Thus ‘`(calc-eval "$+$$" 'raw a b)`’ is an
addition function that operates on raw Calc objects. Of course
in this case it would be easier to call the low-level `math-add`

function in Calc, if you can remember its name.

In particular, note that a plain Lisp integer is acceptable to Calc as a raw object. (All Lisp integers are accepted on input, but integers of more than six decimal digits are converted to “big-integer” form for output. See Data Type Formats.)

When it comes time to display the object, just use ‘`(calc-eval a)`’
to format it as a string.

It is an error if the input expression evaluates to a list of
values. The separator symbol `list`

is like `raw`

except that it returns a list of one or more raw Calc objects.

Note that a Lisp string is not a valid Calc object, nor is a list containing a string. Thus you can still safely distinguish all the various kinds of error returns discussed above.

If the separator symbol is `pred`

, the result of the formula is
treated as a true/false value; `calc-eval`

returns `t`

or
`nil`

, respectively. A value is considered “true” if it is a
non-zero number, or false if it is zero or if it is not a number.

For example, ‘`(calc-eval "$<$$" 'pred a b)`’ tests whether
one value is less than another.

As usual, it is also possible for `calc-eval`

to return one of
the error indicators described above. Lisp will interpret such an
indicator as “true” if you don't check for it explicitly. If you
wish to have an error register as “false”, use something like
‘`(eq (calc-eval ...) t)`’.

Variables in the formula passed to `calc-eval`

are not normally
replaced by their values. If you wish this, you can use the
`evalv`

function (see Algebraic Manipulation). For example,
if 4 is stored in Calc variable `a`

(i.e., in Lisp variable
`var-a`

), then ‘`(calc-eval "a+pi")`’ will return the
formula `"a + pi"`

, but ‘`(calc-eval "evalv(a+pi)")`’
will return `"7.14159265359"`

.

To store in a Calc variable, just use `setq`

to store in the
corresponding Lisp variable. (This is obtained by prepending
‘`var-`’ to the Calc variable name.) Calc routines will
understand either string or raw form values stored in variables,
although raw data objects are much more efficient. For example,
to increment the Calc variable `a`

:

(setq var-a (calc-eval "evalv(a+1)" 'raw))

If the separator symbol is `push`

, the formula argument is
evaluated (with possible ‘`$`’ expansions, as usual). The
result is pushed onto the Calc stack. The return value is `nil`

(unless there is an error from evaluating the formula, in which
case the return value depends on `calc-eval-error`

in the
usual way).

If the separator symbol is `pop`

, the first argument to
`calc-eval`

must be an integer instead of a string. That
many values are popped from the stack and thrown away. A negative
argument deletes the entry at that stack level. The return value
is the number of elements remaining in the stack after popping;
‘`(calc-eval 0 'pop)`’ is a good way to measure the size of
the stack.

If the separator symbol is `top`

, the first argument to
`calc-eval`

must again be an integer. The value at that
stack level is formatted as a string and returned. Thus
‘`(calc-eval 1 'top)`’ returns the top-of-stack value. If the
integer is out of range, `nil`

is returned.

The separator symbol `rawtop`

is just like `top`

except
that the stack entry is returned as a raw Calc object instead of
as a string.

In all of these cases the first argument can be made a list in
order to force the default mode settings, as described above.
Thus ‘`(calc-eval '(2 calc-number-radix 16) 'top)`’ returns the
second-to-top stack entry, formatted as a string using the default
instead of current display modes, except that the radix is
hexadecimal instead of decimal.

It is, of course, polite to put the Calc stack back the way you found it when you are done, unless the user of your program is actually expecting it to affect the stack.

Note that you do not actually have to switch into the `*Calculator*`
buffer in order to use `calc-eval`

; it temporarily switches into
the stack buffer if necessary.

If the separator symbol is `macro`

, the first argument must be a
string of characters which Calc can execute as a sequence of keystrokes.
This switches into the Calc buffer for the duration of the macro.
For example, ‘`(calc-eval "vx5\rVR+" 'macro)`’ pushes the
vector ‘`[1,2,3,4,5]`’ on the stack and then replaces it
with the sum of those numbers. Note that ‘`\r`’ is the Lisp
notation for the carriage return, <RET>, character.

If your keyboard macro wishes to pop the stack, ‘`\C-d`’ is
safer than ‘`\177`’ (the <DEL> character) because some
installations may have switched the meanings of <DEL> and
`C-h`. Calc always interprets `C-d` as a synonym for
“pop-stack” regardless of key mapping.

If you provide a third argument to `calc-eval`

, evaluation
of the keyboard macro will leave a record in the Trail using
that argument as a tag string. Normally the Trail is unaffected.

The return value in this case is always `nil`

.

Finally, if the separator symbol is `eval`

, then the Lisp
`eval`

function is called on the first argument, which must
be a Lisp expression rather than a Calc formula. Remember to
quote the expression so that it is not evaluated until inside
`calc-eval`

.

The difference from plain `eval`

is that `calc-eval`

switches to the Calc buffer before evaluating the expression.
For example, ‘`(calc-eval '(setq calc-internal-prec 17) 'eval)`’
will correctly affect the buffer-local Calc precision variable.

An alternative would be ‘`(calc-eval '(calc-precision 17) 'eval)`’.
This is evaluating a call to the function that is normally invoked
by the `p` key, giving it 17 as its “numeric prefix argument.”
Note that this function will leave a message in the echo area as
a side effect. Also, all Calc functions switch to the Calc buffer
automatically if not invoked from there, so the above call is
also equivalent to ‘`(calc-precision 17)`’ by itself.
In all cases, Calc uses `save-excursion`

to switch back to
your original buffer when it is done.

As usual the first argument can be a list that begins with a Lisp expression to use default instead of current mode settings.

The result of `calc-eval`

in this usage is just the result
returned by the evaluated Lisp expression.

Here is a sample Emacs command that uses `calc-eval`

. Suppose
you have a document with lots of references to temperatures on the
Fahrenheit scale, say “98.6 F”, and you wish to convert these
references to Centigrade. The following command does this conversion.
Place the Emacs cursor right after the letter “F” and invoke the
command to change “98.6 F” to “37 C”. Or, if the temperature is
already in Centigrade form, the command changes it back to Fahrenheit.

(defun convert-temp () (interactive) (save-excursion (re-search-backward "[^-.0-9]\\([-.0-9]+\\) *\\([FC]\\)") (let* ((top1 (match-beginning 1)) (bot1 (match-end 1)) (number (buffer-substring top1 bot1)) (top2 (match-beginning 2)) (bot2 (match-end 2)) (type (buffer-substring top2 bot2))) (if (equal type "F") (setq type "C" number (calc-eval "($ - 32)*5/9" nil number)) (setq type "F" number (calc-eval "$*9/5 + 32" nil number))) (goto-char top2) (delete-region top2 bot2) (insert-before-markers type) (goto-char top1) (delete-region top1 bot1) (if (string-match "\\.$" number) ; change "37." to "37" (setq number (substring number 0 -1))) (insert number))))

Note the use of `insert-before-markers`

when changing between
“F” and “C”, so that the character winds up before the cursor
instead of after it.