discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Technical drawing

M
mikeonenine@web.de
Wed, Nov 27, 2024 3:15 AM

No, down inside the module, replacing the 6 with len(radii) and
rearranging so that radii is defined first:

module gear()
{
    radii = [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t];
    num = n*len(radii);
    ...

Ah yeah, that works.

With your code, the parameters can also be put between the brackets in
gear();

Huh?  I don't immediately see how. 

Like: gear(n=25, R=30, t=2.5);

Is that what you meant at the end of your post?

> No, down inside the module, replacing the 6 with len(radii) and \ > rearranging so that radii is defined first: > > ``` > module gear() > { > radii = [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t]; > num = n*len(radii); > ... > > ``` Ah yeah, that works. > > With your code, the parameters can also be put between the brack`e`ts in \ > > gear(); > > Huh?  I don't immediately see how.  Like: `gear(n=25, R=30, t=2.5);` Is that what you meant at the end of your post?
JB
Jordan Brown
Wed, Nov 27, 2024 5:20 AM

On 11/26/2024 7:15 PM, Caddiy via Discuss wrote:

     With your code, the parameters can also be put between the
     brack|e|ts in
     gear();

 Huh?  I don't immediately see how. 

Like: |gear(n=25, R=30, t=2.5);|

|In the version with "module gear()" with no parameters, you can't pass
those values in.

|

Is that what you meant at the end of your post?

Are you asking about this?

Allowing the user to pass either radii or R and/or t is a little
trickier and is left as an exercise for the reader.  Hint:  is_undef()
is your friend.

If so, I mean so that the caller can say any of:

gear(R=30);
gear(t=2.5);
gear(R=30, t=2.5);
gear(radii=[...]);

and also any variation could take n=xxx.

That's going to look something like

module gear(n=n, R=R, t=t, radii) {
    radii =  is_undef(radii)
        ? [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t]
        : radii;
    ... the rest ...

Using "n=n", "R=R", and "t=t" lets you use the globals as defaults, so
that you can also tweak them with the Customizer.  Whether that's a good
idea, shrug.  I'd say that "n=25, R=30, t=2.5" is a bit more natural.

I've used a kind of obscure feature in the example above.  We say that
you can't reassign variables, and that sure looks like it reassigns
radii.  But it really doesn't; the actual rule is that you can't
reassign variables in the same scope.  In an inner scope, you can
assign them; it creates a new variable for that scope... and until the
very moment that it is created, the outer value is still visible.  The
parameters to the module are one scope, and the actual body of the
module is a separate scope, so the body can override the parameters.

I find this idiom - the body overriding the parameters to set defaults -
to be clean, easy to read, and less error-prone than having the two have
different names.  I could have used "radii2" in the assignment, and then
used it in the rest of the module, but it would be possible for me to
forget and use "radii" instead, injecting a perhaps-subtle bug.  Using
the same name means that the parameter, which I don't want to use in
the body, is not visible to the body.

On 11/26/2024 7:15 PM, Caddiy via Discuss wrote: > > With your code, the parameters can also be put between the > brack|e|ts in > gear(); > > Huh?  I don't immediately see how.  > > Like: |gear(n=25, R=30, t=2.5);| > |In the version with "module gear()" with no parameters, you can't pass those values in. | > > Is that what you meant at the end of your post? > Are you asking about this? > > Allowing the user to pass either radii or R and/or t is a little > trickier and is left as an exercise for the reader.  Hint:  is_undef() > is your friend. > If so, I mean so that the caller can say any of: gear(R=30); gear(t=2.5); gear(R=30, t=2.5); gear(radii=[...]); and also any variation could take n=xxx. That's going to look something like module gear(n=n, R=R, t=t, radii) { radii =  is_undef(radii) ? [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t] : radii; ... the rest ... Using "n=n", "R=R", and "t=t" lets you use the globals as defaults, so that you can also tweak them with the Customizer.  Whether that's a good idea, shrug.  I'd say that "n=25, R=30, t=2.5" is a bit more natural. I've used a kind of obscure feature in the example above.  We say that you can't reassign variables, and that sure looks like it reassigns radii.  But it really doesn't; the actual rule is that you can't reassign variables *in the same scope*.  In an inner scope, you can assign them; it creates a new variable for that scope... and until the very moment that it is created, the outer value is still visible.  The parameters to the module are one scope, and the actual body of the module is a separate scope, so the body can override the parameters. I find this idiom - the body overriding the parameters to set defaults - to be clean, easy to read, and less error-prone than having the two have different names.  I could have used "radii2" in the assignment, and then used it in the rest of the module, but it would be possible for me to forget and use "radii" instead, injecting a perhaps-subtle bug.  Using the same name means that the parameter, which I *don't* want to use in the body, is not visible to the body.
HW
Harvey white
Wed, Nov 27, 2024 3:13 PM

The trick is to use the variable name that makes sense in most of the
code, and have a variable name you wouldn't use by accident in the
beginning of the code.

Harvey

On 11/27/2024 12:20 AM, Jordan Brown via Discuss wrote:

On 11/26/2024 7:15 PM, Caddiy via Discuss wrote:

     With your code, the parameters can also be put between the
     brack|e|ts in
     gear();

 Huh?  I don't immediately see how.

Like: |gear(n=25, R=30, t=2.5);|

|In the version with "module gear()" with no parameters, you can't
pass those values in.

|

Is that what you meant at the end of your post?

Are you asking about this?

Allowing the user to pass either radii or R and/or t is a little
trickier and is left as an exercise for the reader. Hint:  is_undef()
is your friend.

If so, I mean so that the caller can say any of:

