www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Properties no longer work?

reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Did properties stop working?

assuming object abc has a method foo:
# auto x = abc.foo;
gives a compiler error: x cannot be a function (or something like that)

If I change it to the following instead:
# auto x = abc.foo();
it works fine.

Here's an example:
--------
class ABC
{
	int foo() { return 10; }
}

void main()
{
	auto abc = new ABC();
	auto x = abc.foo;	
}
-----------

compiler message:
main.d(9): variable main.main.x cannot be declared to be a function

Like I said, if I add the brackets, it works fine:
-----------
class ABC
{
	int foo() { return 10; }
}

void main()
{
	auto abc = new ABC();
	auto x = abc.foo();	
}
---------

I'm suspecting this could be a bug or something, maybe due to the new 
delegate syntax.

If I change auto to int then it also works
---------
class ABC
{
	int foo() { return 10; }
}

void main()
{
	auto abc = new ABC();
	int x = abc.foo;
}
--------
Jul 25 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Hasan Aljudy" <hasan.aljudy gmail.com> wrote in message 
news:ea6fsm$2lb6$1 digitaldaemon.com...
 Did properties stop working?

 assuming object abc has a method foo:
 # auto x = abc.foo;
 gives a compiler error: x cannot be a function (or something like that)

Stop using type inference. ;) int x = abc.foo; When you write "abc.foo" as the initializer for a type-inferenced declaration, it tries to deduce the type of the declaration before converting the property access to a function call. Thus, it thinks you're trying to create a variable x with the same type as abc.foo; i.e. a function type (not a function pointer, just a function), which is illegal. This might be a bug, but it's been around for a while, and not just since 0.163.
Jul 25 2006
next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Jarrett Billingsley wrote:
 "Hasan Aljudy" <hasan.aljudy gmail.com> wrote in message 
 news:ea6fsm$2lb6$1 digitaldaemon.com...
 Did properties stop working?

 assuming object abc has a method foo:
 # auto x = abc.foo;
 gives a compiler error: x cannot be a function (or something like that)

Stop using type inference. ;) int x = abc.foo; When you write "abc.foo" as the initializer for a type-inferenced declaration, it tries to deduce the type of the declaration before converting the property access to a function call. Thus, it thinks you're trying to create a variable x with the same type as abc.foo; i.e. a function type (not a function pointer, just a function), which is illegal. This might be a bug, but it's been around for a while, and not just since 0.163.

Function types are just bizarre. I only recently discovered that C has them. Are you allowed to do anything with them, other than converting them to a function pointer by taking their address?
Jul 27 2006
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Don Clugston" <dac nospam.com.au> wrote in message 
news:eaajnj$1mo4$1 digitaldaemon.com...

 Function types are just bizarre. I only recently discovered that C has 
 them. Are you allowed to do anything with them, other than converting them 
 to a function pointer by taking their address?

I think they're mostly a "convenience" type for the compiler. Most of the time it's so hard to actually get a function type that I don't know what you'd do with it. I mean, you can't create variables of a function type; the only way you can do it is by declaring a function.
Jul 27 2006
prev sibling parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Don Clugston wrote:
 Jarrett Billingsley wrote:
 "Hasan Aljudy" <hasan.aljudy gmail.com> wrote in message 
 news:ea6fsm$2lb6$1 digitaldaemon.com...
 Did properties stop working?

 assuming object abc has a method foo:
 # auto x = abc.foo;
 gives a compiler error: x cannot be a function (or something like that)

Stop using type inference. ;) int x = abc.foo; When you write "abc.foo" as the initializer for a type-inferenced declaration, it tries to deduce the type of the declaration before converting the property access to a function call. Thus, it thinks you're trying to create a variable x with the same type as abc.foo; i.e. a function type (not a function pointer, just a function), which is illegal. This might be a bug, but it's been around for a while, and not just since 0.163.

Function types are just bizarre. I only recently discovered that C has them. Are you allowed to do anything with them, other than converting them to a function pointer by taking their address?

C has them? Where did you see that, I was under the impression that C only had function pointers, and they were all the same, such that the value a function was the same as the value of taking the address of the function: (func) == (&func) Similarly to what happens to arrays. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 27 2006
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bruno Medeiros" <brunodomedeirosATgmail SPAM.com> wrote in message 
news:eabhs0$2kkr$1 digitaldaemon.com...

 C has them? Where did you see that, I was under the impression that C only 
 had function pointers, and they were all the same, such that the value a 
 function was the same as the value of taking the address of the function:
 (func) == (&func)

I'm not sure, but I think that skipping the & on getting a function pointer in C is an "extension", or part of the newest standard that not all compilers support. Function types are allowed in C; you can't have an array of functions.
 Similarly to what happens to arrays.

Mm? I thought char x[]; x is char* &x is char**
Jul 27 2006
parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Jarrett Billingsley wrote:
 "Bruno Medeiros" <brunodomedeirosATgmail SPAM.com> wrote in message 
 news:eabhs0$2kkr$1 digitaldaemon.com...
 
 C has them? Where did you see that, I was under the impression that C only 
 had function pointers, and they were all the same, such that the value a 
 function was the same as the value of taking the address of the function:
 (func) == (&func)


Ok, I now realize they are subtly different: although the value is the same ( func) == (&func) ) , one can "&" a "func" but can't "&" a "&func" (ie, one can't indefinitely use operator "&") , so that's a small difference. :p
 
 I'm not sure, but I think that skipping the & on getting a function pointer 
 in C is an "extension", or part of the newest standard that not all 
 compilers support.
 

Nope, I think it's there since K&R ANSI C, although I don't have the book here with me to confirm.
 Function types are allowed in C; you can't have an array of functions.
 
 Similarly to what happens to arrays.

Mm? I thought char x[]; x is char* &x is char**

"char x[];" is not valid C. "char x[]" is only valid when there is an array initializer "char x[] = {...};", or as a function parameter type, but in this latter case it is not an array, it is a char pointer (char*). -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 29 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bruno Medeiros" <brunodomedeirosATgmail SPAM.com> wrote in message 
news:eafnr8$e4c$1 digitaldaemon.com...

 Nope, I think it's there since K&R ANSI C, although I don't have the book 
 here with me to confirm.

Hm.
 "char x[];" is not valid C. "char x[]" is only valid when there is an 
 array initializer "char x[] = {...};", or as a function parameter type, 
 but in this latter case it is not an array, it is a char pointer (char*).

Oh that's right; in C[++], arrays and pointers _are_ separate types, it's just that when you pass an array into a function, the type info is lost and it just becomes a pointer. That's why: char x[] = "hello"; printf("%d", sizeof(x)); Prints 6 (length of string + null char), but void fork(char x[]) // old-fashioned, same as "char* x" { printf("%d", sizeof(x)); } .. char x[] = "hello"; fork(x); prints 4 (the size of a char*). This is why I like D. Arrays are actually first-class types.
Jul 29 2006
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Bruno Medeiros wrote:
 Don Clugston wrote:

 Function types are just bizarre. I only recently discovered that C has 
 them. Are you allowed to do anything with them, other than converting 
 them to a function pointer by taking their address?

C has them? Where did you see that, I was under the impression that C only had function pointers, and they were all the same, such that the value a function was the same as the value of taking the address of the function: (func) == (&func) Similarly to what happens to arrays.

