When pass a variable to a function, why the function only gets a duplicate of the variable?
The are basically two schools of thought on this matter.
The first is pass-by-value where a copy of the value is created for the called function.
The second is pass-by-reference where the parameter that appears in the called function is an "alias" of the original. That means changes you make to it are reflected in the original.
C is generally a pass-by-value language. You can emulate pass-by-reference by passing the address of a variable and then using that to modify the original:
void setTo42 (int *x) { *x = 42; }
:
int y;
setTo42 (&y);
// y is now 42
but that's more passing the pointer to a variable by value, than passing the variable itself by reference.
C++ has true reference types, possibly because so many people have trouble with C pointers :-) They're done as follows:
void setTo42 (int &x) { x = 42; }
:
int y;
setTo42 (y);
// y is now 42
Pass-by-value is usually preferable since it limits the effects that a function can have on the "outside world" - encapsulation, modularity and localisation of effect is usually a good thing.
Being able to arbitrarily modify any parameters passed in would be nearly as bad as global variables in terms on modularity and code management.
However, sometimes you need pass-by-reference since it might make sense to change one of the variables passed in.
R: preventing copies when passing a variable into a function
pryr::address
passes an unevaluated symbol to an internal function that returns its address in the parent.frame()
:
pryr::address
#function (x)
#{
# address2(check_name(substitute(x)), parent.frame())
#}
#<environment: namespace:pryr>
Wrapping of the above function can lead to returning address of a "promise". To illustrate we can simulate pryr::address
's functionality as:
ff = inline::cfunction(sig = c(x = "symbol", env = "environment"), body = '
SEXP xx = findVar(x, env);
Rprintf("%s at %p\\n", type2char(TYPEOF(xx)), xx);
if(TYPEOF(xx) == PROMSXP) {
SEXP pr = eval(PRCODE(xx), PRENV(xx));
Rprintf("\tvalue: %s at %p\\n", type2char(TYPEOF(pr)), pr);
}
return(R_NilValue);
')
wrap1 = function(x) ff(substitute(x), parent.frame())
where wrap1
is an equivalent of pryr::address
.
Now:
x = 1:5
.Internal(inspect(x))
#@256ba60 13 INTSXP g0c3 [NAM(1)] (len=5, tl=0) 1,2,3,4,5
pryr::address(x)
#[1] "0x256ba60"
wrap1(x)
#integer at 0x0256ba60
#NULL
with further wrapping, we can see that a "promise" object is being constructed while the value is not copied:
wrap2 = function(x) wrap1(x)
wrap2(x)
#promise at 0x0793f1d4
# value: integer at 0x0256ba60
#NULL
wrap2(x)
#promise at 0x0793edc8
# value: integer at 0x0256ba60
#NULL
# wrap 'pryr::address' like your 'bar'
( function(x) pryr::address(x) )(x)
#[1] "0x7978a64"
( function(x) pryr::address(x) )(x)
#[1] "0x79797b8"
Python: Keep changes on a variable made within a function
This is an example of passing variables to functions by value. By default, when you pass a variable to a function in Python, it is passed by value.
What it means is, that a new variable with a new scope is created with the same value of x
. So, any change that happens to the new x
is not reflected to the x
outside the function's scope.
If you want to get the value from the function back, you can use the return statement (as you have used). return
returns the value back from the function. However, in your example there is no variable to receive it. Hence, it is lost.
You would have to call the function as x = test(x)
. This ensures that x
receives the value back from the function.
avoid creating duplicate variable names in function
Thanks to @G. Grothendieck and @Limey, the following simplification works (pred_fun_final
) although I do get a warning
message.
#original function in OP
pred_fun_original <- function(time_to_sur, model) {
pred_data <- ds[, c("x1", "x2", "x3")] %>%
mutate(ftime = time_to_sur,
fstatus = 1) %>%
as.data.frame()
ds$pred_var_tmp <-
rms::survest(model, times = time_to_sur,
newdata = pred_data,
se.fit = FALSE, what = "survival")$surv
#rename variable
pred_var <- paste0("pred_prob_", as.character(time_to_sur), "_rms")
names(ds)[names(ds) == "pred_var_tmp"] <- pred_var
assign("ds", ds, env = .GlobalEnv)
}
pred_fun_original(time_to_sur = 0.2, fit)
#save created variable
test1 <- ds$pred_prob_0.2_rms
#remove pred_prob_0.2_rms
ds <- ds %>%
select(-pred_prob_0.2_rms)
New function with warning
:
#fixed function
pred_fun_final <- function(data, time_to_sur, model) {
newName <- paste0("pred_prob_", as.character(time_to_sur), "_rms")
pred_data <- data[, c("x1", "x2", "x3")] %>%
mutate(ftime = time_to_sur,
fstatus = 1) %>%
as.data.frame()
data <- data %>%
mutate({{newName}} := rms::survest(model, times = time_to_sur,
newdata = pred_data,
se.fit = FALSE, what = "survival")$surv)
data
}
ds <- pred_fun_final(ds, time_to_sur = 0.2, fit)
# Warning message:
# Problem with `mutate()` column `pred_prob_0.2_rms`.
# i `pred_prob_0.2_rms = ...$NULL`.
#save variable
test2 <- ds$pred_prob_0.2_rms
The two variables are not identical but that is because one is named and the other is not (as.numeric()
would fix this). It doesn't explain the warning
message though.
identical(test1, test2)
#FALSE
str(test1)
# num [1:200] 0.906 0.9 0.884 0.884 0.886 ...
str(test2)
# Named num [1:200] 0.906 0.9 0.884 0.884 0.886 ...
# - attr(*, "names")= chr [1:200] "1" "2" "3" "4" ...
Unable to retrieve variable assigned in function
You must print answer:
- inside of ask function,
or - return answer, catch it and then print it
answer = " " # set empty in the start
def ask(question):
answer = input(question)
return answer
answer = ask("how are you ")
print(answer)
or one line:
print(ask("how are you "))
Array changes it's values inside a function but other variable don't
This function declaration
void func(int arr[5], int n1, int n2);
is adjusted by the compiler to the declaration
void func(int *arr, int n1, int n2);
That is parameters having array types are adjusted by the compiler to pointers to array element types.
On the other hand, this call
func(arr,a,b);
is equivalent to the call
func( &arr[0], a, b );
That is the array designator arr
used as the function argument is implicitly converted to a pointer to its first element.
So in fact elements of the array are passed to the function through a pointer to them because using the pointer arithmetic and dereferencing pointer expressions the function has a direct access to elements of the array. For example these expressions
arr[0]++, arr[3]++;
by the definition are equivalent to
( *( arr + 0 ) )++, ( *( arr + 3 ) )++;
As for the variables a
and b
then the function deals with copies of the values of these variables. If you want to get the same effect as with elements of the array you should define the function like
void func(int arr[5], int *n1, int *n2)
{
cout << "INSIDE func()" << endl;
arr[0]++, arr[3]++;
for(int i = 0; i < 5; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
( *n1 )++, ( *n2 )++;
cout << *n1 << ' ' << *n2 << endl;
}
and call it like
func( arr, &a, &b );
Java, passing variables/objects into a function
Both - you get a copy of the object reference (for objects), and a copy of the value for primitives.
So unlike C, you can't pass in a variable reference (for a string for example) and end up with it being repointed to something else. And you can't pass in an int, for example, and change it's value within the method - any changes it to it will only be within the method scope.
e.g:
MyObjectHolder holder = new MyObjectHolder();
holder.setObject(new Object());
//holder reference id = 1
// holder.object reference id = 2
doIt(holder);
public void doIt(MyObjectHolder methodScopeHolder) {
// methodScpeHolder reference id = 3
// methodScopeHolder.object reference id = 2
}
Related Topics
Does Std::Cout Have a Return Value
Error: Cannot Convert 'Const Wchar_T [13]' to 'Lpcstr {Aka Const Char*}' in Assignment
How to Implement a Map with Different Data Types as Values
Should Std::Common_Type Use Std::Decay
What's the Difference Between Type(Myvar) and (Type)Myvar
How to Speed Up This Histogram of Lut Lookups
Covariant Return Type and Type Conversion
How to Omit the Double-Braces for Std::Array in C++14
Enumdisplaydevices VS Wmi Win32_Desktopmonitor, How to Detect Active Monitors
How to Use Unordered_Set with Custom Types
Can Different Gcc Dialects Be Linked Together
How to Find the Size of All Files Located Inside a Folder
Ifstream Not Reading Eof Character
Different Compiler Behavior for Expression: Auto P {Make_Pointer()};