Jump to page: 1 2
Thread overview
User defined properties signatures
Apr 20, 2015
dvic
Apr 20, 2015
Jonathan M Davis
Apr 20, 2015
dvic
Apr 20, 2015
Jonathan M Davis
Apr 20, 2015
dvic
Apr 21, 2015
Marc Schütz
Apr 21, 2015
Dicebot
Apr 21, 2015
Idan Arye
Apr 21, 2015
Dicebot
Apr 20, 2015
Ali Çehreli
April 20, 2015
Hi guys,

It seems it's possible to define different read properties, only
differing by the return type.

Ex:

@property string value() { return m_value; } // m_value is a string
@property int value() { return to!int(m_value); }

But when using it in writefln() or assert for example, compiler (dmd) complains
about 2 different property signatures.

What I'd like to have is this:

MyObject.value = "12345"; // write property always setting a string

assert(MyObject.value == "12345");  // depending on the context, call 1st prop
assert(MyObject.value == 12345);  // depending on the context, call 2nd prop

Why is the compiler not complaining about defining 2 read properties and it does
otherwise when using both of them?

Any clue?

Thanks a lot.

April 20, 2015
On Monday, April 20, 2015 18:35:34 dvic via Digitalmars-d-learn wrote:
> Hi guys,
>
> It seems it's possible to define different read properties, only differing by the return type.

