Re: Meaning of const variables

2016-06-21 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jun 21, 2016 at 01:48:27PM +, jmh530 via Digitalmars-d-learn wrote:
[...]
> Thanks to you and the others for the detailed clarifications. I think
> part of the difficulty is that there are basically three things being
> discussed that are all very similar: an alias to data, a pointer to
> data, and a view of data.

The word "alias" is unfortunately overloaded to mean similar, but not
exactly the same, things.

"Alias" as used in the keyword "alias" is a compiler construct that has
no real bearing on the type system.  All it is, is to create a new name
for something. For example, if I have:

struct S {
int x;
}
alias y = S.x;

all this means is that whenever the compiler sees "y" it should act as
if it has seen "S.x" instead. Well, not exactly, but basically y will
refer to whatever S.x refers to in the scope of the declaration.  This
makes it useful sometimes for naming things that are hard or impossible
to name in a different scope, for example:

struct S(T) {
alias ElementType = T;
}
S!int s;
static assert(is(s.ElementType == int));

>From an outsider's POV, the template parameter T is not easily obtained,
but having a convenient alias inside the scope where it *is* easily
obtained, makes it readily available to outside code.

None of this is related to the present topic, though.  Which brings us
to the second meaning of "alias", as used in the type system to mean
that the same data can be reached from multiple references.  At the
bottom of this is pointers, and abstractions built on top of pointers.

int x;
int* p = 

This sense of "alias" is usually used as a verb, as in "the pointer p
aliases the variable x". Meaning, you can reach the data represented by
x via the pointer p.  So this is similar to the first meaning of "alias"
in the sense that p is kinda like a different name for x, but
semantically it's not quite the same thing, because alias in the first
sense is a compile-time concept of having one identifier being treated
as though it were another, whereas alias in the second sense here is a
runtime concept, in that the data x exists somewhere in memory, say
location L, and the pointer p happens to contain the value L, so using p
we can find x in memory without actually referring to x directly in the
code.

Now, what's the distinction between int*, const(int)*, and
immutable(int)*?  Or, for that matter, const(int*) and immutable(int*)?

To understand this, it's useful to think of the data being pointed to
distinctly from the pointer.  All of the above pointers point to some
int sitting somewhere in memory.  Let's say there are two ints, sitting
in memory locations L1 and L2, respectively. When we declared the two
ints, we specified the first one as simply 'int', meaning it's mutable.
So memory location L1 contains an int that can be modified.  Let's say
the second int is declared as immutable(int), so L2 contains an int
that, once initialized, cannot be modified.  (In this respect, there is
no difference if we declared const(int) instead, since either way nobody
can modify the value once it's initialized.)

Now, int* is a pointer to (mutable) int, so it can never point to L2. If
the language allowed that, it would break the contract that L2 cannot be
modified. Similarly, immutable(int)* is a pointer to immutable(int), so
it can never point to L1.  However, const(int)* can point to both L1 and
L2, because const(int)* just means that you cannot use *this* pointer to
modify the data, but somebody else who has a mutable reference (i.e.,
int*) pointing to the same data, may use it to modify the data.

So in short:

int*means "pointer to an int that anybody can modify"
immutable(int)* means "pointer to an int that nobody can modify"
const(int)* means "pointer that cannot be used to modify the int,
but can be used to read the int"

So if you have an int* in hand, you know that the memory location it
points to is mutable, and if you have an immutable(int)* in hand, you
know that the memory location it points to is immutable (to everybody,
not just you).  However, if you have a const(int)* in hand, all you know
is that *you* can't modify the data (or more precisely, you cannot use
this particular pointer to modify the data), but it says nothing about
whether the data itself is actually modifiable or not.

What about const(int*) and immutable(int*)?  Here, thanks to transitive
const in D, the const and immutable applies both to the pointer and the
data pointed to. So const(int*) means that the data cannot be modified
through this pointer, and also that you cannot modify this pointer
itself.  (But somebody with a mutable reference to this pointer may
change what it points to.) Similarly, immutable(int*) means that the
data cannot be modified by anybody (whether through this pointer or
otherwise), and the pointer itself also cannot be modified by anybody.


T


Re: Meaning of const variables

2016-06-21 Thread jmh530 via Digitalmars-d-learn

On Tuesday, 21 June 2016 at 15:21:01 UTC, Ali Çehreli wrote:

[snip]


Thanks.


Re: Meaning of const variables

2016-06-21 Thread Ali Çehreli via Digitalmars-d-learn

On 06/21/2016 06:48 AM, jmh530 wrote:

> So an immutable pointer guarantees that whatever it is pointing to will
> never change,

Yes but saying "_requires_ that data never changes" is more correct. 
When it comes to a pointer (i.e. the user of data), "guarantee" is 
related to const.


> but a const pointer can also point to mutable data, which
> might change some other way.

Yes, const means "_I_ will not change."

const and immutable are not interesting unless there are references. 
Otherwise, who cares whether data was copied from const or immutable?


const c = 42;
immutable i = 43;

int a = c;
int b = i;

a and b are copied from const and immutable, respectively, but we don't 
care. (Except when they have members or members of members that are 
references.)


const and immutable are interesting when there are references, of which, 
function parameters make the issue clear to me:


void foo(ref const int c, ref immutable int i) {
// ...
}

foo says "I guarantee that I will not modify your data, which I'm 
referring to as c" and "I require that nobody will modify your data, 
which I'm referring to as i". So, the const-immutable distinction of a 
reference parameter is what makes it easy to understand to me.


As I observe in that chapter[1] and later in the book[2], it's not 
always clear which one to use. For example, although const seems more 
usable, the fact that it has to work with mutable and immutable 
necessarily "erases" the actual mutability[1].


Another example is with constructor parameters where immutable is 
potentially faster[2]. That chapter does not really explain why so here 
is an example:


struct S {
string fileName;// Needs immutable

// Takes as const reference, presumably to be more useful
this(const char[] fileName) {
// Since const does not guarantee immutability, must take a copy
import std.conv;
this.fileName = fileName.to!string;
}
}

void main() {
// The copy in the constructor is unnecessary in this case because here
// the string is already immutable. S's constructor could not know 
that so

// it had to take a copy.
auto s = S("my_file");
}

The same issue applies for other functions where a reference needs to be 
kept longer for later use.


Ali

[1] 
http://ddili.org/ders/d.en/const_and_immutable.html#ix_const_and_immutable.parameter,%20const%20vs.%20immutable


[2] http://ddili.org/ders/d.en/special_functions.html
(Search for the section "Immutability of constructor parameters".)



Re: Meaning of const variables

2016-06-21 Thread jmh530 via Digitalmars-d-learn

On Tuesday, 21 June 2016 at 02:54:06 UTC, ketmar wrote:




Thanks to you and the others for the detailed clarifications. I 
think part of the difficulty is that there are basically three 
things being discussed that are all very similar: an alias to 
data, a pointer to data, and a view of data.




so, what that quote essentially means is: "`const` pointers can 
point to mutable data, but `immutable` pointers cannot".




So an immutable pointer guarantees that whatever it is pointing 
to will never change, but a const pointer can also point to 
mutable data, which might change some other way.


Re: Meaning of const variables

2016-06-21 Thread Mike Parker via Digitalmars-d-learn
behavior is identical. And really, if you never need to take 
the address of the variable, then a manifest constant using 
enum would be more appropriate.




Actually, I should say it *may* be more appropriate. Definitely 
only when the initializer is known at compile time. There are 
cases when you initialize a local immutable variable with a 
runtime value.


Re: Meaning of const variables

