A couple of weeks ago there was a discussion about
function parameters for modules. I linked to the
proposal Doug made some time ago.
I wanted to have that feature for quite some time
so I had a closer look at this. The result is at
https://github.com/openscad/openscad/pull/3077
which is a prototype implementation of function
literals.
This still needs work, specifically verifying that
the parser changes did not break any existing
behavior and verification that the scoping works
as defined.
Anyone interested in helping to get that ready
for merging?
ciao,
Torsten.
It looks nice. This is helpful when developing flexible modules and
functions, such as sort
, filter
, etc.
Sent from: http://forum.openscad.org/
So getting the variable scoping working needed a little
bit more work than anticipated, but it should be ok now.
Function literals capture the static scope as proposed
in:
https://github.com/doug-moen/openscad2/blob/master/rfc/Functions.md
Example with a function returning a function object
and using both lexical/static scoping of variable 'a'
and dynamic scoping of variable '$a'.
module m2(f1, f2) {
a = 3;
$a = 30;
echo(f1 = f1(0.03), f2 = f2(0.07));
}
module m1(f) {
a = 2;
$a = 20;
add2 = function(x) function(y) x + y + a + $a;
m2(f, add2(0.2));
}
a = 1;
$a = 10;
add1 = function(x) function(y) x + y + a + $a;
m1(add1(0.1));
// ECHO: f1 = 31.13, f2 = 32.27
Or for a more visual example defining a simple plot()
module taking a function.
module plot(count, f) {
for (x = [0 : count - 1]) {
translate([x, 0, 0]) cube([1, 1, 1 + f(x / count)]);
}
}
func_sin = function(x) 10 * sin(360 * x) + 10;
func_cos = function(x) 10 * cos(360 * x) + 10;
func_pow = function(x) 10 * pow(abs(4 * (x - 0.5)), 2);
funcs = [
[func_sin, 0, "red"],
[func_cos, 20, "green"],
[func_pow, 40, "yellow"]
];
for (func = funcs)
color(func[2])
translate([0, func[1], 0])
plot(100, func[0]);
Binary downloads of the current state of this branch:
Linux: https://app.circleci.com/jobs/github/openscad/openscad/3622/artifacts
Win32: https://app.circleci.com/jobs/github/openscad/openscad/3624/artifacts
Win64: https://app.circleci.com/jobs/github/openscad/openscad/3623/artifacts
ciao,
Torsten.
Very nice! This will be helpful with several things.
-Revar
On Sep 24, 2019, at 5:47 PM, Torsten Paul Torsten.Paul@gmx.de wrote:
So getting the variable scoping working needed a little
bit more work than anticipated, but it should be ok now.
Function literals capture the static scope as proposed
in:
https://github.com/doug-moen/openscad2/blob/master/rfc/Functions.md
Example with a function returning a function object
and using both lexical/static scoping of variable 'a'
and dynamic scoping of variable '$a'.
module m2(f1, f2) {
a = 3;
$a = 30;
echo(f1 = f1(0.03), f2 = f2(0.07));
}
module m1(f) {
a = 2;
$a = 20;
add2 = function(x) function(y) x + y + a + $a;
m2(f, add2(0.2));
}
a = 1;
$a = 10;
add1 = function(x) function(y) x + y + a + $a;
m1(add1(0.1));
// ECHO: f1 = 31.13, f2 = 32.27
Or for a more visual example defining a simple plot()
module taking a function.
module plot(count, f) {
for (x = [0 : count - 1]) {
translate([x, 0, 0]) cube([1, 1, 1 + f(x / count)]);
}
}
func_sin = function(x) 10 * sin(360 * x) + 10;
func_cos = function(x) 10 * cos(360 * x) + 10;
func_pow = function(x) 10 * pow(abs(4 * (x - 0.5)), 2);
funcs = [
[func_sin, 0, "red"],
[func_cos, 20, "green"],
[func_pow, 40, "yellow"]
];
for (func = funcs)
color(func[2])
translate([0, func[1], 0])
plot(100, func[0]);
Binary downloads of the current state of this branch:
Linux: https://app.circleci.com/jobs/github/openscad/openscad/3622/artifacts
Win32: https://app.circleci.com/jobs/github/openscad/openscad/3624/artifacts
Win64: https://app.circleci.com/jobs/github/openscad/openscad/3623/artifacts
ciao,
Torsten.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Just to close this thread, function literals are
now available in snapshot versions > 2019-10-24.
The feature is marked experimental, so it needs
to be enabled Preferences -> Features.
ciao,
Torsten.
Good news. It will give libraries great improvement. Looking forward to use
this feature in the next release.
Sent from: http://forum.openscad.org/
I wanted to clarify something. What if I want to write some code to operate
on functions, so
function foo(func) = ....;
If I want to pass an existing function like sin or cos, or maybe a function,
myfunc, that I defined, do I have to go through the whole syntax of
foo(function(x) sin(x))
or
foo(function(x,y) myfunc(x,y))
in order to do this? Or if I want to define a function variable to equal
an existing function, similarly do I need to use the full syntax:
func_var = function(x) sin(x);
when the right hand side refers to a function that already exists?
--
Sent from: http://forum.openscad.org/
On 03.11.19 22:40, adrianv wrote:
foo(function(x) sin(x))
Yes, all built-in functions and also those defined in
the previously existing function name() = expression
syntax have their own special namespace and are no values
that can be passed around. To do that they need to be
wrapped like that.
If a function literal is assigned to a variable, then
it can be passed around just like any other value too.
So:
f = function(x) x * x;
Is an unnamed function assigned to variable f, you
can assign it just like any other value to a different
variable:
g = f;
And because now g is of type function literal too:
echo(is_function(g)); // ECHO: true
It's possible to call it:
echo(g(5)); // ECHO: 25
Or pass it to a function or module:
module m(func) {
echo(func(4));
}
m(g); // ECHO: 16
ciao,
Torsten.
On 03.11.19 23:46, Parkinbot wrote:
will detect a recursion. While the following typo will
indeed brick OpenSCAD
sin = function(x) sin();
echo(sin(30));
That should have been caught be the tail recursion limit.
I've created a ticket to investigate why the limit is
not triggered.
https://github.com/openscad/openscad/issues/3118
ciao,
Torsten.
Yes! Just try it out.
function foo(a, f) = f(a);
echo(foo(30, sin));
gives obviously a syntax error: "Ignoring unknown variable 'sin' ... "
while the following code does what you intended.
echo(foo(30, function(x) sin(x)));
Trying to redefine sin() by
sin = function(x) sin(x);
in order to call
echo(foo(30, sin));
will detect a recursion. While the following typo will indeed brick OpenSCAD
sin = function(x) sin();
echo(sin(30));
--
Sent from: http://forum.openscad.org/