Thread overview
[variadics] syntactical sugar
Aug 16, 2005
Manfred Nowak
Aug 16, 2005
Ben Hinkle
Aug 17, 2005
Manfred Nowak
Aug 17, 2005
Ben Hinkle
Aug 17, 2005
Manfred Nowak
Aug 17, 2005
AJG
Aug 16, 2005
Derek Parnell
Aug 17, 2005
Manfred Nowak
August 16, 2005
The possibility to implement lists of equally typed formal parameters with variadics again raises the question of syntactical sugar to prevent ugliness.

For example a list of structs created on the fly currently would look at best like

1:  func( _( 1, "qwert"), _( 2, "asdf"), _( 3, "zxcv"));

If static initialization would be allowed:

2:  func( { 1, "qwert"}, { 2, "asdf"}, { 3, "zxcv"});

For me both possibilities look at bit uglier than:

3:  func( 1, "qwert")( 2, "asdf")( 3, "zxcv");

for which already was written, that it looks ugly enough to not use such notification.

So I again come up with the suggestion of a semicolon to separate the individual actual parameter lists:

4:  func( 1, "qwert"; 2, "asdf"; 3, "zxcv");

What do you suggest?

-manfred
August 16, 2005
I'm confused. What is the signature of func? What use cases did you have in mind?

"Manfred Nowak" <svv1999@hotmail.com> wrote in message news:ddtpfs$17c2$1@digitaldaemon.com...
> The possibility to implement lists of equally typed formal parameters with variadics again raises the question of syntactical sugar to prevent ugliness.
>
> For example a list of structs created on the fly currently would look at best like
>
> 1:  func( _( 1, "qwert"), _( 2, "asdf"), _( 3, "zxcv"));
>
> If static initialization would be allowed:
>
> 2:  func( { 1, "qwert"}, { 2, "asdf"}, { 3, "zxcv"});
>
> For me both possibilities look at bit uglier than:
>
> 3:  func( 1, "qwert")( 2, "asdf")( 3, "zxcv");
>
> for which already was written, that it looks ugly enough to not use such notification.
>
> So I again come up with the suggestion of a semicolon to separate the individual actual parameter lists:
>
> 4:  func( 1, "qwert"; 2, "asdf"; 3, "zxcv");
>
> What do you suggest?
>
> -manfred


August 16, 2005
On Tue, 16 Aug 2005 22:31:24 +0000 (UTC), Manfred Nowak wrote:

> The possibility to implement lists of equally typed formal parameters with variadics again raises the question of syntactical sugar to prevent ugliness.

[snip]
> 
> So I again come up with the suggestion of a semicolon to separate the individual actual parameter lists:
> 
> 4:  func( 1, "qwert"; 2, "asdf"; 3, "zxcv");

Just to clarify, this is a proposal to enable us to code struct literals as function arguments, right? How often is that actually used by people?

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
17/08/2005 9:12:31 AM
August 17, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote:

> I'm confused. What is the signature of func? What use cases did you have in mind?

Ooops, already in that matter for some days I did not realizee, that there might be a difficulty to see what I mean from the specs, that allow lists of arguments of same type T to be declared like:

Answering your first question:

   void func( T[] param ...){ };

If T is a primary type like `int' a call with literals would look like this:

   func( 1, 2, 3, 4);

If you are to use different types in the list, there is currently no solution with variadics, except that there is some regularity in the list, so that you can join adjacent parameters into a struct.

If T is a class or a struct S:

struct S{
  int i;
  char[] s;
}

a call with literals is not possible that easily. The known technic is to insert an opCall into struct S that initiliazes the struct S and returns it:

  S opCall( int ii, char[] si){
    i= ii;
    s= si;
    return *this;
  }

Thus one can code:

  void func( S[] param ...){ };
  S _;
  func( _( 1, "qwert"), _( 2, "asdf"));


Answering your second question:

a) Why didn't you ask that Walter when he introduced this feature
with version 0.126?
b) I am interested in features like this since a long time:
http://www.digitalmars.com/drn-bin/wwwnews?D/26867
c) I use this feature for initializations

   x.init( 1, 2, 3, 6);

or when I have to check whether a particular instance is in a given fixed set of possibilities:

  firstIsIn( _( x, y),
             _( 1, 2), _( 3, 6)
           );



I would prefer to write:

  firstIsIn( x, y;
             1, 2;  3, 6
           )

-manfred
August 17, 2005
Derek Parnell <derek@psych.ward> wrote:

[...]
> Just to clarify, this is a proposal to enable us to code struct literals as function arguments, right? How often is that actually used by people?

Not only struct literals can be used, but also instantiating classes and calling further variadics

According to your question: please look at my answer to Bens post and then: I do not know an answer to your question because currently nobody is forced to report his uses to me and I also believe that only very few users of D have already realized the benefits of programming with list-like structures.

If your question is to be taken more abstract in the sense of how much will this feature be used in the future, I declare to be willing to give an answer after you have stated the same thing you ask me for all the features that are already in the language.

My answer will follow the guidance you will give for justifying your estimations.

-manfred
August 17, 2005
"Manfred Nowak" <svv1999@hotmail.com> wrote in message news:ddu0b8$1dbm$1@digitaldaemon.com...
> "Ben Hinkle" <ben.hinkle@gmail.com> wrote:
>
>> I'm confused. What is the signature of func? What use cases did you have in mind?
>
> Ooops, already in that matter for some days I did not realizee, that there might be a difficulty to see what I mean from the specs, that allow lists of arguments of same type T to be declared like:
>
> Answering your first question:
>
>   void func( T[] param ...){ };
>
> If T is a primary type like `int' a call with literals would look like this:
>
>   func( 1, 2, 3, 4);
>
> If you are to use different types in the list, there is currently no solution with variadics, except that there is some regularity in the list, so that you can join adjacent parameters into a struct.
>
> If T is a class or a struct S:
>
> struct S{
>  int i;
>  char[] s;
> }
>
> a call with literals is not possible that easily. The known technic is to insert an opCall into struct S that initiliazes the struct S and returns it:
>
>  S opCall( int ii, char[] si){
>    i= ii;
>    s= si;
>    return *this;
>  }
>
> Thus one can code:
>
>  void func( S[] param ...){ };
>  S _;
>  func( _( 1, "qwert"), _( 2, "asdf"));

