Call by reference, value, and name - pass-by-reference

I'm trying to understand the conceptual difference between call by reference, value, and name.
So I have the following pseudocode:
foo(a, b, c)
{
b =b++;
a = a++;
c = a + b*10
}
X=1;
Y=2;
Z=3;
foo(X, Y+2, Z);
What's X, Y, and Z after the foo call if a, b, and c are all call by reference?
if a, b, and c are call-by-value/result?
if a, b, and c are call-by-name?
Another scenario:
X=1;
Y=2;
Z=3;
foo(X, Y+2, X);
I'm trying to get a head start on studying for an upcoming final and this seemed like a good review problem to go over. Pass-by-name is definitely the most foreign to me.

When you pass a parameter by value, it just copies the value within the function parameter and whatever is done with that variable within the function doesn't reflect the original variable e.g.
foo(a, b, c)
{
b =b++;
a = a++;
c = a + b*10
}
X=1;
Y=2;
Z=3;
foo(X, Y+2, Z);
//printing will print the unchanged values because variables were sent by value so any //changes made to the variables in foo doesn't affect the original.
print X; //prints 1
print Y; //prints 2
print Z; //prints 3
but when we send the parameters by reference, it copies the address of the variable which means whatever we do with the variables within the function, is actually done at the original memory location e.g.
foo(a, b, c)
{
b =b++;
a = a++;
c = a + b*10
}
X=1;
Y=2;
Z=3;
foo(X, Y+2, Z);
print X; //prints 2
print Y; //prints 5
print Z; //prints 52
for the pass by name;
Pass-by-name

Call by Value : normal way... values of actual parameters are copied to formal parameters.
Call by Reference : instead of the parameters, their addresses are passed and formal parameters are pointing to the actual parameters.
Call by Name : like macros, the whole function definition replaces the function call and formal parameters are just another name for the actual parameters.

By value - there is no changes out the function. all your actions vanish when the function finished.
By reference - your actions indeed changes the variables.
By name - I've never heard ...
Passing x+1 is not change, just tells to the function 3 instead 2 or etc...

This won't change the value of X, Y or Z if it is pass-by-value. When you use a function such as "foo()", it basically copies the variables (x, y and z) into other variables (a, b, and c) and does certain actions with them, without changing the originals (x, y and z). For you to change a value you would have to return a value, something like this:
foo(a, b, c)
{
a = a++;
b = b++;
c = a + b * 10;
return c;
}
x = 1;
y = 2;
z = 3;
z = foo(x, y+2)
Then x and y would be the same, but z would be (x+1)+(y+1)*10 which in this case would be 32.

in javascript :
primitive type variable like string,number are always pass as pass
by value.
Array and Object is passed as pass by reference or pass by value based on these condition.
if you are changing value of that Object or array with new Object or Array then it is pass by Value.
object1 = {item: "car"};
array1=[1,2,3];
here you are assigning new object or array.you are not changing the value of property
of old object.so it is pass by value.
if you are changing a property value of an object or array then it is pass by Reference.
object1.item= "car";
array1[0]=9;
here you are changing a property value of old object.you are not assigning new object or array to old one.so it is pass by reference.
Code
function passVar(object1, object2, number1) {
object1.key1= "laptop";
object2 = {
key2: "computer"
};
number1 = number1 + 1;
}
var object1 = {
key1: "car"
};
var object2 = {
key2: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1.key1);
console.log(object2.key2);
console.log(number1);
Output: -
laptop
bike
10

In Call by value, a copy of the variable is passed whereas in Call by reference, a variable itself is passed. In Call by value, actual and formal arguments will be created in different memory locations whereas in Call by reference, actual and formal arguments will be created in the same memory location.

Related

Hash function for custom type

