## `expr` -- convert into an element of a basic domain

#### Introduction

`expr(`object`)` converts `object` into an element of a basic domain, such that all sub-objects are elements of basic domains as well.

#### Call(s)

`expr(object)`

#### Parameters

`object` | - | an arbitrary object

#### Returns

an element of a basic domain.

### Overloadable:

`object`

#### Related Functions

`coerce`, `domtype`, `eval`, `testtype`, `type`

#### Details

- `expr` is a type conversion function, for converting an element of a more complex library domain, such as a polynomial or a matrix, into an element of a basic kernel domain.

  `expr` proceeds recursively, such that all sub-objects of the returned object are elements of basic domains as well. See example 2.

- The two special objects `infinity` and `complexInfinity` are translated into identifiers with the same name by `expr`. Evaluating these identifiers yields the original objects. See example 1.
- If `object` already belongs to a basic domain other than `DOM_POLY`, then `expr` is only applied recursively to the operands of `object`, if any.
- If `object` is a polynomial of domain type `DOM_POLY`, then `expr` is applied recursively to the coefficients of `object`, and afterwards the result is converted into an identifier, a number, or an expression. See example 1.
- If `object` belongs to a library domain `T` with an `"`expr" slot, then the corresponding slot routine `T::expr` is called with `object` as argument, and the result is returned.

  This can be used to extend the functionality of `expr` to elements of user-defined domains. If the slot routine is unable to perform the conversion, it must return `FAIL`. See example 6.

  If the domain `T` does not have an `"`expr" slot, then `expr` returns `FAIL`.

- The result of `expr` is not evaluated further. Use `eval` to evaluate it. See example 4.

#### Example 1

`expr` converts a polynomial into an expression, an identifier, or a number:

    >> expr(poly(x^2 + y, [x])), expr(poly(x)), expr(poly(2, [x]));
       map(%, domtype)

                                        2
                                   y + x , x, 2

                           DOM_EXPR, DOM_IDENT, DOM_INT

The objects `infinity` and `complexInfinity` are translated into identifiers with the same names:

    >> expr(infinity), expr(complexInfinity);
       map(%, domtype)

                             infinity, complexInfinity

                               DOM_IDENT, DOM_IDENT

If these identifiers are evaluated with `eval` the results are the original objects of the types `stdlib::Infinity` and `stdlib::CInfinity`:

    >> expr(infinity), expr(complexInfinity);
       map(eval(%), domtype)

                             infinity, complexInfinity

                        stdlib::Infinity, stdlib::CInfinity

#### Example 2

This example shows that `expr` works recursively on expressions. All subexpressions which are domain elements are converted into expressions. In earlier versions of MuPAD (up to version 1.4.2) the result would have been `x + (1 mod 7)`. The construction with `hold(_plus)(..)` is necessary since `x + i(1)` would evaluate to `FAIL`:

    >> i := Dom::IntegerMod(7):
       hold(_plus)(x, i(1));  expr(%)

                                   x + (1 mod 7)

                                       x + 1

#### Example 3

The function `series` returns an element of the domain `Series::Puiseux`, which is not a basic domain:

    >> s := series(sin(x), x);
       domtype(s)

                                    3    5
                                   x    x        6
                               x - -- + --- + O(x )
                                   6    120

                                  Series::Puiseux

Use `expr` to convert the result into an element of domain type `DOM_EXPR`:

    >> e := expr(s); domtype(e)

                                        3    5
                                       x    x
                                   x - -- + ---
                                       6    120

                                     DOM_EXPR

Note that the information about the order term is lost after the conversion.

#### Example 4

`expr` does not evaluate its result. In this example the polynomial `p` has a parameter `a` and the global variable `a` has a value. `expr` applied on the polynomial `p` returns an expression containing `a`. If you want to insert the value of `a` use the function `eval`:

    >> p := poly(a*x, [x]):  a := 2:  expr(p);  eval(%)

                                        a x

                                        2 x

#### Example 5

`A` is an element of type `Dom::Matrix(Dom::Integer)`:

    >> A := Dom::Matrix(Dom::Integer)([[1, 2], [3, 2]]);
       domtype(A)

                                    +-      -+
                                    |  1, 2  |
                                    |        |
                                    |  3, 2  |
                                    +-      -+

                             Dom::Matrix(Dom::Integer)

In this case, `expr` converts `A` into an element of type `DOM_ARRAY`:

    >> a := expr(A); domtype(a)

                                    +-      -+
                                    |  1, 2  |
                                    |        |
                                    |  3, 2  |
                                    +-      -+

                                     DOM_ARRAY

However, it is not guaranteed that the result is of type `DOM_ARRAY` in future versions of MuPAD as well. For example, the internal representation of matrices might change in the future. Use `coerce` to request the conversion into a particular data type:

    >> coerce(A, DOM_ARRAY)

                                    +-      -+
                                    |  1, 2  |
                                    |        |
                                    |  3, 2  |
                                    +-      -+

A nested `list` is an alternative representation for a matrix:

    >> coerce(A, DOM_LIST)

                                 [[1, 2], [3, 2]]

#### Example 6

If a sub-object belongs to a domain without an `"`expr" slot, then `expr` returns `FAIL`:

    >> T := newDomain("T"):
       d := new(T, 1, 2);
       expr(d)

                                   new(T, 1, 2)

                                       FAIL

You can extend the functionality of `expr` to your own domains. We demonstrate this for the domain `T` by implementing an `"`expr" slot, which returns a list with the internal operands of its argument:

    >> T::expr := x -> [extop(x)]:

If now `expr` encounters a sub-object of type `T` during the recursive process, it calls the slot routine `T::expr` with the sub-object as argument:

    >> expr(d), expr([d, 3])

                                [1, 2], [[1, 2], 3]

#### Changes

- `expr` is no longer a kernel function.
- `expr` now works recursively. See example 2.

Do you have questions or comments?
Copyright © SciFace Software GmbH & Co. KG 2000