discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Functions literals / higher order functions

TP
Torsten Paul
Mon, Sep 16, 2019 1:08 AM

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.

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.
C
caterpillar
Mon, Sep 16, 2019 5:07 AM

It looks nice. This is helpful when developing flexible modules and
functions, such as sort, filter, etc.


http://openhome.cc

Sent from: http://forum.openscad.org/

It looks nice. This is helpful when developing flexible modules and functions, such as `sort`, `filter`, etc. ----- http://openhome.cc -- Sent from: http://forum.openscad.org/
TP
Torsten Paul
Wed, Sep 25, 2019 12:46 AM

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.

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.
RD
Revar Desmera
Thu, Sep 26, 2019 9:45 PM

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

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
TP
Torsten Paul
Mon, Oct 28, 2019 12:17 AM

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.

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.
C
caterpillar
Mon, Oct 28, 2019 9:21 AM

Good news. It will give libraries great improvement. Looking forward to use
this feature in the next release.


https://openhome.cc

Sent from: http://forum.openscad.org/

Good news. It will give libraries great improvement. Looking forward to use this feature in the next release. ----- https://openhome.cc -- Sent from: http://forum.openscad.org/
A
adrianv
Sun, Nov 3, 2019 9:40 PM

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/

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/
TP
Torsten Paul
Sun, Nov 3, 2019 10:39 PM

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 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.
TP
Torsten Paul
Sun, Nov 3, 2019 10:46 PM

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.

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.
P
Parkinbot
Sun, Nov 3, 2019 10:46 PM

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/

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/
A
adrianv
Sat, Nov 9, 2019 3:15 PM

tp3 wrote

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.

Would it be worth adding a simpler mechanism for passing existing functions?
It seems like the existing scheme creates two independent namespaces for
functions and it's sort of clumsy to get between them.  In MATLAB, for
example, you can pass an existing function by writing "@sin".  I can
imagine having to write code where I generate a table of function
redefinitions to make it easy to pass pre-existing functions without the
need for all the verbosity of a function declaration embedded in the code
for every call.

What would be the disadvantage of writing all of my functions using the new
syntax.  Would there be any problems with this?  So  always write

funcname = function(...) definition....;

This seems like it could be desirable since you can do something with a
function literal defined this way that you can't do with a regular function.
And there is no apparent advantage to defining functions the "normal" way.
I mean, the one obvious limitation is that I no longer have a different
namespace for functions if I do this.

--
Sent from: http://forum.openscad.org/

tp3 wrote > 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. Would it be worth adding a simpler mechanism for passing existing functions? It seems like the existing scheme creates two independent namespaces for functions and it's sort of clumsy to get between them. In MATLAB, for example, you can pass an existing function by writing "@sin". I can imagine having to write code where I generate a table of function redefinitions to make it easy to pass pre-existing functions without the need for all the verbosity of a function declaration embedded in the code for every call. What would be the disadvantage of writing all of my functions using the new syntax. Would there be any problems with this? So always write funcname = function(...) definition....; This seems like it could be desirable since you can do something with a function literal defined this way that you can't do with a regular function. And there is no apparent advantage to defining functions the "normal" way. I mean, the one obvious limitation is that I no longer have a different namespace for functions if I do this. -- Sent from: http://forum.openscad.org/
NH
nop head
Sat, Nov 9, 2019 3:15 PM

The issue is the old format functions have their own namespace,
separate from variables and modules so you can have the same name it all
three namespaces and there is no ambiguity. However new style function
literals are anonymous until you assign them to a variable and then that
variable is in the variable namespace, not the function namespace.

On Sat, 9 Nov 2019 at 15:03, adrianv avm4@cornell.edu wrote:

tp3 wrote

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.

Would it be worth adding a simpler mechanism for passing existing
functions?
It seems like the existing scheme creates two independent namespaces for
functions and it's sort of clumsy to get between them.  In MATLAB, for
example, you can pass an existing function by writing "@sin".  I can
imagine having to write code where I generate a table of function
redefinitions to make it easy to pass pre-existing functions without the
need for all the verbosity of a function declaration embedded in the code
for every call.

What would be the disadvantage of writing all of my functions using the new
syntax.  Would there be any problems with this?  So  always write

funcname = function(...) definition....;

This seems like it could be desirable since you can do something with a
function literal defined this way that you can't do with a regular
function.
And there is no apparent advantage to defining functions the "normal"
way.
I mean, the one obvious limitation is that I no longer have a different
namespace for functions if I do this.

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

The issue is the old format functions have their own namespace, separate from variables and modules so you can have the same name it all three namespaces and there is no ambiguity. However new style function literals are anonymous until you assign them to a variable and then that variable is in the variable namespace, not the function namespace. On Sat, 9 Nov 2019 at 15:03, adrianv <avm4@cornell.edu> wrote: > tp3 wrote > > 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. > > Would it be worth adding a simpler mechanism for passing existing > functions? > It seems like the existing scheme creates two independent namespaces for > functions and it's sort of clumsy to get between them. In MATLAB, for > example, you can pass an existing function by writing "@sin". I can > imagine having to write code where I generate a table of function > redefinitions to make it easy to pass pre-existing functions without the > need for all the verbosity of a function declaration embedded in the code > for every call. > > What would be the disadvantage of writing all of my functions using the new > syntax. Would there be any problems with this? So always write > > funcname = function(...) definition....; > > This seems like it could be desirable since you can do something with a > function literal defined this way that you can't do with a regular > function. > And there is no apparent advantage to defining functions the "normal" > way. > I mean, the one obvious limitation is that I no longer have a different > namespace for functions if I do this. > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Sat, Nov 9, 2019 3:33 PM

