January 10, 2014
On Fri, Jan 10, 2014 at 07:32:23PM +0000, Atila Neves wrote:
> I agree that std.algorithm is better than <algorithm>, but let's not pretend that C++11 never happened (that happens from time to time on this forum). The modern C++ version isn't _that_ different:
> 
>     for(auto& blah: myContainer) { //for-loop condition on one line
>         doSomething(blah->impl->myDataField);
>         if(find(blah->impl->mySubContainer.begin(),
> blah->impl->mySubContainer.end(), key) ==
> blah->impl->mySubContainer.end()) {
>             //decltype is way shorter than std::vector<MyType<Blah>>
>             //and change-resistant
>             return decltype(blah)::iterator{};
>         }
>      }
> 
> Again, I think that std.algorithm is better and that passing a pair of iterators to everything when 99.9% of the time they'll be begin() and end() anyway is a massive PITA. I'm a D convert. Nobody here makes a point of posting D1 code and IMHO there's also no point in posting C++98 / C++2003 code.

You're right, my C++ is outdated. I'm not exactly motivated to keep up with the latest version of C++, though, since D is far better, and my day job is primarily with C, and what C++ code we have is still in the dark ages of C++2003 (or perhaps *shudder* even C++98), and is unlikely to be upgraded to C++11 anytime in the foreseeable future.


