discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Extending OpenSCAD from assembler to C or Perlish language and adding standard library

DM
Doug Moen
Tue, Oct 1, 2019 3:50 AM
  1. Mutable variables.

[...] It's not something very high at my personal wish-list at
this point [...]

This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since let() only sets the value of a variable for the parts of a function subordinate to the let(). Also, mutable variables become much more useful with a while() conditional loop statement.

It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension.

https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst

>>> 1. Mutable variables. >> >> [...] It's not something very high at my personal wish-list at >> this point [...] > > This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since `let()` only sets the value of a variable for the parts of a function subordinate to the `let()`. Also, mutable variables become much more useful with a `while()` conditional loop statement. It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension. https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst
NH
nop head
Tue, Oct 1, 2019 7:00 AM

Doesn't the current C like for(..;..;)  syntax effectively allow a while
loop and mutable variables in the loop?

On Tue, 1 Oct 2019 at 04:51, Doug Moen doug@moens.org wrote:

  1. Mutable variables.

[...] It's not something very high at my personal wish-list at
this point [...]

This is perhaps the most highly desired feature request I have. Though
it's unclear to me how it would be handled in a function context, since
let() only sets the value of a variable for the parts of a function
subordinate to the let().  Also, mutable variables become much more
useful with a while() conditional loop statement.

It would be possible to borrow the syntax that Curv uses for mutable
variables. It would fit in to OpenSCAD with only minor changes. You can use
assignment statements and while statements inside a function, or inside a
list comprehension.

https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst


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

Doesn't the current C like for(..;..;) syntax effectively allow a while loop and mutable variables in the loop? On Tue, 1 Oct 2019 at 04:51, Doug Moen <doug@moens.org> wrote: > > 1. Mutable variables. > > > [...] It's not something very high at my personal wish-list at > this point [...] > > > This is perhaps the most highly desired feature request I have. Though > it's unclear to me how it would be handled in a function context, since > `let()` only sets the value of a variable for the parts of a function > subordinate to the `let()`. Also, mutable variables become much more > useful with a `while()` conditional loop statement. > > > It would be possible to borrow the syntax that Curv uses for mutable > variables. It would fit in to OpenSCAD with only minor changes. You can use > assignment statements and while statements inside a function, or inside a > list comprehension. > > https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
NH
nop head
Tue, Oct 1, 2019 7:02 AM

People say it is hard to write algorithms without mutable variables. Does
that mean it is hard to write algorithms in Haskell or does that have them
as well?

On Tue, 1 Oct 2019 at 08:00, nop head nop.head@gmail.com wrote:

Doesn't the current C like for(..;..;)  syntax effectively allow a while
loop and mutable variables in the loop?

On Tue, 1 Oct 2019 at 04:51, Doug Moen doug@moens.org wrote:

  1. Mutable variables.

[...] It's not something very high at my personal wish-list at
this point [...]

This is perhaps the most highly desired feature request I have. Though
it's unclear to me how it would be handled in a function context, since
let() only sets the value of a variable for the parts of a function
subordinate to the let().  Also, mutable variables become much more
useful with a while() conditional loop statement.

It would be possible to borrow the syntax that Curv uses for mutable
variables. It would fit in to OpenSCAD with only minor changes. You can use
assignment statements and while statements inside a function, or inside a
list comprehension.

https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst


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

People say it is hard to write algorithms without mutable variables. Does that mean it is hard to write algorithms in Haskell or does that have them as well? On Tue, 1 Oct 2019 at 08:00, nop head <nop.head@gmail.com> wrote: > Doesn't the current C like for(..;..;) syntax effectively allow a while > loop and mutable variables in the loop? > > On Tue, 1 Oct 2019 at 04:51, Doug Moen <doug@moens.org> wrote: > >> >> 1. Mutable variables. >> >> >> [...] It's not something very high at my personal wish-list at >> this point [...] >> >> >> This is perhaps the most highly desired feature request I have. Though >> it's unclear to me how it would be handled in a function context, since >> `let()` only sets the value of a variable for the parts of a function >> subordinate to the `let()`. Also, mutable variables become much more >> useful with a `while()` conditional loop statement. >> >> >> It would be possible to borrow the syntax that Curv uses for mutable >> variables. It would fit in to OpenSCAD with only minor changes. You can use >> assignment statements and while statements inside a function, or inside a >> list comprehension. >> >> https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> >
R
Robin2
Tue, Oct 1, 2019 8:08 AM

