March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu wrote: > like printing money is for a government: very tempting, with apparently good short-term benefits, but with devastating cumulative effects. RON PAUL 2012!!! sorry, I couldn't help myself. > Also, as I mentioned, the availability of the easy escape hatch of adding a language feature thwarts creativity. Nobody will care to think about and come with idioms that use the language to do great things, if they know a language feature could be always added that makes things "nicer". You can be creative with a sledge hammer, or you can be creative with a jack hammer. D is already a bulldozer, but that doesn't mean it shouldn't become a wreaking ball. ;-) |
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tue, 20 Mar 2012 11:17:02 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote: > Perhaps we should add a field of type Variant[string]. 1. Variant is not (and shouldn't be IMO) part of druntime. 2. This is *static* data that should be available at compile time. D's runtime wasting cycles filling in static data (including lots of heap allocations) seems like a big enough detriment that compiler help is warranted. >> This is an already ridiculously hackish approach, and >> it *does not* work for anything besides trivial applications. It is >> completly unreasonable to expect everything to be done in a library; the >> compiler exists for a reason and at some point you have to draw the >> line. > > I'm afraid I disagree. A targeted language feature definitely makes a library approach inferior, by definition. But adding features is cheating, like printing money is for a government: very tempting, with apparently good short-term benefits, but with devastating cumulative effects. Not exactly. We could all be writing code in assembly if "adding features" was always caustic. What is nice about adding this feature is it provides a custom solution to hooking the compiler's TypeInfo generation. We are setting up the compiler to give us hooks so we *don't* have to extend the compiler every time we want new reflection features. One of the oft-requested features of D is reflection capability. The answer is generally that we have compile-time reflection, which can theoretically be used to build runtime reflection. However, the rebuttal I always come back with is "yeah, but why should I build at runtime that which is obvious at compile time?" Note that one library that did attempt runtime reflection capability (flectioned) does all this at runtime, and does some really funky shit, like opening /proc/self/map on Linux, or requiring you to pass an OPTLINK map file. I don't look at these as "innovations" as much as I do as workarounds. > Also, as I mentioned, the availability of the easy escape hatch of adding a language feature thwarts creativity. Nobody will care to think about and come with idioms that use the language to do great things, if they know a language feature could be always added that makes things "nicer". I have to disagree for this instance, the barrier to creating reflection data from compile-time info is very large. If anything, this *expands* the ability to create, since you now have a new way to pass information from compiler to runtime. -Steve |
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | On 3/20/12 10:52 AM, Jacob Carlborg wrote: > On 2012-03-20 16:17, Andrei Alexandrescu wrote: >> On 3/20/12 12:50 AM, Kapps wrote: > >> Perhaps we should add a field of type Variant[string]. > > No, not Variant[string] again. Why? I thought it was agreed that that's a good idea for exceptions. >> I'm not saying this particular feature should or should not be in the >> language, but I wish our community exercised considerably more restraint >> when it comes about adding new language features. > > See my reply to one of your other posts: > > http://forum.dlang.org/thread/bccwycoexxykfgxvedix@forum.dlang.org?page=9#post-jk9gk8:242t7k:241:40digitalmars.com I understand the intention there, but my point stands: let's first explore doing it in the language, and advocate a new feature only when that fails. We've been too trigger-happy about proposing features even for the most trivial inconveniences. Andrei |
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 3/20/12 11:09 AM, Steven Schveighoffer wrote: > On Tue, 20 Mar 2012 11:17:02 -0400, Andrei Alexandrescu > <SeeWebsiteForEmail@erdani.org> wrote: >> I'm afraid I disagree. A targeted language feature definitely makes a >> library approach inferior, by definition. But adding features is >> cheating, like printing money is for a government: very tempting, with >> apparently good short-term benefits, but with devastating cumulative >> effects. > > Not exactly. We could all be writing code in assembly if "adding > features" was always caustic. This is trivializing my point. Please. > What is nice about adding this feature is it provides a custom solution > to hooking the compiler's TypeInfo generation. We are setting up the > compiler to give us hooks so we *don't* have to extend the compiler > every time we want new reflection features. There is something nice about every new feature. > One of the oft-requested features of D is reflection capability. The > answer is generally that we have compile-time reflection, which can > theoretically be used to build runtime reflection. However, the rebuttal > I always come back with is "yeah, but why should I build at runtime that > which is obvious at compile time?" I thought there were discussions that didn't add runtime overhead. > Note that one library that did attempt runtime reflection capability > (flectioned) does all this at runtime, and does some really funky shit, > like opening /proc/self/map on Linux, or requiring you to pass an > OPTLINK map file. I don't look at these as "innovations" as much as I do > as workarounds. Maybe there's a better approach than flectioned. Consider the language is frozen solid. How would you solve problems with it? >> Also, as I mentioned, the availability of the easy escape hatch of >> adding a language feature thwarts creativity. Nobody will care to >> think about and come with idioms that use the language to do great >> things, if they know a language feature could be always added that >> makes things "nicer". > > I have to disagree for this instance, the barrier to creating reflection > data from compile-time info is very large. If anything, this *expands* > the ability to create, since you now have a new way to pass information > from compiler to runtime. I hope I'll be convinced. Andrei |
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 3/20/12 11:09 AM, Steven Schveighoffer wrote:
> On Tue, 20 Mar 2012 11:17:02 -0400, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>
>> Perhaps we should add a field of type Variant[string].
>
> 1. Variant is not (and shouldn't be IMO) part of druntime.
> 2. This is *static* data that should be available at compile time. D's
> runtime wasting cycles filling in static data (including lots of heap
> allocations) seems like a big enough detriment that compiler help is
> warranted.
Forgot to mention - I snipped these points because I agree with them.
Andrei
|
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 20 March 2012 at 15:17:04 UTC, Andrei Alexandrescu wrote: > Also, as I mentioned, the availability of the easy escape hatch of adding a language feature thwarts creativity. I agree entirely. Usually, when I see threads like this, my response is "challenge accepted". But, on this problem, my answer is, unfortunately, "challenge failed". I want to annotate declarations for my web.d, where you can write a class and have D do a bunch of work for you in creating all kinds of stuff. Let me do up a quick example: === struct MyType { int num; string name; string desc; Element makeHtmlElement() { auto e = Element.make("div", desc).addClass("my-type"); return e; } } class MySite : ApiProvider { MyType getSomething(int someNumber, string name, Text description) { return MyType(someNumber, name, description); } void savePhoneNumber(string name, string phoneNumber) { _checkLoggedIn(); ensureGoodPost(); _doSave(); } void _doSave() { yada yada yada } } === Now, when you go to mysite.com/get-something, it will generate a form like this: <form method="GET"> Some Number: ____________ Name: ____________ Description: ____________ ____________ ____________ [Get Something] </form> It pulls this info from the D code - it uses an alias template param to the method, then parses .stringof to get the names and default params. (It then mixes in the default to get a D type, which doesn't work on custom types since they aren't in the right scope, but hey, it works in a lot of cases.) When possible, it uses the type of the parameter to specialize the form. This comes from ParameterTypeTuple. Here, it recognizes struct Text{} as being a textarea. tbh, I'd prefer to use @note(Textarea(rows)), but this works, and alias this to string makes it pretty natural to work with too. Moreover, I wrote method="GET". It pulls this from the method name. Since it starts with get, it doesn't require http post for it. So far, so good. Let's look at the next method, savePhoneNumber. This !startsWith("get"), so it generates a POST form, with the same kind of thing: Name: _________ Phone Number: _________ [Save Phone Number] Hey, it works. But, I'd like to do even better. Could we do validation? Well, yeah, I think we could. struct PhoneNumber { enum _validationRegex = "[0-9]+"; } Boom. What about an example text, though? You could use that same enum method, but you would need a different type for each example. If you have two "string name" and in one case, you want it to be "e.g. Bob Smith" and in the other, you want "e.g. Downtown Office", you'd have to make separate structs for them, despite it just being strings in every other way. That's one big case where the compile time annotation comes through: void savePhoneNumber @note(ExampleText("e.g. Downtown Office") string name, PhoneNumber phoneNumber) { } To do that with a mixin, you might: mixin(ExampleText!(savePhoneNumber, "name", "downtown")); void savePhoneNumber(string name, ...) {...} and have that yield: enum _attribute_DsavePhoneNumberMangle_param_name_FILE_LINE_type = ExampleText("downtown"); ok, this is a bit of a pain in the ass, but I think it'd work... (the file_line_type stuff is so you can have multiple things of the same type. Moderately fragile! But, it'd work.) The pain gets bad down the line though. Renaming things means repetition. Separate declarations might get lost as you shuffle the order around. But, not too awful... Until you get into more functions. Enter arsd.web.prepareReflection and makeJavascriptApi: foreach(member; __traits(allMembers, yourclass)) // build a runtime map and corresponding bindings for other languages Should our enum be included here? Should this include code to detect the annotations and translate them to the native target language? How much code is this going to take? What if I use a third party lib? Will it have to be hacked to ignore these extra names too? Well, we can work around this too. web.d has a convention where static if(name[0] == '_') { don't process }. (This is actually a workaround for a lack of __traits(getProtection) though. We already have D keywords that do this: public and/or export. But, there's currently no way to check for these, so I settled for a naming convention. This is what _doSave() demonstrates in the example. I'm hoping to do a dmd pull request to add getProtection at some point though.) We could all agree on a naming convention, in theory. In practice, I don't know. If I could check export || public, I might drop the underscore. Another problem is how do we get this data? We have an alias of the method... but not it's parent. Well, there's __traits(getParent). I think we could actually do that. But the idea of a parent reminds me of another problem. This is a class, the method is virtual. What if a subclass overrides it and wants to tweak the annotation? How will we handle annotation inheritance? Overloading is kinda solved via mangleof (I think, I haven't tried this yet, but in principle it would work), but inheritance is a whole other bag. Perhaps we do ClassName_methodName and in the search go up the base class tree? I don't know... I think we *could* make it work at this point, but it depends on an agreed naming convention, where we (essentially) embed little DSLs in member names, packing all kinds of info in there to work correctly. Piles upon piles of string processing code that we'd all have to agree on for reflection work, with complications around almost every corner. If we solve overloading and inheritance, what will be next? Embedding info directly in names is the easiest, but a bit problematic too: getSomething() What if I want it to be http GET, but be named say, "something-viewer"? Currently, I implement that as two functions: getSomething() for machines to access and alias getSomething somethingViewer; for human users. It isn't ideal, but again, it works. (The ensureGoodPost() function does a runtime check against CSRF. That's a potential candidate for an annotation too, but the exception works perfectly fine too, so meh.) Another thing I'd like, in the same vein as the ExampleText, is Hideable. Again, not really a type, though it could be with enough special case code added throughout to handle it. But, this would be a parameter that, if given, is hidden instead of showed: void changeName(@note(Hide) int id, string name) {} link to change-name?id=1, and then you don't have to show the ID in the automatically generated form. Don't want to always do this though: send-message?message=example+message we *want* that to be editable... (In practice, right now, I make the form another function and modify it myself. That's several lines for something that could be done generically though, which is pain.) Well, I was going to go on longer, but I think we have enough here to draw a conclusion. Can we do it? Well, I kinda think we can. Hell, I already do like 3/4 of what I want in web.d With the power of D, we could make all kinds of weird stuff encoded as strings, stored as variable names. But, it is hard to use at most levels. Writing the annotations is a long, repetitive process. Processing them takes a lot of fragile code. Even /ignoring/ them takes a lot code, and that's what, to me, pushes it over into compiler territory. Compiler provided annotations are opt-in and backward compatible. If you want them, they're there, and if you don't, they aren't in the way like magic enums would be. |
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On 03/20/2012 05:31 PM, Adam D. Ruppe wrote:
>
> Even /ignoring/ them takes a lot code, and that's
> what, to me, pushes it over into compiler territory.
vote++
|
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu wrote:
> On 3/20/12 10:52 AM, Jacob Carlborg wrote:
>> On 2012-03-20 16:17, Andrei Alexandrescu wrote:
>>> On 3/20/12 12:50 AM, Kapps wrote:
>>
>>> Perhaps we should add a field of type Variant[string].
>>
>> No, not Variant[string] again.
>
> Why? I thought it was agreed that that's a good idea for exceptions.
Please, do not transform D into a dynamic language.
|
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Piotr Szturmaj | On 3/20/12 2:04 PM, Piotr Szturmaj wrote:
> Andrei Alexandrescu wrote:
>> On 3/20/12 10:52 AM, Jacob Carlborg wrote:
>>> On 2012-03-20 16:17, Andrei Alexandrescu wrote:
>>>> On 3/20/12 12:50 AM, Kapps wrote:
>>>
>>>> Perhaps we should add a field of type Variant[string].
>>>
>>> No, not Variant[string] again.
>>
>> Why? I thought it was agreed that that's a good idea for exceptions.
>
> Please, do not transform D into a dynamic language.
Where's the "dynamic languages rok" crowd when you need it :o).
Andrei
|
March 20, 2012 Re: Proposal: user defined attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Le 20/03/2012 16:17, Andrei Alexandrescu a écrit : > On 3/20/12 12:50 AM, Kapps wrote: >> On Monday, 19 March 2012 at 21:00:32 UTC, Andrei Alexandrescu wrote: >>> On 3/19/12 3:55 PM, F i L wrote: >>>> I think this could get tricky for the compiler to confidently use given >>>> that the mixed in enums can collide with existing members (although not >>>> likely). Also, if objects are not identified as being unique marked (in >>>> the compilers eyes), what specific attribute post-fixes will it be >>>> searching for on enums members? >>> >>> Not a big issue, the name could always contain a uuid which makes >>> collision practically impossibile. >>> >>> Andrei >> >> And with parameters? Or how about run-time reflection, which is >> something that should be added eventually for attributes as well (that >> is, typeid(Blah).getCustomAttributes())? We can't manually add things >> into the TypeInfo. > > Perhaps we should add a field of type Variant[string]. > >> This is an already ridiculously hackish approach, and >> it *does not* work for anything besides trivial applications. It is >> completly unreasonable to expect everything to be done in a library; the >> compiler exists for a reason and at some point you have to draw the >> line. > > I'm afraid I disagree. A targeted language feature definitely makes a > library approach inferior, by definition. But adding features is > cheating, like printing money is for a government: very tempting, with > apparently good short-term benefits, but with devastating cumulative > effects. > > Also, as I mentioned, the availability of the easy escape hatch of > adding a language feature thwarts creativity. Nobody will care to think > about and come with idioms that use the language to do great things, if > they know a language feature could be always added that makes things > "nicer". > > I'm not saying this particular feature should or should not be in the > language, but I wish our community exercised considerably more restraint > when it comes about adding new language features. > That feature has been added to java with great benefit. I think the underlying need here is AOP. Adding annotation to java had great benefice in introducing AOP capabilities to the language. See : http://projectlombok.org/ Considering that D has great compile time capabilities, this is somewhere we want to go. Additionnaly, this is something that remove other capabilities, and replace them by lib support. For example, with @synchronized, I could specify the phobos that I want that method or class to be synchronized, and the lib is able to add the needed code to ensure that functionality at compile time. I have to say that the whole idea of attaching property to instance doesn't make any sense to me - Walter make a good point on that I think, so I will not repeat his arguments. |
Copyright © 1999-2021 by the D Language Foundation