Why Strings as Classes?

Nick Sabalausky a at a.a
Tue Aug 26 18:35:26 PDT 2008


"superdan" <super at dan.org> wrote in message 
news:g921nb$2qqq$1 at digitalmars.com...
> Nick Sabalausky Wrote:
>
>> "Denis Koroskin" <2korden at gmail.com> wrote in message
>> news:op.ugie28dxo7cclz at proton.creatstudio.intranet...
>> > On Tue, 26 Aug 2008 23:29:33 +0400, superdan <super at dan.org> wrote:
>> > [snip]
>> >>> The D spec certainly doesn't make any guarantees about
>> >>> the time/memory complexity of opIndex; it's up to the implementing 
>> >>> class
>> >>> to do so.
>> >>
>> >> it don't indeed. it should. that's a problem with the spec.
>> >>
>> >
>> > I agree. You can't rely on function invokation, i.e. the following 
>> > might
>> > be slow as death:
>> >
>> > auto n = collection.at(i);
>> > auto len = collection.length();
>> >
>> > but index operations and properties getters should be real-time and 
>> > have
>> > O(1) complexity by design.
>> >
>> > auto n = collection[i];
>> > auto len = collection.length;
>>
>> I disagree. That strategy strikes me as a very clear example of breaking
>> encapsulation by having implementation details dictate certain aspects of
>> the API. At the very least, that will make the API overly rigid, 
>> hindering
>> future changes that could otherwise have been non-breaking,
>> behind-the-scenes changes.
>
> take this:
>
> auto c = new Customer;
> c.loadCustomerInfo("123-12-1234");
>
> that's all cool. there's no performance guarantee other than some best 
> effort kinda thing `we won't sabotage things'. if you come with faster or 
> slower methods to load customers, no problem. coz noone assumes any.
>
> now take sort. sort says. my input is a range that supports indexing and 
> swapping independent of the range size. if you don't have that just let me 
> know and i'll use a totally different method. just don't pretend.
>

Choosing a sort method is a separate task from the actual sorting. Any sort 
that expects to be able to index will still work correctly if given a 
collection that has O(n) or worse indexing, just as it will still work 
correctly if given an O(n) or worse comparison delegate. It's up to the 
caller of the sort function to know that an O(n log n) sort (for instance) 
is only O(n log n) if the indexing and comparison are both O(1). And then 
it's up to them to decide if they still want to send it a linked list or a 
complex comparison. The sort shouldn't crap out at compile-time (or runtime) 
just because some novice might not know that doing a generalized bubble sort 
on a linked list scales poorly.

If you want automatic choosing of an appropriate sort algorithm (which is 
certainly a good thing to have), then that can be done at a separate, 
optional, level of abstraction using function overloading, template 
specialization, RTTI, etc. That way you're not imposing arbitrary 
restrictions on anyone.

> with that indexing and swapping complexity ain't implementation detail. 
> they're part of the spec. guess stepanov's main contribution was to 
> clarify that.
>

When I called indexing an implementation detail, I was referring to the 
collection itself. The method of indexing *is* an implementation detail of 
the collection. It should not be considered an implementation detail of the 
sort algorithm since it's encapsulated in the collection and thus hidden 
away from the sort algorithm. If you make a rule that collections with cheap 
indexing are indexed via opIndex and collections with expensive indexing are 
indexed via a function, then you've just defined the API in terms of the 
collection's implementation (and introduced an unnecessary inconsistency 
into the API).

If a sort function is desired that only accepts collections with O(1) 
indexing, then that can be accomplished at a higher level of abstraction 
(using function overloading, RTTI, etc.) without getting in the way when 
such a guarantee is not needed.

>> For realtime code, I can see the benefit to what you're saying. Although 
>> in
>> many cases only part of a program needs to be realtime, and for the rest 
>> of
>> the program's code I'd hate to have to sacrifice the encapsulation 
>> benefits.
>
> realtime has nothin' to do with it.

For code that needs to run in realtime, I agree with Denis Koroskin that it 
could be helpful to be able to look at a piece of code and have some sort of 
guarantee that there is no behind-the-scenes overloading going on that is 
any more complex than the operators' default behaviors. But for code that 
doesn't need to finish within a maximum amount of time, that becomes less 
important and the encapsulation/syntactic-consistency gained from the use of 
such things becomes a more worthy pursuit. That's what I was saying about 
realtime.

> encapsulation ain't broken by making complexity part of the reqs. any more 
> than any req ain't breakin' encapsulation. if it looks like a problem then 
> encapsulation was misdesigned and needs change.
>
> case in point. all containers should provide 'nth' say is it's o(n) or 
> better. then there's a subclass of container that is indexed_container. 
> that provides opIndex and says it's o(log n) or better. it also provides 
> 'nth' by just forwarding to opIndex. faster than o(n) ain't a problem.
>
> but forcing a list to blurt something for opIndex - that's just bad 
> design.

I agree that not all collections should implement an opIndex. Anything 
without a natural sequence or mapping should lack opIndex (such as a tree or 
graph). But forcing the user of a collection that *does* have a natural 
sequence (like a linked list) to use function-call-syntax instead of 
standard indexing-syntax just because the collection is implemented in a way 
that causes indexing to be less scalable than other collections - that's bad 
design.

The way I see it, "group[n]" means "Get the nth element of group". Not "Get 
the element at location group.ptr + (n * sizeof(group_base_type)) or 
something else that's just as scalable." In plain C, those are one and the 
same. But when you start talking about generic collections, encapsulation 
and interface versus implementation, they are very different: the former is 
interface, the latter is implementation. 





More information about the Digitalmars-d mailing list