in-line definition of a (anonymous) function in Scilab language
deff(funcHeadline, funcBody) deff(definition) deff("[r1, r2, ...] = myFunc(in1, in2, ...)", funcBody) deff "r = myFunc(x,y) r = x^2 - y" deff "r = myFunc(x,y) x^2 - y" deff("r = @(x,y) x^2 - y") // as anonymous container's element myFunc = deff(funcHeadline, funcBody) myFunc = deff(definition) myFunc = deff("[r1, r2, ...] = fakeName(in1, in2, ...)", funcBody) myFunc = deff("r = fakeName(x,y) r = x^2 - y") myFunc = deff("r = fakeName(x,y) x^2 - y") myFunc = deff("r = @(x,y) x^2 - y")
- x, y, in1, in2, ...
- input arguments of the defined function. This one can have any number of input arguments, from 0 to any N.
- r, r1, r2, ...
- Output results of the defined function. This one can have any number of output results, from 0 to any M. If any, all output arguments must be explicit = written on the left-hand-side of the function name.
- Single string: Function's headline = its first line giving the local
function's name and the lists of its right-hand-side input arguments
and left-hand-side output arguments. Examples:
"myFunction(x,y)": no output
"r = myFunction(x,y)": single output
"[a,b] = myFunction(x,y)": two outputs. Etc..
functionkeyword must not be provided. b) If any, writting output arguments in the left-hand-side part of the headline is mandatory.
- a vector of texts = Scilab instructions of the function's body, in the order
they must be executed. These instructions must define and assign the value
of all output arguments. No trailing "endfunction" keyword is expected.
This vector is expected when deff(…) is called with two input arguments.
Single or double quotes included in instructions must be doubled to be protected.
- Single text or vector of texts, including both the function's headline and body.
- If it's a vector, it is equivalent to
definition = [funcHeadline ; funcBody].
- Otherwise, the one-string definition is equivalent to
funcHeadline + " " + strcat(funcBody,"; ").
- If it's a vector, it is equivalent to
- Public name and identifier of the defined function, as implicitly
returned in the current environment, or explicitly assigned to the
deff(…)'s output variable.
When deff(…) is called without explicit output argument but as an element of a container or as input argument of another function, it is implicitly assigned to this element or argument, which is anonymous. It is then an anonymous function. Example:
L = list(3, deff("r=noName(x) x.^2+1"), "Hello");. The result of deff(…) is assigned to L(2). Then,
L(2)(3.5) // ➜ 13.25.
deff(…) can be used to define a single function from Scilab
instructions provided through a matrix of text, instead of through any external
text file of instructions written in a
function … endfunction
block to be executed.
A source file of Scilab code can include the definition of several public functions.
This is not possible with deff(…): Only one public function can be defined.
However, as with a file, the body of the defined function can include one
function … endfunction blocks defining
some nested private functions.
Whatever is the deff(…) syntax used to provide the source code (see below), if this one includes a syntax error, deff(…) will yield a compilation error and stop.
Providing the source code
deff(funcHeadline, funcBody) (2 inputs) and deff([funcHeadline ; funcBody]) (single concatenated input) are equivalent.
funcBody is made of only one (short) string, it may be glued
to and passed with the
funcHeadline, as a one-line function
When the result of deff(…) is assigned to or inserted into any anonymous element
of a container, then it comes that the pseudo-name
defined in the
has no role at all, and could in no way be used to call the function.
This name can then be replaced with the "@" character in the
to highlight that the defined function becomes anonymous.
Identifier of the defined function
The identifier is the actual word (name) to use to call the defined function. The 3 following cases are illustrated in examples.
When the defined function is not expected as a assignable result, its identifier is returned directly in the calling environment. Its public name is then the name used in the headline of the provided source code.
Otherwise, when deff(…) is called with an explicit output argument, the name of this one becomes the only actual public function's identifier. As a consequence, the function name used in the source code can't be used to call it. It becomes a pseudo-name. For this reason, the "@" symbol (standing for "anonymous") can then be used in the function code's headline, instead of any valid function's name. Of course, nothing prevents to use an output name identical to any valid function name defined in the headline. But it's not mandatory.
The last case is using deff(…) as an element of a container, for instance
when defining or inserting into a list, or as input argument of another function.
Then deff(…) works in an assignable way. It returns the identifier of the defined
function and assigns it to the considered list element or input argument.
These ones are nameless, since the
deff(…) call is an expression.
The defined function then becomes really anonymous.
deff('x = myplus(y,z)', 'x = y+z') myplus(1,%i) deff('[y, z] = mymacro(x)', ['y = 3*x+1'; 'z = a*x + x.^2']) a = 3; [u, v] = mymacro(2)
--> deff('x = myplus(y,z)', 'x = y+z') --> myplus(1,%i) ans = 1. + i --> deff('[y, z] = mymacro(x)', ['y = 3*x+1'; 'z = a*x + x.^2']) --> a = 3; --> [u, v] = mymacro(2) v = 10. u = 7.
With some single input and output:
clear myFunc source = ["r = myFunc(x,y)" ; "r = x.*(x-y)"] deff(source) myFunc(3, -2)
--> source = ["r = myFunc(x,y)" ; "r = x.*(x-y)"] source = "r = myFunc(x,y)" "r = x.*(x-y)" --> deff(source) --> myFunc(3, -2) ans = 15.
Same example with a one-line definition, that then allows a console-oriented syntax (without optional deff parentheses, but with still mandatory delimiting quotes):
clear myFunc deff "r = myFunc(x,y) r = x.*(x-y)" myFunc(1:3, -2)
--> deff "r = myFunc(x,y) r = x.*(x-y)" --> myFunc(1:3, -2) ans = 3. 8. 15.
For a one-line direct definition with a single output, we can even omit the "r = " duplicate in the body:
clear myFunc deff "r = myFunc(x,y) x.*(x-y)" myFunc(1:3, -2)
--> deff "r = myFunc(x,y) x.*(x-y)" --> myFunc(1:3, -2) ans = 3. 8. 15.
Function with no assignable output: Note also the usage of doubled quotes to protect them in the definition string:
clear myFunc deff("myFunc(x, y) messagebox(prettyprint(x.*(x-y), ""html"",""""))") myFunc([1 2 ; 3 4], -2)
Defined function assigned to a recipient
Let's keep similar examples as above:
--> actualName = deff("r = myFunc(x,y) x.*(x-y)") actualName = [r]=actualName(x,y) --> isdef(["myFunc" "actualName"]) ans = F T --> actualName(1:3, -2) ans = 3. 8. 15. --> myFunc(1:3, -2) Undefined variable: myFunc
Since the "internal" function name is fake, we can use "@" instead (the "@" character is not allowed in actual function names):
clear actualName actualName = deff("r = @(x,y) x.*(x-y)"); actualName(1:3, -2)
--> actualName = deff("r = @(x,y) x.*(x-y)"); --> actualName(1:3, -2) ans = 3. 8. 15.
Now, let's directly assign the created function to a nameless recipient. Although the function becomes anonymous, we can still call it:
L = list("abc", deff("r = @(x,y) x.*(x-y)"), %z); L(2)(1.1:4, -2.1) // We can extract and set a name to the anonymous function: Abc = L(2) Abc(1.1:4, -2.1)
--> L = list("abc", deff("r = @(x,y) x.*(x-y)"), %z); --> L(2)(1.1:4, -2.1) ans = 3.52 8.82 16.12 --> Abc = L(2) Abc = [r]=Abc(x,y) --> Abc(1.1:4, -2.1) ans = 3.52 8.82 16.12
Finally, let's use deff() to directly define and pass a function as an input argument of another function:
function r=test(txt, x, theFunc) r = x + theFunc(txt) endfunction test(rand(2,3), 0.7, deff("r = @(M) sum(size(M).^2)"))
--> test(rand(2,3), 0.7, deff("r = @(M) sum(size(M).^2)")) ans = 13.7
In this example, the passed function is anonymous in the calling environment, but is assigned and gets its "theFunct" name from inside the called function.
|Report an issue|
|<< argn||Advanced functions||exec >>|