Method or entry of a domain or a function environment
This functionality does not run in MATLAB.
d::n slot(d, "n") d::n := v slot(d, "n", v) object::dom slot(object, "dom")
d::n returns the value of the slot named "n" of the object d.
d::n := v creates or changes the slot "n". The value v is assigned to the slot.
The function 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.
Any MuPAD® object has a special slot named "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.
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.
For a function environmentd, the call slot(d, "n", v) returns d with the changed slot "n" and changes the function environment d as a side-effect. This is the so-called "reference effect" of function environments. Cf. Example 2.
For a domaind, however, the call slot(d, "n", v) modifies d as a side-effect and returns the domain. This is the so-called "reference effect" of domains. Cf. Example 3.
The ::-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 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.
With 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.
For domains, there is a special mechanism to create new values for slots on demand. If a non existing slot is read, the method "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.
Every object has the slot "dom":
x::dom = domtype(x), slot(45, "dom") = domtype(45), sin::dom = domtype(sin)
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 := sin::float: s(1), sin(1)
With the following commands, 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 := funcenv(sin): s::float := x -> float(x - x^3/3!): s(PI/3) = sin(PI/3), s::float(1) <> sin::float(1)
If you are using the slot function to change slot entries in a domain, you must be aware that you are modifying the domain:
old_one := Dom::Float::one
newDomFloat := slot(Dom::Float, "one", 1): newDomFloat::one, Dom::Float::one
We restore the original state:
slot(Dom::Float, "one", old_one): Dom::Float::one
delete old_one, newDomFloat:
slot(sin, "sign"), sin::sign
We define a function environment for a function computing the logarithm to the base 3:
log3 := funcenv(x -> log(3, x)):
If the function info is to give some information about log3, we have to define the "info" slot for this function:
log3::info := "log3 -- the logarithm to the base 3":
log3 -- the logarithm to the base 3
The delete statement is used for deleting a slot:
delete log3::info: info(log3)
log3(x) -- a library procedure [try ?log3 for help]
It is not possible to delete the special slot "dom":
Error: The argument is invalid. [delete]
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")
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: Slot 'd::xyz' is unknown. [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") = (a,b)::dom, slot(null(), "dom") = (null())::dom
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":
Error: Slot '(3/4)::numer' is unknown. [slot]
unprotect(DOM_RAT): 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
a := 3/4: slot(a, "numer", 7)
a::numer := 11: a
We restore the original behavior:
delete DOM_RAT::slot, a: protect(DOM_RAT, Error):
The name of the slot: an identifier
The new value of the slot: an arbitrary MuPAD 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.
Overloading of system functions by domain elements is typically implemented as follows. If a library function 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:
By overloading the function slot, slot access and slot assignment can be implemented for other objects than domains or function environments. Cf. Example 9.
In principle, the name 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.
Strings may be used in conjunction with the ::-operator: the calls d::"n" and d::n are equivalent.