Assigning values to multiple variables in Go - go

I recently came up across this:
func main() {
x, y := 0, 1
x, y = y, x+y
fmt.Println(y)
}
What I thought was that:
x, y = y, x+y
Is identical to:
x = y
y = x+y
Which would result to final values x = 1, y = 2
However the final values I get is x = 1, y = 1
Why is that?
Thanks.

This is how it's specified:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
Assignment first evaluates all expressions on the right side and then assigns the results to the variables on the left side.
Your
x, y = y, x+y
is basically equivalent to this
tmp1 := y
tmp2 := x+y
x = tmp1
y = tmp2
You can even use this fact to swap 2 variables in one line, like this:
a, b = b, a

Related

how to write an algorithim to swap two variables without creating the third variable?

how to swap two variables without creating the third variable? for ex. a=10 b=20 so, how can I write an Algorithm to swap these two variable to a=20 b=10 without adding another variable c in my logic?
You can use this technique
a=a+b
b=a-b
a=a-b
Edit 1:
As commented by pjs, the above technique could overflow in some languages so you can use XOR:
a=a^b
b=a^b ## which is b= (a^b)^b=a
a=a^b ## which is b= (a^b)^a=b
int x = 987, y = 123;
x = x xor y;
y = x xor y;
x = x xor y;
Now x and y are swapped:
x = 123, y = 987;

Checking whether a function is computable or not

I've been given the following function written in pseudocode:
P:
{
int x, y, z;
read (x, y, z);
while (x != y) {
x = x - y;
z = z + y
};
write z;
}
Given that f(x,y,z) is the function calculated by P, I would like to know if the function "g(x,y,z)=1 if f(x,y,z) is not a total function or g(x,y,z)=0 otherwise", is computable.
My first guess is: yes, it is computable (for example for x=y).
Is there a more rigorous general approach to prove that?
P does not change the value of y, and the only way it changes the value of x is to subtract y from x until x = y. If subtracting y from x does not eventually result in x = y, then the loop continues forever. We know that subtracting y from x repeatedly can only cause x = y if initially x = cy for natural numbers c >= 1. So, g(x,y,z) = 1 because f(x,y,z) is not a total function; it is undefined when x != cy for any natural number c >= 1. Even if what you meant is that g(x,y,z) = 1 whenever f(x,y,z) is defined, it is still computable, since g(x,y,z) is the function:
g(x,y,z) = { 1, if x = cy for some natural number c >= 1 }
{ 0, otherwise }
The condition x = cy for some natural number c >= 1 is itself computable since this is equivalent to "x >= y" and "GCD(x, y) = y".

retracting and asserting values in prolog

