On 10/28/12 8:28 AM, Peter Alexander wrote:
On Saturday, 27 October 2012 at 13:06:09 UTC, Andrei Alexandrescu wrote:
On 10/27/12 8:23 AM, Peter Alexander wrote:
Retrofitting some sort of structure to templates will be a Herculean
task, but I think it has to happen. It is clear to me that the
development process we use now (write the template, try a few
instantiations, pray) is unsustainable beyond simple templates.

It's not clear to me at all. The mechanism works very well and is more
expressive than alternatives used by other languages.

I'm not sure I can agree it works well.

For example, here's what happened with bug 8900 mentioned in the OP:

std.range.zip creates a Zip object, which has a Tuple member. Tuple has
a toString function, which calls formatElement, which calls formatValue,
which calls formatRange, which (when there's a range of characters) has
a code path for right-aligning the range. To right-align the range it
needs to call walkLength.

The problem arises when you zip an infinite range of characters e.g.
repeat('a').

This proves nothing at all. So this has to do with invoking walkLength against an infinite range. At the time I wrote walkLength, infinite ranges were an experimental notion that I was ready to remove if there wasn't enough practical support for it. So I didn't even think of the connection, which means the restriction wouldn't have likely made it into the definition of walkLength regardless of the formalism used.

Before pull request 880, walkLength accepted infinite ranges and just
returned size_t.max. Pull request 880 added a constraint to walkLength
to stop it accepting infinite ranges. Suddenly, you cannot zip a range
of infinite chars because of a seemingly unrelated change.

The connection is obvious and is independent qualitatively of other cases of "if you change A and B uses it, B may change in behavior too". It's a pattern old as dust in programming.

Anyway, I'm not sure whether this is clear as day: expressing constraints as Booleans or "C++ concepts" style or Gangnam style doesn't influence this case in the least.

This would have been caught if there was a unit test, but there wasn't,
and as Dijkstra says, "testing can be a very effective way to show the
presence of bugs, but it is hopelessly inadequate for showing their
absence." There are probably other places that are broken, and many
changes in the future will just introduce more bugs without tests.

Maybe we have different standards for "working well", but to me at
least, this isn't what "working well" looks like.

Working well in this case would look like this:

- The person that put together pull request 880 would add the template
constraint to walkLength.
- On the next compile he would get this error: "formatRange potentially
calls walkLength with an infinite range." (or something along those lines).
- The person fixes formatRange, and all is well.

No need for unit tests, it's all caught as soon as possible without need
for instantiation.

But this works today and has nothing to do with "retrofitting structure to templates". Nothing. Nothing.


Andrei

Reply via email to