discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

OO patterns in OpenSCAD

JB
Jordan Brown
Tue, Apr 6, 2021 3:33 PM

On 4/6/2021 5:46 AM, NateTG wrote:

I'm certainly used to "if you care about the order use a list"
thinking.  It's probably a good idea for there to be consistent
behavior, but I'm not sure having people rely on it is a good thing to
encourage.

I'm prototyping some dictionary/object/structure/whatever-you-call-it
support.  (I want to do a text metrics function, and nobody likes
returning all of the data in an undifferentiated array.)

I started with "order not specified", and that's fine when you're just
accessing specific values, but I found it deeply unsatisfying as soon as
you print a value.  Not that I expect us to switch to objects for 3D
points[*], but it would be just wrong to print "{ y: 3, x: 2, z: 4 }".

[*] though we should probably make things that consume 3D points
able to consume such objects.

I can certainly see first beats the second, second beats the first,
and assert(false) as desired behaviors for key collision, and I don't
think there's a perfect solution for that.  I can even see some
utility in retaining multiple (key,value) pairs for a single given key.

I didn't have to think about this for my prototype, because I was only
working on the "consumer" side - the initial producers were going to be
internal.  Even on the consumer side, I didn't try to implement
traversal.  I don't have any strong feelings, other than that "retain
multiple" seems really likely to cause confusion.  (And, depending on
what it means, you still have to decide which wins when you do an
indexed lookup.)

It seems like we should expect dict["key"] to evaluate to undef for
unset values, which leads to the question whether there should be a
difference between setting a value to undef and not setting the value
in the first place.

The answer should be the same as it is today for array references:  a
constant "undef" is the same as a missing entry, at least for simple
lookup.  If there's a "does object X contain key Y" test then yeah, I
suppose you could use that to tell the difference, just as you can use
len() to tell the difference for arrays.

On 4/6/2021 5:46 AM, NateTG wrote: > I'm certainly used to "if you care about the order use a list" > thinking.  It's probably a good idea for there to be consistent > behavior, but I'm not sure having people rely on it is a good thing to > encourage. I'm prototyping some dictionary/object/structure/whatever-you-call-it support.  (I want to do a text metrics function, and nobody likes returning all of the data in an undifferentiated array.) I started with "order not specified", and that's fine when you're just accessing specific values, but I found it deeply unsatisfying as soon as you print a value.  Not that I expect us to switch to objects for 3D points[*], but it would be just wrong to print "{ y: 3, x: 2, z: 4 }". [*] though we should probably make things that consume 3D points able to consume such objects. > I can certainly see first beats the second, second beats the first, > and assert(false) as desired behaviors for key collision, and I don't > think there's a perfect solution for that.  I can even see some > utility in retaining multiple (key,value) pairs for a single given key. I didn't have to think about this for my prototype, because I was only working on the "consumer" side - the initial producers were going to be internal.  Even on the consumer side, I didn't try to implement traversal.  I don't have any strong feelings, other than that "retain multiple" seems really likely to cause confusion.  (And, depending on what it means, you still have to decide which wins when you do an indexed lookup.) > It seems like we should expect dict["key"] to evaluate to undef for > unset values, which leads to the question whether there should be a > difference between setting a value to undef and not setting the value > in the first place. The answer should be the same as it is today for array references:  a constant "undef" is the same as a missing entry, at least for simple lookup.  If there's a "does object X contain key Y" test then yeah, I suppose you could use that to tell the difference, just as you can use len() to tell the difference for arrays.
A
adrianv
Tue, Apr 6, 2021 8:29 PM

Doesn't https://github.com/openscad/openscad/pull/3087 already somewhat
implement this idea?  (It is more like structures than dictionaries, I
think.)

I do not see any reason that "things that consume 3d points consume these
objects".  You think an array of dictionaries that all of x, y and z fields
needs to be treated the same as an array of 3-vectors?  I would say no to
that.

JordanBrown wrote

On 4/6/2021 5:46 AM, NateTG wrote:

I'm certainly used to "if you care about the order use a list"
thinking.  It's probably a good idea for there to be consistent
behavior, but I'm not sure having people rely on it is a good thing to
encourage.

I'm prototyping some dictionary/object/structure/whatever-you-call-it
support.  (I want to do a text metrics function, and nobody likes
returning all of the data in an undifferentiated array.)

I started with "order not specified", and that's fine when you're just
accessing specific values, but I found it deeply unsatisfying as soon as
you print a value.  Not that I expect us to switch to objects for 3D
points[*], but it would be just wrong to print "{ y: 3, x: 2, z: 4 }".

 [*] though we should probably make things that consume 3D points
 able to consume such objects.

