How to Extract Parameters from a List and Pass Them to a Function Call

How to extract parameters from a list and pass them to a function call

You can unpack a tuple or a list into positional arguments using a star.

def add(a, b, c):
print(a, b, c)

x = (1, 2, 3)
add(*x)

Similarly, you can use double star to unpack a dict into keyword arguments.

x = { 'a': 3, 'b': 1, 'c': 2 }
add(**x)

Extract the elements of list as individual arguments within custom function in r

Is this what you're looking for? The crux is to wrap formals() in list(), and thus obtain a named list of all ("formal") parameters for testfunc().

My interpretation of your question is that you want to pass a named list as the x parameter to testfunc(), which contains named values to override other parameters passed to testfunc() alongside x. This list might be "incomplete", in that it does not necessarily name every other parameter (like cc and ee). Those that are not overridden are left as they are; unless they possess the default value of NULL, in which case they are converted to 0.

Using the formals() as above, we can define a testfunc()

testfunc <- function(x, aa = NULL, bb = NULL, cc = NULL, dd = NULL, ee = NULL, ff = NULL) {
# Capture what values were passed to what parameters of 'testfunc()'.
params <- as.list(formals())
param_names <- names(params)

# For convenience, record the named variables listed under 'x'.
x_names <- names(x)


# Process each parameter (besides 'x' itself).
for(p_name in param_names[param_names != "x"]) {
# If the parameter is named in 'x', override it with the value from 'x'.
if(p_name %in% x_names) {
assign(p_name, x[[p_name]])
}
# Otherwise, leave the parameter alone...unless it is NULL and should be
# replaced with 0.
else if(is.null(get(p_name))) {
assign(p_name, 0)
}
}


# ...
# Any further operations; where parameters can be referenced like any other parameter
# in any other function, rather than having to be 'unlist'ed from 'x'.
# ...


# Explicitly name the parameters in the output list.
q <- list(
aa = aa,
bb = bb,
cc = cc,
dd = dd,
ee = ee,
ff = ff
)

return(q)
}

such that this call

test <- list(aa = 2, bb = 0.5, dd = 2, ff = 16)

testfunc(test)

yields the following list as output:

$aa
[1] 2

$bb
[1] 0.5

$cc
[1] 0

$dd
[1] 2

$ee
[1] 0

$ff
[1] 16

Note

I have given priority to x. That is, I have assumed you want to keep any NULLs that were explicitly assigned by name in x. So explicitly giving x a NULL element like aa here

test <- list(aa = NULL, bb = 0.5, dd = 2, ff = 16)
testfunc(test)

will yield a NULL for aa in the output:

$aa
NULL

$bb
[1] 0.5

$cc
[1] 0

$dd
[1] 2

$ee
[1] 0

$ff
[1] 16

If you want to override this behavior, and ensure that any NULL is replaced by 0 in the output, then simply change the else if to an if, in line 18 of the function definition:

    # ...
if(is.null(get(p_name))) {
assign(p_name, 0)
}
# ...

Tips

Your original solution failed because you used !is.null() rather than is.null(); so you avoided overriding any NULLs with 0.

If you were expecting unlist(x) to populate the environment of testfunc() with the contents of x, you are sadly mistaken. All unlist() does is "flatten" x into a (homogenized) vector of its atomic components; so we get

x <- list(
a = 1,
list(
b = TRUE,
"hi"
)
)

unlist(x, recursive = TRUE, use.names = TRUE)

#> a b
#> "1" "TRUE" "hi"

homogenized into a (named) character vector. Your code inertly returns this value and moves on.

Only with something like assign("a", 1) (and so forth) could you achieve the effect of actually populating these values as named variables in your environment.

Extracting Arguments from a Function Passed as a Parameter to Another Function in JavaScript

