discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Would be nice to have constraints/assertions on functions/modules.

A
adrian
Sun, Jan 25, 2015 5:50 PM

When debugging, it would be valuable if I could say something like:

  1. function fn(x) = assert(dim(x) == 1) 2.  let(result = 3.
    [for(i=[1:len(x)]) 4.      if(i!=len(x)-1) 5.        assert(x[i] > x[i-1],
    str("@i==",i,".  Was ", x[i], " > ", x[i-1], ".")) 6.        x[i]-x[i-1] 7.
    ]) 8.    assert(result[0] == 0) assert(len(x) == len(result)+1) result;
    Please note that this is quite contrived example, but it demonstrates a
    function's precondition, postcondition and an interior straight up
    assertion.  Also, I've placed line numbers prior to each line of code and
    we'll pretend that all lines shown here are in a file called x.scad.
    This function shows that it takes only a one dimensional array, where each
    element must be less than the one before it and the result must have a first
    element be equal to 0 and have one less element then the array passed in.
    The result itself is an array where the next element is subtracted from the
    current.
    If the assert's first parameter is equivalent to false, then it should the
    file and line where the assertion occurred, as well as the caller's line all
    the way up the stack.  Variables are substituted for the parameters with
    their values to help in the debugging process.  This would be great to be
    able to trace back where the problem came from.  It would also write out the
    1st parameter as a string as well as the result that it gave back. This is
    because false can be represented in many different ways and may be useful
    when debugging.  Something like:
  2. x=1;21. y=fn(x);
    Would output:
    ASSERTION FAILURE  -> from file x.scad:21 while calling: fn(1)  -> in file
    x.scad:1  (dim(x) == 1) == false
    If an assert has a 2nd parameter, it should evaluate and output that as well
    as the programmer can drop a more explicit hint as to what the user of their
    function did wrong. So something like this:
  3. fn([4,undef,3]);
    Would output:
    ASSERTION FAILURE  -> from x.scad:2 while calling: fn([4,undef,3])  -> in
    file x.scad:5  (x[i] < x[i+1]) == undef  @i==0.  Was 4 < undef.
    An assert can be placed anywhere prior to an expression and if false, then
    should stop the execution in its tracks.  An assert is not an expression, it
    doesn't return any value and must be bound to an expression.  That said,
    multiple asserts can be placed next to each other, so they all would be
    bound to the expression to the right of the rightmost assert.
    Alternatives would be to have specific pre and postcondition constraints as
    well as assertions, but I don't think that it would be that great of a gain.
    Also, instead of just using the 2nd parameter, we could just use the 2nd on
    and treat them as if they were parameters to the str(...) function which
    would remove the need for the call to str(...) which might reduce the
    typing, but may increase the noise as assert value and assert message can
    run together.  If done this way, one could still do it the other way and
    could be left up to the preference of the programmer of the .scad file.
    I think the usefulness to the programmer and user of any .scad library would
    benefit. What do you ppl think?
     
    A

--
View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

When debugging, it would be valuable if I could say something like: 1. function fn(x) = assert(dim(x) == 1) 2. let(result = 3. [for(i=[1:len(x)]) 4. if(i!=len(x)-1) 5. assert(x[i] > x[i-1], str("@i==",i,". Was ", x[i], " > ", x[i-1], ".")) 6. x[i]-x[i-1] 7. ]) 8. assert(result[0] == 0) assert(len(x) == len(result)+1) result; Please note that this is quite contrived example, but it demonstrates a function's precondition, postcondition and an interior straight up assertion. Also, I've placed line numbers prior to each line of code and we'll pretend that all lines shown here are in a file called x.scad. This function shows that it takes only a one dimensional array, where each element must be less than the one before it and the result must have a first element be equal to 0 and have one less element then the array passed in. The result itself is an array where the next element is subtracted from the current. If the assert's first parameter is equivalent to false, then it should the file and line where the assertion occurred, as well as the caller's line all the way up the stack. Variables are substituted for the parameters with their values to help in the debugging process. This would be great to be able to trace back where the problem came from. It would also write out the 1st parameter as a string as well as the result that it gave back. This is because false can be represented in many different ways and may be useful when debugging. Something like: 20. x=1;21. y=fn(x); Would output: ASSERTION FAILURE -> from file x.scad:21 while calling: fn(1) -> in file x.scad:1 (dim(x) == 1) == false If an assert has a 2nd parameter, it should evaluate and output that as well as the programmer can drop a more explicit hint as to what the user of their function did wrong. So something like this: 34. fn([4,undef,3]); Would output: ASSERTION FAILURE -> from x.scad:2 while calling: fn([4,undef,3]) -> in file x.scad:5 (x[i] < x[i+1]) == undef @i==0. Was 4 < undef. An assert can be placed anywhere prior to an expression and if false, then should stop the execution in its tracks. An assert is not an expression, it doesn't return any value and must be bound to an expression. That said, multiple asserts can be placed next to each other, so they all would be bound to the expression to the right of the rightmost assert. Alternatives would be to have specific pre and postcondition constraints as well as assertions, but I don't think that it would be that great of a gain. Also, instead of just using the 2nd parameter, we could just use the 2nd on and treat them as if they were parameters to the str(...) function which would remove the need for the call to str(...) which might reduce the typing, but may increase the noise as assert value and assert message can run together. If done this way, one could still do it the other way and could be left up to the preference of the programmer of the .scad file. I think the usefulness to the programmer and user of any .scad library would benefit. What do you ppl think? &nbsp; A -- View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Sun, Jan 25, 2015 5:56 PM

BTW, when I said bound to an expression, I'm not really sure if that is how
you do it for let(...) but it would be the same idea as that.
 
