Multiple Assignment syntax in C# - c#

Ive seen the following syntax in a couple of code samples, it looks pretty obvious, but not in the context that i saw it in,
so can someone confirm
var x = 1
var y = 2
var z = 3
x = y = z
so in essence does this mean that
x and y both equal z?
tried to google this, and couldn't find the syntax, also looked in murach .net books with no luck

The assignment operator returns the value being assigned as it's result
The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result.
So
x = y = z;
Is parsed as
x = (y = z);
And this is equivalent to
y = z;
x = y;
In the end, x, and y are assigned the same value as z (in this case, 3).

This will indeed set x and y to the value of z, however to see why you can parenthesize the expression:
x = (y = z);
In this case the y = z expression will return the new value for y (in this case 3), and set x to that value.
This works for very long expressions too:
x = y = z = a = b
x = (y = (z = (a = b)))
Where x, y, z and a will be set to the value of b.
EDIT:
Also remember the order of precedence of operators when using this method of reading into a long expression, while its not a good practice to create huge chained statements you do sometimes see it in code online, another (and better) way you can use to read confusing statements like this is to think of the syntax tree that is generated.

Ehm, yes that is correct :).
x, y and x will all be 3 as you can assign values like that.
you can make the chain as long as you like too.
a = b = c = d;
all preceding values would be the value of d

Related

Addition Assignment in C and C#?

So, I'm learning the code for the SplitMix64 generator and came upon this part here:
uint64_t z = (x += 0x9e3779b97f4a7c15);
Not being a C programmer, I don't really understand this construct.
Does the above mean z gets assigned value of x after x is incremented, like so:
x += 0x9e3779b97f4a7c15;
z = x;
Or does that mean z gets the value of x before x is incremented, like so:
z = x;
x += 0x9e3779b97f4a7c15;
And also, does the same behavior happen in C# ?
z gets assigned value of x after x is incremented. Think of it like this:
z = (x = x + 0x9e3779b97f4a7c15);
The return value of an assignment is always the value of the left-hand side of the assignment after the assignment is completed.

using float + Lambda Expressions C#

var distances = new Dictionary<char, float>();
var nodes = new List<char>();
I have this line to find the smallest distance
nodes.Sort((x, y) => distances[x] - distances[y]);
When I use int it works well, but when I used float I got a message
cannot convert lambda expression to type
'System.Collections.Generic.IComparer' because it is not a
delegate type
Do you have an idea?
First off, your original program is a bad programming practice when the values are integers. It works for chars, but I would avoid this bad programming practice.
The delegate you pass to the sort function must have a number of properties; in particular it must return a negative int if x is smaller than y, a positive int if x is greater than y, and zero if they are equal. Your original lambda does not do that for integer values. (See if you can find two integers x and y such that x is smaller than y but x - y is positive.)
The delegate must also impose a total order. In a total order:
Transitivity must hold. If A == B and B == C then A must equal C. If A < B and B < C then A must be smaller than C. And so on.
It must be antisymmetric. That is, if A < B then B > A, and so on.
Subtraction does not meet these conditions in integers. The correct code is to actually write a comparison.
nodes.Sort((x, y) => x < y ? -1 : (x > y ? 1 : 0));
That then works well for chars and floats, provided there are no NaNs. If you have NaNs then you need to do extra work to impose a total order.
I would also point out that this ordinal comparison on chars is usually not the comparison you want. Sure, this will correctly note that e is smaller than z, but simple ordinal comparison also says that z is smaller than é, which is likely not what you want. Character ordering depends on culture; are you sure you want to order by the order that the Unicode committee just happened to impose?
For more on this topic see my series of articles; it begins here:
http://ericlippert.com/2011/01/20/bad-comparisons-part-one/
You can't convert your lambda expression into a Comparison<char> (which is what you want) because it returns a float - you've effectively got a Func<char, char, float> there, whereas Comparison<char> is closer to Func<char, char, int>.
The simplest approach is to use float.CompareTo:
nodes.Sort((x, y) => distances[x].CompareTo(distances[y]));
Or if you don't need to sort in-place, you could use LINQ:
var sorted = nodes.OrderBy(x => distances[x]);
Reformulate the lambda expression as follows.
nodes.Sort((x, y) =>
{
float Result = distances[x] - distances[y];
if ( Result > 0.0f )
return 1;
else if ( Result < 0.0f )
return -1;
else
return 0;
});

What does -Convert.ToSingle do?