2016-06-20 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Jun 21, 2016 at 02:24:03AM +, jmh530 via Digitalmars-d-learn wrote:
> I feel like I have a reasonable understanding of when to use const as
> a parameter in a function or for const member functions. However, I
> don't really understand why/when it should be used as a type modifier.
> 
> For instance, the Programming in D book basically just says
> (http://ddili.org/ders/d.en/const_and_immutable.html) that a const
> variable is the same as an immutable variable, but you should just use
> immutable.

I think that's an oversimplification. :-)  Here's a diagram that helped
me understand what the deal with const/immutable is:

const
   / \
(mutable)   immutable

This is a kind of "type inheritance diagram" analogous to a class
inheritance diagram.  What it means is that mutable and immutable cannot
implicitly convert to each other (except for atomic by-value types), but
both mutable and immutable can implicitly convert to const.

Why?

Because const means "you are not allowed to modify this value" (but
somebody else may).  Converting mutable to const, which usually happens
in function calls, simply means the callee is bound to a contract never
to modify the value, but the caller may have a mutable reference to the
same value and may legally modify it.

OTOH, immutable means "NOBODY is allowed to modify this value". Meaning
that the value is truly, physically immutable; neither caller nor callee
nor any 3rd party may modify its value.  This is actually a strong
guarantee because the compiler can statically verify that nobody
actually modifies the value; therefore certain optimizations can be made
(e.g., storing it in ROM, in an immutable data segment, eliding multiple
reads from the variable because it is guaranteed that its value never
changes no matter what else happens in between).  Such optimizations
cannot be applied to const, because we aren't guaranteed that a 3rd
party won't change the value after we last read it. Const only means
*we* cannot change it.

So const is a weaker form of immutable... its main purpose is to reduce
redundancy in functions that can work with both mutable and immutable
data.  For example, a function that only reads the value of a parameter
can be passed an immutable value safely -- since it won't modify it --
and can also take a mutable value -- even though modification is valid,
the function doesn't modify it anyway. This means we can pass both a
mutable value and an immutable value to the same function and it's fine,
as long as the function itself never changes anything.

But we can't write the function as:

auto func(immutable X x) { ... }

because converting mutable to immutable is illegal, so we couldn't call
the function with mutable arguments. Obviously we also can't write the
function without type qualifiers:

auto func(X x) { ... }

because immutable cannot convert to mutable, so we can't pass an
immutable value to it. The solution is to use const:

auto func(const(X) x) { ... }

Const ensures that func doesn't attempt to modify an immutable value
when we give it one, but since const doesn't guarantee a 3rd party won't
modify the value, we can also legally pass a mutable value to it. Since
func is bound by const never to modify x, it doesn't matter.

Without const, we'd have to write two identical functions, one that
takes an immutable value, and one that takes a mutable value.  Const
lets us unify the two, which is valid since const ensures that func
doesn't do any funny business behind our backs by trying to modify
its arguments.

Of course, this is only part of the story. The other part is that if
a value has a by-value type, then it's OK to implicitly convert to/from
immutable: because you're always making a copy of the by-value type. You
can't convert a mutable *reference* to an immutable reference or vice
versa (otherwise you could use the mutable reference to break
immutability), but you *can* copy the value itself from mutable to
immutable and vice versa. So a function that takes an int argument can
be legally passed an immutable int -- since the function gets a copy of
the immutable value, and it's OK to modify the copy instead of the
original value.

With this in view, it would make sense that const would usually be used
in function parameters, since that is where it's most useful, whereas
immutable would normally be used in variables that you wish to
initialize once and have its value never change again thereafter. This
is probably where that advice came from that you should use immutable
variables rather than const variables.

Still, there *are* times when const variables make sense -- this applies
when iterating read-only over a collection of objects, for example. The
iterator would need to be const so that it can refer to both mutable and
immutable members of the collection, again so that you don't have to
copy-n-paste the same code, one in a function that takes an immutable

Re: Meaning of const variables

2016-06-20 Thread ketmar via Digitalmars-d-learn

On Tuesday, 21 June 2016 at 02:24:03 UTC, jmh530 wrote:

So the line from the spec is
"Const types are like immutable types, except that const forms 
a read-only view of data. Other aliases to that same data may 
change it at any time."


I tried making an alias of a const variable and modifying it, 
but that didn't work. So presumably they mean something else.


yep, the spec was talking about data aliases in compiler 
terminology, not about D aliases. i.e. this is valid:


  int a;
  ...
  const(int)* pa = 

but this is not:

  int a;
  ...
  immutable(int)* pa = 


here, in former case we see `pa` as "alias to data".


so, what that quote essentially means is: "`const` pointers can 
point to mutable data, but `immutable` pointers cannot".


also, remember that slices are just "pointer, length" pairs, so 
when we are talking about "pointers" here, the same applies to 
slices too.


Meaning of const variables

2016-06-20 Thread jmh530 via Digitalmars-d-learn
I feel like I have a reasonable understanding of when to use 
const as a parameter in a function or for const member functions. 
However, I don't really understand why/when it should be used as 
a type modifier.


For instance, the Programming in D book basically just says 
(http://ddili.org/ders/d.en/const_and_immutable.html) that a 
const variable is the same as an immutable variable, but you 
should just use immutable.


The D spec uses slightly different terminology 
(https://dlang.org/spec/const3.html), I think. I think the 
storage class stuff is similar to what the PiD book says about 
const parameters, while const types further below matches up with 
what the book says about const variables.


So the line from the spec is
"Const types are like immutable types, except that const forms a 
read-only view of data. Other aliases to that same data may 
change it at any time."


I tried making an alias of a const variable and modifying it, but 
that didn't work. So presumably they mean something else. The 
only way I was able to get any kind of meaningful difference is 
that for normal pointers and immutable pointers, I would get 
errors if trying to get the address of non-normal or 
non-immutable variables, respectively. By contrast, I could 
assign an address of any of them (normal, const, immutable) to a 
pointer to a constant variable.


Not sure when I would use this property, or if there are any 
other relevant differences.


void main()
{
int x1 = 1;
const(int) x2 = 1;
immutable(int) x3 = 1;

int* p1_1 = 
//int* p1_2 = 
//int* p1_3 = 

const(int)* p2_1 = 
const(int)* p2_2 = 
const(int)* p2_3 = 

//immutable(int)* p3_1 = 
//immutable(int)* p3_2 = 
immutable(int)* p3_3 = 

p1_1++;
//p1_2++;
//p1_3++;
p2_1++;
p2_2++;
p2_3++;
//p3_1++;
//p3_2++;
p3_3++;
}


Re: Meaning of const

2012-01-25 Thread H. S. Teoh
On Tue, Jan 24, 2012 at 08:01:41PM -0500, bearophile wrote:
 Jonathan M Davis:
 
  Now, the confusing part is the fact that unlike C++, D allows you to put 
  the 
  const for making the function on the _left-hand_ side of the function (C++ 
  only lets you put it on the right). This is to increase consistency between 
  modifers (public, override, pure, etc.) - they _all_ can go on both the 
  right 
  and left (which is very unfortunate in the case of const and immutable 
  IMHO). 
  That means that const (and immutable) always modify the function rather 
  than 
  the return value unless you use parens.
 
 Some time ago we have discussed this topic in an enhancement request in 
 Bugzilla. The idea was to disallow code like:
 
 
 struct Foo {
 int x;
 const const(int) bar() {
 return 0;
 }
 }
 void main() {}
 
 
 and require the struct const, immutable to be only on the right if 
 present.
 Walter shot this idea down for consistency. But I generally don't want
 consistency when it's just a potential source of confusion for the
 programmer :-)
[...]

How can this be consistency? For example:

class A {
const int x;
@property const int y();
}

Now you have typeof(A.x)==const(int) and typeof(A.y)==int. Seems quite
inconsistent to me.

But since Walter doesn't like the idea of restricting the syntax to 'int
y() const', then what about making it mandatory to write:

const(int) x;

instead of:

const int x;

?

Requiring the parentheses is a bit extreme, I admit, but it touches upon
another area of D syntax that I don't quite like, and that is const or
immutable applied to arrays:

const(int)[] x; // array of const(int)
const(int[]) x; // const array of int
const int[] x;  // ??? const array of const int? Or one
// of the above?

It gets worse when you throw in ref:

ref int f();// returns int* (I think?)
ref const(int) f(); // returns const(int)* (?)
ref const int f();  // ???
const ref int f():  // ???

The last line is quite bad. Is the return type const(int*) or
const(int)*, or is it just int* (i.e., const applies to f not the return
value)?

ref const(int)[] x; // ref to array of const(int)?
const(ref int)[] x; // array of refs to int?
const ref int[] x;  // array of ???
const ref int[] x();// const function that returns ref int[]?
const const ref int[] x();  // const function returning what?

The more I think about this, the more confusing it becomes. If
parentheses were mandatory after const, things would be much, much
better:

const(ref int) x;
const(ref const(int)) x;
... etc.

Much clearer to me.


T

-- 
You have to expect the unexpected. -- RL


Re: Meaning of const

2012-01-25 Thread Jonathan M Davis
On Tuesday, January 24, 2012 16:24:27 Ali Çehreli wrote:
 On 01/24/2012 04:06 PM, Jonathan M Davis wrote:
   class A {
   int x;
   
   const int f1() { ... }
   int f2() const { ... }
   const(int) f3() { ... }
   }
 
 [...]
 
   int f2() const
   
   becomes
   
   int f2(const A this)
   
   Now, the confusing part is the fact that unlike C++, D allows you to
 
 put the
 
   const for making the function on the _left-hand_ side of the function
 
 (C++
 
   only lets you put it on the right).
 
 Ok.
 
   So, while a C++ programmer expects that
   
   int f2() const
   
   means that f2 is const, they're likely to be surprised by the fact
 
 that in
 
   const int f1()
   
   it's the int that's const, not f1.
 
 Have you phrased that last bit correctly? :) It seems to conflict with
 what you have said earlier.
 
 f1() and f2() are the same thing in D.

You're right. I said that incorrectly. f1 and f2 are identical.

- Jonathan M Davis


Re: Meaning of const

2012-01-25 Thread Timon Gehr

On 01/25/2012 02:29 AM, H. S. Teoh wrote:

On Tue, Jan 24, 2012 at 08:01:41PM -0500, bearophile wrote:

Jonathan M Davis:


Now, the confusing part is the fact that unlike C++, D allows you to put the
const for making the function on the _left-hand_ side of the function (C++
only lets you put it on the right). This is to increase consistency between
modifers (public, override, pure, etc.) - they _all_ can go on both the right
and left (which is very unfortunate in the case of const and immutable IMHO).
That means that const (and immutable) always modify the function rather than
the return value unless you use parens.


Some time ago we have discussed this topic in an enhancement request in 
Bugzilla. The idea was to disallow code like:


struct Foo {
 int x;
 const const(int) bar() {
 return 0;
 }
}
void main() {}


and require the struct const, immutable to be only on the right if present.
Walter shot this idea down for consistency. But I generally don't want
consistency when it's just a potential source of confusion for the
programmer :-)

