"var F = obj.classMethod" What type is F?

19 views
Skip to first unread message

Ernie Rael

unread,
May 20, 2023, 7:33:28 PM5/20/23
to vim...@googlegroups.com
> > var F: func = obj.classMethod
> 1. Binding an object with an object method, like a dictionary is bound
> to a function on a dictionary. "obj.classMethod" in the example.
>
> This applies to 1: It will be a new type, as the bound object is
> included, which differs from a function that is not bound.

Seems like making it a new type is more work for no benefit.
There's the vim9script programmers view, and the vim internals view.

If I have a function today, with a signature like
    def MyFunc(ArgFunc: func)
if "obj.callMethod" is a different type, will I be able to do
    MyFunc(obj.classMethod)

And "map()" builtin says "{expr2} must be a String or Funcref". Will
    []->map(obj.classMethod)
work?

Assume obj.classMethod has type objMethodType. Once you do
    var F = obj.classMethod
Is there a difference between a func and objMethodType as far as
its use? Is there extra capability or functionality?

Of course internally in vim, they are different or maybe
objMethodType is an extension/subtype of func.

-ernie

Bram Moolenaar

unread,
May 21, 2023, 7:49:57 AM5/21/23
to vim...@googlegroups.com, Ernie Rael

Ernie Rael wrote:

> > > var F: func = obj.classMethod
> > 1. Binding an object with an object method, like a dictionary is bound
> > to a function on a dictionary. "obj.classMethod" in the example.
> >
> > This applies to 1: It will be a new type, as the bound object is
> > included, which differs from a function that is not bound.
>
> Seems like making it a new type is more work for no benefit.
> There's the vim9script programmers view, and the vim internals view.

It's often not possible to hide the internal view from what users
experience. We do have incomplete types, such as "any" or "func", which
require runtime type checking. That means you don't get errors for
wrong usage during compile time. And at runtime you might get a
different error depending on what type of function is being passed
around. And there might be additional functionality, e.g. to get the
object that has been bound to.

If you mean, whether the type declaration needs to be different, I'm not
sure. Currently a partial isn't declared differently from a function
reference, it might be possible to not have a separate type declaration
when an object is bound to a function. But since the functionality is
different, it might be useful to declare the type in a way that makes
clear this functionality is available.

When comparing values then the object the function is bound to will also
matter:

var obj_A1 = A.new()
var Func_A1 = obj_A1.Method
var obj_A2 = A.new()
var Func_A2 = obj_A2.Method
echo Func_A1 == Func_A2 # result: false

That differs from when the function reference would not bind an object,
thus the type also differs.


> If I have a function today, with a signature like
>     def MyFunc(ArgFunc: func)
> if "obj.callMethod" is a different type, will I be able to do
>     MyFunc(obj.classMethod)
>
> And "map()" builtin says "{expr2} must be a String or Funcref". Will
>     []->map(obj.classMethod)
> work?

Sure, so long as you pass the right arguments. It's very similar to
using a partial.

> Assume obj.classMethod has type objMethodType. Once you do
>     var F = obj.classMethod
> Is there a difference between a func and objMethodType as far as
> its use? Is there extra capability or functionality?

See above.

> Of course internally in vim, they are different or maybe
> objMethodType is an extension/subtype of func.

I'm not sure about terminology, but it's very similar to using a partial
versus using a function reference.

--
hundred-and-one symptoms of being an internet addict:
49. You never have to deal with busy signals when calling your ISP...because
you never log off.

/// 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 ///

Ernie Rael

unread,
May 21, 2023, 12:36:32 PM5/21/23
to vim...@googlegroups.com
On 23/05/21 4:49 AM, Bram Moolenaar wrote:
> Ernie Rael wrote:
>
>> > > var F: func = obj.classMethod
>> > 1. Binding an object with an object method, like a dictionary is bound
>> > to a function on a dictionary. "obj.classMethod" in the example.
>> >
>> > This applies to 1: It will be a new type, as the bound object is
>> > included, which differs from a function that is not bound.
>>
>> Seems like making it a new type is more work for no benefit.
>> There's the vim9script programmers view, and the vim internals view.
> It's often not possible to hide the internal view from what users
> experience. We do have incomplete types, such as "any" or "func", which
> require runtime type checking. That means you don't get errors for
> wrong usage during compile time. And at runtime you might get a
> different error depending on what type of function is being passed
> around.
My primary concern is that a bound-object-method can be used anywhere a
func can be used. Passing it to an existing function that has an argument
declared "arg: func" or to a builtin that expects a funcref. I have one
case that might push the limit

    export def Log(msgOrFunc: any, category: string = '')
        var msg_type = type(msgOrFunc)
        ...
        elseif msg_type == v:t_func

> And there might be additional functionality, e.g. to get the
> object that has been bound to.
I was wondering about getting the object. If you can get the object, is is
possible to set the object? If there is something like
    setboundobject(bound-object-method, object)
and if the type of object must be assignable to the original object type,
then you you have a variable which is similar to a c++ "pointer to a member
function" except that it includes the object. This would seem to satisfy
the clamoring for using a method as a value. I guess the object could be
any arbitrary type, but that feels much more complicated.

> If you mean, whether the type declaration needs to be different, I'm not
> sure. Currently a partial isn't declared differently from a function
> reference, it might be possible to not have a separate type declaration
> when an object is bound to a function. But since the functionality is
> different, it might be useful to declare the type in a way that makes
> clear this functionality is available.
Is type being used imprecisely? (Like declare versus define)
I can see defining a bound object method differently
    var F: func
    F = bindobjectmethod(obj, method)
which wouldn't affect any existing code. But if the resulting type
is not t_func that presents compatibility/usage problems.

-ernie

Bram Moolenaar

unread,
May 21, 2023, 12:59:34 PM5/21/23
to vim...@googlegroups.com, Ernie Rael

Ernie Rael wrote:

> My primary concern is that a bound-object-method can be used anywhere a
> func can be used. Passing it to an existing function that has an argument
> declared "arg: func" or to a builtin that expects a funcref. I have one
> case that might push the limit
>
>     export def Log(msgOrFunc: any, category: string = '')
>         var msg_type = type(msgOrFunc)
>         ...
>         elseif msg_type == v:t_func

We'll have to see what type() should return for something like this.
Again, it should be similar to what is used for a partial.

> > And there might be additional functionality, e.g. to get the
> > object that has been bound to.
> I was wondering about getting the object. If you can get the object, is is
> possible to set the object? If there is something like
>     setboundobject(bound-object-method, object)

I don't think so. It sounds like a corner case, not much practical use.
You can get the dict from a partial with get(). You can change it with
function(), but there is no type checking at all. When using an object
instead of a dict type checking would be very relevant.

> and if the type of object must be assignable to the original object type,
> then you you have a variable which is similar to a c++ "pointer to a member
> function" except that it includes the object. This would seem to satisfy
> the clamoring for using a method as a value. I guess the object could be
> any arbitrary type, but that feels much more complicated.

The object would need to match what the method is expecting. With
inheritance this isn't simple.

> > If you mean, whether the type declaration needs to be different, I'm not
> > sure. Currently a partial isn't declared differently from a function
> > reference, it might be possible to not have a separate type declaration
> > when an object is bound to a function. But since the functionality is
> > different, it might be useful to declare the type in a way that makes
> > clear this functionality is available.
> Is type being used imprecisely? (Like declare versus define)
> I can see defining a bound object method differently
>     var F: func
>     F = bindobjectmethod(obj, method)
> which wouldn't affect any existing code. But if the resulting type
> is not t_func that presents compatibility/usage problems.

Currently type() only indicates the basic type. For a function it
doesn't mention the argument or return types. This most likely won't
change and there isn't really a reason to add the bound object type.

typename() is more specific. It likely should mention the class of the
bound object.

--
hundred-and-one symptoms of being an internet addict:
50. The last girl you picked up was only a jpeg.

Ernie Rael

unread,
May 21, 2023, 1:25:31 PM5/21/23
to vim...@googlegroups.com

>>> And there might be additional functionality, e.g. to get the
>>> object that has been bound to.
>> I was wondering about getting the object. If you can get the object, is is
>> possible to set the object? If there is something like
>>     setboundobject(bound-object-method, object)
> I don't think so. It sounds like a corner case, not much practical use.
> You can get the dict from a partial with get(). You can change it with
> function(), but there is no type checking at all. When using an object
> instead of a dict type checking would be very relevant.
>
I agree, and I don't see it as a problem at all; it's easy to get the
functionality. Consider the following

    var methodNameAsVar(obj: BaseType, ...args: any) => {
        call(obj.methodName, args)
    }

    methodNameAsVar(obj, arg1, arg2)

With possible runtime errors.

-ernie

Reply all
Reply to author
Forward
0 new messages