www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Explain function syntax

reply Brother Bill <brotherbill mail.com> writes:
In the following from Programming in D, page 483, we use function 
keyword.

I expect that the first int in
```
int function(int);
```

represents the return value.

What does the second (int) refer to?

Then there is another example with 'delegate' instead of 
'function.

```
import std.stdio;

void main()
{

}

alias Calculator = int function(int);

Calculator makeCalculator()
{
	int increment = 10;
	return value => increment + value; // ← compilation ERROR
}

```
Sep 17
next sibling parent monkyyy <crazymonkyyy gmail.com> writes:
On Wednesday, 17 September 2025 at 22:16:50 UTC, Brother Bill 
wrote:
 ```
 import std.stdio;

 void main()
 {

 }

 alias Calculator = int function(int);

 Calculator makeCalculator()
 {
 	int increment = 10;
 	return value => increment + value; // ← compilation ERROR
 }

 ```
function is almost always wrong you need to be very pure to work at all and if by chance you ever have a function pointer you can convert it to a delegate
 What does the second (int) refer to?
it takes an int, just delete the names of the arguments from the header syntax
Sep 17
prev sibling next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Wed, Sep 17, 2025 at 10:16:50PM +0000, Brother Bill via Digitalmars-d-learn
wrote:
 In the following from Programming in D, page 483, we use function keyword.
 
 I expect that the first int in
 ```
 int function(int);
 ```
 
 represents the return value.
 
 What does the second (int) refer to?
[...] The type of the first (and in this case, only) parameter. T -- Being in debt attracts a lot of interest from banks.
Sep 17
prev sibling next sibling parent Paul Backus <snarwin gmail.com> writes:
On Wednesday, 17 September 2025 at 22:16:50 UTC, Brother Bill 
wrote:
 Then there is another example with 'delegate' instead of 
 'function.

 ```
 import std.stdio;

 void main()
 {

 }

 alias Calculator = int function(int);

 Calculator makeCalculator()
 {
 	int increment = 10;
 	return value => increment + value; // ← compilation ERROR
 }

 ```
[Nested functions][1] that access local variables from their enclosing function need to take an additional, hidden "context" parameter in order to actually find those variables at runtime. Because of this, they have a different calling convention than "normal" functions. As a consequence, if you take a pointer to one of these functions, you do not get a normal "function pointer" type (which is represented by the `function` keyword), but a special ["delegate" type][2], which contains both a pointer to the function itself, and a pointer to the context needed to call it successfully. [1]: https://dlang.org/spec/function.html#nested [2]: https://dlang.org/spec/function.html#closures
Sep 17
prev sibling next sibling parent kdevel <kdevel vogtner.de> writes:
On Wednesday, 17 September 2025 at 22:16:50 UTC, Brother Bill 
wrote:
 	return value => increment + value; // ← compilation ERROR
```d void main() { auto calc = makeCalculator; writeln (calc (1)); } alias Calculator = int function(int); Calculator makeCalculator() { enum increment = 10; // must not be a stack var return value => increment + value; } import std.stdio; ``` Compiles and prints 11.
Sep 18
prev sibling next sibling parent Luna <luna foxgirls.gay> writes:
On Wednesday, 17 September 2025 at 22:16:50 UTC, Brother Bill 
wrote:
 In the following from Programming in D, page 483, we use 
 function keyword.

 I expect that the first int in
 ```
 int function(int);
 ```

 represents the return value.

 What does the second (int) refer to?

 Then there is another example with 'delegate' instead of 
 'function.

 ```
 import std.stdio;

 void main()
 {

 }

 alias Calculator = int function(int);

 Calculator makeCalculator()
 {
 	int increment = 10;
 	return value => increment + value; // ← compilation ERROR
 }

 ```
