December 07, 2007
Walter Bright wrote:
> Sean Kelly wrote:
>> Walter Bright wrote:
>>> Ary Borenszweig wrote:
>>>> Why not
>>>>
>>>> macro x = 3;
>>>> ?
>>>
>>> It's been suggested several times. It doesn't make much aesthetic sense to do things like:
>>>
>>>     macro int x = 3;
>>
>> So are you saying that it would be fine without the type qualifier, or that you don't like the use of "macro" here at all?
> 
> Since the optional type qualifier should be supported, it doesn't make sense.

It may be stretching the desire to use "macro" too far, but casting could be used to specify the type:

macro x = 5L; // long int
macro y = cast(short) 2;
macro z = "abc"w;

Thus it wouldn't actually be treated like a storage class.  That might also save some confusion for things like:

enum const static int x = 7;
December 07, 2007
Walter Bright wrote:
> Christopher Wright wrote:
>> Walter Bright wrote:
>>> Christopher Wright wrote:
>>>>> I've given up on tail const in any of its forms. The new regime has no tail const, no head const, it's just const, and fully transitive const at that.
>>>>
>>>> So if I have:
>>>> const(Foo)* t;
>>>> the pointer is const and points to a const Foo?
>>>
>>> No, it is a mutable pointer to a const Foo. A const pointer to a const Foo would be:
>>>     const(Foo*) t;
>>>
>>>> Will that fail?
>>>
>>> Yes, because T[] will be the same thing as const(Foo)[]. Hiding it behind an alias and a template won't change that <g>.
>>
>> So why do arrays take their const status from their elements when pointers don't?
> 
> ??? I think there's a misunderstanding here on what arrays are. Arrays consist of a pointer/length pair. As far as const goes, they are just like pointers.

But I can reassign a const Foo, right?
December 07, 2007
"Walter Bright" wrote
> Steven Schveighoffer wrote:
>> "Walter Bright" wrote
>>> Steven Schveighoffer wrote:
>>>> What happens if you have this?
>>>> const(T)*[]
>>> Array of pointers to constant T.
>>>
>>>> If T is a struct, then it's fine, but if it's a class, then what?  To me the situation is just as bad.
>>> It is perfectly consistent. I don't see why it is bad.
>>
>> const(T)*[] x;
>>
>> x[0].member is a struct member if T is a struct, what is it if T is a class? I was under the (possibly wrong) impression that this is illegal?
>
> I don't understand. Exactly what is illegal?

I guess it isn't :)  I thought:

class C { void f() {} }

C c = new C;
C *cp = &c;
cp.f(); // I thought this was illegal, but it works!

So you CAN still have tail-const.  The only issue is that you need to have a reference to take the address of...

It would be nice if I could just do:
C * cp = new C;

Then I could have generic code like:

const(T)*[] x

x = new const(T)*[5]

for(int i = 0; i < 5; i++)
  x[i] = new T; // this will work for structs, not for classes

then we have functionally tail-const back...

I think this isn't going to be possible, because then you have no way of specifying I want a reference of a reference.  Like a ref parameter.

This is why I proposed that the & operator is used to mean 'pointer to'. The benefit is:

T x; // for classes, this means pointer, for structs, it means value
T *x; // for classes, this means pointer to pointer, for structs it means
pointer.
T &x; // for classes, it means pointer, for structs, it means pointer

>
>
>> Sure, but your original point was to be "able to wrap any type with a
>> struct, and have it be possible for that
>> struct to behave as if it were that member type".  I believed you were
>> implying that this was a reason NOT to have a & operator.  My question to
>> you is, how does having a reference operator make this more difficult
>> than not having one?  A reference is a pointer.
>
> There's the problem we're having. While a class reference is implemented as a pointer 'under the hood', to the type system, it is not a pointer.
>
>
>> OK, I am confused, isn't const(S)* tail const?
>
> No. For const(int*), tail const of that construct would mean that the pointer is mutable while what it points to is not.

