[Vim 9 script] Is there a way to get the actual type of an object?

5 views
Skip to first unread message

Lifepillar

unread,
Jan 15, 2023, 1:46:40 PM1/15/23
to vim...@googlegroups.com
Silly example:

vim9script

class Num
this.n = 0
endclass

class Even extends Num
def new(this.n)
if this.n % 2 == 1
throw 'Not even'
endif
enddef

def IsPrime(): bool
return this.n == 2
enddef
endclass

class Odd extends Num
def new(this.n)
if this.n % 2 == 0
throw 'Not odd'
endif
enddef

def IsDivisibleByFive(): bool
return this.n % 5 == 0
enddef
endclass

def Random(): Num
const n = rand() % 16
return n % 2 == 0 ? Even.new(n) : Odd.new(n)
enddef

const v = Random()
if # v is instance of Odd()
echo v.IsDivisibleByFive()
else
echo v.IsPrime()
endif

Is there a way to distinguish the class of the value returned by
Random()?

Thanks,
Life.

Bram Moolenaar

unread,
Jan 15, 2023, 3:19:28 PM1/15/23
to vim...@googlegroups.com, Lifepillar
Currently not. I have been wondering what would be the best way to
cover this. We already have type(), but this only returns the basic
type. For example for list<number> and list<string> it returns the same
value. It can tell the difference between a list and an object, but not
between two objects from a different class.

You can use typename(), it will include the name of the class. However,
it is possible to have the same class name in two separate scripts,
since they are script-local by default. Thus this may make you think
it's the same class while it is not.

Using "instanceof" would work in many places, but you would need to
import the class to be able to use it. If you only want to know if two
objects are from the same class, that is extra overhead.

Perhaps we need a variant of type() that is specific about the exact
type. Then it can also be used to tell the difference between
list<number> and list<string>. This will be some work to implement,
because this will mean a new variable type.

--
hundred-and-one symptoms of being an internet addict:
20. When looking at a pageful of someone else's links, you notice all of them
are already highlighted in purple.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Lifepillar

unread,
Jan 15, 2023, 3:40:17 PM1/15/23
to vim...@googlegroups.com
On 2023-01-15, Bram Moolenaar <Br...@moolenaar.net> wrote:
>> Is there a way to distinguish the class of the value returned by
>> [a function]?
>
> Currently not. I have been wondering what would be the best way to
> cover this. We already have type(), but this only returns the basic
> type. For example for list<number> and list<string> it returns the same
> value. It can tell the difference between a list and an object, but not
> between two objects from a different class.
>
> You can use typename(), it will include the name of the class. However,
> it is possible to have the same class name in two separate scripts,
> since they are script-local by default. Thus this may make you think
> it's the same class while it is not.

Ah, that would probably be enough for my use case, as the test in my
case is for script-local objects only.

> Using "instanceof" would work in many places, but you would need to
> import the class to be able to use it. If you only want to know if two
> objects are from the same class, that is extra overhead.
>
> Perhaps we need a variant of type() that is specific about the exact
> type. Then it can also be used to tell the difference between
> list<number> and list<string>. This will be some work to implement,
> because this will mean a new variable type.

To me this falls into the "nice to have" category: I think that most use
cases can be rewritten (possibly verbosely and not elegantly) in a way
that the need for this is avoided. I have a possibly related use case,
but I will post about it in another thread.

Thanks for the comprehensive reply!
Life.

Reply all
Reply to author
Forward
0 new messages