June 28, 2010 Re: Renaming std.conv | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote: > Better yet, how about defining std.exception that includes a host of exception-related functionality (such as defining exceptions that retain file and line, perhaps stack traces etc.)? Sounds good. -- Simen | |||
June 28, 2010 Re: Renaming std.conv | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Sunday 27 June 2010 16:09:02 Andrei Alexandrescu wrote:
>
> We haven't reached consensus on where to put enforce() and friends. Any other ideas? Of the above, I like std.checks.
>
> Better yet, how about defining std.exception that includes a host of exception-related functionality (such as defining exceptions that retain file and line, perhaps stack traces etc.)?
>
>
> Andrei
std.exception sounds like a good plan. I'm not overly fond of any of the other names, and I'm not sure that I care much one way or the other if we pick one, but std.exception with a bunch of exception-related stuff sounds particularly useful and could help standardize some of the way exceptions are used in D code.
- Jonathan M Davis
| |||
June 28, 2010 Re: enforce()? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 2010-06-28 07:17:53 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said: > On 06/28/2010 03:15 AM, Norbert Nemec wrote: >> On 19/06/10 22:46, Andrei Alexandrescu wrote: >>> On 06/19/2010 03:55 PM, bearophile wrote: >>>> Inside Phobos2 I have counted about 160 usages of the "body" keyword. >>>> I think contract programming can be used more often inside Phobos2 >>>> (and maybe some usages of enforce() can be turned into contract >>>> programming because they are more similar to program sanity checks). >>> >>> Walter and I discussed this and concluded that Phobos should handle its >>> parameters as user input. Therefore they need to be scrubbed with hard >>> tests, not contracts. >> >> IMHO, this is plain wrong! >> >> By this kind of decision, you are putting the library user under >> tutelage. The D language is explicitly designed to allow the user to >> take off the safety belt, but to do so at their own responsibility. > > C APIs also check their arguments. With C you don't have the option to turn the checks on or off. It's generally better to have them when you don't need them than not have them when you need them. With D, you can turn them on or off on a whim. If the 'in' contract was enforced at the call site instead of inside the function, it'd be up to the one using a function to decide whether to check contracts or not. That's not an option in C, but it could work like that in D... I agree though that with the way contracts are currently implemented this doesn't work very well. You have to recompile the library with contracts on, which in turn forces all the internal contracts inside the library to be evaluated. All this because you're trying to validate inputs you give to that library? Doesn't make sense. In that context I agree that checking explicitly at the library boundaries might be a more viable option (like in C). -- Michel Fortin michel.fortin@michelf.com http://michelf.com/ | |||
June 28, 2010 Re: enforce()? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | Michel Fortin wrote: > On 2010-06-28 07:17:53 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> said: > >> On 06/28/2010 03:15 AM, Norbert Nemec wrote: >>> On 19/06/10 22:46, Andrei Alexandrescu wrote: >>>> On 06/19/2010 03:55 PM, bearophile wrote: >>>>> Inside Phobos2 I have counted about 160 usages of the "body" keyword. >>>>> I think contract programming can be used more often inside Phobos2 >>>>> (and maybe some usages of enforce() can be turned into contract >>>>> programming because they are more similar to program sanity checks). >>>> >>>> Walter and I discussed this and concluded that Phobos should handle its >>>> parameters as user input. Therefore they need to be scrubbed with hard >>>> tests, not contracts. >>> >>> IMHO, this is plain wrong! >>> >>> By this kind of decision, you are putting the library user under >>> tutelage. The D language is explicitly designed to allow the user to >>> take off the safety belt, but to do so at their own responsibility. >> >> C APIs also check their arguments. > > With C you don't have the option to turn the checks on or off. #define NDEBUG Andrei | |||
June 29, 2010 Re: Renaming std.conv | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Sun, 27 Jun 2010 18:09:02 -0500, Andrei Alexandrescu wrote:
> On 06/17/2010 04:10 AM, Lars T. Kyllingstad wrote:
>> On Wed, 16 Jun 2010 07:31:39 -0700, Andrei Alexandrescu wrote:
>>
>>> Michel Fortin wrote:
>>>> On 2010-06-16 05:15:24 -0400, Walter Bright <newshound1@digitalmars.com> said:
>>>>
>>>>> The difference is not based on those 3 points, but on what Andrei wrote here. Contracts and error checking are completely distinct activities and should not be conflated.
>>>>
>>>> True.
>>>>
>>>> Yet, enforce is inside std.contracts. If that isn't conflating the two concepts I wonder what it is. :-)
>>>
>>> You're right! I think Lars' suggestion is sensible - we should move enforce to object. Better yet we should find a better name for std.contracts. Ideas?
>>>
>>> Andrei
>>
>>
>> A few suggestions (even though I still think it belongs in object.d),
>> in no particular order:
>>
>> std.enforce
>> std.assumptions
>> std.constraints
>> std.checks
>> std.tests
>> std.error
>> std.errcheck
>>
>> -Lars
>
> We haven't reached consensus on where to put enforce() and friends. Any other ideas? Of the above, I like std.checks.
>
> Better yet, how about defining std.exception that includes a host of exception-related functionality (such as defining exceptions that retain file and line, perhaps stack traces etc.)?
TDPL mentions several times that enforce() is in std.contracts. Doesn't that preclude moving it or renaming the module?
-Lars
| |||
June 29, 2010 Re: Renaming std.conv | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Lars T. Kyllingstad | Lars T. Kyllingstad wrote:
> On Sun, 27 Jun 2010 18:09:02 -0500, Andrei Alexandrescu wrote:
>
>> On 06/17/2010 04:10 AM, Lars T. Kyllingstad wrote:
>>> On Wed, 16 Jun 2010 07:31:39 -0700, Andrei Alexandrescu wrote:
>>>
>>>> Michel Fortin wrote:
>>>>> On 2010-06-16 05:15:24 -0400, Walter Bright
>>>>> <newshound1@digitalmars.com> said:
>>>>>
>>>>>> The difference is not based on those 3 points, but on what Andrei
>>>>>> wrote here. Contracts and error checking are completely distinct
>>>>>> activities and should not be conflated.
>>>>> True.
>>>>>
>>>>> Yet, enforce is inside std.contracts. If that isn't conflating the
>>>>> two concepts I wonder what it is. :-)
>>>> You're right! I think Lars' suggestion is sensible - we should move
>>>> enforce to object. Better yet we should find a better name for
>>>> std.contracts. Ideas?
>>>>
>>>> Andrei
>>>
>>> A few suggestions (even though I still think it belongs in object.d),
>>> in no particular order:
>>>
>>> std.enforce
>>> std.assumptions
>>> std.constraints
>>> std.checks
>>> std.tests
>>> std.error
>>> std.errcheck
>>>
>>> -Lars
>> We haven't reached consensus on where to put enforce() and friends. Any
>> other ideas? Of the above, I like std.checks.
>>
>> Better yet, how about defining std.exception that includes a host of
>> exception-related functionality (such as defining exceptions that retain
>> file and line, perhaps stack traces etc.)?
>
>
> TDPL mentions several times that enforce() is in std.contracts. Doesn't that preclude moving it or renaming the module?
I plan to move it to std.exception in a backward-compatible way (have std.conv consist of only one import, then deprecate it).
Andrei
| |||
July 05, 2010 Re: Renaming std.conv | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 28.06.2010 01:09, Andrei Alexandrescu wrote:
[...]
> We haven't reached consensus on where to put enforce() and friends. Any
> other ideas? Of the above, I like std.checks.
>
> Better yet, how about defining std.exception that includes a host of
> exception-related functionality (such as defining exceptions that retain
> file and line, perhaps stack traces etc.)?
>
How will std.exception relate to core.exception? Seems to me having two module with that similiar names could easily be confusing.
| |||
July 17, 2010 Re: enforce()? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 06/16/2010 05:47 AM, Steven Schveighoffer wrote:
> On Tue, 15 Jun 2010 22:23:15 -0400, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> bearophile wrote:
>>> I have counted about 200 usages of std.contracts.enforce() inside
>>> Phobos. Can you tell me what's the purpose of enforce() in a language
>>> that has built-in Contract Programming?
>>
>> You need to read TDPL for that :o).
>>
>>> And what are the purposes of std.contracts.AssumeSorted()? Is it
>>> useful for something?
>>
>> AssumeSorted was an experiment. I think it has drawbacks that I don't
>> know how to address, so I'll retire it.
>
> Hm... what are the drawbacks (besides it not being enforced)? I thought
> it was a good solution.
Sorry I took so long (over one month!) to reply to this. I've delayed the reply to the point when it could be integrated within the upcoming thread about improving std.algorithm.find.
The problem with AssumeSorted is that generally predicates in D (and also in most other languages) are not easy to compare. Let's first recall AssumSorted's definition. It's just a wrapper:
/**
Passes the type system the information that $(D range) is already
sorted by predicate $(D pred). No checking is performed; debug builds
may insert checks randomly. To insert a check, see $(XREF algorithm,
isSorted).
*/
struct AssumeSorted(Range, alias pred = "a < b")
{
/// Alias for $(D Range).
alias Range AssumeSorted;
/// The passed-in range.
Range assumeSorted;
/// The sorting predicate.
alias pred assumeSortedBy;
}
/// Ditto
AssumeSorted!(Range, pred) assumeSorted(alias pred = "a < b", Range)
(Range r)
{
AssumeSorted!(Range, pred) result;
result.assumeSorted = r;
return result;
}
The recommended way to use the facility is:
int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
assert(find(assumeSorted(a), 3) == [ 3, 4, 5 ]);
find() uses simple means to detect that its first argument has type AssumeSorted and takes advantage of that when searching (specifically by doing binary search).
So far so good. The problem ensues when we want to make sure that the sorting predicate is in sync with the search predicate. For example, if the search predicate is "==" then it's okay to use "<" or ">" as a sorting predicate. But searching for "a.zip == b.zip" in a range sorted by "a.name < b.name" is not okay.
If predicates were all expressed as strings, probably some string manipulation could be done to see whether they are compatible. But as things stand, assertSorted has quite limited power.
Andrei
| |||
July 19, 2010 Re: enforce()? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Sat, 17 Jul 2010 16:25:16 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote: > On 06/16/2010 05:47 AM, Steven Schveighoffer wrote: >> On Tue, 15 Jun 2010 22:23:15 -0400, Andrei Alexandrescu >> <SeeWebsiteForEmail@erdani.org> wrote: >> >>> bearophile wrote: >>>> I have counted about 200 usages of std.contracts.enforce() inside >>>> Phobos. Can you tell me what's the purpose of enforce() in a language >>>> that has built-in Contract Programming? >>> >>> You need to read TDPL for that :o). >>> >>>> And what are the purposes of std.contracts.AssumeSorted()? Is it >>>> useful for something? >>> >>> AssumeSorted was an experiment. I think it has drawbacks that I don't >>> know how to address, so I'll retire it. >> >> Hm... what are the drawbacks (besides it not being enforced)? I thought >> it was a good solution. > > Sorry I took so long (over one month!) to reply to this. I've delayed the reply to the point when it could be integrated within the upcoming thread about improving std.algorithm.find. > > The problem with AssumeSorted is that generally predicates in D (and also in most other languages) are not easy to compare. Let's first recall AssumSorted's definition. It's just a wrapper: > > /** > Passes the type system the information that $(D range) is already > sorted by predicate $(D pred). No checking is performed; debug builds > may insert checks randomly. To insert a check, see $(XREF algorithm, > isSorted). > */ > struct AssumeSorted(Range, alias pred = "a < b") > { > /// Alias for $(D Range). > alias Range AssumeSorted; > /// The passed-in range. > Range assumeSorted; > /// The sorting predicate. > alias pred assumeSortedBy; > } > > /// Ditto > AssumeSorted!(Range, pred) assumeSorted(alias pred = "a < b", Range) > (Range r) > { > AssumeSorted!(Range, pred) result; > result.assumeSorted = r; > return result; > } > > The recommended way to use the facility is: > > int[] a = [ -1, 0, 1, 2, 3, 4, 5 ]; > assert(find(assumeSorted(a), 3) == [ 3, 4, 5 ]); > > find() uses simple means to detect that its first argument has type AssumeSorted and takes advantage of that when searching (specifically by doing binary search). > > So far so good. The problem ensues when we want to make sure that the sorting predicate is in sync with the search predicate. For example, if the search predicate is "==" then it's okay to use "<" or ">" as a sorting predicate. But searching for "a.zip == b.zip" in a range sorted by "a.name < b.name" is not okay. > > If predicates were all expressed as strings, probably some string manipulation could be done to see whether they are compatible. But as things stand, assertSorted has quite limited power. Just thinking out loud here, couldn't you use the predicate already in AssumeSorted? I mean, if you're going to pass AssumeSorted into find, you don't want to also specify the predicate as then the range just becomes a standard range. There must be some kind of way to use template constraints to kill the predicate arg to find when the range is an AssumeSorted struct. If not, there should be. -Steve | |||
July 19, 2010 Re: enforce()? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 07/19/2010 06:36 AM, Steven Schveighoffer wrote:
> Just thinking out loud here, couldn't you use the predicate already in
> AssumeSorted? I mean, if you're going to pass AssumeSorted into find,
> you don't want to also specify the predicate as then the range just
> becomes a standard range.
>
> There must be some kind of way to use template constraints to kill the
> predicate arg to find when the range is an AssumeSorted struct. If not,
> there should be.
That's a good idea. The find predicate that could be derived from AssumeSorted's predicate pred would be !pred(a, b) && !pred(b, a).
Thanks, Steve.
Andrei
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply