Re: Calling through a function reference with a variable argument list
On 6/12/06, Hari Krishna Dara [EMAIL PROTECTED] wrote: On Mon, 12 Jun 2006 at 4:07pm, Charles E Campbell Jr wrote: Bob Hiestand wrote: On 6/2/06, Charles E Campbell Jr [EMAIL PROTECTED] wrote: Bob Hiestand wrote: My question is whether there is a simpler way to pass an unknown number of arguments from the current function to a function which accepts a variable-length list of arguments. ...snip... I don't think that does what I wanted, though I may have misunderstood the implications. That converts the arguments into a string representation of a list, which then becomes the single argument to the second function. Looks like I made a mistake. Here's one that does illustrate passing a variable number of arguments along: -- fun! AFunc(...) let args = string(a:000) let len = strlen(args) let args = strpart(args,1,len-2) echomsg call BFunc(.args.) a:0=.a:0 exe call BFunc(.args.) endfun -- fun! BFunc(...) echomsg BFunc sees: a:0=.a:0 echomsg a:000.string(a:000). endfun -- echomsg 'AFunc(1):' call AFunc(1) echomsg 'AFunc(1,a):' call AFunc(1,a) echomsg 'AFunc(1,a,b):' let b=BBB call AFunc(1,a,b) The idea is to have a string hold just the arguments, not the list delimiters. The exe squeezes the string together and then executes it. Consequently, the output is: AFunc(1): call BFunc(1) a:0=1 BFunc sees: a:0=1 a:000[1] AFunc(1,a): call BFunc(1, 'a') a:0=2 BFunc sees: a:0=2 a:000[1, 'a'] AFunc(1,a,b): call BFunc(1, 'a', 'BBB') a:0=3 BFunc sees: a:0=3 a:000[1, 'a', 'BBB'] P So you can see that BFunc is being called with a variable number of arguments depending on whatever AFunc received (look at the BFunc sees: lines) I don't know if the OP can use a Vim7.0 only solution, but the genutils plugin has a utility to make this possible for prior versions. I have been using this in several places of one of my plugins with no issues. However, if Vim7.0 only solution is acceptable, Vim supports this already with the call() function. -- fun! AFunc(...) echomsg call BFunc(.string(a:000).) a:0=.a:0 call call('BFunc', a:000) endfun -- fun! BFunc(...) echomsg BFunc sees: a:0=.a:0 echomsg a:000.string(a:000). endfun -- HTH, Hari My intention was to create a passthrough function that could call any other function after determining the function to which it would dispatch control (the application here is a general source integration script that would dispatch to the appropriate function specific to the version control system controlling the current file). As it turns out, I was a victim of narrow thinking because I was trying to modify as little as possible of an existing plugin. The correct change was to simply make the dispatch function and the end functions accept a list as the parameter, in which case pass-through becomes trivial. Thank you for looking at this, You're welcome! Chip Campbell Thanks, Hari, that was exactly the functionality I wanted.
Re: Calling through a function reference with a variable argument list
On Mon, 12 Jun 2006 at 4:07pm, Charles E Campbell Jr wrote: Bob Hiestand wrote: On 6/2/06, Charles E Campbell Jr [EMAIL PROTECTED] wrote: Bob Hiestand wrote: My question is whether there is a simpler way to pass an unknown number of arguments from the current function to a function which accepts a variable-length list of arguments. ...snip... I don't think that does what I wanted, though I may have misunderstood the implications. That converts the arguments into a string representation of a list, which then becomes the single argument to the second function. Looks like I made a mistake. Here's one that does illustrate passing a variable number of arguments along: -- fun! AFunc(...) let args = string(a:000) let len = strlen(args) let args = strpart(args,1,len-2) echomsg call BFunc(.args.) a:0=.a:0 exe call BFunc(.args.) endfun -- fun! BFunc(...) echomsg BFunc sees: a:0=.a:0 echomsg a:000.string(a:000). endfun -- echomsg 'AFunc(1):' call AFunc(1) echomsg 'AFunc(1,a):' call AFunc(1,a) echomsg 'AFunc(1,a,b):' let b=BBB call AFunc(1,a,b) The idea is to have a string hold just the arguments, not the list delimiters. The exe squeezes the string together and then executes it. Consequently, the output is: AFunc(1): call BFunc(1) a:0=1 BFunc sees: a:0=1 a:000[1] AFunc(1,a): call BFunc(1, 'a') a:0=2 BFunc sees: a:0=2 a:000[1, 'a'] AFunc(1,a,b): call BFunc(1, 'a', 'BBB') a:0=3 BFunc sees: a:0=3 a:000[1, 'a', 'BBB'] P So you can see that BFunc is being called with a variable number of arguments depending on whatever AFunc received (look at the BFunc sees: lines) I don't know if the OP can use a Vim7.0 only solution, but the genutils plugin has a utility to make this possible for prior versions. I have been using this in several places of one of my plugins with no issues. However, if Vim7.0 only solution is acceptable, Vim supports this already with the call() function. -- fun! AFunc(...) echomsg call BFunc(.string(a:000).) a:0=.a:0 call call('BFunc', a:000) endfun -- fun! BFunc(...) echomsg BFunc sees: a:0=.a:0 echomsg a:000.string(a:000). endfun -- HTH, Hari My intention was to create a passthrough function that could call any other function after determining the function to which it would dispatch control (the application here is a general source integration script that would dispatch to the appropriate function specific to the version control system controlling the current file). As it turns out, I was a victim of narrow thinking because I was trying to modify as little as possible of an existing plugin. The correct change was to simply make the dispatch function and the end functions accept a list as the parameter, in which case pass-through becomes trivial. Thank you for looking at this, You're welcome! Chip Campbell __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Re: Calling through a function reference with a variable argument list
On 5/16/06, Hari Krishna Dara [EMAIL PROTECTED] wrote: On Tue, 16 May 2006 at 2:43pm, Bob Hiestand wrote: Hi all, I'm re-writing my cvscommand.vim plugin to handle both CVS and Subversion version control systems. I'm currently implementing some of the functionality through function references that define common operations for each source control system in a dictionary specfic to that system. I have a situation where I have a generic dispatch function that identifies which dictionary to dereference to obtain the function reference. The problem is that the function eventually called behind the function reference may have any number of arguments. Therefore, the dispatch function takes any number of arguments to pass through. This leads to the actual call, which looks like this (all on one line): function! s:ExecuteVCSCommand(command, ...) find the proper functionMap dictionary, and then: execute return functionMap[a:command]( . join(map(copy(a:000), '\' . v:val . '\'), ,) . ) My question is whether there is a simpler way to pass an unknown number of arguments from the current function to a function which accepts a variable-length list of arguments. Thank you, Bob My suggestion would be to have the underlying methods always accept a list of arguments, then you can just pass a:000 straight-through. Yes, I've changed the implementation functions in this way per Yakov. Thanks. BTW, your approach to enclose the arguments in double-quotes is a bad-idea, especially if you are handling paths on windows with back-slashes in them (among various others). Imagine what would happen if the argument is c:\dev\tst\newfile, both \t and \n will result in getting expanded to tab and newline. What you should do is to use single-quotes to avoid accidental transformations, but then escape the existing single-quotes themselves (if any). Take a look at the MakeArgumentString() function in my genutils.vim. -- HTH, Hari Yes, I've changed the implementation functions in this way per Yakov. Thanks. With your heads-up about the double quote in mind, I'm glad that I'm not using execute now, as the equivalent expression looks to be: execute 'return functionMap[a:command](' . join(map(copy(b:alist), ' . v:val . ')), ',') . ')' which is fairly difficult for me to read. Thank you, Bob
Calling through a function reference with a variable argument list
Hi all, I'm re-writing my cvscommand.vim plugin to handle both CVS and Subversion version control systems. I'm currently implementing some of the functionality through function references that define common operations for each source control system in a dictionary specfic to that system. I have a situation where I have a generic dispatch function that identifies which dictionary to dereference to obtain the function reference. The problem is that the function eventually called behind the function reference may have any number of arguments. Therefore, the dispatch function takes any number of arguments to pass through. This leads to the actual call, which looks like this (all on one line): function! s:ExecuteVCSCommand(command, ...) find the proper functionMap dictionary, and then: execute return functionMap[a:command]( . join(map(copy(a:000), '\' . v:val . '\'), ,) . ) My question is whether there is a simpler way to pass an unknown number of arguments from the current function to a function which accepts a variable-length list of arguments. Thank you, Bob
Re: Calling through a function reference with a variable argument list
On 5/16/06, Bob Hiestand [EMAIL PROTECTED] wrote: I'm re-writing my cvscommand.vim plugin to handle both CVS and Subversion version control systems. I'm currently implementing some of the functionality through function references that define common operations for each source control system in a dictionary specfic to that system. I have a situation where I have a generic dispatch function that identifies which dictionary to dereference to obtain the function reference. The problem is that the function eventually called behind the function reference may have any number of arguments. Therefore, the dispatch function takes any number of arguments to pass through. This leads to the actual call, which looks like this (all on one line): function! s:ExecuteVCSCommand(command, ...) find the proper functionMap dictionary, and then: execute return functionMap[a:command]( . join(map(copy(a:000), '\' . v:val . '\'), ,) . ) My question is whether there is a simpler way to pass an unknown number of arguments from the current function to a function which accepts a variable-length list of arguments. The only thing I can think of is rewriting target functions into accepting 1 argument which is a list. I don't find vim vararg mechanism easy to use in general. Yakov