[...]

How can this be consistency? For example:

class A {
const int x;
@property const int y();
}

Now you have typeof(A.x)==const(int) and typeof(A.y)==int. Seems quite
inconsistent to me.

But since Walter doesn't like the idea of restricting the syntax to 'int
y() const', then what about making it mandatory to write:

const(int) x;

instead of:

const int x;

?


You essentially propose to remove the const/immutable/shared/inout 
storage classes for variables. It would break almost every D program and 
I don't see many benefits.


Requiring the parentheses is a bit extreme, I admit, but it touches upon
another area of D syntax that I don't quite like, and that is const or
immutable applied to arrays:

const(int)[] x; // array of const(int)
const(int[]) x; // const array of int
const int[] x;  // ??? const array of const int? Or one
// of the above?


const(int[]).


The storage class of a declaration applies to the whole declaration.


It gets worse when you throw in ref:


Ref does not change anything but the calling convention *of the 
function*. The reference itself cannot be rebound, there is no syntax 
for it.




ref int f();// returns int* (I think?)
ref const(int) f(); // returns const(int)* (?)
ref const int f();  // ???
const ref int f():  // ???

The last line is quite bad. Is the return type const(int*) or
const(int)*, or is it just int* (i.e., const applies to f not the return
value)?


It is int.



