Command–query separation principle [re: @mustuse as a function attribute]
mw
mingwu at gmail.com
Wed Oct 19 18:16:39 UTC 2022
On Wednesday, 19 October 2022 at 18:04:54 UTC, Paul Backus wrote:
> On Wednesday, 19 October 2022 at 17:40:00 UTC, mw wrote:
>> That's because you still consider the @mustuse attribute on
>> each class level individually, if you think about the global
>> system analysis as a whole, it will work, and consistently.
>> Yes, what I proposed is transitive closure:
>>
>> /--------Base------\
>> | | |
>> Derived1 Derive2 Derive3
>>
>> If the programmer only manually marked Derive3.remove() as
>> @mustuse, everything else (Base, Derived1 Derive2
>> Derive3)'s .remove() method will become @mustuse (as seen by
>> the compiler internally).
>
> The fundamental problem with this on a conceptual level
> (leaving aside implementation issues) is that it completely
> breaks modularity.
>
> Suppose we have the following module layout:
>
> --- base.d
> module base;
>
> class Base {
> int fun() {...}
> }
>
> void doStuff(Base b)
> {
> import std.stdio;
>
> writeln("Calling b.fun");
> b.fun(); // ok - Base.fun is not @mustuse
> }
>
> --- derived.d
> module derived;
>
> import base;
>
> class Derived : Base {
> int fun() {...}
> }
> ---
>
> If I now decide to add @mustuse to Derived.fun, in the
> "derived" module, and we apply your proposed global analysis,
> this will cause a compilation error in the "doStuff" function
> in the "base" module!
>
> Note that the "base" module does not have any explicit
> dependency on the "derived" module. It does not import it, or
> otherwise refer to it in any way. In the real world, these two
> modules might even be in separate dub packages.
Yes, I know that. But this in my view is still a compiler
implementation issue: even in separate dub packages, as long as
the compiler visit that package, it need to propagate the
attribute to that package's relevant class.
More information about the Digitalmars-d
mailing list