Here is a solution that only requires you to change the code in test (with the exception of your call to test where I've replaced (isNumber, isNumber) with [isNumber, isNumber]).

You don't have to do anything special to get access to add's arguments because you create the function inside test and return it to be called by console.log(add(5, 6));.

Using arguments inside any function will give you the function's arguments as an array.

The ... in func(... arguments); is the spread operate which takes an array and expands it in place. See spread operator.

function test(precondition, postcondition, func)   {
// Extract arguments of func which in this case should be 5 and 6
// This is required to check whether isNumber(5) and isNumber(6)
// both return true, so that precondition is met
return function() {
for (const i in arguments) {
const argi = arguments[i];
const precondition_i = precondition[i];
console.log('precondition['+i+'] met: ' + precondition_i(argi));
}
const r = func(... arguments);
console.log('postcondition met: ' + postcondition(r));
return r;
};
}

var add = test([isNumber, isNumber], isNumber, function add(x, y) {return x+y; });

console.log(add(5, 6));

Or a less generic solution that doesn't use arguments and ... and doesn't pass in an array as precondition:

function test(precondition, postcondition, func)   {
// Extract arguments of func which in this case should be 5 and 6
// This is required to check whether isNumber(5) and isNumber(6)
// both return true, so that precondition is met
return function(x, y) {
console.log('precondition met for x: ' + precondition(x));
console.log('precondition met for y: ' + precondition(y));
const r = func(x, y);
console.log('postcondition met: ' + postcondition(r));
return r;
};
}

var add = test(isNumber, isNumber, function add(x, y) {return x+y; });

console.log(add(5, 6));

Call functions on elements of list

You can use * to unpack the values in your list as parameters of your function:

def f(a, b, c):
print(a,b,c)

x = [4, 6, 10]

f(*x)

Output:

4 6 10

Just be careful that your list has the proper number of parameters.

Extracting a parameter from a function passed as parameter

What you already have is the correct (and only) way to approach this situation in C++Builder's "classic" (pre-C++11) compilers.

In order to support a variable number of parameters, you will have to use multiple overloads, there is no other option (without delving into low-level inline assembly to setup call stacks manually, but even then it may not work correctly across thread boundaries), eg:

void Class1::MainThreadFunction()
{
if (GetCurrentThreadId() != System::MainThreadID)
{
RunInMainThread(MainThreadFunction);
return;
}
//...
}

void Class1::MainThreadFunction(const __int64 param)
{
if(GetCurrentThreadId() != System::MainThreadID)
{
RunInMainThread(MainThreadFunction, param);
return;
}
//...
}

// and so on as needed ...
template<typename FuncType>
void Class2::RunInMainThread(FuncType FuncToCall)
{
struct {
FuncType F;
void __fastcall FTC() { F(); }
} Args = {FuncToCall};

TThread::Synchronize(NULL, &Args.FTC);
}

template<typename FuncType, typename ParamType>
void Class2::RunInMainThread(FuncType FuncToCall, const ParamType param)
{
struct {
const ParamType &P;
FuncType F;
void __fastcall FTC() { F(P); }
} Args = {param, FuncToCall};

TThread::Synchronize(NULL, &Args.FTC);
}

template<typename FuncType, typename ParamType1, typename ParamType2>
void Class2::RunInMainThread(FuncType FuncToCall, const ParamType1 param1, const ParamType2 param2)
{
struct {
const ParamType1 &P1;
const ParamType2 &P2;
FuncType F;
void __fastcall FTC() { F(P1, P2); }
} Args = {param1, param2, FuncToCall};

TThread::Synchronize(NULL, &Args.FTC);
}

// and so on as needed...

If you look through various RTL header files, such as sysvari.h and utilcls.h, using overloads is how Borland itself approaches the issue of variable number of parameters in several of its own APIs, sometimes upwards of 30+ parameters, which is more than enough to handle most user code.

Pass a list to a function to act as multiple arguments

function_that_needs_strings(*my_list) # works!

You can read all about it here: Unpacking Argument Lists - The Python Tutorial

Calling Python function with set of parameters from variable

You can use *args or **kwargs. The names args and kwargs don't actually matter, but its the * and ** that does the trick. Basically, * will unpack a list, and similarly, ** will unpack a dict.

*args is just a list of values in the same order as where you defined your function.

eg.

args = [23, 6, 2, "label", 5, 25, 21, 343.22, 111.34, 2]
write2db(*args)

**kwargs is a key-value mapping (python dict) of argument names to argument values

eg.

kwargs = {
'pocnr': 23,
'larm1': 21,
# ... etc.
}
write2db(**kwargs)

Extract parameter values of a function passed into parameter of function

compile_name <- function(first_name, last_name){
paste(first_name, last_name)
}

convert_call_to_list <- function(x) {
if (is.call(x)) as.list(x) else x
}

create_project <- function(project_name,...) {
first_pass <- as.list(match.call())
second_pass <- lapply(first_pass, convert_call_to_list)
setNames(second_pass, names(first_pass))
}

create_project(project_name = compile_name(first_name = "first", last_name = "last"), more_stuff = "more")
#> [[1]]
#> create_project
#>
#> $project_name
#> $project_name[[1]]
#> compile_name
#>
#> $project_name$first_name
#> [1] "first"
#>
#> $project_name$last_name
#> [1] "last"
#>
#>
#> $more_stuff
#> [1] "more"

Created on 2019-02-27 by the reprex package (v0.2.1)

How to get parameters from data list with 'for' cycle

A list should be created using squared bracket [] instead of curly bracket {} used by set and dictionary.

For your question you should be able to achieve it using the code snippet as follow

for i in list:
function(*i)

The * operator unpacks the tuple in the list and provides it as parameter for the function



Related Topics



Leave a reply



Submit