Thread overview
IsExpression
Mar 12, 2007
Luís Marques
Mar 13, 2007
Kirk McDonald
Mar 13, 2007
Frits van Bommel
March 12, 2007
Hello,

The documentation of IsExpression lists the following valid forms:

is ( Type )
is ( Type : TypeSpecialization )
is ( Type == TypeSpecialization )
is ( Type Identifier )
is ( Type Identifier : TypeSpecialization )
is ( Type Identifier == TypeSpecialization )

What about the form "expression is expression"? I cannot find documentation for that form. What are its semantics? "exp is null" is an obvious one. But what about other forms?

- for classes it seems that "obj1 is obj2" is equivalent to "&obj1 == &obj2". Can I rely on that? I have a singleton called "nil", so it's great being able to say "obj is nil".

- for structs "structvar1 is structvar2" is always true.

- for PODs it seems that values must be semantically equivalent. For instance, "1L is 1.0+0i" is true.

Could this be documented?

Also, the IsExpression docs refer to a "Type", which can be an identifier (e.g. "int x; writefln(is(x));" is valid, even though the form in question is "is(Type)"). Perhaps that could be made more clear?

Regards,
Luis
March 13, 2007
Luís Marques wrote:
> Hello,
> 
> The documentation of IsExpression lists the following valid forms:
> 
> is ( Type )
> is ( Type : TypeSpecialization )
> is ( Type == TypeSpecialization )
> is ( Type Identifier )
> is ( Type Identifier : TypeSpecialization )
> is ( Type Identifier == TypeSpecialization )
> 
> What about the form "expression is expression"? I cannot find documentation for that form. What are its semantics? "exp is null" is an obvious one. But what about other forms?
> 
> - for classes it seems that "obj1 is obj2" is equivalent to "&obj1 == &obj2". Can I rely on that? I have a singleton called "nil", so it's great being able to say "obj is nil".
> 
> - for structs "structvar1 is structvar2" is always true.
> 
> - for PODs it seems that values must be semantically equivalent. For instance, "1L is 1.0+0i" is true.
> 
> Could this be documented?
> 

The 'is' keyword is used in two completely separate contexts: The first is the IsExpression, which has the grammar you outlined above. This is used for compile-time type checking.

The other use of 'is' is in the IdentityExpression.
http://www.digitalmars.com/d/expression.html#IdentityExpression

"For operand types other than class objects, static or dynamic arrays, identity is defined as being the same as equality."

Thus for structs I would expect it to perform a bitwise comparison of the two instances if the struct doesn't overload opEquals.

> Also, the IsExpression docs refer to a "Type", which can be an identifier (e.g. "int x; writefln(is(x));" is valid, even though the form in question is "is(Type)"). Perhaps that could be made more clear?
> 

It is indeed valid. As you point out, a "Type" can be an identifier, and it is a property of the IsExpression that it returns false if the Type provided is not a semantically valid type. Therefore, you must be able to provide it semantically /invalid/ types. (Which must still be /syntactically/ valid.)

-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
March 13, 2007
Luís Marques wrote:
> 
> The documentation of IsExpression lists the following valid forms:
> 
> is ( Type )
> is ( Type : TypeSpecialization )
> is ( Type == TypeSpecialization )
> is ( Type Identifier )
> is ( Type Identifier : TypeSpecialization )
> is ( Type Identifier == TypeSpecialization )
> 
> What about the form "expression is expression"? I cannot find documentation for that form.

That isn't an IsExpression, it's an IdentityExpression: http://www.digitalmars.com/d/expression.html#IdentityExpression

> What are its semantics? "exp is null" is an
> obvious one. But what about other forms?

See above URL:
---
The is compares for identity. To compare for not identity, use e1 !is e2. The type of the result is bool. The operands go through the usual conversions to bring them to a common type before comparison.

For operand types other than class objects, static or dynamic arrays, identity is defined as being the same as equality.

For class objects, identity is defined as the object references are for the same object. Null class objects can be compared with is.

For static and dynamic arrays, identity is defined as referring to the same array elements.

The identity operator is cannot be overloaded.
---

> - for classes it seems that "obj1 is obj2" is equivalent to "&obj1 == &obj2". Can I rely on that? I have a singleton called "nil", so it's great being able to say "obj is nil".

Yes, you can rely on that, as long as it's a class type.

> - for structs "structvar1 is structvar2" is always true.

Should only be so if the contents of the member variables is equal (or opEqual is defined and returns true)

> - for PODs it seems that values must be semantically equivalent. For instance, "1L is 1.0+0i" is true.

This is because of equivalence to '==' in this case and implicit conversions.

> Could this be documented?

It is.

> Also, the IsExpression docs refer to a "Type", which can be an identifier (e.g. "int x; writefln(is(x));" is valid, even though the form in question is "is(Type)"). Perhaps that could be made more clear?

To be clear, is(x) is allowed for int x, but will return false. As it will if x isn't even declared.
An IsExpression tests if the argument is a valid type, so obviously "Type" refers to something that should be tested for type-ness.
Note that the syntax definition defines just that: the syntax, not the semantics. As long as the argument is something that can possibly be parsed as a type (as far as the syntax is concerned, so before inspecting the declarations of the symbols used) it should be allowed.