 gear(R=30);
 gear(t=2.5);
 gear(R=30, t=2.5);
 gear(radii=[...]);

and also any variation could take n=xxx.

That's going to look something like

 module gear(n=n, R=R, t=t, radii) {
      radii =  is_undef(radii)
          ? [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t]
          : radii;
      ... the rest ...

Using "n=n", "R=R", and "t=t" lets you use the globals as defaults, so
that you can also tweak them with the Customizer. Whether that's a
good idea, shrug.  I'd say that "n=25, R=30, t=2.5" is a bit more natural.

I've used a kind of obscure feature in the example above.  We say that
you can't reassign variables, and that sure looks like it reassigns
radii.  But it really doesn't; the actual rule is that you can't
reassign variables in the same scope.  In an inner scope, you can
assign them; it creates a new variable for that scope... and until the
very moment that it is created, the outer value is still visible.  The
parameters to the module are one scope, and the actual body of the
module is a separate scope, so the body can override the parameters.

I find this idiom - the body overriding the parameters to set defaults

  • to be clean, easy to read, and less error-prone than having the two
    have different names.  I could have used "radii2" in the assignment,
    and then used it in the rest of the module, but it would be possible
    for me to forget and use "radii" instead, injecting a perhaps-subtle
    bug.  Using the same name means that the parameter, which I don't
    want to use in the body, is not visible to the body.

OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

The trick is to use the variable name that makes sense in most of the code, and have a variable name you wouldn't use by accident in the beginning of the code. Harvey On 11/27/2024 12:20 AM, Jordan Brown via Discuss wrote: > On 11/26/2024 7:15 PM, Caddiy via Discuss wrote: >> >> With your code, the parameters can also be put between the >> brack|e|ts in >> gear(); >> >> Huh?  I don't immediately see how. >> >> Like: |gear(n=25, R=30, t=2.5);| >> > > |In the version with "module gear()" with no parameters, you can't > pass those values in. > > | >> >> Is that what you meant at the end of your post? >> > > Are you asking about this? >> >> Allowing the user to pass either radii or R and/or t is a little >> trickier and is left as an exercise for the reader. Hint:  is_undef() >> is your friend. >> > > If so, I mean so that the caller can say any of: > > gear(R=30); > gear(t=2.5); > gear(R=30, t=2.5); > gear(radii=[...]); > > and also any variation could take n=xxx. > > > That's going to look something like > > module gear(n=n, R=R, t=t, radii) { > radii =  is_undef(radii) > ? [0.99*R-t,0.99*R+0.10*t,0.99*R+t, 0.99*R+t,0.99*R+0.10*t,0.99*R-t] > : radii; > ... the rest ... > > Using "n=n", "R=R", and "t=t" lets you use the globals as defaults, so > that you can also tweak them with the Customizer. Whether that's a > good idea, shrug.  I'd say that "n=25, R=30, t=2.5" is a bit more natural. > > I've used a kind of obscure feature in the example above.  We say that > you can't reassign variables, and that sure looks like it reassigns > radii.  But it really doesn't; the actual rule is that you can't > reassign variables *in the same scope*.  In an inner scope, you can > assign them; it creates a new variable for that scope... and until the > very moment that it is created, the outer value is still visible.  The > parameters to the module are one scope, and the actual body of the > module is a separate scope, so the body can override the parameters. > > I find this idiom - the body overriding the parameters to set defaults > - to be clean, easy to read, and less error-prone than having the two > have different names.  I could have used "radii2" in the assignment, > and then used it in the rest of the module, but it would be possible > for me to forget and use "radii" instead, injecting a perhaps-subtle > bug.  Using the same name means that the parameter, which I *don't* > want to use in the body, is not visible to the body. > > > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
JB
Jordan Brown
Wed, Nov 27, 2024 4:12 PM

On 11/27/2024 7:13 AM, Harvey white via Discuss wrote:

The trick is to use the variable name that makes sense in most of the
code, and have a variable name you wouldn't use by accident in the
beginning of the code.

The problem is that because OpenSCAD supports passing parameters by name
(not just positionally like many languages), the name used for the
parameter is part of the external interface to the module.

The pattern I initially used was to have the parameter be named "foo"
and the variable that had a default applied be named "_foo", and use
"_foo" throughout the module.  But that is, as I said, prone to the
error of forgetting the underscore.

Of course, this only applies when the parameter needs a default more
complex than is allowed in the parameter declaration.  An example would
be a circular figure that lets you specify either diameter or radius. 
Each can be derived from the other, but in the parameter list you can't
say "default diameter is two times the specified radius" and "default
radius is half of the specified diameter".

On 11/27/2024 7:13 AM, Harvey white via Discuss wrote: > The trick is to use the variable name that makes sense in most of the > code, and have a variable name you wouldn't use by accident in the > beginning of the code. The problem is that because OpenSCAD supports passing parameters by name (not just positionally like many languages), the name used for the parameter is part of the external interface to the module. The pattern I initially used was to have the parameter be named "foo" and the variable that had a default applied be named "_foo", and use "_foo" throughout the module.  But that is, as I said, prone to the error of forgetting the underscore. Of course, this only applies when the parameter needs a default more complex than is allowed in the parameter declaration.  An example would be a circular figure that lets you specify either diameter or radius.  Each can be derived from the other, but in the parameter list you can't say "default diameter is two times the specified radius" and "default radius is half of the specified diameter".