August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andre Artus | On Monday, 5 August 2013 at 21:48:46 UTC, Andre Artus wrote:
> On Monday, 5 August 2013 at 19:58:21 UTC, ron wrote:
>> On Monday, 5 August 2013 at 08:46:54 UTC, Andre Artus wrote:
>>> On Monday, 5 August 2013 at 06:28:12 UTC, luminousone wrote:
>>>> perhaps a more generic solution should be looked at, extend contracts to work with all scope blocks.
>>>>
>>>> switch(somenumber)
>>>> in {
>>>> ... before stuff ...
>>>> }
>>>> out {
>>>> .... after stuff ...
>>>> }
>>>> body {
>>>> case 1:
>>>> in {
>>>> ... etc ....
>>>> }
>>>> out {
>>>> ... more etc ...
>>>> }
>>>> body {
>>>> ...
>>>> }
>>>> case 2:
>>>> // and so on
>>>> }
>>>>
>>>> or perhaps
>>>>
>>>> for( int i = 0 ; i < 10 ; i ++ )
>>>> in {
>>>> assert( i == 0 );
>>>> }
>>>> out {
>>>> assert( i == 9 );
>>>> }
>>>> body {
>>>> ... stuff ...
>>>> }
>>>>
>>>> if it is desired for a particular contract block to be called in release builds perhaps a attribute label to mark it as a runtime block or something similar.
>>>>
>>>> foreach( i, k ; somerange )
>>>> @runtime in {
>>>> ...
>>>> }
>>>> body {
>>>> }
>>>
>>> Please do not take offense, but I do not see this as a good idea. Contracts have a very different function; not just in D, but every language that uses them. The idea is to support design-by-contract programming. Overloading the constructs for the purposes proposed here would, in my opinion, cause confusion and/or weaken the proper use of contract programming.
>>>
>>>
>>> The code in the contract conditions should never do anything more than what is necessary to specify the contract. It should not do explicit IO (other than implied by assert()), mutate state, or anything like that.
>>>
>>> At the bottom of this page you can find a reading list for more info.
>>> http://www.digitalmars.com/d/dbc.html
>>>
>>> Or for a general overview:
>>> http://en.wikipedia.org/wiki/Design_by_contract
>>>
>>> Walter, does the D compiler or any of it's companion tools do any static analysis on the contracts? Such as a void safety/null reference check?
>>
>> None taken, =-p.
>>
>> I don't see how this is different from current contract usage, right now they apply to function scopes only. currently I believe you could get a similar effect via using an inner function.
>>
>> void a() {
>> int i = 0;
>> void b()
>> in {
>> assert( i == 0 );
>> }
>> out {
>> assert( i == 10 );
>> }
>> body {
>> for( ; i < 10 ; i ++ ) {
>> ... do something ...
>> }
>> }
>> b();
>> }
>
> I could be missing something, if so please clarify.
>
> The construct I have issue with is this one,
>
>>>> switch(somenumber)
>>>> in {
>>>> ... before stuff ...
>>>> }
>>>> out {
>>>> .... after stuff ...
>>>> }
>
> I would contend that code within in/out/invariant blocks should be 'pure' (no state changes, no IO [other than assert throwing]), it's only there to validate that a class and it's methods do not violate certain conditions. They should be able to be stripped out of the release build without altering the execution of the application in any way.
>
> A classic example is the null dereference check, which some compilers and most (all?) static analysers can detect.
>
>
>
> string whoIsAMonkey(Person p)
> in
> {
> assert(p !is null, "Person can not be null");
> assert(!isNullOrEmpty(p.Name), "Person name can not be null or empty");
> }
> body
> {
> return p.Name ~ " is a monkey!";
> }
>
>
> void main() {
> Person p = null;
> // Compiler / analyser should complain with
> // "Person can not be null"
> writeln(whoIsAMonkey(p));
> // ^ here
> }
>
> void main() {
> Person p = new Person();
> // Compiler / analyser should complain with
> // "Person name can not be null or empty"
> writeln(whoIsAMonkey(p));
> }
>
> etc.
>
> Contracts are meant to define the public (*) interface of a class.
>
> * By public I mean here anything not 'private', e.g. 'protected' for inheritance.
>
> As Andrei points out in his book ("The D Programming Language") contracts are not used to validate/scrub user (or any external) input as they can be compiled out of the executable.
>
> Contracts are there to check sanity at compile time, or at the very least during testing.
>
> The contract is (or should be) part of the documentation.
You are correct. I will have to check out his book.
|
August 05, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to luminousone | >> As Andrei points out in his book ("The D Programming Language") contracts are not used to validate/scrub user (or any external) input as they can be compiled out of the executable. >> >> Contracts are there to check sanity at compile time, or at the very least during testing. >> >> The contract is (or should be) part of the documentation. > > You are correct. I will have to check out his book. Be sure to check out the errata page http://erdani.com/tdpl/errata/ |
August 06, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Saturday, 3 August 2013 at 19:22:53 UTC, Walter Bright wrote:
> On 8/3/2013 12:00 PM, JS wrote:
>> What I really don't get it is why people think that just because they won't use
>> such a feature then it must be useless to everyone else.
>
> You could provide supporting evidence by examining every use of switch in the dmd, phobos, and druntime source code, and see what percentage of those would benefit from your proposal.
>
> Consider, for example, the scope guard statement in D. It is extremely useful - but it is an unusual form (doesn't exist in other languages) and programmers just don't think in those terms. Andrei & I constantly have to work at 'selling' the benefits of it. It still hasn't really caught on.
The scope guard statement is my all-time favourite feature in D. It's so much easier to reason about than several layers of try/catch/finally.
A close second is the Contracts, especially as it can be applied to interfaces. a huge win for service oriented programming.
|
August 06, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andre Artus | > I was under the impression that D has nested functions, unless by inner function you mean something else.
Yeah, pardon my terminology.
|
August 06, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to QAston | On Tuesday, 6 August 2013 at 07:44:46 UTC, QAston wrote:
>> I was under the impression that D has nested functions, unless by inner function you mean something else.
>
> Yeah, pardon my terminology.
Not an issue, they normally mean the same thing. I believe JS's use case can be covered easily and clearly using a nested function taking a void delegate. With the not insubstatial benefit of being easier to debug.
|
August 10, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Sat, Aug 03, 2013 at 12:22:53PM -0700, Walter Bright wrote: > On 8/3/2013 12:00 PM, JS wrote: > >What I really don't get it is why people think that just because they won't use such a feature then it must be useless to everyone else. > > You could provide supporting evidence by examining every use of switch in the dmd, phobos, and druntime source code, and see what percentage of those would benefit from your proposal. > > Consider, for example, the scope guard statement in D. It is extremely useful - but it is an unusual form (doesn't exist in other languages) and programmers just don't think in those terms. Andrei & I constantly have to work at 'selling' the benefits of it. It still hasn't really caught on. At least it has caught on with me. :) After learning about scope guards in D, I've been plagued with persistent thoughts of "I wish I could use a scope guard here!" every time I work with C/C++ code. Ironically, though, D's superior design has pretty much eliminated the need for scope guards except in a few rare cases. :-P They used to be still useful for things like closing files at the end of the block, but struct dtors have pretty much eliminated that use case as well. But I'd venture to say that in code that uses manual memory management (like game engines), scope guards are a lifesaver. Maybe Manu can chime in here. :) T -- The best compiler is between your ears. -- Michael Abrash |
August 10, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
On Sat, Aug 03, 2013 at 01:33:44PM -0700, Jonathan M Davis wrote: > On Saturday, August 03, 2013 12:35:22 H. S. Teoh wrote: > > On Sat, Aug 03, 2013 at 12:22:53PM -0700, Walter Bright wrote: [...] > > > Consider, for example, the scope guard statement in D. It is extremely useful - but it is an unusual form (doesn't exist in other languages) and programmers just don't think in those terms. Andrei & I constantly have to work at 'selling' the benefits of it. It still hasn't really caught on. > > > > At least it has caught on with me. :) After learning about scope guards in D, I've been plagued with persistent thoughts of "I wish I could use a scope guard here!" every time I work with C/C++ code. > > > > Ironically, though, D's superior design has pretty much eliminated the need for scope guards except in a few rare cases. :-P They used to be still useful for things like closing files at the end of the block, but struct dtors have pretty much eliminated that use case as well. > > I'm surprised that you'd miss scope in C++ and yet not use it in D. Well, I miss it more in C than C++, but C++'s manual memory management does make scope rather attractive. The same goes for D, actually, but that's largely alleviated due to the built-in GC. > The only thing that's really missing from C++ that D has that you might use in place of scope is finally. Truth be told, I think scope trumps finally because it localizes the cleanup statement to the initialization. Sprinkling related code across two different places is more fragile and bug-prone. > C++ has RAII just like D does. There's a much bigger difference when comparing against languages which don't have RAII (such as Java or C#), but with C++ has RAII. Yeah, I think I mostly had C in mind when I wrote what I did. :) > In general, I think that it comes down to a question of whether RAII > or scope(exit) is more appropriate, and RAII works better in common > cases (such as closing files or releasing a mutex), wheras scope(exit) > works better in cases which aren't common (since it doesn't make sense > to create types just for those cases). RAII also makes more sense in > cases where you essentially need a reference count before doing the > action rather than just when exiting the scope (e.g. closing files is > also a good example of that; a File struct is more flexible than using > scope(exit) to close the file). Yeah, with RAII, much of the use cases of scope is eliminated. I'm mainly working with C at my job right now, which is why I miss scope so much. C is just so tedious to use due to the amount of manual baby-sitting required to make things work properly. I still miss scope in C++ because of the lack of a GC, but otherwise, even C++ doesn't have that many use cases for scope left. > I definitely use scope from time to time, but I don't know how frequently I use it in comparison to how often I should use it. I was actually using scope(success) more until someone pointed out that there's an efficiency hit with that as it was putting try-catch blocks in places where there wouldn't have been before (as opposed to scope(exit) or scope(failure) where you'd be using try-catch blocks if you weren't using scope). [...] Hmm, I never thought of that. So that limits the use cases of scope guards even more. :-P T -- My program has no bugs! Only unintentional features... |
August 10, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
On Saturday, August 03, 2013 12:35:22 H. S. Teoh wrote:
> On Sat, Aug 03, 2013 at 12:22:53PM -0700, Walter Bright wrote:
> > On 8/3/2013 12:00 PM, JS wrote:
> > >What I really don't get it is why people think that just because they won't use such a feature then it must be useless to everyone else.
> >
> > You could provide supporting evidence by examining every use of switch in the dmd, phobos, and druntime source code, and see what percentage of those would benefit from your proposal.
> >
> > Consider, for example, the scope guard statement in D. It is extremely useful - but it is an unusual form (doesn't exist in other languages) and programmers just don't think in those terms. Andrei & I constantly have to work at 'selling' the benefits of it. It still hasn't really caught on.
>
> At least it has caught on with me. :) After learning about scope guards in D, I've been plagued with persistent thoughts of "I wish I could use a scope guard here!" every time I work with C/C++ code.
>
> Ironically, though, D's superior design has pretty much eliminated the need for scope guards except in a few rare cases. :-P They used to be still useful for things like closing files at the end of the block, but struct dtors have pretty much eliminated that use case as well.
I'm surprised that you'd miss scope in C++ and yet not use it in D. The only thing that's really missing from C++ that D has that you might use in place of scope is finally. C++ has RAII just like D does. There's a much bigger difference when comparing against languages which don't have RAII (such as Java or C#), but with C++ has RAII.
In general, I think that it comes down to a question of whether RAII or scope(exit) is more appropriate, and RAII works better in common cases (such as closing files or releasing a mutex), wheras scope(exit) works better in cases which aren't common (since it doesn't make sense to create types just for those cases). RAII also makes more sense in cases where you essentially need a reference count before doing the action rather than just when exiting the scope (e.g. closing files is also a good example of that; a File struct is more flexible than using scope(exit) to close the file).
I definitely use scope from time to time, but I don't know how frequently I use it in comparison to how often I should use it. I was actually using scope(success) more until someone pointed out that there's an efficiency hit with that as it was putting try-catch blocks in places where there wouldn't have been before (as opposed to scope(exit) or scope(failure) where you'd be using try-catch blocks if you weren't using scope).
- Jonathan M Davis
|
August 10, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
On Saturday, August 03, 2013 14:25:24 H. S. Teoh wrote: > On Sat, Aug 03, 2013 at 01:33:44PM -0700, Jonathan M Davis wrote: > > The only thing that's really missing from C++ that D has that you might use in place of scope is finally. > > Truth be told, I think scope trumps finally because it localizes the cleanup statement to the initialization. Sprinkling related code across two different places is more fragile and bug-prone. Yes. There are lots of places where scope(exit) is far better than finally. It's just that aside from scope statements, the only related feature that C++ lacks is finally (and scope(exit) uses finally underneath the hood). > > C++ has RAII just like D does. There's a much bigger difference when comparing against languages which don't have RAII (such as Java or C#), but with C++ has RAII. > > Yeah, I think I mostly had C in mind when I wrote what I did. :) Yeah. The lack of RAII and scope in C is truly painful. I'm very glad that I've never had to write much pure C code. > > I definitely use scope from time to time, but I don't know how frequently I use it in comparison to how often I should use it. I was actually using scope(success) more until someone pointed out that there's an efficiency hit with that as it was putting try-catch blocks in places where there wouldn't have been before (as opposed to scope(exit) or scope(failure) where you'd be using try-catch blocks if you weren't using scope). > > [...] > > Hmm, I never thought of that. So that limits the use cases of scope guards even more. :-P Yeah. For instance, I'd made it so that RedBlackTree was using scope(success) for mutating its length in a few places, which helped make the code cleaner (because you didn't have to worry about incrementing the length at each of the various return statements), but that introduced try-catch blocks where there otherwise wouldn't have been any, and that code definitely needs to be as efficient as possible, so the scope(success) statements were removed from there. Other code wouldn't care as much, but for something like RedBlackTree, it really matters. It is a bit of a shame though, since it made the code cleaner. - Jonathan M Davis |
August 10, 2013 Re: request switch statement with common block | ||||
---|---|---|---|---|
| ||||
On Sat, Aug 03, 2013 at 02:34:51PM -0700, Jonathan M Davis wrote: > On Saturday, August 03, 2013 14:25:24 H. S. Teoh wrote: > > On Sat, Aug 03, 2013 at 01:33:44PM -0700, Jonathan M Davis wrote: [...] > > > I definitely use scope from time to time, but I don't know how frequently I use it in comparison to how often I should use it. I was actually using scope(success) more until someone pointed out that there's an efficiency hit with that as it was putting try-catch blocks in places where there wouldn't have been before (as opposed to scope(exit) or scope(failure) where you'd be using try-catch blocks if you weren't using scope). > > > > [...] > > > > Hmm, I never thought of that. So that limits the use cases of scope guards even more. :-P > > Yeah. For instance, I'd made it so that RedBlackTree was using scope(success) for mutating its length in a few places, which helped make the code cleaner (because you didn't have to worry about incrementing the length at each of the various return statements), but that introduced try-catch blocks where there otherwise wouldn't have been any, and that code definitely needs to be as efficient as possible, so the scope(success) statements were removed from there. Other code wouldn't care as much, but for something like RedBlackTree, it really matters. It is a bit of a shame though, since it made the code cleaner. [...] On second thoughts, why is scope(success) implemented as try/catch? Shouldn't the compiler be able to insert it before the end of each block instead? Stack-unwinding bypasses the end of block code, so the only way you can get there is by successful exit. T -- Error: Keyboard not attached. Press F1 to continue. -- Yoon Ha Lee, CONLANG |
Copyright © 1999-2021 by the D Language Foundation