digitalmars.D - User Defined Attributes (UDA) in Phobos/druntime
- Jacob Carlborg (32/32) Jun 11 2013 This was brought up in the thread reviewing std.serialization:
- Walter Bright (4/5) Jun 11 2013 I'd like to see more use of UDAs in non-Phobos code so we can figure out...
- Peter Alexander (2/7) Jun 11 2013 Wise words. +1
- Jonas Drewsen (10/15) Jun 11 2013 Though I might not agree with this suggested meta-attribute thing
- Jacob Carlborg (10/14) Jun 11 2013 The generic code for attributes is located in orange.core.Attribute,
- Jacob Carlborg (4/6) Jun 11 2013 The template mixins basically emulates UDA's.
- Steven Schveighoffer (8/20) Jun 11 2013 I think we can have and use UDAs in Phobos without yet having to create ...
- Idan Arye (5/10) Jun 11 2013 I disagree - if you wait for UDAs to appear more in user-code,
- John Colvin (3/12) Jun 11 2013 That's what we want, surely: Multiple conventions appear, then
- deadalnix (3/8) Jun 12 2013 That sound good, but the complete opposite have been done every
- SomeDude (3/12) Jun 12 2013 And that's why Walter wants to avoid repeating the same mistakes
- Idan Arye (9/27) Jun 11 2013 Camel case has two versions - and I suggest to use the one that
- Jonathan M Davis (4/6) Jun 11 2013 The term pascal case is frequently used when referring to the variant of...
- QAston (7/40) Jun 11 2013 I agree that attributes should have types - that way it's easily
- Jacob Carlborg (9/15) Jun 11 2013 It shows the intent of the type. D both have a keywords to indicate an
- QAston (19/37) Jun 11 2013 Ok, i see the point now, thanks :). Maybe it'd be worth to
- Idan Arye (5/8) Jun 11 2013 How about passing template arguments to `@attribute` to determine
- QAston (2/6) Jun 12 2013 Yes, I think something like this solves interoperation issues.
- Jacob Carlborg (9/19) Jun 11 2013 Yes, I would like to have the language enforce this. My utility function...
- QAston (11/22) Jun 12 2013 Accrding to this http://dpaste.dzfl.pl/728872fa it's not possible
- Andrej Mitrovic (33/35) Jun 12 2013 But without this you lose the ability to customize. I don't like just
- deadalnix (2/10) Jun 12 2013 Both are 100% orthogonal
- Jacob Carlborg (6/38) Jun 12 2013 As far as I know other language allows UDA's to be of any type/value.
This was brought up in the thread reviewing std.serialization: http://forum.dlang.org/thread/adyanbsdsxsfdpvoozne forum.dlang.org Currently we haven't started to use UDA's in Phobos or druntime yet (as far as I know). I would like to start a discussion about putting out some guidelines for using UDA's in Phobos/druntime. I've created a small module that handles UDA's: https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d The idea is to have a kind of meta UDA called "attribute". This attribute needs to be attached to all structs, enums and so on that is to be used as an attribute. The module provides a template (getAttributes) to get, by default, only those values attached to a given symbol that is an attribute. That is, marked with the "attribute" attribute. So my suggestion for guidelines are: * Only types with the "attribute" UDA is to be used as attributes * In general, don't use primitive values as a UDA Don't use this (3) int a; Use this: attribute struct foo { int b; } foo(3) int a; * A user defined type marked with "attribute" should not be used for something else than an UDA * All attributes use camel case names If we agree on this and that we need a module like the one above I think it should be added to druntime. The reason for that is that we most likely want to use UDA's in druntime and not only in Phobos. Example, if we ever get std.serialization into Phobos we would want to mark Thread and similar structs/classes as "nonSerialized". Thoughts? -- /Jacob Carlborg
Jun 11 2013
On 6/11/2013 12:00 AM, Jacob Carlborg wrote:Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 11 2013
On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:On 6/11/2013 12:00 AM, Jacob Carlborg wrote:Wise words. +1Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 11 2013
On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:On 6/11/2013 12:00 AM, Jacob Carlborg wrote:Though I might not agree with this suggested meta-attribute thing I really think that serialization screams for using attributes to mark fields/classes as serializable. Would be sad not to have them. Jacob: Would it be doable to refactor the attribute magic in std.serialization into a separate module that could be provided as 3rd party extension to std.serialization until phobos itself is ready for attributes? /JonasThoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 11 2013
On 2013-06-11 11:07, Jonas Drewsen wrote:Jacob: Would it be doable to refactor the attribute magic in std.serialization into a separate module that could be provided as 3rd party extension to std.serialization until phobos itself is ready for attributes?The generic code for attributes is located in orange.core.Attribute, this can be inlined or removed. The actual attributes them self are located in orange.serialization.Serializable. The library is perfectly usable without UDA's. The old template mixins are still available. If __traits(getAttributes) is not allowed in Phobos then I have to remove the code that checks for UDA's. -- /Jacob Carlborg
Jun 11 2013
On 2013-06-11 11:58, Jacob Carlborg wrote:The library is perfectly usable without UDA's. The old template mixins are still available.The template mixins basically emulates UDA's. -- /Jacob Carlborg
Jun 11 2013
On Tue, 11 Jun 2013 05:58:50 -0400, Jacob Carlborg <doob me.com> wrote:On 2013-06-11 11:07, Jonas Drewsen wrote:I think we can have and use UDAs in Phobos without yet having to create a guideline. Note that there is lots of experience with attributes in other languages that we can draw from. Most people here have written in at least one other language that uses them. I have no problem with std.serialization using attributes, even if there is no "official" guide. -SteveJacob: Would it be doable to refactor the attribute magic in std.serialization into a separate module that could be provided as 3rd party extension to std.serialization until phobos itself is ready for attributes?The generic code for attributes is located in orange.core.Attribute, this can be inlined or removed. The actual attributes them self are located in orange.serialization.Serializable. The library is perfectly usable without UDA's. The old template mixins are still available. If __traits(getAttributes) is not allowed in Phobos then I have to remove the code that checks for UDA's.
Jun 11 2013
On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:On 6/11/2013 12:00 AM, Jacob Carlborg wrote:I disagree - if you wait for UDAs to appear more in user-code, you'll end up with multiple conventions for using them. If they are used in Phobos/druntime first, users will conform to the Phobos/druntime convention.Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 11 2013
On Tuesday, 11 June 2013 at 14:59:44 UTC, Idan Arye wrote:On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:That's what we want, surely: Multiple conventions appear, then with the benefit of hindsight the best can be selected for phobos.On 6/11/2013 12:00 AM, Jacob Carlborg wrote:I disagree - if you wait for UDAs to appear more in user-code, you'll end up with multiple conventions for using them.Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 11 2013
On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:On 6/11/2013 12:00 AM, Jacob Carlborg wrote:That sound good, but the complete opposite have been done every single time. That raise the question of consistency.Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 12 2013
On Wednesday, 12 June 2013 at 07:46:31 UTC, deadalnix wrote:On Tuesday, 11 June 2013 at 07:36:44 UTC, Walter Bright wrote:And that's why Walter wants to avoid repeating the same mistakes again.On 6/11/2013 12:00 AM, Jacob Carlborg wrote:That sound good, but the complete opposite have been done every single time. That raise the question of consistency.Thoughts?I'd like to see more use of UDAs in non-Phobos code so we can figure out best practices from experience before putting it into Phobos, where we'll be stuck with any bad decisions.
Jun 12 2013
On Tuesday, 11 June 2013 at 07:00:29 UTC, Jacob Carlborg wrote:The idea is to have a kind of meta UDA called "attribute". This attribute needs to be attached to all structs, enums and so on that is to be used as an attribute. The module provides a template (getAttributes) to get, by default, only those values attached to a given symbol that is an attribute. That is, marked with the "attribute" attribute. So my suggestion for guidelines are: * Only types with the "attribute" UDA is to be used as attributes * In general, don't use primitive values as a UDA Don't use this (3) int a; Use this: attribute struct foo { int b; } foo(3) int a; * A user defined type marked with "attribute" should not be used for something else than an UDA * All attributes use camel case namesCamel case has two versions - and I suggest to use the one that starts with capital - that is, ` attribute struct FooBar` and not ` attribute struct fooBar`. This will save a lot of trouble when we want to add new keyword attributes. The exception is the `attribute` attribute itself - in the future we might want to make it a keyword attribute(so we can, for example, enforce it's usage for attributes), and it that case it would be helpful if all UDAs already use it.
Jun 11 2013
On Tuesday, June 11, 2013 16:48:13 Idan Arye wrote:Camel case has two versions - and I suggest to use the one that starts with capitalThe term pascal case is frequently used when referring to the variant of camelcase which starts with a capital letter. - Jonathan M Davis
Jun 11 2013
On Tuesday, 11 June 2013 at 07:00:29 UTC, Jacob Carlborg wrote:This was brought up in the thread reviewing std.serialization: http://forum.dlang.org/thread/adyanbsdsxsfdpvoozne forum.dlang.org Currently we haven't started to use UDA's in Phobos or druntime yet (as far as I know). I would like to start a discussion about putting out some guidelines for using UDA's in Phobos/druntime. I've created a small module that handles UDA's: https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d The idea is to have a kind of meta UDA called "attribute". This attribute needs to be attached to all structs, enums and so on that is to be used as an attribute. The module provides a template (getAttributes) to get, by default, only those values attached to a given symbol that is an attribute. That is, marked with the "attribute" attribute. So my suggestion for guidelines are: * Only types with the "attribute" UDA is to be used as attributes * In general, don't use primitive values as a UDA Don't use this (3) int a; Use this: attribute struct foo { int b; } foo(3) int a; * A user defined type marked with "attribute" should not be used for something else than an UDA * All attributes use camel case names If we agree on this and that we need a module like the one above I think it should be added to druntime. The reason for that is that we most likely want to use UDA's in druntime and not only in Phobos. Example, if we ever get std.serialization into Phobos we would want to mark Thread and similar structs/classes as "nonSerialized". Thoughts?I agree that attributes should have types - that way it's easily recognizable what are they for in code. "Anonymous" attributes seem to me to be sort of like "you can throw ANYTHING in c++" feature - it's there, but probably without a sane use case. Could you explain to me what's the benefit of the attribute convention you introduce? It seems non-obvious to me.
Jun 11 2013
On 2013-06-11 18:12, QAston wrote:I agree that attributes should have types - that way it's easily recognizable what are they for in code. "Anonymous" attributes seem to me to be sort of like "you can throw ANYTHING in c++" feature - it's there, but probably without a sane use case. Could you explain to me what's the benefit of the attribute convention you introduce? It seems non-obvious to me.It shows the intent of the type. D both have a keywords to indicate an interface and an abstract class. In C++ interfaces and abstract classes are possible as well, but there's no real way to tell that a given class is actually supposed to be used as an interface. I was kind of disappointed with the way D implemented UDA's. Just dump any value/type to a symbol. -- /Jacob Carlborg
Jun 11 2013
On Tuesday, 11 June 2013 at 20:31:22 UTC, Jacob Carlborg wrote:On 2013-06-11 18:12, QAston wrote:Ok, i see the point now, thanks :). Maybe it'd be worth to enforce that convention on a language level, let's say: only types with attribute can be used as UDA. One reason for making that restriction is that when there's more than a one way of doing something people will do that using all the ways possible. This may be a problem to code which uses many libraries simultanously - your utility functions will not interoperate with UDAs made by someone else. BTW I've just found one use case for anonymous UDA: (Enum.Entry) is verbose, the question is: "Is it useful enough to keep it, or maybe having single convention is better?" Certainly, there's no need to have arbitrary types in attributes like UnawareClass because you can do TakeUnaware!(UnawareClass) instead. The other way around would be to operate on SerializationAttribute specific to the lib so you can fetch only the attributes you're interested in easily.I agree that attributes should have types - that way it's easily recognizable what are they for in code. "Anonymous" attributes seem to me to be sort of like "you can throw ANYTHING in c++" feature - it's there, but probably without a sane use case. Could you explain to me what's the benefit of the attribute convention you introduce? It seems non-obvious to me.It shows the intent of the type. D both have a keywords to indicate an interface and an abstract class. In C++ interfaces and abstract classes are possible as well, but there's no real way to tell that a given class is actually supposed to be used as an interface. I was kind of disappointed with the way D implemented UDA's. Just dump any value/type to a symbol.
Jun 11 2013
On Tuesday, 11 June 2013 at 21:04:40 UTC, QAston wrote:The other way around would be to operate on SerializationAttribute specific to the lib so you can fetch only the attributes you're interested in easily.How about passing template arguments to ` attribute` to determine what libraries the UDA it declares belong to? Here is an example implementation: https://gist.github.com/someboddy/5762072
Jun 11 2013
On Wednesday, 12 June 2013 at 00:42:24 UTC, Idan Arye wrote:How about passing template arguments to ` attribute` to determine what libraries the UDA it declares belong to? Here is an example implementation: https://gist.github.com/someboddy/5762072Yes, I think something like this solves interoperation issues.
Jun 12 2013
On 2013-06-11 23:04, QAston wrote:Ok, i see the point now, thanks :). Maybe it'd be worth to enforce that convention on a language level, let's say: only types with attribute can be used as UDA. One reason for making that restriction is that when there's more than a one way of doing something people will do that using all the ways possible. This may be a problem to code which uses many libraries simultanously - your utility functions will not interoperate with UDAs made by someone else.Yes, I would like to have the language enforce this. My utility function fetches by default types that are marked with attribute. You can add flag when calling the function to fetch all UDA's.BTW I've just found one use case for anonymous UDA: (Enum.Entry) is verbose, the question is: "Is it useful enough to keep it, or maybe having single convention is better?"Is it possible to attach a UDA to an enum member? Or is it possible to figure out that it's an enum member and check if the enum itself has attribute attached to it? -- /Jacob Carlborg
Jun 11 2013
On Wednesday, 12 June 2013 at 06:46:06 UTC, Jacob Carlborg wrote:Yes, I would like to have the language enforce this. My utility function fetches by default types that are marked with attribute. You can add flag when calling the function to fetch all UDA's.Accrding to this http://dpaste.dzfl.pl/728872fa it's not possible to attach an UDA to enum member. I think that what you propose, together with parametrisation made by IdanArye to your attribute definition is a nice compromise for now. It allows reuse of utils and interoperation, sets up a convention to follow and does not enforce language changes. But it will only work if it's going to be in phobos for example as std.attribute. In my opinion such compromise would be easier to get into the language than fully enforcing the convention and I think it's very important to have some form of UDAs for serialization just for users' convenience.BTW I've just found one use case for anonymous UDA: (Enum.Entry) is verbose, the question is: "Is it useful enough to keep it, or maybe having single convention is better?"Is it possible to attach a UDA to an enum member? Or is it possible to figure out that it's an enum member and check if the enum itself has attribute attached to it?
Jun 12 2013
On 6/11/13, Jacob Carlborg <doob me.com> wrote:I was kind of disappointed with the way D implemented UDA's. Just dump any value/type to a symbol.But without this you lose the ability to customize. I don't like just "tagging" something, I like D's ability where you can actually customize the UDA, for example: ----- import std.typetuple; struct Server { string url; } struct Config { (Server("http://foo.bar")) string name; (Server("http://doo.bar")) string[] items; } template GetAttributes(T...) if (T.length == 1) { alias GetAttributes = TypeTuple!(__traits(getAttributes, T[0])); } void main() { Config config; alias attribs = GetAttributes!(config.name); static if (attribs.length && is(typeof(attribs[0]) == test.Server)) { pragma(msg, attribs[0]); } } ----- Thanks to CTFE we can tag a field with a struct that may have any state. All you have to do in the library code is to first check if any of the attributes is an "attribute type (a struct of some sort)" that you recognize, and then read its state.
Jun 12 2013
On Wednesday, 12 June 2013 at 12:29:53 UTC, Andrej Mitrovic wrote:On 6/11/13, Jacob Carlborg <doob me.com> wrote:Both are 100% orthogonalI was kind of disappointed with the way D implemented UDA's. Just dump any value/type to a symbol.But without this you lose the ability to customize. I don't like just "tagging" something, I like D's ability where you can actually customize the UDA, for example:
Jun 12 2013
On 2013-06-12 14:29, Andrej Mitrovic wrote:But without this you lose the ability to customize. I don't like just "tagging" something, I like D's ability where you can actually customize the UDA, for example: ----- import std.typetuple; struct Server { string url; } struct Config { (Server("http://foo.bar")) string name; (Server("http://doo.bar")) string[] items; } template GetAttributes(T...) if (T.length == 1) { alias GetAttributes = TypeTuple!(__traits(getAttributes, T[0])); } void main() { Config config; alias attribs = GetAttributes!(config.name); static if (attribs.length && is(typeof(attribs[0]) == test.Server)) { pragma(msg, attribs[0]); } } ----- Thanks to CTFE we can tag a field with a struct that may have any state. All you have to do in the library code is to first check if any of the attributes is an "attribute type (a struct of some sort)" that you recognize, and then read its state.As far as I know other language allows UDA's to be of any type/value. with System.Attribute as the base class are used. -- /Jacob Carlborg
Jun 12 2013