Are there any right associative short-circuit operators - language-design

I'm working on a interrupter the lets one define their own operators. The goal then is to take an AST that looks like exp op exp op exp and turn it into either exp op (exp op exp) or (exp op exp) op exp based on the relative precedence and associativity of the two operators. The language is dynamic so the only way to know what version of the operator to use is to evaluate the first expression and ask it what version of op to use.
On the other hand, it is important that we not evaluate the second expression because if op is || (as commonly used) then we should be able to short-circuit if the first exp is false.
a problem would arise if some operator were both right associative and short-circuiting. My question is are there any right associative, short-circuiting operators in common use (for a chosen value of "common")?
N.b. assignment is handled separately by the parser so = is not an operator and a (op)= b is syntactic sugar for a = a op b.

Boolean implication might be.
I would probably read
a → b → c
as "a implies that b implies c" which would suggest that it should parenthesize
a → (b → c)
and boolean implication should probably be short-circuiting since when a is false then the right side of (a → b) is irrelevant to the result.

Related

What does the operator := mean? [duplicate]

I've seen := used in several code samples, but never with an accompanying explanation. It's not exactly possible to google its use without knowing the proper name for it.
What does it do?
http://en.wikipedia.org/wiki/Equals_sign#In_computer_programming
In computer programming languages, the equals sign typically denotes either a boolean operator to test equality of values (e.g. as in Pascal or Eiffel), which is consistent with the symbol's usage in mathematics, or an assignment operator (e.g. as in C-like languages). Languages making the former choice often use a colon-equals (:=) or ≔ to denote their assignment operator. Languages making the latter choice often use a double equals sign (==) to denote their boolean equality operator.
Note: I found this by searching for colon equals operator
It's the assignment operator in Pascal and is often used in proofs and pseudo-code. It's the same thing as = in C-dialect languages.
Historically, computer science papers used = for equality comparisons and ← for assignments. Pascal used := to stand in for the hard-to-type left arrow. C went a different direction and instead decided on the = and == operators.
In the statically typed language Go := is initialization and assignment in one step. It is done to allow for interpreted-like creation of variables in a compiled language.
// Creates and assigns
answer := 42
// Creates and assigns
var answer = 42
Another interpretation from outside the world of programming languages comes from Wolfram Mathworld, et al:
If A and B are equal by definition (i.e., A is defined as B), then this is written symbolically as A=B, A:=B, or sometimes A≜B.
■ http://mathworld.wolfram.com/Defined.html
■ https://math.stackexchange.com/questions/182101/appropriate-notation-equiv-versus
Some language uses := to act as the assignment operator.
In a lot of CS books, it's used as the assignment operator, to differentiate from the equality operator =. In a lot of high level languages, though, assignment is = and equality is ==.
This is old (pascal) syntax for the assignment operator. It would be used like so:
a := 45;
It may be in other languages as well, probably in a similar use.
A number of programming languages, most notably Pascal and Ada, use a colon immediately followed by an equals sign (:=) as the assignment operator, to distinguish it from a single equals which is an equality test (C instead used a single equals as assignment, and a double equals as the equality test).
Reference: Colon (punctuation).
In Python:
Named Expressions (NAME := expr) was introduced in Python 3.8. It allows for the assignment of variables within an expression that is currently being evaluated. The colon equals operator := is sometimes called the walrus operator because, well, it looks like a walrus emoticon.
For example:
if any((comment := line).startswith('#') for line in lines):
print(f"First comment: {comment}")
else:
print("There are no comments")
This would be invalid if you swapped the := for =. Note the additional parentheses surrounding the named expression. Another example:
# Compute partial sums in a list comprehension
total = 0
values = [1, 2, 3, 4, 5]
partial_sums = [total := total + v for v in values]
# [1, 3, 6, 10, 15]
print(f"Total: {total}") # Total: 15
Note that the variable total is not local to the comprehension (so too is comment from the first example). The NAME in a named expression cannot be a local variable within an expression, so, for example, [i := 0 for i, j in stuff] would be invalid, because i is local to the list comprehension.
I've taken examples from the PEP 572 document - it's a good read! I for one am looking forward to using Named Expressions, once my company upgrades from Python 3.6. Hope this was helpful!
Sources: Towards Data Science Article and PEP 572.
It's like an arrow without using a less-than symbol <= so like everybody already said "assignment" operator. Bringing clarity to what is being set to where as opposed to the logical operator of equivalence.
In Mathematics it is like equals but A := B means A is defined as B, a triple bar equals can be used to say it's similar and equal by definition but not always the same thing.
Anyway I point to these other references that were probably in the minds of those that invented it, but it's really just that plane equals and less that equals were taken (or potentially easily confused with =<) and something new to define assignment was needed and that made the most sense.
Historical References: I first saw this in SmallTalk the original Object Language, of which SJ of Apple only copied the Windows part of and BG of Microsoft watered down from them further (single threaded). Eventually SJ in NeXT took the second more important lesson from Xerox PARC in, which became Objective C.
Well anyway they just took colon-equals assiment operator from ALGOL 1958 which was later popularized by Pascal
https://en.wikipedia.org/wiki/PARC_(company)
https://en.wikipedia.org/wiki/Assignment_(computer_science)
Assignments typically allow a variable to hold different values at
different times during its life-span and scope. However, some
languages (primarily strictly functional) do not allow that kind of
"destructive" reassignment, as it might imply changes of non-local
state.
The purpose is to enforce referential transparency, i.e. functions
that do not depend on the state of some variable(s), but produce the
same results for a given set of parametric inputs at any point in
time.
https://en.wikipedia.org/wiki/Referential_transparency
For VB.net,
a constructor (for this case, Me = this in Java):
Public ABC(int A, int B, int C){
Me.A = A;
Me.B = B;
Me.C = C;
}
when you create that object:
new ABC(C:=1, A:=2, B:=3)
Then, regardless of the order of the parameters, that ABC object has A=2, B=3, C=1
So, ya, very good practice for others to read your code effectively
Colon-equals was used in Algol and its descendants such as Pascal and Ada because it is as close as ASCII gets to a left-arrow symbol.
The strange convention of using equals for assignment and double-equals for comparison was started with the C language.
In Prolog, there is no distinction between assignment and the equality test.