I discovered quite recently that C supports such oddities as typedef int qwert(char*); (if I've got the syntax right), thereby defining qwert to be an alias for a function of type int(char*). I've seen it in the LAM MPI headers. But as you say, it seems useless - AFAIK the only thing you can do with it is declare something of type pointer to qwert. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Jul 30 2006
parent reply Bruno Medeiros <brunodomedeirosATgmail SPAM.com> writes:
Stewart Gordon wrote:
 Bruno Medeiros wrote:
 Don Clugston wrote:

 Function types are just bizarre. I only recently discovered that C 
 has them. Are you allowed to do anything with them, other than 
 converting them to a function pointer by taking their address?

C has them? Where did you see that, I was under the impression that C only had function pointers, and they were all the same, such that the value a function was the same as the value of taking the address of the function: (func) == (&func) Similarly to what happens to arrays.

I discovered quite recently that C supports such oddities as typedef int qwert(char*); (if I've got the syntax right), thereby defining qwert to be an alias for a function of type int(char*). I've seen it in the LAM MPI headers. But as you say, it seems useless - AFAIK the only thing you can do with it is declare something of type pointer to qwert. Stewart.

I've quite recently discovered that D supports that as well! -> http://d.puremagic.com/issues/show_bug.cgi?id=270 But ah... there is a use for such a typedef after all. I thought they could not be used in declarations at all, but forgot about declaring a pointer to it. But still I don't know if they are worth the strange syntax. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jul 30 2006
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Bruno Medeiros wrote:
 Stewart Gordon wrote:

 I discovered quite recently that C supports such oddities as

     typedef int qwert(char*);

 (if I've got the syntax right), thereby defining qwert to be an alias 
 for a function of type int(char*).  I've seen it in the LAM MPI 
 headers.  But as you say, it seems useless - AFAIK the only thing you 
 can do with it is declare something of type pointer to qwert.

I've quite recently discovered that D supports that as well! -> http://d.puremagic.com/issues/show_bug.cgi?id=270 But ah... there is a use for such a typedef after all. I thought they could not be used in declarations at all, but forgot about declaring a pointer to it. But still I don't know if they are worth the strange syntax.

Can anyone think of a use case for this? I can't. Just declare a typedef or alias of the function pointer type and be done with it. UIMS there is nothing to be gained, besides empty complexity, by trying to support such things. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Aug 01 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:eaoc0i$309e$2 digitaldaemon.com...

 Can anyone think of a use case for this?  I can't.  Just declare a
 typedef or alias of the function pointer type and be done with it.  UIMS 
 there is nothing to be gained, besides empty complexity, by trying to 
 support such things.

Don't get so worked up about it. It'd probably be more complex to add in checking to make sure that you don't try to create an alias/typedef to a function type. And there's already checking in place to make sure that you don't use function types incorrectly.
Aug 01 2006
prev sibling parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 "Hasan Aljudy" <hasan.aljudy gmail.com> wrote in message 
 news:ea6fsm$2lb6$1 digitaldaemon.com...
 
Did properties stop working?

assuming object abc has a method foo:
# auto x = abc.foo;
gives a compiler error: x cannot be a function (or something like that)

Stop using type inference. ;) int x = abc.foo; When you write "abc.foo" as the initializer for a type-inferenced declaration, it tries to deduce the type of the declaration before converting the property access to a function call. Thus, it thinks you're trying to create a variable x with the same type as abc.foo; i.e. a function type (not a function pointer, just a function), which is illegal. This might be a bug, but it's been around for a while, and not just since 0.163.

It gets worse. If foo is overloaded, then DMD silently grabs the lexically first version and uses it. This is in direct contradiction of the idea that lexical order of functions/classes/etc. should not effect semantics. (I seem to recall that this is one of the goals of D, but I can't find the reference).
Jul 27 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eaarq2$1h47$1 digitaldaemon.com...

 It gets worse. If foo is overloaded, then DMD silently grabs the lexically 
 first version and uses it. This is in direct contradiction of the idea 
 that lexical order of functions/classes/etc. should not effect semantics. 
 (I seem to recall that this is one of the goals of D, but I can't find the 
 reference).

That is ugly. In fact, I even came up with a solution for it in my scripting language (before it was dynamically typed): an "overload resolution expression." It goes like this: void foo(int x) { } void foo(float x) { } &foo // ambiguous &foo.(int) // foo(int) overload &foo.(float) // foo(float) overload The dot is in there so that the parser doesn't interpret it as a function call. And as far as I know, there is no other syntax that allows the ".(" sequence.
Jul 27 2006
parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 "BCS" <BCS pathlink.com> wrote in message 
 news:eaarq2$1h47$1 digitaldaemon.com...
 
 
It gets worse. If foo is overloaded, then DMD silently grabs the lexically 
first version and uses it. This is in direct contradiction of the idea 
that lexical order of functions/classes/etc. should not effect semantics. 
(I seem to recall that this is one of the goals of D, but I can't find the 
reference).

That is ugly. In fact, I even came up with a solution for it in my scripting language (before it was dynamically typed): an "overload resolution expression."

 
 &foo // ambiguous
 &foo.(int) // foo(int) overload
 &foo.(float) // foo(float) overload
 
 The dot is in there so that the parser doesn't interpret it as a function 
 call.  And as far as I know, there is no other syntax that allows the ".(" 
 sequence. 
 

Nice. Looks a bit odd though, I'll have to think on that. Does D allow taking the address of a return value? Seems to me that could be used to disambiguate the resolution version from the function call version. I'm not sure how this would effect the context free aspect of the syntax. Alternately the [ Identifier "(" Type ] sequence shouldn't ever show up where a function call would be. This, however, still leave a problem with the "function taking void" type. humm byte foo(int); char foo(float); int foo(); auto a = foo(); // a is int auto b = &foo; // ambiguous auto c = &foo(int); // a is byte function(int) auto d = &foo(); // address of return | address of foo(/*void*/) auto e = &foo(void); // inconsistent but unambiguous
Jul 27 2006
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eab6vo$1h47$4 digitaldaemon.com...

 Does D allow taking the address of a return value? Seems to me that could 
 be used to disambiguate the resolution version from the  function call 
 version. I'm not sure how this would effect the context free aspect of the 
 syntax. Alternately the [ Identifier "(" Type ] sequence shouldn't ever 
 show up  where a function call would be. This, however, still leave a 
 problem with the "function taking void" type.

 humm


 byte foo(int);
 char foo(float);
 int foo();

 auto a = foo(); // a is int
 auto b = &foo; // ambiguous
 auto c = &foo(int); // a is byte function(int)
 auto d = &foo(); // address of return | address of foo(/*void*/)
 auto e = &foo(void); // inconsistent but unambiguous

Actually, thinking about it, the & wouldn't even be necessary. The overload resolution expression would simply return a function pointer. Then there wouldn't be any ambiguity of whether you're getting the function address or the address of the return value. auto a = foo(); auto b = &foo; // ambiguous auto c = foo.(int); // c is byte function(int) (or byte(int)*, as typeid call it) auto d = foo.(); // d is address of foo(); auto e = foo.(float); No need for foo.(void), which is good because you can't declare a function to take (void) as its arguments in D. And if you're right about the ident(type never showing up where a function call should, the dot might just be unnecessary.
Jul 27 2006
parent reply BCS <BCS pathlink.com> writes:
Jarrett Billingsley wrote:
 Actually, thinking about it, the & wouldn't even be necessary.  The overload 
 resolution expression would simply return a function pointer.  

I'd leave it. It would be more consistant. FunctionPointer ::= "&" FunctionSpecifier; FunctionSpecifier ::= FunctionIdentifier [ OverloadResolver ] OverloadResolver ::= ["." "(" TypeList ")" ] vs. // "&" befor OR resolver after, Hmmm. FunctionPointer ::= "&" FunctionIdentifier | FunctionIdentifier OverloadResolver; OverloadResolver ::= ["." "(" TypeList ")" ] (I don't think that the type of a ID is known at the syntax pass, but this illustrates the point)
 Then there
 wouldn't be any ambiguity of whether you're getting the function address or 
 the address of the return value.

It would still leave that problem. And I wouldn't count on address-of-returns being invalid. If const references get in, then a const reference to a return value might be handy (see below). I'll have to think some more on that one. // try something until sentinel is false; void fig(bool *const sentinel); bool quit; bool Quit(){return quit;} ... bool local; passToAnotherThread(&local); fig(&local); // time out from another thread quit = true; fig(&Quit()); // no timeout; quit = false; fig(&Quit()); // no blocking;
 
 auto a = foo();
 auto b = &foo; // ambiguous
 auto c = foo.(int); // c is byte function(int) (or byte(int)*, as typeid 
 call it)
 auto d = foo.(); // d is address of foo();
 auto e = foo.(float);
 
 No need for foo.(void), which is good because you can't declare a function 
 to take (void) as its arguments in D.
 
 And if you're right about the ident(type never showing up where a function 
 call should, the dot might just be unnecessary. 
 
 

Thinking about it the "Ident . ( Types )" syntax looks good.
Jul 27 2006
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"BCS" <BCS pathlink.com> wrote in message 
news:eabg5b$1h47$6 digitaldaemon.com...

 I'd leave it. It would be more consistant.

 FunctionPointer ::= "&" FunctionSpecifier;
 FunctionSpecifier ::= FunctionIdentifier [ OverloadResolver ]
 OverloadResolver ::= ["." "(" TypeList ")" ]

 vs.

 // "&" befor OR resolver after,   Hmmm.
 FunctionPointer ::=
 "&" FunctionIdentifier |
 FunctionIdentifier OverloadResolver;
 OverloadResolver ::= ["." "(" TypeList ")" ]

I think we could just skip the "&ident" form and make it required to use the "ident.()" form instead. So the only way to get a function pointer would be to use the overload resolve exp.
 It would still leave that problem.

Ah, I see; yeah, there'd be the problem if the "&ident" form were allowed, since it could be a property call (damn D "properties"). Get rid of that, though, and there's _no_ ambiguity ;)
 Thinking about it the "Ident . ( Types )" syntax looks good.

My rationale for it was that it's kind of selecting a member. "ident" declares a sort of namespace of functions with the same name, and you select the correct overload as if it were a member of that namespace.
Jul 27 2006