I'm trying to define a custom equality method for a new type I've constructed. This is a MWE getting at what I'm trying to do.
mutable struct a
first_num::Int
second_num::Int
end
import Base.==
import Base.hash
function hash(obj::a, h=33141651)
return hash((obj.first_num, obj.second_num), h)
end
function ==(obj1::a, obj2::a)
if hash(obj1) == hash(obj2)
return true
else
return false
end
end
a1 = a(2,3)
a2 = a(2,3)
a1 == a2
I then get an error like ERROR: TypeError: ==: in typeassert, expected UInt64, got Int64
Is h becoming Int64?
In addition, if hashing the tuple of attributes is simply not the correct way to do this, let me know.
Edit: Actually, I ran this and I'm getting MethodError: no method matching hash(::Tuple{Int64,Int64}, ::Int64). Is h being promoted to Int64?
The problem is that your literal value for h (33141651) is an Int rather than a UInt. Thus, when you call hash with the tuple h is an Int, but the internal tuple hash function expects a UInt. I don't think you have to specify a value for h at all, and something like this should be enough:
function Base.hash(obj::a, h::UInt)
return hash((obj.first_num, obj.second_num), h)
end
Full example for completeness:
mutable struct A
first::Int
second::Int
end
function Base.hash(obj::A, h::UInt)
return hash((obj.first, obj.second), h)
end
function Base.:(==)(obj1::A, obj2::A)
return hash(obj1) == hash(obj2)
end
With the following behaviour
julia> a = A(2,3); b = A(2,3)
A(2, 3)
julia> hash(a)
0x965b43497b212144
julia> hash(b)
0x965b43497b212144
julia> a == b
true

using a name macro for variables from a functions inputs

