[OpenSCAD] Proposal for extensions to the OpenSCAD syntax

nop head nop.head at gmail.com
Mon Oct 28 04:51:19 EDT 2019


Instead of

module bar() {
        union : {
                foo.union();
                _cylinder(d = 5, h = 10);
        }
        diff : {
                foo.diff();
        }
}

Why don't you simply define two modules foo_union() and foo_diff()?

In conventional programming it is bonkers to have combine two
completely different bits of code in one function and pass a global
variable to decide which one is executed.

In my case I would have foo(type), foo_holes(type) where type is a list
with all the parameters and I have accessor functions such as
foo_width(type).

If there is common positioning between foo() and foo_holes() then I would
have foo_hole_positions(type) that positions children().

On Mon, 28 Oct 2019 at 04:25, Hugo Jackson <hugo at apres.net> wrote:

>
>
> > On Oct 27, 2019, at 5:13 PM, Torsten Paul <Torsten.Paul at gmx.de> wrote:
> >
> > First note that the function literals are now
> > implemented, so the snapshot version of OpenSCAD
> > has functions as first class values which means
> > support for higher order functions.
> > (https://github.com/openscad/openscad/pull/3077)
> >
> > I hope to find some time to collect notes and post
> > an article about it. Meanwhile the minimalist docu
> > can be found at
> >
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/User-Defined_Functions_and_Modules#Function_Literals
> >
> > On 28.10.19 00:09, Hugo Jackson wrote:
> >> To start, I would propose an extension of the "dot"
> >> notation, that would allow one to refer to a value
> >> declaration and/or function or module component of
> >> another module with a dot.
> >
> > Yes, having access to a nested data structure is
> > definitely something that would help a lot. The
> > core changes to the parser implementation that are
> > required for this are now done and merged to the
> > development snapshot.
> >
> > But I don't think it will be possible to link to
> > the existing function and/or module definitions.
> >
> > Slightly modified example, just adding a parameter
> > to module foo():
> >
> > module foo(offset) {
> >       valueA = 7 + offset;
> >
> >       function myFunc(num) = valueA + num;
> > }
> >
> > module bar() {
> >       valueB = 8;
> >
> >       valueC = foo.valueA + foo.myFunc(valueB);
> > }
> >
> > foo(10);
> > translate([10, 10, 0]) foo(20);
> >
> > bar(); // <- now what is valueC ?
> >
>
> Good point… for my part I don’t usually code modules with parameters, but
> I appreciate that isn’t how the real world works. :)
> But I would think that calling any module part or function would require
> an enumeration of all needed values in the parameter arguments, e.g. for
> the example you
> provide the call for valueC in bar would need to be:
>
> valueC = foo(offset = 7).valueA + foo(offset = 7).myFunc(valueB) … or
> literally valueC = foo(7).valueA + foot(7).myFunc(valueB)
>
> Perhaps that would lead to a preponderance of code that would only serve
> to make code look more tortuous than it already does. Yet I think the
> proposed ‘dot’ syntax would lead to more insightful coding that would tend
> to mitigate the damage that might occur.
>
> >
> >> The second extension would be the election of three
> >> operations as 'reserved' functions, union, difference
> >> and intersection such that one could explicitly call
> >> that part of a module without calling the others:
> >
> > I'm not sure I understand how this will work. Why
> > select specifically those 3 special cases?
> >
> > Is that meant just as names or would that also mean
> > intersection() { bar(); foo(); } a bit like operator
> > overloading?
> >
> >> foo(); // would execute intersection(){difference(){union(){<union
> code>}<difference code>}<intersection code>}
> >
> > Where's the nesting coming from? From the order of
> > the definitions?
> >
> >> Please let me know… I didn’t want to bog this
> >> proposal down with details if it’s obvious, but in
> >> doing that I have taken the risk that the improvement
> >> And benefits of such extensions may not be evident.
>
>
>
> I often code modules using a special varialble I name $e and a skeleton
> module that looks like this:
>
> module foo($e = -1) {
>         module _union() {
>                 // code that primarily builds the object
>         }
>
>         module _diff() {
>                 // code that primarily subtracts geometry from _union()
>         }
>
>         difference() {
>                 if($e == -1 || $e == 0)
>                         _union();
>                 if($e == -1 || $e == 1)
>                         _diff();
>         }
> }
>
> I then get to call foo and either get just the _union code or just the
> _diff code or have the object definition run completely when $e == -1
>
> With this approach, when I just want the foo object I simply write:
>
> foo();
>
> But if I want the foo object to be united with some other objects before
> any difference is applied I could do it like this:
>
> module bar() {
>         difference() {
>                 union() {
>                         foo($e = 0);
>                         cylinder(d = 5, h = 10);
>                 }
>                 foo($e = 1);
>         }
> }
>
> I find that this kind of approach helps with the overall flow and data
> abstraction, but the addition of a special variable and the requirement for
> the difference(){union() {}} code to make it work detracts from what I feel
> is overall a more elegant approach, and I find it particularly helpful for
> code reuse.
> So that’s really what my suggestion for ’reserved’ functions is about..
> following the logic that you would execute union functionality before
> difference because you need to have first constructed an object before you
> remove anything from it. Don’t almost all modules have the…
>
> difference() {
>         union() {
>                 // add some stuff
>         }
>         // take some stuff away
> }
>
> construct in them?
>
> So that’s why I was thinking that a syntax that supported what I have at
> least found to be the most common code construction would make code more
> readable, so that I would just write:
>
> module foo() {
>
>         union : {
>                 // code that primarily builds the object
>         }
>         diff : {
>                 // code that primarily subtracts geometry from union()
>         }
>
>         // code that follows executes only if foo is called
> }
>
> Now when I want the foo object to be combined with other objects, I would
> just have to write:
>
> module bar() {
>         union : {
>                 foo.union();
>                 _cylinder(d = 5, h = 10);
>         }
>         diff : {
>                 foo.diff();
>         }
> }
>
> Perhaps there may be a more elegant way of structuring things, but I was
> aiming at a syntax that while not backwards compatible, wouldn’t break
> anything that was already working.
>
> Thanks for the heads up on the availability of function literals… that
> should make life more fun and exciting. And thanks for the links to the
> discussion lists.
>
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss at lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscad.org/pipermail/discuss_lists.openscad.org/attachments/20191028/8bf82647/attachment.html>


More information about the Discuss mailing list