digitalmars.D.learn - Explain function syntax
- Brother Bill (22/22) Sep 17 In the following from Programming in D, page 483, we use function
- monkyyy (7/20) Sep 17 function is almost always wrong you need to be very pure to work
- H. S. Teoh (6/16) Sep 17 [...]
- Paul Backus (14/28) Sep 17 [Nested functions][1] that access local variables from their
- kdevel (17/18) Sep 18 ```d
- Luna (9/31) Sep 18 To give a proper reply, `function` is the a function pointer
- Dejan Lekic (38/46) Sep 18 Second int is the type of the first (and only) parameter.
- =?UTF-8?Q?Ali_=C3=87ehreli?= (10/10) Sep 18 As stated by multiple people, most nested functions will be 'delegates'....
- Steven Schveighoffer (45/57) Sep 18 You are mistaking the is expression for a function test with the
- =?UTF-8?Q?Ali_=C3=87ehreli?= (12/17) Sep 19 I disagree because it is impossible to mistake much from the
- Steven Schveighoffer (30/49) Sep 19 `is(T == function)`
- user1234 (9/12) Sep 21 Actually D has a syntax to expression function types:
- Steven Schveighoffer (11/23) Sep 21 Well, I was sure you couldn't do this! I thought the only way was
- user1234 (5/15) Sep 21 You're right, I forgot that detail. The change in 2.087 was made
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
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 delegateWhat does the second (int) refer to?it takes an int, just delete the names of the arguments from the header syntax
Sep 17
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
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
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
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
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 = ×2; 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
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
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
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
On Friday, 19 September 2025 at 16:58:38 UTC, Ali Çehreli wrote:On 9/18/25 10:18 PM, Steven Schveighoffer wrote:`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.On Thursday, 18 September 2025 at 18:10:13 UTC, Ali Çehreliwrote:// Not a delegate: static assert(is (typeof(twice) == function));You are mistaking the is expression for a function test withthefunction 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_expressionI 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
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
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: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... -SteveWhat 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
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... -SteveYou'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









monkyyy <crazymonkyyy gmail.com> 