has -- check if an object occurs in
another object
Introductionhas(object1, object2) checks, whether
object2 occurs syntactically in object1.
Call(s)has(object1, object2)
has(object1, l)
Parametersobject1, object2 |
- | arbitrary MuPAD objects |
l |
- | a list or a set |
Returnsobject1
Related
Functions_in, _index, contains, hastype, op, subs, subsex
Detailshas 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.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).object1 is a container, then has
checks whether object2 occurs in an entry of
object1. See example 4.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.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
1The 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
2has 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
3If 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
4has 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
5has 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
6The 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