I have been modelling some directive graphs in prolog. It consists of nodes and edges and how they are connected. Every node has a certain value of surfers (page rank).
e.g.
e(a,c).
e(b,a).
e(b,h).
:-dynamic s/2.
s(a,1).
s(b,1).
s(c,1).
I have written an interpreter. This interpreter calculates new values for each node.
The problem is how to assign these new values to the database.
I have been doing it with retractall(s(,)) and asserting new values to every single node with e.g. assertz(s(a,sum0),
assertz(s(b,sum1), ....
This has been working, but is it possible to assert new values without asserting each particular node in the graph a value, so that the interpreter is completely independent from the graph?
I have been trying to generate a list with all nodes in a graph and indicating the nodes of a graph in this list.
sum_nodes_0(X,Y):-
list_nodes(_,L),
amount_nodes(N),
nth1(I,L,X),I=<N,sum_node(X,Y).
reset(X,S):-
list_nodes(_,L),
s(X,S),
sum_node(X,Y),
retractall(s(_,_)),
forall(member(X,L),assertz(s(X,Y))).
sum_nodes_0 displays me the new values like.
X = a,
Y = 1.0 ;
X = b,
Y = 1 ;
X = c,
Y = 2 ;
X = d,
Y = 0.5 ;
X = e,
Y = 1.5 ;
X = f,
Y = 0.5 ;
X = g,
Y = 1 ;
X = h,
Y = 0.5.
These values I want to be assigned by reset(X,S). But reset just resets one value not all. e.g.
X=h; Y=0
I have tried foreach, forall and member predicates. But it didn't work as intended.
I hope that someone has an idea.

Prolog - adding two arguments, even if one is not a number

in Prolog, how should I proceed when I want to add two arguments, even if one is not a number. So for instance, if I enter add2args(1,2,R). the result should be R = 3. If I enter add2args(1,x,R). the result should be R=1+x.
So far I have this:
add_2args(X,Y,R):- number(X),number(Y), R is (X+Y).
Which allows me to add two numbers, but I don't know how I can get it to print out anything other than true and false if X and Y are not numbers which is normal since number(X) checks if X is a number or not. What other rule do I have to add to get the desired result?
Prolog will view an expression symbolically (as a Prolog term) unless explicitly evaluated with something like is/2. So the simplest way to do this in your case would be the following:
add_2args(X, Y, R) :-
( number(X), number(Y) % Both X and Y are numbers, then...
-> R is X + Y % Evaluate the expression
; R = X + Y % Else, just unify R with the expression
).
The R = X + Y will not evaluate the expression but only unify the term X + Y with R. This is also a nice "Prolog beginner's guide" illustration for the difference between =/2 and is/2. If you wrote, for example, R = 2 + 3, then did a write(R) you would see 2 + 3, not 5. You could subsequently do, Result is R which would then evaluate the expression R and yield Result = 5.
| ?- R = 2 + 3, Result is R.
R = 2+3
Result = 5
yes
| ?-

Simultaneous variable assignment in Go different from individual variable assignment

I was under the impression that despite the differences in syntax, function a and function b below were logically equivalent. However, they are not and I do not understand the difference between them.
It seems to me that they are both assigning:
the value of x to the variable z,
the value of y to the variable x, and
the value of x+y to the variable y.
Could anyone help clear up my misunderstanding regarding the multiple variable assignment and the logical difference between function a and function b?
package main
import "fmt"
func a() (int, int, int) {
x:=1
y:=2
z:=3
z = x
x = y
y = x+y
return x, y, z
}
func b() (int, int, int) {
x:=1
y:=2
z:=3
z, x, y = x, y, x+y
return x, y, z
}
func main() {
fmt.Println(a()) // prints 2 4 1
fmt.Println(b()) // prints 2 3 1
}
Assignment can be thought of as an "atomic" operation. That is, it's useful to think that all values on the left hand side of the = are "frozen" until all of the operations are finished.
Consider the following program:
package main
import "fmt"
func swap() (int, int) {
x := 1
y := 2
x, y = y, x
return x, y
}
func main() {
fmt.Println(swap()) // prints 2 1
}
Without this "freezing" behaviour, you would get 2 for both x and y, which is probably not what you'd expect from the code. It's also probably easier to reason about the semantics of this "freezing" behaviour than if the "cascading" approach were taken.
The simple answer is because it's all one statement and the value of y hasn't been updated to 2 at the point when x+y is evaluated. IE the expression on the right hand side is evaluated prior to any assignment. In the other case everything happens on step at a time so ofc y's value has been updated to 2 and you get four.
Interesting problem for academic purposes, terrible code in real life so please don't write anything like that in a real program.
The Go Programming Language Specification
Assignments
the number of operands on the left must equal the number of
expressions on the right, each of which must be single-valued, and the
nth expression on the right is assigned to the nth operand on the
left:
one, two, three = '一', '二', '三'
The blank identifier provides a way to ignore right-hand side values
in an assignment:
_ = x // evaluate x but ignore it
x, _ = f() // evaluate f() but ignore second result value
The assignment proceeds in two phases. First, the operands of index
expressions and pointer indirections (including implicit pointer
indirections in selectors) on the left and the expressions on the
right are all evaluated in the usual order. Second, the assignments
are carried out in left-to-right order.
Tuple assignments are two phase assignment. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
For example,
package main
import "fmt"
func a() (int, int, int) {
x := 1
y := 2
z := 3
// phase 1
tx := x
ty := y
// phase 2
z = tx
x = ty
y = tx + ty
return x, y, z
}
func b() (int, int, int) {
x := 1
y := 2
z := 3
z, x, y = x, y, x+y
return x, y, z
}
func main() {
fmt.Println(a())
fmt.Println(b())
}
Output:
2 3 1
2 3 1

Resources