Loading ...
Sorry, an error occurred while loading the content.

Funcref and script local functions

Expand Messages
  • Hari Krishna Dara
    When Funcref s were introduced in Vim7, I expected them to work for script-local functions, across scripts. The documentation didn t say that, but it didn t
    Message 1 of 12 , Jun 29, 2006
    • 0 Attachment
      When Funcref's were introduced in Vim7, I expected them to work for
      script-local functions, across scripts. The documentation didn't say
      that, but it didn't say that it wouldn't either, and I thought that that
      is one of its biggest uses (other than the actual intended
      functionality, which is for implementing numbered functions). However, I
      found that the Funcref references for such functions can't actually be
      passed out to other scripts. This reduces the usefulness of this feature
      as we can't register private functions to receive callbacks from other
      scripts.

      What is weird is that the the Funcref() actually behaves exactly like
      the function name itself. Say you have a function called s:T() and say
      the script id is 60. The Funcref obtained via function('s:T') can't be
      called from outside the script, but if the Funcref is obtained using
      function('<SNR>60_T'), then it will be fine. Also, a Funcref obtained
      using these two methods will not be to the same object, though you would
      expect them to be. The below echoes 0:

      echomsg function('s:T') is function('<SNR>60_T')

      where as the below echoes 1:

      echomsg function('s:T') is function('s:T')

      The above two facts make Funcref counter-intuitive to understand. I
      actually wonder why even a special function called function() was
      required to obtain the Funcref in the first place (unlike in Python).

      There are other aspects of the new features that are very
      counter-intuitive to me, whether I think in terms of Python or generic
      "objects" in any language. The one which gets me the most is the
      implicit typing of variables based on the initializer. For basic types
      prior to Vim7 (integer and string), you could easily switch the value of
      the variable from integer to string or vice versa, and the type() of the
      variable would change, suggesting that it behaves like "duck typing" (as
      per (wikipedia). But this observation can't be extended to the newer
      object types, as the below will fail:

      let a = {}
      let a = []

      If the type of value determines the type of the variable, and if we are
      merely dealing with references (assigning references instead of copying
      objects), then why should the second statement above generate the below
      error?

      E706: Variable type mismatch for: a

      Is there a standard for this type of language behavior? I didn't find
      anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed

      I declare all my script variables before they are used, and it hurts me
      for the fact that you have to create an empty array or hash such that
      these variable types are established correctly. But when it comes to a
      Funcref type, it is lousy that you have to initialize the variable with
      the Funcref of some random function so that the type of variable gets
      established as Funcref.

      I don't know if what I say above makes sense to anyone (I never studied
      computer science, so these are based on what you could call as common
      sense of a software developer :), or if anything can be done about them
      now, but at least I thought I will give some feedback on what has been
      bothering me.

      --
      Thank you,
      Hari

      __________________________________________________
      Do You Yahoo!?
      Tired of spam? Yahoo! Mail has the best spam protection around
      http://mail.yahoo.com
    • Eric Arnold
      Ok. For starters, it seems that you *can* call a numbered function from anywhere: function! s:T() echomsg here echomsg SID= . expand( )
      Message 2 of 12 , Jun 29, 2006
      • 0 Attachment
        Ok. For starters, it seems that you *can* call a numbered function
        from anywhere:



        function! s:T()
        echomsg "here"
        echomsg 'SID=' . expand( '<sfile>' )
        endfunction

        let F=function('s:T')
        echomsg F()

        let F1 = function( '<SNR>66_T' )
        echomsg F1()

        echomsg string( F )

        let s:dict = {}
        function s:dict.init() dict
        echomsg "in dict function"
        endfunction

        unlet! F2
        let F2 = s:dict.init

        call call(F2,[],{})
        " Note: F2 is a global, so the numbered function declared for a local dict
        " is available to call globally.


        On 6/29/06, Hari Krishna Dara <hari_vim@...> wrote:
        >
        > When Funcref's were introduced in Vim7, I expected them to work for
        > script-local functions, across scripts. The documentation didn't say
        > that, but it didn't say that it wouldn't either, and I thought that that
        > is one of its biggest uses (other than the actual intended
        > functionality, which is for implementing numbered functions). However, I
        > found that the Funcref references for such functions can't actually be
        > passed out to other scripts. This reduces the usefulness of this feature
        > as we can't register private functions to receive callbacks from other
        > scripts.
        >
        > What is weird is that the the Funcref() actually behaves exactly like
        > the function name itself. Say you have a function called s:T() and say
        > the script id is 60. The Funcref obtained via function('s:T') can't be
        > called from outside the script, but if the Funcref is obtained using
        > function('<SNR>60_T'), then it will be fine. Also, a Funcref obtained
        > using these two methods will not be to the same object, though you would
        > expect them to be. The below echoes 0:
        >
        > echomsg function('s:T') is function('<SNR>60_T')
        >
        > where as the below echoes 1:
        >
        > echomsg function('s:T') is function('s:T')


        In this case you are *not* creating numbered functions, so the string
        value you use is what gets stored.


        > The above two facts make Funcref counter-intuitive to understand. I
        > actually wonder why even a special function called function() was
        > required to obtain the Funcref in the first place (unlike in Python).
        >
        > There are other aspects of the new features that are very
        > counter-intuitive to me, whether I think in terms of Python or generic
        > "objects" in any language. The one which gets me the most is the
        > implicit typing of variables based on the initializer. For basic types
        > prior to Vim7 (integer and string), you could easily switch the value of
        > the variable from integer to string or vice versa, and the type() of the
        > variable would change, suggesting that it behaves like "duck typing" (as
        > per (wikipedia). But this observation can't be extended to the newer
        > object types, as the below will fail:


        The whole auto-initialize thing is a sticky wicket as far as I see it.
        I'd love to have it initialize *all* cases where a name is
        references, either on RHS or LHS.

        However, I don't know whether this was intended by Bram as a way to
        implement type checking.


        > let a = {}
        > let a = []
        >
        > If the type of value determines the type of the variable, and if we are
        > merely dealing with references (assigning references instead of copying
        > objects), then why should the second statement above generate the below
        > error?
        >
        > E706: Variable type mismatch for: a
        >
        > Is there a standard for this type of language behavior? I didn't find
        > anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed
        >
        > I declare all my script variables before they are used, and it hurts me
        > for the fact that you have to create an empty array or hash such that
        > these variable types are established correctly. But when it comes to a
        > Funcref type, it is lousy that you have to initialize the variable with
        > the Funcref of some random function so that the type of variable gets
        > established as Funcref.


        I'm not sure I see the problem in practice. The only time you'd have
        to pre-define a funcref variable would be if you intended to try to
        use it when it was empty. Are you really doing this?


        > I don't know if what I say above makes sense to anyone (I never studied
        > computer science, so these are based on what you could call as common
        > sense of a software developer :), or if anything can be done about them
        > now, but at least I thought I will give some feedback on what has been
        > bothering me.

        > --
        > Thank you,
        > Hari
        >
      • Hari Krishna Dara
        ... Right, and that is what I intended by saying the Funcref s are behaving as the original functions. Since numbered functions are accessible globally, their
        Message 3 of 12 , Jul 2 7:12 PM
        • 0 Attachment
          On Thu, 29 Jun 2006 at 10:50pm, Eric Arnold wrote:

          > Ok. For starters, it seems that you *can* call a numbered function
          > from anywhere:
          >
          >
          >
          > function! s:T()
          > echomsg "here"
          > echomsg 'SID=' . expand( '<sfile>' )
          > endfunction
          >
          > let F=function('s:T')
          > echomsg F()
          >
          > let F1 = function( '<SNR>66_T' )
          > echomsg F1()
          >
          > echomsg string( F )
          >
          > let s:dict = {}
          > function s:dict.init() dict
          > echomsg "in dict function"
          > endfunction
          >
          > unlet! F2
          > let F2 = s:dict.init
          >
          > call call(F2,[],{})
          > " Note: F2 is a global, so the numbered function declared for a local dict
          > " is available to call globally.

          Right, and that is what I intended by saying the Funcref's are behaving
          as the original functions. Since numbered functions are accessible
          globally, their Fucrefs are too (for that matter, I don't think you can
          even call numbered functions directly, so this situation is not
          completely same).

          >
          >
          > On 6/29/06, Hari Krishna Dara <hari_vim@...> wrote:
          > >
          > > When Funcref's were introduced in Vim7, I expected them to work for
          > > script-local functions, across scripts. The documentation didn't say
          > > that, but it didn't say that it wouldn't either, and I thought that that
          > > is one of its biggest uses (other than the actual intended
          > > functionality, which is for implementing numbered functions). However, I
          > > found that the Funcref references for such functions can't actually be
          > > passed out to other scripts. This reduces the usefulness of this feature
          > > as we can't register private functions to receive callbacks from other
          > > scripts.
          > >
          > > What is weird is that the the Funcref() actually behaves exactly like
          > > the function name itself. Say you have a function called s:T() and say
          > > the script id is 60. The Funcref obtained via function('s:T') can't be
          > > called from outside the script, but if the Funcref is obtained using
          > > function('<SNR>60_T'), then it will be fine. Also, a Funcref obtained
          > > using these two methods will not be to the same object, though you would
          > > expect them to be. The below echoes 0:
          > >
          > > echomsg function('s:T') is function('<SNR>60_T')
          > >
          > > where as the below echoes 1:
          > >
          > > echomsg function('s:T') is function('s:T')
          >
          >
          > In this case you are *not* creating numbered functions, so the string
          > value you use is what gets stored.

          I think you misunderstood me, I didn't mean this.

          >
          > > The above two facts make Funcref counter-intuitive to understand. I
          > > actually wonder why even a special function called function() was
          > > required to obtain the Funcref in the first place (unlike in Python).
          > >
          > > There are other aspects of the new features that are very
          > > counter-intuitive to me, whether I think in terms of Python or generic
          > > "objects" in any language. The one which gets me the most is the
          > > implicit typing of variables based on the initializer. For basic types
          > > prior to Vim7 (integer and string), you could easily switch the value of
          > > the variable from integer to string or vice versa, and the type() of the
          > > variable would change, suggesting that it behaves like "duck typing" (as
          > > per (wikipedia). But this observation can't be extended to the newer
          > > object types, as the below will fail:
          >
          >
          > The whole auto-initialize thing is a sticky wicket as far as I see it.
          > I'd love to have it initialize *all* cases where a name is
          > references, either on RHS or LHS.
          >
          > However, I don't know whether this was intended by Bram as a way to
          > implement type checking.

          Do you mean E706 is probably unintentional in this case?

          >
          >
          > > let a = {}
          > > let a = []
          > >
          > > If the type of value determines the type of the variable, and if we are
          > > merely dealing with references (assigning references instead of copying
          > > objects), then why should the second statement above generate the below
          > > error?
          > >
          > > E706: Variable type mismatch for: a
          > >
          > > Is there a standard for this type of language behavior? I didn't find
          > > anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed
          > >
          > > I declare all my script variables before they are used, and it hurts me
          > > for the fact that you have to create an empty array or hash such that
          > > these variable types are established correctly. But when it comes to a
          > > Funcref type, it is lousy that you have to initialize the variable with
          > > the Funcref of some random function so that the type of variable gets
          > > established as Funcref.
          >
          >
          > I'm not sure I see the problem in practice. The only time you'd have
          > to pre-define a funcref variable would be if you intended to try to
          > use it when it was empty. Are you really doing this?

          No, that is not what I was saying. If there is a way to declare
          variables without initializing them, I would have said something like:

          Funcref var

          However, the equivalent of the above is to say:

          let var = function('somefunc')

          The alternative is of course to just initialize the variable as and when
          it is required, but I generally don't like this approach, as it is not
          clear which variables are being used.

          --
          Thanks,
          Hari

          __________________________________________________
          Do You Yahoo!?
          Tired of spam? Yahoo! Mail has the best spam protection around
          http://mail.yahoo.com
        • Eric Arnold
          ... I m still not getting it, I think. Do you have a case where the numbered function scheme will break down, or is it about the callbacks, described below?
          Message 4 of 12 , Jul 3 5:35 AM
          • 0 Attachment
            On 7/2/06, Hari Krishna Dara <hari_vim@...> wrote:
            >
            > On Thu, 29 Jun 2006 at 10:50pm, Eric Arnold wrote:
            >
            > > Ok. For starters, it seems that you *can* call a numbered function
            > > from anywhere:
            > >
            > >
            > >
            > > function! s:T()
            > > echomsg "here"
            > > echomsg 'SID=' . expand( '<sfile>' )
            > > endfunction
            > >
            > > let F=function('s:T')
            > > echomsg F()
            > >
            > > let F1 = function( '<SNR>66_T' )
            > > echomsg F1()
            > >
            > > echomsg string( F )
            > >
            > > let s:dict = {}
            > > function s:dict.init() dict
            > > echomsg "in dict function"
            > > endfunction
            > >
            > > unlet! F2
            > > let F2 = s:dict.init
            > >
            > > call call(F2,[],{})
            > > " Note: F2 is a global, so the numbered function declared for a local dict
            > > " is available to call globally.
            >
            > Right, and that is what I intended by saying the Funcref's are behaving
            > as the original functions. Since numbered functions are accessible
            > globally, their Fucrefs are too (for that matter, I don't think you can
            > even call numbered functions directly, so this situation is not
            > completely same).


            I'm still not getting it, I think. Do you have a case where the
            numbered function scheme will break down, or is it about the
            callbacks, described below?


            > >
            > >
            > > On 6/29/06, Hari Krishna Dara <hari_vim@...> wrote:
            > > >
            > > > When Funcref's were introduced in Vim7, I expected them to work for
            > > > script-local functions, across scripts. The documentation didn't say
            > > > that, but it didn't say that it wouldn't either, and I thought that that
            > > > is one of its biggest uses (other than the actual intended
            > > > functionality, which is for implementing numbered functions). However, I

            I'm not sure that there is a problem. As with C code, if you have
            the option of declaring a function global/local, public/private, etc.
            I think Vim script is allowing these options.

            Are you saying that you want to override the private script
            declarations by declaring a function reference to a low enough level
            pointer that it goes under the scope checker?


            > > > found that the Funcref references for such functions can't actually be
            > > > passed out to other scripts. This reduces the usefulness of this feature
            > > > as we can't register private functions to receive callbacks from other
            > > > scripts.


            I think this is probably a request that it be more object oriented
            than it is, ie. you really want object-scoped functions, not
            script-scoped. You seem to want the script localized, so it can't be
            access generally, but then be public for registering callbacks. This
            seems like an object-scope problem.

            I think that the numbered functions are allowed globally, probably
            because they are intended to be used as you describe, for callbacks
            from other scripts, since they are only created for the 'dict'
            "object" functions, as far as I can tell.

            > > >
            > > > What is weird is that the the Funcref() actually behaves exactly like
            > > > the function name itself. Say you have a function called s:T() and say
            > > > the script id is 60. The Funcref obtained via function('s:T') can't be
            > > > called from outside the script, but if the Funcref is obtained using
            > > > function('<SNR>60_T'), then it will be fine. Also, a Funcref obtained


            Both of these examples seem reasonable to me. If you declare a
            function reference to a script-local object, s:T then you don't
            want it being accessed outside the script. If you declare a
            '<SNR>60_T' reference, then you probably wanted to use it outside
            the script, otherwise you wouldn't have gone through the trouble of
            finding the script id.


            > > > using these two methods will not be to the same object, though you would
            > > > expect them to be. The below echoes 0:


            How did you test what the object was? Actually, I wouldn't expect it
            to be the same object in any case, since each reference to it should
            crease a new instance. They both might refer to the same function
            definition stored internally, but I don't know.

            Also, we aren't talking about true "objects", just to be clear, but an
            enhancment that allows object-oriented-like functional access. This
            limits the expectations we can have.


            > > >
            > > > echomsg function('s:T') is function('<SNR>60_T')
            > > >
            > > > where as the below echoes 1:
            > > >
            > > > echomsg function('s:T') is function('s:T')
            > >
            > >
            > > In this case you are *not* creating numbered functions, so the string
            > > value you use is what gets stored.
            >
            > I think you misunderstood me, I didn't mean this.

            > >
            > > > The above two facts make Funcref counter-intuitive to understand. I
            > > > actually wonder why even a special function called function() was
            > > > required to obtain the Funcref in the first place (unlike in Python).


            I suppose the Funcref function was probably created as a shortcut to
            adding a more complex syntax modification to the language.


            > > >
            > > > There are other aspects of the new features that are very
            > > > counter-intuitive to me, whether I think in terms of Python or generic
            > > > "objects" in any language. The one which gets me the most is the
            > > > implicit typing of variables based on the initializer. For basic types
            > > > prior to Vim7 (integer and string), you could easily switch the value of
            > > > the variable from integer to string or vice versa, and the type() of the
            > > > variable would change, suggesting that it behaves like "duck typing" (as
            > > > per (wikipedia). But this observation can't be extended to the newer
            > > > object types, as the below will fail:
            > >
            > >
            > > The whole auto-initialize thing is a sticky wicket as far as I see it.
            > > I'd love to have it initialize *all* cases where a name is
            > > references, either on RHS or LHS.
            > >
            > > However, I don't know whether this was intended by Bram as a way to
            > > implement type checking.
            >
            > Do you mean E706 is probably unintentional in this case?


            No, it is clearly intentional. What I'm not sure about is whether
            Bram intends Vim script to become more or less 'typed'. Right now, it
            isn't really consistent, since string and numbers are pretty loosely
            typed, whereas the new Dict/List/Funcref are not.

            I'm suspecting that this didn't fit into the schedule when Vim7 was released.


            >
            > >
            > >
            > > > let a = {}
            > > > let a = []
            > > >
            > > > If the type of value determines the type of the variable, and if we are
            > > > merely dealing with references (assigning references instead of copying
            > > > objects), then why should the second statement above generate the below
            > > > error?
            > > >
            > > > E706: Variable type mismatch for: a
            > > >
            > > > Is there a standard for this type of language behavior? I didn't find
            > > > anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed
            > > >
            > > > I declare all my script variables before they are used, and it hurts me
            > > > for the fact that you have to create an empty array or hash such that
            > > > these variable types are established correctly. But when it comes to a
            > > > Funcref type, it is lousy that you have to initialize the variable with
            > > > the Funcref of some random function so that the type of variable gets
            > > > established as Funcref.
            > >
            > >
            > > I'm not sure I see the problem in practice. The only time you'd have
            > > to pre-define a funcref variable would be if you intended to try to
            > > use it when it was empty. Are you really doing this?
            >
            > No, that is not what I was saying. If there is a way to declare
            > variables without initializing them, I would have said something like:
            >
            > Funcref var
            >
            > However, the equivalent of the above is to say:
            >
            > let var = function('somefunc')
            >
            > The alternative is of course to just initialize the variable as and when
            > it is required, but I generally don't like this approach, as it is not
            > clear which variables are being used.
            >

            I want to have it auto-initialize whether in a "let" statement, or an
            implicit setting via a function call argument. And I'd like to be
            able to test a value that hasn't been explicitly initialized, i.e.

            if var1[1].elem1 > 0
            ...

            where nothing about "var1" has been defined, but is used such that
            automatic NULL elements would have to be created manually in any case.
            If I really want it to fail if [1] or .elem1 are not
            defined, I can use 'exists()' or 'has()'. As I said elsewhere, it
            should be an option, for backward compatibility.
          • Yakov Lerner
            ... I agree, Hari. I d expect funcref function( s:T ) to be callable outside of the script, too. Yakov
            Message 5 of 12 , Jul 3 8:02 AM
            • 0 Attachment
              On 6/30/06, Hari Krishna Dara <hari_vim@...> wrote:
              > ... The Funcref obtained via function('s:T') can't be
              > called from outside the script ... [unexpectedly]

              I agree, Hari. I'd expect funcref function('s:T') to be callable
              outside of the script, too.

              Yakov
            • Yakov Lerner
              ... To make myself more clear. I expect g:Xxx() to be callable from global scope of from another script in this example: --- scritp x.vim function! s:XXX()
              Message 6 of 12 , Jul 3 8:07 AM
              • 0 Attachment
                On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                > On 6/30/06, Hari Krishna Dara <hari_vim@...> wrote:
                > > ... The Funcref obtained via function('s:T') can't be
                > > called from outside the script ... [unexpectedly]
                >
                > I agree, Hari. I'd expect funcref function('s:T') to be callable
                > outside of the script, too.

                To make myself more clear. I expect g:Xxx() to be callable
                from global scope of from another script in this example:

                " --- scritp x.vim
                function! s:XXX()
                echo "func XXX"
                endfunction

                let g:Xxx=function('s:XXX')

                Yakov
              • Eric Arnold
                ... The problem with this is that you can no longer have private object function refs. I d be interested to hear from Bram about what the intent was here. I
                Message 7 of 12 , Jul 3 9:03 AM
                • 0 Attachment
                  On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                  > On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                  > > On 6/30/06, Hari Krishna Dara <hari_vim@...> wrote:
                  > > > ... The Funcref obtained via function('s:T') can't be
                  > > > called from outside the script ... [unexpectedly]
                  > >
                  > > I agree, Hari. I'd expect funcref function('s:T') to be callable
                  > > outside of the script, too.
                  >
                  > To make myself more clear. I expect g:Xxx() to be callable
                  > from global scope of from another script in this example:
                  >
                  > " --- scritp x.vim
                  > function! s:XXX()
                  > echo "func XXX"
                  > endfunction
                  >
                  > let g:Xxx=function('s:XXX')
                  >
                  > Yakov
                  >


                  The problem with this is that you can no longer have private object
                  function refs.

                  I'd be interested to hear from Bram about what the intent was here.

                  I think I can see some method in the maddness.

                  1) let ref = function('s:XXX')

                  This mains the standard scope rules for the func ref, and so it
                  stays local even if the variable holding it is global. I can image
                  situations where this could be useful.

                  2) let ref = function('<SNR>66_XXX')

                  This forces the function to be available globally because it is
                  explicitely defined, and there is little chance of mistakes about
                  that.

                  3) function obj.funcref() dict

                  Again, I think the intent for having the object function in the global
                  scope is unknown (to me at least). I think it left global because you
                  don't really need specific scoping for it, as when it is used, it
                  *should* be used via the object name, which is scoped by the user.

                  function s:obj.funcref() dict

                  Hari, can you give an example of why function('s:T') should be
                  globally scoped? I can't see a need for it, given all the
                  possibilites for obtaining a ref.
                • Yakov Lerner
                  ... Of course you can .: let s:Xxx=function( s:XXX ) script-private funcref let l:Xxx=function( s:XXX ) function-private funcref let
                  Message 8 of 12 , Jul 3 9:14 AM
                  • 0 Attachment
                    On 7/3/06, Eric Arnold <eric.p.arnold@...> wrote:
                    > On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                    > > On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                    > > > On 6/30/06, Hari Krishna Dara <hari_vim@...> wrote:
                    > > > > ... The Funcref obtained via function('s:T') can't be
                    > > > > called from outside the script ... [unexpectedly]
                    > > >
                    > > > I agree, Hari. I'd expect funcref function('s:T') to be callable
                    > > > outside of the script, too.
                    > >
                    > > To make myself more clear. I expect g:Xxx() to be callable
                    > > from global scope of from another script in this example:
                    > >
                    > > " --- scritp x.vim
                    > > function! s:XXX()
                    > > echo "func XXX"
                    > > endfunction
                    > >
                    > > let g:Xxx=function('s:XXX')
                    > >
                    > > Yakov
                    > >
                    >
                    >
                    > The problem with this is that you can no longer have private object
                    > function refs.

                    Of course you can .:

                    let s:Xxx=function('s:XXX') " script-private funcref

                    let l:Xxx=function('s:XXX') " function-private funcref

                    let g:Xxx=function('s:XXX') " globally-accessible funcref

                    Yakov
                  • Eric Arnold
                    ... No. These are variables where you have managed their scopes, but the underlying func ref *contained* would lose it s ability to maintain it s scope, i.e.
                    Message 9 of 12 , Jul 3 10:50 AM
                    • 0 Attachment
                      On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                      > On 7/3/06, Eric Arnold <eric.p.arnold@...> wrote:
                      > > On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                      > > > On 7/3/06, Yakov Lerner <iler.ml@...> wrote:
                      > > > > On 6/30/06, Hari Krishna Dara <hari_vim@...> wrote:
                      > > > > > ... The Funcref obtained via function('s:T') can't be
                      > > > > > called from outside the script ... [unexpectedly]
                      > > > >
                      > > > > I agree, Hari. I'd expect funcref function('s:T') to be callable
                      > > > > outside of the script, too.
                      > > >
                      > > > To make myself more clear. I expect g:Xxx() to be callable
                      > > > from global scope of from another script in this example:
                      > > >
                      > > > " --- scritp x.vim
                      > > > function! s:XXX()
                      > > > echo "func XXX"
                      > > > endfunction
                      > > >
                      > > > let g:Xxx=function('s:XXX')
                      > > >
                      > > > Yakov
                      > > >
                      > >
                      > >
                      > > The problem with this is that you can no longer have private object
                      > > function refs.
                      >
                      > Of course you can .:


                      No. These are variables where you have managed their scopes, but the
                      underlying func ref *contained* would lose it's ability to maintain
                      it's scope, i.e. .....


                      > let s:Xxx=function('s:XXX') " script-private funcref


                      You could do

                      let g:Xxx = s:Xxx

                      and now the private/script-local function s:XXX() can be called
                      globally through g:Xxx . I'm not sure whether this would be a
                      good or bad thing. It's sort of an ease-of-use vs strict scoping
                      rules.

                      Also, I think there might be a semantics problem here about the term
                      "function reference". It seems to be concurrently the variable name,
                      which can be called as a function directly, vs the underlying
                      reference itself. I *think* that the func ref var actually does
                      contain a reference, rather than *being* a reference, especially since
                      you can pass it around, and maintain the original function name

                      Anyway, I think there are, or should be two terms to talk about this
                      kind of issue:

                      - function reference

                      - function reference variable



                      > let l:Xxx=function('s:XXX') " function-private funcref
                      >
                      > let g:Xxx=function('s:XXX') " globally-accessible funcref
                      >
                      > Yakov
                      >


                      I'm still not sure that I understand the utility of this. If you want
                      to create a global func ref variable which can call its content, which
                      is a script-local function ref, then why not just make the function
                      global in the first place? Are you worried about a global namespace
                      conflict of the global function [ref] name? I guess the proposed
                      change/request would allow creating an alias in the form of a global
                      func ref var, bypass a global namespace conflict.

                      Detouring away from the namespace question, here are two examples to consider:


                      let s:obj = {}
                      function s:obj.tstfunc() dict
                      return 'here'
                      endfunction
                      echo s:obj.tstfunc()
                      let g:Ref = s:obj
                      " Yank and put this into the command line to test global scope:
                      echo g:Ref.tstfunc()


                      or


                      function! s:tstfunc2()
                      return 'here2'
                      endfunction

                      let s:ref = function( 's:tstfunc2' )
                      echo s:ref()
                      let g:Global_ref = s:ref
                      " Yank and put this into the command line to test global scope, it should fail:
                      echo g:Global_ref()


                      So, my question is: Why should this be allowed? In the above test
                      script, if you made function('s:XXX') global, then it is true in
                      your examples, that you can create local function ref variables which
                      hold that ref. However, in your example,

                      > let g:Xxx=function('s:XXX') " globally-accessible funcref

                      here you have violated the explicit scope set on the function s:XXX
                      . Actually, I personally don't care which happens, since I use
                      scoping in Vim only for namespace separation, not data hiding (where I
                      think the violation might cause some problem that I can't think of
                      :-).

                      Lastly, we've got an inconsistency: dict functions created as
                      numbered function refs which are always global, vs the above which
                      maintains scope.
                    • Hari Krishna Dara
                      On Mon, 3 Jul 2006 at 6:35am, Eric Arnold wrote: [snip] numbered functions. [/snip] ... I think it is best to leave the discussion about numbered functions. It
                      Message 10 of 12 , Jul 3 11:56 AM
                      • 0 Attachment
                        On Mon, 3 Jul 2006 at 6:35am, Eric Arnold wrote:

                        [snip]
                        numbered functions.
                        [/snip]
                        >
                        > I'm still not getting it, I think. Do you have a case where the
                        > numbered function scheme will break down, or is it about the
                        > callbacks, described below?

                        I think it is best to leave the discussion about numbered functions. It
                        hasn't got much value to the current discussion of whether the functions
                        references to the script local functions should be callable outside the
                        script in which the functions are defined.

                        > > >
                        > > >
                        > > > On 6/29/06, Hari Krishna Dara <hari_vim@...> wrote:
                        > > > >
                        > > > > When Funcref's were introduced in Vim7, I expected them to work for
                        > > > > script-local functions, across scripts. The documentation didn't say
                        > > > > that, but it didn't say that it wouldn't either, and I thought that
                        that
                        > > > > is one of its biggest uses (other than the actual intended
                        > > > > functionality, which is for implementing numbered functions). However,
                        I
                        >
                        > I'm not sure that there is a problem. As with C code, if you have
                        > the option of declaring a function global/local, public/private, etc.
                        > I think Vim script is allowing these options.
                        >
                        > Are you saying that you want to override the private script
                        > declarations by declaring a function reference to a low enough level
                        > pointer that it goes under the scope checker?

                        As Yakov Lerner already clarified, this should be allowed by Vim. As we
                        already know, Vim's script-local scoping for functions is not realy
                        intended to prevent external callers. In fact, Vim allows you to use
                        these functions in all your mappings etc., and the calls then originate
                        from outside outside the script context. This is probably why Vim allows
                        a script local function be called in general, using the <SNR> syntax.
                        All that I am saying is that this should be more formalized for
                        Funcrefs (see below).

                        >
                        >
                        > > > > found that the Funcref references for such functions can't actually be
                        > > > > passed out to other scripts. This reduces the usefulness of this
                        feature
                        > > > > as we can't register private functions to receive callbacks from other
                        > > > > scripts.
                        >
                        >
                        > I think this is probably a request that it be more object oriented
                        > than it is, ie. you really want object-scoped functions, not
                        > script-scoped. You seem to want the script localized, so it can't be
                        > access generally, but then be public for registering callbacks. This
                        > seems like an object-scope problem.

                        The script-local functions in Vim is more of a means to distinguish the
                        public API from private. They are not really intended to prevent outside
                        callers. We are not going to build a security system using Vim scripting
                        after all.

                        >
                        > I think that the numbered functions are allowed globally, probably
                        > because they are intended to be used as you describe, for callbacks
                        > from other scripts, since they are only created for the 'dict'
                        > "object" functions, as far as I can tell.
                        >
                        > > > >
                        > > > > What is weird is that the the Funcref() actually behaves exactly like
                        > > > > the function name itself. Say you have a function called s:T() and say
                        > > > > the script id is 60. The Funcref obtained via function('s:T') can't be
                        > > > > called from outside the script, but if the Funcref is obtained using
                        > > > > function('<SNR>60_T'), then it will be fine. Also, a Funcref obtained
                        >
                        >
                        > Both of these examples seem reasonable to me. If you declare a
                        > function reference to a script-local object, s:T then you don't
                        > want it being accessed outside the script. If you declare a
                        > '<SNR>60_T' reference, then you probably wanted to use it outside
                        > the script, otherwise you wouldn't have gone through the trouble of
                        > finding the script id.

                        You can't declare a function using the <SNR> prefix. When you use the s:
                        or <SID> prefix, vim automatically changes it to the <SNR> form using
                        the id of the script. When you want to register a callback, through an
                        autocommand or a map, you don't need to go through the trouble (which
                        actually is not a big trouble) of finding the script id, as Vim takes
                        care of expand <SID> to the right value. This doesn't work the same,
                        when you want to register the same function as a callback with another
                        plugin, so you have to explicitly pass the function name with the <SNR>
                        form (ie., <SNR>60_T not <SID>T). If Funcref's on s:T is same as
                        <SNR>60_T, then this makes it simpler (and more formal) (again, see
                        below).

                        > > > > using these two methods will not be to the same object, though you
                        would
                        > > > > expect them to be. The below echoes 0:
                        >
                        >
                        > How did you test what the object was? Actually, I wouldn't expect it
                        > to be the same object in any case, since each reference to it should
                        > crease a new instance. They both might refer to the same function
                        > definition stored internally, but I don't know.

                        As my code sample below shows, the "is" operator on two separate
                        references of "s:T" gives you "true", but if one reference is to the
                        <SNR> form, you get "false". This is counter-intuitive, as you
                        referencing the same exact function.

                        >
                        > Also, we aren't talking about true "objects", just to be clear, but an
                        > enhancment that allows object-oriented-like functional access. This
                        > limits the expectations we can have.

                        This limitation is not applicable to my argument.

                        [snip]

                        > >
                        > > No, that is not what I was saying. If there is a way to declare
                        > > variables without initializing them, I would have said something like:
                        > >
                        > > Funcref var
                        > >
                        > > However, the equivalent of the above is to say:
                        > >
                        > > let var = function('somefunc')
                        > >
                        > > The alternative is of course to just initialize the variable as and when
                        > > it is required, but I generally don't like this approach, as it is not
                        > > clear which variables are being used.
                        > >
                        >
                        > I want to have it auto-initialize whether in a "let" statement, or an
                        > implicit setting via a function call argument. And I'd like to be
                        > able to test a value that hasn't been explicitly initialized, i.e.
                        >
                        > if var1[1].elem1 > 0
                        > ...
                        >
                        > where nothing about "var1" has been defined, but is used such that
                        > automatic NULL elements would have to be created manually in any case.
                        > If I really want it to fail if [1] or .elem1 are not
                        > defined, I can use 'exists()' or 'has()'. As I said elsewhere, it
                        > should be an option, for backward compatibility.

                        I am not talking about "initialization" here, just declaration.

                        --
                        Thanks,
                        Hari

                        __________________________________________________
                        Do You Yahoo!?
                        Tired of spam? Yahoo! Mail has the best spam protection around
                        http://mail.yahoo.com
                      • Bram Moolenaar
                        ... The whole purpose of script-local functions is that they will only be used locally in the script. Thus they can t be called from outside the script
                        Message 11 of 12 , Jul 8 6:10 AM
                        • 0 Attachment
                          Hari Krishna Dara wrote:

                          > When Funcref's were introduced in Vim7, I expected them to work for
                          > script-local functions, across scripts. The documentation didn't say
                          > that, but it didn't say that it wouldn't either, and I thought that that
                          > is one of its biggest uses (other than the actual intended
                          > functionality, which is for implementing numbered functions). However, I
                          > found that the Funcref references for such functions can't actually be
                          > passed out to other scripts. This reduces the usefulness of this feature
                          > as we can't register private functions to receive callbacks from other
                          > scripts.

                          The whole purpose of script-local functions is that they will only be
                          used locally in the script. Thus they can't be called from outside the
                          script (without the trick to obtain the script nr). Also not when using
                          a Funcref.

                          > What is weird is that the the Funcref() actually behaves exactly like
                          > the function name itself.

                          Yes, that basically sums it up.

                          > There are other aspects of the new features that are very
                          > counter-intuitive to me, whether I think in terms of Python or generic
                          > "objects" in any language. The one which gets me the most is the
                          > implicit typing of variables based on the initializer. For basic types
                          > prior to Vim7 (integer and string), you could easily switch the value of
                          > the variable from integer to string or vice versa, and the type() of the
                          > variable would change, suggesting that it behaves like "duck typing" (as
                          > per (wikipedia). But this observation can't be extended to the newer
                          > object types, as the below will fail:
                          >
                          > let a = {}
                          > let a = []
                          >
                          > If the type of value determines the type of the variable, and if we are
                          > merely dealing with references (assigning references instead of copying
                          > objects), then why should the second statement above generate the below
                          > error?
                          >
                          > E706: Variable type mismatch for: a
                          >
                          > Is there a standard for this type of language behavior? I didn't find
                          > anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed

                          I don't know if there is a standard and generally I don't care. There
                          is nothing against inventing something new. The main point is that it's
                          very easy to make mistakes with using the wrong type for a variable.
                          Using declarations is the normal way to have the compiler or interpreter
                          check the type. But declarations are annoying and certainly don't fit
                          with Vim 6.x script. Therefore I used the "sticky types" mechanism: the
                          first time a variable is assigned a value that's the type it has. Very
                          simple and efficient. You just need to remember that variables are not
                          dynamically typed. Except for int/string, for backwards compatibility.

                          --
                          Back off man, I'm a scientist.
                          -- Peter, Ghostbusters

                          /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
                          /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
                          \\\ download, build and distribute -- http://www.A-A-P.org ///
                          \\\ help me help AIDS victims -- http://ICCF-Holland.org ///
                        • Hari Krishna Dara
                          ... I often provide public functions that are useful for other plugins to interface, so I don t like mixing them up with the functions that are not really
                          Message 12 of 12 , Jul 8 2:45 PM
                          • 0 Attachment
                            On Sat, 8 Jul 2006 at 3:10pm, Bram Moolenaar wrote:

                            >
                            > Hari Krishna Dara wrote:
                            >
                            > > When Funcref's were introduced in Vim7, I expected them to work for
                            > > script-local functions, across scripts. The documentation didn't say
                            > > that, but it didn't say that it wouldn't either, and I thought that that
                            > > is one of its biggest uses (other than the actual intended
                            > > functionality, which is for implementing numbered functions). However, I
                            > > found that the Funcref references for such functions can't actually be
                            > > passed out to other scripts. This reduces the usefulness of this feature
                            > > as we can't register private functions to receive callbacks from other
                            > > scripts.
                            >
                            > The whole purpose of script-local functions is that they will only be
                            > used locally in the script. Thus they can't be called from outside the
                            > script (without the trick to obtain the script nr). Also not when using
                            > a Funcref.

                            I often provide public functions that are useful for other plugins to
                            interface, so I don't like mixing them up with the functions that are
                            not really meant for getting called directly. Can the support for
                            calling the script local functions from outside using SNR form be ever
                            dropped? If not, I don't mind using this form to keep my plugin
                            interface clean, as a workaround (I actually use this trick all the
                            time, but always wondered if this is a feature or a bug, and in case it
                            is a bug, if it ever will be fixed).

                            --
                            Thanks,
                            Hari

                            >
                            > > What is weird is that the the Funcref() actually behaves exactly like
                            > > the function name itself.
                            >
                            > Yes, that basically sums it up.
                            >
                            > > There are other aspects of the new features that are very
                            > > counter-intuitive to me, whether I think in terms of Python or generic
                            > > "objects" in any language. The one which gets me the most is the
                            > > implicit typing of variables based on the initializer. For basic types
                            > > prior to Vim7 (integer and string), you could easily switch the value of
                            > > the variable from integer to string or vice versa, and the type() of the
                            > > variable would change, suggesting that it behaves like "duck typing" (as
                            > > per (wikipedia). But this observation can't be extended to the newer
                            > > object types, as the below will fail:
                            > >
                            > > let a = {}
                            > > let a = []
                            > >
                            > > If the type of value determines the type of the variable, and if we are
                            > > merely dealing with references (assigning references instead of copying
                            > > objects), then why should the second statement above generate the below
                            > > error?
                            > >
                            > > E706: Variable type mismatch for: a
                            > >
                            > > Is there a standard for this type of language behavior? I didn't find
                            > > anything at this page: http://en.wikipedia.org/wiki/Dynamically_typed
                            >
                            > I don't know if there is a standard and generally I don't care. There
                            > is nothing against inventing something new. The main point is that it's
                            > very easy to make mistakes with using the wrong type for a variable.
                            > Using declarations is the normal way to have the compiler or interpreter
                            > check the type. But declarations are annoying and certainly don't fit
                            > with Vim 6.x script. Therefore I used the "sticky types" mechanism: the
                            > first time a variable is assigned a value that's the type it has. Very
                            > simple and efficient. You just need to remember that variables are not
                            > dynamically typed. Except for int/string, for backwards compatibility.
                            >
                            >

                            __________________________________________________
                            Do You Yahoo!?
                            Tired of spam? Yahoo! Mail has the best spam protection around
                            http://mail.yahoo.com
                          Your message has been successfully submitted and would be delivered to recipients shortly.