I can certainly see first beats the second, second beats the first,
and assert(false) as desired behaviors for key collision, and I don't
think there's a perfect solution for that.  I can even see some
utility in retaining multiple (key,value) pairs for a single given key.

I didn't have to think about this for my prototype, because I was only
working on the "consumer" side - the initial producers were going to be
internal.  Even on the consumer side, I didn't try to implement
traversal.  I don't have any strong feelings, other than that "retain
multiple" seems really likely to cause confusion.  (And, depending on
what it means, you still have to decide which wins when you do an
indexed lookup.)

It seems like we should expect dict["key"] to evaluate to undef for
unset values, which leads to the question whether there should be a
difference between setting a value to undef and not setting the value
in the first place.

The answer should be the same as it is today for array references:  a
constant "undef" is the same as a missing entry, at least for simple
lookup.  If there's a "does object X contain key Y" test then yeah, I
suppose you could use that to tell the difference, just as you can use
len() to tell the difference for arrays.


OpenSCAD mailing list
To unsubscribe send an email to

discuss-leave@.openscad

Doesn't https://github.com/openscad/openscad/pull/3087 already somewhat implement this idea? (It is more like structures than dictionaries, I think.) I do not see any reason that "things that consume 3d points consume these objects". You think an array of dictionaries that all of x, y and z fields needs to be treated the same as an array of 3-vectors? I would say no to that. JordanBrown wrote > On 4/6/2021 5:46 AM, NateTG wrote: >> I'm certainly used to "if you care about the order use a list" >> thinking.  It's probably a good idea for there to be consistent >> behavior, but I'm not sure having people rely on it is a good thing to >> encourage. > > I'm prototyping some dictionary/object/structure/whatever-you-call-it > support.  (I want to do a text metrics function, and nobody likes > returning all of the data in an undifferentiated array.) > > I started with "order not specified", and that's fine when you're just > accessing specific values, but I found it deeply unsatisfying as soon as > you print a value.  Not that I expect us to switch to objects for 3D > points[*], but it would be just wrong to print "{ y: 3, x: 2, z: 4 }". > > [*] though we should probably make things that consume 3D points > able to consume such objects. > > > >> I can certainly see first beats the second, second beats the first, >> and assert(false) as desired behaviors for key collision, and I don't >> think there's a perfect solution for that.  I can even see some >> utility in retaining multiple (key,value) pairs for a single given key. > > I didn't have to think about this for my prototype, because I was only > working on the "consumer" side - the initial producers were going to be > internal.  Even on the consumer side, I didn't try to implement > traversal.  I don't have any strong feelings, other than that "retain > multiple" seems really likely to cause confusion.  (And, depending on > what it means, you still have to decide which wins when you do an > indexed lookup.) > >> It seems like we should expect dict["key"] to evaluate to undef for >> unset values, which leads to the question whether there should be a >> difference between setting a value to undef and not setting the value >> in the first place. > > The answer should be the same as it is today for array references:  a > constant "undef" is the same as a missing entry, at least for simple > lookup.  If there's a "does object X contain key Y" test then yeah, I > suppose you could use that to tell the difference, just as you can use > len() to tell the difference for arrays. > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to > discuss-leave@.openscad -- Sent from: http://forum.openscad.org/
JB
Jordan Brown
Wed, Apr 7, 2021 12:33 AM

On 4/6/2021 1:29 PM, adrianv wrote:

Doesn't https://github.com/openscad/openscad/pull/3087
https://github.com/openscad/openscad/pull/3087 already somewhat
implement this idea?  (It is more like structures than dictionaries, I
think.)  

My work is based on that and is intended to be a subset that could be
integrated before the full wad is ready.  The "consumer" side - the idea
that in a structure s with member m, you can say s.m to access the
member - seems to be pretty non-controversial.  Being able to say s["m"]
doesn't seem controversial either.  The syntactic trouble is in how
object literals are specified and how that syntax interacts with other
proposals.

What distinction are you drawing between structures and dictionaries? 
If we were talking about a static-typed language there would likely be a
data typing difference, but we're talking about a dynamic-type
language.  Maybe I've spent too much time in JavaScript recently, but in
this class of language I'd tend to put associative arrays, dictionaries,
structures, and object members all in the same bucket.  I don't see
enough difference between them to warrant the complexity associated with
having more than one concept.

I do not see any reason that "things that consume 3d points consume
these objects".  You think an array of dictionaries that all of x, y
and z fields needs to be treated the same as an array of 3-vectors?  I
would say no to that.

I can't say that it's important to me or that it's a fully-formed
concept, but ... why not?  "Needs"?  Certainly not.  But it might be good.

For instance, using a hypothetical syntax for object literals, some
might consider

translate({z: 10}) ...

to be more obvious than

