View mode: basic / threaded / horizontal-split · Log in · Help
July 16, 2012
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Re: Why is std.algorithm so complicated to use?
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
Next ›   Last »
10 11 12 13 14
Top | Discussion index | About this forum | D home