## `hastype` -- test if an object of a specified type occurs in another object

#### Introduction

`hastype(`object, T`)` tests if an object of type `T` occurs syntactically in `object`.

#### Call(s)

`hastype(object, T <, inspect>)`

#### Parameters

`object` | - | an arbitrary MuPAD object
`T` | - | a type specifier, or a set or a list of type specifiers
`inspect` | - | a set of domain types

#### Returns

either `TRUE` or `FALSE`.

### Overloadable:

`object`

#### Related Functions

`domtype`, `has`, `misc::maprec`, `testtype`, `Type`, `type`

#### Details

- `hastype(`object, T`)` tests if a sub-object `s` of type `T` occurs in `object`, i.e., such that `testtype(s, T)` returns `TRUE`.
- The type specifier `T` may be either a domain type such as `DOM_INT`, `DOM_EXPR` etc., a string as returned by the function `type`, or a `Type` object. The latter are probably the most useful pre-defined values for the argument `T`.

  If `T` is not a valid type specifier, then `hastype` returns `FALSE`.

  See example 1.

- If `object` is an expression, then `hastype(`object, T`)` tests whether `object` contains a subexpression of type `T`; see example 1.

  If `object` is a container, then `hastype` checks whether a sub-object of type `T` occurs in an entry of `object`; see example 3.

- If the second argument is a list or a set, `hastype` checks whether a sub-object of one of the types in `T` occurs in `object`. Cf. example 1.

- `hastype` works in a recursive fashion and descends into the following objects: expressions, arrays, lists, sets, and tables; see example 3. `hastype` does not step into the other basic domains, such as rational numbers, complex numbers, polynomials, or procedures; see example 2.
- If the third argument `inspect` is present, then `hastype` also steps recursively into sub-objects of the domain types given in `inspect`; cf. example 2.

- `hastype` looks only for sub-objects that are syntactically of type `T`. Properties of identifiers set via `assume` are not taken into account; cf. example 3.

#### Example 1

In this example, we first test if a given expression has a subexpression of type `DOM_FLOAT`:

    >> hastype(1.0 + x, DOM_FLOAT)

                                       TRUE

    >> hastype(1 + x, DOM_FLOAT)

                                       FALSE

We may also test if an expressions contains a subexpression of one of the two types `DOM_FLOAT` or `DOM_INT`:

    >> hastype(1.0 + x, {DOM_FLOAT, DOM_INT})

                                       TRUE

While the first of following two tests returns `FALSE`, since `tan` is not a valid type specifier, the second test yields `TRUE`, since the given expression contains a subexpression of type `"tan"`:

    >> hastype(sin(tan(x) + 1/exp(1 - x)), tan),
       hastype(sin(tan(x) + 1/exp(1 - x)), "tan")

                                    FALSE, TRUE

You can also use type specifiers from the `Type` library:

    >> hastype([-1, 10, -5, 2*I], Type::PosInt)

                                       TRUE

#### Example 2

We demonstrate the use of the optional third argument. We want to check if a procedure contains a subexpression of type `"float"`. By default, `hastype` does not descend recursively into a procedure:

    >> f := x -> float(x) + 3.0:
       hastype(f, "float")

                                       FALSE

You can use the third argument to request the inspection of procedures explicitly:

    >> hastype(f, "float", {DOM_PROC})

                                       TRUE

Also, by default, `hastype` does not descend recursively into the basic domains `DOM_COMPLEX` and `DOM_RAT`:

    >> hastype(1 + I, DOM_INT), hastype(2/3,  DOM_INT)

                                   FALSE, FALSE

In order to inspect these data types, one has to use the third argument:

    >> hastype(1 + I, DOM_INT, {DOM_COMPLEX}),
       hastype(2/3,  DOM_INT, {DOM_RAT})

                                    TRUE, TRUE

It is also possible to inspect domains elements using the third argument. As an example let us define a matrix element and ask for a subexpression of type integer:

    >> A:=matrix([[1, 1], [1, 0]]):
       hastype(A, DOM_INT),  hastype(A, DOM_INT, {Dom::Matrix()})

                                    FALSE, TRUE

#### Example 3

We demonstrate how `hastype` effects on container objects. Let us first stress tables:

    >> hastype(table(1 = a), DOM_INT), hastype(table(a = 1), DOM_INT)

                                    FALSE, TRUE

As shown, `hastype` does not inspect the indices of a table, but checks recursively whether a sub-object of a given type occurs in an entry. This is also true for arrays, lists and sets:

    >> hastype(array(1..4, [1, 2, 3, 4]), DOM_INT),
       hastype([1, 2, 3, 4], DOM_INT),
       hastype({1, 2, 3, 4}, DOM_INT),
       hastype([[a, [1]], b, c], DOM_INT)

                              TRUE, TRUE, TRUE, TRUE

`hastype` can only work syntactically, i.e. properties are not taken into account:

    >> assume(a,Type::Integer):
       hastype([a, b], Type::Integer), hastype([a, b], DOM_INT)

                                   FALSE, FALSE

    >> delete a:

#### Changes

- The second argument can now also be a list or a set.
- The optional third argument was introduced.

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