For object members most languages use the "this." prefix. But not
everywhere, which makes it inconsistent. A good example is a
constructor where object members that are also an argument need to be
prefixed with "this." to avoid a name collision, while other object
members are used without "this.". I find that very confusing. Example:
SomeObject(String name)
{
this.name = name;
gender = Gender.unknown;
}
One thing I'm not yet sure about is the declaration. Currently it works
like this:
this.name: string
this.gender: Gender
I'm not a big fan of the "this" keyword. I agree if going to use it, ensure to use it everywhere. Consistency is good. I like simplicity, and dislike redundancy.
So, about "this", alternatively, don't use it anywhere, but maybe you could throw an error if a function argument name is also member variable name. Not sure what static analysis is available - given that its a scripting language. There's not really a compilation step is there?OR, perhaps another option, just thinking outside the box, if a function argument does actually happen to match a member variable name - then automatically force it to actually set that variable. When (if) this becomes the expected behavior, I think it would enable simplifying some things a lot.Explaining with an example. Often, when I'm coding and the arg name is the same as a member variable name, then I usually find myself setting that early-ish in the code. (just using a pseudo code to explain, obviously not real code;)class Blahhthis.toX: TYPE_A
this.toY: TYPE_B
fn SetXandY(toX: TPYE_A, toY: TYPE_B )this.toX = toXthis.toY = toYenfuncendclassSo, I find that pattern happens a lot. And it gets real tedious. I think this could be simplified to the following;
class BlahhtoX: TYPE_AtoY: TYPE_B
fn SetXandY(toX, toY)enfuncendclass
ie. This would set the member variables, toX and toY automatically.Now, we might want to do some sanity check on the argument before clobbering whatever was in there previously. The developer could very easily use another temporary name, for example prefixed with p_ as they wish, and check it is in range for example, before setting it. Like so;
class BlahhtoX: TYPE_AtoY: TYPE_B
fn SetXandY(p_toX, toY)if p_toX in rangetoX = p_toXelseignore, or throw, or set some default, whatever for toXendifenfuncendclass
In this last example, any matching names could be automatically set, so here, the toY would be automatically set.
This is inspired by your idea from the constructor idea you had here;def new(this.lnum, this.col)enddefI like that one :)Cheers,Chris Plewright
> I'm not a big fan of the "this" keyword. I agree if going to use it,
> ensure to use it everywhere. Consistency is good. I like simplicity, and
> dislike redundancy.
What do you mean, do you prefer "self"?
> So, about "this", alternatively, don't use it anywhere, but maybe you
> could throw an error if a function argument name is also member variable
> name.
That is actually very common. It is very likely that methods pass
arguments to set or modify the object members, thus using the same name
is very likely to happen.
> OR, perhaps another option, just thinking outside the box, if a function
> argument does actually happen to match a member variable name - then
> automatically force it to actually set that variable. When (if) this
> becomes the expected behavior, I think it would enable simplifying some
> things a lot.
Boundary checks are often done on arguments, assuming that the argument
is always assigned to an object member is too limiting.
I also want to avoid doing things very differently from what existing
languages are doing. Some different syntax and rules can be acceptable,
but introducing new mechanisms that are hard to understand are to be
avoided.
> class Blahh
> this.toX: TYPE_A
> this.toY: TYPE_B
> fn SetXandY(toX: TPYE_A, toY: TYPE_B )
> this.toX = toX
> this.toY = toY
> enfunc
> endclass
>
> So, I find that pattern happens a lot. And it gets real tedious. I
> think this could be simplified to the following;
>
> class Blahh
> toX: TYPE_A
> toY: TYPE_B
> fn SetXandY(toX, toY)
> enfunc
> endclass
>
> ie. This would set the member variables, toX and toY automatically.
I don't know any language that does this and I find it very obscure and
confusing. Also, it makes giving useful errors difficult. Using an
argument name that happens to be a member name would not result in any
error but silently turned into an assignment.
The difference between a regular method and a constructor is that for a
constructor it is very common to assign the argument to an object
member.
The idea comes from Dart, and I don't think Dart supports this for
anything but constructors.
One thing I'm not yet sure about is the declaration. Currently it works
like this:
this.name: string
this.gender: Gender
Notice that there is no "var" keyword. It's not needed to recognize the
declaration. I can't think of a good reason to add "var" here, other
than that a declaration would be expected to always have "var". Well, I
don't have that expectation.
For class members most languages use the "static" keyword. It's a bit
of a weird word, but I suppose most people are used to it, and I can't
find a popular language that has a good alternative.
If we leave out "var" for object members, I suppose we should also leave
it out for class members. We then get:
static oneClassMember: number
static twoClassMember: string
I think this looks fine. Any objections?
> No, I prefer 'this' over 'self'. I was considering if its possible to go without any keyword for it. For example, these days we also have syntax highlighting which can give a different color for member variables and arguments.In order to give different colors for member variables and function arguments you need a very sophisticated parser. Otherwise you cannot distinguish the two in code. For the same reason C++ developers often prefix member variables with `m_`, like `m_age`, others use a postfix underscore like `age_` etc. I don't like it because it's not consistent
Personally, I would prefer `this` (or `self` etc.) for member variables. It makes the syntax script a lot simpler and the syntax highlighting will work 100%. It will also be easier to `:grep` for all usages of a member variable since every reference of a member variable will contain `this`
On Mon, 19 Dec 2022 at 00:33, Bram Moolenaar <Br...@moolenaar.net> wrote:
One thing I'm not yet sure about is the declaration. Currently it works
like this:
this.name: string
this.gender: Gender
Notice that there is no "var" keyword. It's not needed to recognize the
declaration. I can't think of a good reason to add "var" here, other
than that a declaration would be expected to always have "var". Well, I
don't have that expectation.This following currently defines a field and is, without context, indistinguishable from any other assignment. Is that intended?this.name = "Somebody"
As methods still require :def I think it would be more consistent to not special case field declarations and still require the :var.For class members most languages use the "static" keyword. It's a bit
of a weird word, but I suppose most people are used to it, and I can't
find a popular language that has a good alternative.
If we leave out "var" for object members, I suppose we should also leave
it out for class members. We then get:
static oneClassMember: number
static twoClassMember: string
I think this looks fine. Any objections?It seems from the documentation that static fields can be referenced as bare identifiers? This feels a bit unexpected to me given that instance fields are always qualified.
echomsg c.classMember
MyClass.SomeStaticFunction()
vim9script
class MyClass
public this.instanceMember: string
public static classMember = 'foo'
def new(instanceMember: string)
this.instanceMember = instanceMember
enddef
def GetCM(): string
return 'foobar'
# following gets: Variable not found: classMember
#return classMember
# following gets: compile_class_object_index: not handled
#return MyClass.classMember
enddef
endclass
var c = MyClass.new("abc")
echomsg c.instanceMember
echomsg MyClass.classMember
echomsg c.GetCM()
# fails
echomsg c.classMember
With 9.0.1094, in the script that follows, attempting to read a classMember through an instance fails; echomsg c.classMember should it?No, an object does not provide a class member.I suppose requiring the class name makes it most clear, but I recall mention that classnames can get long. I suppose a getter could be added.How can you access the getter without referring to the class?
Assuming c is an object
c.GetClassMember()
where the method GetClassMember() returns the classMember that was declared static.
Can a class method (or should it be called class function?) be static?Nothing *is* static, the "static" keyword is used to change the meaning of items.
I should have said "can a method/function defined in a class be declared static?"
One way to look at it: is it the case that any method can be invoked as
MyClass.SomeMethod()
and as long as "SomeMethod()" doesn't reference a variable like "this.someVar" then it's OK?
-ernieOn 22/12/25 1:07 PM, Bram Moolenaar wrote:
With 9.0.1094, in the script that follows, attempting to read a classMember through an instance fails; echomsg c.classMember should it?No, an object does not provide a class member.I suppose requiring the class name makes it most clear, but I recall mention that classnames can get long. I suppose a getter could be added.How can you access the getter without referring to the class?
Assuming c is an object
c.GetClassMember()
where the method GetClassMember() returns the classMember that was declared static.
Can a class method (or should it be called class function?) be static?Nothing *is* static, the "static" keyword is used to change the meaning of items.I should have said "can a method/function defined in a class be declared static?"
One way to look at it: is it the case that any method can be invoked as
MyClass.SomeMethod()
and as long as "SomeMethod()" doesn't reference a variable like "this.someVar" then it's OK?
-ernie
On Monday, 26 December 2022 at 09:08:22 UTC+11 err...@raelity.com wrote:
On 22/12/25 1:07 PM, Bram Moolenaar wrote:
With 9.0.1094, in the script that follows, attempting to read a classMember through an instance fails; echomsg c.classMember should it?No, an object does not provide a class member.I suppose requiring the class name makes it most clear, but I recall mention that classnames can get long. I suppose a getter could be added.How can you access the getter without referring to the class?
Assuming c is an object
c.GetClassMember()
where the method GetClassMember() returns the classMember that was declared static.
Can a class method (or should it be called class function?) be static?Nothing *is* static, the "static" keyword is used to change the meaning of items.I should have said "can a method/function defined in a class be declared static?"
I don't think it's a good idea to access static class function from an object instance of that class.
I was not suggesting that. I've botched the question. I was saying that to get a class member (something declared static) from an object, there could be an instance method that returns the class member.
And I didn't know that it was documented that a function could be
declared static; missed that, my bad.
Also, I would not name that function with "Member" if it is a static function, because member implies that it is a member method of an object instance. I think that could lead to confusion for someone else trying to read your code.The difference between a function and a method is important - with regard to this topic of classes vs objects of the class. According to Bram's preliminary doco. Yes, class "method" can be declared static. But then, I think that makes it a static class "function", and not a class "method".
Bram, I think that the doco here is referring to a class "function", not a class "method". It might be worth distinguishing between method and function in the doco?
Ref:
One way to look at it: is it the case that any method can be invoked as
MyClass.SomeMethod()
and as long as "SomeMethod()" doesn't reference a variable like "this.someVar" then it's OK?
-ernie
How would Vim know when that is an error or not, if you didn't specify the static keyword when declaring the static class function.
I didn't know it was documented that there could be a static class function. The whole point of the question was to determine if there could be a static class function.
Sorry for the noise and confusion,
-ernie
You want Vim to treat it as if it was a static class function, but wouldn't Vim need to analyse deeper to see if it uses any object members, to be able to allow that?
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups "vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/vim_dev/656faf72-e6a1-452c-bd25-59c22a071115n%40googlegroups.com.
> I thought that the declaration would be like this;
>
> this.name : *string *= "Somebody"
>
> Or is auto-type detection at play here too?
It's called type inference. The type of the expression is used as the
type of the variable. In most cases this works very well, keeps it
short and it's obvious what the variable is used for. What it does not
work well for is when using an empty list or dictionary.
> >>> For class members most languages use the "static" keyword. It's a bit
> >> of a weird word, but I suppose most people are used to it, and I can't
> >> find a popular language that has a good alternative.
> >>
> >> If we leave out "var" for object members, I suppose we should also leave
> >> it out for class members. We then get:
> >>
> >> static oneClassMember: number
> >> static twoClassMember: string
> >>
> >> I think this looks fine. Any objections?
> >>
> >
> > It seems from the documentation that static fields can be referenced as
> > bare identifiers? This feels a bit unexpected to me given that instance
> > fields are always qualified.
>
> Just sharing another idea - perhaps also require "*static.*" as the class
> scope prefix, and enforce it - for all the same reasons that "*this.*"
> would be enforced as the object scope prefix.
I don't know a language that does this. As I mentioned, the word
"static" is a bit strange anyway, using it in more places makes that
worse.
> Alternatively, perhaps we could use the actual class name as the enforced
> prefix for static class scoped variables. Either option would avoid
> confusion with inner function variables.
Some languages use the class name as a prefix for class members.
Outside of the class this makes sense, it's like a scope name. Inside
the class, however, using the class name is more duplicating what you
already know. With inheritance the question comes up if the current
class name or the parent class name need to be used (maybe both work?).
And class names have a tendency to be quite long.
There is also some similarity of using a script-local variable in code
and functions inside that script. We currently don't use a prefix, and
that works fine. I can predict that using class members inside the
class can work without a prefix without a problem, just like using
script-local variables.
> Either way, it seems consistency is important here.
>
> The following is all over the place;
>
> var static oneClassMember: number
> var static twoClassMember: string
> this.threeObjectMember: number
> this.fourObjectMember: string
Using "var" is either for both or none, this mix is not making sense.
> I think that the following also looks inconsistent;
>
> static oneClassMember: number
> static twoClassMember: string
> this.threeObjectMember: number
> this.fourObjectMember: string
Class and object members *are* different, thus I don't think consistency
is important here, or even a goal.
> I think the following is better, more consistent, and this would be my
> preference;
>
> static.oneClassMember: number
> static.twoClassMember: string
> this.threeObjectMember: number
> this.fourObjectMember: string
This goes against the syntax we know from any other language. Using
"static" as a prefix looks weird to me.
> I don't mind var, but I don't see a real need for it either, because the
> declarations will have the type name included. Anyway, if going to use
> var, please keep it consistent, eg like this;
>
> var static.oneClassMember: number
> var static.twoClassMember: string
> var this.threeObjectMember: number
> var this.fourObjectMember: string
Whether to use "var" or not was also part of the discussion. It does
make it clearer that we're looking at a declaraction. But otherwise the
"var" keyword is not actually needed.
I also wonder if it should be "var static oneClassMember" or
"static var oneClassMember". Just using "static oneClassMember" avoids
that. That still leaves open the possibility to use:
static oneClassMember: number
var this.oneObjectMember: number
Or:
static oneClassMember: number
this.oneObjectMember: number
On 22/12/25 2:54 PM, Christopher Plewright wrote:I didn't know it was documented that there could be a static class function. The whole point of the question was to determine if there could be a static class function.
Sorry for the noise and confusion,
-ernie
> I think that makes it a static class "function", and not a class "method".
That depends on how you define this. A method usually implicitily gets
an extra argument or is aware of its context. It does not necessarily
alwayw need to be an object.
> Bram, I think that the doco here is referring to a class "function", not a
> class "method". It might be worth distinguishing between method and
> function in the doco?
If that makes it easier to understand.
Another possibility occurred to me, that you could keep; function and endfunctionThat could still be used to always mean static functions - as that essentially does now already - I mean, because there was no such thing as object member methods in vimscript before classes were added.So, if you say function and endfunction, when defined inside a class, means a static function of that class. You wouldn't need the word static for that.Because... you now have the opportunity to add; method and endmethod to define object member methods. ie. instead of def and enddef. I find def and enddef a bit too generic, but that is just my opinion. Again, this is relying on a certain meaning of the word method, which I dont think is uncommon, but as you said it doesn't necessarily always have that meaning either.If you did this then static wouldn't need to be used for functions or methods. That would just leave static for variables. And, I think "s:" is very close in meaning already to how I understand static, (it implies certain lifetime and accessibility), and so you could say that an s: variable, when declared inside a class definition, is a static variable.If you did these couple of things, then you wouldn't need to use the word "static" anywhere.
> This following currently defines a field and is, without context,
> indistinguishable from any other assignment. Is that intended?
With "var" it's indistinguishable from another declaration, I don't
think it matters much that it looks like an assignment otherwise.
> It seems from the documentation that static fields can be referenced as
> bare identifiers? This feels a bit unexpected to me given that instance
> fields are always qualified.
Static fields (class members) are totally different from object members.
I have always found it confusing, in many languages it's hard to tell
them apart, especially if the declaration is further away. Always using
"this" for object members helps a lot for this. I would not know what
to use for class members. The only thing I have seen is using the class
name, which can be long (and gets tricky when using inheritance).
I believe most languages access class members directly, without a
prefix.