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
Related
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) .
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
}
I have a source file like (without loss of generality (only to image a possible syntax)):
function a()
return g // global variable without any internal structure exactly
end
function b(x, y)
local z = x * y
return z + 1
end
function c(z, t)
return b(z * z, a())
end
// ...etc
I want to defferentiate any function WRT to some variable.
All the formal parametres we can treat as a functions with unknown at derive time internal structure.
If I stand correct further, then the following is truth (for depending symbols ' is part of symbol, for global variables is operator during substitute time stage (def: g{g} is one, but g{y} is zero)):
function a'()
return g';
end
function b'(x, y, x', y')
local z' = x' * y + x * y'
return z' + 0
end
But what to do with last function? Namely, with actual parameters in substitution of function b?
Is there any ready to use implementations of general algorithm to work with the above? What to do with higher order derivatives (especially interesting, how to handle the formal parameters)? Are there any other possible unclear cases?
I would suggest having your parameters be symbolic expressions that know how to respond to derivatives, and having all operations take functions and return functions. Then you will get a final expression that knows how to be represented as a derivative. Furthermore you can do things like partial derivatives at a later point because you have the symbolic expression.
For a real example of what I mean, see http://www.elem.com/~btilly/kelly-criterion/js/advanced-math.js for a library that I wrote to solve a calculus problem in JavaScript, and search for "Optimize if requested" in the source for http://www.elem.com/~btilly/kelly-criterion/betting-returns2.html to see how I used it. See http://www.elem.com/~btilly/kelly-criterion/ for an explanation of why I was writing that code.
In that example I, of course, was not working from infix notation. But that is a standard parsing problem that I think you know how to solve.
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.
I want to emphasize I am looking for the actual way the ||= operator is expanded by the Ruby 1.9.3 interpreter, not how it appears to be expanded based on its behavior. What I'm really hoping for is someone who has grokked the actual interpreter source, a task which I sadly am probably not up to. The only resource I have found that appears to examine this question is out of date: "A short-circuit (||=) edge case".
The resource I mentioned above seems to suggest that the "official" expansion of x ||= y to x = x || y was either inaccurate or buggy in interpreter versions prior to 1.9. In any case, the edge case indicated seems to have been smoothed out. The resource above claims that x || x = y or x or x = y are "more accurate". Neither of those, however, is correct, because they don't work when x is a previously undeclared global variable:
[11:04:18][****#asha:~]$ irb
1.9.3-p194 :001 > a || a = 3
NameError: undefined local variable or method `a' for main:Object
1.9.3-p194 :002 > b or b = 3
NameError: undefined local variable or method `b' for main:Object
1.9.3-p194 :003 > c = c || 3
=> 3
So in 1.9.3, at least, the x = x || y expansion appears to be correct, as far as these examples are concerned. However, to reiterate my original point, I would really like to see some truly authoritative source resolve this question, well, authoritatively rather than anecdotally as I (and others) have done.
x ||= y
is a shorthand form for
x || x = y
If x is not nil and x is not false, the assignation will have place because of the short-circuit evaluation of the || operator.
EDIT: This post is about the spec, read the comments to get the somewhat less ideal "implementation story"
The Ruby draft spec (PDF) section 11.4.2.3.2 defines it fairly specifically (even if fairly hard to interpret); let's do a (theoretically somewhat loose) example with c ||= 3;
a) Evaluate the variable as a variable reference (see 11.5.4). Let V be the resulting value.
V is set to the value of c
b) Evaluate the operator-expression or the method-invocation-without-parentheses. Let W be the resulting value.
W is set to 3.
c) Let OP be the assignment-operator-name of the assignment-operator.
OP is set to ||
d) Let X be the operator-expression of the form V OP W.
X is set to c || 3.
e) Let I be the variable of the abbreviated-variable-assignment-expression or the abbreviated- variable-assignment-statement.
I is set to refer to c.
f) Evaluate a single-variable-assignment-expression (see 11.4.2.2.2) where its variable is I and the operator-expression is X.
c = c || 3 is evaluated.
g) The value of the abbreviated-variable-assignment is the resulting value of the evaluation.
The result of the assignment is 3.
In other words, the expansion c = c || 3 is (excluding bugs like in pre-1.9) correct.