Go: confusion about multiple assignments - go

I am a bit confused about multiple assignments in Go, e.g. varA, varB = varC, varD.
My question is, is such an operation atomic (not on the HW layer of course, but from the programmer's point of view)?
Personally, I expect it to be atomic, so this expression a, b = b, a just swap the values. I tried it in the Go playground and yes, it worked exactly like that.
On the other hand, the Golang specs states:
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.
which I understand as a is assigned b's value, then b is assigned a's value (which is now b), so in the end, both a and b equals b's original value.
Are the specs wrong or do I misunderstand it?

You misunderstood it, and it is not the second part you misunderstood.
The spec say:
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.
Here evaluated means all expressions, including variable are ..., well, being evaluated into value and the value is fixed at that time. So in a,b = b,a, in the first part, the lhs expression a,b got resolved, and rhs expression b,a got evaluated into something like 5,3 (assuming a,b:=3,5, of course); and in the second part, the assignment took place, and becomes a = 5; b = 3.
The evaluation is the samething happens when using defer and goroutine. It is why the below code prints 5.
func T() {
x := 5
defer func(i int) {
fmt.Println(i)
}(x)
x = 3
}

Related

Is nonexistence queriable in Datalog?

Suppose I've defined a few values for a function:
+(value[1] == "cats")
+(value[2] == "mice")
Is it possible to define a function like the following?
(undefined[X] == False) <= (value[X] == Y)
(undefined[X] == True) <= (value[X] does not exist)
My guess is that it can't, for two reasons:
(1) Queries are guaranteed to terminate in Datalog, and you could query for undefined[X] == True.
(2) According to Wikipedia, one of the ways Datalog differs from Prolog is that Datalog "requires that every variable appearing in a negative literal in the body of a clause also appears in some positive literal in the body of the clause".
But I'm not sure, because the terms involved ("terminate", "literal", "negative") have so many uses. (For instance: Does negative literal mean f[X] == not Y or does it mean not (f[X] == Y)? Does termination mean that it can evaluate a single expression like undefined[3] == True, or does it mean it would have found all X for which undefined[X] == True?)
Here another definition of "safe".
A safety condition says that every variable in the body of a rule must occur in at least one positive (i.e., not negated)
atom.
Source: Datalog and Recursive Query Processing
And an atom (or goal) is a predicate symbol (function) along with a list of terms as arguments. (Note that “term” and “atom” are used differently here than they are in Prolog.)
The safety problem is to decide whether the result of a given Datalog program can be guaranteed to be finite even when some source relations are infinite.
For example, the following rule is not safe because the Y variable appears only in a negative atom (i.e. not predicate2(Z,Y)).
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y) .
To meet the condition of safety the Y variable should appear in a positive predicate too:
rule(X,Y) :- predicate1(X,Z), not predicate2(Z,Y), predicate3(Y) .

how to assign one list to a variable in prolog?

I want to append([],C,C) where C is a list containing some elements . Is it possible? I will append some list in C containing elements append (Found,C,C) if other condition is true.
And also i want to store final value in C to a variable D . How can I do that?
I want to append([],C,C) where C is a list containing some elements. Is it possible?
append([],C,C) is always true. An empty list combined with anything is that anything. Look what Prolog says when you attempt it:
?- append([],C,C).
true.
This true without any bindings tells you that Prolog established the proof but no new bindings were created as a result. This code would have the same result:
meaningless(_, _, _).
?- meaningless(everybody, X, Squant).
true.
This suggests your desire is misplaced. append([], C, C) does not do what you think it does.
I will append some list in C containing elements append (Found,C,C) if other condition is true. And also i want to store final value in C to a variable D. How can I do that?
Thinking in terms of "storing" and other operations implying mutable state is a sure sign that you are not understanding Prolog. In Prolog, you establish bindings (or assert facts into the dynamic store, which is a tar pit for beginners). Something similar could be achieved in a Prolog fashion by doing something like this:
frob(cat, List, Result) :- append([cat], List, Result).
frob(dog, List, List).
This predicate frob/3 has two in-parameters: an atom and a list. If the atom is cat then it will append [cat] to the beginning of the list. The threading you see going between the arguments in the head of the clause and their use in the body of the clause is how Prolog manages state. Basically, all state in Prolog is either in the call stack or in the dynamic store.
To give an example in Python, consider these two ways of implementing factorial:
def fac(n):
result = 1
while n > 1:
result = result * n
n = n - 1
This version has a variable, result, which is a kind of state. We mutate the state repeatedly in a loop to achieve the calculation. While the factorial function may be defined as fac(n) = n * fac(n-1), this implementation does not have fac(n-1) hiding in the code anywhere explicitly.
A recursive method would be:
def fac(n):
if n < 1:
return 1
else:
return n * fac(n-1)
There's no explicit state here, so how does the calculation work? The state is implicit, it's being carried on the stack. Procedural programmers tend to raise a skeptical eyebrow at recursion, but in Prolog, there is no such thing as an assignable so the first method cannot be used.
Back to frob/3, the condition is implicit on the first argument. The behavior is different in the body because in the first body, the third argument will be bound to the third argument of the append/3 call, which will unify with the list of the atom cat appended to the second argument List. In the second body, nothing special will happen and the third argument will be bound to the same value as the second argument. So if you were to call frob(Animal, List, Result), Result will be bound with cat at the front or not based on what Animal is.
Do not get mixed up and think that Prolog is just treating the last argument as a return value! If that were true, this would certainly not work like so:
?- frob(X, Y, [whale]).
X = dog,
Y = [whale].
What appears to have happened here is that Prolog could tell that because the list did not start with cat it was able to infer that X was dog. Good Prolog programmers aspire to maintain that illusion in their APIs, but all that really happened here is that Prolog entered the first rule, which expanded to append([cat], X, [whale]) and then unification failed because Prolog could not come up with an X which, having had [cat] prepended to it, would generate [whale]. As a result, it went to the second rule, which unifies X with dog and the second two arguments with each other. Hence Y = [whale].
I hope this helps!

swapping three numbers using xor in a single line

I read that three variables a,b, and c can be swapped using the single statement below:
c = a ^ b ^ c ^ (a=b) ^ (b=c)
Similarly, two variables a and b can be swapped as:
a = a ^ b ^ (b=a)
Can somebody please explain how does this work?
P.S. Here is the link saying so.
http://p--np.blogspot.ro/2011/04/reverse-linked-list-using-only-2.html
You only need to make in the original statement all assignments (except the one you want to change to) are countered:
a = a ^ b ^ c ^ (b=c) ^ (c=a);
You assign c=a, b=c. The return value of those is a and c respectevely, so, you want to "counter" a and c, and you use the fact that a^a == 0 and c^c == 0, and just add a,c at the beginning.
In addition, you add a b, to assign a to the value of b.
Here is a demo on ideone
Note that as discussed in comments, it is language dependent if the above is guaranteed to succeed or not. In Java, for example - it is: The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right., while in others, such as C, it is not.

Evaluation functions and expressions in Boolean expressions

I am aware how we can evaluate an expression after converting into Polish Notations. However I would like to know how I can evaluate something like this:
If a < b Then a + b Else a - b
a + b happens in case condition a < b is True, otherwise, if False a - b is computed.
The grammar is not an issue here. Since I only need the algorithm to solve this problem. I am able evaluate boolean and algebraic expressions. But how can I go about solving the above problem?
Do you need to assign a+b or a-b to something?
You can do this:
int c = a < b ? a+b : a-b;
Or
int sign = a < b ? 1 : -1;
int c = a + (sign * b);
Refer to LISP language for S-express:
e.g
(if (> a b) ; if-part
(+ a b) ; then-part
(- a b)) ; else-part
Actually if you want evaluate just this simple if statement, toknize it and evaluate it, but if you want to evaluate somehow more complicated things, like nested if then else, if with experssions, multiple else, variable assignments, types, ... you need to use some parser, like LR parsers. You can use e.g Lex&Yacc to write a good parser for your own language. They support somehow complicated grammars. But if you want to know how does LR parser (or so) works, you should read into them, and see how they use their table to read tokens and parse them. e.g take a look at wiki page and see how does LR parser table works (it's something more than simple stack and is not easy to describe it here).
If your problem is just really parsing if statement, you can cheat from parser techniques, you can add empty thing after a < b, which means some action, and empty thing after else, which also means an action. When you parsed the condition, depending on correctness or wrongness you will run one of actions. By the way if you want to parse expressions inside if statement you need conditional stack, means something like SLR table.
Basically, you need to build in support for a ternary operator. IE, where currently you pop an operator, and then wait for 2 sequential values before resolving it, you need to wait for 3 if your current operation is IF, and 2 for the other operations.
To handle the if statement, you can consider the if statement in terms of C++'s ternary operator. Which formats you want your grammar to support is up to you.
a < b ? a + b : a - b
You should be able to evaluate boolean operators on your stack the way you currently evaluate arithmetic operations, so a < b should be pushed as
< a b
The if can be represented by its own symbol on the stack, we can stick with '?'.
? < a b
and the 2 possible conditions to evaluate need to separated by another operator, might as well use ':'
? < a b : + a b - a b
So now when you pop '?', you see it is the operator that needs 3 values, so put it aside as you normally would, and continue to evaluate the stack until you have 3 values. The ':' operator should be a binary operator, that simply pushes both of its values back onto the stack.
Once you have 3 values on the stack, you evaluate ? as:
If the first value is 1, push the 2nd value, throw away the third.
If the first value is 0, throw away the 2nd and push the 3rd.

What is the := operator?

In some programming languages, I see (ex.):
x := y
What is this := operator generally called and what does it do?
In all languages that support an operator := it means assignment.
In languages that support an operator :=, the = operator usually means an equality comparison.
In languages where = means assignment, == is typically used for equality comparison.
does := mean =?
I can't recall any languages where := means the same as =.
In MySQL := and = are both used for assignment, however they are not interchangeable and selecting the correct one depends on the context. To make matters more confusing the = operator is also used for comparison. The interpretation of = as either assignment or comparison also depends on context.
This is a new operator that is coming to Python 3.8 and actually had a role in BDFL Guido van Rossum's early retirement.
Formally, the operator allows what's called an "assignment expression". Informally, the operator is referred to as the "walrus operator".
It allows assignment while also evaluating an expression.
So this:
env_base = os.environ.get("PYTHONUSERBASE", None)
if env_base:
return env_base
can be shortened to:
if env_base := os.environ.get("PYTHONUSERBASE", None):
return env_base
https://www.python.org/dev/peps/pep-0572/#examples-from-the-python-standard-library
I usually see it more in pseudocode where it means an assignment. Thus x := y means 'set the value of x to the value of y' whereas x = y means 'does the value of x equal the value of y?'
The symbol is called "becomes" and was introduced with IAL (later called Algol 58) and Algol 60. It is the symbol for assigning a value to a variable. One reads x := y; as "x becomes y".
Using ":=" rather than "=" for assignment is mathematical fastidiousness; to such a viewpoint, "x = x + 1" is nonsensical. Other contemporary languages might have used a left arrow for assignment, but that was not common (as a single character) in many character sets.
Algol 68 further distinguished identification and assignment; INT the answer = 42; says that "the answer" is declared identically equal to 42 (i.e., is a constant value). In INT the answer := 42; "the answer" is declared as a variable and is initially assigned the value 42.
There are other assigning symbols, like +:=, pronounced plus-and-becomes; x +:= y adds y to the current value of x, storing the result in x.
(Spaces have no significance, so can be inserted "into" identifiers rather than having to mess with underscores)
A lot of languages use common operators. Generally the = is reserved for variable assignment and should not be viewed in a mathematical context if it is alone. Equality in some languages like Java and Bash is tested though ==
PL/I has (had?) both = and :=. = is used for both assignment and comparison -- the compiler tries to figure out which you meant based on context. When/if it decides to do comparison where you really meant assignment, you can use := to force assignment.
For example, consider x=y=0; In C (for one example) this would mean "assign 0 to y, then the result of that (also 0) to x."
In PL/I, it means compare y to 0, and then assign the Boolean result of that comparison to x (i.e., equivalent to x = y == 0; in something like C). If you (being sane, unlike the designers of PL/I) intended that to mean "assign 0 to x and y", you'd use x = y := 0; (or x := y := 0;).
:= it means "set equal to"
An assignment with syntax
v := expr
sets the value of variable «v» to the value obtained from expression «expr».
Example:
X := B Sets the Definition of X to the value of B

Resources