Yeah, I was aware of that.  But I don't think I'd really miss this.  In most
languages, functions don't get a separate namespace from variables, so it's
actually kind of an odd quirk of OpenSCAD.  I wonder if there are any other
issues I have overlooked, or relating to performance.

nophead wrote

The issue is the old format functions have their own namespace,
separate from variables and modules so you can have the same name it all
three namespaces and there is no ambiguity. However new style function
literals are anonymous until you assign them to a variable and then that
variable is in the variable namespace, not the function namespace.

On Sat, 9 Nov 2019 at 15:03, adrianv <

avm4@

> wrote:

I mean, the one obvious limitation is that I no longer have a different
namespace for functions if I do this.

Yeah, I was aware of that. But I don't think I'd really miss this. In most languages, functions don't get a separate namespace from variables, so it's actually kind of an odd quirk of OpenSCAD. I wonder if there are any other issues I have overlooked, or relating to performance. nophead wrote > The issue is the old format functions have their own namespace, > separate from variables and modules so you can have the same name it all > three namespaces and there is no ambiguity. However new style function > literals are anonymous until you assign them to a variable and then that > variable is in the variable namespace, not the function namespace. > > On Sat, 9 Nov 2019 at 15:03, adrianv &lt; > avm4@ > &gt; wrote: > > >> I mean, the one obvious limitation is that I no longer have a different >> namespace for functions if I do this. -- Sent from: http://forum.openscad.org/
TP
Torsten Paul
Sat, Nov 9, 2019 3:46 PM

On 09.11.19 16:15, adrianv wrote:

Would it be worth adding a simpler mechanism for passing
existing functions?

Yes, that certainly is open for discussion. It might even be
possible to bind the built-in functions to the respective
names in the variable namespace.

As that is one layer up from the top layer available to the
user, it would still be possible to just overwrite those names
in existing code.

I believe the only non-compatible change is that you can
still observe this by "if (is_undef(sin))" on top level.

It seems like the existing scheme creates two independent
namespaces for functions and it's sort of clumsy to get
between them.

The other way around. Those separate namespaces already exist
and cause the issues now. The problem is that first class
functions obviously need to be in the variable namespace as
they are really just values.

What would be the disadvantage of writing all of my functions
using the new syntax. Would there be any problems with this?
So always write

funcname = function(...) definition....;

Right now, the only disadvantage I'm aware of is that use<>
will not import them as they are variables, and use<> only
imports (old style) functions and modules.

That's something which needs to be changed of cause.

ciao,
Torsten.

On 09.11.19 16:15, adrianv wrote: > Would it be worth adding a simpler mechanism for passing > existing functions? Yes, that certainly is open for discussion. It might even be possible to bind the built-in functions to the respective names in the variable namespace. As that is one layer up from the top layer available to the user, it would still be possible to just overwrite those names in existing code. I believe the only non-compatible change is that you can still observe this by "if (is_undef(sin))" on top level. > It seems like the existing scheme creates two independent > namespaces for functions and it's sort of clumsy to get > between them. The other way around. Those separate namespaces already exist and cause the issues now. The problem is that first class functions obviously need to be in the variable namespace as they are really just values. > What would be the disadvantage of writing all of my functions > using the new syntax. Would there be any problems with this? > So always write > > funcname = function(...) definition....; Right now, the only disadvantage I'm aware of is that use<> will not import them as they are variables, and use<> only imports (old style) functions and modules. That's something which needs to be changed of cause. ciao, Torsten.
NH
nop head
Sat, Nov 9, 2019 3:51 PM

But I don't think I'd really miss this.

Maybe but people like me would as I have made extensive use of it so
changing it would break a lot of code.

On Sat, 9 Nov 2019 at 15:47, Torsten Paul Torsten.Paul@gmx.de wrote:

On 09.11.19 16:15, adrianv wrote:

Would it be worth adding a simpler mechanism for passing
existing functions?

Yes, that certainly is open for discussion. It might even be
possible to bind the built-in functions to the respective
names in the variable namespace.

As that is one layer up from the top layer available to the
user, it would still be possible to just overwrite those names
in existing code.

I believe the only non-compatible change is that you can
still observe this by "if (is_undef(sin))" on top level.

It seems like the existing scheme creates two independent
namespaces for functions and it's sort of clumsy to get
between them.

The other way around. Those separate namespaces already exist
and cause the issues now. The problem is that first class
functions obviously need to be in the variable namespace as
they are really just values.

What would be the disadvantage of writing all of my functions
using the new syntax. Would there be any problems with this?
So always write

funcname = function(...) definition....;

Right now, the only disadvantage I'm aware of is that use<>
will not import them as they are variables, and use<> only
imports (old style) functions and modules.

That's something which needs to be changed of cause.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

