Thread overview
Function Parameters without Names?
Feb 19, 2022
Vijay Nayar
Feb 20, 2022
Ali Çehreli
Feb 20, 2022
Salih Dincer
Feb 20, 2022
Ali Çehreli
Feb 20, 2022
Stanislav Blinov
February 19, 2022

I encountered an odd bug in a project of mine which is illustrated in the example below:

class Thing {
  int val;
  this(int) {
    this.val = val;
  }
}

void main()
{
  auto t = new Thing(3);
  assert(t.val != 3);
}

The problem is that the parameter of the constructor actually has no name at all. Thus, the statement this.val = val simply sets the member variable to its own value, thus it stays the same as int.init.

According to the specification, this is permissible via the following grammar rules: FuncDeclaration => FuncDeclarator => FuncDeclaratorSuffix => Parameters => ParameterList => Parameter => Declarator => ParameterAttributes_opt Type.

What is the main motivator to allow parameters with no names? Do they get an automatic implied name like _ or something?

February 19, 2022
On 2/19/22 15:37, Vijay Nayar wrote:

> The problem is that the parameter of the constructor actually has no
> name at all. Thus, the statement `this.val = val` simply sets the member
> variable to its own value

Wow! I've never come accross that one before. :)

> What is the main motivator to allow parameters with no names?

This is common in C++ as well. You have to have a parameter because an interface requires it but you don't really have any use for that parameter. If you name it, then there may be "unused variable" warning. So, it is common to comment out the parameter name so that it is instructive to people who look at the code:

void foo(int /* length */) {
  // ...
}

> Do they get an automatic implied name like `_` or something?

The function is compiled to take the specified type of a parameter but it is simply not used. (Names are only for source code so it doesn't matter.)

Ali

February 20, 2022

On Saturday, 19 February 2022 at 23:37:01 UTC, Vijay Nayar wrote:

>

What is the main motivator to allow parameters with no names? Do they get an automatic implied name like _ or something?

The problem was about here, it should not be type inference: https://dlang.org/spec/function.html#function-attribute-inference

Do you think so? But it works when you open inactive codes and convert this(int) to this(T)! The program below throws an error about _param_0 when compiling because the inferred type is not int.

import std.conv;

class Foo
{
  int i;

  //   v=== type of inferred
  this(int)//(T i)
  {
    this.i = i;//.to!int;
  }

  string test()
  {
    return i.to!string;
  }
}

void main()
{
  long bar = 42;
  auto foo = new Foo(bar);
  assert(foo.test == "42"); /* Error:

  constructor `source.Foo.this(int _param_0)` is not callable using argument types `(long)`
  cannot pass argument `bar` of type `long` to parameter `int _param_0`

  */
}

The following doesn't work in a function outside the class:

TYPE foo(TYPE) { return 42; }

The compiler gives the following error:
undefined identifier TYPE

SDB@79

February 20, 2022

On Saturday, 19 February 2022 at 23:37:01 UTC, Vijay Nayar wrote:

>

What is the main motivator to allow parameters with no names?

  1. extern(C) void* malloc(size_t);

No need for parameter name at all as that is only a declaration. You don't have an implementation thus don't need a name for the parameter.

  1. As Ali says, unused parameters (i.e. in template specializations, virtual function overrides, dummy parameters for overload resolution purposes, etc.)
February 20, 2022
On 2/19/22 22:09, Salih Dincer wrote:

> The following doesn't work in a function outside the class:
> ```d
> TYPE foo(TYPE) { return 42; }
> ```
> The compiler gives the following error:
> ```undefined identifier TYPE```

I am not sure whether you are asking a question so apologies if I am stating the obvious. For (TYPE) to be a template parameter list, there must be the function parameter list as well:

TYPE foo(TYPE)() { return 42; }

<aside>
By the way, the fact that we can return the "int" 42 even when TYPE is e.g. 'short' is thanks to "value range propagation". The compilr sees that the manifest constant 42 fits in a short and compiles the code without complaint.

On the other hand, the following modification does not compile:

TYPE foo(TYPE)() {
  int r = 42;
  return r;  // <-- Compilation ERROR
// Error: cannot implicitly convert expression `r` of type `int` to `short`
}

void main() {
  foo!short();
}
</aside>

Getting back to the main topic, you may or may not need the function parameter list for a member function:

struct S(TYPE) {

  // This is not a template but a function
  // with the parameter name not omitted.
  // (TYPE is already known at this point.)
  TYPE foo(TYPE) {
    return 42;
  }

  // This is a member function template
  TYPE bar(TYPE2)() {
    // ...
  }
}

Ali

March 01, 2022

On 2/19/22 6:37 PM, Vijay Nayar wrote:

>

Do they get an automatic implied name like _ or something?

Yes, _param_0, _param_1, etc.

Don't depend on this though, I think it's an implementation detail.

-Steve