MichaelAtOz wrote

When I first go into 3D printing I looked around as many of the CAD like
offering as I could try, I even considered commercial software (but most
were out of my $'range).
I found the 'traditional' mouse driven CAD cumbersome, if you want
accuracy
you have to do various mousing-about then click on things to open
parameters
then type in values etc.

Then I came across OpenSCAD, as I had a programming background it seemed
good, you just type out your specification for the thing, press F5 and
there
it is. (after debugging...)

This echoes my own experience perfectly.

But then I got tired of all the typing and realised that I can have the best
of both worlds. I don't want to discourage the people who prefer to type in
their code. But I think that a front-end that allows the lazy (like me) to
avoid it would be a benefit.

...R

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

MichaelAtOz wrote > When I first go into 3D printing I looked around as many of the CAD like > offering as I could try, I even considered commercial software (but most > were out of my $'range). > I found the 'traditional' mouse driven CAD cumbersome, if you want > accuracy > you have to do various mousing-about then click on things to open > parameters > then type in values etc. > > Then I came across OpenSCAD, as I had a programming background it seemed > good, you just type out your specification for the thing, press F5 and > there > it is. (after debugging...) This echoes my own experience perfectly. But then I got tired of all the typing and realised that I can have the best of both worlds. I don't want to discourage the people who prefer to type in their code. But I think that a front-end that allows the lazy (like me) to avoid it would be a benefit. ...R -- Sent from: http://forum.openscad.org/
DM
Doug Moen
Tue, Oct 1, 2019 1:30 PM

On Tue, Oct 1, 2019, at 3:00 AM, nop head wrote:

Doesn't the current C like for(..;..;) syntax effectively allow a while loop and mutable variables in the loop?

If we add mutable variables, an assignment statement, and a while loop to OpenSCAD, then we enable a rich set of coding patterns:

  • conditional assignment statements
  • assignments inside a for or while statement which modify an accumulator variable
    And these patterns can be nested and sequenced.

The C-like for (;;) syntax is only available inside list comprehensions, where it is used for generating a sequence of list elements. I do not think that list comprehensions are in any way a replacement for general imperative programming features.

Here is a Curv function that I used for generating a shape based on voronoi diagrams. I think it would be quite painful to translate this into OpenSCAD using tail recursion and list comprehensions. I ported this code from another language. A major benefit of imperative programming in Curv is that I could port the code trivially, doing a line-for-line transliteration, without wholesale restructuring of the code to use entirely different coding patterns.

// input: 2D coordinate, output: distance to cell border
voronoi x =
let
n = floor(x - 1.5);
f = x - n;
md = 8;
in do
// first pass: distance to cell centre
local mr = [0,0];
for (j in 0 .. 3)
for (i in 0 .. 3) (
local g = [i,j];
local o = hash2x2(n + g);
local r = g + o - f;
local d = dot(r,r);
if (d < md) (
md := d;
mr := r;
);
);
// second pass: distance to border
md := 8.0;
for (j in 0 .. 3)
for (i in 0 .. 3) (
local g = [i,j];
local o = hash2x2( n + g );
local r = g + o - f;
if (dot(mr-r,mr-r)>EPSILON) // skip the same cell
md := smooth_min(md, dot(0.5*(mr+r), normalize(r-mr)),.2);
);
in md;

On Tue, Oct 1, 2019, at 3:00 AM, nop head wrote: > Doesn't the current C like for(..;..;) syntax effectively allow a while loop and mutable variables in the loop? If we add mutable variables, an assignment statement, and a while loop to OpenSCAD, then we enable a rich set of coding patterns: * conditional assignment statements * assignments inside a `for` or `while` statement which modify an accumulator variable And these patterns can be nested and sequenced. The C-like for (;;) syntax is only available inside list comprehensions, where it is used for generating a sequence of list elements. I do not think that list comprehensions are in any way a replacement for general imperative programming features. Here is a Curv function that I used for generating a shape based on voronoi diagrams. I think it would be quite painful to translate this into OpenSCAD using tail recursion and list comprehensions. I ported this code from another language. A major benefit of imperative programming in Curv is that I could port the code trivially, doing a line-for-line transliteration, without wholesale restructuring of the code to use entirely different coding patterns. // input: 2D coordinate, output: distance to cell border voronoi x = let n = floor(x - 1.5); f = x - n; md = 8; in do // first pass: distance to cell centre local mr = [0,0]; for (j in 0 .. 3) for (i in 0 .. 3) ( local g = [i,j]; local o = hash2x2(n + g); local r = g + o - f; local d = dot(r,r); if (d < md) ( md := d; mr := r; ); ); // second pass: distance to border md := 8.0; for (j in 0 .. 3) for (i in 0 .. 3) ( local g = [i,j]; local o = hash2x2( n + g ); local r = g + o - f; if (dot(mr-r,mr-r)>EPSILON) // skip the same cell md := smooth_min(md, dot(0.5*(mr+r), normalize(r-mr)),.2); ); in md;
DM
Doug Moen
Tue, Oct 1, 2019 3:08 PM

On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote:

People say it is hard to write algorithms without mutable variables. Does that mean it is hard to write algorithms in Haskell or does that have them as well?

Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of expressive power. It's true that Haskell and OpenSCAD are both declarative languages with immutable variables, but aside from that, they are totally different.

Haskell has many features and idioms which are not available/not possible in OpenSCAD, which are used as an alternative to mutable variables.

  1. Haskell has generalized tail recursion optimization. The corresponding feature in OpenSCAD is restricted to one specific code pattern, and only works for self-recursive functions, not mutually recursive functions.

  2. Haskell has combinators, which are functions that take functions as arguments, and return functions as results. There is a large standard library of combinators, which are used as functional control structures, and replace most uses of tail recursion. These library combinators use tail recursion internally, and encapsulate high level patterns of tail recursion. Tail recursion is considered to be a "low level" coding pattern, which you only resort to when necessary.

This style of programming will become possible in OpenSCAD once function values are added to the language. To fully support this style of programming, we would want better tail recursion support, and a very terse syntax for anonymous function literals.

  1. Haskell has lazy data structures. Notably, it has lazy lists. A lazy list is a potentially infinite list, in which list elements are only computed the first time you access them, then the element values are cached. Using lazy lists, you can decompose an imperative loop into two pieces: the piece that generates the sequence of elements is encapsulated as a lazy list. The piece that consumes the sequence of elements is now separate. This enables a new kind of modularity and a new style of programming.

  2. Haskell has monads, which are a generalization of sequentially executed statements in imperative programming. In OpenSCAD, you can use sequences of if statements and for statements at the top level, or inside a module, to construct an "implicit union" of shapes. In Haskell terminology, we would call that the "union monad". In OpenSCAD, you can also use this same statement syntax inside a list comprehension, to construct a sequence of list values. This corresponds to the List Monad in Haskell. Haskell has many other monads, and it's easy to define new ones.

One of the things that originally impressed me about OpenSCAD is the fact that it has monads (which are declarative) dressed up to look exactly like C statements and control structures (which are imperative). In Curv, I've created something that is essentially a "mutable variable monad". It looks just like imperative programming, but it is syntactic sugar for something that is actually declarative and referentially transparent.

Haskell monads are notoriously difficult to learn (due to the way they are presented). In F#, the same feature is called "computation expressions". The syntax and presentation of computation expressions is much more friendly to imperative programmers. In F#, the "list monad" is called the "sequence builder", and F# sequence expressions are very similar to OpenSCAD list comprehensions, except that there are more statement types, including a "while" statement.

  1. In imperative programming languages, you use mutable variables to incrementally build up a compound data structure. You can assign an individual component of an array using a[i] = newvalue, and this is an efficient operation. Haskell has functional data structures, which support efficient incremental update without mutation, and Haskell has an "optics" library for efficiently constructing and composing get and set operations on individual elements of a large data structure. Think of optics as a declarative query language.

I think that function values are an essential programming feature, and they will allow us to cherry pick some of the easiest to understand idioms from Haskell. But I also think that imperative style programming idioms are easier for the OpenSCAD community than the corresponding Haskell idioms that are used for doing the same job.

On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote: > People say it is hard to write algorithms without mutable variables. Does that mean it is hard to write algorithms in Haskell or does that have them as well? Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of expressive power. It's true that Haskell and OpenSCAD are both declarative languages with immutable variables, but aside from that, they are totally different. Haskell has many features and idioms which are not available/not possible in OpenSCAD, which are used as an alternative to mutable variables. 0. Haskell has generalized tail recursion optimization. The corresponding feature in OpenSCAD is restricted to one specific code pattern, and only works for self-recursive functions, not mutually recursive functions. 1. Haskell has combinators, which are functions that take functions as arguments, and return functions as results. There is a large standard library of combinators, which are used as functional control structures, and replace most uses of tail recursion. These library combinators use tail recursion internally, and encapsulate high level patterns of tail recursion. Tail recursion is considered to be a "low level" coding pattern, which you only resort to when necessary. This style of programming will become possible in OpenSCAD once function values are added to the language. To fully support this style of programming, we would want better tail recursion support, and a very terse syntax for anonymous function literals. 2. Haskell has lazy data structures. Notably, it has lazy lists. A lazy list is a potentially infinite list, in which list elements are only computed the first time you access them, then the element values are cached. Using lazy lists, you can decompose an imperative loop into two pieces: the piece that generates the sequence of elements is encapsulated as a lazy list. The piece that consumes the sequence of elements is now separate. This enables a new kind of modularity and a new style of programming. 3. Haskell has monads, which are a generalization of sequentially executed statements in imperative programming. In OpenSCAD, you can use sequences of if statements and for statements at the top level, or inside a module, to construct an "implicit union" of shapes. In Haskell terminology, we would call that the "union monad". In OpenSCAD, you can also use this same statement syntax inside a list comprehension, to construct a sequence of list values. This corresponds to the List Monad in Haskell. Haskell has many other monads, and it's easy to define new ones. One of the things that originally impressed me about OpenSCAD is the fact that it has monads (which are declarative) dressed up to look exactly like C statements and control structures (which are imperative). In Curv, I've created something that is essentially a "mutable variable monad". It looks just like imperative programming, but it is syntactic sugar for something that is actually declarative and referentially transparent. Haskell monads are notoriously difficult to learn (due to the way they are presented). In F#, the same feature is called "computation expressions". The syntax and presentation of computation expressions is much more friendly to imperative programmers. In F#, the "list monad" is called the "sequence builder", and F# sequence expressions are very similar to OpenSCAD list comprehensions, except that there are more statement types, including a "while" statement. 4. In imperative programming languages, you use mutable variables to incrementally build up a compound data structure. You can assign an individual component of an array using `a[i] = newvalue`, and this is an efficient operation. Haskell has functional data structures, which support efficient incremental update without mutation, and Haskell has an "optics" library for efficiently constructing and composing get and set operations on individual elements of a large data structure. Think of optics as a declarative query language. I think that function values are an essential programming feature, and they will allow us to cherry pick some of the easiest to understand idioms from Haskell. But I also think that imperative style programming idioms are easier for the OpenSCAD community than the corresponding Haskell idioms that are used for doing the same job.
NH
nop head
Tue, Oct 1, 2019 3:41 PM

Thanks for the detailed explanation.  I never program anything complicated
enough in OpenSCAD to need anything mutable variables.

On Tue, 1 Oct 2019 at 16:09, Doug Moen doug@moens.org wrote:

On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote:

People say it is hard to write algorithms without mutable variables. Does
that mean it is hard to write algorithms in Haskell or does that have them
as well?

Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of
expressive power. It's true that Haskell and OpenSCAD are both declarative
languages with immutable variables, but aside from that, they are totally
different.

Haskell has many features and idioms which are not available/not possible
in OpenSCAD, which are used as an alternative to mutable variables.

  1. Haskell has generalized tail recursion optimization. The corresponding
    feature in OpenSCAD is restricted to one specific code pattern, and only
    works for self-recursive functions, not mutually recursive functions.

  2. Haskell has combinators, which are functions that take functions as
    arguments, and return functions as results. There is a large standard
    library of combinators, which are used as functional control structures,
    and replace most uses of tail recursion. These library combinators use tail
    recursion internally, and encapsulate high level patterns of tail
    recursion. Tail recursion is considered to be a "low level" coding pattern,
    which you only resort to when necessary.

This style of programming will become possible in OpenSCAD once function
values are added to the language. To fully support this style of
programming, we would want better tail recursion support, and a very terse
syntax for anonymous function literals.

  1. Haskell has lazy data structures. Notably, it has lazy lists. A lazy
    list is a potentially infinite list, in which list elements are only
    computed the first time you access them, then the element values are
    cached. Using lazy lists, you can decompose an imperative loop into two
    pieces: the piece that generates the sequence of elements is encapsulated
    as a lazy list. The piece that consumes the sequence of elements is now
    separate. This enables a new kind of modularity and a new style of
    programming.

  2. Haskell has monads, which are a generalization of sequentially executed
    statements in imperative programming. In OpenSCAD, you can use sequences of
    if statements and for statements at the top level, or inside a module, to
    construct an "implicit union" of shapes. In Haskell terminology, we would
    call that the "union monad". In OpenSCAD, you can also use this same
    statement syntax inside a list comprehension, to construct a sequence of
    list values. This corresponds to the List Monad in Haskell. Haskell has
    many other monads, and it's easy to define new ones.

One of the things that originally impressed me about OpenSCAD is the fact
that it has monads (which are declarative) dressed up to look exactly like
C statements and control structures (which are imperative). In Curv, I've
created something that is essentially a "mutable variable monad". It looks
just like imperative programming, but it is syntactic sugar for something
that is actually declarative and referentially transparent.

Haskell monads are notoriously difficult to learn (due to the way they are
presented). In F#, the same feature is called "computation expressions".
The syntax and presentation of computation expressions is much more
friendly to imperative programmers. In F#, the "list monad" is called the
"sequence builder", and F# sequence expressions are very similar to
OpenSCAD list comprehensions, except that there are more statement types,
including a "while" statement.

  1. In imperative programming languages, you use mutable variables to
    incrementally build up a compound data structure. You can assign an
    individual component of an array using a[i] = newvalue, and this is an
    efficient operation. Haskell has functional data structures, which support
    efficient incremental update without mutation, and Haskell has an "optics"
    library for efficiently constructing and composing get and set operations
    on individual elements of a large data structure. Think of optics as a
    declarative query language.

I think that function values are an essential programming feature, and
they will allow us to cherry pick some of the easiest to understand idioms
from Haskell. But I also think that imperative style programming idioms are
easier for the OpenSCAD community than the corresponding Haskell idioms
that are used for doing the same job.


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

Thanks for the detailed explanation. I never program anything complicated enough in OpenSCAD to need anything mutable variables. On Tue, 1 Oct 2019 at 16:09, Doug Moen <doug@moens.org> wrote: > On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote: > > People say it is hard to write algorithms without mutable variables. Does > that mean it is hard to write algorithms in Haskell or does that have them > as well? > > > Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of > expressive power. It's true that Haskell and OpenSCAD are both declarative > languages with immutable variables, but aside from that, they are totally > different. > > Haskell has many features and idioms which are not available/not possible > in OpenSCAD, which are used as an alternative to mutable variables. > > 0. Haskell has generalized tail recursion optimization. The corresponding > feature in OpenSCAD is restricted to one specific code pattern, and only > works for self-recursive functions, not mutually recursive functions. > > 1. Haskell has combinators, which are functions that take functions as > arguments, and return functions as results. There is a large standard > library of combinators, which are used as functional control structures, > and replace most uses of tail recursion. These library combinators use tail > recursion internally, and encapsulate high level patterns of tail > recursion. Tail recursion is considered to be a "low level" coding pattern, > which you only resort to when necessary. > > This style of programming will become possible in OpenSCAD once function > values are added to the language. To fully support this style of > programming, we would want better tail recursion support, and a very terse > syntax for anonymous function literals. > > 2. Haskell has lazy data structures. Notably, it has lazy lists. A lazy > list is a potentially infinite list, in which list elements are only > computed the first time you access them, then the element values are > cached. Using lazy lists, you can decompose an imperative loop into two > pieces: the piece that generates the sequence of elements is encapsulated > as a lazy list. The piece that consumes the sequence of elements is now > separate. This enables a new kind of modularity and a new style of > programming. > > 3. Haskell has monads, which are a generalization of sequentially executed > statements in imperative programming. In OpenSCAD, you can use sequences of > if statements and for statements at the top level, or inside a module, to > construct an "implicit union" of shapes. In Haskell terminology, we would > call that the "union monad". In OpenSCAD, you can also use this same > statement syntax inside a list comprehension, to construct a sequence of > list values. This corresponds to the List Monad in Haskell. Haskell has > many other monads, and it's easy to define new ones. > > One of the things that originally impressed me about OpenSCAD is the fact > that it has monads (which are declarative) dressed up to look exactly like > C statements and control structures (which are imperative). In Curv, I've > created something that is essentially a "mutable variable monad". It looks > just like imperative programming, but it is syntactic sugar for something > that is actually declarative and referentially transparent. > > Haskell monads are notoriously difficult to learn (due to the way they are > presented). In F#, the same feature is called "computation expressions". > The syntax and presentation of computation expressions is much more > friendly to imperative programmers. In F#, the "list monad" is called the > "sequence builder", and F# sequence expressions are very similar to > OpenSCAD list comprehensions, except that there are more statement types, > including a "while" statement. > > 4. In imperative programming languages, you use mutable variables to > incrementally build up a compound data structure. You can assign an > individual component of an array using `a[i] = newvalue`, and this is an > efficient operation. Haskell has functional data structures, which support > efficient incremental update without mutation, and Haskell has an "optics" > library for efficiently constructing and composing get and set operations > on individual elements of a large data structure. Think of optics as a > declarative query language. > > I think that function values are an essential programming feature, and > they will allow us to cherry pick some of the easiest to understand idioms > from Haskell. But I also think that imperative style programming idioms are > easier for the OpenSCAD community than the corresponding Haskell idioms > that are used for doing the same job. > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Tue, Oct 1, 2019 4:55 PM

I have learned how to code without mutable variables with OpenSCAD. Most of
time. But the lack of mutable data structures is a drawback for instance to
express in OpenSCAD language efficient algorithms to triangulate a set of
points.

A terça, 1/10/2019, 16:43, nop head nop.head@gmail.com escreveu:

Thanks for the detailed explanation.  I never program anything complicated
enough in OpenSCAD to need anything mutable variables.

On Tue, 1 Oct 2019 at 16:09, Doug Moen doug@moens.org wrote:

On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote:

People say it is hard to write algorithms without mutable variables. Does
that mean it is hard to write algorithms in Haskell or does that have them
as well?

Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of
expressive power. It's true that Haskell and OpenSCAD are both declarative
languages with immutable variables, but aside from that, they are totally
different.

Haskell has many features and idioms which are not available/not possible
in OpenSCAD, which are used as an alternative to mutable variables.

  1. Haskell has generalized tail recursion optimization. The corresponding
    feature in OpenSCAD is restricted to one specific code pattern, and only
    works for self-recursive functions, not mutually recursive functions.

  2. Haskell has combinators, which are functions that take functions as
    arguments, and return functions as results. There is a large standard
    library of combinators, which are used as functional control structures,
    and replace most uses of tail recursion. These library combinators use tail
    recursion internally, and encapsulate high level patterns of tail
    recursion. Tail recursion is considered to be a "low level" coding pattern,
    which you only resort to when necessary.

This style of programming will become possible in OpenSCAD once function
values are added to the language. To fully support this style of
programming, we would want better tail recursion support, and a very terse
syntax for anonymous function literals.

  1. Haskell has lazy data structures. Notably, it has lazy lists. A lazy
    list is a potentially infinite list, in which list elements are only
    computed the first time you access them, then the element values are
    cached. Using lazy lists, you can decompose an imperative loop into two
    pieces: the piece that generates the sequence of elements is encapsulated
    as a lazy list. The piece that consumes the sequence of elements is now
    separate. This enables a new kind of modularity and a new style of
    programming.

  2. Haskell has monads, which are a generalization of sequentially
    executed statements in imperative programming. In OpenSCAD, you can use
    sequences of if statements and for statements at the top level, or inside a
    module, to construct an "implicit union" of shapes. In Haskell terminology,
    we would call that the "union monad". In OpenSCAD, you can also use this
    same statement syntax inside a list comprehension, to construct a sequence
    of list values. This corresponds to the List Monad in Haskell. Haskell has
    many other monads, and it's easy to define new ones.

One of the things that originally impressed me about OpenSCAD is the fact
that it has monads (which are declarative) dressed up to look exactly like
C statements and control structures (which are imperative). In Curv, I've
created something that is essentially a "mutable variable monad". It looks
just like imperative programming, but it is syntactic sugar for something
that is actually declarative and referentially transparent.

Haskell monads are notoriously difficult to learn (due to the way they
are presented). In F#, the same feature is called "computation
expressions". The syntax and presentation of computation expressions is
much more friendly to imperative programmers. In F#, the "list monad" is
called the "sequence builder", and F# sequence expressions are very similar
to OpenSCAD list comprehensions, except that there are more statement
types, including a "while" statement.

  1. In imperative programming languages, you use mutable variables to
    incrementally build up a compound data structure. You can assign an
    individual component of an array using a[i] = newvalue, and this is an
    efficient operation. Haskell has functional data structures, which support
    efficient incremental update without mutation, and Haskell has an "optics"
    library for efficiently constructing and composing get and set operations
    on individual elements of a large data structure. Think of optics as a
    declarative query language.

I think that function values are an essential programming feature, and
they will allow us to cherry pick some of the easiest to understand idioms
from Haskell. But I also think that imperative style programming idioms are
easier for the OpenSCAD community than the corresponding Haskell idioms
that are used for doing the same job.


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

I have learned how to code without mutable variables with OpenSCAD. Most of time. But the lack of mutable data structures is a drawback for instance to express in OpenSCAD language efficient algorithms to triangulate a set of points. A terça, 1/10/2019, 16:43, nop head <nop.head@gmail.com> escreveu: > Thanks for the detailed explanation. I never program anything complicated > enough in OpenSCAD to need anything mutable variables. > > On Tue, 1 Oct 2019 at 16:09, Doug Moen <doug@moens.org> wrote: > >> On Tue, Oct 1, 2019, at 3:02 AM, nop head wrote: >> >> People say it is hard to write algorithms without mutable variables. Does >> that mean it is hard to write algorithms in Haskell or does that have them >> as well? >> >> >> Haskell and OpenSCAD are at opposite ends of the spectrum, in terms of >> expressive power. It's true that Haskell and OpenSCAD are both declarative >> languages with immutable variables, but aside from that, they are totally >> different. >> >> Haskell has many features and idioms which are not available/not possible >> in OpenSCAD, which are used as an alternative to mutable variables. >> >> 0. Haskell has generalized tail recursion optimization. The corresponding >> feature in OpenSCAD is restricted to one specific code pattern, and only >> works for self-recursive functions, not mutually recursive functions. >> >> 1. Haskell has combinators, which are functions that take functions as >> arguments, and return functions as results. There is a large standard >> library of combinators, which are used as functional control structures, >> and replace most uses of tail recursion. These library combinators use tail >> recursion internally, and encapsulate high level patterns of tail >> recursion. Tail recursion is considered to be a "low level" coding pattern, >> which you only resort to when necessary. >> >> This style of programming will become possible in OpenSCAD once function >> values are added to the language. To fully support this style of >> programming, we would want better tail recursion support, and a very terse >> syntax for anonymous function literals. >> >> 2. Haskell has lazy data structures. Notably, it has lazy lists. A lazy >> list is a potentially infinite list, in which list elements are only >> computed the first time you access them, then the element values are >> cached. Using lazy lists, you can decompose an imperative loop into two >> pieces: the piece that generates the sequence of elements is encapsulated >> as a lazy list. The piece that consumes the sequence of elements is now >> separate. This enables a new kind of modularity and a new style of >> programming. >> >> 3. Haskell has monads, which are a generalization of sequentially >> executed statements in imperative programming. In OpenSCAD, you can use >> sequences of if statements and for statements at the top level, or inside a >> module, to construct an "implicit union" of shapes. In Haskell terminology, >> we would call that the "union monad". In OpenSCAD, you can also use this >> same statement syntax inside a list comprehension, to construct a sequence >> of list values. This corresponds to the List Monad in Haskell. Haskell has >> many other monads, and it's easy to define new ones. >> >> One of the things that originally impressed me about OpenSCAD is the fact >> that it has monads (which are declarative) dressed up to look exactly like >> C statements and control structures (which are imperative). In Curv, I've >> created something that is essentially a "mutable variable monad". It looks >> just like imperative programming, but it is syntactic sugar for something >> that is actually declarative and referentially transparent. >> >> Haskell monads are notoriously difficult to learn (due to the way they >> are presented). In F#, the same feature is called "computation >> expressions". The syntax and presentation of computation expressions is >> much more friendly to imperative programmers. In F#, the "list monad" is >> called the "sequence builder", and F# sequence expressions are very similar >> to OpenSCAD list comprehensions, except that there are more statement >> types, including a "while" statement. >> >> 4. In imperative programming languages, you use mutable variables to >> incrementally build up a compound data structure. You can assign an >> individual component of an array using `a[i] = newvalue`, and this is an >> efficient operation. Haskell has functional data structures, which support >> efficient incremental update without mutation, and Haskell has an "optics" >> library for efficiently constructing and composing get and set operations >> on individual elements of a large data structure. Think of optics as a >> declarative query language. >> >> I think that function values are an essential programming feature, and >> they will allow us to cherry pick some of the easiest to understand idioms >> from Haskell. But I also think that imperative style programming idioms are >> easier for the OpenSCAD community than the corresponding Haskell idioms >> that are used for doing the same job. >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RD
Revar Desmera
Tue, Oct 1, 2019 6:16 PM

Just because a language is Turing Complete, does not mean it is efficient or developer friendly.

  • Revar

On Oct 1, 2019, at 12:04 AM, nop head nop.head@gmail.com wrote:


People say it is hard to write algorithms without mutable variables. Does that mean it is hard to write algorithms in Haskell or does that have them as well?

On Tue, 1 Oct 2019 at 08:00, nop head nop.head@gmail.com wrote:
Doesn't the current C like for(..;..;)  syntax effectively allow a while loop and mutable variables in the loop?

On Tue, 1 Oct 2019 at 04:51, Doug Moen doug@moens.org wrote:

  1. Mutable variables.

[...] It's not something very high at my personal wish-list at
this point [...]

This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since let() only sets the value of a variable for the parts of a function subordinate to the let().  Also, mutable variables become much more useful with a while() conditional loop statement.

It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension.

https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst


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

Just because a language is Turing Complete, does not mean it is efficient or developer friendly. - Revar > On Oct 1, 2019, at 12:04 AM, nop head <nop.head@gmail.com> wrote: > >  > People say it is hard to write algorithms without mutable variables. Does that mean it is hard to write algorithms in Haskell or does that have them as well? > >> On Tue, 1 Oct 2019 at 08:00, nop head <nop.head@gmail.com> wrote: >> Doesn't the current C like for(..;..;) syntax effectively allow a while loop and mutable variables in the loop? >> >>> On Tue, 1 Oct 2019 at 04:51, Doug Moen <doug@moens.org> wrote: >>> >>>>>> 1. Mutable variables. >>>>> >>>>> [...] It's not something very high at my personal wish-list at >>>>> this point [...] >>>> >>>> This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since `let()` only sets the value of a variable for the parts of a function subordinate to the `let()`. Also, mutable variables become much more useful with a `while()` conditional loop statement. >>> >>> It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension. >>> >>> https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst >>> _______________________________________________ >>> OpenSCAD mailing list >>> Discuss@lists.openscad.org >>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
RD
Revar Desmera
Tue, Oct 1, 2019 6:22 PM

Actually, it might. Slightly awkward, but it should be abusable to allow more complex algorithms. Honestly I’d forgotten that syntax existed.  Thanks.

  • Revar

On Oct 1, 2019, at 12:02 AM, nop head nop.head@gmail.com wrote:


Doesn't the current C like for(..;..;)  syntax effectively allow a while loop and mutable variables in the loop?

On Tue, 1 Oct 2019 at 04:51, Doug Moen doug@moens.org wrote:

  1. Mutable variables.

[...] It's not something very high at my personal wish-list at
this point [...]

This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since let() only sets the value of a variable for the parts of a function subordinate to the let().  Also, mutable variables become much more useful with a while() conditional loop statement.

It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension.

https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst


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

Actually, it might. Slightly awkward, but it should be abusable to allow more complex algorithms. Honestly I’d forgotten that syntax existed. Thanks. - Revar > On Oct 1, 2019, at 12:02 AM, nop head <nop.head@gmail.com> wrote: > >  > Doesn't the current C like for(..;..;) syntax effectively allow a while loop and mutable variables in the loop? > >> On Tue, 1 Oct 2019 at 04:51, Doug Moen <doug@moens.org> wrote: >> >>>>> 1. Mutable variables. >>>> >>>> [...] It's not something very high at my personal wish-list at >>>> this point [...] >>> >>> This is perhaps the most highly desired feature request I have. Though it's unclear to me how it would be handled in a function context, since `let()` only sets the value of a variable for the parts of a function subordinate to the `let()`. Also, mutable variables become much more useful with a `while()` conditional loop statement. >> >> It would be possible to borrow the syntax that Curv uses for mutable variables. It would fit in to OpenSCAD with only minor changes. You can use assignment statements and while statements inside a function, or inside a list comprehension. >> >> https://github.com/curv3d/curv/blob/master/docs/language/Statements.rst >> _______________________________________________ >> OpenSCAD mailing list >> Discuss@lists.openscad.org >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org