> But I don't think I'd really miss this. Maybe but people like me would as I have made extensive use of it so changing it would break a lot of code. On Sat, 9 Nov 2019 at 15:47, Torsten Paul <Torsten.Paul@gmx.de> wrote: > On 09.11.19 16:15, adrianv wrote: > > Would it be worth adding a simpler mechanism for passing > > existing functions? > > Yes, that certainly is open for discussion. It might even be > possible to bind the built-in functions to the respective > names in the variable namespace. > > As that is one layer up from the top layer available to the > user, it would still be possible to just overwrite those names > in existing code. > > I believe the only non-compatible change is that you can > still observe this by "if (is_undef(sin))" on top level. > > > It seems like the existing scheme creates two independent > > namespaces for functions and it's sort of clumsy to get > > between them. > > The other way around. Those separate namespaces already exist > and cause the issues now. The problem is that first class > functions obviously need to be in the variable namespace as > they are really just values. > > > What would be the disadvantage of writing all of my functions > > using the new syntax. Would there be any problems with this? > > So always write > > > > funcname = function(...) definition....; > > Right now, the only disadvantage I'm aware of is that use<> > will not import them as they are variables, and use<> only > imports (old style) functions and modules. > > That's something which needs to be changed of cause. > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
A
adrianv
Sat, Nov 9, 2019 6:01 PM

I wasn't suggesting that the old syntax be removed.  Rather, I was pondering
how to write code in the future.  It appears like with the new function
syntax that it might make sense to always use the new one.  In other words,
to treat the old syntax like a sort of old-style method and abandon it.

Out of curiosity, is there some particular use case for using variables with
the same name as functions, or you just find it convenient to make variables
named "square" and "cube" and so on?

nophead wrote

But I don't think I'd really miss this.

Maybe but people like me would as I have made extensive use of it so
changing it would break a lot of code.

On Sat, 9 Nov 2019 at 15:47, Torsten Paul <

Torsten.Paul@

> wrote:

On 09.11.19 16:15, adrianv wrote:

Would it be worth adding a simpler mechanism for passing
existing functions?

Yes, that certainly is open for discussion. It might even be
possible to bind the built-in functions to the respective
names in the variable namespace.

As that is one layer up from the top layer available to the
user, it would still be possible to just overwrite those names
in existing code.

I believe the only non-compatible change is that you can
still observe this by "if (is_undef(sin))" on top level.

It seems like the existing scheme creates two independent
namespaces for functions and it's sort of clumsy to get
between them.

The other way around. Those separate namespaces already exist
and cause the issues now. The problem is that first class
functions obviously need to be in the variable namespace as
they are really just values.

What would be the disadvantage of writing all of my functions
using the new syntax. Would there be any problems with this?
So always write

funcname = function(...) definition....;

Right now, the only disadvantage I'm aware of is that use<>
will not import them as they are variables, and use<> only
imports (old style) functions and modules.

That's something which needs to be changed of cause.

ciao,
Torsten.


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

I wasn't suggesting that the old syntax be removed. Rather, I was pondering how to write code in the future. It appears like with the new function syntax that it might make sense to always use the new one. In other words, to treat the old syntax like a sort of old-style method and abandon it. Out of curiosity, is there some particular use case for using variables with the same name as functions, or you just find it convenient to make variables named "square" and "cube" and so on? nophead wrote >> But I don't think I'd really miss this. > > Maybe but people like me would as I have made extensive use of it so > changing it would break a lot of code. > > On Sat, 9 Nov 2019 at 15:47, Torsten Paul &lt; > Torsten.Paul@ > &gt; wrote: > >> On 09.11.19 16:15, adrianv wrote: >> > Would it be worth adding a simpler mechanism for passing >> > existing functions? >> >> Yes, that certainly is open for discussion. It might even be >> possible to bind the built-in functions to the respective >> names in the variable namespace. >> >> As that is one layer up from the top layer available to the >> user, it would still be possible to just overwrite those names >> in existing code. >> >> I believe the only non-compatible change is that you can >> still observe this by "if (is_undef(sin))" on top level. >> >> > It seems like the existing scheme creates two independent >> > namespaces for functions and it's sort of clumsy to get >> > between them. >> >> The other way around. Those separate namespaces already exist >> and cause the issues now. The problem is that first class >> functions obviously need to be in the variable namespace as >> they are really just values. >> >> > What would be the disadvantage of writing all of my functions >> > using the new syntax. Would there be any problems with this? >> > So always write >> > >> > funcname = function(...) definition....; >> >> Right now, the only disadvantage I'm aware of is that use<> >> will not import them as they are variables, and use<> only >> imports (old style) functions and modules. >> >> That's something which needs to be changed of cause. >> >> ciao, >> Torsten. >> >> _______________________________________________ >> OpenSCAD mailing list >> > Discuss@.openscad >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
NH
nop head
Sat, Nov 9, 2019 7:43 PM

I often have code like this:

screw = iec_screw(type);

...

screw(screw, screw_length);

screw is both a local variable and a global module. Because it is local it
isn't really appropriate to give it a longer name, like the_screw or
iec_screw. If it was iec_screw then again it is the same name as a
function. In other languages I would have to think up a different name.

On Sat, 9 Nov 2019 at 17:49, adrianv avm4@cornell.edu wrote:

