Call by value, name/reference, need in ML - parameter-passing

I am studying for a final, and I have a practice problem here.
The question asks for the result of
val y = ref 1;
fun f x = (!y) + (x + x);
(f (y := (!y)+1; !y)) + (!y);
under the following parameter passing techniques:
Call by value
Call by name
Call by need.
It seems to me that for call by value, the answer is 8.
However, I believe the answer for call by name is also 8, but I would expect it to be different. The reason I think it is 8:
y := (!y)+1 derefs y as 1, adds 1, and then sets y to 2
!y in line 3 serves as the argument to f, and since it is being dereferenced it is
passed as a value rather than as a reference (this may be where I am
going wrong?)
The function call returns 6, but does not set y as y was passed in as a value from the previous step
6 is added to the dereferenced value of y, which is 2.
This returns 8
Is this the correct answer, and if not, can someone please point out where I have gone wrong? Also, can someone explain to me how call by need would work in this situation also?
Many thanks.

I found out how it works:
(y := (!y)+1; !y) is the parameter passed to f.
f then looks like:
fun f x = (!y) + ((y:= (!y)+1; !y) + (y:= (!y)+1; !y));
so this ends up being 1+2+3, and the final step + (!y) adds 3 as this is the current value of y, giving 9.
Thanks for pointing out that I was still doing call-by-value.

Related

What happens when you pass an expression to a function which has passing by value-result?

I'm attending a course of principles of programming languages and there's this exercise where I'm supposed to tell what gets printed by this program:
{
int x=2;
void A (val/res int y)
{
x++;
write(y);
y=y+2;
}
A(x)
A(x+1)
write (x);
}
A is a function with value/result parameters passing, so right before returning it should copy the final value of its formal parameter (y) in the actual parameter. When A first gets called its actual parameter is x, so there's no problem there. However, the second call to A has x+1 as the actual parameter.
What does that mean? Maybe the final value of y gets lost because there's no variable where to copy it? Or maybe I should consider it like an equation, so if the final value of y is 7 I get that x + 1 = 7, and then the value of x is 6?
It means the value of the argument is copied to y:
When x=2, A(x) copies 2 to y at the start of A
When x=4, A(x+1) copies the value of x+1, or 5, to y at the start of A
However, as you pointed, out, passing x+1 for a value/result parameter is problematic, and I would expect any language supporting this type of parameter would not consider it legal, for just the reason you cite. If it is considered legal, how it is accomplished would be up to the language definition; I do not believe there is a standard way to handle this.

Applying a function to multiple rows of a data frame where the row is an argument in the function in R

