-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhancing Annotations and Macros #4238
Comments
The problem is not "prefix vs postfix" IMO.
Compare with @[log, validateInvariants, inline] void fetchData(String id) {
...
} |
Thanks for your input. I agree that |
Or... Perhaps... We can do what we already do and put all annotations before the element. As in, the line before. |
... or use a less flashy color scheme for annotations |
To clarify, I’m not suggesting that the current approach is inherently flawed. There are specific cases where the proposed syntax would improve readability. This would be particularly observable when working with large codebases with numerous annotations and macros, especially ones which are really targeting expressions. Simply sticking to the status quo doesn’t address the potential for improvements in readability and expressiveness. Furthermore, the proposed changes do not prevent annotations from being used before an item it annotates.
This isn’t about not wanting to notice the annotations, which is what that suggestion implies. It’s about a potential enhancement for readability and expressiveness. |
@RohitSaily I don't really agree. Putting annotations after an expression would just get more confusing, and add ambiguity. I think that the current simplicity makes more sense. That said, we can definitely try to find improvements, such as expression macros, macros |
Thank you for your response. I have a clearer understanding of that viewpoint now. I agree that this does increase the complexity of the language. However, I don't think the added complexity is significant enough to justify avoiding this syntax. As with any language feature, misuse could affect code quality, but I’m still not seeing how this would introduce major ambiguity or confusion. If possible, could you provide further elaboration or examples to help me understand how this could lead to ambiguity? |
Allowing annotations to come after an expression or statement makes it hard to tell that anything is happening. Plus, it can mean that annotations can be "hidden" at the end of the expression. Having the annotations ahead of the expression allows us to define the context of the following code before we read the code. We can know that there's extra information to be had. But if that information comes after, it can confuse you as your initial impression is now tainted - what you read may in fact be something entirely else thanks to the annotations. I like what you're going for with the wrapper functions - but I think that the annotations should remain where they are. Its basically like python decorators in that sense. Expression macros would be way more powerful, as it may expand into who knows what. |
Annotations look better with a different color: @log @validateInvariants @inline void fetchData(String id) {
//...
} |
Perhaps, but that is a theming/tooling change, and has nothing to do with the language itself. That said, the formatter places annotations vertically, not inline, so perhaps you want to consider how that applies instead. They could possibly be folded away like you might a code block or imports. |
@TekExplorer I appreciate the explanation, it helps me think this through more.
I agree that this can be an issue, like many language features, it is only an issue if the developer misuses it. It makes it hard to tell anything is happening until the developer finishes reading or examining the expression/declaration. That is actually the benefit of it. It allows detailed information that is not necessary for the implementation to be moved to the side, making it secondary in content.
This is a good and important point. It is valuable for certain kinds of annotations or macros that are relevant to actual implementation behaviour to be placed at the forefront. Other kinds of annotations or macros can actually unnecessarily add to the cognitive context of the reader before they examine the main implementation details of the expression/declaration. This actually decreases readability. Ultimately, it is the responsibility of developers to write readable code. Developers are limited by what the language permits and prohibits. It is in their best interest if the language provides flexibility so they can write as readable and expressive code as possible. |
An additional consideration is to allow the annotation/macro definer to easily and concisely define the annotation or macro as prefix or postfix. This helps force the developer apply it appropriately and consistently. To maintain compatibility, when it is not specified it is prefix. Postfix would have to be explicitly indicated in the annotation/macro definition somehow. |
I still don't see the benefit. When would a postfix annotation ever be the sensible thing? |
One potential use case for a postfix annotation is related to #3580. final int x @toBeAugmented; (Some shorter word has to be found) |
I have revised the proposal (the first post in this thread) to try and make the readability benefits more clear. Please take a look and let me know what you think
That's a good example. Imagine there were more annotations on that declaration too: @toBeAugmented @annotationA @annotationB final int x; It's quite the journey for the eyes to get to the point of the declaration! The following would be much better. final int x @toBeAugmented @annotationA @annotationB; We can immediately identify what is actually at that line (a definition of |
I see. I think I can understand that.
I actually don't agree here, since they would not be on the same line. @toBeAugmented @annotationA @annotationB
final int x; As you can see, you can see the declaration just fine. I can see the point to having an annotation on the trailing end of a declaration like that, as you effectively put the marker exactly where the code will go. Though perhaps it may be better to consider expression macros, in a sense: class Foo {
final int i = @someAnnotation;
} It actually occurs to me that this can synergize with a different issue, (#3580) such that it's equivalent (in terms of actionable code) to: class Foo {
// Indicates that the initializer is filled in elsewhere
final int i =;
// type identifier = annotations*;
} Edit: actually heh, that issue is exactly the one mentioned above |
I agree putting the annotations on the line before improves it from the example I gave. However, now it is taking up another line. Furthermore, if the annotations are lengthy due to names and parameters, it becomes multiple lines before the declaration (depending on code formatting guidelines being used). Having the subsequent lines contain the annotations is better for readability as explained in the revised original post. I didn't consider an annotation as a standalone expression, that is interesting. I believe it would be beneficial to have an expression which can be annotated and for multiple annotations to be applicable to the expression. |
Proposal: Enhancing Annotations in Dart with Postfix and Expression Syntax
Annotations, including macros, are powerful tools for ensuring systems are robust and for code generation. However, their current usage is limited by where they can be applied in the code. This proposal aims to remove that limitation while maintaining backward compatibility and promoting a consistent and deterministic coding style.
Overview of Changes
Annotations in Expressions
Consider a scenario where there is a performance bottleneck in your code, and you want to optimize a function,
c
, by inlining it or using an annotation to alter its behavior—such as disabling runtime checks. The function is widely used across the codebase, but the performance-related alteration should only apply at the bottleneck.Currently, the closest approach to achieving this is:
This requires a verbose multi-line expression to specify the annotation. A more concise and readable solution would be to place the annotation directly within the function call:
Even better, we could place the annotation after the function call to indicate that it's secondary to the implementation logic:
This approach keeps the annotation close to the expression it modifies without interrupting the readability of the code. The annotation is still important, but it's less intrusive and aligns with the overall design of the code. This brings us to the other part of the proposed changes.
Postfix Annotations
One additional change proposed is the ability to define annotations that must be used in a postfix manner. This would enforce consistent and predictable code formatting, which improves readability, especially when dealing with development-time behaviors.
For example, suppose you want to log the result of a function call, validate its invariants, and ensure it's inlined. The current approach requires placing multiple annotations in front of the declaration:
With postfix annotations, this could be written as:
This not only improves readability in a single line of code, but it becomes even more advantageous in larger code blocks where annotations might otherwise disrupt the flow. By placing annotations as postfixes, we ensure they are secondary details and don’t interfere with the core implementation logic.
One clear, but still simple, example for multiple lines:
Without postfix annotations
With postfix annotations
Implementation Considerations
To maintain backward compatibility and ensure predictable behavior, postfix annotations must be explicitly defined. This can be achieved through a marker type or by using a prefix annotation.
Example using an annotation:
Alternatively, an annotation could implement a
PostfixAnnotation
marker type:These are just a few possible ways to implement this feature. The details of the implementation can vary, but the core idea is to have a clear distinction for postfix annotations.
Conclusion
Dart is already a powerful and customizable language, and adding support for postfix and expression annotations would significantly enhance its flexibility. This proposal aims to improve the readability of code by allowing annotations to be used in more natural and less disruptive ways. Additionally, I foresee this feature being widely adopted by Domain-Specific Languages (DSLs), as it would allow them to define more intuitive and natural syntax for augmenting expressions with additional behaviour.
The text was updated successfully, but these errors were encountered: