[OpenSCAD] eval( ) ???

doug moen doug at moens.org
Sat May 16 22:27:53 EDT 2015


Hi Yona. I find parts of your post confusing (the term "module" is
overloaded), but we are thinking along the same lines.

A quick way to summarize my thinking is that you don't need classes to do
object oriented programming. The prototype/delegation paradigm used by
Javascript is just as powerful. But if all objects are immutable, then you
don't need delegation, and things get really simple. You just need:

   1. object literals
   2. a way to make a new object by specifying the differences from an old
   object. Or: a way to customize an object, overriding some fields, resulting
   in a new object.
   3. functions

And that's it, you have a functional OOP system. It's simple, more powerful
than it looks, and good enough for our purposes.

OpenSCAD already has the above 3 concepts:

   1. an OpenSCAD script corresponds to an object
   2. you can customize a script, overriding some definitions, by writing
   'include <scriptname>' and then writing new definitions that override some
   of the bindings inherited from <scriptname>. Or, you can override
   definitions within a script from the command line using the -D flag.
   3. OpenSCAD has functions. Also, 'module' definitions are really just
   functions by another name.

OpenSCAD 2 just generalizes these already-existing concepts. It adds object
literals and first class object values. It adds a better syntax for
customizing an object. It unifies "functions" and "modules", using the word
"function" to describe both.

Now I'll copy and paste part of Yona's post, with terminology and syntax
changed to correspond to my current OpenSCAD 2 design:

// If we consider { ... } to be an "inline object", you get associative
> arrays for free:
> data = {
>    a = 10;
>    b = 20;
> }
> echo(data.a);
> // You can create a copy with new values as well
> data2 = data(b=30, c=100);


Doug Moen.

On 16 May 2015 at 20:52, Yona Appletree <hypher at gmail.com> wrote:

