| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
June 20, 2008 Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
I've found myself not using contracts nearly as much as I'd kind of like to. Mostly because, well, other than a nice syntactic separation between the contracts and the body of the function, there's almost nothing I can do with contracts that can't be done with a debug{} block in the function.
The problem boils down to this: no matter how well-defined I make my contracts, they will never actually be tested until runtime. At that point there's no real benefit to doing stuff in an in{} block. And since most of the contents of the in{} block are asserts which disappear in release mode anyway..
But -- if contracts, or at least portions of them, were able to be evaluated at _compile time_ on functions (or individual parameters) that take constant values, I could see a much larger benefit.
For example, say you have a function that takes a range of integers:
void fork(int x)
in
{
assert(x >= 0 && x < 20, "x is out of range");
}
body
{
// use x!
}
If I call fork(30), this is obviously an error, but won't be reported until runtime, and even then, *only in debug mode*.
If, instead, the compiler used its CTFE mechanism to interpret the in{} block as long as the params to the functions are constants, you'd get a nice compile-time message, like:
error calling fork with parameters (30):
assertion (x >= 0 && x < 20) failed: "x is out of range"
And better yet, this would happen regardless of whether you're compiling in debug mode or not.
It seems like a cool idea anyway. I wonder, in practice, how often the
compiler would be able to evaluate the contracts, and if it would be of
practical use. Or if there would be a better way to do this (like extending
the new template parameter constraints to functions: "void fork(int x) if(x
>= 0 && x < 20)").
| ||||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | >Jarrett Billingsley schrieb:
>....
> If I call fork(30), this is obviously an error, but won't be reported until runtime, and even then, *only in debug mode*.
>...
> It seems like a cool idea anyway. I wonder, in practice, how often the compiler would be able to evaluate the contracts, and if it would be of practical use. Or if there would be a better way to do this (like extending the new template parameter constraints to functions: "void fork(int x) if(x >= 0 && x < 20)").
if got the same for assert itselfe
why do assert not act like an static assert if the evaluated is a compiletime value
something like
better_assert( predicat, text )
{
static if compile_time_value( predicate )
static assert( predicate, text )
else
assert( predicate, text )
}
function test( int value )
{
better_assert( value == 4 );
// bla bla
}
test( 5 ); // compiletime error
test( non_const_wrong_value_variable ); // runtime assert
and this does not realy help in this small testcase
but think of the 1000 in/out checks and normal asserts in your projects
do realy want to see the problem only when you actualy call a specific function?
ciao dennis
| |||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | dennis luehring schrieb:
> >Jarrett Billingsley schrieb:
> >....
>> If I call fork(30), this is obviously an error, but won't be reported until runtime, and even then, *only in debug mode*.
>> ...
>> It seems like a cool idea anyway. I wonder, in practice, how often the compiler would be able to evaluate the contracts, and if it would be of practical use. Or if there would be a better way to do this (like extending the new template parameter constraints to functions: "void fork(int x) if(x >= 0 && x < 20)").
>
> if got the same for assert itselfe
>
> why do assert not act like an static assert if the evaluated is a compiletime value
>
> something like
>
> better_assert( predicat, text )
> {
> static if compile_time_value( predicate )
> static assert( predicate, text )
> else
> assert( predicate, text )
> }
>
> function test( int value )
> {
> better_assert( value == 4 );
> // bla bla
> }
>
> test( 5 ); // compiletime error
> test( non_const_wrong_value_variable ); // runtime assert
>
> and this does not realy help in this small testcase
>
> but think of the 1000 in/out checks and normal asserts in your projects
>
> do realy want to see the problem only when you actualy call a specific function?
>
> ciao dennis
and don't want to change assert - maybe another(ouch!) keyword for example "predication"
so i and jarett can use predication (or predicate?) as a
replacement for assert in in/out contracts and the other positions im currrently using assert
| |||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to dennis luehring | == Quote from dennis luehring (dl.soluz@gmx.net)'s article
> and don't want to change assert - maybe another(ouch!) keyword for
> example "predication"
> so i and jarett can use predication (or predicate?) as a
> replacement for assert in in/out contracts and the other positions im
> currrently using assert
hehe, I use "predicate" in C/C++ for assertion checks that I don't want compiled out in release builds :-) Handy for verifying the return value of functions with side-effects.
Sean
| |||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote:
> I've found myself not using contracts nearly as much as I'd kind of like to. Mostly because, well, other than a nice syntactic separation between the contracts and the body of the function, there's almost nothing I can do with contracts that can't be done with a debug{} block in the function.
>
> The problem boils down to this: no matter how well-defined I make my contracts, they will never actually be tested until runtime. At that point there's no real benefit to doing stuff in an in{} block. And since most of the contents of the in{} block are asserts which disappear in release mode anyway..
>
> But -- if contracts, or at least portions of them, were able to be evaluated at _compile time_ on functions (or individual parameters) that take constant values, I could see a much larger benefit.
>
> For example, say you have a function that takes a range of integers:
>
> void fork(int x)
> in
> {
> assert(x >= 0 && x < 20, "x is out of range");
> }
> body
> {
> // use x!
> }
>
> If I call fork(30), this is obviously an error, but won't be reported until runtime, and even then, *only in debug mode*.
>
> If, instead, the compiler used its CTFE mechanism to interpret the in{} block as long as the params to the functions are constants, you'd get a nice compile-time message, like:
>
> error calling fork with parameters (30):
> assertion (x >= 0 && x < 20) failed: "x is out of range"
>
> And better yet, this would happen regardless of whether you're compiling in debug mode or not.
>
> It seems like a cool idea anyway. I wonder, in practice, how often the
> compiler would be able to evaluate the contracts, and if it would be of
> practical use. Or if there would be a better way to do this (like extending
> the new template parameter constraints to functions: "void fork(int x) if(x
> >= 0 && x < 20)").
>
>
Sounds totally unnecessary.
if you pass 30 to the above fork you already know that it's not between
0 and 20 (that is if you finished 2nd grade of school). you need help
from the compiler when you do not know what x is, i.e. in run-time.
I don't see any practical benefits to this outside of meta-programming
and there I'd expect the compiler to throw the assert error during
compilation.
another issue is the removal of asserts in release mode. I'm not sure
that asserts should only work in debug mode and personally would prefer
to keep them in the released version. this probably should have a
compiler flag to control it. I don't like DMD's release and debug modes
at all and thing that the user should have a more fine grained control
over compilation. GCC allows me to define what kinds of optimizations I
want with a flag for each setting instead of a global release mode as
defined by Walter.
for example what if I'd like to compile my code with contracts and with
array bounds checking removed? How do I accomplish that?
| |||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | > Sounds totally unnecessary. > if you pass 30 to the above fork you already know that it's not between > 0 and 20 (that is if you finished 2nd grade of school). just think of x 100 000 lines of code projects - not these 3 lines examples - and think of projects that are growing over years ... > you need help > from the compiler when you do not know what x is, i.e. in run-time. > I don't see any practical benefits to this outside of meta-programming > and there I'd expect the compiler to throw the assert error during > compilation. why should the meta-programming section be more "safe" than normal coding? both sides can benefit | |||
June 20, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | "Yigal Chripun" <yigal100@gmail.com> wrote in message news:g3h56u$2evu$1@digitalmars.com... > Sounds totally unnecessary. > if you pass 30 to the above fork you already know that it's not between > 0 and 20 (that is if you finished 2nd grade of school). you need help > from the compiler when you do not know what x is, i.e. in run-time. > I don't see any practical benefits to this outside of meta-programming > and there I'd expect the compiler to throw the assert error during > compilation. I'm suggesting this from the point of view of someone who writes libraries which have certain input restrictions. I'd rather the errors about the inputs to a function happen at compile time than at some indefinite point in time at runtime. > another issue is the removal of asserts in release mode. I'm not sure > that asserts should only work in debug mode and personally would prefer > to keep them in the released version. this probably should have a > compiler flag to control it. I don't like DMD's release and debug modes > at all and thing that the user should have a more fine grained control > over compilation. GCC allows me to define what kinds of optimizations I > want with a flag for each setting instead of a global release mode as > defined by Walter. > for example what if I'd like to compile my code with contracts and with > array bounds checking removed? How do I accomplish that? Totally agree. It's funny -- DMDFE already has fine-grained control for contracts, asserts, bounds checking etc. but for some reason those options aren't exposed by the command-line compiler, they're all set as a chunk by -debug and -release. | |||
July 26, 2008 Re: Idea: function contracts + CTFE | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote: > I've found myself not using contracts nearly as much as I'd kind of like to. Mostly because, well, other than a nice syntactic separation between the contracts and the body of the function, there's almost nothing I can do with contracts that can't be done with a debug{} block in the function. > > The problem boils down to this: no matter how well-defined I make my contracts, they will never actually be tested until runtime. At that point there's no real benefit to doing stuff in an in{} block. And since most of the contents of the in{} block are asserts which disappear in release mode anyway.. > > But -- if contracts, or at least portions of them, were able to be evaluated at _compile time_ on functions (or individual parameters) that take constant values, I could see a much larger benefit. > > For example, say you have a function that takes a range of integers: > > void fork(int x) > in > { > assert(x >= 0 && x < 20, "x is out of range"); > } > body > { > // use x! > } > > If I call fork(30), this is obviously an error, but won't be reported until runtime, and even then, *only in debug mode*. > > If, instead, the compiler used its CTFE mechanism to interpret the in{} block as long as the params to the functions are constants, you'd get a nice compile-time message, like: > > error calling fork with parameters (30): > assertion (x >= 0 && x < 20) failed: "x is out of range" > > And better yet, this would happen regardless of whether you're compiling in debug mode or not. > > It seems like a cool idea anyway. I wonder, in practice, how often the compiler would be able to evaluate the contracts, and if it would be of practical use. Or if there would be a better way to do this (like extending the new template parameter constraints to functions: "void fork(int x) if(x >= 0 && x < 20)"). > > It would be nice, yes, but I think having a contract inference & analysis engine that could find (in compile-time) contract violations on any more than just trivial cases would take quite a lot of effort to implement. (so that would be too much for Walter alone) -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply