February 03, 2012
Al 03/02/12 00:14, En/na bearophile ha escrit:
> xancorreu:
>
>> But you "only" put a "in" in
>> recFactorial function argument. What this mean? **Why** this is more
>> efficient than mine?
> It wasn't meant to improve performance. "in" turns a function argument to "input only" (and eventually scoped too). Generally when you program in D2 it's a good practice to use immutability where you can and where this doesn't cause other performance or typing problems. Immutability avoids bugs, allows a stronger purity (and I have seen DMD is often able to compiler a little more efficient program if you use immutability/constants everywhere they are a good fit). So 95% of the arguments of your program are better tagged with "in".

Mmm. Thanks. It remembers me val in scala ;-)
I note it for  optimizations.
> Bye,
> bearophile

February 03, 2012
On Friday, February 03, 2012 15:40:34 xancorreu wrote:
> Al 02/02/12 20:40, En/na Jonathan M Davis ha escrit:
> > And whether that's the best way to handle it depends on what you're trying to do in terms of user input and error messages. How on earth is all of that going to be handled generically? It all depends on what the programmer is trying to do. Switching to use command-line switches and getopt would help some, but you still have to deal with the error messages yourself. Creating the Person is the easy part. - Jonathan M Davis
> 
> I think it as a tool, not solve-everything-thing, it just a tool for easy your job. Yeah, you could manually do that (thanks for the code) but really you, maybe, want to do it _fastest_ and _easyest_.

Fastest and easiest would be to simply do

auto person = person(args[1], to!uint(args[2]), to!bool(args[3]));

but that's going to blow up in your face in all sorts of entertaining ways if you didn't do verify the arguments that the user gave you (both in terms of number and their values). And it's so easy to do, that I don't see much point in trying to have some sort of function or library for automatically generating your object from the program's arguments - especially when you really should be doing argument validation, which no one else can do for you, since the correct way to do it is completely dependent on your application.

- Jonathan M Davis
February 04, 2012
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.

>
> If it isn't obvious why - GC. The compiler can optimize the cases where it
> knows a newly allocated object can't escape and reduce or omit the GC overhead.
> And yes, it can also do this automatically - but that requires analyzing the
> whole call chain, which is a) not always possible and b) much more expensive.
>
> artur

Any optimization that relies on alias analysis potentially benefits from 'scope'.
February 04, 2012
On 02/03/2012 01:06 PM, Jonathan M Davis wrote:
> On Friday, February 03, 2012 11:08:54 Artur Skawina wrote:
>> 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.
>
> That would destroy slicing. I'm firmly of the opinion that scope should be used
> sparingly.
>
> - Jonathan M Davis

It could be enabled on by type basis.
February 04, 2012
Timon Gehr:

> However, it is nice that the shortest storage class, 'in', implies scope.

I'd like to ask this to be valid, to shorten my code:
alias immutable imm;
Is this silly?

Bye,
bearophile
February 04, 2012
"bearophile" <bearophileHUGS@lycos.com> wrote in message news:jgi3jn$2o6p$1@digitalmars.com...
> I'd like to ask this to be valid, to shorten my code:
> alias immutable imm;
> Is this silly?
>

Yes =)

immutable might be more characters than you want to type, but at this point it's extremely unlikely it will be changed or a synonym will be added.

You can always define something like this:

template imm(T) { alias immutable T imm; }

imm!int cantchangethis = ...;


February 04, 2012
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.
February 04, 2012
On 02/04/2012 06:55 PM, Artur Skawina wrote:
> 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?"?
>

I think this is covered in this issue:

http://d.puremagic.com/issues/show_bug.cgi?id=7311

But feel free to open a more specific enhancement/bug report.

>
> 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.

I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
February 04, 2012
On 02/04/12 22:20, Timon Gehr wrote:
> On 02/04/2012 06:55 PM, Artur Skawina wrote:
>> 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?"?
>>
> 
> I think this is covered in this issue:
> 
> http://d.puremagic.com/issues/show_bug.cgi?id=7311
> 
> But feel free to open a more specific enhancement/bug report.

Apparently, there's already a bug open for everything.
I'm not sure if it's a good or bad thing. :)

I don't think there's one correct answer here - you're right that unique const
does not really make sense. But is mutable (non-const) really better than
immutable? It depends, sometimes you will want one, sometimes the other.
I first ran into this while doing a custom string class - there it was the cause
of the one and only cast - (string ~ const(char)[]) can obviously still be a
string, but the compiler won't accept it without a cast.
I'm not sure how often you'll want the result of concatenation to be mutable,
compared to immutable. Anyway, the result really is "unique", not mutable, const
or immutable, at least until it is converted to one of those, hence the solution
described below.

>> 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.
> 
> I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
> 

It would be great if as many of the /language/ issues were fixed and documented as soon as possible. They don't even have to be implemented. What i'm afraid of is what will happen once dmd no longer is the normative compiler... Walter did a very good job with D, i wouldn't expect others to get even a small part of it right; it would be best if by the time the committee hordes start to "fix" things there was not much left to fix.

[Changes such as defaulting to scoped args are obviously D3 material, i'm only
 mentioning them so that they're already out there to consider/discuss. But some
 things *can* still be fixed in D2 in a mostly backward compatible way]

artur
February 04, 2012
On 02/04/2012 11:23 PM, Artur Skawina wrote:
> On 02/04/12 22:20, Timon Gehr wrote:
>> On 02/04/2012 06:55 PM, Artur Skawina wrote:
>>> 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?"?
>>>
>>
>> I think this is covered in this issue:
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=7311
>>
>> But feel free to open a more specific enhancement/bug report.
>
> Apparently, there's already a bug open for everything.
> I'm not sure if it's a good or bad thing. :)
>
> I don't think there's one correct answer here - you're right that unique const
> does not really make sense. But is mutable (non-const) really better than
> immutable? It depends, sometimes you will want one, sometimes the other.
> I first ran into this while doing a custom string class - there it was the cause
> of the one and only cast - (string ~ const(char)[]) can obviously still be a
> string, but the compiler won't accept it without a cast.
> I'm not sure how often you'll want the result of concatenation to be mutable,
> compared to immutable. Anyway, the result really is "unique", not mutable, const
> or immutable, at least until it is converted to one of those, hence the solution
> described below.
>


Well, string = string ~ const(char)[] and char[] = string ~ const(char)[] should work, regardless of the type of immutable[] ~ const[]. The compiler can track the uniqueness of the data at the expression level without actually introducing a type modifier. There is precedent: Array literals are covariant, because it is safe. Do you want to open the enhancement or should I do it? (I really thought I already had an issue open for this...)

>>> 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.
>>
>> I am certain we'll get something like this eventually, once the compiler bug count has shrunk sufficiently. It is a natural thing to add.
>>
>
> It would be great if as many of the /language/ issues were fixed and documented
> as soon as possible. They don't even have to be implemented. What i'm afraid of
> is what will happen once dmd no longer is the normative compiler... Walter did a
> very good job with D, i wouldn't expect others to get even a small part of it
> right; it would be best if by the time the committee hordes start to "fix" things
> there was not much left to fix.
>
> [Changes such as defaulting to scoped args are obviously D3 material, i'm only
>   mentioning them so that they're already out there to consider/discuss. But some
>   things *can* still be fixed in D2 in a mostly backward compatible way]
>
> artur