I wasn't suggesting that the old syntax be removed.  Rather, I was
pondering
how to write code in the future.  It appears like with the new function
syntax that it might make sense to always use the new one.  In other words,
to treat the old syntax like a sort of old-style method and abandon it.

Out of curiosity, is there some particular use case for using variables
with
the same name as functions, or you just find it convenient to make
variables
named "square" and "cube" and so on?

nophead wrote

But I don't think I'd really miss this.

Maybe but people like me would as I have made extensive use of it so
changing it would break a lot of code.

On Sat, 9 Nov 2019 at 15:47, Torsten Paul <

Torsten.Paul@

> wrote:

On 09.11.19 16:15, adrianv wrote:

Would it be worth adding a simpler mechanism for passing
existing functions?

Yes, that certainly is open for discussion. It might even be
possible to bind the built-in functions to the respective
names in the variable namespace.

As that is one layer up from the top layer available to the
user, it would still be possible to just overwrite those names
in existing code.

I believe the only non-compatible change is that you can
still observe this by "if (is_undef(sin))" on top level.

It seems like the existing scheme creates two independent
namespaces for functions and it's sort of clumsy to get
between them.

The other way around. Those separate namespaces already exist
and cause the issues now. The problem is that first class
functions obviously need to be in the variable namespace as
they are really just values.

What would be the disadvantage of writing all of my functions
using the new syntax. Would there be any problems with this?
So always write

funcname = function(...) definition....;

Right now, the only disadvantage I'm aware of is that use<>
will not import them as they are variables, and use<> only
imports (old style) functions and modules.

That's something which needs to be changed of cause.

ciao,
Torsten.


OpenSCAD mailing list

Discuss@.openscad

Discuss@.openscad

I often have code like this: screw = iec_screw(type); ... screw(screw, screw_length); screw is both a local variable and a global module. Because it is local it isn't really appropriate to give it a longer name, like the_screw or iec_screw. If it was iec_screw then again it is the same name as a function. In other languages I would have to think up a different name. On Sat, 9 Nov 2019 at 17:49, adrianv <avm4@cornell.edu> wrote: > I wasn't suggesting that the old syntax be removed. Rather, I was > pondering > how to write code in the future. It appears like with the new function > syntax that it might make sense to always use the new one. In other words, > to treat the old syntax like a sort of old-style method and abandon it. > > Out of curiosity, is there some particular use case for using variables > with > the same name as functions, or you just find it convenient to make > variables > named "square" and "cube" and so on? > > > nophead wrote > >> But I don't think I'd really miss this. > > > > Maybe but people like me would as I have made extensive use of it so > > changing it would break a lot of code. > > > > On Sat, 9 Nov 2019 at 15:47, Torsten Paul &lt; > > > Torsten.Paul@ > > > &gt; wrote: > > > >> On 09.11.19 16:15, adrianv wrote: > >> > Would it be worth adding a simpler mechanism for passing > >> > existing functions? > >> > >> Yes, that certainly is open for discussion. It might even be > >> possible to bind the built-in functions to the respective > >> names in the variable namespace. > >> > >> As that is one layer up from the top layer available to the > >> user, it would still be possible to just overwrite those names > >> in existing code. > >> > >> I believe the only non-compatible change is that you can > >> still observe this by "if (is_undef(sin))" on top level. > >> > >> > It seems like the existing scheme creates two independent > >> > namespaces for functions and it's sort of clumsy to get > >> > between them. > >> > >> The other way around. Those separate namespaces already exist > >> and cause the issues now. The problem is that first class > >> functions obviously need to be in the variable namespace as > >> they are really just values. > >> > >> > What would be the disadvantage of writing all of my functions > >> > using the new syntax. Would there be any problems with this? > >> > So always write > >> > > >> > funcname = function(...) definition....; > >> > >> Right now, the only disadvantage I'm aware of is that use<> > >> will not import them as they are variables, and use<> only > >> imports (old style) functions and modules. > >> > >> That's something which needs to be changed of cause. > >> > >> ciao, > >> Torsten. > >> > >> _______________________________________________ > >> OpenSCAD mailing list > >> > > > Discuss@.openscad > > >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >> > > > > _______________________________________________ > > OpenSCAD mailing list > > > Discuss@.openscad > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Wed, Nov 20, 2019 5:09 PM

f = function(a)  a;
echo(f==f); // ECHO: false

???

OpenSCAD version 2019.10.25.ci3851 (git feee8f02)

Torsten Paul Torsten.Paul@gmx.de wrote:

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.

f = function(a) a; echo(f==f); // ECHO: false ??? OpenSCAD version 2019.10.25.ci3851 (git feee8f02) Torsten Paul <Torsten.Paul@gmx.de> wrote: > 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. >
TP
Torsten Paul
Wed, Nov 20, 2019 5:35 PM

Yes, currently you can't compare function literals.

Yes, currently you can't compare function literals.
RP
Ronaldo Persiano
Tue, Nov 26, 2019 12:08 AM

I can't see why the following generates a stack overflow:

function move(a, g) =
function(x) g(x+a) ;

g1 = function(x) x;
g2 = move(0,g1);
g3 = move(0,g2);

echo(g3_x=g3);
echo(g3_2=g3(2));

If g3 is defined as g2 no error is reported.