Not possible. Just like pretty much any C-derived language (C++, Java, C#, etc.) the return type of a function is not considered in function overloading, and it is illegal to overload a function based on its return type.

> Why is the compiler not complaining about defining 2 read
> properties and it does
> otherwise when using both of them?

Now, that is weird. I would fully expect something like

struct S
{
    @property int foo() { return 7; }
    @property string foo() { return "foo"; }
}

to result in an error, but for some reason, it doesn't (and it doesn't seem to have anything to do with the fact that it's a property function). I have no idea why and would be inclined to argue that it's a compiler bug (though a compiler dev may be able to come up with a good reason for why it's acting the way it is). However, since it _is_ failing to compile as soon as you use the function, the only real problem is that if you declare a function without ever testing it, you risk having a duplicate function without knowing it.  But still, I really think that the compiler should be giving an error message even if you don't call it.

- Jonathan M Davis

April 20, 2015
On 04/20/2015 11:35 AM, dvic wrote:

> @property string value() { return m_value; } // m_value is a string
> @property int value() { return to!int(m_value); }

Yes, as Jonathan M Davis said, that's weird.

> But when using it in writefln() or assert for example, compiler (dmd)
> complains
> about 2 different property signatures.
>
> What I'd like to have is this:
>
> MyObject.value = "12345"; // write property always setting a string
>
> assert(MyObject.value == "12345");  // depending on the context, call
> 1st prop
> assert(MyObject.value == 12345);  // depending on the context, call 2nd
> prop

I think that would work if multiple 'alias this' were allowed. (There is a pull request that does not pass some tests; that's why it is not included in 2.067.)

struct S
{
    int int_value() { /* ... */ }
    string string_value() { /* ... */ }

    alias int_value this;
    alias string_value this;

    // ...
}

The matching function would be called depending on whether S is used in place of an int or a string.

Ali

April 20, 2015
On 4/20/15 2:50 PM, Jonathan M Davis via Digitalmars-d-learn wrote:
> On Monday, April 20, 2015 18:35:34 dvic via Digitalmars-d-learn wrote:

>> Why is the compiler not complaining about defining 2 read
>> properties and it does
>> otherwise when using both of them?
>
> Now, that is weird. I would fully expect something like
>
> struct S
> {
>      @property int foo() { return 7; }
>      @property string foo() { return "foo"; }
> }
>
> to result in an error, but for some reason, it doesn't (and it doesn't seem
> to have anything to do with the fact that it's a property function).

There's an open bugzilla on this: https://issues.dlang.org/show_bug.cgi?id=2789

-Steve
April 20, 2015
On Monday, 20 April 2015 at 18:50:31 UTC, Jonathan M Davis wrote:
> On Monday, April 20, 2015 18:35:34 dvic via Digitalmars-d-learn wrote:
>> Hi guys,
>>
>> It seems it's possible to define different read properties, only
>> differing by the return type.
>
> Not possible. Just like pretty much any C-derived language (C++, Java, C#,
> etc.) the return type of a function is not considered in function
> overloading, and it is illegal to overload a function based on its return
> type.
>
>> Why is the compiler not complaining about defining 2 read
>> properties and it does
>> otherwise when using both of them?
>
> Now, that is weird. I would fully expect something like
>
> struct S
> {
>     @property int foo() { return 7; }
>     @property string foo() { return "foo"; }
> }
>
> to result in an error, but for some reason, it doesn't (and it doesn't seem
> to have anything to do with the fact that it's a property function). I have
> no idea why and would be inclined to argue that it's a compiler bug (though
> a compiler dev may be able to come up with a good reason for why it's acting
> the way it is). However, since it _is_ failing to compile as soon as you use
> the function, the only real problem is that if you declare a function
> without ever testing it, you risk having a duplicate function without
> knowing it.  But still, I really think that the compiler should be giving an
> error message even if you don't call it.
>
> - Jonathan M Davis


Thanks for your answer Jonathan. But does the return type part of a method
signature? I don't know what theory is claiming about that, but for me they
are 2 different methods. So contextually, the best fit should prevail.
April 20, 2015
On Monday, April 20, 2015 19:42:30 dvic via Digitalmars-d-learn wrote:
> Thanks for your answer Jonathan. But does the return type part of
> a method
> signature? I don't know what theory is claiming about that, but
> for me they
> are 2 different methods. So contextually, the best fit should
> prevail.

The return type is not considered in overloading. And it would complicate things considerably if it were. Some basic cases are pretty obvious, like

int foo();
string foo();
int a = foo()

But what about something like

int foo();
float foo();
auto a = foo() + foo();

or

int foo();
string foo();
void bar(int);
void bar(string);
bar(foo());

It's far simpler for the language to not consider return types in overloading and to simply use it for the type of the resulting expression. Then it's generally straightforward for it to determine what the type of complex expressions are. But if the return type is considered in overloading, then it gets _way_ more complicated, especially when the expressions get at all complicated.

At best, the compiler would be able to work in the simple cases and error out in the complex ones, but it wouldn't take much before it would have to give up and give an error due to ambiguity.

There may be languages out there which take the the return type into account when overloading, but I've never seen one.

- Jonathan M Davis

April 20, 2015
On Monday, 20 April 2015 at 20:22:40 UTC, Jonathan M Davis wrote:
> On Monday, April 20, 2015 19:42:30 dvic via Digitalmars-d-learn wrote:
>> Thanks for your answer Jonathan. But does the return type part of
>> a method
>> signature? I don't know what theory is claiming about that, but
>> for me they
>> are 2 different methods. So contextually, the best fit should
>> prevail.
>
> The return type is not considered in overloading. And it would complicate
> things considerably if it were. Some basic cases are pretty obvious, like
>
> int foo();
> string foo();
> int a = foo()
>
> But what about something like
>
> int foo();
> float foo();
> auto a = foo() + foo();
>
> or
>
> int foo();
> string foo();
> void bar(int);
> void bar(string);
> bar(foo());
>
> It's far simpler for the language to not consider return types in
> overloading and to simply use it for the type of the resulting expression.
> Then it's generally straightforward for it to determine what the type of
> complex expressions are. But if the return type is considered in
> overloading, then it gets _way_ more complicated, especially when the
> expressions get at all complicated.
>
> At best, the compiler would be able to work in the simple cases and error
> out in the complex ones, but it wouldn't take much before it would have to
> give up and give an error due to ambiguity.
>
> There may be languages out there which take the the return type into account
> when overloading, but I've never seen one.
>
> - Jonathan M Davis


Thanks Johnathan for the detailed explanation !
April 21, 2015
On Monday, 20 April 2015 at 20:22:40 UTC, Jonathan M Davis wrote:
> There may be languages out there which take the the return type into account
> when overloading, but I've never seen one.

Rust does, as far as I know.

I don't think that the ambiguities are an insurmountable obstacle. It's probably sufficient to error out when a call is ambiguous in its context, as can already happen during overloading.

Also note that, as Ali pointed out, with multiple alias this we will be able to implement this indirectly. Which means that the compiler needs to deal with exactly the same ambiguities anyway. Might as well just take the return type into consideration directly.
April 21, 2015
On Tuesday, 21 April 2015 at 13:27:48 UTC, Marc Schütz wrote:
> On Monday, 20 April 2015 at 20:22:40 UTC, Jonathan M Davis wrote:
>> There may be languages out there which take the the return type into account
>> when overloading, but I've never seen one.
>
> Rust does, as far as I know.

And this is incredibly frustrating approach that harms both readability and maintainability (you can't cut/paste RHS of an expression anymore without additional changes to the context). I have actually mentioned that when doing "first impressions" post about Rust.
April 21, 2015
On Tuesday, 21 April 2015 at 13:53:15 UTC, Dicebot wrote:
> On Tuesday, 21 April 2015 at 13:27:48 UTC, Marc Schütz wrote:
>> On Monday, 20 April 2015 at 20:22:40 UTC, Jonathan M Davis wrote:
>>> There may be languages out there which take the the return type into account
>>> when overloading, but I've never seen one.
>>
>> Rust does, as far as I know.
>
> And this is incredibly frustrating approach that harms both readability and maintainability (you can't cut/paste RHS of an expression anymore without additional changes to the context). I have actually mentioned that when doing "first impressions" post about Rust.

Considering ownership and all the compile-time checks Rust does, I'd say you generally can't just cut/paste any part of an expression, or even whole statements, and expect it to just work. Also, in Rust's case this doesn't really count as overloading but as a template instantiation.



BTW, the scope of this feature is much wider. Take a look at the channels example from the online book: http://doc.rust-lang.org/1.0.0-beta.2/book/concurrency.html#channels. Rust's type system is super strict, but mpsc::channel() doesn't specify the type of the stuff sent into the channel, and yet it is set correctly for both tx and rx.

What's happening here is this:

1) tx.send receives an argument(or doesn't receive an argument), which lets the compiler know what the type of tx is.
2) Now that the compiler knows what the type of tx is, it knows what the type of mpsc::channel is, because it needs to match tx.
3) At this point, type inferring rx's type is straightforward.

Now, Rust can do this because it has a super-strict type system. For D to be able to do this, it would have to completely reinvent it's type system, discarding many of it's idioms along the way, resulting at quite a different language.
« First   ‹ Prev
1 2