Ask Your Question

How to write a function with arbitrary number of arguments?

asked 2018-09-24 21:45:15 +0200

endolith gravatar image

updated 2018-09-24 21:46:05 +0200

For example, in Python, I can write:

def par(x, y):
    return x * y / (x + y)

and this will find equivalent resistance of two resistors in parallel. I can then extend it to arbitrary number of resistors like so:

def par(*resistors):
    def par(x, y):
        return x * y / (x + y)

return reduce(par, resistors)

So now par(a, b, c) actually calls par(par(a, b), c) (or par(a, par(b, c)), doesn't matter).

In Star Basic, I can write this as:

Function Par(R1, R2)
    Par = R1*R2 / (R1+R2)
End Function

How would I extend this to arbitrary number of arguments, in the same way that =SUM(A1, A2:B4, C5) can accept them?

edit retag flag offensive close merge delete



What about Optional and IsMissing()?

JohnSUN gravatar imageJohnSUN ( 2018-09-24 22:24:37 +0200 )edit

What do you want to calculate by this function? You can use an array as argument, where you need not know its size beforehand.

Regina gravatar imageRegina ( 2018-09-24 23:35:48 +0200 )edit

@Regina There are multiple functions that I would like to calculate. Multiple resistors in parallel, multiple incoherent noise sources root-sum-squared together, etc.

endolith gravatar imageendolith ( 2018-10-03 18:08:27 +0200 )edit

2 Answers

Sort by » oldest newest most voted

answered 2018-10-05 22:03:10 +0200

Using ParamArray compatibility option (requires option compatible) with a single function's parameter, you pack all parameters passed to the function into a single array.

option compatible

function vararg(paramarray p)
  t = ""
  for i = LBound(p) to UBound(p)
    x = p(i)
    t = t & Format(x, "0")
  next i
  vararg = t
end function

sub test
  print vararg(1)
  print vararg(1,2,3)
  print vararg(1,3,5,6,7,8)
  print vararg(1,1,2,3,4,5,6,7,8,9,0,2,1,3,4,5,6,7,6,3,1,1,2,3,4,2,3,3,4,2,3)
end sub
edit flag offensive delete link more



Thanks! I didn't know that. I once was told OpenOffice didn't support the construct, and never tried it under Option Compatible. Just tested it with AOO 4.1.5 and it worked also there. Is it "common heritage" or was it implemented twice independently?

What are the main disadvantages of Option Compatible?
Option Compatible seems to be included with Option VBAsupport 1. Is this true, and what are the main disadvantages of VBAsupport 1?

Lupp gravatar imageLupp ( 2018-10-06 00:23:24 +0200 )edit

Well - that is common heritage (just tested with OOo330m20 (Build:9567)).

I am not really familiar with Basic code in LO, so I cannot tell for sure, but from what I happened to come across, there shouldn't be much disadvantages from using both of the options (I only saw that they add some function lists and keywords). Of course, using some functions or syntax that is enabled by these might have huge penalty (at least, in terms of performance) - but that's another story. ParamArray should be OK.

Mike Kaganski gravatar imageMike Kaganski ( 2018-10-06 00:33:03 +0200 )edit

Option Compatible seems to be included with Option VBAsupport 1. Is this true

Yes, just checked that. When Option VBASupport is encountered, both flags are set (see SbModule::SetSource32 in basic/source/classes/sbxmod.cxx; look for VBASUPPORT).

Mike Kaganski gravatar imageMike Kaganski ( 2018-10-06 00:54:45 +0200 )edit

Thanks again! And apologies for hijacking the thread.

Lupp gravatar imageLupp ( 2018-10-06 01:31:08 +0200 )edit

It doesn't really matter for my application, but if I try to pass a range instead of several things separated by commas, I get "Object variable not set." error

endolith gravatar imageendolith ( 2018-10-08 03:54:29 +0200 )edit

"It" seems to be the paramarray under Option Compatible?
What I suggested also has the issue that the array of parameters is corretly created by the dedicated function.but then not is correctly passed to a second function trying to evaluate it. I suppose this to be caused by the fact that the second step again is organised by the evaluator of Calc which only can pass correctly shaped arrays.
Concerning a possible workaround see the new amendment to my answer.

Lupp gravatar imageLupp ( 2018-10-08 12:03:13 +0200 )edit

answered 2018-09-25 00:33:39 +0200

Lupp gravatar image

updated 2018-10-08 12:17:40 +0200

===Amendment 2018-10-08 12:06 CEST ===
(See the comment by the OQ to the answer by @Mike Kaganski and my answer to this comment.)
This very roughly sketeched demo shows a possible workaround based on global parameters.  To make it reliably usable "in production" would require a lot of programming developing a complete system for the management of global parameter(s) used for the purpose.
===End Amendment===

In completion of what @Regina wrote: Values from cell ranges and results of array expressions in Calc are always passed as 2D-arrays. You may try this code:

Function parRes(p)
REM p must be an array as it is passed to the function for a range of cells
REM or as the result uf a respective array expression. 

REM For rare cases where this may occur, also a single value is accepted:
If Not IsArray(p) Then 
  Dim h(1 To 1, 1 To 1)
  h(1, 1) = p :  p = h
End If

REM Now the relevant part calculating the conductivity first.
l1 = Lbound(p, 1) : u1 = Ubound(p, 1)
l2 = Lbound(p, 2) : u2 = Ubound(p, 2)
Dim s As Double
s = 0
For j = l1 To u1
  For k = l2 To u2
    s = s+  IIf((TypeName(p(j, k))<>"Empty") AND (TypeName(p(j, k))<>"String"),1/p(j,k), 0)
  Next k
Next j
parRes = 1/s
End Function

It's clearly longer than what the OP posted, but it avoids inefficient recursion. Basic does not allowing for a parameter list of arbitrary length. You can circumvent this to a certain degree with a helper function collecting non-missing optional parameters in an array. It needs a few lines of code per each new introduced parameter position.

===Amendment regarding the comments===
StarBasic comes with a few "commands" and functions allowing for an arbitrary number of parameters.
The one relevant here is the Array() Function. Resricting the aim to a limited but sufficiently high number of allowed parameters you can use it as is demonstrated in the code below. I can think of many variants, enhancements, and specialised modifications.
However, if a function should be useful as a (sub-)expression in Calc formulae there is a serious issue I judge to be a bug: tdf#102381. It prohibits the omission of parameters by leaving unused places. See the demo ask166628variadicRoutines.ods. (To avoid a misunderstanding: The function is not supposed to be used for direct output mainly.) Below the crude code for up to 30 arguments. Use the "(more)" hyperlink to see it completely.

Function prepareArguments( _
           Optional p00, Optional p01, Optional p02, Optional p03, Optional p04, _
           Optional p05, Optional p06, Optional p07, Optional p08, Optional p09, _
           Optional p10, Optional p11, Optional p12, Optional p13, Optional p14, _
           Optional p15, Optional p16, Optional p17, Optional p18, Optional p19, _
           Optional p20, Optional p21, Optional p22, Optional p23, Optional p24, _
           Optional p25, Optional p26, Optional p27, Optional p28, Optional p29)
helper = Array(p00,p01,p02,p03,p04,p05,p06 ...
edit flag offensive delete link more


Well I want to use it for other functions, too, so recursive function calls would be a better solution, as I showed in my question

endolith gravatar imageendolith ( 2018-10-01 16:25:16 +0200 )edit

That's coherent, and I actually mused about the topic now and then. It might be an appropriate challenge in higher education concerning programming. I'm neither a professor nor a student and I only know programming languages to a certain level that do NOT support so called variadic user functions though they come with prefab constructs allowing for arbitrary numbers of parameters or something alike. .
And I can imagine relevant reasons for the fact.
See the amendments by editing to my answer

Lupp gravatar imageLupp ( 2018-10-01 18:57:53 +0200 )edit
Login/Signup to Answer

Question Tools

1 follower


Asked: 2018-09-24 21:45:15 +0200

Seen: 580 times

Last updated: Oct 08 '18