OK - I see what you mean. (ps - love the _ :-)

> Answering your second question:
>
> a) Why didn't you ask that Walter when he introduced this feature with version 0.126?

The typesafe vararg is fine with me. I was asking for use cases for the special struct sugar.

> b) I am interested in features like this since a long time: http://www.digitalmars.com/drn-bin/wwwnews?D/26867

Yeah I remember those. That was when vararg discussions were all the rage and how to do printf or C++ <<-style io etc etc. Fun stuff.

> c) I use this feature for initializations
>
>   x.init( 1, 2, 3, 6);

You mean for some init(int[] param ...), I presume. In other words the init call above works today, correct?

> or when I have to check whether a particular instance is in a given fixed set of possibilities:
>
>  firstIsIn( _( x, y),
>             _( 1, 2), _( 3, 6)
>           );
>
> I would prefer to write:
>
>  firstIsIn( x, y;
>             1, 2;  3, 6
>           )

What does firstIsIn do? I'm not getting it. But this was exactly what I was looking for when I asked for use cases. By "use case" I mean a (preferrably common) coding pattern or construct that would be made much easier with this sugar.

Stepping back I wonder if the oft-requested ability to create structs in expressions would be good enough. The firstIsIn(x,y;1,2;3,6) is definitely the most compact syntax we could use but why add a special case for the nearly equally simple firstIsIn(S{x,y},S{1,2},S{3,6}) or whatever the magic syntax will be for struct-expressions. The struct S already needs to be defined in order to write the declaration of firstIsIn (unless you also want to change the syntax for typesafe varargs).

>
> -manfred


August 17, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote:

[...]
> You mean for some init(int[] param ...), I presume. In other words the init call above works today, correct?

Yes, that works.


>> or when I have to check whether a particular instance is in a given fixed set of possibilities:
[...]
> What does firstIsIn do? I'm not getting it. But this was exactly what I was looking for when I asked for use cases. By "use case" I mean a (preferrably common) coding pattern or construct that would be made much easier with this sugar.

Because it is sugar only, there is no case where the "much" is justified. The coding pattern you ask for I already described above: "check whether a particular instance is in a given fixed set of possibilities". Therefore in the given example firstIsIn checks, whether the coordinate (x,y) is in the set of coordinates that follows. In the example a set consisting of the two coordinates {(1,2), (3,6)}. But the list might also be interpreted as a list of rectangles. Then firstIsIn checks whether ( x, y) is in the rectangle denoted by the coordinates ( (1,2) , ( 3,6)).


> Stepping back I wonder if the oft-requested ability to create structs in expressions would be good enough. The firstIsIn(x,y;1,2;3,6) is definitely the most compact syntax we could use but why add a special case for the nearly equally simple firstIsIn(S{x,y},S{1,2},S{3,6}) or whatever the magic syntax will be for struct-expressions. The struct S already needs to be defined in order to write the declaration of firstIsIn (unless you also want to change the syntax for typesafe varargs).

Right, the struct S and the opCalls of S has to be defined in order to use `firstIsIn' in this example. And yes, in this example the suggested syntax sugar saves only three characters per instantiation. But when I introduced the FSM on signatures, in my post mentioned above, there were replies that a surplus of only one character per instantiation renders my suggestion at that time as unusable: the one additional character in `)(' against `;'.

But the mere syntax sugar, that my suggestion is in this case may turn out to be really usefull in other cases of variadics. In http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/4713 I posted, that an ambiguity using variadics is currently not detected.

But the ambiguity stems from the fact, that the start of the parameter list for the instantiation of the class currently can not be marked sufficiently enough. If a semicolon must be used to mark the start of the parameter list for the instantiation the call

  test( 1, 1)

must belong to the overload

  void test( Foo f ...){}

and the call

  test( 1; 1)

must belong to the overload

  void test( int x, Foo f ...){}

Because I have not thaught of this usage before, my suggestion may turn out, to be not only syntactical sugar.

-manfred
August 17, 2005
Hi,

>But the ambiguity stems from the fact, that the start of the parameter list for the instantiation of the class currently can not be marked sufficiently enough. If a semicolon must be used to mark the start of the parameter list for the instantiation the call
>  test( 1, 1)
>must belong to the overload
>  void test( Foo f ...){}
>and the call
>  test( 1; 1)
>must belong to the overload
>  void test( int x, Foo f ...){}

Hm... I think I agree with the syntax you propose. It makes sense to delineate
clearly which subset(s) of the parameter list belongs to which of
1) object instantiation
2) struct creation.
3) regular parameter.

Cheers,
--AJG.