NH
nop head
Wed, Jul 29, 2020 8:03 AM
Or better this:
list = [];
x = list[0]; // x = undef(list index out of bounds at line 2)
if(x)
sphere(x); // Not executed
else
cube(x); // Error cube size parameter is undef(list index out of bounds
at line 2) at line 6
On Wed, 29 Jul 2020 at 09:00, nop head nop.head@gmail.com wrote:
Yes making warmings optional doesn't really solve the backward
compatibility option. A library maintainer would want to turn it on to make
the library easy to use but would then have to fix all the intended uses of
functions returning undef by adding extra code.
Perhaps it should only be an error to use undef in operations that need a
concrete value, i.e. nearly everywhere, except in a boolean context, where
it is simply false. If the undef value carries information of what
generated it that could be part of the warning when it was used.
So something like this.
list = [];
x = list[0]; // x = undef(list index out of bounds)
if(x)
sphere(x); // Not executed
else
cube(x); // Error cube size parameter is undefined (list index out of
bounds at line 2)
On Wed, 29 Jul 2020 at 08:11, Rogier Wolff R.E.Wolff@bitwizard.nl wrote:
On Tue, Jul 28, 2020 at 08:04:54PM +0000, Jordan Brown wrote:
's detected, the harder it will be to find the bug.
Failing "soft" - returning undef, in OpenSCAD - may feel like a happy
Some "failures" are not failures, and need to be handled by higher
layers. The classical example is of a program going to write a file.
To prevent accidentally overwriting the file, the program will attempt
to open the file, get an error: "Can't open file", and then proceed to
write the file.
Sure you can find other ways to do this specific thing, but this is an
example where what the "open" function thought was an error, was
precisely the opposite to the program making the call.
Moving to the context of openscad: Suppose I have a module to make a
screw that takes the "head" as an argument. You could make such a
module to take a number to define what head to use out of a list of
possible heads, but lets say I've structured this differently and I
want to pass the object. (Not sure how to do that in openscad, but
lets assume I can.... Oh! I can do it with a "children" construct!)
Now what if instead of a screw I want to make a threaded rod? No head!
In this case, the module might try to access the empty list of "heads
to put on", but that's not an error. If you report the error, HARD, as
in throw an error and abort, then I can't even create that threaded
rod.
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But
when you think about it, it is not as clear cut as you might think.
Roger.
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110
**
** Delftechpark 11 2628 XJ Delft, The Netherlands. KVK: 27239233
**
The plan was simple, like my brother-in-law Phil. But unlike
Phil, this plan just might work.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Or better this:
list = [];
x = list[0]; // x = undef(list index out of bounds at line 2)
if(x)
sphere(x); // Not executed
else
cube(x); // Error cube size parameter is undef(list index out of bounds
at line 2) at line 6
On Wed, 29 Jul 2020 at 09:00, nop head <nop.head@gmail.com> wrote:
> Yes making warmings optional doesn't really solve the backward
> compatibility option. A library maintainer would want to turn it on to make
> the library easy to use but would then have to fix all the intended uses of
> functions returning undef by adding extra code.
>
> Perhaps it should only be an error to use undef in operations that need a
> concrete value, i.e. nearly everywhere, except in a boolean context, where
> it is simply false. If the undef value carries information of what
> generated it that could be part of the warning when it was used.
>
> So something like this.
> list = [];
> x = list[0]; // x = undef(list index out of bounds)
> if(x)
> sphere(x); // Not executed
> else
> cube(x); // Error cube size parameter is undefined (list index out of
> bounds at line 2)
>
>
>
> On Wed, 29 Jul 2020 at 08:11, Rogier Wolff <R.E.Wolff@bitwizard.nl> wrote:
>
>> On Tue, Jul 28, 2020 at 08:04:54PM +0000, Jordan Brown wrote:
>> 's detected, the harder it will be to find the bug.
>> >
>> > Failing "soft" - returning undef, in OpenSCAD - may feel like a happy
>>
>> Some "failures" are not failures, and need to be handled by higher
>> layers. The classical example is of a program going to write a file.
>> To prevent accidentally overwriting the file, the program will attempt
>> to open the file, get an error: "Can't open file", and then proceed to
>> write the file.
>>
>> Sure you can find other ways to do this specific thing, but this is an
>> example where what the "open" function thought was an error, was
>> precisely the opposite to the program making the call.
>>
>> Moving to the context of openscad: Suppose I have a module to make a
>> screw that takes the "head" as an argument. You could make such a
>> module to take a number to define what head to use out of a list of
>> possible heads, but lets say I've structured this differently and I
>> want to pass the object. (Not sure how to do that in openscad, but
>> lets assume I can.... Oh! I can do it with a "children" construct!)
>>
>> Now what if instead of a screw I want to make a threaded rod? No head!
>> In this case, the module might try to access the empty list of "heads
>> to put on", but that's not an error. If you report the error, HARD, as
>> in throw an error and abort, then I can't even create that threaded
>> rod.
>>
>> So... when talking abstractly: "You should throw errors as close as
>> possible to the line causing the problem." I'm all for it.... But
>> when you think about it, it is not as clear cut as you might think.
>>
>>
>> Roger.
>>
>> --
>> ** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110
>> **
>> ** Delftechpark 11 2628 XJ Delft, The Netherlands. KVK: 27239233
>> **
>> The plan was simple, like my brother-in-law Phil. But unlike
>> Phil, this plan just might work.
>>
>> _______________________________________________
>> OpenSCAD mailing list
>> Discuss@lists.openscad.org
>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>>
>
A
adrianv
Wed, Jul 29, 2020 12:40 PM
Some "failures" are not failures, and need to be handled by higher
layers. The classical example is of a program going to write a file.
To prevent accidentally overwriting the file, the program will attempt
to open the file, get an error: "Can't open file", and then proceed to
write the file.
Sure you can find other ways to do this specific thing, but this is an
example where what the "open" function thought was an error, was
precisely the opposite to the program making the call.
....
Now what if instead of a screw I want to make a threaded rod? No head!
In this case, the module might try to access the empty list of "heads
to put on", but that's not an error. If you report the error, HARD, as
in throw an error and abort, then I can't even create that threaded
rod.
...
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But
when you think about it, it is not as clear cut as you might think.
I don't think you can find other ways to test for file existence that aren't
equivalent to trying to open the file. You can divide errors into two
kinds: preventable and not preventable. You have no way of knowing that the
file open operation will fail except that you try it. In OpenSCAD you don't
know that two lines are parallel until the line intersection routine runs,
so it wouldn't make sense to write a line intersection routine that issued a
fatal error on parallel lines, because the line intersection function also
needs to serve as the test for parallel lines.
But if you calculate list[ind] you can guard against errors by not passing
it an invalid index, which is a simple matter since the valid indices are
integers with ind>=0 and ind<len(list). If you calculate
a+b
in some context you can and should validate that a and b are legitimate
values before doing the calculation, which will guarantee validity of a+b.
It's an unlikely context where the validity of a+b is sufficient alone.
Some further testing is necessary to assure that the computation makes sense
in the larger context, which will ensure that a and b are compatible for
addition.
For the example of threaded rod and lists of heads, you check the length of
the list before indexing into it. Your example is a little weird since
screws don't have multiple heads, but if someone passes you a list to
operate on your code is going to look like:
for(entry=list){...} or for(i=[0:1:len(list)-1]){...}
and if the list had no entries, nothing would happen. If you're passing
geometry you check $children before invoking a given child.
I think it's pretty clear cut. If the error is preventable then it is
reasonable to throw the error as soon as it occurs. If the programmer
doesn't want an error then a test can be used to prevent the error. Only in
the case where the error is not preventable does it make sense to do
something different. Indexing out of bounds is preventable. Are there any
OpenSCAD operations that generate undef where performing the operation is
the only way to validate it? If there are they probably should return undef
rather than producing an immediate error. But then if you try to do
operations on that undef you should get an immediate error.
--
Sent from: http://forum.openscad.org/
rew wrote
> Some "failures" are not failures, and need to be handled by higher
> layers. The classical example is of a program going to write a file.
> To prevent accidentally overwriting the file, the program will attempt
> to open the file, get an error: "Can't open file", and then proceed to
> write the file.
>
> Sure you can find other ways to do this specific thing, but this is an
> example where what the "open" function thought was an error, was
> precisely the opposite to the program making the call.
>
> ....
>
> Now what if instead of a screw I want to make a threaded rod? No head!
> In this case, the module might try to access the empty list of "heads
> to put on", but that's not an error. If you report the error, HARD, as
> in throw an error and abort, then I can't even create that threaded
> rod.
>
> ...
>
> So... when talking abstractly: "You should throw errors as close as
> possible to the line causing the problem." I'm all for it.... But
> when you think about it, it is not as clear cut as you might think.
I don't think you can find other ways to test for file existence that aren't
equivalent to trying to open the file. You can divide errors into two
kinds: preventable and not preventable. You have no way of knowing that the
file open operation will fail except that you try it. In OpenSCAD you don't
know that two lines are parallel until the line intersection routine runs,
so it wouldn't make sense to write a line intersection routine that issued a
fatal error on parallel lines, because the line intersection function also
needs to serve as the test for parallel lines.
But if you calculate list[ind] you can guard against errors by not passing
it an invalid index, which is a simple matter since the valid indices are
integers with ind>=0 and ind<len(list). If you calculate
a+b
in some context you can and should validate that a and b are legitimate
values before doing the calculation, which will guarantee validity of a+b.
It's an unlikely context where the validity of a+b is sufficient alone.
Some further testing is necessary to assure that the computation makes sense
in the larger context, which will ensure that a and b are compatible for
addition.
For the example of threaded rod and lists of heads, you check the length of
the list before indexing into it. Your example is a little weird since
screws don't have multiple heads, but if someone passes you a list to
operate on your code is going to look like:
for(entry=list){...} or for(i=[0:1:len(list)-1]){...}
and if the list had no entries, nothing would happen. If you're passing
geometry you check $children before invoking a given child.
I think it's pretty clear cut. If the error is preventable then it is
reasonable to throw the error as soon as it occurs. If the programmer
doesn't want an error then a test can be used to prevent the error. Only in
the case where the error is not preventable does it make sense to do
something different. Indexing out of bounds is preventable. Are there any
OpenSCAD operations that generate undef where performing the operation is
the only way to validate it? If there are they probably should return undef
rather than producing an immediate error. But then if you try to do
operations on that undef you should get an immediate error.
--
Sent from: http://forum.openscad.org/
JB
Jordan Brown
Wed, Jul 29, 2020 6:08 PM
[ Please forgive my tendency to write a lot about this. It's actually a
primary interest in my professional life - how to write programs to make
it difficult to have bugs, how to detect the bugs you can't prevent, and
how to design languages, libraries, and other infrastructure so as to
prevent and detect bugs. A related topic is "how to report errors so
that the error reports are useful". ]
On 7/29/2020 12:10 AM, Rogier Wolff wrote:
Some "failures" are not failures, [...]
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But when
you think about it, it is not as clear cut as you might think.
Yes. Distinguishing a likely bug from an "expected" error is important.
Nop head's "when you need a concrete answer" test is certainly a good
start. But I don't think it's quite enough. The next question is "what
is a likely bug, and what is merely missing data?".
A missing parameter (in OpenSCAD, where missing parameters are expected)
is clearly not an error. (But maybe OpenSCAD should have a syntax that
says "this parameter is required".)
An attempt to divide by zero is clearly an error. In the unlikely event
that you really want something infinity-like as the result, require the
programmer to explicitly check first. (atan2() comes to mind.)
I think it's clear that if a function requires a particular parameter,
then not supplying it is an error. (But not everybody agrees. In C, I
often see people checking required parameters for NULL and returning an
error if they're NULL. No! The parameter is required; if the caller
supplied a NULL then the caller unquestionably has a bug!)
But an array index that's out of bounds? Hard to say. You might say
it's a bug, or you might say that returning undef allows the program to
probe for the dimensions of the array. I would come down on the side of
calling it an error. If you want to probe for the dimensions of the
array, you can use len() and then the intent is obvious. That's a key
thing: having the program convey the programmer's intent. If you have
out-of-bounds references simply return undef, neither the interpreter
nor a reviewer can tell what the intent is, and so you can't detect the
bug. If, on the other hand, you consider it an error, then you have two
distinct idioms: if your intent is to retrieve a value (and you don't
expect your index to be out of bounds) then you do a simple reference;
if your intent is to check for the presence of the value then you use
len(). Yes, if "undef" was a reasonable default value you have to go a
bit out of your way and say i < len(x) ? x[i] : undef, but that doesn't
seem like an onerous price to pay for protecting all of the other cases.
Mixed-type expressions are particularly tricky. There are reasonable
definitions for many combinations. I'd draw the line at the point where
you have to "stretch" to say that the definition is reasonable. String
concatenation through '+' is reasonable. String replication through
multiplication seems reasonable. Saying that boolean*string is
equivalent to (boolean ? string : "") seems past the limit. Automatic
to-string when you mix a string and something else with "+"... I'm not
sure. It's reasonably obvious and awfully convenient, but is implicated
in any number of cases of "null" appearing in user interfaces.
Hans's "undef with a reason" does help a lot. I'm not sure it's
enough. Because undef is considered false for "if" purposes (a
definition that seems unlikely to change) an undef that came from a bug
can lead to silently going down an execution path that doesn't happen to
ever use the value in a "concrete" way.
[ Please forgive my tendency to write a lot about this. It's actually a
primary interest in my professional life - how to write programs to make
it difficult to have bugs, how to detect the bugs you can't prevent, and
how to design languages, libraries, and other infrastructure so as to
prevent and detect bugs. A related topic is "how to report errors so
that the error reports are useful". ]
On 7/29/2020 12:10 AM, Rogier Wolff wrote:
> Some "failures" are not failures, [...]
>
> So... when talking abstractly: "You should throw errors as close as
> possible to the line causing the problem." I'm all for it.... But when
> you think about it, it is not as clear cut as you might think.
>
Yes. Distinguishing a likely bug from an "expected" error is important.
Nop head's "when you need a concrete answer" test is certainly a good
start. But I don't think it's quite enough. The next question is "what
is a likely bug, and what is merely missing data?".
A missing parameter (in OpenSCAD, where missing parameters are expected)
is clearly not an error. (But maybe OpenSCAD should have a syntax that
says "this parameter is required".)
An attempt to divide by zero is clearly an error. In the unlikely event
that you really want something infinity-like as the result, require the
programmer to explicitly check first. (atan2() comes to mind.)
I think it's clear that if a function requires a particular parameter,
then not supplying it is an error. (But not everybody agrees. In C, I
often see people checking required parameters for NULL and returning an
error if they're NULL. No! The parameter is required; if the caller
supplied a NULL then the caller unquestionably has a bug!)
But an array index that's out of bounds? Hard to say. You might say
it's a bug, or you might say that returning undef allows the program to
probe for the dimensions of the array. I would come down on the side of
calling it an error. If you *want* to probe for the dimensions of the
array, you can use len() and then the intent is obvious. That's a key
thing: having the program convey the programmer's intent. If you have
out-of-bounds references simply return undef, neither the interpreter
nor a reviewer can tell what the intent is, and so you can't detect the
bug. If, on the other hand, you consider it an error, then you have two
distinct idioms: if your intent is to retrieve a value (and you don't
expect your index to be out of bounds) then you do a simple reference;
if your intent is to check for the presence of the value then you use
len(). Yes, if "undef" was a reasonable default value you have to go a
bit out of your way and say i < len(x) ? x[i] : undef, but that doesn't
seem like an onerous price to pay for protecting all of the *other* cases.
Mixed-type expressions are particularly tricky. There are reasonable
definitions for many combinations. I'd draw the line at the point where
you have to "stretch" to say that the definition is reasonable. String
concatenation through '+' is reasonable. String replication through
multiplication seems reasonable. Saying that boolean*string is
equivalent to (boolean ? string : "") seems past the limit. Automatic
to-string when you mix a string and something else with "+"... I'm not
sure. It's reasonably obvious and awfully convenient, but is implicated
in any number of cases of "null" appearing in user interfaces.
Hans's "undef with a reason" does help a lot. I'm not sure it's
enough. Because undef is considered false for "if" purposes (a
definition that seems unlikely to change) an undef that came from a bug
can lead to silently going down an execution path that doesn't happen to
ever use the value in a "concrete" way.
NH
nop head
Wed, Jul 29, 2020 6:56 PM
The issue is that OpenSCAD has been used for many years and has always
returned undef for an out of bounds index so I use it as a shortcut.
Instead of if(len(type) > 3 && type[3]) is just if(type[3]), which is a lot
less ugly. It saves adding empty values to the end of my object descriptors
and makes the lack of an entry the same as an empty entry, which makes
semantic sense to me. And len should go back to silently returning undef
when applied to a scalar. Otherwise it becomes if(is_list(type) &&
len(type) > 3 && type[3]), which is even more ugly. In practice the list
element is wrapped in an accessor function, so the intent becomes obvious.
E.g.
conn = camera_connector_size(type);
if(conn) {
use conn to draw the connector
}
I doubt there are many cases where people do if(list[n]) where it is a
mistake, using list[n] to compute something or compare it to anything
other than undef is definitely an error if the list isn't that long and my
proposal would catch all other errors due to bad indexing.
If an undef value goes down an execution path that doesn't use it then it
isn't a bug as far as I am concerned. undef exists as a value, can be
assigned to variables and passed as parameters and silently tested as false
with if, so I don't think that should change. But if it always stores how
it became undef then debugging is easy because if you ever use it in an
expression you will get a warning showing where it became undef and where
it was finally used. Exactly what you need to debug.
Whether operators get overloaded to work on strings in the future doesn't
matter. At the moment they don't so you get undef.
On Wed, 29 Jul 2020 at 19:09, Jordan Brown openscad@jordan.maileater.net
wrote:
[ Please forgive my tendency to write a lot about this. It's actually a
primary interest in my professional life - how to write programs to make it
difficult to have bugs, how to detect the bugs you can't prevent, and how
to design languages, libraries, and other infrastructure so as to prevent
and detect bugs. A related topic is "how to report errors so that the error
reports are useful". ]
On 7/29/2020 12:10 AM, Rogier Wolff wrote:
Some "failures" are not failures, [...]
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But when you
think about it, it is not as clear cut as you might think.
Yes. Distinguishing a likely bug from an "expected" error is important.
Nop head's "when you need a concrete answer" test is certainly a good
start. But I don't think it's quite enough. The next question is "what is
a likely bug, and what is merely missing data?".
A missing parameter (in OpenSCAD, where missing parameters are expected)
is clearly not an error. (But maybe OpenSCAD should have a syntax that
says "this parameter is required".)
An attempt to divide by zero is clearly an error. In the unlikely event
that you really want something infinity-like as the result, require the
programmer to explicitly check first. (atan2() comes to mind.)
I think it's clear that if a function requires a particular parameter,
then not supplying it is an error. (But not everybody agrees. In C, I
often see people checking required parameters for NULL and returning an
error if they're NULL. No! The parameter is required; if the caller
supplied a NULL then the caller unquestionably has a bug!)
But an array index that's out of bounds? Hard to say. You might say it's
a bug, or you might say that returning undef allows the program to probe
for the dimensions of the array. I would come down on the side of calling
it an error. If you want to probe for the dimensions of the array, you
can use len() and then the intent is obvious. That's a key thing:
having the program convey the programmer's intent. If you have
out-of-bounds references simply return undef, neither the interpreter nor a
reviewer can tell what the intent is, and so you can't detect the bug. If,
on the other hand, you consider it an error, then you have two distinct
idioms: if your intent is to retrieve a value (and you don't expect your
index to be out of bounds) then you do a simple reference; if your intent
is to check for the presence of the value then you use len(). Yes, if
"undef" was a reasonable default value you have to go a bit out of your way
and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
price to pay for protecting all of the other cases.
Mixed-type expressions are particularly tricky. There are reasonable
definitions for many combinations. I'd draw the line at the point where
you have to "stretch" to say that the definition is reasonable. String
concatenation through '+' is reasonable. String replication through
multiplication seems reasonable. Saying that boolean*string is equivalent
to (boolean ? string : "") seems past the limit. Automatic to-string
when you mix a string and something else with "+"... I'm not sure. It's
reasonably obvious and awfully convenient, but is implicated in any number
of cases of "null" appearing in user interfaces.
Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
Because undef is considered false for "if" purposes (a definition that
seems unlikely to change) an undef that came from a bug can lead to
silently going down an execution path that doesn't happen to ever use the
value in a "concrete" way.
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
The issue is that OpenSCAD has been used for many years and has always
returned undef for an out of bounds index so I use it as a shortcut.
Instead of if(len(type) > 3 && type[3]) is just if(type[3]), which is a lot
less ugly. It saves adding empty values to the end of my object descriptors
and makes the lack of an entry the same as an empty entry, which makes
semantic sense to me. And len should go back to silently returning undef
when applied to a scalar. Otherwise it becomes if(is_list(type) &&
len(type) > 3 && type[3]), which is even more ugly. In practice the list
element is wrapped in an accessor function, so the intent becomes obvious.
E.g.
conn = camera_connector_size(type);
if(conn) {
use conn to draw the connector
}
I doubt there are many cases where people do if(list[n]) where it is a
mistake, using list[n] to compute something or compare it to anything
other than undef is definitely an error if the list isn't that long and my
proposal would catch all other errors due to bad indexing.
If an undef value goes down an execution path that doesn't use it then it
isn't a bug as far as I am concerned. undef exists as a value, can be
assigned to variables and passed as parameters and silently tested as false
with if, so I don't think that should change. But if it always stores how
it became undef then debugging is easy because if you ever use it in an
expression you will get a warning showing where it became undef and where
it was finally used. Exactly what you need to debug.
Whether operators get overloaded to work on strings in the future doesn't
matter. At the moment they don't so you get undef.
On Wed, 29 Jul 2020 at 19:09, Jordan Brown <openscad@jordan.maileater.net>
wrote:
> [ Please forgive my tendency to write a lot about this. It's actually a
> primary interest in my professional life - how to write programs to make it
> difficult to have bugs, how to detect the bugs you can't prevent, and how
> to design languages, libraries, and other infrastructure so as to prevent
> and detect bugs. A related topic is "how to report errors so that the error
> reports are useful". ]
>
> On 7/29/2020 12:10 AM, Rogier Wolff wrote:
>
> Some "failures" are not failures, [...]
>
> So... when talking abstractly: "You should throw errors as close as
> possible to the line causing the problem." I'm all for it.... But when you
> think about it, it is not as clear cut as you might think.
>
>
> Yes. Distinguishing a likely bug from an "expected" error is important.
>
> Nop head's "when you need a concrete answer" test is certainly a good
> start. But I don't think it's quite enough. The next question is "what is
> a likely bug, and what is merely missing data?".
>
> A missing parameter (in OpenSCAD, where missing parameters are expected)
> is clearly not an error. (But maybe OpenSCAD should have a syntax that
> says "this parameter is required".)
>
> An attempt to divide by zero is clearly an error. In the unlikely event
> that you really want something infinity-like as the result, require the
> programmer to explicitly check first. (atan2() comes to mind.)
>
> I think it's clear that if a function requires a particular parameter,
> then not supplying it is an error. (But not everybody agrees. In C, I
> often see people checking required parameters for NULL and returning an
> error if they're NULL. No! The parameter is required; if the caller
> supplied a NULL then the caller unquestionably has a bug!)
>
> But an array index that's out of bounds? Hard to say. You might say it's
> a bug, or you might say that returning undef allows the program to probe
> for the dimensions of the array. I would come down on the side of calling
> it an error. If you *want* to probe for the dimensions of the array, you
> can use len() and then the intent is obvious. That's a key thing:
> having the program convey the programmer's intent. If you have
> out-of-bounds references simply return undef, neither the interpreter nor a
> reviewer can tell what the intent is, and so you can't detect the bug. If,
> on the other hand, you consider it an error, then you have two distinct
> idioms: if your intent is to retrieve a value (and you don't expect your
> index to be out of bounds) then you do a simple reference; if your intent
> is to check for the presence of the value then you use len(). Yes, if
> "undef" was a reasonable default value you have to go a bit out of your way
> and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
> price to pay for protecting all of the *other* cases.
>
> Mixed-type expressions are particularly tricky. There are reasonable
> definitions for many combinations. I'd draw the line at the point where
> you have to "stretch" to say that the definition is reasonable. String
> concatenation through '+' is reasonable. String replication through
> multiplication seems reasonable. Saying that boolean*string is equivalent
> to (boolean ? string : "") seems past the limit. Automatic to-string
> when you mix a string and something else with "+"... I'm not sure. It's
> reasonably obvious and awfully convenient, but is implicated in any number
> of cases of "null" appearing in user interfaces.
>
> Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
> Because undef is considered false for "if" purposes (a definition that
> seems unlikely to change) an undef that came from a bug can lead to
> silently going down an execution path that doesn't happen to ever use the
> value in a "concrete" way.
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
A
adrianv
Wed, Jul 29, 2020 8:54 PM
There's no reason this is true. What if I have a parameter, x, and I want to
based a decision on the value of x, but in some complex way, so I write
f(x) ? g(x) : h(x)
but unfortunately, the function f has a bug and sometimes produces undef
when it should produce true. My code now silently executes h(x) when it
should instead run g(x) and there's no sign of the mistake. Maybe this
later leads to a failure of some kind? But it's not direct. The idea that
bugs can only occur if the expression is used outside a boolean context is
incorrect.
A simpler and less complex case would be a decision parameter mistakenly
ends up somehow as undef and hence gets interpreted as false. The program
doesn't produce bad output, but it produces the wrong output, which is a
bug. This might happen if the programmer mistyped a variable name, for
example.
if (add_dooodad) { make_doodad(..)}
This is always false since add_dooodad was spelled wrong so it is undef, and
so the doodad is never created, and the programmer is absolutely baffled
because the code looks correct, and add_doodad is definitely set to true.
nophead wrote
If an undef value goes down an execution path that doesn't use it then it
isn't a bug as far as I am concerned. undef exists as a value, can be
assigned to variables and passed as parameters and silently tested as
false
with if, so I don't think that should change. But if it always stores how
it became undef then debugging is easy because if you ever use it in an
expression you will get a warning showing where it became undef and where
it was finally used. Exactly what you need to debug.
Whether operators get overloaded to work on strings in the future doesn't
matter. At the moment they don't so you get undef.
On Wed, 29 Jul 2020 at 19:09, Jordan Brown <
[ Please forgive my tendency to write a lot about this. It's actually a
primary interest in my professional life - how to write programs to make
it
difficult to have bugs, how to detect the bugs you can't prevent, and how
to design languages, libraries, and other infrastructure so as to prevent
and detect bugs. A related topic is "how to report errors so that the
error
reports are useful". ]
On 7/29/2020 12:10 AM, Rogier Wolff wrote:
Some "failures" are not failures, [...]
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But when
you
think about it, it is not as clear cut as you might think.
Yes. Distinguishing a likely bug from an "expected" error is important.
Nop head's "when you need a concrete answer" test is certainly a good
start. But I don't think it's quite enough. The next question is "what
is
a likely bug, and what is merely missing data?".
A missing parameter (in OpenSCAD, where missing parameters are expected)
is clearly not an error. (But maybe OpenSCAD should have a syntax that
says "this parameter is required".)
An attempt to divide by zero is clearly an error. In the unlikely event
that you really want something infinity-like as the result, require the
programmer to explicitly check first. (atan2() comes to mind.)
I think it's clear that if a function requires a particular parameter,
then not supplying it is an error. (But not everybody agrees. In C, I
often see people checking required parameters for NULL and returning an
error if they're NULL. No! The parameter is required; if the caller
supplied a NULL then the caller unquestionably has a bug!)
But an array index that's out of bounds? Hard to say. You might say
it's
a bug, or you might say that returning undef allows the program to probe
for the dimensions of the array. I would come down on the side of
calling
it an error. If you want to probe for the dimensions of the array, you
can use len() and then the intent is obvious. That's a key thing:
having the program convey the programmer's intent. If you have
out-of-bounds references simply return undef, neither the interpreter nor
a
reviewer can tell what the intent is, and so you can't detect the bug.
If,
on the other hand, you consider it an error, then you have two distinct
idioms: if your intent is to retrieve a value (and you don't expect your
index to be out of bounds) then you do a simple reference; if your intent
is to check for the presence of the value then you use len(). Yes, if
"undef" was a reasonable default value you have to go a bit out of your
way
and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
price to pay for protecting all of the other cases.
Mixed-type expressions are particularly tricky. There are reasonable
definitions for many combinations. I'd draw the line at the point where
you have to "stretch" to say that the definition is reasonable. String
concatenation through '+' is reasonable. String replication through
multiplication seems reasonable. Saying that boolean*string is
equivalent
to (boolean ? string : "") seems past the limit. Automatic to-string
when you mix a string and something else with "+"... I'm not sure. It's
reasonably obvious and awfully convenient, but is implicated in any
number
of cases of "null" appearing in user interfaces.
Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
Because undef is considered false for "if" purposes (a definition that
seems unlikely to change) an undef that came from a bug can lead to
silently going down an execution path that doesn't happen to ever use the
value in a "concrete" way.
OpenSCAD mailing list
There's no reason this is true. What if I have a parameter, x, and I want to
based a decision on the value of x, but in some complex way, so I write
f(x) ? g(x) : h(x)
but unfortunately, the function f has a bug and sometimes produces undef
when it should produce true. My code now silently executes h(x) when it
should instead run g(x) and there's no sign of the mistake. Maybe this
later leads to a failure of some kind? But it's not direct. The idea that
bugs can only occur if the expression is used outside a boolean context is
incorrect.
A simpler and less complex case would be a decision parameter mistakenly
ends up somehow as undef and hence gets interpreted as false. The program
doesn't produce bad output, but it produces the wrong output, which is a
bug. This might happen if the programmer mistyped a variable name, for
example.
if (add_dooodad) { make_doodad(..)}
This is always false since add_dooodad was spelled wrong so it is undef, and
so the doodad is never created, and the programmer is absolutely baffled
because the code looks correct, and add_doodad is definitely set to true.
nophead wrote
> If an undef value goes down an execution path that doesn't use it then it
> isn't a bug as far as I am concerned. undef exists as a value, can be
> assigned to variables and passed as parameters and silently tested as
> false
> with if, so I don't think that should change. But if it always stores how
> it became undef then debugging is easy because if you ever use it in an
> expression you will get a warning showing where it became undef and where
> it was finally used. Exactly what you need to debug.
>
> Whether operators get overloaded to work on strings in the future doesn't
> matter. At the moment they don't so you get undef.
>
>
> On Wed, 29 Jul 2020 at 19:09, Jordan Brown <
> openscad@.maileater
> >
> wrote:
>
>> [ Please forgive my tendency to write a lot about this. It's actually a
>> primary interest in my professional life - how to write programs to make
>> it
>> difficult to have bugs, how to detect the bugs you can't prevent, and how
>> to design languages, libraries, and other infrastructure so as to prevent
>> and detect bugs. A related topic is "how to report errors so that the
>> error
>> reports are useful". ]
>>
>> On 7/29/2020 12:10 AM, Rogier Wolff wrote:
>>
>> Some "failures" are not failures, [...]
>>
>> So... when talking abstractly: "You should throw errors as close as
>> possible to the line causing the problem." I'm all for it.... But when
>> you
>> think about it, it is not as clear cut as you might think.
>>
>>
>> Yes. Distinguishing a likely bug from an "expected" error is important.
>>
>> Nop head's "when you need a concrete answer" test is certainly a good
>> start. But I don't think it's quite enough. The next question is "what
>> is
>> a likely bug, and what is merely missing data?".
>>
>> A missing parameter (in OpenSCAD, where missing parameters are expected)
>> is clearly not an error. (But maybe OpenSCAD should have a syntax that
>> says "this parameter is required".)
>>
>> An attempt to divide by zero is clearly an error. In the unlikely event
>> that you really want something infinity-like as the result, require the
>> programmer to explicitly check first. (atan2() comes to mind.)
>>
>> I think it's clear that if a function requires a particular parameter,
>> then not supplying it is an error. (But not everybody agrees. In C, I
>> often see people checking required parameters for NULL and returning an
>> error if they're NULL. No! The parameter is required; if the caller
>> supplied a NULL then the caller unquestionably has a bug!)
>>
>> But an array index that's out of bounds? Hard to say. You might say
>> it's
>> a bug, or you might say that returning undef allows the program to probe
>> for the dimensions of the array. I would come down on the side of
>> calling
>> it an error. If you *want* to probe for the dimensions of the array, you
>> can use len() and then the intent is obvious. That's a key thing:
>> having the program convey the programmer's intent. If you have
>> out-of-bounds references simply return undef, neither the interpreter nor
>> a
>> reviewer can tell what the intent is, and so you can't detect the bug.
>> If,
>> on the other hand, you consider it an error, then you have two distinct
>> idioms: if your intent is to retrieve a value (and you don't expect your
>> index to be out of bounds) then you do a simple reference; if your intent
>> is to check for the presence of the value then you use len(). Yes, if
>> "undef" was a reasonable default value you have to go a bit out of your
>> way
>> and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
>> price to pay for protecting all of the *other* cases.
>>
>> Mixed-type expressions are particularly tricky. There are reasonable
>> definitions for many combinations. I'd draw the line at the point where
>> you have to "stretch" to say that the definition is reasonable. String
>> concatenation through '+' is reasonable. String replication through
>> multiplication seems reasonable. Saying that boolean*string is
>> equivalent
>> to (boolean ? string : "") seems past the limit. Automatic to-string
>> when you mix a string and something else with "+"... I'm not sure. It's
>> reasonably obvious and awfully convenient, but is implicated in any
>> number
>> of cases of "null" appearing in user interfaces.
>>
>> Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
>> Because undef is considered false for "if" purposes (a definition that
>> seems unlikely to change) an undef that came from a bug can lead to
>> silently going down an execution path that doesn't happen to ever use the
>> value in a "concrete" way.
>>
>> _______________________________________________
>> OpenSCAD mailing list
>>
> Discuss@.openscad
>> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>>
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@.openscad
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
--
Sent from: http://forum.openscad.org/
NH
nop head
Wed, Jul 29, 2020 9:10 PM
Well then it is a trade off between people that like to write succinct code
versus those that write bugs.
The point is OpenSCAD has this feature, so in order to maintain backwards
compatibility it should keep it. Does it make sense I have to add more and
more code to make OpenSCAD do what it used to do without complaining?
if (add_dooodad) { make_doodad(..)} already creates a warning because you
have used a variable that does not exist, different from using an
expression that yields undef.
On Wed, 29 Jul 2020 at 21:55, adrianv avm4@cornell.edu wrote:
There's no reason this is true. What if I have a parameter, x, and I want
to
based a decision on the value of x, but in some complex way, so I write
f(x) ? g(x) : h(x)
but unfortunately, the function f has a bug and sometimes produces undef
when it should produce true. My code now silently executes h(x) when it
should instead run g(x) and there's no sign of the mistake. Maybe this
later leads to a failure of some kind? But it's not direct. The idea that
bugs can only occur if the expression is used outside a boolean context is
incorrect.
A simpler and less complex case would be a decision parameter mistakenly
ends up somehow as undef and hence gets interpreted as false. The program
doesn't produce bad output, but it produces the wrong output, which is a
bug. This might happen if the programmer mistyped a variable name, for
example.
if (add_dooodad) { make_doodad(..)}
This is always false since add_dooodad was spelled wrong so it is undef,
and
so the doodad is never created, and the programmer is absolutely baffled
because the code looks correct, and add_doodad is definitely set to true.
nophead wrote
If an undef value goes down an execution path that doesn't use it then it
isn't a bug as far as I am concerned. undef exists as a value, can be
assigned to variables and passed as parameters and silently tested as
false
with if, so I don't think that should change. But if it always stores how
it became undef then debugging is easy because if you ever use it in an
expression you will get a warning showing where it became undef and where
it was finally used. Exactly what you need to debug.
Whether operators get overloaded to work on strings in the future doesn't
matter. At the moment they don't so you get undef.
On Wed, 29 Jul 2020 at 19:09, Jordan Brown <
[ Please forgive my tendency to write a lot about this. It's actually a
primary interest in my professional life - how to write programs to make
it
difficult to have bugs, how to detect the bugs you can't prevent, and
to design languages, libraries, and other infrastructure so as to
and detect bugs. A related topic is "how to report errors so that the
error
reports are useful". ]
On 7/29/2020 12:10 AM, Rogier Wolff wrote:
Some "failures" are not failures, [...]
So... when talking abstractly: "You should throw errors as close as
possible to the line causing the problem." I'm all for it.... But when
you
think about it, it is not as clear cut as you might think.
Yes. Distinguishing a likely bug from an "expected" error is important.
Nop head's "when you need a concrete answer" test is certainly a good
start. But I don't think it's quite enough. The next question is "what
is
a likely bug, and what is merely missing data?".
A missing parameter (in OpenSCAD, where missing parameters are expected)
is clearly not an error. (But maybe OpenSCAD should have a syntax that
says "this parameter is required".)
An attempt to divide by zero is clearly an error. In the unlikely event
that you really want something infinity-like as the result, require the
programmer to explicitly check first. (atan2() comes to mind.)
I think it's clear that if a function requires a particular parameter,
then not supplying it is an error. (But not everybody agrees. In C, I
often see people checking required parameters for NULL and returning an
error if they're NULL. No! The parameter is required; if the caller
supplied a NULL then the caller unquestionably has a bug!)
But an array index that's out of bounds? Hard to say. You might say
it's
a bug, or you might say that returning undef allows the program to probe
for the dimensions of the array. I would come down on the side of
calling
it an error. If you want to probe for the dimensions of the array,
can use len() and then the intent is obvious. That's a key thing:
having the program convey the programmer's intent. If you have
out-of-bounds references simply return undef, neither the interpreter
a
reviewer can tell what the intent is, and so you can't detect the bug.
If,
on the other hand, you consider it an error, then you have two distinct
idioms: if your intent is to retrieve a value (and you don't expect
index to be out of bounds) then you do a simple reference; if your
is to check for the presence of the value then you use len(). Yes, if
"undef" was a reasonable default value you have to go a bit out of your
way
and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
price to pay for protecting all of the other cases.
Mixed-type expressions are particularly tricky. There are reasonable
definitions for many combinations. I'd draw the line at the point where
you have to "stretch" to say that the definition is reasonable. String
concatenation through '+' is reasonable. String replication through
multiplication seems reasonable. Saying that boolean*string is
equivalent
to (boolean ? string : "") seems past the limit. Automatic to-string
when you mix a string and something else with "+"... I'm not sure. It's
reasonably obvious and awfully convenient, but is implicated in any
number
of cases of "null" appearing in user interfaces.
Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
Because undef is considered false for "if" purposes (a definition that
seems unlikely to change) an undef that came from a bug can lead to
silently going down an execution path that doesn't happen to ever use
value in a "concrete" way.
OpenSCAD mailing list
Well then it is a trade off between people that like to write succinct code
versus those that write bugs.
The point is OpenSCAD has this feature, so in order to maintain backwards
compatibility it should keep it. Does it make sense I have to add more and
more code to make OpenSCAD do what it used to do without complaining?
if (add_dooodad) { make_doodad(..)} already creates a warning because you
have used a variable that does not exist, different from using an
expression that yields undef.
On Wed, 29 Jul 2020 at 21:55, adrianv <avm4@cornell.edu> wrote:
> There's no reason this is true. What if I have a parameter, x, and I want
> to
> based a decision on the value of x, but in some complex way, so I write
>
> f(x) ? g(x) : h(x)
>
> but unfortunately, the function f has a bug and sometimes produces undef
> when it should produce true. My code now silently executes h(x) when it
> should instead run g(x) and there's no sign of the mistake. Maybe this
> later leads to a failure of some kind? But it's not direct. The idea that
> bugs can only occur if the expression is used outside a boolean context is
> incorrect.
>
> A simpler and less complex case would be a decision parameter mistakenly
> ends up somehow as undef and hence gets interpreted as false. The program
> doesn't produce bad output, but it produces the wrong output, which is a
> bug. This might happen if the programmer mistyped a variable name, for
> example.
>
> if (add_dooodad) { make_doodad(..)}
>
> This is always false since add_dooodad was spelled wrong so it is undef,
> and
> so the doodad is never created, and the programmer is absolutely baffled
> because the code looks correct, and add_doodad is definitely set to true.
>
>
> nophead wrote
> > If an undef value goes down an execution path that doesn't use it then it
> > isn't a bug as far as I am concerned. undef exists as a value, can be
> > assigned to variables and passed as parameters and silently tested as
> > false
> > with if, so I don't think that should change. But if it always stores how
> > it became undef then debugging is easy because if you ever use it in an
> > expression you will get a warning showing where it became undef and where
> > it was finally used. Exactly what you need to debug.
> >
> > Whether operators get overloaded to work on strings in the future doesn't
> > matter. At the moment they don't so you get undef.
> >
> >
> > On Wed, 29 Jul 2020 at 19:09, Jordan Brown <
>
> > openscad@.maileater
>
> > >
> > wrote:
> >
> >> [ Please forgive my tendency to write a lot about this. It's actually a
> >> primary interest in my professional life - how to write programs to make
> >> it
> >> difficult to have bugs, how to detect the bugs you can't prevent, and
> how
> >> to design languages, libraries, and other infrastructure so as to
> prevent
> >> and detect bugs. A related topic is "how to report errors so that the
> >> error
> >> reports are useful". ]
> >>
> >> On 7/29/2020 12:10 AM, Rogier Wolff wrote:
> >>
> >> Some "failures" are not failures, [...]
> >>
> >> So... when talking abstractly: "You should throw errors as close as
> >> possible to the line causing the problem." I'm all for it.... But when
> >> you
> >> think about it, it is not as clear cut as you might think.
> >>
> >>
> >> Yes. Distinguishing a likely bug from an "expected" error is important.
> >>
> >> Nop head's "when you need a concrete answer" test is certainly a good
> >> start. But I don't think it's quite enough. The next question is "what
> >> is
> >> a likely bug, and what is merely missing data?".
> >>
> >> A missing parameter (in OpenSCAD, where missing parameters are expected)
> >> is clearly not an error. (But maybe OpenSCAD should have a syntax that
> >> says "this parameter is required".)
> >>
> >> An attempt to divide by zero is clearly an error. In the unlikely event
> >> that you really want something infinity-like as the result, require the
> >> programmer to explicitly check first. (atan2() comes to mind.)
> >>
> >> I think it's clear that if a function requires a particular parameter,
> >> then not supplying it is an error. (But not everybody agrees. In C, I
> >> often see people checking required parameters for NULL and returning an
> >> error if they're NULL. No! The parameter is required; if the caller
> >> supplied a NULL then the caller unquestionably has a bug!)
> >>
> >> But an array index that's out of bounds? Hard to say. You might say
> >> it's
> >> a bug, or you might say that returning undef allows the program to probe
> >> for the dimensions of the array. I would come down on the side of
> >> calling
> >> it an error. If you *want* to probe for the dimensions of the array,
> you
> >> can use len() and then the intent is obvious. That's a key thing:
> >> having the program convey the programmer's intent. If you have
> >> out-of-bounds references simply return undef, neither the interpreter
> nor
> >> a
> >> reviewer can tell what the intent is, and so you can't detect the bug.
> >> If,
> >> on the other hand, you consider it an error, then you have two distinct
> >> idioms: if your intent is to retrieve a value (and you don't expect
> your
> >> index to be out of bounds) then you do a simple reference; if your
> intent
> >> is to check for the presence of the value then you use len(). Yes, if
> >> "undef" was a reasonable default value you have to go a bit out of your
> >> way
> >> and say i < len(x) ? x[i] : undef, but that doesn't seem like an onerous
> >> price to pay for protecting all of the *other* cases.
> >>
> >> Mixed-type expressions are particularly tricky. There are reasonable
> >> definitions for many combinations. I'd draw the line at the point where
> >> you have to "stretch" to say that the definition is reasonable. String
> >> concatenation through '+' is reasonable. String replication through
> >> multiplication seems reasonable. Saying that boolean*string is
> >> equivalent
> >> to (boolean ? string : "") seems past the limit. Automatic to-string
> >> when you mix a string and something else with "+"... I'm not sure. It's
> >> reasonably obvious and awfully convenient, but is implicated in any
> >> number
> >> of cases of "null" appearing in user interfaces.
> >>
> >> Hans's "undef with a reason" does help a lot. I'm not sure it's enough.
> >> Because undef is considered false for "if" purposes (a definition that
> >> seems unlikely to change) an undef that came from a bug can lead to
> >> silently going down an execution path that doesn't happen to ever use
> the
> >> value in a "concrete" way.
> >>
> >> _______________________________________________
> >> OpenSCAD mailing list
> >>
>
> > Discuss@.openscad
>
> >> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
> >>
> >
> > _______________________________________________
> > OpenSCAD mailing list
>
> > Discuss@.openscad
>
> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
>
>
>
> --
> Sent from: http://forum.openscad.org/
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
RP
Ronaldo Persiano
Wed, Jul 29, 2020 9:55 PM
Well then it is a trade off between people that like to write
succinct code versus those that write bugs.
Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
that succinct enough?
function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
...
if(in_bounds(arr)) ...
>
> Well then it is a trade off between people that like to write
> succinct code versus those that write bugs.
Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
that succinct enough?
function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
...
if(in_bounds(arr)) ...
NH
nop head
Wed, Jul 29, 2020 10:15 PM
No it's horrible. Instead of
function camera_connector_size(type)= type[6];
It would be
function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
Longer, slower, less readable.
On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano rcmpersiano@gmail.com
wrote:
Well then it is a trade off between people that like to write
succinct code versus those that write bugs.
No it's horrible. Instead of
function camera_connector_size(type)= type[6];
It would be
function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
Longer, slower, less readable.
On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano <rcmpersiano@gmail.com>
wrote:
> Well then it is a trade off between people that like to write
>> succinct code versus those that write bugs.
>
>
> Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
> that succinct enough?
>
> function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
> ...
> if(in_bounds(arr)) ...
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
A
adrianv
Wed, Jul 29, 2020 10:36 PM
Yeah, I'm with Ronaldo that I'd rather have a little bit more code than bugs.
function ind(list,i) = is_list(list) && i>=0 && i<len(i) && list[i]
? list[i] : 0;
function camera_connector_sizes(type) = ind(list,6);
This seems equally readable to me as list[6] and significantly less obscure.
Succinct is not always more readable or better when it means more cryptic or
obscure, and the form you prefer is definitely more obscure---someone
reading the code would have a harder time grasping the full implication, I
think.
The speed complaint is bogus. I already tested the speed consequences of
this and it saves less than a microsecond. Are you doing this a hundred
million times?
<quote author="nophead">
No it's horrible. Instead of
function camera_connector_size(type)= type[6];
It would be
function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
Longer, slower, less readable.
On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano <rcmpersiano@>
wrote:
Well then it is a trade off between people that like to write
succinct code versus those that write bugs.
Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
that succinct enough?
function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
Yeah, I'm with Ronaldo that I'd rather have a little bit more code than bugs.
function ind(list,i) = is_list(list) && i>=0 && i<len(i) && list[i]
? list[i] : 0;
function camera_connector_sizes(type) = ind(list,6);
This seems equally readable to me as list[6] and significantly less obscure.
Succinct is not always more readable or better when it means more cryptic or
obscure, and the form you prefer is definitely more obscure---someone
reading the code would have a harder time grasping the full implication, I
think.
The speed complaint is bogus. I already tested the speed consequences of
this and it saves less than a microsecond. Are you doing this a hundred
million times?
<quote author="nophead">
No it's horrible. Instead of
function camera_connector_size(type)= type[6];
It would be
function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
Longer, slower, less readable.
On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano <rcmpersiano@>
wrote:
> Well then it is a trade off between people that like to write
>> succinct code versus those that write bugs.
>
>
> Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
> that succinct enough?
>
> function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
> ...
> if(in_bounds(arr)) ...
> _______________________________________________
> OpenSCAD mailing list
> Discuss@.openscad
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
_______________________________________________
OpenSCAD mailing list
Discuss@.openscad
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
--
Sent from: http://forum.openscad.org/
NH
nop head
Thu, Jul 30, 2020 8:47 AM
Are you doing this a hundred million times?
Due to the bug in OpenSCAD where it evaluates every expression hundreds of
thousands of times the time taken to parse my code and instantiate modules
dominates after the first time where all the geometry is cached. Since
ind() would be a global function, I think each time it is called all my
global constants would get evaluated again.
Each operation might only take microseconds because PCs are basically very
fast but when there are explosions of complexity the time taken gets
exponential, making large projects impractical. I.e. there is a finite
limit to how big a project I can make and I am constantly looking for speed
optimisations. My current project has 1355 vitamins in it and probably only
half complete. Each one is described by a list and every property in the
list is read by an accessor function to isolate the list format. Of course
record structure with named fields would save a lot of this boilerplate
code.
On Wed, 29 Jul 2020 at 23:37, adrianv avm4@cornell.edu wrote:
Yeah, I'm with Ronaldo that I'd rather have a little bit more code than
bugs.
function ind(list,i) = is_list(list) && i>=0 && i<len(i) && list[i]
? list[i] : 0;
function camera_connector_sizes(type) = ind(list,6);
This seems equally readable to me as list[6] and significantly less
obscure.
Succinct is not always more readable or better when it means more cryptic
or
obscure, and the form you prefer is definitely more obscure---someone
reading the code would have a harder time grasping the full implication, I
think.
The speed complaint is bogus. I already tested the speed consequences of
this and it saves less than a microsecond. Are you doing this a hundred
million times?
<quote author="nophead">
No it's horrible. Instead of
function camera_connector_size(type)= type[6];
It would be
function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
Longer, slower, less readable.
On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano <rcmpersiano@>
wrote:
Well then it is a trade off between people that like to write
succinct code versus those that write bugs.
Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
that succinct enough?
function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
>Are you doing this a hundred million times?
Due to the bug in OpenSCAD where it evaluates every expression hundreds of
thousands of times the time taken to parse my code and instantiate modules
dominates after the first time where all the geometry is cached. Since
ind() would be a global function, I think each time it is called all my
global constants would get evaluated again.
Each operation might only take microseconds because PCs are basically very
fast but when there are explosions of complexity the time taken gets
exponential, making large projects impractical. I.e. there is a finite
limit to how big a project I can make and I am constantly looking for speed
optimisations. My current project has 1355 vitamins in it and probably only
half complete. Each one is described by a list and every property in the
list is read by an accessor function to isolate the list format. Of course
record structure with named fields would save a lot of this boilerplate
code.
On Wed, 29 Jul 2020 at 23:37, adrianv <avm4@cornell.edu> wrote:
> Yeah, I'm with Ronaldo that I'd rather have a little bit more code than
> bugs.
>
> function ind(list,i) = is_list(list) && i>=0 && i<len(i) && list[i]
> ? list[i] : 0;
>
> function camera_connector_sizes(type) = ind(list,6);
>
> This seems equally readable to me as list[6] and significantly less
> obscure.
> Succinct is not always more readable or better when it means more cryptic
> or
> obscure, and the form you prefer is definitely more obscure---someone
> reading the code would have a harder time grasping the full implication, I
> think.
>
> The speed complaint is bogus. I already tested the speed consequences of
> this and it saves less than a microsecond. Are you doing this a hundred
> million times?
>
> <quote author="nophead">
> No it's horrible. Instead of
>
> function camera_connector_size(type)= type[6];
>
> It would be
>
> function camera_connector_size(type)= in_bounds(type, 6) ? type[6] : false;
>
> Longer, slower, less readable.
>
>
>
> On Wed, 29 Jul 2020 at 22:56, Ronaldo Persiano <rcmpersiano@>
> wrote:
>
> > Well then it is a trade off between people that like to write
> >> succinct code versus those that write bugs.
> >
> >
> > Well, I don't like bugs. I prefer to be cautious than lazy. Anyway, isn't
> > that succinct enough?
> >
> > function in_bounds(var,i) = is_list(var) && i>=0 && i<len(var);
> > ...
> > if(in_bounds(arr)) ...
> > _______________________________________________
> > OpenSCAD mailing list
> > Discuss@.openscad
> > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
> >
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@.openscad
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>
>
>
>
>
> --
> Sent from: http://forum.openscad.org/
>
> _______________________________________________
> OpenSCAD mailing list
> Discuss@lists.openscad.org
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
>