Apologies for the rather long name, but I wanted to be specific. I am rather new to R and coding so please go easy on me.
I have a function as follows:
myfun = function(x, y, g) {return(1 / (1 + exp(y*g%*%x)))}
where x is any data frame with n rows and d columns, y is a scalar and integer, and g is a vector of length d (i.e. same as x). I want to run this function for each row of x without using loops.
I have tried various function in the apply family similar to the code below:
apply(x = a, 1, myfun(y = 1, g = b)
where a is a 3x3 data frame and b is a vector 3 elements long. The above code gives an error that I am missing an argument from myfun, but I am obviously clueless on what to try.
Thanks for any help in advance!
Edit: My actual data frame is huge, sparse, and not very straight forward (I think), so I will include an example data frame and other variables:
a = data.frame(c1 = seq(1,3,1), c2 = seq(4,6,1), c3 = seq(7,9,1))
b = c(1,2,3)
c = 1
Also, I think I may have not clearly stated an important piece of information. I want to actually do a summation of myfun over all the rows and values of b, so I actually want the following:
answer = myfun(a[1,], c, b[1]) + myfun(a[2,], c, b[2]) + myfun(a[3,], c, b[3])
In other words, a[1,] should be applied to myfun with b[1] as they are grouped together. I also made an edit to the function above because I forgot to include return(). Hopefully, this makes things more clear. Apologies for the confusion!

Confusing about a very simple program

I have this question :
The program is very simple :
sub(b, a)
<=>
sub(x, y)
x = x + y = 3 + 2 = 5
y = x + y = 5 + 2 = 7
<=>
b = 5
a = 7
therefore d is the right answer
but the given answer is c(a = 7, b =3 )
Why? What am i missing here ?
Any help is greatly appreciated !
Note that "the parameter x is called by value, and the parameter y is called by reference".
So b is passed by value, which means that the x inside sub is just a local variable - it's not pointing to the same location as b.
Therefore, the changes made to x inside sub do not affect the variable b that was passed in.
Contrast with y which is passed by reference, which means that y and a are actually the same variable, so changes to y inside sub are reflected in a outside of it.
The trick here is the difference between pass-by-value and pass-by-reference. As the prompt notes x is passed (or "called") by value. This means that when you pass b to sub as x, x contains only the literal value of b. What this means from a practical standpoint is that any changes made to x in sub will NOT affect b back in the main program.
On the other hand, since y is passed by reference, when you pass a to sub as y, y is really a reference to the variable a (y "points" to a). This means that if you make changes to y in sub those changes affect a back in the main program.
If the above is confusing to you, think of it this way: if a variable is passed by value to a function, you can replace the parameter name (x) with the value of the argument (3). If a variable is passed by reference to a function, you can think of it as replacing the parameter name (y) with the variable name of the argument (a).
With that in mind, let's revisit the question:
a = 2;
b = 3;
sub(b, a);
----------
x = x + y
(in this line x represents the value of b, which is 3, so the value of x (but not b) is now 5)
y = x + y
(in this line y represents the actual variable a, whose value is 3. When we add x to y, however, it actually changes a. Therefore, the value of both y and a after this line is 7)
return;
So as you can see, b cannot be changed in the original function, so its final value can only be 3. a however can be changed, and due to operations in sub now has a value of 7.
I hope this clears up any confusion you were facing with this problem.

Prolog binary addition without cuts(!)

I am trying to figure out how to add two binary numbers together which are represented as lists. For example:
addNumbers([1,0,1], [1,1,0,0], X). should return X = [1,0,0,0,1].
We are not aloud to use cuts(!) to solve this problem. So I know I have to implement a adder of sorts. Right now I have adding Digits implemented with its needed predicates:
addDigits(A,B,X,Y) :- myXor(A,B,X), myAnd(A,B,Y).
myAnd(A,B,R) :- A == 1, B == 1, R is 1.
myAnd(A,B,R) :- A == 0, B == 0, R is 0.
myAnd(A,B,R) :- A == 1, B == 0, R is 0.
myAnd(A,B,R) :- A == 0, B == 1, R is 0.
myOr(A,B,R) :- A == 0, B == 0, R is 0.
myOr(A,B,R) :- A == 0, B == 1, R is 1.
myOr(A,B,R) :- A == 1, B == 0, R is 1.
myor(A,B,R) :- A == 1, B == 1, R is 1.
This correctly returns X as the sum of the 2 binary digits and Y as the carry. Now I know I need this for my adder. Now to actually implement addDigits is where I am stuck. This is currently what I have but does not work. NOTE: The hint was the start the the LSB's but I currently don't do that.
addNumbers([HA|TA],[HB|TB],X) :- adder(HA,HB,Cin,Sum,Cout,X),
append(Sum, X, X),
addNumbers(TA,TB,X).
adder(X,Y,Cin,Sum,Cout) :- addDigits(X,Y,Sum1,Carry1),
addDigits(Sum1, Cin, Sum, Carry2),
myOr(Carry1, Carry2, Cout).
Any help/suggestions would be appreciated.
Cheers
You are on a good track. Your major problem is to understand typical Prolog recursion.
But first, your binary functions: They are correct, but it's easier and more readable like this (you are missing this one anyway):
myXor(1,0,1).
myXor(0,1,1).
myXor(1,1,0).
myXor(0,0,0).
There is a typo in your myOr in the fourth case: you spelled it with a lower case "o". With this defined, your adder does indeed work correctly!
Now, about the recursion: You really need to start with the LSB, otherwise you can't even know which bits to add, because the numbers are not necessarily the same length. Fortunately, you can do this easily by wrapping the call in reverses:
addNumbers(N1, N2, Sum) :-
reverse(N1, N12),
reverse(N2, N22),
addNumbers(N12, N22, 0, [], Sum0),
reverse(Sum0, Sum).
This is quite a common pattern in Prolog: addNumbers/3 calling addNumbers/5 with more parameters needed for the recursion. The "0" is the initial carry, the [] is the accumulator for the result.
Here is addNumbers/5, with some changes from your version:
addNumbers([HA|TA],[HB|TB],Cin,X0,X) :-
adder(HA,HB,Cin,Sum,Cout),
append(X0, [Sum], X1),
addNumbers(TA,TB,Cout,X1,X).
First, note that you need to receive Cin as an input parameter here! Also, we have X0 as an "accumulator" variable, that is, it grows longer with each recursive call. The final call will have the result, so it can make it into the output variable. For that, you also need the base cases:
addNumbers([],B,Cin,X0,X) :- % TODO: Respect Cin
append(X0,B,X).
addNumbers(A,[],Cin,X0,X) :- % TODO: Respect Cin
append(X0,A,X).
See how the result of append is not X1 (another intermediate variable) as above, but X? This is because its the final result, and it will be unified with the same X all the way down the call stack, and this way it becomes the output of the whole addNumbers/5 call!
I left it unfinished though, so that there is some (little) work for you left: Also the base cases need to take Cin into account...

Error plotting a function of 2 variables

I am trying to plot the function
f(x, y) = (x – 3).^2 – (y – 2).^2.
x is a vector from 2 to 4, and y is a vector from 1 to 3, both with increments of 0.2. However, I am getting the error:
"Subscript indices must either be real positive integers or logicals".
What do I do to fix this error?
I (think) I see what you are trying to achieve. You are writing your syntax like a mathematical function definition. Matlab is interpreting f as a 2-dimensional data type and trying to assign the value of the expression to data indexed at x,y. The values of x and y are not integers, so Matlab complains.
If you want to plot the output of the function (we'll call it z) as a function of x and y, you need to define the function quite differently . . .
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
z = f( repmat(x(:)',numel(y),1) , repmat(y(:),1,numel(x) ) );
surf(x,y,z);
xlabel('X'); ylabel('Y'); zlabel('Z');
This will give you an output like this . . .
The f = #(x,y) part of the first line states you want to define a function called f taking variables x and y. The rest of the line is the definition of that function.
If you want to plot z as a function of both x and y, then you need to supply all possible combinations in your range. This is what the line containing the repmat commands is for.
EDIT
There is a neat Matlab function meshgrid that can replace the repmat version of the script as suggested by #bas (welcome bas, please scroll to bas' answer and +1 it!) ...
f = #(x,y)(x-3).^2 - (y-2).^2;
x=2:.2:4;
y=1:.2:3;
[X,Y] = meshgrid(x,y);
surf(x,y,f(X,Y));
xlabel('x'); ylabel('y'); zlabel('z');
I typically use the MESHGRID function. Like so:
x = 2:0.2:4;
y = 1:0.2:3;
[X,Y] = meshgrid(x,y);
F = (X-3).^2-(Y-2).^2;
surf(x,y,F);
xlabel('x');ylabel('y');zlabel('f')
This is identical to the answer by #learnvst. it just does the repmat-ing for you.
Your problem is that the function you are using uses integers, and you are trying to assign a double to it. Integers cannot have decimal places. To fix this, you can make it to where it increases in increments of 1, instead of 0.2