www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - About function keyword

reply deadalnix <deadalnix gmail.com> writes:
Hi,

I was working with std.concurrency and discovered a (now reported) bug 
about receive and function. It lead me to some experimentations with 
fucntions. consider the code bellow :

module funtest;

import std.stdio;

void infos(T)(T fun) {
	writeln(typeof(fun).stringof);
	writeln("is function ? : ", is(T == function)); // Always false
	writeln("is delegate ? : ", is(T == delegate)); // true if we have a 
delegate
}

int doNothing() { return 0; }

void main() {
	infos(doNothing); // Evaluate even if it isn't  property . Expected 
behaviour ?
	infos(&doNothing);
	auto fun = &doNothing; infos(&fun);
	infos(function int() { return 0; });
	infos(delegate int() { return 0; });
	infos(() { return 0; }); // Delegate ??
}

And its output :

int
is function ? : false
is delegate ? : false
int function()
is function ? : false
is delegate ? : false
int function()*
is function ? : false
is delegate ? : false
int function() pure nothrow  safe
is function ? : false
is delegate ? : false
int delegate() pure nothrow  safe
is function ? : false
is delegate ? : true
int delegate() pure nothrow
is function ? : false
is delegate ? : true

Now some strange stuff happens. I wonder if they all are intended. First 
of all, in the first case, doNothing is evaluated, even with no () . 
This function isn't  property, so this behaviour is somehow misleading 
and error prone.

When passing a delegate, is(T == delegate) is true, but when passing a 
function is(T == function) is false. This is also misleading and 
inconsistent. This lead to the bugs in std.concurrency I faced.

When it is not specifiate if something is a delegate or a function, the 
compiler always makes it a delegate. Is it intended ? This can create 
some overhead in many cases for nothing. Plus, this si always possible 
to wrap a function into a delegate, but the other way around isn't 
possible. So the compiler should do its best to make a function whatever 
can be one.

Even if it is not in the code snippet, typeof(doNothing).stringof is 
int() . When doNothing is passed, it is evaluated, and we get an int. 
Theses 2 results are counter intuitives, and this is a types of things 
that we want to avoid in D.

So, what is a bug ? What is an expected behaviour ? What isn't 
defined/decided yet ? And what do we decide if it is so ?
Dec 10 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
deadalnix:

 in the first case, doNothing is evaluated, even with no () . 
 This function isn't  property, so this behaviour is somehow misleading 
 and error prone.

This needs to change.
 When passing a delegate, is(T == delegate) is true, but when passing a 
 function is(T == function) is false. This is also misleading and 
 inconsistent.

This too needs to change. Is this already in Bugzilla? There are so many important things to fix in D... Bye, bearophile
Dec 10 2011
parent deadalnix <deadalnix gmail.com> writes:
Le 10/12/2011 23:42, bearophile a écrit :
 deadalnix:

 in the first case, doNothing is evaluated, even with no () .
 This function isn't  property, so this behaviour is somehow misleading
 and error prone.

This needs to change.
 When passing a delegate, is(T == delegate) is true, but when passing a
 function is(T == function) is false. This is also misleading and
 inconsistent.

This too needs to change. Is this already in Bugzilla? There are so many important things to fix in D... Bye, bearophile

Nothing is filled in bugzilla expect the fact that std.concurency is broken. The fact is, I don't know what is intended or not here, and we lack a precise specification - or I'm not aware of it. So this has to be decided/confirmed as being a bug before I fill it in the bugtracker.
Dec 10 2011
prev sibling next sibling parent reply kenji hara <k.hara.pg gmail.com> writes:
2011/12/11 deadalnix <deadalnix gmail.com>:
 Hi,

 I was working with std.concurrency and discovered a (now reported) bug ab=

 receive and function. It lead me to some experimentations with fucntions.
 consider the code bellow :

 module funtest;

 import std.stdio;

 void infos(T)(T fun) {
 =A0 =A0 =A0 =A0writeln(typeof(fun).stringof);
 =A0 =A0 =A0 =A0writeln("is function ? : ", is(T =3D=3D function)); // Alw=

 =A0 =A0 =A0 =A0writeln("is delegate ? : ", is(T =3D=3D delegate)); // tru=

 delegate
 }

 int doNothing() { return 0; }

 void main() {
 =A0 =A0 =A0 =A0infos(doNothing); // Evaluate even if it isn't  property .=

 behaviour ?
 =A0 =A0 =A0 =A0infos(&doNothing);
 =A0 =A0 =A0 =A0auto fun =3D &doNothing; infos(&fun);
 =A0 =A0 =A0 =A0infos(function int() { return 0; });
 =A0 =A0 =A0 =A0infos(delegate int() { return 0; });
 =A0 =A0 =A0 =A0infos(() { return 0; }); // Delegate ??
 }

 And its output :

 int
 is function ? : false
 is delegate ? : false
 int function()
 is function ? : false
 is delegate ? : false
 int function()*
 is function ? : false
 is delegate ? : false
 int function() pure nothrow  safe
 is function ? : false
 is delegate ? : false
 int delegate() pure nothrow  safe
 is function ? : false
 is delegate ? : true
 int delegate() pure nothrow
 is function ? : false
 is delegate ? : true

 Now some strange stuff happens. I wonder if they all are intended. First =

 all, in the first case, doNothing is evaluated, even with no () . This
 function isn't  property, so this behaviour is somehow misleading and err=

 prone.