To give a proper reply, `function` is the a function pointer type, in D function pointers are strongly typed using this keyword. `delegate` is a function pointer but with extra data along with it, to eg. a class function would be a delegate due to the hidden `this` pointer that tags along. in this case `int function(int)` means "A function which takes an integer argument, and returns an integer."
Sep 18
prev sibling next sibling parent Dejan Lekic <dejan.lekic gmail.com> writes:
On Wednesday, 17 September 2025 at 22:16:50 UTC, Brother Bill 
wrote:
 In the following from Programming in D, page 483, we use 
 function keyword.

 I expect that the first int in
 ```
 int function(int);
 ```

 represents the return value.

 What does the second (int) refer to?
Second int is the type of the first (and only) parameter. Functions and delegates may or may not have parameters, as you probably already know. Another D example that tries to demonstrate the difference between the two: ```d import std.stdio; int times2(int arg) { return arg * 2; } // function that takes an integer and returns an integer alias FunCalc = int function(int); // delegate that takes an integer and returns an integer alias DelCalc = int delegate(int); void main() { int foo = 2; int fooPlus(int arg) { return foo + arg; } // Works because times2 is a regular function FunCalc fn = &times2; writeln(fn(10)); // Output: 20 // Works because fooPlus is a nested function. Just like // lambdas and methods they have context pointer. fooPlus // uses the "foo" variable from the local context (scope in this case). DelCalc dg = &fooPlus; writeln(dg(10)); // Output: 12 foo = 5; writeln(dg(10)); // Output: 15 // Following will not be allowed as compiler detects that fooPlus // is actually a delegate (nested function) : // FunCalc funNotWorking = &fooPlus; } ```
Sep 18
prev sibling parent reply =?UTF-8?Q?Ali_=C3=87ehreli?= <acehreli yahoo.com> writes:
As stated by multiple people, most nested functions will be 'delegates'. 
However, a nested function is a 'function' if it does not touch local scope:

void main() {
     int twice(int i) {
         return i * 2;
     }

     // Not a delegate:
     static assert(is (typeof(twice) == function));
}

Ali
Sep 18
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Thursday, 18 September 2025 at 18:10:13 UTC, Ali Çehreli wrote:
 As stated by multiple people, most nested functions will be 
 'delegates'. However, a nested function is a 'function' if it 
 does not touch local scope:

 ```d
 void main() {
     int twice(int i) {
         return i * 2;
     }

     // Not a delegate:
     static assert(is (typeof(twice) == function));
 }
 ```
You are mistaking the is expression for a function test with the function pointer type. In fact, the compiler treats this as a function with a context pointer, because it's not static. Only function literals can be infer as a function pointer. Some demo code: ```d void main() { int x; int couldBeStatic(int i) { return i * 2; } int cantBeStatic(int i) { return i * x; } static assert(is(typeof(couldBeStatic) == function)); static assert(is(typeof(cantBeStatic) == function)); // function pointer is not a function static assert(!is(typeof(&couldBeStatic) == function)); static assert(!is(typeof(&cantBeStatic) == function)); // this one does not need a context pointer static int isStatic(int i) { return i * 2; } static assert(!__traits(compiles, {int function(int) fp = &couldBeStatic;})); static assert(!__traits(compiles, {int function(int) fp = &cantBeStatic;})); static assert( __traits(compiles, {int function(int) fp = &isStatic;})); static assert( __traits(compiles, {int delegate(int) dg = &couldBeStatic;})); static assert( __traits(compiles, {int delegate(int) dg = &cantBeStatic;})); static assert(!__traits(compiles, {int delegate(int) dg = &isStatic;})); // lambdas are more malleable static assert(__traits(compiles, {int function(int) fp = (int i) => i * 2;})); static assert(__traits(compiles, {int delegate(int) dg = (int i) => i * 2;})); } ``` -Steve
Sep 18
parent reply =?UTF-8?Q?Ali_=C3=87ehreli?= <acehreli yahoo.com> writes:
On 9/18/25 10:18 PM, Steven Schveighoffer wrote:
 On Thursday, 18 September 2025 at 18:10:13 UTC, Ali Çehreli wrote:
     // Not a delegate:
     static assert(is (typeof(twice) == function));
 You are mistaking the is expression for a function test with the
 function pointer type.
