Plans to change variable behavior ?

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

Re: Plans to change variable behavior ?

doug.moen
I agree that OpenSCAD is frustrating to use for large projects, for people who are used to using a general purpose programming language.

It looks like this problem is going to be solved over time by making OpenSCAD more like a functional programming language. In the most recent edition, we added list comprehensions and 'let' expressions, which came directly from functional programming. There is general agreement that these changes made OpenSCAD much more powerful. But we still have a ways to go.

I've written up a proposal/roadmap called "openscad2", which proposes a way to evolve OpenSCAD into a more powerful geometric description language, by adding more of the features of functional programming languages, and without breaking backwards compatibility.  https://github.com/doug-moen/openscad2

You say that you are most comfortable programming in Perl. That means you have learned enough of the Perl idioms so that you can be productive in that language. Functional programming languages use a different set of idioms, and you have to learn those idioms in order to be productive in those languages. If you put in the effort to learn this new style of programming, you'll find it is more powerful than the old way of doing things. And yes, I do see a lot of momentum behind the functional programming movement, I think it is transforming the industry. New programming languages are incorporating more and more of the idioms of functional programming. I see this in Apple's new language Swift, Mozilla's new language Rust, even Perl 6.


On 15 November 2015 at 08:36, rickan <[hidden email]> wrote:
I really feel I should add my vote against these silly immutable variables.

<rant>
It really is silly, it makes some very, very useful things that are trivial
to do with regular variables seemingly impossible in openscad, and I can't
imagine it's good for beginning programmers or people who do it
infrequently. It seems obvious what if you want OpenSCAD to be as widely
adopted as possible, you will drop this immutable variable ideology. Find
some other way to advocate the functional programming ideology.

I'm retired from doing programming for a living, and I've never been
impressed with the "problems" that functional programming is supposed to be
a solution for, nor is it apparent to me that it's been widely adopted to
solve those "problems".

