equivariant functions
Denis Koroskin
2korden at gmail.com
Wed Oct 15 03:02:28 PDT 2008
On Wed, 15 Oct 2008 09:51:59 +0400, Bill Baxter <wbaxter at gmail.com> wrote:
>> inout(C) foo(inout(C) c, inout(B) function(inout(A) a) fn);
>>
>> In the last example, constancy of return value matches constancy of
>> input
>> parameter.
>
> .. and inout(B), inout(A) there have that same constancy? Or is their
> constancy unrelated?
>
> --bb
To answer this I need to take a use case and look at a concrete function
implementation:
Case #1
-------
void testInoutFunction(inout(char[]) function(inout(char)[]) fn)
{
char[] a1 = "hello".dup;
a1 = fn(a1);
writefln(a1);
const(char)[] a2 = "hello";
a2 = b(a2);
writefln(a2);
invariant(char)[] a3 = "hello";
a3 = b(a3);
writefln(a3);
}
inout(char)[] foo(inout(char)[] a);
testInoutFunction(&foo);
I think this is a valid use case. Note that testInoutFunction doesn't take
any inout() params and the inout() constancy expantion doesn't take place
at the call-time, i.e.
void testInoutFunction(inout(char[]) function(inout(char)[]) fn)
doesn't transform into one of these:
void testInoutFunction(char[] function(char[]) fn);
void testInoutFunction(const(char[]) function(const(char)[]) fn);
void testInoutFunction(invariant(char[]) function(invariant(char)[]) fn);
Adding an additional parameter doesn't change a bit (function shouldn't
change its behaviour drastically given additional parameter):
inout(char)[] testInoutFunction(inout(char)[] a, inout(char[])
function(inout(char)[]) fn)
{
testInoutFunction(fn); // call zero-arg version
// do something with a
return a[1..$];
}
So a rule here is that inout() constancy expansion doesn't take place for
delegate and function pointers.
Case #2
-------
In this case, inout() constancy expantion does take place on delegates and
function pointers. Let's see if it is useful:
char[] foo1(char[] a);
invariant(char)[] foo2(invariant(char)[] a);
void testInoutFunction(inout(char[]) function(inout(char)[]) fn);
testInoutFunction(&foo1); // assume, we wanna call like this
testInoutFunction(&foo2); // and like this
Given these uses cases, what assumptions can testInoutFunction make and
actions take?
void testInoutFunction(inout(char[]) function(inout(char)[]) fn)
{
char[] a = "hello".dup;
a = fn(a); // invalid, violates foo2 typechecking
invariant(char)[] b = "hello";
b = fn(b); // invalid, violates foo1 typechecking
const(char)[] c = "hello";
c = fn(c); // ok
}
See, testInoutFunction's actually can't do much. In fact it is no
different from
void testInoutFunction(const(char)[] function(char(char)[]) fn);
So the second use case is in fact incorrect and should not be allowed.
Back to the original example:
> inout(C) foo(inout(C) c, inout(B) function(inout(A) a) fn);
Type of return value here depends on type of first argument (c), type of
fn doesn't vary, it is always the same.
More information about the Digitalmars-d
mailing list