November 06, 2012
On 11/6/2012 9:26 AM, Adam D. Ruppe wrote:
> On Tuesday, 6 November 2012 at 17:16:34 UTC, Adam D. Ruppe wrote:
>>   [ExternalName("log-in")] /* we can do this now */
>>     void logIn([ExternalName("user-id")] string userId)
>
>
> BTW we could conceivably do:
>
> [ExternalName("log-in"),
> ParameterAttribute!("userId")(ExternalName("user-id")]
>     void logIn(string userId) {}
>
>
> Where the ParameterAttribute simply matches up the param by name or by position
> (if you pass an int instead of string) and puts the other argument in that map.
>
> When you scan the function for attributes, you keep your eye open for that
> ParameterAttribute thingy and match it up in the library.
>
>
> So if it is too painful to put it in the compiler, we could make it work in the
> library.

That looks like it can work. It's an interesting idea.

Other possibilities are:

1. Use a naming convention for the parameters, and then have an attribute for the function that more or less means that the function follows that naming convention. Naming conventions are often used in systems that don't have UDAs.

2. Use a user-defined wrapper type for the parameter. Then query for that type.
November 06, 2012
Am 06.11.2012 18:17, schrieb Walter Bright:> On 11/6/2012 9:06 AM, deadalnix wrote:> Le 06/11/2012 16:15, Walter Bright a écrit :
>   >> On 11/6/2012 5:14 AM, Adam D. Ruppe wrote:
>   >>> Hmmm, it didn't work on the most important place for my use case,
>   >>> function
>   >>> parameters:
>   >>
>   >> It didn't occur to me to enable that.
>   >>
>   >
>   > It should work everywhere or not work at all.
>
> You can't have @pure attributes on function parameters, either. Parameters don't
> work like regular declarations, never have, and I don't know of a language where
> they do. They even have a different grammar.
>

but why should an UDA only extend the semantic of regular declarations?

can't you please give us a bad-usage example why it is/should be forbidden to use UDA on parameters (and please - we are not talking about pure, in, out and stuff like that)
November 06, 2012
Am 06.11.2012 18:32, schrieb David Nadlinger:
> On Tuesday, 6 November 2012 at 17:00:27 UTC, Walter Bright wrote:
>> Ok, I ask again, what use case for a UDA is there for function
>> parameters? (Note that IDL isn't it, as D already has enough
>> parameter attributes to support IDL.)
>
> What »IDL« are you referring to here? At least as far as I am
> aware, IDL usually just refers to an »interface definition
> language« in general, so I'm not quite sure what you mean if you
> are talking about »enough to support IDL«.
>
> Actually, the Thrift IDL would be a perfect example of how
> attributes on parameters can be useful. A simple service
> definition in a .thrift could look like this:
>
> ---
> service Calculator {
>      i32 calculate(1:i32 a, 2:i32 b, 3:Op op)
> }

perfect example - thx alot

November 06, 2012
Am 06.11.2012 18:32, schrieb David Nadlinger:
> On Tuesday, 6 November 2012 at 17:00:27 UTC, Walter Bright wrote:
>> Ok, I ask again, what use case for a UDA is there for function
>> parameters? (Note that IDL isn't it, as D already has enough
>> parameter attributes to support IDL.)
>
> What »IDL« are you referring to here? At least as far as I am
> aware, IDL usually just refers to an »interface definition
> language« in general, so I'm not quite sure what you mean if you
> are talking about »enough to support IDL«.
>
> Actually, the Thrift IDL would be a perfect example of how
> attributes on parameters can be useful. A simple service
> definition in a .thrift could look like this:

http://svn.apache.org/repos/asf/thrift/trunk/tutorial/tutorial.thrift

November 06, 2012
On Tuesday, 6 November 2012 at 17:32:55 UTC, David Nadlinger wrote:
> Currently, the equivalent D code for the interface would look something like this:
>
> ---
> interface Calculator : SharedService {
>   int calculate(int a, int b, Op op);
>
>   enum methodMeta = [
>     TMethodMeta(`calculate`,
>       [TParamMeta(`a`, 1), TParamMeta(`b`, 2), TParamMeta(`op`, 3)]
>     )
>   ];
> }
> ---

(Note that this is actual code that has the intended result with DMD 2.060. Now with UDAs in the picture, one could obviously make TMethodMeta a method-level annotation.)

David
November 06, 2012
On 11/6/2012 9:32 AM, David Nadlinger wrote:
> On Tuesday, 6 November 2012 at 17:00:27 UTC, Walter Bright wrote:
>> Ok, I ask again, what use case for a UDA is there for function parameters?
>> (Note that IDL isn't it, as D already has enough parameter attributes to
>> support IDL.)
>
> What »IDL« are you referring to here? At least as far as I am aware, IDL usually
> just refers to an »interface definition language« in general, so I'm not quite
> sure what you mean if you are talking about »enough to support IDL«.

Back in the olden days, Microsoft released a language called IDL (Interface Definition Language) where you retyped your C function declarations and annotated them with in, out, and inout. This was used to connect with COM. I think Microsoft replaced it with extensions to the C compiler.


> Actually, the Thrift IDL would be a perfect example of how attributes on
> parameters can be useful. A simple service definition in a .thrift could look
> like this:
>
> ---
> service Calculator {
>     i32 calculate(1:i32 a, 2:i32 b, 3:Op op)

What does this mean? That 'a' is the first parameter and has type i32?

> }
> ---
>
> Note that the parameters are given explicit ids, similar to regular struct
> fields in Thrift, to provide robustness of the generated code against future RPC
> protocol changes (e.g. addition of parameters).
>
> Currently, the equivalent D code for the interface would look something like this:
>
> ---
> interface Calculator : SharedService {
>    int calculate(int a, int b, Op op);
>
>    enum methodMeta = [
>      TMethodMeta(`calculate`,
>        [TParamMeta(`a`, 1), TParamMeta(`b`, 2), TParamMeta(`op`, 3)]
>      )
>    ];
> }
> ---
>
> Being able to assign the IDs in-line using UDAs would make for a much more
> natural method declaration syntax.


November 06, 2012
Walter Bright:

> I don't see how having the user add a UDA is better than having the user add "const".

I am still referring to this:
http://forum.dlang.org/thread/znbtczbgipqqzllafmzk@forum.dlang.org

"const" is not enough.

Const is optional and it's useful for Case1, this means when you don't want to modify the struct (even if maybe sometimes you can't use a const, because not always is usable as const, like some ranges, but this is beside the point).

Often you want Case2 but you forget the "ref" so instead of Case2 you fall in Case3 by mistake.

So to avoid that common bug that proposal was to statically refuse code like this because it's ambiguous: is the programmer trying to use Case2 or Case3 here?

void main() {
    auto data = [0, 1, 2, 3];
    foreach (x; data)
        x++;
}


So you use:

// Case1
void main() {
    auto data = [0, 1, 2, 3];
    foreach (x; data)
        writeln(x);
    foreach (const x; data)
        writeln(x);
}

// Case2
void main() {
    auto data = [0, 1, 2, 3];
    foreach (ref x; data)
        x++;
}


// Case3 (uncommon)
void main() {
    auto data = [0, 1, 2, 3];
    foreach (@copy x; data)
        writeln(++x);
}

Bye,
bearophile
November 06, 2012
On 2012-11-06 17:04, Walter Bright wrote:

>> How about this then:
>>
>> @mtype("foo", 3, "bar") int a;
>>
>> And have the argument list be optional? I really like to have a short
>> nice
>> looking syntax for the simple use cases, i.e.
>>
>> @mtype int b;
>>
>
> There's a lot more you can do with the ArgumentList syntax than
> associative arrays. Furthermore, there remains the problem of how mtype
> fits into the name scoping system.

As I just wrote above, how about this:

@mtype("foo", 3, "bar") int a;
@mtype int b;

In the above example, the values in the parentheses would be the same as your ArgumentList. The important thing here is also to have the ArgumentList and parentheses be optional.

What's the issue with the name scoping system? That the user defined attributes will conflict with already existing attributes? You'll have the same problem with keywords. Perhaps that's why attributes where created, to have a new namespace for keywords. Even if they might not be the same internally for the compiler it's the same for the user/developer.

Just as we have operator overloading to allow user defined types to look like built-in types we/I want the same thing for user defined attributes.

-- 
/Jacob Carlborg
November 06, 2012
On Tuesday, 6 November 2012 at 17:51:28 UTC, Walter Bright wrote:
> On 11/6/2012 9:32 AM, David Nadlinger wrote:
>> service Calculator {
>>    i32 calculate(1:i32 a, 2:i32 b, 3:Op op)
>
> What does this mean? That 'a' is the first parameter and has type i32?

It means that ›a‹ has type i32 and is the parameter with ID 1. The parameter list could have also been (42:i32 a, 5:i32 b, 1:Op op). If no ids are specified, negative ones are auto-assigned by the compiler, starting from -1.

David
November 06, 2012
On 11/6/2012 9:34 AM, dennis luehring wrote:
> can't you please give us a bad-usage example why it is/should be forbidden to
> use UDA on parameters (and please - we are not talking about pure, in, out and
> stuff like that)

I believe this is the wrong question. For a new feature, the question should be "why should it be included", not "why shouldn't it be included."

For example, UDAs in general are not actually necessary. They can be faked using a naming convention, and such is very common. The trouble, though, is that if one uses UDAs a lot, then the complexity of the naming convention becomes unbearable.

It's become clear to me that UDAs can be used a lot, and so more targeted support for them is justified - i.e. a compelling use case.

It's hard to see that on parameters, though.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18