Open badeend opened 1 year ago
Good points and thanks for the great write up! Yes, this has been in the idea queue for a while (I think maybe @guybedford brought this up somewhere too?) and hasn't been added yet mostly due to not having yet had the time to analyze the option space. Thanks for the detailed examples and ideas, which look reasonable. I can't say I have any strong opinions yet on whether to be more like JS or C#; I'd be interested to see more examples of what other languages do beyond C# and JS.
Here ya go:
@property
def the_property_name(self):
return # value
@the_property_name.setter
def the_property_name(self, value):
# update value
Public Property ThePropertyName As String
Get
Return name
End Get
Set(ByVal value As String)
name = value
End Set
End Property
def name # get
@name
end
def name=(name) # set
@name = name
end
class Point {
var x: Int {
get { return /* value */ }
set { /* update value */ }
}
}
var thePropertyName: String
get() {
return /* value */
}
set(value) {
/* update value */
}
@property int someNumber;
- (int)someNumber {
return // value
}
- (void)setSomeNumber: (int)newValue {
// update value
}
def age = // value
def age_=(newValue: Int) {
// update value
}
@property bar() { return 10; }
@property bar(int x) { writeln(x); }
int get thePropertyName {
return /* value */
}
void set thePropertyName(int newValue) {
/* update value */
}
member MyProperty
with get() = // value
and set(value) = // update value
public int MyProperty
{
get
{
return /* value */;
}
set
{
/* update value */
}
}
get thePropertyName() {
return /* value */;
}
set thePropertyName(newValue) {
/* update value */
}
Thanks a bunch, that's super-helpful to see the spectrum. I guess the take-away for me is that it doesn't seem like there's a clear "everyone does it this way" precedent. Also, we're in a slightly different boat than all these languages since we only care about defining the signature, not implementations, which makes our constraints slightly different.
My impression is that the "JavaScript-esque" option you presented in your original comment is the better option:
func
)shared
, async
, or reentrant
), it's easy enough to allow those to be used along with get
or set
if we want.I have recently encountered the need for this as well. For syntax I would prefer something a little less verbose than the "Javascript-esque" option since having to define two functions each time seems like overkill. Some kind of default for the non-result
getter/setter option would be nice, only requiring explicitly typing the functions if they differ from the simple case.
//This has the default getter/setter signatures
foo: string
//This type can fail on get or set, so must define the signature for both
bar: get func() -> result<string, error-type>
bar: set func(value: string) -> result<_, error-type>
A readonly
keyword would be nice as well to indicate that a value would only have a getter (assuming that the default is gettable and settable).
Most languages have either:
string MyProperty { get; set; }
get myProperty()
set myProperty(value)
String getMyProperty()
void setMyProperty(String value)
my_property(&self) -> String
set_my_property(&mut self, value: String) -> ()
If properties are not encoded natively in WIT, we'll probably end up with everybody choosing their own convention (based on their own language). Which is bound to end up looking foreign to the other languages. Or we can prescribe a convention for tooling to convert from&to, but at that point we might as well just encode it into Wit itself.
My suggestion:
Or more Javascript-esque:
Either way, in both variants getters and setters:
self
argument, regardless of the outcome of #226%[get]T.property-name: func(self: borrow<T>) -> T
%[get]T.property-name: func(self: borrow<T>) -> result<T, error-type>
%[set]T.property-name: func(self: borrow<T>, value: T)
%[set]T.property-name: func(self: borrow<T>, value: T) -> result<_, error-type>