I can't see why the following generates a stack overflow: function move(a, g) = function(x) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); g3 = move(0,g2); echo(g3_x=g3); echo(g3_2=g3(2)); If g3 is defined as g2 no error is reported.
MM
Michael Marx
Tue, Nov 26, 2019 12:51 AM

I get

Compiling design (CSG Tree generation)...

ECHO: g3_x = function(x) g((x + a))

ERROR: Recursion detected calling function 'g' in file fn literals parkinbot.scad, line 4

TRACE: called by 'g', in file fn literals parkinbot.scad, line 4.

TRACE: called by 'g3', in file fn literals parkinbot.scad, line 13.

TRACE: called by 'echo', in file fn literals parkinbot.scad, line 13.

Compiling design (CSG Products generation)...

When I changed it to:

function move(a, g) =

function(x)

//echo(a,g) 

  g(x+a) ;

g1 = function(x) x;

g2 = move(0,g1);

g3 = move(1,g2);

echo(g3_x=g3);

echo(g3_2=g3(2));

removing the comments causes a seeming infinite recursion echoing to the console, had to quit the
gui, then it crashed.


From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano
Sent: Tue, 26 Nov 2019 11:08
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] Functions literals / higher order functions

I can't see why the following generates a stack overflow:

function move(a, g) =

function(x) g(x+a) ;

g1 = function(x) x;

g2 = move(0,g1);

g3 = move(0,g2);

echo(g3_x=g3);

echo(g3_2=g3(2));

If g3 is defined as g2 no error is reported.

I get Compiling design (CSG Tree generation)... ECHO: g3_x = function(x) g((x + a)) ERROR: Recursion detected calling function 'g' in file fn literals parkinbot.scad, line 4 TRACE: called by 'g', in file fn literals parkinbot.scad, line 4. TRACE: called by 'g3', in file fn literals parkinbot.scad, line 13. TRACE: called by 'echo', in file fn literals parkinbot.scad, line 13. Compiling design (CSG Products generation)... When I changed it to: function move(a, g) = function(x) //echo(a,g) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); g3 = move(1,g2); echo(g3_x=g3); echo(g3_2=g3(2)); removing the comments causes a seeming infinite recursion echoing to the console, had to quit the gui, then it crashed. _____ From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano Sent: Tue, 26 Nov 2019 11:08 To: OpenSCAD general discussion Subject: Re: [OpenSCAD] Functions literals / higher order functions I can't see why the following generates a stack overflow: function move(a, g) = function(x) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); g3 = move(0,g2); echo(g3_x=g3); echo(g3_2=g3(2)); If g3 is defined as g2 no error is reported.
MM
Michael Marx
Tue, Nov 26, 2019 1:07 AM

I expect it is a scope issue with the 'move' function, I'll mention it on GitHub.


From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Michael Marx
Sent: Tue, 26 Nov 2019 11:51
To: 'OpenSCAD general discussion'
Subject: Re: [OpenSCAD] Functions literals / higher order functions

I get

Compiling design (CSG Tree generation)...

ECHO: g3_x = function(x) g((x + a))

ERROR: Recursion detected calling function 'g' in file fn literals parkinbot.scad, line 4

TRACE: called by 'g', in file fn literals parkinbot.scad, line 4.

TRACE: called by 'g3', in file fn literals parkinbot.scad, line 13.

TRACE: called by 'echo', in file fn literals parkinbot.scad, line 13.

Compiling design (CSG Products generation)...

When I changed it to:

function move(a, g) =

function(x)

//echo(a,g) 

  g(x+a) ;

g1 = function(x) x;

g2 = move(0,g1);

g3 = move(1,g2);

echo(g3_x=g3);

echo(g3_2=g3(2));

removing the comments causes a seeming infinite recursion echoing to the console, had to quit the
gui, then it crashed.


From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano
Sent: Tue, 26 Nov 2019 11:08
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] Functions literals / higher order functions

I can't see why the following generates a stack overflow:

function move(a, g) =

function(x) g(x+a) ;

g1 = function(x) x;

g2 = move(0,g1);

g3 = move(0,g2);

echo(g3_x=g3);

echo(g3_2=g3(2));

If g3 is defined as g2 no error is reported.

I expect it is a scope issue with the 'move' function, I'll mention it on GitHub. _____ From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Michael Marx Sent: Tue, 26 Nov 2019 11:51 To: 'OpenSCAD general discussion' Subject: Re: [OpenSCAD] Functions literals / higher order functions I get Compiling design (CSG Tree generation)... ECHO: g3_x = function(x) g((x + a)) ERROR: Recursion detected calling function 'g' in file fn literals parkinbot.scad, line 4 TRACE: called by 'g', in file fn literals parkinbot.scad, line 4. TRACE: called by 'g3', in file fn literals parkinbot.scad, line 13. TRACE: called by 'echo', in file fn literals parkinbot.scad, line 13. Compiling design (CSG Products generation)... When I changed it to: function move(a, g) = function(x) //echo(a,g) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); g3 = move(1,g2); echo(g3_x=g3); echo(g3_2=g3(2)); removing the comments causes a seeming infinite recursion echoing to the console, had to quit the gui, then it crashed. _____ From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano Sent: Tue, 26 Nov 2019 11:08 To: OpenSCAD general discussion Subject: Re: [OpenSCAD] Functions literals / higher order functions I can't see why the following generates a stack overflow: function move(a, g) = function(x) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); g3 = move(0,g2); echo(g3_x=g3); echo(g3_2=g3(2)); If g3 is defined as g2 no error is reported.
M
MichaelAtOz
Tue, Nov 26, 2019 1:49 AM