translate([0,0,10]) ...
On 4/6/2021 1:29 PM, adrianv wrote: > Doesn't https://github.com/openscad/openscad/pull/3087 > <https://github.com/openscad/openscad/pull/3087> already somewhat > implement this idea?  (It is more like structures than dictionaries, I > think.)   My work is based on that and is intended to be a subset that could be integrated before the full wad is ready.  The "consumer" side - the idea that in a structure s with member m, you can say s.m to access the member - seems to be pretty non-controversial.  Being able to say s["m"] doesn't seem controversial either.  The syntactic trouble is in how object literals are specified and how that syntax interacts with other proposals. What distinction are you drawing between structures and dictionaries?  If we were talking about a static-typed language there would likely be a data typing difference, but we're talking about a dynamic-type language.  Maybe I've spent too much time in JavaScript recently, but in this class of language I'd tend to put associative arrays, dictionaries, structures, and object members all in the same bucket.  I don't see enough difference between them to warrant the complexity associated with having more than one concept. > I do not see any reason that "things that consume 3d points consume > these objects".  You think an array of dictionaries that all of x, y > and z fields needs to be treated the same as an array of 3-vectors?  I > would say no to that. I can't say that it's important to me or that it's a fully-formed concept, but ... why not?  "Needs"?  Certainly not.  But it might be good. For instance, using a hypothetical syntax for object literals, some might consider translate({z: 10}) ... to be more obvious than translate([0,0,10]) ...
A
adrianv
Wed, Apr 7, 2021 1:07 AM

I guess I think of structures as things that are indexed by strings only with
a syntax like variable.field and dictionaries as a broader category that can
be indexed by other types and need a syntax more like variable[key].  It's
not a huge distinction.  I do not think OpenSCAD should have more than one
of them.

To me the idea of

translate( {z: 10} );

seems clumsy and overly complex.  Seems like if you want this functionality
you write ztranslate().    If you really want something that looks like
that you implement translate(x,y,z) and then you can say
translate(z=10).

JordanBrown wrote

On 4/6/2021 1:29 PM, adrianv wrote:

Doesn't https://github.com/openscad/openscad/pull/3087
<https://github.com/openscad/openscad/pull/3087> already somewhat
implement this idea?  (It is more like structures than dictionaries, I
think.)  

My work is based on that and is intended to be a subset that could be
integrated before the full wad is ready.  The "consumer" side - the idea
that in a structure s with member m, you can say s.m to access the
member - seems to be pretty non-controversial.  Being able to say s["m"]
doesn't seem controversial either.  The syntactic trouble is in how
object literals are specified and how that syntax interacts with other
proposals.

What distinction are you drawing between structures and dictionaries? 
If we were talking about a static-typed language there would likely be a
data typing difference, but we're talking about a dynamic-type
language.  Maybe I've spent too much time in JavaScript recently, but in
this class of language I'd tend to put associative arrays, dictionaries,
structures, and object members all in the same bucket.  I don't see
enough difference between them to warrant the complexity associated with
having more than one concept.

I do not see any reason that "things that consume 3d points consume
these objects".  You think an array of dictionaries that all of x, y
and z fields needs to be treated the same as an array of 3-vectors?  I
would say no to that.

I can't say that it's important to me or that it's a fully-formed
concept, but ... why not?  "Needs"?  Certainly not.  But it might be good.

For instance, using a hypothetical syntax for object literals, some
might consider

 translate({z: 10}) ...

to be more obvious than

 translate([0,0,10]) ...

OpenSCAD mailing list
To unsubscribe send an email to

discuss-leave@.openscad

I guess I think of structures as things that are indexed by strings only with a syntax like variable.field and dictionaries as a broader category that can be indexed by other types and need a syntax more like variable[key]. It's not a huge distinction. I do not think OpenSCAD should have more than one of them. To me the idea of translate( {z: 10} ); seems clumsy and overly complex. Seems like if you want this functionality you write ztranslate(). If you *really* want something that looks like that you implement `translate(x,y,z)` and then you can say `translate(z=10)`. JordanBrown wrote > On 4/6/2021 1:29 PM, adrianv wrote: >> Doesn't https://github.com/openscad/openscad/pull/3087 >> &lt;https://github.com/openscad/openscad/pull/3087&gt; already somewhat >> implement this idea?  (It is more like structures than dictionaries, I >> think.)   > > My work is based on that and is intended to be a subset that could be > integrated before the full wad is ready.  The "consumer" side - the idea > that in a structure s with member m, you can say s.m to access the > member - seems to be pretty non-controversial.  Being able to say s["m"] > doesn't seem controversial either.  The syntactic trouble is in how > object literals are specified and how that syntax interacts with other > proposals. > > What distinction are you drawing between structures and dictionaries?  > If we were talking about a static-typed language there would likely be a > data typing difference, but we're talking about a dynamic-type > language.  Maybe I've spent too much time in JavaScript recently, but in > this class of language I'd tend to put associative arrays, dictionaries, > structures, and object members all in the same bucket.  I don't see > enough difference between them to warrant the complexity associated with > having more than one concept. > >> I do not see any reason that "things that consume 3d points consume >> these objects".  You think an array of dictionaries that all of x, y >> and z fields needs to be treated the same as an array of 3-vectors?  I >> would say no to that. > > I can't say that it's important to me or that it's a fully-formed > concept, but ... why not?  "Needs"?  Certainly not.  But it might be good. > > For instance, using a hypothetical syntax for object literals, some > might consider > > translate({z: 10}) ... > > to be more obvious than > > translate([0,0,10]) ... > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to > discuss-leave@.openscad -- Sent from: http://forum.openscad.org/
JB
Jordan Brown
Wed, Apr 7, 2021 4:05 AM

