Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
January 21, 2009 Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
In this test I'm trying to emulate how I want a typedef to act, but I run into a problem: import std.stdio; struct BlockNum { uint value; uint opCast() { return value; } void opAssign (uint val) { value = val; } uint opCall() { return value; } } void main() { BlockNum test; test = 42; uint tst2 = test(); // <<== if I don't have the parenthesis I // get a compiler error (cast // required). // kfile.d(15): Error: cannot implicitly convert expression // (test) of type BlockNum to uint writef ("tst2 = %d\n", tst2); } It seemed to me as if the parens shouldn't be required here, but I seem mistaken. Which leads to ugly code. Is there a way around this? |
January 21, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | P.S.: This is Digital Mars D Compiler v2.023 running on Linux
Charles Hixson wrote:
> In this test I'm trying to emulate how I want a typedef to act, but I run into a problem:
>
> import std.stdio;
>
> struct BlockNum
> { uint value;
>
> uint opCast() { return value; }
> void opAssign (uint val) { value = val; }
> uint opCall() { return value; }
> }
>
> void main()
> { BlockNum test;
> test = 42;
> uint tst2 = test(); // <<== if I don't have the parenthesis I
> // get a compiler error (cast
> // required).
> // kfile.d(15): Error: cannot implicitly convert expression
> // (test) of type BlockNum to uint
>
> writef ("tst2 = %d\n", tst2);
> }
>
> It seemed to me as if the parens shouldn't be required here, but I seem mistaken. Which leads to ugly code. Is there a way around this?
|
January 21, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | On Wed, 21 Jan 2009 20:26:08 +0300, Charles Hixson <charleshixsn@earthlink.net> wrote:
> P.S.: This is Digital Mars D Compiler v2.023 running on Linux
>
> Charles Hixson wrote:
>> In this test I'm trying to emulate how I want a typedef to act, but I run into a problem:
>> import std.stdio;
>> struct BlockNum
>> { uint value;
>> uint opCast() { return value; }
>> void opAssign (uint val) { value = val; }
>> uint opCall() { return value; }
>> }
>> void main()
>> { BlockNum test;
>> test = 42;
>> uint tst2 = test(); // <<== if I don't have the parenthesis I
>> // get a compiler error (cast
>> // required).
>> // kfile.d(15): Error: cannot implicitly convert expression
>> // (test) of type BlockNum to uint
>> writef ("tst2 = %d\n", tst2);
>> }
>> It seemed to me as if the parens shouldn't be required here, but I seem mistaken. Which leads to ugly code. Is there a way around this?
No, there isn't. It leads to ambiguity and here is why:
class Foo
{
Foo opCall() { return new Foo(); }
}
void main() {
Foo bar = new Foo();
auto ambiguous = bar; // is it 'bar' or 'bar()'?
}
One more case where empty pair of parens is mandatory.
To Walter & Co: Please, oh *PLEASE* drop this feature and give us real properties!
|
January 26, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | Wed, 21 Jan 2009 09:24:01 -0800, Charles Hixson wrote:
> In this test I'm trying to emulate how I want a typedef to act, but I run into a problem:
>
> import std.stdio;
>
> struct BlockNum
> { uint value;
>
> uint opCast() { return value; }
> void opAssign (uint val) { value = val; }
> uint opCall() { return value; }
> }
>
> void main()
> { BlockNum test;
> test = 42;
> uint tst2 = test(); // <<== if I don't have the parenthesis I
> // get a compiler error (cast
> // required).
> // kfile.d(15): Error: cannot implicitly convert expression
> // (test) of type BlockNum to uint
>
> writef ("tst2 = %d\n", tst2);
> }
>
> It seemed to me as if the parens shouldn't be required here, but I seem mistaken. Which leads to ugly code. Is there a way around this?
test is an expression of type BlockNum. opCall() is called when you use
parentheses syntax on it. opCast() is called when you use cast() syntax
for it. Otherwise it stays BlockNum and therefore is not convertible to
uint.
|
January 28, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergey Gromov | Sergey Gromov wrote:
> Wed, 21 Jan 2009 09:24:01 -0800, Charles Hixson wrote:
>
>> In this test I'm trying to emulate how I want a typedef to act, but I run into a problem:
>>
>> import std.stdio;
>>
>> struct BlockNum
>> { uint value;
>>
>> uint opCast() { return value; }
>> void opAssign (uint val) { value = val; }
>> uint opCall() { return value; }
>> }
>>
>> void main()
>> { BlockNum test;
>> test = 42;
>> uint tst2 = test(); // <<== if I don't have the parenthesis I
>> // get a compiler error (cast
>> // required).
>> // kfile.d(15): Error: cannot implicitly convert expression
>> // (test) of type BlockNum to uint
>>
>> writef ("tst2 = %d\n", tst2);
>> }
>>
>> It seemed to me as if the parens shouldn't be required here, but I seem mistaken. Which leads to ugly code. Is there a way around this?
>
> test is an expression of type BlockNum. opCall() is called when you use
> parentheses syntax on it. opCast() is called when you use cast() syntax
> for it. Otherwise it stays BlockNum and therefore is not convertible to
> uint.
I think that means "No, there isn't a way around it."
OK. I'll just ...
well, I'm not totally sure. Either give up type safety or ... something else.
|
January 28, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson | Honestly, I can't see what you're trying to accomplish. It looks like you want something that's not called int, but which works exactly like an int does, and can be passed as one. If you just want another name for "int", you can use an alias. From the compiler's POV, there's no difference between "BlockNum" and "int". > alias int BlockNum; > BlockNum a = 42; > someFuncThatTakesAnInt(a); If you want to have a type that is an int, but which won't allow itself to directly interact with ints, use a typedef. Personally, I like this usage for simple numeric values which I don't want to accidentally mix with other types. Yes, it's a bit of a pain to do arithmetic, but that's the trade-off you make. From the compiler's POV, "BlockNum" and "int" are totally distinct, incompatible types that just happen to be the same under the hood. > typedef int BlockNum; > BlockNum a = cast(BlockNum) 42; > someFuncThatTakesAnInt(cast(int) a); The last is if you need something that's basically an int, but you want it to behave differently. In that case, a struct with operators is your best bet. Let's say you wanted to do something like a Meters struct to store lengths. I'd do something like this: > struct Meters { > private int value; > int asInt() { return value; } > int asInt(int v) { return value=v; } > // ... operator overloads ... > } > > Meters a; a.asInt = 42; > someFuncThatTakesAnInt( a.asInt ); I can't really offer more than that, since I don't know what it is you're trying to accomplish. -- Daniel |
January 28, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | I guess I'm going to do that, but it causes an annoying proliferation of casts throughout the program whenever I need to interact with a library call that recognized more than one int type. (The compiler, D2.023 on Linux) doesn't seem to properly upcast the type.
Perhaps I'll write separate functions through which to interact with library routines. Unpleasant and messy, but better than scattering casts all over the code (as long as they get optimized away).
Daniel Keep wrote:
> Honestly, I can't see what you're trying to accomplish. It looks like
> you want something that's not called int, but which works exactly like
> an int does, and can be passed as one.
>
> If you just want another name for "int", you can use an alias.
>
> From the compiler's POV, there's no difference between "BlockNum" and "int".
>
>> alias int BlockNum;
>> BlockNum a = 42;
>> someFuncThatTakesAnInt(a);
>
> If you want to have a type that is an int, but which won't allow itself
> to directly interact with ints, use a typedef.
>
> Personally, I like this usage for simple numeric values which I don't
> want to accidentally mix with other types. Yes, it's a bit of a pain to
> do arithmetic, but that's the trade-off you make.
>
> From the compiler's POV, "BlockNum" and "int" are totally distinct,
> incompatible types that just happen to be the same under the hood.
>
>> typedef int BlockNum;
>> BlockNum a = cast(BlockNum) 42;
>> someFuncThatTakesAnInt(cast(int) a);
>
> The last is if you need something that's basically an int, but you want
> it to behave differently. In that case, a struct with operators is your
> best bet.
>
> Let's say you wanted to do something like a Meters struct to store
> lengths. I'd do something like this:
>
>> struct Meters {
>> private int value;
>> int asInt() { return value; }
>> int asInt(int v) { return value=v; }
>> // ... operator overloads ...
>> }
>>
>> Meters a; a.asInt = 42;
>> someFuncThatTakesAnInt( a.asInt );
>
> I can't really offer more than that, since I don't know what it is
> you're trying to accomplish.
>
> -- Daniel
|
January 28, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | On Wed, 28 Jan 2009 08:45:12 +0300, Daniel Keep <daniel.keep.lists@gmail.com> wrote:
>
> Honestly, I can't see what you're trying to accomplish. It looks like
> you want something that's not called int, but which works exactly like
> an int does, and can be passed as one.
>
> If you just want another name for "int", you can use an alias.
>
> From the compiler's POV, there's no difference between "BlockNum" and "int".
>
>> alias int BlockNum;
>> BlockNum a = 42;
>> someFuncThatTakesAnInt(a);
>
> If you want to have a type that is an int, but which won't allow itself
> to directly interact with ints, use a typedef.
>
> Personally, I like this usage for simple numeric values which I don't
> want to accidentally mix with other types. Yes, it's a bit of a pain to
> do arithmetic, but that's the trade-off you make.
>
> From the compiler's POV, "BlockNum" and "int" are totally distinct,
> incompatible types that just happen to be the same under the hood.
>
>> typedef int BlockNum;
>> BlockNum a = cast(BlockNum) 42;
>> someFuncThatTakesAnInt(cast(int) a);
>
> The last is if you need something that's basically an int, but you want
> it to behave differently. In that case, a struct with operators is your
> best bet.
>
> Let's say you wanted to do something like a Meters struct to store
> lengths. I'd do something like this:
>
>> struct Meters {
>> private int value;
>> int asInt() { return value; }
>> int asInt(int v) { return value=v; }
>> // ... operator overloads ...
>> }
>>
>> Meters a; a.asInt = 42;
>> someFuncThatTakesAnInt( a.asInt );
>
> I can't really offer more than that, since I don't know what it is
> you're trying to accomplish.
>
> -- Daniel
Perhaps, he wants opImplicitCast?
|
January 28, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denis Koroskin | Suppose that you have four types, equivalent to, say, float.
Call one of them Horiz, one Vertic, one Radians, and one Radius.
These are all floats, but when you specify, say,
float dist (Horiz x, Vert y)
{ return sqrt(x * x + y * y); }
It's important that the arguments aren't Radius and Radians. Or Horiz and Horiz.
Denis Koroskin wrote:
> On Wed, 28 Jan 2009 08:45:12 +0300, Daniel Keep <daniel.keep.lists@gmail.com> wrote:
>
>>
>> Honestly, I can't see what you're trying to accomplish. It looks like
>> you want something that's not called int, but which works exactly like
>> an int does, and can be passed as one.
>>
>> If you just want another name for "int", you can use an alias.
>>
>> From the compiler's POV, there's no difference between "BlockNum" and "int".
>>
>>> alias int BlockNum;
>>> BlockNum a = 42;
>>> someFuncThatTakesAnInt(a);
>>
>> If you want to have a type that is an int, but which won't allow itself
>> to directly interact with ints, use a typedef.
>>
>> Personally, I like this usage for simple numeric values which I don't
>> want to accidentally mix with other types. Yes, it's a bit of a pain to
>> do arithmetic, but that's the trade-off you make.
>>
>> From the compiler's POV, "BlockNum" and "int" are totally distinct,
>> incompatible types that just happen to be the same under the hood.
>>
>>> typedef int BlockNum;
>>> BlockNum a = cast(BlockNum) 42;
>>> someFuncThatTakesAnInt(cast(int) a);
>>
>> The last is if you need something that's basically an int, but you want
>> it to behave differently. In that case, a struct with operators is your
>> best bet.
>>
>> Let's say you wanted to do something like a Meters struct to store
>> lengths. I'd do something like this:
>>
>>> struct Meters {
>>> private int value;
>>> int asInt() { return value; }
>>> int asInt(int v) { return value=v; }
>>> // ... operator overloads ...
>>> }
>>>
>>> Meters a; a.asInt = 42;
>>> someFuncThatTakesAnInt( a.asInt );
>>
>> I can't really offer more than that, since I don't know what it is
>> you're trying to accomplish.
>>
>> -- Daniel
>
> Perhaps, he wants opImplicitCast?
>
|
January 29, 2009 Re: Is there a way to remove the requirement for parenthesis? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Charles Hixson |
Charles Hixson wrote:
> Suppose that you have four types, equivalent to, say, float.
> Call one of them Horiz, one Vertic, one Radians, and one Radius.
> These are all floats, but when you specify, say,
> float dist (Horiz x, Vert y)
> { return sqrt(x * x + y * y); }
> It's important that the arguments aren't Radius and Radians. Or Horiz
> and Horiz.
>
> [snip]
There's no problem with that: make them structs that implement the appropriate operators.
See, what I don't get (note: this is how I perceive it) is the desire to
have this sort of type protection, but require the compiler to somehow
be psychic in order to know when and where you don't care and throw it away.
You either have distinct types that aren't automatically compatible, or you don't.
-- Daniel
|
Copyright © 1999-2021 by the D Language Foundation