slot
-- method or entry of a domain
or a function environmentslot(
d, "n")
returns the value of the slot
named "n"
of the object d
.
slot(
d, "n", v)
creates or changes the
slot "n"
. The value v
is assigned to the
slot.
d :: n slot(d, "n")
d :: n := v slot(d, "n", v)
object :: domslot(object, "dom")
d |
- | a domain or a function environment |
n |
- | the name of the slot: an identifier |
v |
- | the new value of the slot: an arbitrary MuPAD object |
object |
- | an arbitrary MuPAD object |
slot(
d, "n")
returns the value of the
slot; slot(
d, "n", v)
returns the object
d
with the added or changed slot;
slot(
object, "dom")
returns the domain type of the object.
d
Section 5.7 of the document "From MuPAD 1.4 to MuPAD 2.0".
DOM_DOMAIN
,
DOM_FUNC_ENV
,
domain
, funcenv
, newDomain
slot
is used for defining methods and
entries of data types (domains) or for
defining attributes of function
environments. Such methods, entries, or attributes are called
slots. They allow to overload system functions by user defined
domains and function environments. See the ``Background'' section below
for further information."dom"
. It holds the domain the object belongs to:
slot(
object, "dom")
is
equivalent to domtype(object)
. The value of this
special slot cannot be changed. Cf. example 1."dom"
, only domains and
function environments may have further
slots.
The call slot(
d, "n")
is equivalent to
d::n
. It returns the value of the slot.
The call slot(
d, "n", v)
returns the
object d
with an added or changed slot "n"
bearing the value v
.
d
, the call
slot(
d, "n", v)
returns a copy of
d
with the changed slot "n"
. The function
environment d
itself is not changed! Use the assignment
d := slot(d, "n", v)
to modify d
. Cf.
example 2.
For a domain d
, however, the call
slot(
d, "n", v)
modifies d
as a
side-effect! This is the so-called ``reference effect'' of domains. Cf.
example 3.
FAIL
is returned as the value of the
slot. Cf. example 4.::
-operator is a shorthand
notation to access a slot.
The expression d::n
, when not appearing on the left
hand side of an assignment, is equivalent to slot
(d,
"n")
.
The command d::n := v
assigns the value v
to the slot "n"
of d
. This assignment is
almost equivalent to changing or creating a slot via d:= slot(d,
"n", v)
. Note the following subtle semantical difference between
these assignments: in d::n := v
, the identifier
d
is evaluated with level 1, i.e., the slot
"n"
is attached to the value of d
.
In slot(d, "n", v)
, the identifier d
is
fully evaluated. See example 6.
delete d::n
or delete slot(d,"n")
,
the slot "n"
of the function environment or the domain
d
is deleted. Cf. example 5. The
special slot "dom"
cannot be deleted.slot
is not flattened. This allows to access the slots of expression sequences and null()
objects. Cf. example 7."make_slot"
of the domain is called in order to create the
slot. If such a method does not exist, FAIL
is returned. Cf. example 8.slot
is a function of the system kernel.Every object has the slot "dom"
:
>> slot(x, "dom") = domtype(x), slot(45, "dom") = domtype(45), slot(sin, "dom") = domtype(sin)
DOM_IDENT = DOM_IDENT, DOM_INT = DOM_INT, DOM_FUNC_ENV = DOM_FUNC_ENV
Here we access the existing "float"
slot of
the function environment sin
implementing the sine function. The
float slot is again a function environment and may be called like any
MuPAD function. Note, however, the different functionality: in
contrast to sin
, the float
slot always tries to compute a floating point approximation:
>> s := slot(sin, "float"): s(1) , sin(1)
0.8414709848, sin(1)
With the following command, s
becomes the
function environment sin
apart from a changed "float"
slot. The slot
call has no effect on the original sin
function because
slot
returns a copy of the function environment:
>> s := slot(sin, "float", x -> float(x - x^3/3!)): s(PI/3) = sin(PI/3), s::float(1) <> sin::float(1)
1/2 1/2 3 3 ---- = ----, 0.8333333333 <> 0.8414709848 2 2
>> delete s:
If you are using the slot
function to
change slot entries in a domain, you must be aware that you are
modifying the domain. This is in contrast to changing slots of function
environments (see example 2):
>> old_one := slot(Dom::Float, "one")
1.0
>> newDomFloat := slot(Dom::Float, "one", 1): slot(newDomFloat, "one"), slot(Dom::Float, "one")
1, 1
We restore the original state:
>> slot(Dom::Float, "one", old_one): slot(Dom::Float, "one")
1.0
>> delete old_one, newDomFloat:
The function environment sin
does not contain a
"sign"
slot. So accessing this slot yields FAIL
:
>> slot(sin, "sign"), sin::sign
FAIL, FAIL
We define a function environment for a function
computing the logarithm to the base 10
:
>> log10 := funcenv(x -> log(10, x)):
If the function info
is to give some information about
log10
, we have to define the "info"
slot for
this function. For function environments, slot
returns a
copy of the original object, so the result of the slot
call has to be assigned to log10
:
>> log10 := slot(log10, "info", "log10 -- the logarithm to the base 10"):
>> info(log10)
log10 -- the logarithm to the base 10
The delete
statement is used for deleting
a slot:
>> delete log10::info: info(log10)
Sorry, no information available.
It is not possible to delete the special slot
"dom"
:
>> delete log10::dom
Error: Illegal argument [delete]
>> delete log10:
Here we demonstrate the subtle difference between the
slot
function and the use of the ::
-operator
in assignments. The following call adds a "xyz"
slot to
the domain DOM_INT
of
integer numbers:
>> delete b: d := b: b := DOM_INT: slot(d, "xyz", 42):
The slot "xyz"
of DOM_INT
is changed, because
d
is fully evaluated with the result DOM_INT
.
Hence, the slot DOM_INT::xyz
is set to 42:
>> slot(d, "xyz") , slot(DOM_INT, "xyz")
42, 42
Here is the result when using the
::
-operator: d
is only evaluated with level
1, i.e., it is evaluated to the identifier b
. However,
there is no slot b::xyz
, and an error occurs:
>> delete b: d := b: b := DOM_INT: d::xyz := 42
Error: Unknown slot "d::xyz" [slot]
>> delete b, d:
The first argument of slot
is not flattened. This allows access to the slots of
expression sequences and null()
objects:
>> slot((a, b), "dom"), slot(null(), "dom")
DOM_EXPR, DOM_NULL
We give an example for the use of the function
make_slot
. The element undefined
of the
domain stdlib::Undefined
represents an undefined value.
Any function f
should yield f(undefined) =
undefined
. Inside the implementation of
stdlib::Undefined
, we find:
>> undef := newDomain("stdlib::Undefined"): undefined := new(undef): undef::func_call := proc() begin undefined end_proc; undef::make_slot := undef::func_call:
The following mechanism takes place automatically for a
function f
that is overloadable by its first argument: in
the call f(undefined)
, it is checked whether the slot
undef::f
exists. If this is not the case, the
make_slot
function creates this slot ``on the fly'',
producing the value undefined
. Thus, via overloading,
f(undefined)
returns the value undefined
.
The following example is rather advanced and technical.
It demonstrates overloading of the slot
function to
implement slot access and slot assignments for other objects than
domains (DOM_DOMAIN
) or function
environments (DOM_FUNC_ENV
). The following
example defines the slots "numer"
and "denom"
for rational numbers. The domain DOM_RAT
of such numbers does not
have slots "numer"
and "denom"
:
>> domtype(3/4)
DOM_RAT
>> slot(3/4, "numer");
Error: Unknown slot "(3/4)::numer" [slot]
We can change DOM_RAT
, however. For this, we have
to unprotect DOM_RAT
temporarily:
>> unprotect(DOM_RAT): _assign(DOM_RAT::slot, proc(r : DOM_RAT, n : DOM_STRING, v=null(): DOM_INT) local i : DOM_INT; begin i := contains(["numer", "denom"], n); if i = 0 then error("Unknown slot \"".expr2text(r)."::".n."\"") end; if args(0) = 3 then subsop(r, i = v) else op(r, i) end end_proc):
Now, we can access the operands of rational numbers, which are the numerator and the denominator respectively, via our new slots:
>> slot(3/4, "numer"), (3/4)::numer, slot(3/4, "denom"), (3/4)::denom
3, 3, 4, 4
>> a := 3/4: slot(a, "numer", 7)
7/4
>> a::numer := 11: a
11/4
We restore the original behaviour:
>> delete DOM_RAT::slot, a: protect(DOM_RAT, Error):
f
, say, is
to be overloadable by user defined data types, a code segment as
indicated by the following lines is appropriate. It tests whether the
domain x::dom
of the argument x
contains a
method f
. If this is the case, this domain method is
called:
f:= proc(x) begin // check if f is overloaded by x if x::dom::f <> FAIL then // use the method of the domain of x return(x::dom::f(args())) else // execute the code for the function f endif end_proc:
slot
, slot access and slot
assignment can be implemented for other objects than domains or
function environments. Cf. example 9.n
of a slot may be an arbitrary
MuPAD object. Note, however, that the ::
-operator
cannot access slots defined by slot(d, n, v)
if the the
name n
is not a string.::
-operator: the calls d::"n"
and
d::n
are equivalent.slot
replaces and unifies the functions
domattr
and funcattr
of previous MuPAD
versions. The domain method "make_slot"
works exactly as
the former domain method domattr
.