On 4/6/2021 6:07 PM, adrianv wrote:

I guess I think of structures as things that are indexed by strings
only with a syntax like variable.field and dictionaries as a broader
category that can be indexed by other types and need a syntax more
like variable[key].  It's not a huge distinction.  I do not think
OpenSCAD should have more than one of them.

In that model, I'd say that what I'm thinking of is a dictionary where,
as a special case, if the key is a constant string you can just say
"variable.field".

To me the idea of

translate( {z: 10} );

seems clumsy and overly complex.   Seems like if you want this
functionality you write ztranslate().    If you really want
something that looks like that you implement translate(x,y,z) and
then you can say translate(z=10).  

I don't really disagree, but if we think about other environments you
might well see "Point" as a defined type.  It seems like

typedef struct {
    unsigned x;
    unsigned y;
} POINT;

might well be the canonical example of the use of "typedef".

Should we adopt that notion, that "point" is a distinct (constructed)
type?  If OpenSCAD was a statically typed language, maybe; the type
safety would be nice.  As it is... don't know.

The win over defining translate(x,y,z) is that it applies everywhere;
you don't have to keep defining new arguments.

But I should be clear:  this is not something that I'm passionate
about.  It just seems like a natural evolution.

On 4/6/2021 6:07 PM, adrianv wrote: > I guess I think of structures as things that are indexed by strings > only with a syntax like variable.field and dictionaries as a broader > category that can be indexed by other types and need a syntax more > like variable[key].  It's not a huge distinction.  I do not think > OpenSCAD should have more than one of them. In that model, I'd say that what I'm thinking of is a dictionary where, as a special case, if the key is a constant string you can just say "variable.field". > To me the idea of > > translate( {z: 10} ); > > seems clumsy and overly complex.   Seems like if you want this > functionality you write ztranslate().    If you *really* want > something that looks like that you implement `translate(x,y,z)` and > then you can say `translate(z=10)`.   I don't really disagree, but if we think about other environments you might well see "Point" as a defined type.  It seems like typedef struct { unsigned x; unsigned y; } POINT; might well be the canonical example of the use of "typedef". Should we adopt that notion, that "point" is a distinct (constructed) type?  If OpenSCAD was a statically typed language, maybe; the type safety would be nice.  As it is... don't know. The win over defining translate(x,y,z) is that it applies everywhere; you don't have to keep defining new arguments. But I should be clear:  this is not something that I'm passionate about.  It just seems like a natural evolution.
N
NateTG
Wed, Apr 7, 2021 4:51 PM

JordanBrown wrote

On 4/6/2021 5:46 AM, NateTG wrote:

I'm certainly used to "if you care about the order use a list"
thinking.  It's probably a good idea for there to be consistent
behavior, but I'm not sure having people rely on it is a good thing to
encourage.

I'm prototyping some dictionary/object/structure/whatever-you-call-it
support.  (I want to do a text metrics function, and nobody likes
returning all of the data in an undifferentiated array.)
...

Yeah, my questions was mostly about whether there was some low-hanging thing
that could be done, but I see trial implementations that are at least a year
old, so it seems to be about other aspects of the issue.

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

JordanBrown wrote > On 4/6/2021 5:46 AM, NateTG wrote: >> I'm certainly used to "if you care about the order use a list" >> thinking.  It's probably a good idea for there to be consistent >> behavior, but I'm not sure having people rely on it is a good thing to >> encourage. > > I'm prototyping some dictionary/object/structure/whatever-you-call-it > support.  (I want to do a text metrics function, and nobody likes > returning all of the data in an undifferentiated array.) > ... Yeah, my questions was mostly about whether there was some low-hanging thing that could be done, but I see trial implementations that are at least a year old, so it seems to be about other aspects of the issue. -- Sent from: http://forum.openscad.org/