I can't understand precedence of Ruby operators in a following example:
x = 1 && y = 2
Since && has higher precedence than =, my understanding is that similarly to + and * operators:
1 + 2 * 3 + 4
which is resolved as
1 + (2 * 3) + 4
it should be equal to:
x = (1 && y) = 2
However, all Ruby sources (including internal syntax parser Ripper) parse this as
x = (1 && (y = 2))
Why?
EDIT [08.01.2016]
Let's focus on a subexpression: 1 && y = 2
According to precedence rules, we should try to parse it as:
(1 && y) = 2
which doesn't make sense because = requires a specific LHS (variable, constant, [] array item etc). But since (1 && y) is a correct expression, how should the parser deal with it?
I've tried consulting with Ruby's parse.y, but it's so spaghetti-like that I can't understand specific rules for assignment.
Simple. Ruby only interprets it in a way that makes sense. = is assignment. In your expectation:
x = (1 && y) = 2
it does not make sense to assign something to 1 && y. You can only assign something to a variable or a constant.
And note that the purpose of the precedence rule is to disambiguate an otherwise ambiguous expression. If one way to interpret it does not make sense, then there is no need for disambiguation, and hence the precedence rule would not be in effect.
My understanding is that in the case of
x = 1 && y = 2
The logical AND is parsed first. The AND then is forced to evaluate its left side and its right side. In the evaluation the left side the first assignment occurs, and then in the evaluation of the right side the second does the same. It is for this reason that in the case of:
x = false && y = 2
"y" will never be assigned. The AND is hit, forcing the x assignment to evaluate, but never bothering to run the y assignment, as it is unnecessary for the AND to fulfill its purpose.
In other words, the parser is, again, simply to my understanding, smart enough to recognize that in running the AND the equation is split into a left and right side (equations), which are in turn evaluated according to the order of operation.
Related
Working on an exercise for university class and cant seem to represent what I am trying to do with correct syntax in ocaml. I want the function sum_positive to sum all the positive integers in the list into a single int value and return that value.
let int x = 0 in
let rec sum_positive (ls: int list) = function
|h::[] -> x (*sum of positive ints in list*)
|[] -> 0
|h::t -> if (h >= 0) then x + h then sum_positive t else sum_positive t (*trying to ensure that sum_positive t will still run after the addition of x + h*)
On compiling I am met with this error,
File "functions.ml", line 26, characters 34-38:
Error: Syntax error
This points to the then then statement I have in there, I know it cannot work but I cant think of any other representations that would.
You have if ... then ... then which is not syntactically valid.
It seems what you're asking is how to write what you have in mind in a way that is syntactically valid. But it's not clear what you have in mind.
You can evaluate two expressions in OCaml sequentially (one after the other) by separating them with ;. Possibly that is what you have in mind.
However it seems to me your code has bigger problems than just syntax. It appears you're trying to use x as an accumulated sum for the calculation. You should be aware that OCaml variables like x are immutable. Once you say let x = 0, the value can't be changed later. x will always be 0. The expression x + h doesn't change the value of x. It just evaluates to a new value.
The usual way to make this work is to pass x as a function parameter.
I was getting an issue that had involved the parameter of , I believe it was because I was trying to add an int value to function of type int list. This is what I ended up with.
let rec sum_positive = function
|[] -> 0
|h::t -> if h > 0 then h + (sum_positive t) else sum_positive t
a lot simpler than I thought it out to be.
I want to quickly create a structure in Picat. But the components of the structure should be evaluated when creating the structure. So far I tried, which gives me a structure when the components are already constants:
Picat 2.0b5, (C) picat-lang.org, 2013-2016.
Picat> X = $point(2,3).
X = point(2,3)
yes
But the following doesn't work, i.e. components that should be evaluated. I am expecting as a result X = point(3,12), but it doesn't give this result:
Picat> X = $point(1+2,3*4).
X = point(1 + 2,3 * 4)
yes
What is the shortest way to do that? It seems that the Picat ($)/1 operator is like lisp quote operator and it prevents Picat evaluation. What remains is Prolog unification. Here are some examples of Prolog unification in Picat:
Picat> $point(X,Y) = $point(1+2,3*4).
X = 1 + 2
Y = 3 * 4
yes
Picat> $point(X+Y,Z) = $point(1+2,3*4).
X = 1
Y = 2
Z = 3 * 4
yes
Picat> $X = $point(1+2,3*4).
X = point(1 + 2,3 * 4)
yes
As in Prolog expressions such as 1+2 and 3*4 are not evaluated inside ($)/1. Maybe its impossible to have evaluating constructors in Picat, similarly they are not found in standard Prolog at the moment.
Try this:
Picat> X = new_struct(point, [1+2,3*4]).
X = point(3,12)
yes
It's another way to create structures in Picat. With new_struct you could create a structure passing as first argument the name of the structure that you would like to create and as second argument either an integer (that will be the number of fields of the structure) or a list. In the latter case the fields of the structure will be the elements of the list.
Even I can't understand why expressions are not evaluated before the creation of point. If I'm not wrong in the book Constraint solving with Picat is said that arguments are completely evaluated before calls are evaluated.
To illustrate the difference between 'is' and '=', next example is given in my Prolog course:
?- X is 2+3
X = 5.
?- X = 2+3.
X = 2+3.
However, both Y is 3 and Y = 3 seem to do the same. Is there a difference? And if not, is there a convention not to use one of the two in Prolog programs?
In Prolog, =/2 and is/2 serve very different purposes. is/2 is used to assign a value from an arithmetic expression. The right hand side must be fully instantiated (all variables bound) and it will compute the expression and unify it with the single variable on the left. For example:
Y = 3,
X is log(Y+7)/2.
X = 1.151292546497023
Y = 3
The = is used to unify terms on each side of the =. So when you say:
X = log(Y+7)/2.
That is unifying the term X with the term log(Y+7)/2 (or, technically, '/'(log('+'(Y,7),2)) which gives you X = log(Y+7)/2. It doesn't compute log(Y+7)/2. because that's not the job of =. That's a job for is/2.
With = you can also say things like:
foo(X, _) = foo(3, blah).
And you will get X = 3 since it can unify both terms by setting X to 3.
In the simplest case, these operators appear to be the same because X is 3 evaluates the expression 3 and assigns it (binds it to) X, and X = 3 unifies X with 3. Both results are the same in this case.
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.