GPU Optimization: should I avoid logical OR?

I'm getting started writing some shader code in Cg. I've read that GPUs don't handle branching conditions very well, but I'm not sure what this means for me as a programmer.
More precisely, I'm trying to understand which structures have performance costs.
For instance, I have some code that looks like this:
bool v = step( _Margin, c.y)
|| step( _Margin, c.x)
|| !step( 1-_Margin, c.x)
|| !step( 1-_Margin, c.y);
It seems to me like the logical ORs in that statement do some conditional logic, placing a true value in the variable v if a certain set of conditions are met. Is this branching: is it okay, or if not, should I be going about it another way?
I don't want to step too far down the premature optimization path, but I also do want to understand what is going on here.
Finally I've done some investigation (it's necessary even if sure of the answer!)
According to Cg language specification:
Both sides of && and || are always evaluated; there is no short-circuiting as there is in C.
And even for conditional operator (?:)
Unlike C, side effects in the expressions in the second and third operands are always executed, regardless of the condition.
http://http.developer.nvidia.com/Cg/Cg_language.html
It's interesting that GLSL is different here:
And (&&) will only evaluate the right hand operand
if the left hand operand evaluated to true. Or ( | | ) will only evaluate the right hand operand if the left
hand operand evaluated to false
for conditional operator
Only
one of the second and third expressions is evaluated.
https://www.opengl.org/registry/doc/GLSLangSpec.4.40.pdf

In lambda calculus, can variable be expression in general?