> Doug,
>
> This is a fascinating discussion, and I wanted to chime in about objects
> and mutability (full disclosure, experienced programmer). I have an
> interest in functional, immutable programming styles, but have not
> personally used lisp or Haskell. Most of my experience is with Scala.
>
> I think you can preserve much of the usefulness of objects while keeping a
> simple syntax and immutability. In fact, we don't even really need a new
> keyword. Modules are fine as is, with a few minor extensions. The main
> features that seem useful are:
>
>    1. Combining data, geometry and functions into one variable space
>    2. Module mix-ins
>    3. Access to module parameters and variables as "fields"
>    4. A module "copy" method. I will use the name "with", where you can
>    specify overrides to the parameters and variables in the modules. This
>    would return a copy of the module with the new values, keeping immutability.
>
> Carsten's example would look something like this:
>
> module Lollipop(
>    radius,
>    diameter,
>    height
> ) extends Geometry /* This could be the default, and not needed to be stated explicitly */ {
>    translate([0,0,height]) sphere(r=radius);
>    cylinder(d=diameter,h=height
> }
>
> // modules exist as before
> module example_model()
> {
>     // create 2 lollipops of different sizes, the second dependent on the first
>
>     lolA = Lollipop(radius = 10, diameter = 2, height = 50);
>     lolB = lolA.with(radius = lolA.radius*2, diameter = lolA.diameter*2); // height is omitted -- it stays the same
>
>     // create a cube representing the table plate.
>     // cube is a module just like everything else (albeit a native one),
>     // and it's parameters ARE accessible, and has a .with() if needed.
>     table_plate = cube(size=[100,100,5], center=true);
>
>     // union, a member of the base geometry module, returns an immutable copy of itself
>     // unioned with the arguments to union. Since we are a module, any geometry declared is
>     // implicitly unioned as before.
>     table_plate.union(lolA, lolB);
> }
>
> // construct the exmple model and export it as STL
> example_model()
>    .render() // Produces rendered geometry... more on this later
>    .exportStl("lollipops_on_table.stl"); // magic strings are ugly. Use an actual method name for STL
>
>
> But these extensions would allow far more, but remain mostly, if not
> completely backwards compatible. We can actually implement the "geometry"
> base module using the existing functionality of OpenSCAD:
>
> module GeometryBase {
>    unionOf = (args* /*vararg syntax tdb, of course */) -> { /* Anonymous function syntax TDB */
>       union() {
>          this
>          args
>       }
>    }
>
>    rendered = (x = 1) -> render(x) { this }
> }
>
>
> If we consider { ... } to be an "inline module", you get associative
> arrays for free:
>
> data = {
>    a = 10;
>    b = 20;
> }
> echo(data.a); // Valid because variables of modules are exposed
>
> // You can create a copy with new values as well
> data2 = data.with(b=30, c=100);
>
>
> Just my two cents, but it would be a simple way to keep backwards
> compatibility and all the desirable current features while giving the
> programmers many of the features that feel natural to us.
>
> - Yona
>
>   doug moen <doug at moens.org>
>  May 16, 2015 at 16:35
>
> Hi Carsten.
>
> One of my top goals for "OpenSCAD 2" is to stay true to the goals and
> philosophy of OpenSCAD. I've tried to figure out what these are by
> talking to Marius and reading forum posts for the last few years.
>
> Some OpenSCAD users are computer programmers like you and me, but many
> are not. If OpenSCAD is your first experience with computer
> programming, then how many new concepts do you need to learn before
> you can be productive? OpenSCAD seems to have a low barrier to entry,
> and we want to keep it this way.
>
> One philosophical principle I've learned from the community is that
> OpenSCAD is intended to be a purely declarative or 'functional'
> language, except that it should also be much easier to learn than
> serious functional languages such as Haskell. This means that there is
> no state. You can't increment a variable or modify a data structure
> in-place.
>
> Traditional OOP languages are based on the idea of objects with state,
> and there is a lot of additional heavy weight machinery that you need
> to learn before you can be productive. But we don't want this: we'll
> end up with a language that is easy to use once you have learned
> object oriented programming, but it with a higher barrier to entry for
> beginners.
>
> In your first example (class lollipop), you defined a class, you
> defined a constructor inside the class, you declared data members then
> separately assigned them initial values within the constructor, and
> you have an assignment to the special variable 'this'. You used a lot
> of machinery to accomplish something very simple.
>
> In your second example (module example_module), you create a mutable
> object and modify its state, in these lines:
>
>     table_plate = cube(size=[100,100,5],center=true);
>
>     // union the lollipops with the table plate and return it
>     table_plate.union(lolA);
>     table_plate.union(lolB);
>
>     // be explicit about what the module returns
>     return table_plate;
>
> But we want OpenSCAD to be purely declarative, without state mutation semantics.
>
> When I have more time, maybe I'll try and rewrite your code in
> OpenSCAD 2, to demonstrate that the same things can be accomplished in
> a simpler way, without all the heavy machinery of OOP.
>
> Doug Moen.
>
> On 16/05/2015, Carsten Arnholm <arnholm at arnholm.org> <arnholm at arnholm.org> wrote:
>
> On 2015-05-16 19:33, G. Wade Johnson wrote:
>
> Is there a {beta,alpha,prototype} version of OpenSCAD2 somewhere for
> people to play with? Is there a spec to read?
>
> I, for one, would like to see anything you are willing to share on this.
>
> That was my reaction as well.
>
> In my opinion, classes are not there to complicate things. On the
> contrary, it is an important tool for simplification. Being able to name
> a type, encapsulate its data members and provide member functions would
> go a long way towards the goal of being more expressive without
> complicating things.
>
> In my line of thinking, which may be different from OpenSCAD2 (as I have
> not grasped the full idea of it), the main ideas would be:
>
> classes would be used for constructing named parametric objects
> (instantiation) and being able to union, intersect and difference the
> result with other named or unnamed objects (union(), intersect() and
> difference() would be member functions on any class. unlike a module, a
> class may contain data members unique to each instance created.
>
> Below is just a silly example to illustrate: 2 lollipops on a table.
> The difference between a module and a class here is that a class may be
> instantiated and may remember its construction parameters so they can be
> re-used later. It also owns its CSG object.
>
> // classes are new
> class lollipop {
>
>     // a constructor is a member function with the same name as the class
>     lollipop(rad, diam, hei)
>     {
>        // keep data members
>        radius   = rad;
>        diameter = diam;
>        height   = hei;
>
>        // "this CSG object"
>        this = union() {
>           translate([0,0,height]) sphere(r=radius);
>           cylinder(d=diameter,h=height);
>        };
>     }
>
>     // data members of the class
>     radius;
>     diameter;
>     height;
> };
>
>
> // modules exist as before
> module example_model()
> {
>     // create 2 lollipops of different sizes
>     // the second is dependent on the first
>
>     lolA = lollipop(rad=10,diam=2,hei=50);
>     lolB = lollipop(lolA.radius*2,lolA.diameter*3,lolA.height);
>
>     // create a cube representing the table plate. Here,
>     // the construction parameters cannot be accessed later
>     // since the cube is a primitive only
>     table_plate = cube(size=[100,100,5],center=true);
>
>     // union the lollipops with the table plate and return it
>     table_plate.union(lolA);
>     table_plate.union(lolB);
>
>     // be explicit about what the module returns
>     return table_plate;
> }
>
> // construct the exmple model and export it as STL
> example_model().render().export("STL","lollipops_on_table.stl");
>
>
> You could go on, classes could have data members being instantiations of
> other classes, or even containers containing such.
>
> The above is just meant as a supplement to what I wrote before,
> illustrating the idea that the OpenSCAD language could be extended in a
> direction which would be immediately recognisable to programmers, while
> still being backwards compatible with existing OpenSCAD code. If you
> want to express things as it is currently being done, you can, but you
> also have other possibilities.
>
> Again, just my thoughts. I don't know if it would be easy to implement.
>
>
> Carsten
>
>
> _______________________________________________
> OpenSCAD mailing listDiscuss at lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
> _______________________________________________
> OpenSCAD mailing listDiscuss at lists.openscad.orghttp://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>   Carsten Arnholm <arnholm at arnholm.org>
>  May 16, 2015 at 15:08
>
>
> That was my reaction as well.
>
> In my opinion, classes are not there to complicate things. On the
> contrary, it is an important tool for simplification. Being able to name a
> type, encapsulate its data members and provide member functions would go a
> long way towards the goal of being more expressive without complicating
> things.
>
> In my line of thinking, which may be different from OpenSCAD2 (as I have
> not grasped the full idea of it), the main ideas would be:
>
> classes would be used for constructing named parametric objects
> (instantiation) and being able to union, intersect and difference the
> result with other named or unnamed objects (union(), intersect() and
> difference() would be member functions on any class. unlike a module, a
> class may contain data members unique to each instance created.
>
> Below is just a silly example to illustrate: 2 lollipops on a table.
> The difference between a module and a class here is that a class may be
> instantiated and may remember its construction parameters so they can be
> re-used later. It also owns its CSG object.
>
> // classes are new
> class lollipop {
>
>    // a constructor is a member function with the same name as the class
>    lollipop(rad, diam, hei)
>    {
>       // keep data members
>       radius   = rad;
>       diameter = diam;
>       height   = hei;
>
>       // "this CSG object"
>       this = union() {
>          translate([0,0,height]) sphere(r=radius);
>          cylinder(d=diameter,h=height);
>       };
>    }
>
>    // data members of the class
>    radius;
>    diameter;
>    height;
> };
>
>
> // modules exist as before
> module example_model()
> {
>    // create 2 lollipops of different sizes
>    // the second is dependent on the first
>
>    lolA = lollipop(rad=10,diam=2,hei=50);
>    lolB = lollipop(lolA.radius*2,lolA.diameter*3,lolA.height);
>
>    // create a cube representing the table plate. Here,
>    // the construction parameters cannot be accessed later
>    // since the cube is a primitive only
>    table_plate = cube(size=[100,100,5],center=true);
>
>    // union the lollipops with the table plate and return it
>    table_plate.union(lolA);
>    table_plate.union(lolB);
>
>    // be explicit about what the module returns
>    return table_plate;
> }
>
> // construct the exmple model and export it as STL
> example_model().render().export("STL","lollipops_on_table.stl");
>
>
> You could go on, classes could have data members being instantiations of
> other classes, or even containers containing such.
>
> The above is just meant as a supplement to what I wrote before,
> illustrating the idea that the OpenSCAD language could be extended in a
> direction which would be immediately recognisable to programmers, while
> still being backwards compatible with existing OpenSCAD code. If you want
> to express things as it is currently being done, you can, but you also have
> other possibilities.
>
> Again, just my thoughts. I don't know if it would be easy to implement.
>
>
> Carsten
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss at lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>   G. Wade Johnson <gwadej at anomaly.org>
>  May 16, 2015 at 10:33
> Is there a {beta,alpha,prototype} version of OpenSCAD2 somewhere for
> people to play with? Is there a spec to read?
>
> I, for one, would like to see anything you are willing to share on this.
>
> G. Wade
>
> On Sat, 16 May 2015 12:44:38 -0400
>
>
>   doug moen <doug at moens.org>
>  May 16, 2015 at 09:44
> Carsten said:
> Personally, I use modules in OpenSCAD extensively, but I would be even
> happier with a class concept with both member functions and data members. A
> 3d hierarchy can be expressed also that way.
> ... Perhaps one could keep the OpenSCAD language limited and use it as an
> intermediate representation generated by the kind of object oriented
> language I am dreaming of :-)
>
> The OpenSCAD2 design that I am working on will have a very simple object
> model. Consider a typical OpenSCAD script: it has some named numeric
> parameters at the top, then some function and module definitions, then some
> top level geometry statements that render the model based on the
> parameters. So that's an object. An object is a set of top level
> definitions (name/value pairs), plus a list of values (which are normally
> geometric shapes). OpenSCAD2 has a syntax for referencing an external
> library file as an object, and a syntax for object literals (just an
> OpenSCAD script, surrounded by braces). Given an object, you can reference
> its named components using dot notation (object.name), or you can
> reference the object in a geometric context (as an argument to a geometric
> transformation, or at the top level of a script), in which case the object
> behaves like its geometry.
>
> There are a few more details, but that's the basic idea. Note that this is
> much simpler than object oriented programming. There are no mutable
> objects, no classes or user defined types, no support for encapsulation or
> data abstraction. But, as I mentioned, objects do have "member functions
> and data members", so it may go part way towards satisfying Carsten's
> requirements. Objects will also satisfy Runsun's requirement for
> associative arrays. I also think that constructing a 3D model as a tree of
> objects will give us a better (more declarative) way to support
> bill-of-materials.
>
> We want to preserve the simple and declarative nature of OpenSCAD. I
> believe that this very simple object model will address some of the main
> pain points in doing geometric modelling with OpenSCAD, without turning it
> into a complex OOP language.
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss at lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>   Carsten Arnholm <arnholm at arnholm.org>
>  May 14, 2015 at 09:58
> Hi Marius!
>
> On 2015-05-14 16:22, Marius Kintel wrote:
>
> OpenSCAD aim to directly describe a 3D design hierarchy, not merely
> execute code to spit out 3D objects.
>
>
> I do understand, and any language chosen would obviously have to support
> the design hierarchy. As far as I can tell, many languages should be able
> to do it. Personally, I use modules in OpenSCAD extensively, but I would be
> even happier with a class concept with both member functions and data
> members. A 3d hierarchy can be expressed also that way.
>
> Anyway, this was just my thoughts. OpenSCAD has made decisions long ago,
> which I respect. Perhaps one could keep the OpenSCAD language limited and
> use it as an intermediate representation generated by the kind of object
> oriented language I am dreaming of :-)
>
> Using a faster and more powerful CAD kernel is indeed on the radar.
>
> > Sadly, the world of Open Source CAD kernels is severely limited.
>
> If we manage to get sufficient contributions or funding, working
>
> > towards such a kernel would be doable. If you have any spare
> > time, this would be a good place to start:
>
>
> https://github.com/openscad/openscad/wiki/Project%3A-Survey-of-CSG-algorithms
>
> ..or if someone has the experience to do so: Evaluate OpenCascade as an
> option. Most people I’ve talked to who’ve ever used that has strongly
> recommended me never to touch it though. ..but FreeCAD somehow manages.
>
>
> The funny thing is, I evaluated CAS.CADE (as it was known at the time) in
> about 1994-1995 for the work previously mentioned. It was marketed by Matra
> Datavision in France and I even went to see them a couple of times. They
> had what we thought was a curious idea of their own home-grown language
> (CDL) encapsulating the C++ kernel. Nowadays it looks like some finally
> agree with our thoughts at the time :
> http://dev.opencascade.org/doc/overview/html/occt_dev_guides__cdl.html
>
> "Please note that CDL is considered as obsolete and is to be removed in
> one of future releases of OCCT."   :-)
>
> CAS.CADE was closed source and extremely expensive back then, but we still
> struggled very hard to make use of it. The end result for us was that it
> was dropped and replaced it with ACIS. Only a few years ago, I discovered
> CAS.CADE had become quasi open source as OpenCascade (OCCT). I also found
> there is now something called OCE - Open CASCADE Community Edition
> https://github.com/tpaviot/oce/
> I had the idea of trying OCE, but frankly not enough incentive and power
> to do it, and my work is different now. OCE may probably be something to be
> considered for OpenSCAD CAD kernel, I suspect OpenCascade has come a long
> way since I saw it.
>
> Sidenote: One thing that has struck me is that the compilation in OpenSCAD
> is quite fast, but the rendering (F6) is extremely slow. I was wondering if
> the generation of triangles for STL really needs the graphical rendering to
> be completed first? If not, one could imagine a function to export the
> compiled model to STL and use an external viewer to speed things up when
> iterating on a complex design that takes forever to render.
>
> Carsten Arnholm
>
>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss at lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
> _______________________________________________
> 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/20150516/caaf4398/attachment-0002.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: compose-unknown-contact.jpg
Type: image/jpeg
Size: 770 bytes
Desc: not available
URL: <http://lists.openscad.org/pipermail/discuss_lists.openscad.org/attachments/20150516/caaf4398/attachment.jpg>


More information about the Discuss mailing list