If you don't specify -property switch in command line, `doNothing` is implicitly converted to `doNothing()` for backward compatibility. It is correct behavior.
 When passing a delegate, is(T =3D=3D delegate) is true, but when passing =

 function is(T =3D=3D function) is false. This is also misleading and
 inconsistent. This lead to the bugs in std.concurrency I faced.

 When it is not specifiate if something is a delegate or a function, the
 compiler always makes it a delegate. Is it intended ? This can create som=

 overhead in many cases for nothing. Plus, this si always possible to wrap=

 function into a delegate, but the other way around isn't possible. So the
 compiler should do its best to make a function whatever can be one.

 Even if it is not in the code snippet, typeof(doNothing).stringof is int(=

 When doNothing is passed, it is evaluated, and we get an int. Theses 2
 results are counter intuitives, and this is a types of things that we wan=

 to avoid in D.

 So, what is a bug ? What is an expected behaviour ? What isn't
 defined/decided yet ? And what do we decide if it is so ?

is(X =3D=3D function) checks whether the X is a function type. For example, this code can compile without error. static assert(is(typeof(doNothing) =3D=3D function)); doNothing is non-property free function, so its type is function type. I agree that is(X =3D=3D function) is bit difficult to understand, but it is consistent feature and there is no bug. Kenji Hara
Dec 10 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/11/2011 12:35 AM, kenji hara wrote:
 2011/12/11 deadalnix<deadalnix gmail.com>:
 Hi,

 I was working with std.concurrency and discovered a (now reported) bug about
 receive and function. It lead me to some experimentations with fucntions.
 consider the code bellow :

 module funtest;

 import std.stdio;

 void infos(T)(T fun) {
         writeln(typeof(fun).stringof);
         writeln("is function ? : ", is(T == function)); // Always false
         writeln("is delegate ? : ", is(T == delegate)); // true if we have a
 delegate
 }

 int doNothing() { return 0; }

 void main() {
         infos(doNothing); // Evaluate even if it isn't  property . Expected
 behaviour ?
         infos(&doNothing);
         auto fun =&doNothing; infos(&fun);
         infos(function int() { return 0; });
         infos(delegate int() { return 0; });
         infos(() { return 0; }); // Delegate ??
 }

 And its output :

 int
 is function ? : false
 is delegate ? : false
 int function()
 is function ? : false
 is delegate ? : false
 int function()*
 is function ? : false
 is delegate ? : false
 int function() pure nothrow  safe
 is function ? : false
 is delegate ? : false
 int delegate() pure nothrow  safe
 is function ? : false
 is delegate ? : true
 int delegate() pure nothrow
 is function ? : false
 is delegate ? : true

 Now some strange stuff happens. I wonder if they all are intended. First of
 all, in the first case, doNothing is evaluated, even with no () . This
 function isn't  property, so this behaviour is somehow misleading and error
 prone.

If you don't specify -property switch in command line, `doNothing` is implicitly converted to `doNothing()` for backward compatibility. It is correct behavior.
 When passing a delegate, is(T == delegate) is true, but when passing a
 function is(T == function) is false. This is also misleading and
 inconsistent. This lead to the bugs in std.concurrency I faced.

 When it is not specifiate if something is a delegate or a function, the
 compiler always makes it a delegate. Is it intended ? This can create some
 overhead in many cases for nothing. Plus, this si always possible to wrap a
 function into a delegate, but the other way around isn't possible. So the
 compiler should do its best to make a function whatever can be one.

 Even if it is not in the code snippet, typeof(doNothing).stringof is int() .
 When doNothing is passed, it is evaluated, and we get an int. Theses 2
 results are counter intuitives, and this is a types of things that we want
 to avoid in D.

 So, what is a bug ? What is an expected behaviour ? What isn't
 defined/decided yet ? And what do we decide if it is so ?

is(X == function) checks whether the X is a function type. For example, this code can compile without error. static assert(is(typeof(doNothing) == function)); doNothing is non-property free function, so its type is function type. I agree that is(X == function) is bit difficult to understand, but it is consistent feature and there is no bug. Kenji Hara

There is no bug, but it is not consistent. void delegate() x; void function() y; static assert(is(x == delegate)); // fine static assert(is(y == function)); // fail
Dec 10 2011
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 11/12/2011 00:35, kenji hara a écrit :
 is(X == function) checks whether the X is a function type.
 For example, this code can compile without error.

 static assert(is(typeof(doNothing) == function));

 doNothing is non-property free function, so its type is function type.

Well, this is true. But this isn't usable due to the autoevaluation, see first case.
 I agree that is(X == function) is bit difficult to understand, but it
 is consistent feature and there is no bug.

 Kenji Hara

This is not a problem of understanding. This is a problem of consistency, and usefullness. When you look at the types given, the only one that could be true using is(X == function) is one where the function keyword does not appears (int() ). All types using the keyword function will evaluate this expression to false. This inconsistency (1). Plus, objects of this type cannot be passed around because it realize a function call and pass the result. Expect in some very hacky way, you cannot ends up with is(X == function) evaluating to true. Plus, when you look at the behaviour of delegate, this is clearly inconsistent. This is inconsistency (2). In addition, this is error prone. As matter of facts, experienced programmer did make a mistake with that, without even noticing it ! To me, if it is specified that way, ok, this isn't a compiler bug. In this case, this is a specification bug.
Dec 11 2011
prev sibling parent kenji hara <k.hara.pg gmail.com> writes:
2011/12/11 Timon Gehr <timon.gehr gmx.ch>:
 On 12/11/2011 12:35 AM, kenji hara wrote:
 2011/12/11 deadalnix<deadalnix gmail.com>:
 Hi,

 I was working with std.concurrency and discovered a (now reported) bug
 about
 receive and function. It lead me to some experimentations with fucntion=



 consider the code bellow :

 module funtest;

 import std.stdio;

 void infos(T)(T fun) {
 =A0 =A0 =A0 =A0writeln(typeof(fun).stringof);
 =A0 =A0 =A0 =A0writeln("is function ? : ", is(T =3D=3D function)); // A=



 =A0 =A0 =A0 =A0writeln("is delegate ? : ", is(T =3D=3D delegate)); // t=



 a
 delegate
 }

 int doNothing() { return 0; }

 void main() {
 =A0 =A0 =A0 =A0infos(doNothing); // Evaluate even if it isn't  property=



 Expected
 behaviour ?
 =A0 =A0 =A0 =A0infos(&doNothing);
 =A0 =A0 =A0 =A0auto fun =3D&doNothing; infos(&fun);

 =A0 =A0 =A0 =A0infos(function int() { return 0; });
 =A0 =A0 =A0 =A0infos(delegate int() { return 0; });
 =A0 =A0 =A0 =A0infos(() { return 0; }); // Delegate ??
 }

 And its output :

 int
 is function ? : false
 is delegate ? : false
 int function()
 is function ? : false
 is delegate ? : false
 int function()*
 is function ? : false
 is delegate ? : false
 int function() pure nothrow  safe
 is function ? : false
 is delegate ? : false
 int delegate() pure nothrow  safe
 is function ? : false
 is delegate ? : true
 int delegate() pure nothrow
 is function ? : false
 is delegate ? : true

 Now some strange stuff happens. I wonder if they all are intended. Firs=



 of
 all, in the first case, doNothing is evaluated, even with no () . This
 function isn't  property, so this behaviour is somehow misleading and
 error
 prone.

If you don't specify -property switch in command line, `doNothing` is implicitly converted to `doNothing()` for backward compatibility. It is correct behavior.
 When passing a delegate, is(T =3D=3D delegate) is true, but when passin=



 function is(T =3D=3D function) is false. This is also misleading and
 inconsistent. This lead to the bugs in std.concurrency I faced.

 When it is not specifiate if something is a delegate or a function, the
 compiler always makes it a delegate. Is it intended ? This can create
 some
 overhead in many cases for nothing. Plus, this si always possible to wr=



 a
 function into a delegate, but the other way around isn't possible. So t=



 compiler should do its best to make a function whatever can be one.

 Even if it is not in the code snippet, typeof(doNothing).stringof is
 int() .
 When doNothing is passed, it is evaluated, and we get an int. Theses 2
 results are counter intuitives, and this is a types of things that we
 want
 to avoid in D.

 So, what is a bug ? What is an expected behaviour ? What isn't
 defined/decided yet ? And what do we decide if it is so ?

is(X =3D=3D function) checks whether the X is a function type. For example, this code can compile without error. static assert(is(typeof(doNothing) =3D=3D function)); doNothing is non-property free function, so its type is function type. I agree that is(X =3D=3D function) is bit difficult to understand, but i=


 is consistent feature and there is no bug.

 Kenji Hara

There is no bug, but it is not consistent. void delegate() x; void function() y;

In here, x and y are variables, not types. Perhaps your assuming is: alias void delegate() x; alias void function() y;
 static assert(is(x =3D=3D delegate)); // fine
 static assert(is(y =3D=3D function)); // fail

Yes, it is syntactic problem. Better syntax and keyword would become the learning more easier. Kenji Hara
Dec 10 2011