I disagree because it is impossible to mistake much from the documentation of the is expression: https://dlang.org/spec/expression.html#is_expression I stress strongly that there is not enough information there to take anything incorrectly. The reader has to construct a consistent mental model from that documentation. I did and my mental model is intact. I did test with 'function' against 'delegate' and it worked as I still understand it. For the example I wrote, 'is' expression succeeds for 'function' but not for 'delegate' if the nested function makes use of local scope. Ali
Sep 19
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Friday, 19 September 2025 at 16:58:38 UTC, Ali Çehreli wrote:
 On 9/18/25 10:18 PM, Steven Schveighoffer wrote:
 On Thursday, 18 September 2025 at 18:10:13 UTC, Ali Çehreli
wrote:
     // Not a delegate:
     static assert(is (typeof(twice) == function));
 You are mistaking the is expression for a function test with
the
 function pointer type.
I disagree because it is impossible to mistake much from the documentation of the is expression: https://dlang.org/spec/expression.html#is_expression
`is(T == function)` means, is `T` a type, and is it a *function* type. Not a *function pointer* type. What is a function type? It's the internal type that the compiler has for a function, which you actually cannot express in syntax. Note from my example how both functions that need context and functions that do not need context both satisfy this test. Because they are all functions.
 I stress strongly that there is not enough information there to 
 take anything incorrectly. The reader has to construct a 
 consistent mental model from that documentation. I did and my 
 mental model is intact.

 I did test with 'function' against 'delegate' and it worked as 
 I still understand it. For the example I wrote, 'is' expression 
 succeeds for 'function' but not for 'delegate' if the nested 
 function makes use of local scope.
```d void main() { int x; int iNeedContext() { return x; } static int iDontNeedContext() { return 5; } static assert(is(typeof(iNeedContext) == function)); static assert(is(typeof(iDontNeedContext) == function)); static assert(!is(typeof(&iNeedContext) == function)); static assert(!is(typeof(&iDontNeedContext) == function)); } ``` I don't know how to show it any clearer. `is(T == function)` is testing whether `T` is a function type, not whether it needs context. It is always false for types that are not functions (including function pointers or delegates). -Steve
Sep 19
parent reply user1234 <user1234 12.de> writes:
On Saturday, 20 September 2025 at 02:36:47 UTC, Steven 
Schveighoffer wrote:
 What is a function type? It's the internal type that the 
 compiler has for a function, which you actually cannot express 
 in syntax.
Actually D has a syntax to expression function types: ```d alias FT = void(int); void v(int a){} static assert(is(typeof(v) == function)); static assert(is(typeof(v) == FT)); ```
Sep 21
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On Sunday, 21 September 2025 at 20:33:11 UTC, user1234 wrote:
 On Saturday, 20 September 2025 at 02:36:47 UTC, Steven 
 Schveighoffer wrote:
 What is a function type? It's the internal type that the 
 compiler has for a function, which you actually cannot express 
 in syntax.
Actually D has a syntax to expression function types: ```d alias FT = void(int); void v(int a){} static assert(is(typeof(v) == function)); static assert(is(typeof(v) == FT)); ```
Well, I was sure you couldn't do this! I thought the only way was to use `typeof` on an actual function. But I stand corrected. Looking at historical compilers, the `alias ... =` syntax was added in 2.087.0. But before then, you could also do it like: ```d alias void FT(int); ``` Which gives me so much C vibes... -Steve
Sep 21
parent user1234 <user1234 12.de> writes:
On Monday, 22 September 2025 at 00:27:09 UTC, Steven 
Schveighoffer wrote:
 On Sunday, 21 September 2025 at 20:33:11 UTC, user1234 wrote:
 On Saturday, 20 September 2025 at 02:36:47 UTC, Steven 
 Schveighoffer wrote:
 Looking at historical compilers, the `alias ... =` syntax was 
 added in 2.087.0. But before then, you could also do it like:

 ```d
 alias void FT(int);
 ```

 Which gives me so much C vibes...

 -Steve
You're right, I forgot that detail. The change in 2.087 was made exactly because there's was no equivalent for the `alias =` syntax.
Sep 21