ref const(int)[] x; // ref to array of const(int)?


Note that ref can only be on a function or on a parameter.


const(ref int)[] x; // array of refs to int?


No such thing exists.


const ref int[] x;  // array of ???


const(int[]). Declaration is invalid, would have to be a parameter.


const ref int[] x();// const function that returns ref int[]?


It returns int[], by reference. It is equivalent to

int[] x()const ref;

Though most people will prefer to have 'ref' on the lhs:

ref int[] x()const;

It still applies to the function though.


const const ref int[] x();  // const function returning what?


Redundant storage class const.

ref int[] x()const const; is the same thing.



The more I think about this, the more confusing it becomes.


It is very simple. What may be confusing you is that 
const/immutable/shared/inout are both type constructors and storage classes.



If
parentheses were mandatory after const, things would be much, much
better:

const(ref int) x;
const(ref const(int)) x;
... etc.

Much clearer to me.


It is not to me. This is not valid syntax. Also, types of the general 
form const(...const(...)...) don't make a lot of sense. Const is transitive.




Re: Meaning of const

2012-01-25 Thread H. S. Teoh
On Wed, Jan 25, 2012 at 11:50:57PM +0100, Timon Gehr wrote:
 On 01/25/2012 02:29 AM, H. S. Teoh wrote:
[...]
 But since Walter doesn't like the idea of restricting the syntax to 'int
 y() const', then what about making it mandatory to write:
 
  const(int) x;
 
 instead of:
 
  const int x;
 
 ?
 
 You essentially propose to remove the const/immutable/shared/inout
 storage classes for variables. It would break almost every D program
 and I don't see many benefits.
[...]
 It is very simple. What may be confusing you is that
 const/immutable/shared/inout are both type constructors and storage
 classes.
[...]

Ah, I see. This is very helpful.

So what's the difference between a const int type, and an int variable
with const storage class?

I think this is the key issue. The syntax makes this distinction
non-obvious, IMHO, which is very confusing. This ambiguity also shows up
in function definitions (allowing storage classes to appear left or
right of the function name/parameters), which we discussed earlier. From
what I can tell, Walter doesn't want to change this, but I have to say
that this is one part of D I find unnecessarily confusing.


T

-- 
Do not reason with the unreasonable; you lose by definition.


Re: Meaning of const

2012-01-25 Thread Timon Gehr

On 01/26/2012 12:35 AM, H. S. Teoh wrote:

On Wed, Jan 25, 2012 at 11:50:57PM +0100, Timon Gehr wrote:

On 01/25/2012 02:29 AM, H. S. Teoh wrote:

[...]

But since Walter doesn't like the idea of restricting the syntax to 'int
y() const', then what about making it mandatory to write:

const(int) x;

instead of:

const int x;

?


You essentially propose to remove the const/immutable/shared/inout
storage classes for variables. It would break almost every D program
and I don't see many benefits.

[...]

It is very simple. What may be confusing you is that
const/immutable/shared/inout are both type constructors and storage
classes.

[...]

Ah, I see. This is very helpful.

So what's the difference between a const int type, and an int variable
with const storage class?

I think this is the key issue. The syntax makes this distinction
non-obvious, IMHO, which is very confusing.


The syntax is clear on it: If it is followed by parentheses, it is a 
type constructor. Otherwise it is a storage class.



This ambiguity also shows up
in function definitions (allowing storage classes to appear left or
right of the function name/parameters), which we discussed earlier. From
what I can tell, Walter doesn't want to change this, but I have to say
that this is one part of D I find unnecessarily confusing.



For variables, the storage class just implies that the type will be 
wrapped in the respective type constructor. The storage class still 
'talks' about the whole declaration though.

A key application is for type deduction:

immutable a = foo();

Foo may return something mutable, and a will automatically have it's 
type deduced to the respective immutable type.


Storage classes always apply to the whole declaration they refer to. It 
is _not_


const intx;

and

const int  foo;

but:

constint x;

and

const  int foo(){}








Re: Meaning of const

2012-01-24 Thread Jonathan M Davis
On Tuesday, January 24, 2012 15:52:50 H. S. Teoh wrote:
 Hi all,
 
 I'm a bit confused by what 'const' means when used as part of a member
 function's signature:
 
 class A {
 int x;
 
 const int f1() { ... }
 int f2() const { ... }
 const(int) f3() { ... }
 }
 
 Is there a difference between f1 and f2? If not, which is the preferred
 syntax? If yes, what is the meaning of 'const' in either case?
 
 I tried various code inside f1 and f2, and it seems in both of them I
 can't change x, which appears to mean that 'const' in this case refers
 to immutability of the class object? Is this correct?
 
 What exactly does 'const' mean in f3? That the returned int cannot be
 modified?
 
 Confused by const syntax,

