By default the generated getter and setter do not perform defensive copying (see Effective Java). I would propose the following syntax for fields:
Person person //No defensive copying
Person (anotherPerson) // Use defensive copying
Motivation: the parens give a visible impression of some sort of protection of the field.
The generated getters and setters should use a copy constructor (the copy constructor should be called makeCopy(Person person) or something similar):
Person person
{
get { return Person.makeCopy(&person) }
set { &person = Person.makeCopy(it) }
}
This is of course only useful for mutable fields, so the following should generate a compiler error:
const Person (person)
yachrisWed 27 Oct 2010
I think I'd prefer to see, if possible, a facet such as @DefensiveCopied rather than special syntax.
qualidafialWed 27 Oct 2010
Going a step further, I'd love to have a way to mark certain annotations as "magic," like an implicit call to a compiler plugin whenever a magic annotation is used. e.g.
Then I could write a compiler plugin that turned this:
@Bindable Str firstName
into this:
@Bindable Str firstName
{
set
{
&firstName = it
listeners.fire(Event(#firstName))
}
}
brianThu 28 Oct 2010
Going a step further, I'd love to have a way to mark certain annotations as "magic," like an implicit call to a compiler plugin whenever a magic annotation
Agreed - this is where we need to go
andyThu 28 Oct 2010
+1 qualidafial
HenriThu 28 Oct 2010
I believe the general rule should be that facets do not alter the semantics of the annotated element. That is why I didn't propose a facet in the first place.
However, a facet called @Magic might be an exception to the rule.
yachrisThu 28 Oct 2010
Well, annotations in Java are metadata-only, but that doesn't mean they have to be that way in Fantom. And (having a hard time believing you were serious, but just in case...) having a facet called @Magic which is the only way to do non-metadata behavior is probably too broad.
HenriThu 28 Oct 2010
I agree that facets do not have to be like annotations in Java. I just think that magic behavior is very dangerous for the readability of the code. The magic part, if any, should be only what the (knowledgeable) reader could reasonably expect or logically assume, but nothing more, and should certainly not have suprises. Facets would become some sort of template facility, which I don't think is a good idea in general.
The best way to tell the reader that something magic, as an exception, is going on is to explicitly mention that. Of course, @Magic should not be the only mechanism to introduce non-metadata behavior, but I think some kind of visible distinction would be beneficial. How about @@Bindable?
katoxThu 28 Oct 2010
Well, annotations in Java are metadata-only,
It depends on your point of view. Some annotations (ORM typically) just cause runtime bytecode generation so wild that the resulting bytecode couldn't be expressed directly in java syntax. There are also IDE annotations like IDEA's @Nullable and @NotNull which I wouldn't count as pure metadata.
+1 - it would make sense to have a special name or syntax for facets which cause additional compiler calls. I agree with yachris that a single name @Magic is not enough.
qualidafialThu 28 Oct 2010
Well, annotations in Java are metadata-only, but that doesn't mean they have to be that way in Fantom. And (having a hard time believing you were serious, but just in case...) having a facet called @Magic which is the only way to do non-metadata behavior is probably too broad.
Just to clarify, the idea with the @Magic annotation is so that you can create your own facets with magic behavior. Ergo my previous example:
By annotating the @Bindable facet as @Magic, we are saying that using the @Bindable tag will enhance your code in some way. For example the following class:
class Foo
{
@Bindable Str foo
}
Would be transformed by the BindablePlugin compiler plugin into something like this:
class Foo : EventDispatcher
{
override once Listeners listeners() { Listeners() }
@Bindable Str foo
{
set
{
&foo = it
listeners.fire(Event(Foo#foo))
}
}
}
qualidafialThu 28 Oct 2010
Another idea is to use facet-based compiler plugins for things like limiting what targets a facet can be applied to, similar to the @Target annotation in Java:
The best way to tell the reader that something magic, as an exception, is going on is to explicitly mention that. Of course, @Magic should not be the only mechanism to introduce non-metadata behavior, but I think some kind of visible distinction would be beneficial. How about @@Bindable?
I don't care for @@Bindable syntax, but I do think there would be value in requiring a different syntax so that someone reading the code would see right away that there is compiler magic going on.
Bonus points if the syntax looks like an emoticon for magic without being tedious to type. :)
yachrisThu 28 Oct 2010
I stand corrected on several fronts today :-) ... I didn't know that java annotations could be used for behavior, and now I understand the intent of the @Magic facet.
However, the original suggestion:
like an implicit call to a compiler plugin whenever a magic annotation is used...
is slightly scary, for the following reasons. I use Eclipse, which has a plugin architecture, which is both fantastic and kind of a nightmare. The nightmare part is our old friend, dll hell... you can wind up wanting two completely separate plugins, but you either can't use both or you can't use them simultaneously (or you have to go back several versions on one or both) because they depend on some third plugin. Companies have made whole businesses out of configuring Eclipse!
My concern is that I wouldn't be able to compile someone's source code I wanted to use, or I would have to somehow maintain "N" versions of the Fantom compiler plugin directory.
I certainly vote +1 on the idea, but it bears serious thought on the implementation.
DanielFathThu 28 Oct 2010
+1 to @@Magic. IMO every other type of facet should try to be as dumb as possible.
mslThu 28 Oct 2010
Personally, this strikes as a horrible opening for massive abuse and confusion.
I agree with the take that annotations/facets should be metadata only - while ORM does generate layers upon layers on top of my code, it doesn't change the internal meaning of my code - which the @Magic idea does.
I'd rather look at more adventurous solutions at the language level than shoe horning facets into something larger than (IMHO) they should be.
The only solid use case I've seen so far for @Magic is the Bindable case - which could easily be achieved by allowing the specification of mix ins on an arbitrary object at declaration time as you can do with scala (although the syntax with fantoms Type name rather than scalas name: Type is a little ordinary):
class Foo
{
Str : Bindable foo
}
(later)
I should also say that I'd feel less strongly about it if we weren't talking about compiler tricks. I'm not sure how you could write the hook to @Bindable without using the AST - but having it as a single piece of source code I can browse through and debug as opposed to internal AST hackery would make it at least bearable.
brianThu 28 Oct 2010
I won't go into all the details, but this issue has been heavily discussed on the forum already:
there is general agreement (I believe) that things like creating Bindable fields should not require boiler plate
this might start to sound like "macros", but in general I am opposed to them if it hurts the readability of the code
we have discussed this in terms of DSLs maybe borrowing the <|...|> syntax
we also had a very promising discussion about how you might be able to mixin types into the fields/methods themselves; to me this is actually maybe the closest to what I would consider the most elegant solution
But there is no concrete design in-place yet, and I want to finish what we have as a 1.0 release before tackling something this huge.
tacticsFri 29 Oct 2010
this might start to sound like "macros", but in general I am opposed to them if it hurts the readability of the code
The problem with macros arise when the macro solution is lightweight. This encourages application-level designers to try to improve the language.
As long as any macro system is heavyweight and requires a deeper understanding of the compiler, they should be less of a problem. Instead of ad hoc solutions written per-application, you'd end up with a standard library of well-known compiler plugins.
As long as there is a feeling of standardization to language extensions, it doesn't matter if they are baked into the language or available from a third party.
Henri Wed 27 Oct 2010
Just an idea for discussion purposes:
By default the generated getter and setter do not perform defensive copying (see Effective Java). I would propose the following syntax for fields:
Motivation: the parens give a visible impression of some sort of protection of the field.
The generated getters and setters should use a copy constructor (the copy constructor should be called
makeCopy(Person person)
or something similar):This is of course only useful for mutable fields, so the following should generate a compiler error:
yachris Wed 27 Oct 2010
I think I'd prefer to see, if possible, a facet such as
@DefensiveCopied
rather than special syntax.qualidafial Wed 27 Oct 2010
Going a step further, I'd love to have a way to mark certain annotations as "magic," like an implicit call to a compiler plugin whenever a magic annotation is used. e.g.
Then I could write a compiler plugin that turned this:
into this:
brian Thu 28 Oct 2010
Agreed - this is where we need to go
andy Thu 28 Oct 2010
+1 qualidafial
Henri Thu 28 Oct 2010
I believe the general rule should be that facets do not alter the semantics of the annotated element. That is why I didn't propose a facet in the first place.
However, a facet called @Magic might be an exception to the rule.
yachris Thu 28 Oct 2010
Well, annotations in Java are metadata-only, but that doesn't mean they have to be that way in Fantom. And (having a hard time believing you were serious, but just in case...) having a facet called
@Magic
which is the only way to do non-metadata behavior is probably too broad.Henri Thu 28 Oct 2010
I agree that facets do not have to be like annotations in Java. I just think that magic behavior is very dangerous for the readability of the code. The magic part, if any, should be only what the (knowledgeable) reader could reasonably expect or logically assume, but nothing more, and should certainly not have suprises. Facets would become some sort of template facility, which I don't think is a good idea in general.
The best way to tell the reader that something magic, as an exception, is going on is to explicitly mention that. Of course,
@Magic
should not be the only mechanism to introduce non-metadata behavior, but I think some kind of visible distinction would be beneficial. How about@@Bindable
?katox Thu 28 Oct 2010
It depends on your point of view. Some annotations (ORM typically) just cause runtime bytecode generation so wild that the resulting bytecode couldn't be expressed directly in java syntax. There are also IDE annotations like IDEA's @Nullable and @NotNull which I wouldn't count as pure metadata.
+1
- it would make sense to have a special name or syntax for facets which cause additional compiler calls. I agree with yachris that a single name@Magic
is not enough.qualidafial Thu 28 Oct 2010
Just to clarify, the idea with the
@Magic
annotation is so that you can create your own facets with magic behavior. Ergo my previous example:By annotating the
@Bindable
facet as@Magic
, we are saying that using the@Bindable
tag will enhance your code in some way. For example the following class:Would be transformed by the
BindablePlugin
compiler plugin into something like this:qualidafial Thu 28 Oct 2010
Another idea is to use facet-based compiler plugins for things like limiting what targets a facet can be applied to, similar to the
@Target
annotation in Java:qualidafial Thu 28 Oct 2010
I don't care for
@@Bindable
syntax, but I do think there would be value in requiring a different syntax so that someone reading the code would see right away that there is compiler magic going on.Bonus points if the syntax looks like an emoticon for magic without being tedious to type. :)
yachris Thu 28 Oct 2010
I stand corrected on several fronts today :-) ... I didn't know that java annotations could be used for behavior, and now I understand the intent of the
@Magic
facet.However, the original suggestion:
is slightly scary, for the following reasons. I use Eclipse, which has a plugin architecture, which is both fantastic and kind of a nightmare. The nightmare part is our old friend, dll hell... you can wind up wanting two completely separate plugins, but you either can't use both or you can't use them simultaneously (or you have to go back several versions on one or both) because they depend on some third plugin. Companies have made whole businesses out of configuring Eclipse!
My concern is that I wouldn't be able to compile someone's source code I wanted to use, or I would have to somehow maintain "N" versions of the Fantom compiler plugin directory.
I certainly vote +1 on the idea, but it bears serious thought on the implementation.
DanielFath Thu 28 Oct 2010
+1 to
@@Magic
. IMO every other type of facet should try to be as dumb as possible.msl Thu 28 Oct 2010
Personally, this strikes as a horrible opening for massive abuse and confusion.
I agree with the take that annotations/facets should be metadata only - while ORM does generate layers upon layers on top of my code, it doesn't change the internal meaning of my code - which the
@Magic
idea does.I'd rather look at more adventurous solutions at the language level than shoe horning facets into something larger than (IMHO) they should be.
The only solid use case I've seen so far for
@Magic
is theBindable
case - which could easily be achieved by allowing the specification of mix ins on an arbitrary object at declaration time as you can do with scala (although the syntax with fantomsType name
rather than scalasname: Type
is a little ordinary):(later)
I should also say that I'd feel less strongly about it if we weren't talking about compiler tricks. I'm not sure how you could write the hook to
@Bindable
without using the AST - but having it as a single piece of source code I can browse through and debug as opposed to internal AST hackery would make it at least bearable.brian Thu 28 Oct 2010
I won't go into all the details, but this issue has been heavily discussed on the forum already:
<|...|>
syntaxBut there is no concrete design in-place yet, and I want to finish what we have as a 1.0 release before tackling something this huge.
tactics Fri 29 Oct 2010
The problem with macros arise when the macro solution is lightweight. This encourages application-level designers to try to improve the language.
As long as any macro system is heavyweight and requires a deeper understanding of the compiler, they should be less of a problem. Instead of ad hoc solutions written per-application, you'd end up with a standard library of well-known compiler plugins.
As long as there is a feeling of standardization to language extensions, it doesn't matter if they are baked into the language or available from a third party.