I tried to search on Google and Bing this but both return zero results....
What does it mean when you put a hyphen in front of convert?
-Convert.ToSingle
It's just the - operator, applied to the result of calling Convert.ToSingle(...).
So for example when used as a unary operator:
double x = 10.52123;
float y = -Convert.ToSingle(x);
is equivalent to:
double x = 10.52123;
float tmp = Convert.ToSingle(x);
float y = -tmp;
Or when used as a binary operator:
double x = 10.52123;
float y = 10-Convert.ToSingle(x);
is equivalent to:
double x = 10.52123;
float tmp = Convert.ToSingle(x);
float y = 10 - tmp;
I'd say it's shorthand for
-1 * Convert.ToSingle(...)
Since the method returns a Single (which is a number, so it's subject to arithmetic operators)
The - operator is an unary or a binary operator. The result of a unary - operation on a numeric type is the numeric negation of the operand. For an example
int x = 5;
float b = -Convert.ToSingle(x);
Console.WriteLine(b);
Here the output should be -5. In the absence of unary operator. The output value should have been just 5
Just think about the C# syntax: what means a minus at the right of an assignment? In every language (or almost, don't talk to me about Brainfuck & co), it means change the sign of the number which following.
So the operation after this minus has to return a Number. Good, that's what Convert.ToSingle does, which returns a float.
float x = - Convert.ToSingle(42);
^ ^^^^^^^^^^^^^^^^
^ function call
minus operation
// equivalent to:
float x = 0 - Convert.ToSingle(42);
^^^
0 minus the result

Have I implemented Y-combinator using C# dynamic, and if I haven't, what is it?

My brain seems to be in masochistic mode, so after being drowned in this, this and this, it wanted to mess around with some DIY in C#.
I came up with the following, which I don't think is the Y-combinator, but it does seem to manage to make a non-recursive function recursive, without referring to itself:
Func<Func<dynamic, dynamic>, Func<dynamic, dynamic>> Y = x => x(x);
So given these:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(self)(n - 1);
Func<dynamic, Func<dynamic, dynamic>> fib =
self => n => n < 2 ? n : self(self)(n-1) + self(self)(n-2);
We can generate these:
Func<dynamic, dynamic> Fact = Y(fact);
Func<dynamic, dynamic> Fib = Y(fib);
Enumerable.Range(0, 10)
.ToList()
.ForEach(i => Console.WriteLine("Fact({0})={1}", i, Fact(i)));
Enumerable.Range(0, 10)
.ToList()
.ForEach(i => Console.WriteLine("Fib({0})={1}", i, Fib(i)));
No, that's not the Y combinator; you're only halfway there. You still need to factor out the self-application within the "seed" functions you're applying it to. That is, instead of this:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(self)(n - 1);
you should have this:
Func<dynamic, Func<dynamic, dynamic>> fact =
self => n => n == 0 ? 1 : n * self(n - 1);
Note the single occurrence of self in the second definition as opposed to the two occurrences in the first definition.
(edited to add:) BTW, since your use of C# simulates the lambda calculus with call-by-value evaluation, the fixed-point combinator you want is the one often called Z, not Y
(edited again to elaborate:) The equation that describes Y is this (see the wikipedia page for the derivation):
Y g = g (Y g)
But in most practical programming languages, you evaluate the argument of a function before you call the function. In the programming languages community, that's called call-by-value evaluation (not to be confused with the way C/C++/Fortran/etc programmers distinguish "call by value" vs "call by reference" vs "call by copy-restore", etc).
But if we did that, we'd get
Y g = g (Y g) = g (g (Y g)) = g (g (g (Y g))) = ...
That is, we'd spend all of our time constructing the recursive function and never get around to applying it.
In call-by-name evaluation, on the other hand, you apply a function, here g, to the unevaluated argument expression, here (Y g). But if g is like fact, it's waiting for another argument before it does anything. So we would wait for the second argument to g before trying to evaluate (Y g) further---and depending on what the function does (ie, if it has a base case), we might not need to evaluate (Y g) at all. That's why Y works for call-by-name evaluation.
The fix for call-by-value is to change the equation. Instead of Y g = g (Y g), we want something like the following equation instead:
Z g = g (λx. (Z g) x)
(I think I got the equation right, or close to right. You can calculate it out and see if it fits with the definition of Z.)
One way to think of this is instead of computing "the whole recursive function" and handing it to g, we hand it a function that will compute the recursive function a little bit at a time---and only when we actually need a bit more of it so we can apply it to an argument (x).

int x = 10; x += x--; in .Net - Why?

int x = 10;
x += x--;
In C#/.Net, why does it equal what it equals? (I'm purposely leaving the answer out so you can guess and see if you're right)
Look at this statement:
x += x--;
This is equivalent to:
x = x + x--;
Which is equivalent to:
int a1 = x; // a1 = 10, x = 10
int a2 = x--; // a2 = 10, x = 9
x = a1 + a2; // x = 20
So x is 20 afterwards - and that's guaranteed by the spec.
What's also pretty much guaranteed, although not by the spec, is that anyone using such code will be attacked by their colleagues. Yes, it's good that the result is predictable. No, it's not good to use that kind of code.
Jon is of course right.
A good way to think about this is to remember:
1) subexpressions are always evaluated left to right. Period. Evaluation of a subexpression may induce a side effect.
2) execution of operators is always done in the order indicated by parentheses, precedence and associativity. Execution of operators may induce a side effect.
The "x" to the left of the += is the leftmost subexpression, and therefore rule (1) applies. Its value is computed first -- 10.
The x-- to the right of the += is the next one in left-to-right order, so it is evaluated next. The value of x-- is 10, and the side effect is that x becomes 9. This is as it should be, because -- is of higher precedence than +=, so its side effect runs first.
Finally, the side effect of += runs last. The two operands were 10 and 10, so the result is to assign 20 to x.
I get questions about this all the time. Remember, the rules are very straightforward: subexpressions left-to-right, operators in precedence order, period.
In particular, note that the commonly-stated reasoning "the -- operator is postfix and therefore runs after everything else" is incorrect reasoning. I discuss why that is incorrect in the articles below.
Here are some articles I've written on this subject:
http://blogs.msdn.com/ericlippert/archive/tags/precedence/default.aspx
20; the "--" doesn't happen until after everything gets evaluated, and that value is overwritten by the left-hand side of the equals.
From the specs 7.13.2
If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
So your statement is equivalent to x = x + x--; which is evaluated in left-to-right order and gives the answer 20.
Note that there is also a difference between --x and x-- here. If you had written x += --x; this would be equivalent to x = x + --x; then you would get 19. This is because the value of x is decremented and the resulting value is used in the expression (unlike x-- where the original value of x is used in the expression).
This expression x = x + --x + x will give 28 because the third timefourth time (see comments) x is evaluated it is 9.
The answer is 20. And Tom, you really aren't as surprised as your questions seems to imply, right? And to those of you who are assuming the answer is 19 - I think you're confused with x += --x;

Categories