I'm sure these ideas have already been thoroughly hashed in this thread
(which I don't have the patience to read) -- this is just my vote.

P.S. I'm a Perl programmer when given a choice because the Perl ideology is
"There is more than one way to do it" and I can choose the way that's best
for me, for each of projects of widely various character, from what seems to
be a very nearly complete set of tools including some which impose
programming restrictions for those who seem to need them. I've never found
it wanting and can't recall the language interposing itself as part of the
problem the way I can other other languages.

P.P.S. I'm certainly NOT advocating for making the OpenSCAD language as
universal as Perl. I'm not very experienced with it and probably never will
be, but it seems to be more than adequate for solid modelling except for
those silly...
</rant>




--
View this message in context: http://forum.openscad.org/Plans-to-change-variable-behavior-tp9647p14508.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Plans to change variable behavior ?

L Boyd
In reply to this post by rickan
This is all about philosophy. The argument "All programming languages I have used do it differently" is irrelevant. Of the many languages I have used, all have some features you learn to live with.

OpenSCAD has a very valid reason for doing what it does.

My vote is to leave it alone.
Larry
Reply | Threaded
Open this post in threaded view
|

Re: Plans to change variable behavior ?

kintel
Administrator
In reply to this post by rickan

> On Nov 15, 2015, at 08:36 AM, rickan <[hidden email]> wrote:
>
> I really feel I should add my vote against these silly immutable variables.
>
General purpose programming can be done in a language-specific framework, similar to how you’d use such frameworks to generate HTML, rather than modifying the HTML spec to support certain dynamic features.

I’m not advocating any particular languages. I’ll just mention the ruby-based CrystalSCAD as an example, because I had the pleasure to chat with the author a few months back: https://github.com/Joaz/CrystalScad

Now, I’m open to support a plugin infrastructure to allow writing such code in the OpenSCAD environment, if that’s something people really want to do. We could even support people writing modules in other languages, as long as modules follow the same rules of not mutating its host environment. I feel that most people familiar with certain programming languages would rather use the extended feature set of that language environment, so I’m not sure how effective this would be.

 -Marius

> <rant>
> It really is silly, it makes some very, very useful things that are trivial
> to do with regular variables seemingly impossible in openscad, and I can't
> imagine it's good for beginning programmers or people who do it
> infrequently. It seems obvious what if you want OpenSCAD to be as widely
> adopted as possible, you will drop this immutable variable ideology. Find
> some other way to advocate the functional programming ideology.
>
> I'm retired from doing programming for a living, and I've never been
> impressed with the "problems" that functional programming is supposed to be
> a solution for, nor is it apparent to me that it's been widely adopted to
> solve those "problems".
>
> I'm sure these ideas have already been thoroughly hashed in this thread
> (which I don't have the patience to read) -- this is just my vote.
>
> P.S. I'm a Perl programmer when given a choice because the Perl ideology is
> "There is more than one way to do it" and I can choose the way that's best
> for me, for each of projects of widely various character, from what seems to
> be a very nearly complete set of tools including some which impose
> programming restrictions for those who seem to need them. I've never found
> it wanting and can't recall the language interposing itself as part of the
> problem the way I can other other languages.
>
> P.P.S. I'm certainly NOT advocating for making the OpenSCAD language as
> universal as Perl. I'm not very experienced with it and probably never will
> be, but it seems to be more than adequate for solid modelling except for
> those silly...
> </rant>
>
>
>
>
> --
> View this message in context: http://forum.openscad.org/Plans-to-change-variable-behavior-tp9647p14508.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> 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: Plans to change variable behavior ?

ctchin
Here is my attempt at explaining functional programming to myself.

https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/General_%28by_c.t.chin%29#Basic_Concepts

I'm with kintel here.  While I find declarative programming to very restrictive and
inconvenient, I can sense that catastrophe awaits if the development team agrees
to change to or allow even limited procedural computation.  

My solution to enable iterative computation or logic in OpenSCAD is to use Matlab
(you could do VC, perl, Python whatever) for the computation and "export" the
answer(s) to OpenSCAD by generating OpenSCAD code.  

Matlab may not be a well-known language, but its code is easy enough to understand,
following generate an OpenSCAD polyhedron module from Matlab:

function outstr = openscad(fid, modname, objs);

fprintf(fid, 'module %s() { union() {\n', modname);

for o = objs;  // for each object o
    nv = size(o.verts, 1);
    nf = numel(o.faces);

    fprintf(fid, 'polyhedron(\n  points = [\n');
    for kv = 1:nv
        fprintf(fid, '    [%g, %g, %g],\n', o.verts(kv,1), o.verts(kv,2), o.verts(kv,3));
    end;
    fseek(fid,-2,0); % remove the last comma and newline
    fprintf(fid, '\n  ],\n');

    fprintf(fid, '  faces = [\n');
    for kf = 1:nf;
        m = sprintf('%d, ', o.faces(kf).vi-1);
        m = m(1:end-2);
        fprintf(fid, '    [%s],\n',m);
    end
    fseek(fid,-2,0); % remove the last comma and newline
    fprintf(fid, '\n  ]\n);\n');
end

fprintf(fid, '} } \n');
Reply | Threaded
Open this post in threaded view
|

Re: Plans to change variable behavior ?

rickan
In reply to this post by L Boyd
In the instance which aroused my desire to vote against immutable variables, the location of my primitive call, cube(), in the inner of 3 nested for ops, is ideal for calculating various properties of the cube for that specific call and for counting the numbers of cubes with the same properties, etc.

The reasons, in addition to immutable variables, I can't to that is that modules do not return anything and modules cannot be called within functions.

I can do it by writing other functions to be called on the list equivalent of the three nested for ops with the same conditionals resulting in horrible code proliferation with it's attendant pitfalls. Or I can just write it in Perl which spews huge volumes of module calls generated in the 3 nested for loops in which case features of the OpenSCAD language such as immutable variables are irrelevant.

I read parts of your OpenSCAD 2 proposal with interest. Most relevant is that the only distinction between functions and modules is what they return, i.e. functions return anything at all and modules return geometrical objects. (Please correct any error in my understanding.)

I would like to suggest that modules return objects which contain the geometrical object in addition to a user definable, user settable, set of key => value pairs, i.e. user definable meta-data the module produces. It might make sense that some of the keys would be standard e.g. the key for the geometrical object itself, the parameters passed to the call including children objects, the coordinate transform matrix of the call, the color, etc.; but whether or not that is done, the user should be able to augment the set.

If this were done, then aggregation of the meta-data could be accomplished by calling functions on lists of these module produced objects.

What I'm calling meta-data here is, I think, a very important part of solid modeling.

Here's my specific case: Wallis.scad inserted here for convenience:

// Copyright 2015 Richard Kandarian http://kandarian.com/

function mkp(p, n, m) = n>m ?
  p : mkp(concat(p, [p[len(p)-1]*(2*n-1)/(2*n-2)]), n+1, m);

function mka(a, n, m) = n>m ?
  a : mka(concat(a, [a[len(a)-1]*(2*n-1)/(2*n)]), n+1, m);

function shift(o, v) = [for(i=[o:len(v)-1]) v[i]];

function hsv2rgb(h, s, v) =
  let(hs=h/60, f=hs-floor(hs), p=v*(1-s), q=v*(1-s*f), t=v*(1-s*(1-f)))
  h>=0 && h<60 ? [v, t, p] : (
    h>=60 && h<120 ? [q, v, p] : (
      h>=120 && h<180 ? [p, v, t] : (
	h>=180 && h<240 ? [p, q, v] : (
	  h>=240 && h<300 ? [t, p, v] : [v, p, q]
	)
      )
    )
  );

m = 50;
hollow = 1;
thick = 1;
p = mkp([1], 2, m);
pl = len(p)-1;
a = concat([1], shift(1, mka([1], 1, m-1)));
al = len(a)-1;

//echo(pl, p);
//echo(al, a);

module octant(){
  for(zi = [0:pl]){
    zm = pl-zi;
    z = zm<1 ? 0 : p[zm-1];
    h = a[zm];
//    hv1 = zm/m*360+(zm%2)*120;
//    hv = hv1 > 360 ? hv1-360 : hv1;
    for(yi = [0:zi]){
      ym = zi-yi;
      y = ym<1 ? 0 : p[ym-1];
      l = a[ym];
      for(xi = [0:yi]){
	xm = yi-xi;
	x = xm<1 ? 0 : p[xm-1];
	w = a[xm];
	if(!hollow || abs(xm+ym-zi) < thick){
	  hv1 = (xm+ym)/m*360+(zm%2)*120;
	  hv = hv1 > 360 ? hv1-360 : hv1;
	  translate([x, y, z]){
	    color(hsv2rgb(hv, .3, 1)){
	      cube([w, l, h], center=false);
	    };
	  };
	}
      }
    }
  }
}

module hemi(){
  octant();
  rotate([0,0,90]) octant();
  rotate([0,0,180]) octant();
  rotate([0,0,270]) octant();
}

//hull(){
  hemi();
  rotate([180,0,0]) hemi();
//}
Reply | Threaded
Open this post in threaded view
|

Re: Plans to change variable behavior ?

rickan
Hmmm, Seems I hit the wrong reply button. I meant to reply to Doug Moen.
Reply | Threaded
Open this post in threaded view
|

Re: Plans to change variable behavior ?

doug.moen
It's okay, I got the message. And I'll try to respond.

On 16 November 2015 at 13:53, rickan <[hidden email]> wrote:
Hmmm, Seems I hit the wrong reply button. I meant to reply to Doug Moen.



--
View this message in context: http://forum.openscad.org/Plans-to-change-variable-behavior-tp9647p14558.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Plans to change variable behavior ?

doug.moen
In reply to this post by rickan
rickan said:
> I read parts of your OpenSCAD 2 proposal with interest. Most relevant is
> that the only distinction between functions and modules is what they return,
> i.e. functions return anything at all and modules return geometrical
> objects. (Please correct any error in my understanding.)

That is correct. The distinction between modules and functions disappears,
and the 'module' keyword is deprecated (only needed for backward compatibility).
Modules are replaced by functions that return geometric objects.

rickan, again:
> I would like to suggest that modules return objects which contain the
> geometrical object in addition to a user definable, user settable, set of
> key => value pairs, i.e. user definable meta-data the module produces. It
> might make sense that some of the keys would be standard e.g. the key for
> the geometrical object itself, the parameters passed to the call including
> children objects, the coordinate transform matrix of the call, the color,
> etc.; but whether or not that is done, the user should be able to augment
> the set.

That is pretty much how the OpenSCAD2 design already works.
I have not made any attempt to define "standard keys", and in the present design,
primitive shapes like the ones returned by cube() and sphere() don't have any keys.
All keys within a geometric object are user defined.
But otherwise, it works as you have described.

Here is the section that describes "geometric objects":
https://github.com/doug-moen/openscad2/blob/master/rfc/Objects.md

The design makes a distinction between "shapes" (which are primitive)
and "objects" (which are user defined). Shapes and objects are the
two kinds of geometric values, both represent a 2D or 3D figure.


On 16 November 2015 at 13:47, rickan <[hidden email]> wrote:
In the instance which aroused my desire to vote against immutable variables,
the location of my primitive call, cube(), in the inner of 3 nested for ops,
is ideal for calculating various properties of the cube for that specific
call and for counting the numbers of cubes with the same properties, etc.

The reasons, in addition to immutable variables, I can't to that is that
modules do not return anything and modules cannot be called within
functions.

I can do it by writing other functions to be called on the list equivalent
of the three nested for ops with the same conditionals resulting in horrible
code proliferation with it's attendant pitfalls. Or I can just write it in
Perl which spews huge volumes of module calls generated in the 3 nested for
loops in which case features of the OpenSCAD language such as immutable
variables are irrelevant.

I read parts of your OpenSCAD 2 proposal with interest. Most relevant is
that the only distinction between functions and modules is what they return,
i.e. functions return anything at all and modules return geometrical
objects. (Please correct any error in my understanding.)

I would like to suggest that modules return objects which contain the
geometrical object in addition to a user definable, user settable, set of
key => value pairs, i.e. user definable meta-data the module produces. It
might make sense that some of the keys would be standard e.g. the key for
the geometrical object itself, the parameters passed to the call including
children objects, the coordinate transform matrix of the call, the color,
etc.; but whether or not that is done, the user should be able to augment
the set.

If this were done, then aggregation of the meta-data could be accomplished
by calling functions on lists of these module produced objects.

What I'm calling meta-data here is, I think, a very important part of solid
modeling.

Here's my specific case:  Wallis.scad
<http://forum.openscad.org/file/n14556/Wallis.scad>   inserted here for
convenience:





--
View this message in context: http://forum.openscad.org/Plans-to-change-variable-behavior-tp9647p14556.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Plans to change variable behavior ?

rickan
Doug Moen said:
> rickan, again:
> > I would like to suggest that modules return objects which contain the
> > geometrical object in addition to a user definable, user settable, set of
> > key => value pairs, i.e. user definable meta-data the module produces. It
> > might make sense that some of the keys would be standard e.g. the key for
> > the geometrical object itself, the parameters passed to the call including
> > children objects, the coordinate transform matrix of the call, the color,
> > etc.; but whether or not that is done, the user should be able to augment
> > the set.
>
> That is pretty much how the OpenSCAD2 design already works.
> I have not made any attempt to define "standard keys", and in the present design,
> primitive shapes like the ones returned by cube() and sphere() don't have any keys.
> All keys within a geometric object are user defined.
> But otherwise, it works as you have described.
>
> Here is the section that describes "geometric objects":
> https://github.com/doug-moen/openscad2/blob/master/rfc/Objects.md

It doesn't look that way to me because I only see how parameters are input
to the object, not how the object creates values (meta-data) and stores
them for later use as a result of the module call or object instantiation,
e.g, volume or moment of inertia calculated from the input parameters.

In my code example where the cube() is called inside if{!hollow... if
I were to take that if block and put it in a module or object with all
the required input parameters, I could, in that module, calculate and
store the volume of the cube, it's moment of inertia, and I could store
the color for access and analysis in some other part of my program.
Reply | Threaded
Open this post in threaded view
|

Re: Plans to change variable behavior ?

doug.moen
Okay, let me explain how it works.

In OpenSCAD2, an object is delimited by {...}. It may contain definitions, like 'zm = pl-zi;' from your octant module, and it may contain geometry statements, like 'translate(..) color(..) cube(..)' from your octant module. Definitions add key-value pairs to the object, while geometry statements add geometry.

Now lets consider your octant module:
module octant(){
  for(zi = [0:pl]){
    zm = pl-zi;
    z = zm<1 ? 0 : p[zm-1];
    h = a[zm];
    for(yi = [0:zi]){
      ym = zi-yi;
      y = ym<1 ? 0 : p[ym-1];
      l = a[ym];
      for(xi = [0:yi]){
	xm = yi-xi;
	x = xm<1 ? 0 : p[xm-1];
	w = a[xm];
	if(!hollow || abs(xm+ym-zi) < thick){
	  hv1 = (xm+ym)/m*360+(zm%2)*120;
	  hv = hv1 > 360 ? hv1-360 : hv1;
	  translate([x, y, z]){
	    color(hsv2rgb(hv, .3, 1)){
	      cube([w, l, h], center=false);
	    };
	  };
	}
      }
    }
  }
}

There are lots of {...} object literals in this module, so the result will be a nested tree of objects.

L0: the top level object contains a list of objects generated by 'for (zi=...)'
L1: the objects in L0 each contain 3 fields named zm, z, h, plus the objects generated by 'for (yi=...)'
L2: the objects in L1 each contain 3 fields named ym, y, l, plus the objects generated by 'for (xi=...)'
L3: the objects in L2 each contain 3 fields xm, x, w, plus zero or one objects generated by the if, depending on whether the if condition is false or true.
L4: the optional object in L3 contains 2 fields, hv1, hv, plus the shape 'translate(..) color(..) cube(..)'.

So if I write
    oct = octant();
then 'oct' is a object tree, nested 4 levels deep.
    len(oct) is the number of L1 objects in oct
    oct[0] is the first L1 object in oct
    oct[0].zm is the value of the zm field of oct[0], which is a number

Okay?

On 16 November 2015 at 14:53, rickan <[hidden email]> wrote:
Doug Moen said:
> rickan, again:
> > I would like to suggest that modules return objects which contain the
> > geometrical object in addition to a user definable, user settable, set
> of
> > key => value pairs, i.e. user definable meta-data the module produces.
> It
> > might make sense that some of the keys would be standard e.g. the key
> for
> > the geometrical object itself, the parameters passed to the call
> including
> > children objects, the coordinate transform matrix of the call, the
> color,
> > etc.; but whether or not that is done, the user should be able to
> augment
> > the set.
>
> That is pretty much how the OpenSCAD2 design already works.
> I have not made any attempt to define "standard keys", and in the present
> design,
> primitive shapes like the ones returned by cube() and sphere() don't have
> any keys.
> All keys within a geometric object are user defined.
> But otherwise, it works as you have described.
>
> Here is the section that describes "geometric objects":
> https://github.com/doug-moen/openscad2/blob/master/rfc/Objects.md

It doesn't look that way to me because I only see how parameters are input
to the object, not how the object creates values (meta-data) and stores
them for later use as a result of the module call or object instantiation,
e.g, volume or moment of inertia calculated from the input parameters.

In my code example where the cube() is called inside if{!hollow... if
I were to take that if block and put it in a module or object with all
the required input parameters, I could, in that module, calculate and
store the volume of the cube, it's moment of inertia, and I could store
the color for access and analysis in some other part of my program.




--
View this message in context: http://forum.openscad.org/Plans-to-change-variable-behavior-tp9647p14567.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Plans to change variable behavior ?

rickan
Okay!
That will work very nicely!
12345