I believe I understand your confusion.  To me tail-const == reference is mutable, pointed to data is not.  I think of this as the semantic meaning of tail-const regardless of what the syntax says

To you, tail-const is the specific syntax of const(C) for a reference type meaning C is tail-const.  I agree that this is confusing, and bad for generic code.  But const(C)* under the new regime is still functionally tail-const, is it not?

>
>
>> And if so, how does this new scheme rid us of tail const?
>
> It would say that const(int*) would mean an immutable pointer to an immutable int.
>
>> Couldn't I use this to call a const member function on a struct?
>
> I'm very confused as to what you're referring to.

I was confused also :)  I think the new regime allows tail const, but makes it difficult to make tail-const references to classes.

>> The way I am interpreting your new const is that I can have tail-const for struct references (pointers) but not tail-const for class references.
>
> No. The correct interpretation is that all parts of the type within the ( ) are immutable.

I understand this and agree with it.

>> In other words, I can create a tail-const struct array via:
>>
>> const(S)*[] tailconst;
>> tailconst[0] = new S; // ok to assign to tailconst[0]
>> tailconst[0].nonconstfunc; // error, cannot call const function
>>
>> How do I do the same for a class?
>
> You cannot separate the class reference from the class fields.

That is why I proposed a new syntax.  If you want to do const in a way that is correct and backwards compatible, I think you cannot avoid this.  To allow for more power for structs to easily have tail const, but not classes seems very wrong to me.

-Steve


December 07, 2007
sambeau, el  6 de diciembre a las 20:53 me escribiste:
> Walter Bright Wrote:
> 
> > 'define' has been proposed before. I'd prefer to stay away from it because of the negative connotations of C's preprocessor.
> 
> How about 'let' then?
> It works for FP..

Even when I find 'let' appealing, I think 'macro' is the way to go. It doesn't introduce a new keyword ('macro' is a keyword since DMD 1.011) and is something it got rewriten/processed by the compiler at compile-time.

-- 
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
¿Qué será lo que hace que una brújula siempre marque el norte?
- Ser aguja, nada más, y cumplir su misión.
	-- Ricardo Vaporeso
December 07, 2007
Walter Bright wrote:
> BCS wrote:
> 
>> totally random though: I'm designing a program and ran across a place where I want to say "this pointer shall never be dereferenced, it shall only be used as an identity" the idea being that I want to be sure that the code has no dependencies on anything under it. It would be used somthing like a key in a hash table but where the test is "same thing" not "equal things". What should this be implemented as? Does this have any place in the const system? Is there an existing clean solution?
> 
> 
> Since the point of a pointer is to dereference, perhaps a pointer is the wrong thing. Perhaps it should be a struct.
> 

In my case I have a table of info that I want to get things from, the things to be got are associated with object that are available to the caller. If I don't use the object pointers, then I need to add some process unique ID to the objects as handles. The pointer is good enough except that I want to drop the implies functional dependency. I might try typedefs of void* but that seems hackish.
December 08, 2007
Sean Kelly wrote:
> It may be stretching the desire to use "macro" too far, but casting could be used to specify the type:
> 
> macro x = 5L; // long int
> macro y = cast(short) 2;
> macro z = "abc"w;

Yes, it could be. But I just can't see it being a preferred choice to use:
	macro y = cast(short) 2;
rather than:
	enum short y = 2;
as the latter is how declarations work (setting aside the use of 'enum' for the moment). There is a reasonable school of thought that says that the use of casting should be minimized, and that every cast should be scrutinized (since it is a meataxe rather than a scalpel). Having too many casts in regular use will hide the questionable uses.


> Thus it wouldn't actually be treated like a storage class.  That might also save some confusion for things like:
> 
> enum const static int x = 7;

That wouldn't be allowed any more than:

	typedef static int x = 7;

because it makes no sense.
1 2 3 4 5
Next ›   Last »