As I mentioned  On GitHub here
https://github.com/openscad/openscad/pull/3077#issuecomment-558417555  ,
this stops the infinite recursion, don't know why, need caffeine...

function move(a, g) = echo(move=a,g)
function(x)
echo(g_in_move=a,x)
(x+a) ;

g1 = function(x)

      x;

g2 = move(1,g1);
g3 = move(3,g2);

echo(g1_=g1);
echo(g1_1=g1(1));
echo(g2_=g2);
echo(g2_7=g2(7));
echo(g3_x=g3);
echo(g3_5=g3(5));

Gets:

Compiling design (CSG Tree generation)...
ECHO: move = 1, function(x) x
ECHO: move = 3, function(x) echo(g_in_move = a, x) (x + a)
ECHO: g1_ = function(x) x
ECHO: g1_1 = 1
ECHO: g2_ = function(x) echo(g_in_move = a, x) (x + a)
ECHO: g_in_moveg = 1, 7
ECHO: g2_7 = 8
ECHO: g3_x = function(x) echo(g_in_move = a, x) (x + a)
ECHO: g_in_moveg = 3, 5
ECHO: g3_5 = 8
Compiling design (CSG Products generation)...
Geometries in cache: 0


Admin - email* me if you need anything,  or if I've done something stupid...

  • click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

--
Sent from: http://forum.openscad.org/

As I mentioned On GitHub here <https://github.com/openscad/openscad/pull/3077#issuecomment-558417555> , this stops the infinite recursion, don't know why, need caffeine... function move(a, g) = echo(move=a,g) function(x) echo(g_in_move=a,x) (x+a) ; g1 = function(x) x; g2 = move(1,g1); g3 = move(3,g2); echo(g1_=g1); echo(g1_1=g1(1)); echo(g2_=g2); echo(g2_7=g2(7)); echo(g3_x=g3); echo(g3_5=g3(5)); Gets: Compiling design (CSG Tree generation)... ECHO: move = 1, function(x) x ECHO: move = 3, function(x) echo(g_in_move = a, x) (x + a) ECHO: g1_ = function(x) x ECHO: g1_1 = 1 ECHO: g2_ = function(x) echo(g_in_move = a, x) (x + a) ECHO: g_in_moveg = 1, 7 ECHO: g2_7 = 8 ECHO: g3_x = function(x) echo(g_in_move = a, x) (x + a) ECHO: g_in_moveg = 3, 5 ECHO: g3_5 = 8 Compiling design (CSG Products generation)... Geometries in cache: 0 ----- Admin - email* me if you need anything, or if I've done something stupid... * click on my MichaelAtOz label, there is a link to email me. Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Tue, Nov 26, 2019 2:08 AM

Michael,

You may need another coffee after confirming that the following runs
without error:

function move(a, g) =
function(x) g(x+a) ;

g1 = function(x) x;
g2 = move(0,g1);
//g0 = g2;
g0 = function(x) g2(x) ;
g3 = move(0,g0);

echo(g3_x=g3);
echo(g3_2=g3(2));

unless the commented line substitute the g0 definition.

Compiling design (CSG Tree generation)...

ECHO: g3_x = function(x) g((x + a))

ECHO: g3_2 = 2

Compiling design (CSG Products generation)...

Geometries in cache: 5

Geometry cache size in bytes: 1774120

CGAL Polyhedrons in cache: 0

CGAL cache size in bytes: 0

Compiling design (CSG Products normalization)...

Normalized CSG tree has 0 elements

Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 0 seconds

Michael, You may need another coffee after confirming that the following runs without error: function move(a, g) = function(x) g(x+a) ; g1 = function(x) x; g2 = move(0,g1); //g0 = g2; g0 = function(x) g2(x) ; g3 = move(0,g0); echo(g3_x=g3); echo(g3_2=g3(2)); unless the commented line substitute the g0 definition. Compiling design (CSG Tree generation)... ECHO: g3_x = function(x) g((x + a)) ECHO: g3_2 = 2 Compiling design (CSG Products generation)... Geometries in cache: 5 Geometry cache size in bytes: 1774120 CGAL Polyhedrons in cache: 0 CGAL cache size in bytes: 0 Compiling design (CSG Products normalization)... Normalized CSG tree has 0 elements Compile and preview finished. Total rendering time: 0 hours, 0 minutes, 0 seconds >
RP
Ronaldo Persiano
Tue, Nov 26, 2019 2:23 AM

Inserting an indirection also works fine:

function move(a, g) =
function(x) identity(x+a) ;

function  identity(x) = x;

g1 = function(x) x;
g2 = move(0,g1);
g3 = move(0,g2);

echo(g3_x=g3);
echo(g3_2=g3(2));

Inserting an indirection also works fine: function move(a, g) = function(x) identity(x+a) ; function identity(x) = x; g1 = function(x) x; g2 = move(0,g1); g3 = move(0,g2); echo(g3_x=g3); echo(g3_2=g3(2)); > >
M
MichaelAtOz
Tue, Nov 26, 2019 2:29 AM

