Smalltalk: what's the difference between "&" and "and:" - smalltalk

I just started learning Smalltalk at uni.
I would like to know the difference between the messages & and and: (just like | and or:)

Welcome to Smalltalk! You are asking a good question that points out some subtle differences in expressions that are outside or inside blocks.
The '&' message is a "binary" message so takes only one argument. In this case the argument is expected to be a Boolean or an expression that evaluates to a Boolean. Most importantly for our purposes in this comparison, the expression will always be evaluated.
The 'and:' message is a "keyword" message and also takes only one argument. But in this case the argument is expected to be a Block that if later sent the 'value' message would return a Boolean. So, for our purposes in this comparison, the Block will not always be evaluated. (The difference between the binary and keyword messages does not matter for this question.)
The option to not evaluate the argument allows Short-circuit evaluation in which knowing the left-hand side often allows us to avoid a (possibly expensive) calculation of the right-hand side. So, if the left ("receiver") is false, there is nothing to be gained by evaluating the right-hand side.
So, consider the following:
self cheapFalse & self expensiveTrue. "an expensive way to get false"
self cheapFalse and: [self expensiveTrue]. "a cheap way to get false"

One obvious difference is that and: is a keyword message thus you can write something like
a > b and: [b < c]
while with & you would need parentheses in this expression:
a > b & (b < c)
because all the binary messages (+, -, >, <, &, |) have the same precedence.
More importantly, and: and or: expect blocks while & and | expect values. This means that you can write
this shouldRedraw and: [ obj stateChanged ]
where obj stateChanged will be executed only if this shouldRedraw is true. This is useful if you want to optimize your code and avoid computing something which is not needed at the moment.

Related

Cannot assign an if statement to a variable

The problem here is that I do not understand well the difference between statements and blocks in control flow.
Looking the ternary operator I can use it to assign a variable. But this is an operator, so it is like applying a function--isn't it?
> my $variable = True ?? 34 !! 42;
34
since in the raku documentation says:
if documentation
if
To conditionally run a block of code, use an if followed by a
condition. The condition, an expression, will be evaluated immediately
after the statement before the if finishes. The block attached to the
condition will only be evaluated if the condition means True when
coerced to Bool. Unlike some languages the condition does not have to
be parenthesized, instead the { and } around the block are mandatory:
do documentation
do
The simplest way to run a block where it cannot be a stand-alone statement is by writing do before it:
so this should work in both cases:
> my $variable = do {34};
34
> my $variable = if True {34;} else {43;}
===SORRY!===
Word 'if' interpreted as a listop; please use 'do if' to introduce the statement control word
------> my $variable = if⏏ True {34;} else {43;}
Unexpected block in infix position (two terms in a row)
------> my $variable = if True⏏ {34;} else {43;}
as said in the error I need to add the do:
> my $variable = do if True {34;} else {43;}
34
So the if really does not run the block...or what is the real problem here?
TL;DR: The actual difference is between statement and expression, not statement and block. do is a statement prefix that creates expressions.
if actually creates a statement (anything that is run in Raku is), however, what it's not is an expression. do is a statement prefix, and what it does is turn statements into expressions.
However, if is not really a first-class function that you can assign to a variable or handle around. Whenever you find pieces of syntax such as that one (or for, for instance), you need to prefix them with do to "expressionify" them.
say &say.^name;# OUTPUT: «Sub␤» say &do.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>␤Undeclared routine:␤...
say &if.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>␤Undeclared routine:␤ if used at line 1␤␤»
So if, by itself, does not create a block, it does not create an expression, it simply creates a statement. You need to precede it with do if you want it to actually turn it into a expression. It does run the block that's behind it, however.
Let's go back to the original question, statements and blocks. Blocks are objects, first-class citizens. You can use them, apply them, pass them around.
my &ifs = { if $_ {34} else {43}};
ifs(True).say; # OUTPUT: «34␤»
Statements are throwaway blocks you simply run. In some cases, they are also expressions: they yield a result which, then, you can assign.
my &ifs = { if $_ {34} else {43}};
my $result = ifs(True).say; # OUTPUT: «34␤»
say $result; # OUTPUT: «True␤»
The ifs(True).say statement prints to output, it also produces a result that can be assigned. All three lines are also statements, and as a matter of fact, expressions too.
Some control structures, however, do not create expressions.
Some others do; for creates a expression; while does not.
if is an example of this. They don't produce a result. You use them for the side effects: running a statement (if true) or another (if not). You might turn them into a block, as above, and pass them around. Or you can just precede them with do and make them produce a throwaway result, which you can then use.
So it will very much depend on your actual use case. You can surround the if statement with curly braces and create a block; or you can simply use the result creating an expression. Or you might want to use it just for the side effects, doing nothing.

What is the “and” and “or” Operator in Kotlin?