For better understanding of functional programming, I am reading the wiki page for lambda calculus here.
The definition says:
If x is a variable and M ∈ Λ, then (λx.M) ∈ Λ
Intuitively I thought variable are / represented by single-letter id's. But since here we deal with strict math definitions, I just want to double confirm this understanding: in general, can expression be classified as variable?
e.g. if x is a variable, is expression (x + x) a variable in lambda calculus? i.e. is it ok to write (λ(x+x).M) as an lambda calculus abstraction?
(Concern is in some context this is true. e.g. Here: An expression such as 4x^3 is a variable)
No, (x + x) is no variable (indeed it's not even a expression in naive lambda calculus).
I think you mix the terms variables and expressions somehow (or want some kind of pattern-matching?).
So let's follow the core-definition of lambda-calculus and expressions:
The definition itself is not that hard (indeed you linked it yourself with the wiki-page).
It's mentioned right from the start:
you have a set of variables V: (v_1, v_2, ...) (of course you can name them as you want - it's only important that you remmber that these are considered different symbols in your calculus)
the symbols λ, ., ( and )
This is it - thats all of the "Tokens" for this grammar/calculus.
Now there are a couple of rules how you can form Expressions from these:
each Variable is a expression
Abstraction: if E is a expression and x is a Variable then (λx.E) is a expression (here x and E are templates or Metavariables - you have to fill them with some real Expression to make this an Expression!)
Application: if A and B are expressions than (A B) is a expression.
So possible expressions are:
v_50
(λv_4.v_5)
((λv_4.v_5) v_50)
....
This is all when it comes to expressions.
You see: if you don't allow (x+x) as a symbol or name for a variable from the start it can never be a variable - indeed no expression is a variable even if there are some expressions consisting only of one said variable - if you called something expression it will never be a variable (again) ;)
PS: of course there are a couple of conventions to keep the parentheses a bit down - but for a start you don't need those.

Context sensitive grammar

Noam Chomsky - formal languages - type 1 - context sensitive grammar
Does AB->BA violate the rule? I assume it does.
A -> aAB does not violate condition?
aAB->ABc violates condition?
Using the wikipedia link provided, you can answer each question if you can map your production rules to the form:
iAr -> ibr, where A is a single non-terminal, i and r are (possibly empty) strings of terminals and non-terminals, and b is a non-empty string of terminals and non-terminals.
In other words, look at each of your rules, and try to make suitable choices for i, A, r, and b.
Before we look at your questions, let's look at some hypothetical examples:
Is CRC -> CRRRRRC a valid context-sensitive rule?
Yes. I can choose i=empty, A=C, r=RC, and b=CRRRR. Note, I could have made other choices that work, too.
Is xYz -> xWzv a valid context-sensitive rule?
No. There is no choice for i, A, and r that allow a match. If I chose i=x A=Y, r=z, and b=W, that trailing v screws things up.
Is xY -> xWzv a valid context-sensitive rule?
Yes. I can choose i=x, A=Y, r=empty, and b=Wzv.
This is the scheme you should use to answer your questions. Now, let's look at those:
AB -> BA: Assume you choose either A or B to be your single non-terminal. The choice fixes i and r (one will be empty, the other will be the non-terminal you didn't choose). Is there a string of the form ibr that can match based on how you fixed i and r? In other words, can you choose the string to replace b that maps to your rule?
A -> aAB. I hope the choice of your single non-terminal on the left is intuitively obvious. This choice will again fix i and r. Does the right map to a suitable ibr form where b is a nonempty string of terminals and nonterminals?
aAB -> ABc. Again, choose A or B to be your single non-terminal. This fixes i and r. Is there a choice that allows you to choose a suitable ibr?

Ambiguous grammar?

hi
there is this question in the book that said
Given this grammer
A --> AA | (A) | epsilon
a- what it generates\
b- show that is ambiguous
now the answers that i think of is
a- adjecent paranthesis
b- it generates diffrent parse tree so its abmbiguous and i did a draw showing two scenarios .
is this right or there is a better answer ?
a is almost correct.
Grammar really generates (), ()(), ()()(), … sequences.
But due to second rule it can generate (()), ()((())), etc.
b is not correct.
This grammar is ambiguous due ot immediate left recursion: A → AA.
How to avoid left recursion: one, two.
a) Nearly right...
This grammar generates exactly the set of strings composed of balanced parenthesis. To see why is that so, let's try to make a quick demonstration.
First: Everything that goes out of your grammar is a balanced parenthesis string. Why?, simple induction:
Epsilon is a balanced (empty) parenthesis string.
if A is a balanced parenthesis string, the (A) is also balanced.
if A1 and A2 are balanced, so is A1A2 (I'm using too different identifiers just to make explicit the fact that A -> AA doesn't necessary produces the same for each A).
Second: Every set of balanced string is produced by your grammar. Let's do it by induction on the size of the string.
If the string is zero-sized, it must be Epsilon.
If not, then being N the size of the string and M the length of the shortest prefix that is balanced (note that the rest of the string is also balanced):
If M = N then you can produce that string with (A).
If M < N the you can produce it with A -> AA, the first M characters with the first A and last N - M with the last A.
In either case, you have to produce a string shorter than N characters, so by induction you can do that. QED.
For example: (()())(())
We can generate this string using exactly the idea of the demonstration.
A -> AA -> (A)A -> (AA)A -> ((A)(A))A -> (()())A -> (()())(A) -> (()())((A)) -> (()())(())
b) Of course left and right recursion is enough to say it's ambiguous, but to see why specially this grammar is ambiguous, follow the same idea for the demonstration:
It is ambiguous because you don't need to take the shortest balanced prefix. You could take the longest balanced (or in general any balanced prefix) that is not the size of the string and the demonstration (and generation) would follow the same process.
Ex: (())()()
You can chose A -> AA and generate with the first A the (()) substring, or the (())() substring.
Yes you are right.
That is what ambigious grammar means.
the problem with mbigious grammars is that if you are writing a compiler, and you want to identify each token in certain line of code (or something like that), then ambigiouity wil inerrupt you in identifying as you will have "two explainations" to that line of code.
It sounds like your approach for part B is correct, showing two independent derivations for the same string in the languages defined by the grammar.
However, I think your answer to part A needs a little work. Clearly you can use the second clause recursively to obtain strings like (((((epsilon))))), but there are other types of derivations possible using the first clause and second clause together.