If I have 2 variables, a=[.3, .2, .4]; b=[.1, .2, .3]; I can create a string with the name of the variable using a macro:
macro varname(arg)
string(arg)
end
#varname(a)
now say I have a function and I want to pass it an arbitrary number of arguments and use the actual variable names that are being given to function to create dictionary keys:
function test(arguments...)
Dict(Symbol(#varname(i)) => i for i in arguments)
end
this won't work because #varname will take i and create "i", so for example:
out=test(a,b)
the output I would like is:
Dict("a" => [.3, .2, .4], "b" => [.1, .2, .3])
Is there a way to achieve this behavior?
Parameters.jl has such a macro. It works like this:
using Parameters
d = Dict{Symbol,Any}(:a=>5.0,:b=>2,:c=>"Hi!")
#unpack a, c = d
a == 5.0 #true
c == "Hi!" #true
d = Dict{Symbol,Any}()
#pack d = a, c
d # Dict{Symbol,Any}(:a=>5.0,:c=>"Hi!")
If you want to know how it's done, just check its source:
https://github.com/mauro3/Parameters.jl/blob/v0.7.3/src/Parameters.jl#L594

Function with different return variables

Is there a way to have one function that can return two different variables, but only one at a time AND knowing which one is returned in the function call?
example:
I have the following function in which only one of the outputs is valid (the other one would be [])
function [a,b] = AlternatingOutput (input)
if input == 1
return ONLY A
else
return ONLY B
end
end
and i call it in a script
[a,b] = AlternatingOutput (input)
i want a way to say the following (pseudocode):
if (function outputs a)
[a,~] = AlternatingOutput(input)
elseif (function outputs b)
[~,b] = AlternatingOutput(input)
end
the script is run in a loop, and later i need the newest Valid values for a and b, so i cannot overwrite one of the two with []
I do understand that I could just write a function that checks which variable will be output, but I was wondering if there is a more elegant way.
I hope I have made my question clear, and I hope someone can answer me :)
There is no way to tell if an output argument is actually used. You may check the number of output arguments using nargout and it would allow to distinguish between [a] = AlternatingOutput(input) and [~,b] = AlternatingOutput(input)
I don't know the full context of your problem, but maybe you can put all your variables into a struct? Simply pass this struct everytime you call the function and let it decide which variables to manipulate. (This might be slow in some programming languages, but not in matlab).
How about retuning a cell?
function [ ab ] = testfun( input )
if input
ab={'ax'};
else
ab={2};
end
end
No worries about what is in the cell.
thb you could return what ever you want, Matlab does not check the type anyways
If only one of the outputs from the function AlternatingOutput is valid, then you only need to return one output:
function [X] = AlternatingOutput(input)
if input == 1
X = A;
else
X = B;
end
end
To allocate the retured value to either a or b in the loop, put them into a cell:
C = {AlternatingOutput(1), AlternatingOutput(2)};
and then use input to determine which value is change. If input is either 1 or 2 you can just do
for counter = ...
input = mod(input,2)+1;
C{input}=AlternatingOutput(input);
end
If your function doesn't mind accepting more input variables, why not pass a and b as input:
function [a,b] = AlternatingOutput(a,b,input)
if input == 1
a = new_value_for_a;
% b retains its former value
else
% a retains its former value
b = new_value_for_b;
end
end
Then it can be easily called from your script in a loop:
for i= ...
[a,b] = AlternatingOutput(a,b,input);
...
...
end

using evalin to evaluate a function in the base workspace

I am trying to allow a function to have access to the base workspace using the evalin function, but I am having trouble. Here is a simple example:
My main code:
A = 1;
B = 2
evalin('base','[ C ] = FUN(B)');
C
My Function:
function [C ] = FUN( B )
C = A + B;
end
My error:
Undefined function or variable 'A'.
Error in FUN (line 4)
C = A + B;
Error in Test (line 4)
evalin('base','[ C ] = FUN(B)');
So, the function is not being evaluated in the base workspace because it does not know what the value of A is.
Can anyone suggest something? I have a lot of variables that I need to access in several functions and I don't want to pass them and I don't want to use global variables.
Thanks!
From the evalin documentation,
evalin(ws, expression) executes expression, a string containing any valid MATLABĀ® expression, in the context of the workspace ws. ws can have a value of 'base' or 'caller' to denote the MATLAB base workspace or the workspace of the caller function.
So the line of code
evalin('base','[ C ] = FUN(B)');
evaluates only the line of code
[ C ] = FUN(B)
in the context of the base workspace. It does not evaluate the body of the function within the context of the base workspace. So the error that you are observing makes sense.
Is there a particular reason why you don't want to pass the variables in to the function? Why do you have several variables in the base (?) workspace, or do you just have several variables within a main function?
If the latter, you could use nested functions to have access to the variables declared in the caller (function) workspace. For example, suppose you have a main function like
function main()
A = 1;
B = 2;
C = FUN();
function [C] = FUN()
C = A + B;
end
end
The function FUN has access to both A and B and so you don't have to pass in any arguments.
An alternative to passing in several different inputs, is to just pass in a structure that has different fields that your function can access at will. Using the above example, we could do the following
function main()
A = 1;
B = 2;
data.A = A;
data.B = B;
C = FUN(data);
end
function [C] = FUN(data)
C = data.A + data.B;
end
In this case, the function FUN can be a function within its own file or declared after main. Again, we only pass in one argument that has all the data that the function needed.
Actually Evalin function is used to take data from base workspace:
Syntax is :
evalin('base','variable')
Evalin function is used in the function .
For example see the below function
function [out1 out2 out3]=main_fun(in1,in2)
out1=in1+in2;
out2=in1-in2;
in3=evalin('base','in3');
in4=evalin('base','in4');
out3=in3+in4;
end
Here out3 value will have the sum of in3 and in4 from workspace.
out1 and out2 will have the sum and difference of in1 and in2 from current function workspace.

scala assignment of value vs. reference types

I thought I had a firm grasp of Scala's treatment of reference types (i.e., those derived from AnyRef), but now I am not so sure.
If I create a simple class like this
class C(var x: Int = 0) {}
and define a few instances
var a = new C
var b = new C(1)
var c = new C(2)
and then I assign
a = b
I do not get a (shallow) copy, but rather the original reference to the instance to a is lost forever, and a and b are essentially "aliases" for the same object. (This can be seen by looking at the addresses of these items.) This is fine and sensible. It is also clear that these are references (as opposed to values), since I can do
c = null
and this does not generate an error.
Now, suppose I do this
import scala.math.BigInt
var x = BigInt("12345678987654321")
var y = BigInt("98765432123456789")
var z = x + y
This creates three BigInts, with x, y and z, as, I suppose, references to these. In fact, I can do
z = null
and again get no error. However,
y = x
x += 1
does not cause y to change, i.e., it appears that in this case assignment did not simply create another "name" for the object referred to by x, but made a copy of it.
Why does this happen? I cannot find any mechanism (e.g., akin to the "copy constructor" of C++) that would be silently invoked by (what appears to be) straightforward reference assignment.
Any explanation would be greatly appreciated, as two days of web search has proved fruitless.
x += 1 will be expanded into x = x + 1 so it's not only assignment.
If you will look at the source of bigInt you'll see that + creates new instance:
def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger))
in fact it uses java's BigInteger underneath whose add operations leaves both arguments untouched.
So what basically happens at the end of the day is reference reassignment of result of copy constructor of immutable addition
y = x
x += 1
BigInt is immutable so +1 creates new BigInt that's why y does not change. y still points to previous object while x points to new BigInt object.
I suppose its related to the immutability of BigInt and similar classes, you always get a new immutable object.