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.