## `has` -- check if an object occurs in another object

#### Introduction

`has(`object1, object2`)` checks, whether `object2` occurs syntactically in `object1`.

#### Call(s)

`has(object1, object2)`
`has(object1, l)`

#### Parameters

`object1, object2` | - | arbitrary MuPAD objects
`l` | - | a list or a set

#### Returns

either `TRUE` or `FALSE`

### Overloadable:

`object1`

#### Related Functions

`_in`, `_index`, `contains`, `hastype`, `op`, `subs`, `subsex`

#### Details

- `has` is a fast test for the existence of sub-objects or subexpressions. It works syntactically, i.e., mathematically equivalent objects are considered to be equal only if they are syntactically identical. See example 2.

- If `object1` is an expression, then `has(`object1, object2`)` tests whether `object1` contains `object2` as a subexpression. Only complete subexpressions and objects occurring in the 0th operand of a subexpression are found (see example 1).

- If `object1` is a container, then `has` checks whether `object2` occurs in an entry of `object1`. See example 4.

- If the second argument is a list or a set `l`, then `has` returns `TRUE` if at least one of the elements in `l` occurs in `object1` (see example 3). In particular, if `l` is the empty list or the empty set, then the return value is `FALSE`.

- If `object1` is an element of a domain with a `"has"` slot, then the slot routine is called with the same arguments, and its result is returned. If the domain does not have such a slot, then `FALSE` will be returned. See example 6.

  If `has` is called with a list or set as second argument, then the `"has"` slot of the domain of `object1` is called for each object of the list or the set. When the first object is found that occurs in `object1`, the evaluation is terminated and `TRUE` is returned. If none of the objects occurs in `object1`, `FALSE` will be returned.

- `has` is a function of the system kernel.

#### Example 1

The given expression has `x` as an operand:

    >> has(x + y + z, x)

                                       TRUE

Note that `x + y` is not a complete subexpression. Only `x`, `y`, `z` and `x + y + z` are complete subexpressions:

    >> has(x + y + z, x + y)

                                       FALSE

However, `has` also finds objects in the 0th operand of a subexpression:

    >> has(x + sin(x), sin)

                                       TRUE

Every object occurs in itself:

    >> has(x, x)

                                       TRUE

#### Example 2

`has` works in a purely syntactical fashion. Although the two expressions `y*(x + 1)` and `y*x + y` are mathematically equivalent, they differ syntactically:

    >> has(sin(y*(x + 1)), y*x + y),
       has(sin(y*(x + 1)), y*(x + 1))

                                    FALSE, TRUE

Complex numbers are not regarded as atomic objects:

    >> has(2 + 5*I, 2), has(2 + 5*I, 5), has(2 + 5*I, I)

                                 TRUE, TRUE, TRUE

In contrast, rational numbers are considered to be atomic:

    >> has(2/3*x, 2), has(2/3*x, 3), has(2/3*x, 2/3)

                                FALSE, FALSE, TRUE

#### Example 3

If the second argument is a list or a set, `has` checks whether one of the entries occurs in the first argument:

    >> has((x + y)*z, [x, t])

                                       TRUE

0th operands of subexpressions are checked as well:

    >> has((a + b)*c, {_plus, _mult})

                                       TRUE

#### Example 4

`has` works for lists, sets, tables, and arrays:

    >> has([sin(f(a) + 2), cos(x), 3], {f, g})

                                       TRUE

    >> has({a, b, c, d, e}, {a, z})

                                       TRUE

    >> has(array(1..2, 1..2, [[1, 2], [3, 4]]), 2)

                                       TRUE

For an array `A`, the command `has(`A,NIL`)` checks whether the array has any uninitialized entries:

    >> has(array(1..2, 1 = x), NIL),
       has(array(1..2, [2, 3]), NIL)

                                    TRUE, FALSE

For tables, `has` checks indices, entries, as well as the internal operands of a table, given by equations of the form `index=entry`:

    >> T := table(a = 1, b = 2, c = 3):
       has(T, a), has(T, 2), has(T, b = 2)

                                 TRUE, TRUE, TRUE

#### Example 5

`has` works syntactically. Although the variable `x` does not occur mathematically in the constant polynomial `p` in the following example, the identifier `x` occurs syntactically in `p`, namely, in the second operand:

    >> delete x: p := poly(1, [x]):
       has(p, x)

                                       TRUE

#### Example 6

The second argument may be an arbitrary MuPAD object, even from a user-defined domain:

    >> T := newDomain("T"):
       e := new(T, 1, 2);
       f := [e, 3];

                                   new(T, 1, 2)

                                 [new(T, 1, 2), 3]

    >> has(f, e), has(f, new(T, 1))

                                    TRUE, FALSE

If the first argument of `has` belongs to a domain without a `"`has" slot, then `has` always returns `FALSE`:

    >> has(e, 1)

                                       FALSE

Users can overload `has` for their own domains. For illustration, we supply the domain `T` with a `"`has" slot, which puts the internal operands of its first argument in a list and calls `has` for the list:

    >> T::has := (object1, object2) -> has([extop(object1)], object2):

If we now call `has` with the object `e` of domain type `T`, the slot routine `T::has` is invoked:

    >> has(e, 1), has(e, 3)

                                    TRUE, FALSE

The slot routine is also called if an object of domain type `T` occurs syntactically in the first argument:

    >> has(f, 1), has(f, 3)

                                    TRUE, TRUE

#### Changes

- no changes

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