Moved from: "Initialize/Finalize management operators and Default intrinsic". I'd like to keep Initialize/Finalize topic more clear ;P
Small introduction:
for selected language elements in Delphi is possible to use attributes. For example in Delphi we have:
TCustomAttribute = class(TObject)
end;
WeakAttribute = class(TCustomAttribute);
UnsafeAttribute = class(TCustomAttribute);
RefAttribute = class(TCustomAttribute);
VolatileAttribute = class(TCustomAttribute);which is used like this:
procedure Foo([ref] const X: TFoo); // AFAIK FPC equivalent is procedure
Foo(constref X: TFoo);or like this for TObject field for ref. count for ARC:
[Volatile] FRefCount: Integer;Michael Van Canneyt really doesn't like them :) :
2016-04-12 15:37 GMT+02:00 Michael Van Canneyt :
Show quoted text 35 lines
To clarify: I am not a big fan of the attributes syntax. But...
If attribute is used you already know that it has more "flag idea" (by analogy to RTTI attributes, anyway it does not have to be just like a flag), as in our example presented in "Initialize/Finalize management operators and Default intrinsic" topic - is more visible whole context. Introducing many new keyword is the waste and can collide with existing keywords.
I don't want the language with thousands of keywords, some things can be delegated to attributes. *That helps to keep main language more clear*.
Usage of attributes is more readable than mix of many keywords (it depends of context ofc). I think in many areas it is matter of taste. Of course is possible to implement new keywords, but
*the main idea of using attributes for syntax elements is to omit explosion of new keywords*... Just imagine this as attributes for nodes of compiler. Pure theory:
// open mp - attributes way
[OmpParallel]
begin
[OmpFor]
for i := 1 to 10 do
WriteLn(i);
end;
// new keywords way ? set of keywords?...
ompparallelbegin
ompfor i := 1 to 10 do
WriteLn(i);
end;
// or...
omp parallel begin
omp for i := 1 to 10 do
WriteLn(i);
end;
// another example
//Throws - like java throws - used to force the caller of the method to
catch exceptions
// JSExport - some special export for JavaScript without deeper sense for
non-existing FPC JS target ;)[Throws(EConvertError, EClassNotFound, ECrtSocket)] [JSExport('Foo')]
class procedure procedure Foo(); stdcall; overloaded; static;
// new keywords ...
class procedure procedure Foo(); stdcall; overloaded; static; throws EConvertError, EClassNotFound, ECrtSocket; {$IFDEF JS}jsexport 'foo';{$ENDIF}
The line between attribute and keyword is thin. Attribute is always declared "before". You don't need to redesign language to put something new (sometimes it is even impossible or very complicated, so attribute is the only way).
FINAL NOTE: attributes for a language should be introduced with great carefulness.
FINAL COMPROMISE: is good to allow selected attributes for Delphi compatibility (in Delphi mode only) for example to allow usage of [ref]. I'd like to run my Generics.Collections in Delphi too :). No big deal:
procedure Foo([ref] const X: TFoo);can be interpreted just like:
procedure Foo(constref X: TFoo);or in the future:
[Volatile] FRefCount: Integer;can be interpreted like:
FRefCount: Integer; volatile;