On 02/04/12 02:03, Timon Gehr wrote:
> On 02/03/2012 11:08 AM, Artur Skawina wrote:
>> On 02/03/12 00:20, Jonathan M Davis wrote:
>>> in is pointless on value types. All it does is make the function parameter
>>> const, which really doesn't do much for you, and in some instances, is
>>> really
>>> annoying. Personally, I see no point in using in unless the parameter is a
>>> reference type, and even then, it's often a bad idea with reference types,
>>> because in is really const scope, and the scope is problematic if you want
>>> to
>>> return anything from that variable. It's particularly problematic with
>>> arrays,
>>> since it's frequently desirable to return slices of them, and scope (and
>>> therefore in) would prevent that. It's useful in some instances
>>> (particularly
>>> with delegates), but I'd use in _very_ sparingly. It's almost always more
>>> trouble than it's worth IMHO.
>>
>> BTW, scope should have been the default for *all* reference type function
>> arguments, with an explicit modifier, say "esc", required to let the thing
>> escape. It's an all-or-nothing thing, just like immutable strings - not using
>> it everywhere is painful, but once you switch everything over you get the
>> benefits.
>
> I totally agree. Most function arguments are not escaped. However, it is nice
> that the shortest storage class, 'in', implies scope.
There are currently two problems with using "in": a) the one mentioned, where
using in/scope means you can't (or shouldn't be able to) pass the thing to
another
function w/o scope marked args, and b) "in" implies "const", which is a problem
because you may want to reassign the argument - a perfectly safe thing to do.
With "const" itself you can use parentheses to limit its scope to not include
the reference itself; the problematic case is the builtin "string" alias, ie
"int f(in string s);" would have to allow reassigning 's' inside the function.
Semi-related quiz:
immutable(char)[] a = "a";
const (char)[] b = "b";
auto aa = a ~ a;
auto bb = b ~ b;
auto ab = a ~ b;
writeln("aa: ", typeid(aa), " bb: ", typeid(bb), " ab: ", typeid(ab));
And the question is: How many people, who have not already been bitten by this,
will give the correct answer to: "What will this program print?"?
There should have been another class, in addition to immutable/const, say
"uniq".
For cases where an expression results in new unique objects. This class
implicitly
converts to any of const/immutable and mutates to the new type. IOW
string a = "a";
char[] b = "b";
auto c = a ~ b; // typeid(c) == (uniq(char)[])
string d = c; // Fine, "c" is unique and can be safely treated as a string.
// But, from now on, "c" is (immutable(char)[]) so:
char[] e = c; // Fails.
// And the other way:
auto f = a ~ b;
char[] g = f; // OK
string h = f // Fails, as f is now a (char[])
No need for unsafe-looking casts, just so that the compiler accepts perfectly
safe
code, like: "string c = ab;", which would currently fail if used in the above
quiz,
and has to be written as "string c = cast(string)ab;". [1]
artur
[1] Using a helper template is not different from adding a comment, it only
serves
to document /why/ the programmer had to something, which is only a workaround
for
a language/compiler limitation. "Compiler" because at least the simple cases
could
be silently fixed in a backward compatible way (by not disallowing safe
conversions).
"Language" because "uniq" would also be useful when the programmer knows it
applies,
but the compiler can't figure it out by itself.