Oops, at line 4, dropped the g() in my edits...


Admin - email* me if you need anything,  or if I've done something stupid...

  • click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

--
Sent from: http://forum.openscad.org/

Oops, at line 4, dropped the g() in my edits... ----- Admin - email* me if you need anything, or if I've done something stupid... * click on my MichaelAtOz label, there is a link to email me. Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Tue, Nov 26, 2019 2:58 AM

I followed Michael and also dropped the g. But anyway, the last code still
works fine with

function move(a, g) =
function(x) identity(g(x+a)) ;

Em ter., 26 de nov. de 2019 às 02:23, Ronaldo Persiano <
rcmpersiano@gmail.com> escreveu:

Inserting an indirection also works fine:

function move(a, g) =
function(x) identity(x+a) ;

function  identity(x) = x;

g1 = function(x) x;
g2 = move(0,g1);
g3 = move(0,g2);

echo(g3_x=g3);
echo(g3_2=g3(2));

I followed Michael and also dropped the g. But anyway, the last code still works fine with function move(a, g) = function(x) identity(g(x+a)) ; Em ter., 26 de nov. de 2019 às 02:23, Ronaldo Persiano < rcmpersiano@gmail.com> escreveu: > Inserting an indirection also works fine: > > > function move(a, g) = > function(x) identity(x+a) ; > > function identity(x) = x; > > g1 = function(x) x; > g2 = move(0,g1); > g3 = move(0,g2); > > echo(g3_x=g3); > echo(g3_2=g3(2)); > > > >> >>
M
MichaelAtOz
Tue, Nov 26, 2019 3:45 AM

See https://github.com/openscad/openscad/pull/3077#issuecomment-558442998

assert() helps, feels like a scope problem, but I need paper and pencil, my
head is filling with virtual functions...I don't like function literals...


Admin - email* me if you need anything,  or if I've done something stupid...

  • click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

--
Sent from: http://forum.openscad.org/

See https://github.com/openscad/openscad/pull/3077#issuecomment-558442998 assert() helps, feels like a scope problem, but I need paper and pencil, my head is filling with virtual functions...I don't like function literals... ----- Admin - email* me if you need anything, or if I've done something stupid... * click on my MichaelAtOz label, there is a link to email me. Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Tue, Nov 26, 2019 11:58 AM

Yet another hack that works:

function move(a, g) =
function(x)
let( v = g(x+a) ) v;

g1 = function(x) x;
g2 = move(2, g1);
g3 = move(3, g2);

echo(g3_x=g3);
echo(g3_2=g3(2));

Compiling design (CSG Tree generation)...

ECHO: g3_x = function(x) let(v = g((x + a))) v

ECHO: g3_2 = 7

Compiling design (CSG Products generation)...

Geometries in cache: 1

Geometry cache size in bytes: 270008

CGAL Polyhedrons in cache: 0

CGAL cache size in bytes: 0

Compiling design (CSG Products normalization)...

Normalized CSG tree has 0 elements
Compile and preview finished.

I can't see how scope may matter here.

Yet another hack that works: function move(a, g) = function(x) let( v = g(x+a) ) v; g1 = function(x) x; g2 = move(2, g1); g3 = move(3, g2); echo(g3_x=g3); echo(g3_2=g3(2)); Compiling design (CSG Tree generation)... ECHO: g3_x = function(x) let(v = g((x + a))) v ECHO: g3_2 = 7 Compiling design (CSG Products generation)... Geometries in cache: 1 Geometry cache size in bytes: 270008 CGAL Polyhedrons in cache: 0 CGAL cache size in bytes: 0 Compiling design (CSG Products normalization)... Normalized CSG tree has 0 elements Compile and preview finished. I can't see how scope may matter here.
MM
Michael Marx
Tue, Nov 26, 2019 12:08 PM

Not normal scope, a bug in how it works.

function move(a, g) = echo(move=a,g)

function(m)

  echo(m_in_move=a,m,g)

  assert(m<12)

    g(echo(str("call g(",m+a,")[g=",g,"]")) m+a) ;

g1 = function(x)

   echo(fx=x)

      x;

g2 = move(2,g1);

g3 = move(3,g2);

echo(g2_=g2);

echo(g3_x=g3);

echo(g3_5=g3(5));

Produces

Compiling design (CSG Tree generation)...

ECHO: move = 2, function(x) echo(fx = x) x

ECHO: move = 3, function(m) echo(m_in_move = a, m, g) assert((m

ECHO: g2_ = function(m) echo(m_in_move = a, m, g) assert((m

ECHO: g3_x = function(m) echo(m_in_move = a, m, g) assert((m

ECHO: m_in_move = 3, 5, function(m) echo(m_in_move = a, m, g) assert((m

ECHO: "call g(8)[g=function(m) echo(m_in_move = a, m, g) assert((m

ECHO: "call g(8)[g=function(m) echo(m_in_move = a, m, g) assert((m

ECHO: m_in_move = 2, 8, function(x) echo(fx = x) x

ECHO: "call g(10)[g=function(x) echo(fx = x) x]"

ECHO: m_in_move = 2, 10, function(x) echo(fx = x) x

ECHO: "call g(12)[g=function(x) echo(fx = x) x]"

ECHO: m_in_move = 2, 12, function(x) echo(fx = x) x

ERROR: Assertion '(m < 12)' failed in file fn literals ronaldo.scad, line 4

TRACE: called by 'g', in file fn literals ronaldo.scad, line 5.

TRACE: called by 'g3', in file fn literals ronaldo.scad, line 15.

TRACE: called by 'echo', in file fn literals ronaldo.scad, line 15.

Compiling design (CSG Products generation)...

Geometries in cache: 0

You can see it is saying it wants to call g1, but is actually calling g2 recursively.


From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano
Sent: Tue, 26 Nov 2019 22:58
To: OpenSCAD general discussion
Subject: Re: [OpenSCAD] Functions literals / higher order functions

Yet another hack that works:

function move(a, g) =
function(x)
let( v = g(x+a) ) v;

g1 = function(x) x;
g2 = move(2, g1);
g3 = move(3, g2);

echo(g3_x=g3);

echo(g3_2=g3(2));

Compiling design (CSG Tree generation)...

ECHO: g3_x = function(x) let(v = g((x + a))) v

ECHO: g3_2 = 7

Compiling design (CSG Products generation)...

Geometries in cache: 1

Geometry cache size in bytes: 270008

CGAL Polyhedrons in cache: 0

CGAL cache size in bytes: 0

Compiling design (CSG Products normalization)...

Normalized CSG tree has 0 elements

Compile and preview finished.

I can't see how scope may matter here.

Not normal scope, a bug in how it works. function move(a, g) = echo(move=a,g) function(m) echo(m_in_move=a,m,g) assert(m<12) g(echo(str("call g(",m+a,")[g=",g,"]")) m+a) ; g1 = function(x) echo(fx=x) x; g2 = move(2,g1); g3 = move(3,g2); echo(g2_=g2); echo(g3_x=g3); echo(g3_5=g3(5)); Produces Compiling design (CSG Tree generation)... ECHO: move = 2, function(x) echo(fx = x) x ECHO: move = 3, function(m) echo(m_in_move = a, m, g) assert((m ECHO: g2_ = function(m) echo(m_in_move = a, m, g) assert((m ECHO: g3_x = function(m) echo(m_in_move = a, m, g) assert((m ECHO: m_in_move = 3, 5, function(m) echo(m_in_move = a, m, g) assert((m ECHO: "call g(8)[g=function(m) echo(m_in_move = a, m, g) assert((m ECHO: "call g(8)[g=function(m) echo(m_in_move = a, m, g) assert((m ECHO: m_in_move = 2, 8, function(x) echo(fx = x) x ECHO: "call g(10)[g=function(x) echo(fx = x) x]" ECHO: m_in_move = 2, 10, function(x) echo(fx = x) x ECHO: "call g(12)[g=function(x) echo(fx = x) x]" ECHO: m_in_move = 2, 12, function(x) echo(fx = x) x ERROR: Assertion '(m < 12)' failed in file fn literals ronaldo.scad, line 4 TRACE: called by 'g', in file fn literals ronaldo.scad, line 5. TRACE: called by 'g3', in file fn literals ronaldo.scad, line 15. TRACE: called by 'echo', in file fn literals ronaldo.scad, line 15. Compiling design (CSG Products generation)... Geometries in cache: 0 You can see it is saying it wants to call g1, but is actually calling g2 recursively. _____ From: Discuss [mailto:discuss-bounces@lists.openscad.org] On Behalf Of Ronaldo Persiano Sent: Tue, 26 Nov 2019 22:58 To: OpenSCAD general discussion Subject: Re: [OpenSCAD] Functions literals / higher order functions Yet another hack that works: function move(a, g) = function(x) let( v = g(x+a) ) v; g1 = function(x) x; g2 = move(2, g1); g3 = move(3, g2); echo(g3_x=g3); echo(g3_2=g3(2)); Compiling design (CSG Tree generation)... ECHO: g3_x = function(x) let(v = g((x + a))) v ECHO: g3_2 = 7 Compiling design (CSG Products generation)... Geometries in cache: 1 Geometry cache size in bytes: 270008 CGAL Polyhedrons in cache: 0 CGAL cache size in bytes: 0 Compiling design (CSG Products normalization)... Normalized CSG tree has 0 elements Compile and preview finished. I can't see how scope may matter here.
RP
Ronaldo Persiano
Tue, Nov 26, 2019 1:20 PM

This is a very suggestive hack: simply add 0 to the result of the function
in move.

function move(a, g) = echo(move=a,g)
function(m)
echo(m_in_move=a,m,g)
assert(m<15)
g(m+a)+0 ;

g1 = function(x) x;
g2 = move(2, g1);
g3 = move(3, g2);
echo(g3_x=g3);
echo(g3_2=g3(2));

I can't remember exactly what but someone reported a similar hack to solve
another trouble.

This is a very suggestive hack: simply add 0 to the result of the function in move. function move(a, g) = echo(move=a,g) function(m) echo(m_in_move=a,m,g) assert(m<15) g(m+a)+0 ; g1 = function(x) x; g2 = move(2, g1); g3 = move(3, g2); echo(g3_x=g3); echo(g3_2=g3(2)); I can't remember exactly what but someone reported a similar hack to solve another trouble.