A

--
View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11238.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

BTW, when I said bound to an expression, I'm not really sure if that is how you do it for let(...) but it would be the same idea as that. &nbsp; A -- View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11238.html Sent from the OpenSCAD mailing list archive at Nabble.com.
TP
Torsten Paul
Mon, Jan 26, 2015 4:17 AM

On 01/25/2015 06:50 PM, adrian wrote:

I think the usefulness to the programmer and user of any .scad library
would benefit. What do you ppl think?

Maybe add this to https://github.com/openscad/openscad/issues/381

It might not be easy to cover all in the first go as the line
number tracking is very limited currently. That's a big issue
that needs to be solved in itself.

Why tie it to an expression, just to make it usable at any place
where an expression can be used right now? It probably is useful
in a module context too, e.g.

module m() {
assert(...);

...

}

ciao,
Torsten.

On 01/25/2015 06:50 PM, adrian wrote: > I think the usefulness to the programmer and user of any .scad library > would benefit. What do you ppl think? > Maybe add this to https://github.com/openscad/openscad/issues/381 It might not be easy to cover all in the first go as the line number tracking is very limited currently. That's a big issue that needs to be solved in itself. Why tie it to an expression, just to make it usable at any place where an expression can be used right now? It probably is useful in a module context too, e.g. module m() { assert(...); ... } ciao, Torsten.
TA
Taahir Ahmed
Mon, Jan 26, 2015 7:00 PM

Sort of a shameless plug --- this patch is still floating around, but has not
made it into mainline.

http://forum.openscad.org/PATCH-Add-function-pre-and-post-conditions-td9493.html

Taahir

Sort of a shameless plug --- this patch is still floating around, but has not made it into mainline. http://forum.openscad.org/PATCH-Add-function-pre-and-post-conditions-td9493.html Taahir
A
adrian
Tue, Jan 27, 2015 12:23 AM

Taahir Ahmed wrote

Sort of a shameless plug --- this patch is still floating around, but has
not made it into
mainline.http://forum.openscad.org/PATCH-Add-function-pre-and-post-conditions-td9493.htmlTaahir

This is interesting.  I would like your __pre(), __post(), __doc() and
__test() decorators to be implemented.  However, the assert() that I propose
/should/ be easier to implement as it probably could piggyback off of how
let() was done and could be used in the interim for the pre and post
decorator conditions you propose without being as big as a discussion.
 
A

--
View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11247.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Taahir Ahmed wrote > Sort of a shameless plug --- this patch is still floating around, but has > not made it into > mainline.http://forum.openscad.org/PATCH-Add-function-pre-and-post-conditions-td9493.htmlTaahir This is interesting. I would like your __pre(), __post(), __doc() and __test() decorators to be implemented. However, the assert() that I propose /*should*/ be easier to implement as it probably could piggyback off of how let() was done and could be used in the interim for the pre and post decorator conditions you propose without being as big as a discussion. &nbsp; A -- View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11247.html Sent from the OpenSCAD mailing list archive at Nabble.com.
A
adrian
Tue, Jan 27, 2015 12:41 AM

tp3 wrote

On 01/25/2015 06:50 PM, adrian wrote:

I think the usefulness to the programmer and user of any .scad library
would benefit. What do you ppl think?

Sure, I'll do that.

tp3 wrote

It might not be easy to cover all in the first go as the line
number tracking is very limited currently. That's a big issue
that needs to be solved in itself.

Really?  Hmmm. Ok, then that could be postponed for a later time.  How about
the rest of the output that I stated?  Would that be possible?  And the text
that an assert outputs could be still used for a person to do a find in the
code at least.

tp3 wrote

Why tie it to an expression, just to make it usable at any place
where an expression can be used right now? It probably is useful
in a module context too, e.g.

Tieing it to an expression was meant for coding simplicity (of modifying the
SCAD parser) since there is already a let() function, it could be
implemented in the same manner which is known to work.

This would still allow it to be put into a module (abit somewhat hackily) by
putting it in the first or in a fake assignment.  The assert() idea I had
was mostly for testing near the point of need, but it could be expanded to a
module scope as well.  In fact, if we have it as I suggest, one could make a
module that is called assert() and use the hack.  I.e.

A

--
View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11249.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

tp3 wrote > On 01/25/2015 06:50 PM, adrian wrote: >> I think the usefulness to the programmer and user of any .scad library > > would benefit. What do you ppl think? >> > Maybe add this to https://github.com/openscad/openscad/issues/381 Sure, I'll do that. tp3 wrote > It might not be easy to cover all in the first go as the line > number tracking is very limited currently. That's a big issue > that needs to be solved in itself. Really? Hmmm. Ok, then that could be postponed for a later time. How about the rest of the output that I stated? Would that be possible? And the text that an assert outputs could be still used for a person to do a find in the code at least. tp3 wrote > Why tie it to an expression, just to make it usable at any place > where an expression can be used right now? It probably is useful > in a module context too, e.g. Tieing it to an expression was meant for coding simplicity (of modifying the SCAD parser) since there is already a let() function, it could be implemented in the same manner which is known to work. This would still allow it to be put into a module (abit somewhat hackily) by putting it in the first or in a fake assignment. The assert() idea I had was mostly for testing near the point of need, but it could be expanded to a module scope as well. In fact, if we have it as I suggest, one could make a module that is called assert() and use the hack. I.e. A -- View this message in context: http://forum.openscad.org/Would-be-nice-to-have-constraints-assertions-on-functions-modules-tp11237p11249.html Sent from the OpenSCAD mailing list archive at Nabble.com.