Callable function arguments?

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Callable function arguments?

DarioPellegrini
Hi, any project which requires to operate on mathematical functions (root
finding, minimization, integration,  here is an example
<https://www.thingiverse.com/thing:3179773>  ) would greatly benefit from
being able to pass a callable as the argument of a function.

The neatest syntax that I can envisage is something like this:

    function g(h,i) = h(i);
    function f(i) = i;

    echo(g(f,3));

however it could also mimic the module's children pattern:
 
    function g(i) = children[0](i);
    function f(i) = i;

    echo( g(3) { f; } );

Right now I am circumventing this limitation by pre-defining the internal
function:

    function f(i) = i;
    function g(i) = f(i);

but this requires a copy of g (which is large, complicated and calls f many
times) for any possible f:

    function f1(i) = i;
    function g1(i) = f1(i);

    function f2(i) = i;
    function g2(i) = f2(i);
 
    ...

and, even worse, this approach prevents the possibility of packing g into a
library.

Is anything similar possible/practical/planned/wip within the OpenSCAD
ecosystem?



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

acwest
I would love to have some sort of function pointer support in
openSCAD, it would make a lot of tasks much easier to implement...

On Wed, Aug 21, 2019 at 3:51 PM DarioPellegrini
<[hidden email]> wrote:

>
> Hi, any project which requires to operate on mathematical functions (root
> finding, minimization, integration,  here is an example
> <https://www.thingiverse.com/thing:3179773>  ) would greatly benefit from
> being able to pass a callable as the argument of a function.
>
> The neatest syntax that I can envisage is something like this:
>
>     function g(h,i) = h(i);
>     function f(i) = i;
>
>     echo(g(f,3));
>
> however it could also mimic the module's children pattern:
>
>     function g(i) = children[0](i);
>     function f(i) = i;
>
>     echo( g(3) { f; } );
>
> Right now I am circumventing this limitation by pre-defining the internal
> function:
>
>     function f(i) = i;
>     function g(i) = f(i);
>
> but this requires a copy of g (which is large, complicated and calls f many
> times) for any possible f:
>
>     function f1(i) = i;
>     function g1(i) = f1(i);
>
>     function f2(i) = i;
>     function g2(i) = f2(i);
>
>     ...
>
> and, even worse, this approach prevents the possibility of packing g into a
> library.
>
> Is anything similar possible/practical/planned/wip within the OpenSCAD
> ecosystem?
>
>
>
> --
> Sent from: http://forum.openscad.org/
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

jschobben
I too would like such a feature! I think there have been a few proposals for
that already.

But, at the risk of derailing the discussion: there are some sneaky tricks
to make it work right now.

Here's one I sometimes use. Basically, the idea is to abuse the mechanics of
include/use, and put your code in multiple .scad files.

Without further ado, here's an example for sorting with a custom compare
function:

--- sort.scad
// Big and complicated function, where you want to use a "function pointer".
// Shamelessly based on quicksort example from the wiki, except that
"compare" is added.
// Note how the function "compare" is undefined here; it's your function
pointer variable.
// input : list of numbers
// output : sorted list of numbers
function quicksort(arr) = !(len(arr)>0) ? [] : let(
    pivot   = arr[floor(len(arr)/2)],
    lesser  = [ for (y = arr) if (compare(y, pivot) < 0) y ],
    equal   = [ for (y = arr) if (compare(y, pivot) == 0) y ],
    greater = [ for (y = arr) if (compare(y, pivot) > 0) y ]
) concat(
    quicksort(lesser), equal, quicksort(greater)
);

--- sort_length.scad
// Define a custom comparator, and a version of quicksort that sorts on
"length".
include <sort.scad>
function compare(a, b) = len(a) - len(b);
function quicksort_length(v) = quicksort(v);

--- sort_reverse.scad
// Another quicksort variant, this time sorting backwards
include <sort.scad>
function compare(a, b) = a < b ? 1 : a > b ? -1 : 0;
function quicksort_reverse(v) = quicksort(v);

--- main.scad
use <sort_length.scad>
use <sort_reverse.scad>
data = ["cheese", "kaas", "fromage"];
// sorted on string length: ["kaas", "cheese", "fromage"]
echo(sort_len=quicksort_length(data));
// reverse-sorted on natural comparison: ["kaas", "fromage", "cheese"]
echo(sort_rev=quicksort_reverse(data));

It's a nasty hack, but hey, it works :)

Alternatively, if you want all of it in a single .scad file, you probably
have a fixed amount of uses for "compare" anyway. In that case you might get
away with having a single "compare" function that takes an extra (numerical)
parameter to decide what behavior to use, and pass that parameter on via the
quicksort call.



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

DarioPellegrini
jschobben wrote
>  abuse the mechanics of include/use, and put your code in multiple .scad
> files.

I have the feeling that this could be accomplished in a single scad file
just by the preprocessor alone, even without the need of touching the
parser.
Maybe one can help the preprocessor by introducing some syntax, eg prefixing
callable arguments with a special char or keyword, so that the whole tasks
boils down to some text replacement.

    function g(h, i) = h(i);
    function f(i) = i;

    g(callable h=f, 3);

The last line is translated to g_f(3) where g_f is defined by the
preprocessor dropping the callable argument h and replacing h with f in the
body of g.

Of course staying at the preprocessor level is still quite a hack, and one
does not get any useful debug info. But I am not a computer scientist or
software engineer, so I leave the ball to whoever feels like scoring the
goal or serving an assist!



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

cacb
In reply to this post by acwest
On 21.08.2019 21:57, A. Craig West wrote:
> I would love to have some sort of function pointer support in
> openSCAD, it would make a lot of tasks much easier to implement...

You need something like this
https://gist.github.com/arnholm/7061458777913e5795585eee46fcb664

Carsten Arnholm


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

adrianv
cacb wrote
> On 21.08.2019 21:57, A. Craig West wrote:
>> I would love to have some sort of function pointer support in
>> openSCAD, it would make a lot of tasks much easier to implement...
>
> You need something like this
> https://gist.github.com/arnholm/7061458777913e5795585eee46fcb664

I couldn't figure out exactly how that syntax works.  For OpenSCAD, the
original poster's syntax wouldn't work because f can be a function, module
or variable, so there's no way to know what g(f) means if function pointers
can be passed.  So some kind of syntax is needed to clarify.   MATLAB, for
example, uses @ to mark function pointers, so @sin becomes a function
pointer to the sin function.  There's a second syntactic question having to
do with the function definition.  If you write

function g(f,x) = ....

then what is f?  Is it a function or a variable?  The two things have
different name spaces, so you have to decide which one it is.  Or if it's a
variable that contains a function then you need a way to call it.   I'm sure
it's been talked to death in previous posts.  And I agree it would be a
great feature.  Though if I were to prioritize features I'd put the ability
to avoid doing unions and to pass children un-unioned to a submodule first
in line before function pointers.  




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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

tp3
A probably better base for the discussion is that one

https://github.com/doug-moen/openscad2/blob/master/rfc/Functions.md

as it's considering the existing OpenSCAD syntax.

ciao,
  Torsten.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

doug.moen
Okay, I justed updated the OpenSCAD2 project to show the current status.

The original OpenSCAD2 proposal was not popular with some members of the community, and it had some problems with backward compatibility.

Back in 2017, I starting writing an updated proposal, "OpenSCAD bis", which is simpler, and has a lower risk of breaking backwards compatibility. For the record, the document is here: https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md

Doug Moen.

On Thu, Aug 22, 2019, at 5:28 PM, Torsten Paul wrote:

> A probably better base for the discussion is that one
>
> https://github.com/doug-moen/openscad2/blob/master/rfc/Functions.md
>
> as it's considering the existing OpenSCAD syntax.
>
> ciao,
>   Torsten.
>
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

cacb
In reply to this post by adrianv
On 2019-08-22 23:22, adrianv wrote:
> cacb wrote
>> On 21.08.2019 21:57, A. Craig West wrote:
>>> I would love to have some sort of function pointer support in
>>> openSCAD, it would make a lot of tasks much easier to implement...
>>
>> You need something like this
>> https://gist.github.com/arnholm/7061458777913e5795585eee46fcb664
>
> I couldn't figure out exactly how that syntax works.

It is not that complicated. In any language, you can have variables that
represent data, such as integers and doubles. In some languages you can
have variables that represent functions. Instead of assigning data to
such variables, you assign functions to them. The AngelCAD statement

funcdef double CALLBACK(int i);

means to declare a function pointer type. In this case the type name is
CALLBACK, representing the signature of a function that takes an integer
argument and returns a double value. So if you have an actual function
with the same signature

double myfunc(int i) { return i*i; }

you can do

CALLBACK@ f = myfunc;

The @ means it is a handle type (i.e. f is a pointer to myfunc). One can
use the variable f later, for example

double value = f(5);

The result will obviously be 25.0


Carsten Arnholm

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

nophead
In reply to this post by doug.moen
I think OpenSCAD bis would still have compatibility issues if you put built in modules into the function and variable namespaces. Keeping the namespaces separate for compatibility is pointless if you put built in things in more than one namespace.

For example I have function versions of rotate, translate, etc, that work on matrices.

On Thu, 22 Aug 2019 at 23:25, Doug Moen <[hidden email]> wrote:
Okay, I justed updated the OpenSCAD2 project to show the current status.

The original OpenSCAD2 proposal was not popular with some members of the community, and it had some problems with backward compatibility.

Back in 2017, I starting writing an updated proposal, "OpenSCAD bis", which is simpler, and has a lower risk of breaking backwards compatibility. For the record, the document is here: https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md

Doug Moen.

On Thu, Aug 22, 2019, at 5:28 PM, Torsten Paul wrote:
> A probably better base for the discussion is that one
>
> https://github.com/doug-moen/openscad2/blob/master/rfc/Functions.md
>
> as it's considering the existing OpenSCAD syntax.
>
> ciao,
>   Torsten.
>
>
> _______________________________________________
> OpenSCAD mailing list
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

doug.moen
Hi nop head.

OpenSCAD bis would be compatible with your code, because your definitions of the function versions of rotate, translate, etc, would hide the built in definitions.

If I was implementing this, I would test the changes against your code to ensure that there were no additional warnings or errors and no changes of behaviour. Any incompatibilities would be considered a bug.

Also, if I was implementing this today, I would ignore the part of the design that tries to make shapes and modules into first class values, because that part is too big and scary. I would only implement the function part of OpenSCAD bis. The function part can be summarized as:
 * New style function definitions define the function in both the variable and the function namespaces.
 * Within a new style function definition, parameter names and let-bound local variables are defined in both the variable and the function namespaces.
 * Most built in functions are also defined in the variable namespace. But those definitions are hidden by user defined variables.

Doug Moen.

On Fri, Aug 23, 2019, at 3:21 AM, nop head wrote:
I think OpenSCAD bis would still have compatibility issues if you put built in modules into the function and variable namespaces. Keeping the namespaces separate for compatibility is pointless if you put built in things in more than one namespace.

For example I have function versions of rotate, translate, etc, that work on matrices.

On Thu, 22 Aug 2019 at 23:25, Doug Moen <[hidden email]> wrote:
Okay, I justed updated the OpenSCAD2 project to show the current status.

The original OpenSCAD2 proposal was not popular with some members of the community, and it had some problems with backward compatibility.

Back in 2017, I starting writing an updated proposal, "OpenSCAD bis", which is simpler, and has a lower risk of breaking backwards compatibility. For the record, the document is here: https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md

Doug Moen.

On Thu, Aug 22, 2019, at 5:28 PM, Torsten Paul wrote:
> A probably better base for the discussion is that one
>
>
> as it's considering the existing OpenSCAD syntax.
>
> ciao,
>   Torsten.
>
>
> _______________________________________________
> OpenSCAD mailing list
>

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



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

nophead
OK that makes sense. 

I does open the door to more complexity and I like OpenSCAD because it is simple. With function pointers I can put them in lists and make vtables for my objects adding polymorphism and inheritance as I did with C before C++ was invented and I knew what OO was.

On Fri, 23 Aug 2019 at 14:46, Doug Moen <[hidden email]> wrote:
Hi nop head.

OpenSCAD bis would be compatible with your code, because your definitions of the function versions of rotate, translate, etc, would hide the built in definitions.

If I was implementing this, I would test the changes against your code to ensure that there were no additional warnings or errors and no changes of behaviour. Any incompatibilities would be considered a bug.

Also, if I was implementing this today, I would ignore the part of the design that tries to make shapes and modules into first class values, because that part is too big and scary. I would only implement the function part of OpenSCAD bis. The function part can be summarized as:
 * New style function definitions define the function in both the variable and the function namespaces.
 * Within a new style function definition, parameter names and let-bound local variables are defined in both the variable and the function namespaces.
 * Most built in functions are also defined in the variable namespace. But those definitions are hidden by user defined variables.

Doug Moen.

On Fri, Aug 23, 2019, at 3:21 AM, nop head wrote:
I think OpenSCAD bis would still have compatibility issues if you put built in modules into the function and variable namespaces. Keeping the namespaces separate for compatibility is pointless if you put built in things in more than one namespace.

For example I have function versions of rotate, translate, etc, that work on matrices.

On Thu, 22 Aug 2019 at 23:25, Doug Moen <[hidden email]> wrote:
Okay, I justed updated the OpenSCAD2 project to show the current status.

The original OpenSCAD2 proposal was not popular with some members of the community, and it had some problems with backward compatibility.

Back in 2017, I starting writing an updated proposal, "OpenSCAD bis", which is simpler, and has a lower risk of breaking backwards compatibility. For the record, the document is here: https://github.com/doug-moen/openscad2/blob/master/OpenSCADbis.md

Doug Moen.

On Thu, Aug 22, 2019, at 5:28 PM, Torsten Paul wrote:
> A probably better base for the discussion is that one
>
>
> as it's considering the existing OpenSCAD syntax.
>
> ciao,
>   Torsten.
>
>
> _______________________________________________
> OpenSCAD mailing list
>

_______________________________________________
OpenSCAD mailing list
_______________________________________________
OpenSCAD mailing list


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: Callable function arguments?

tp3
In reply to this post by doug.moen
On 23.08.19 15:42, Doug Moen wrote:
> ... I would ignore the part of the design that tries to make
> shapes and modules into first class values, because that
> part is too big and scary. I would only implement the function
> part of OpenSCAD bis.

Yes, that what I'm thinking too. This is also pretty much what
we were doing (slowly) in past. Taking small steps implementing
parts of your proposal. The functions would be a bigger step
but I think it's worth it as there's a lot of use cases that
could greatly benefit from this feature.

Just to highlight that again: Thanks for all the work you did
writing those proposals, they are a big help in showing a road
to a future OpenSCAD without breaking too much of the past.

ciao,
  Torsten.


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten