July 16, 2012
On 2012-07-16 09:18, Jonathan M Davis wrote:

> We do have InPlace in function names when one version of a function operates
> in place and another doesn't, but we haven't generally done that on functions
> which only have one version, and I don't expect that to change now (at least
> not for existing functions).

Yes, that's good. But we can always add that to the documentation. There can also be some general documentation about this on the top of the std.algorithm module. Something like:

"No function operates in place unless it explicitly says so in the documentation or if its name has the 'inPlace' suffix."

> In any case, _most_ range-based functions _don't_ operate in place, but it's
> certainly true that the ones that do should make that clear in their
> documentation.
>
> remove is a bit of a special case, however, in that it does the changes in
> place but doesn't take a ref, so while the return value is shortened to not
> include the removed elements, the original is just as long as it was before
> (which is useful in cases where you want to then set the elements at the end),
> and you end up with something that's sort of in place and sort of not.
> Regardless, remove is confusing enough to most people (just like erase in C++)
> that it's documentation needs to be very clear, but I don't know how good it
> is or isn't. Given the difficulty of explaining it properly and Merhdad's
> confusion, it probably stands to be improved.

Just _because_ of how "remove" works in std.algorithm and "erase" in C++, I though "sort" behaved similar.

-- 
/Jacob Carlborg


July 16, 2012
On Monday, July 16, 2012 10:08:11 Jacob Carlborg wrote:
> Just _because_ of how "remove" works in std.algorithm and "erase" in C++, I though "sort" behaved similar.

Well, it does in that it sorts in place and returns the result, but the result and the original are more in line with one another then they are with remove, since they're both sorted rather than having their lengths differ like they do with remove (though the result of sort is usually a different type from the original range, unlike with remove). But I don't dispute that the documentation needs improvement. It probably does. I haven't read through much of it recently, and in many cases, I probably already fully understand it anyway, so I'm not a good judge of how good it is.

- Jonathan M Davis
July 16, 2012
On 10/07/12 16:59, Andrei Alexandrescu wrote:
> On 7/10/12 9:59 AM, H. S. Teoh wrote:
>> On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote:
>>> On 7/10/12 2:50 AM, Jacob Carlborg wrote:
>>>> On 2012-07-09 22:16, Andrei Alexandrescu wrote:
>>>>
>>>>> So foo is a range of strings, because each element of it is a
>>>>> string.  Then you want to chain a range of strings with a string,
>>>>> which is a range of dchar. That doesn't work, and I agree the error
>>>>> message should be more informative.
>>>>
>>>> Is that by design or something that can be fixed?
>>>
>>> We can arrange things in the library that a custom message is issued,
>>> or in the compiler to do it once for all.
>>
>> Please don't do it in the compiler. Custom messages should be in the
>> library. Tying the compiler to phobos is a bad idea; druntime should be
>> the only dependency.
>
> The idea there being that the compiler could give good details about
> what part of a complex constraint has failed.

However the compiler doesn't know which constraint was supposed to pass.
If it is lucky enough to only have one template, it can do it, but if it has:
template1 if (A && B)
template2 if (C && D)
template3 if ( (E || F) && G)

should it print:
foo.d(99): Error: no matching template
foo.d(10):    constraint failed: A
foo.d(28):    constraint failed: D
foo.d(57):    constraint failed: (E || F)
?
Could be a very long list, if there are many templates.

Determining the minimal list of constraints seems like a nice application for BDDs...



July 16, 2012
On 07/16/2012 05:22 PM, Don Clugston wrote:
> On 10/07/12 16:59, Andrei Alexandrescu wrote:
>> On 7/10/12 9:59 AM, H. S. Teoh wrote:
>>> On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote:
>>>> On 7/10/12 2:50 AM, Jacob Carlborg wrote:
>>>>> On 2012-07-09 22:16, Andrei Alexandrescu wrote:
>>>>>
>>>>>> So foo is a range of strings, because each element of it is a
>>>>>> string. Then you want to chain a range of strings with a string,
>>>>>> which is a range of dchar. That doesn't work, and I agree the error
>>>>>> message should be more informative.
>>>>>
>>>>> Is that by design or something that can be fixed?
>>>>
>>>> We can arrange things in the library that a custom message is issued,
>>>> or in the compiler to do it once for all.
>>>
>>> Please don't do it in the compiler. Custom messages should be in the
>>> library. Tying the compiler to phobos is a bad idea; druntime should be
>>> the only dependency.
>>
>> The idea there being that the compiler could give good details about
>> what part of a complex constraint has failed.
>
> However the compiler doesn't know which constraint was supposed to pass.
> If it is lucky enough to only have one template, it can do it, but if it
> has:
> template1 if (A && B)
> template2 if (C && D)
> template3 if ( (E || F) && G)
>
> should it print:
> foo.d(99): Error: no matching template
> foo.d(10): constraint failed: A
> foo.d(28): constraint failed: D
> foo.d(57): constraint failed: (E || F)
> ?
> Could be a very long list, if there are many templates.
>
> Determining the minimal list of constraints seems like a nice
> application for BDDs...
>

Well, are template constraints likely to contain a lot of redundant information?
July 16, 2012
On Monday, July 16, 2012 22:53:36 Timon Gehr wrote:
> On 07/16/2012 05:22 PM, Don Clugston wrote:
> > On 10/07/12 16:59, Andrei Alexandrescu wrote:
> >> On 7/10/12 9:59 AM, H. S. Teoh wrote:
> >>> On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote:
> >>>> On 7/10/12 2:50 AM, Jacob Carlborg wrote:
> >>>>> On 2012-07-09 22:16, Andrei Alexandrescu wrote:
> >>>>>> So foo is a range of strings, because each element of it is a string. Then you want to chain a range of strings with a string, which is a range of dchar. That doesn't work, and I agree the error message should be more informative.
> >>>>> 
> >>>>> Is that by design or something that can be fixed?
> >>>> 
> >>>> We can arrange things in the library that a custom message is issued, or in the compiler to do it once for all.
> >>> 
> >>> Please don't do it in the compiler. Custom messages should be in the library. Tying the compiler to phobos is a bad idea; druntime should be the only dependency.
> >> 
> >> The idea there being that the compiler could give good details about what part of a complex constraint has failed.
> > 
> > However the compiler doesn't know which constraint was supposed to pass.
> > If it is lucky enough to only have one template, it can do it, but if it
> > has:
> > template1 if (A && B)
> > template2 if (C && D)
> > template3 if ( (E || F) && G)
> > 
> > should it print:
> > foo.d(99): Error: no matching template
> > foo.d(10): constraint failed: A
> > foo.d(28): constraint failed: D
> > foo.d(57): constraint failed: (E || F)
> > ?
> > Could be a very long list, if there are many templates.
> > 
> > Determining the minimal list of constraints seems like a nice application for BDDs...
> 
> Well, are template constraints likely to contain a lot of redundant information?

They're likely to contain a lot of stuff negation of other template constraints. For instance,

auto func(R)(R range)
    if(isForwardRange!R && !isBidirectionalRange!R)
{}

auto func(R)(R range)
    if(isBidirectionalRange!R)
{}

If you have a function with very many overloads, it can be very easy to end up with a bunch of different template constraints which are all slightly different. std.algorithm.find is a prime example of this.

But as much as it may be a bit overwhelming to print every failed constraint, without doing that, you _have_ to go to the source code to see what they were, which isn't all that great (especially if it's not in a library that you wrote and don't normally look at the source of - e.g. Phobos).

On the other hand, a failed instantiation of std.conv.to would print out reams of failed constraints...

Getting the compiler to print out the constraints come out to if combined could be very useful, but in some ways, it would be worse, since it would generally result in one big constraint with a bunch of ||s between them - particularly since it can't understand how the various templates involved work (e.g. isForwardRange vs isBidirectionalRange). I've considered taking up the practice of putting all template function overloads inside of a single template which has a constraint for them all (with each individual function still having its own of course). The programmer would likely do a better job at simplifying it than the compiler, but often you can't do that, especially when different overloads require drastically different stuff (e.g. the constraints on needle often depend on the constraints on haystack for find). So, in a lot of cases, you'd just end up with a really nasty looking and hard to understand template constraint.

If it weren't for the case of std.conv, I'd argue for just displaying all of the failed constraints, but I don't know.

- Jonathan M Davis
July 17, 2012
Jonathan M Davis , dans le message (digitalmars.D:172564), a écrit :
> They're likely to contain a lot of stuff negation of other template constraints. For instance,
> 
> auto func(R)(R range)
>     if(isForwardRange!R && !isBidirectionalRange!R)
> {}
> 
> auto func(R)(R range)
>     if(isBidirectionalRange!R)
> {}
> 
> If you have a function with very many overloads, it can be very easy to end up with a bunch of different template constraints which are all slightly different. std.algorithm.find is a prime example of this.
> 
> But as much as it may be a bit overwhelming to print every failed constraint, without doing that, you _have_ to go to the source code to see what they were, which isn't all that great (especially if it's not in a library that you wrote and don't normally look at the source of - e.g. Phobos).
> 
> On the other hand, a failed instantiation of std.conv.to would print out reams of failed constraints...

The compiler could stop displaying at about 10 failed constrains and claim there are more. It would be best if it could figure out what are the 10 most interesting constrains, but that may not be easy!

Then it's up to the programmer to use template constrains, static if and eventually pragma, to allow the compiler to display pleasant error messages. The langage could help you by allowing you to make hiearchized template constrains, but static if is a fine solution most of the time.
July 17, 2012
On Tuesday, July 17, 2012 11:47:07 Christophe Travert wrote:
> The compiler could stop displaying at about 10 failed constrains and claim there are more. It would be best if it could figure out what are the 10 most interesting constrains, but that may not be easy!

That seems like a good idea.

- Jonathan M Davis
4 5 6 7 8 9 10 11 12 13 14
Next ›   Last »