[...]
> >	// You can't even write the for-loop conditions in a single
> >	// line!
> >	for (std::vector<MyType<Blah> >::iterator it =
> >		myContainer.start();
> >		it != myContainer.end();
> >		it++)
> >	{
> >		// What's with this (*smartPtr)->x nonsense everywhere?
> >		doSomething((*((*it)->impl)->myDataField);
> >
> >		// What, I can't even write a simple X != Y if-condition
> >		// in a single line?! Not to mention the silly
> >		// redundancy of having to write out the entire chain of
> >		// dereferences to exactly the same object twice.
> >		if (find((*(*it)->impl)->mySubContainer, key) ==
> >			(*(*it)->impl)->mySubContainer.end())
> >		{
> >			// How I long for D's .init!
> >			std::vector<MyTypeBlah> >::iterator empty;
> >			return empty;
> >		}
> >	}


T
-- 
Heuristics are bug-ridden by definition. If they didn't have bugs, they'd be algorithms.
January 10, 2014
On Friday, 10 January 2014 at 19:32:24 UTC, Atila Neves wrote:
> I agree that std.algorithm is better than <algorithm>, but let's not pretend that C++11 never happened (that happens from time to time on this forum). The modern C++ version isn't _that_ different:
>
>     for(auto& blah: myContainer) { //for-loop condition on one line
>         doSomething(blah->impl->myDataField);
>         if(find(blah->impl->mySubContainer.begin(), blah->impl->mySubContainer.end(), key) == blah->impl->mySubContainer.end()) {
>             //decltype is way shorter than std::vector<MyType<Blah>>
>             //and change-resistant
>             return decltype(blah)::iterator{};
>         }
>      }
>
> Again, I think that std.algorithm is better and that passing a pair of iterators to everything when 99.9% of the time they'll be begin() and end() anyway is a massive PITA. I'm a D convert. Nobody here makes a point of posting D1 code and IMHO there's also no point in posting C++98 / C++2003 code.
>
> Atila
>

In our company we have people working with Visual Studio 2005, so when I am working on common code I still have to avoid any new C++ features! I am 'really' trying to get them to upgrade!

Craig

January 11, 2014
On Fri, Jan 10, 2014 at 04:03:53AM +0100, Timon Gehr wrote:
> On 01/10/2014 02:19 AM, Brad Anderson wrote:
> >On Friday, 10 January 2014 at 00:52:27 UTC, H. S. Teoh wrote:
> >>
> >><snip>
> >>
> >>So to summarize:
> >>(1) use sig constraints to define the scope of an overload; and
> >>(2) use static if inside the function body (or template body) to
> >>enforce type requirements within that scope.
> >>
> >>This solves the problem of needing the compiler to somehow read your mind and figure out exactly which of the 56 overloads of find() you intended to match but failed to.
> >>
> >>
> >>T
> >
> >Ok, you've convinced me. I still think highlighting which constraints failed should happen but for well implemented modules like those in the standard library your approach offers even more helpful and tight error messages.
> 
> static assert is not a good way to implement custom error messages because it also changes the behaviour of the declaration.

It's not just about custom error messages; it's about picking up a particular template signature even when you don't have an implementation for it, because logically speaking, your set of overloads *should* pick up all such instantiations to begin with. This is why I differentiated between the scope of a template, vs. the actual available overloads.

With sig constraints, you're declining instantiations that don't satisfy certain conditions; I'm arguing that sometimes you *want* to accept instantiations that you currently don't implement (yet), because it falls under the logical scope of what you intend to handle; you just haven't gotten around to actually implementing it yet.


T

-- 
Stop staring at me like that! It's offens... no, you'll hurt your eyes!
January 12, 2014
On Friday, 10 January 2014 at 16:54:30 UTC, Brad Anderson wrote:
> Updating the website is almost strictly Andrei's domain so he should be able to do it independently of the release process (though integrating updating the website with the release process should probably happen at some point).  ddox was merged with the tools repo 6 months ago and dlang.org 3 months ago so as far as I know all that's left is for Andrei to generate the pages and upload them as 2.065 is completed.

Andrew should have access too as any release-related updates are supposed to be moved into domain of release manager.
January 12, 2014
Your proposal is awesome, this should be in phobos style guide imo.
January 13, 2014
On Saturday, 11 January 2014 at 05:45:41 UTC, H. S. Teoh wrote:
> It's not just about custom error messages; it's about picking up a
> particular template signature even when you don't have an implementation
> for it, because logically speaking, your set of overloads *should* pick
> up all such instantiations to begin with. This is why I differentiated
> between the scope of a template, vs. the actual available overloads.
>
> With sig constraints, you're declining instantiations that don't satisfy
> certain conditions; I'm arguing that sometimes you *want* to accept
> instantiations that you currently don't implement (yet), because it
> falls under the logical scope of what you intend to handle; you just
> haven't gotten around to actually implementing it yet.

There is nothing stopping you from writing constraints that accept currently unimplemented instantiations. There is no difference here with the two approaches.
January 13, 2014
On Fri, 10 Jan 2014 16:30:12 -0000, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> On 1/10/14 6:07 AM, Regan Heath wrote:
>> On Fri, 10 Jan 2014 08:16:53 -0000, Andrei Alexandrescu
>> <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> On 1/9/14 11:56 PM, Jacob Carlborg wrote:
>>>> On 2014-01-10 02:34, Manu wrote:
>>>>
>>>>> Or just alias the functions useful for string processing...
>>>>
>>>> I agree. It already has some aliases, converting to lower and uppercase.
>>>
>>> I wouldn't want to get to the point where many functions have 2-3 names.
>>
>> This is only a problem if they are all in the same sphere of concern..
>> by that I mean if you're looking for string functions and you find 2
>> names for the same function this would be wrong/confusing/pointless.
>> But, if you have one name in the string category and one in the range
>> category and they were both the same function underneath I don't see
>> this as the "same" problem, right?
>
> The way I see it one learns a name for an algorithm (low cognitive load) and then uses it everywhere. This is not Go.

Sure.  But, lets take an example: std.algorithm.canFind is more or less what you might call std.string.contains (which does not exist - instead we'd use indexOf != -1.. I think).

What is the harm in having an alias in std.string called contains which simply calls std.algorithm.canFind?

Sure, it opens the door to someone using both canFind and contains on strings in their code.  So what?  Use of contains is more likely/intuitive for string related code, but both are intelligible.  canFind will be more likely in generic code, where you would think of that generic algorithm name.

It seems to me that people think of algorithms by different names in different contexts.  In the context of strings "contains" would make the most intuitive sense to the most people.

Side-issue.. from std.algorithm:

bool canFind(alias pred = "a == b", R, E)(R haystack, E needle) if (is(typeof(find!pred(haystack, needle))));
Returns true if and only if **value** can be found in range. Performs Ο(needle.length) evaluations of pred.

What is **value** shouldn't that be needle?

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
January 13, 2014
On 2014-01-13 13:53, Regan Heath wrote:

> Sure.  But, lets take an example: std.algorithm.canFind is more or less
> what you might call std.string.contains (which does not exist - instead
> we'd use indexOf != -1.. I think).

I think "contains" is a way better name. That's what most other languages use, I think.

-- 
/Jacob Carlborg
January 17, 2014
"Brad Anderson" <eco@gnuk.net> writes:

> On Friday, 10 January 2014 at 00:56:36 UTC, Manu wrote:
>> The D docs are pretty terrible, they don't do much to help you find what
>> you're looking for.
>> You have a massive block of function names at the top of the page, you have
>> to carefully scan through one by one, hoping that it's named something
>> obvious that will stand out to you, and in the event it doesn't have a
>> helper function, you need to work out the proper sequence of
>> algorithm/range/whatever operations to do what you want (and then repeat
>> the process finding the small parts you need across a bunch of modules).
>
> DDox improves on this a bit by giving a table with brief descriptions right up top: http://vibed.org/temp/dlang.org/library/std/string.html
>
> Still plenty left to do though.

This looks much nicer as a summary.  I would personally prefer to have the details all on the same page below, rather than having to jump to a new page for each different function.

Still, thumbs up!

Jerry
January 22, 2014
On 1/13/14 4:53 AM, Regan Heath wrote:
> On Fri, 10 Jan 2014 16:30:12 -0000, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>> The way I see it one learns a name for an algorithm (low cognitive
>> load) and then uses it everywhere. This is not Go.
>
> Sure.  But, lets take an example: std.algorithm.canFind is more or less
> what you might call std.string.contains (which does not exist - instead
> we'd use indexOf != -1.. I think).

Well there's no perfection in this world :o).

> What is the harm in having an alias in std.string called contains which
> simply calls std.algorithm.canFind?

I think you can answer that for yourself. Just take the approach to its logical conclusion.

> Sure, it opens the door to someone using both canFind and contains on
> strings in their code.  So what?  Use of contains is more
> likely/intuitive for string related code, but both are intelligible.
> canFind will be more likely in generic code, where you would think of
> that generic algorithm name.
>
> It seems to me that people think of algorithms by different names in
> different contexts.  In the context of strings "contains" would make the
> most intuitive sense to the most people.

I agree that good names are difficult to find. I think you'd have a hard time with a "the more the merrier" stance.

> Side-issue.. from std.algorithm:
>
> bool canFind(alias pred = "a == b", R, E)(R haystack, E needle) if
> (is(typeof(find!pred(haystack, needle))));
> Returns true if and only if **value** can be found in range. Performs
> Ο(needle.length) evaluations of pred.
>
> What is **value** shouldn't that be needle?

Please file a bug or pull request. Thanks!


Andrei