I used an || operator within the Kotlin IDEA but was throwing an error. This confused me, one of the first queries when searching google was a closed stack overflow thread with a snarky "answer" comment which wasn't helpful.
The first query in google hit is some function "or" gibberish.
My code:
if(inputAmount >= 0 || inputAmount = -99)
I understand what is "wrong". there was some logic errors the second part of the "if" statement should have been inputAmount == -99. In my case, the code needed to further be adjusted because of the actual type that was being used.
if(inputAmount >= 0.0 || inputAmount.toInt() == -99)
This appears to be different then other languages in that other languages just simply allow you to have your "logic" error with the "inputAmount = -99". So the '||' operator is allowed and is similar to most other languages.
So first step if encounter this error is to make sure your logic is correct. (check)
infix functions > sense according to the documentation "or" and "and" are infix functions that don't use the short circuit, is it technically wrong to call the "||" operator an "or" operator and should be called logical 'or'?
when referring to the infix 'or' how do people refer to that in Kotlin?
in boolean logic takes statements. A=b is a statement that is always true
No, it isn't. In C, C++ and Java it's an expression, and its value is the value of b. If b is false, it's false, if b is 10, it's 10. And you really don't want to confuse "statements" in programming languages with "statements" in logic; they are entirely different things.
Separately, C and C++ (but not Java) allow || to work on all integral types, and not just booleans (because they didn't originally have booleans as a separate type).
when referring to the infix function 'or' how do Kotlin folk typically refer to that?
Bitwise or for integral types, and I've never actually seen anyone use non-short-circuiting or on booleans, but if I had to I'd call it... well, non-short-circuiting or.
is it technically wrong to call the "||" operator an "or" operator and should be called logical 'or'
Both || and or (on booleans) are "logical 'or'" and I don't see any problem with calling them simply 'or'. If you need to distinguish use short-circuiting vs non-short-circuiting. But again, I've never actually ran into a use of the non-short-circuiting version.

What (if anything) does ++ do in VB.NET?

I'm fairly new to Visual Basic (my background is mostly C#) so I only recently found out that ++i is not the same thing as i+=1 in VB.NET. However, my VB.NET code still compiles when I pass ++i as a parameter, even though it doesn't increment the variable:
++i 'doesn't compile
i++ 'doesn't compile
Foobar(i++) 'doesn't compile
Foobar(++i) 'compiles, but doesn't increment i
The fact that the last statement above doesn't cause an error leads me to wonder if ++ actually does mean something in VB.NET, just not what I thought it meant at first. If it doesn't, is there some other reason it isn't causing an error?
It is just the unary version of the + operator (see docs) applied twice.
Foobar(++i)
Foobar(+(+i))
Foobar(+(+(i)))
' These are all the same
For numerical values, the unary + (i.e. the + operator without second operand) does nothing:
If expression2 is absent, the + operator is the unary identity operator for the unchanged value of an expression.
However, it is not entirely clear from the docs what it will do to non-numeric values. The docs explain various cases with two operands, which all don't seem to apply here.
There is even one sentence that sounds like it could be applied, but it does not do what it says if used with unary +:
If either Object expression evaluates to Nothing or DBNull, the + operator treats it as a String with a value of "".
So you would expect that +Nothing gives "" as well, but it gives 0 instead. In fact, it appears that the unary + converts non-numerical types to Double, including strings for which + would otherwise mean concatenation (for example +"1.234" gives 1.234, and +"Hello" gives an error that this string cannot be converted to Double - and with Option Strict On, you can't convert any string implicitly anyway). It seems to behave more like a binary + with 0.0 as first operand.
You can also overload the unary + separately from the binary + and give it a different meaning entirely*. (Or do the opposite - make it do nothing even on a non-numeric type, such as what TimeSpan does - it returns the original timespan again when unary + is applied on it, and not a Double.)
*: Which probably is not such a good idea though. When overloading an operator, the meaning of it should always be intuitive.
There is no ++ operator in VB. The + unary operator is just like the - unary operator applied to a number. Numbers are positive by default but, just as you can explicitly make a number negative by prefixing it with a - operator, you can make it explicitly positive by prefixing it with a + operator. You can use as many + operators as you like. Similarly, you can use as many - operators as you like. The difference is that + operators don't change the value where - operators do.
In C-based languages, assignments actually return a value where they don't in VB. In C#, you can do this:
i += 1
and it will get the value of i, add 1 to it, assign the result back to i and then return that result, so you can use that expression where a value is expected. In VB, it does all the same things up to the assignment but it does not return a value, so you cannot use that expression where a value is expected.
In C-based languages, where you place the ++ operator makes a difference. The expression:
++i
increments i and returns the final value, whereas this expression:
i++
increments i and returns the original value. That's why some argue that the C++ language should actually be named ++C.

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

How to suppress VB's "Iteration variable shouldn't been used in lambda expression"

I'm working with LINQ in VB.NET and sometimes I get to a query like
For i = 0 To 10
Dim num = (From n In numbers Where n Mod i = 0 Select n).First()
Next
and then it comes the warning "Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it the value of the iteration variable."
I know it's not a good practice to use the iteration variable in the lambda expression, because lambda expressions are evaluated only when needed. (This question is about that)
Now my question is, how to suppress this warning in cases where the expression is evaluated in-place, with constructions like First(), Single(), ToList(), etc. (It's only a warning, but i like my code clean.)
(Declaring a local variable and passing the iteration variable to it is an option, but I'm looking for a clean solution.)
In this particular case where the lambda is evaluated immediately, then you can safely eliminate the warning by moving the declaration of the iteration variable outside the for loop.
Dim i = 0
For i = 0 To 10
...
I do want to stress though that this only works if the lambda does not escape the for loop (true for your scenario).
Also here is a detailed link to an article I wrote on this warning (why it exists, how to avoid it, etc ...)
http://blogs.msdn.com/b/jaredpar/archive/2007/07/26/closures-in-vb-part-5-looping.aspx