const on a return value means that the return value is const. const on a 
member function means that the invisible this argument is const (meaning that 
you can't call non-const member functions within that function or mutate any 
member variables). You can think of it like this

int f2() const

becomes

int f2(const A this)

Now, the confusing part is the fact that unlike C++, D allows you to put the 
const for making the function on the _left-hand_ side of the function (C++ 
only lets you put it on the right). This is to increase consistency between 
modifers (public, override, pure, etc.) - they _all_ can go on both the right 
and left (which is very unfortunate in the case of const and immutable IMHO). 
That means that const (and immutable) always modify the function rather than 
the return value unless you use parens.

So, while a C++ programmer expects that

int f2() const

means that f2 is const, they're likely to be surprised by the fact that in

const int f1()

it's the int that's const, not f1. It's only in the case of

const(int) f3()

that the return value is const. You could, however, have both

const(int) f4() const

in which case both the return value and the function are const.

Now, having a const return value is rather pointless in the case of int, since 
it's a value type and would juts be copied. It matters a great deal more with 
a pointer or referenc type. e.g.

const(int*) func()

or

ref const(int) func()

or in the case of your A class,

const(A) func()

In those cases, it protects the return value from being mutated, since there's 
actually something to protect from mutation given that the return value is not 
a value type.

Hopefully, that clears things up.

- Jonathan M Davis


Re: Meaning of const

2012-01-24 Thread H. S. Teoh
On Tue, Jan 24, 2012 at 07:06:47PM -0500, Jonathan M Davis wrote:
[...]
 So, while a C++ programmer expects that
 
 int f2() const
 
 means that f2 is const, they're likely to be surprised by the fact that in
 
 const int f1()
 
 it's the int that's const, not f1.
[...]

Wait, I thought 'const int f1()' means that 'int f1(const this, ...)',
not the other way round?

I guess you're trying to say that in C++:

const int f();

means the return value is 'const int', but in D:

const int f();

means the same thing as 'int f() const', and the return value is 'int'.
Is that correct?

//

Anyway, I find this variable syntax a bit annoying. The basic syntax of
a function is:

return type func_name(args...) { body }

But now we have additional modifiers like 'pure', 'lazy', 'const', etc.,
and syntax becomes:

modifiers return type func_name(args...) more_modifiers { 
body }

Which makes sense, since then you can write 'pure int f()' which reads
nicely. However, in the case of const, it's very confusing because
you're used to writing 'const typename' to mean 'const(typename)',
yet here 'const int f()' means 'const(int f())' rather than 'const(int)
f()':

class A {
const int f();
}
auto a = new A;
const int x;// typeof(x) == const(int)
auto y = a.f(); // typeof(y) == int

This is a visual ambiguity with the basic pattern 'return type
func_name(...)', which I find very jarring.

Should I file an issue for this? :)


T

-- 
I think Debian's doing something wrong, `apt-get install pesticide',
doesn't seem to remove the bugs on my system! -- Mike Dresser


Re: Meaning of const

2012-01-24 Thread bearophile
Jonathan M Davis:

 Now, the confusing part is the fact that unlike C++, D allows you to put the 
 const for making the function on the _left-hand_ side of the function (C++ 
 only lets you put it on the right). This is to increase consistency between 
 modifers (public, override, pure, etc.) - they _all_ can go on both the right 
 and left (which is very unfortunate in the case of const and immutable IMHO). 
 That means that const (and immutable) always modify the function rather than 
 the return value unless you use parens.

Some time ago we have discussed this topic in an enhancement request in 
Bugzilla. The idea was to disallow code like:


struct Foo {
int x;
const const(int) bar() {
return 0;
}
}
void main() {}


and require the struct const, immutable to be only on the right if present.
Walter shot this idea down for consistency. But I generally don't want 
consistency when it's just a potential source of confusion for the programmer 
:-)

Bye,
bearophile