Why is it valid to have a reference of the result of string adding if c++17? - string

In c++17, it is valid like
string s = "asd";
string &ss = "asd" + s; --> here
Now I have two doubts:
1.Why reference of ss is valid? What is it reference to? An anonymous variable of the result of
"asd" + s?But is it valid to reference to an anonymous variable?
2.Why "asd" could directly add s?Wouldn't write it as string("asd") + s like before?Why?

Related

Dart Errors Unhandled

I'm new in Dart.
In the code bellow exception ccures :
void main(){
dynamic alpha = "String";
dynamic beta = 12;
print("Your code is so "+beta+" "+alpha);
}
Error :
type 'int' is not a subtype of type 'String'
Why when we use dynamic keyword to insist on telling the compiler for doing this job it's still got error? "combining string and other types"
When you declare your variable dynamic it does not mean the variable won't have a runtime type. It means the type can change:
dynamic alpha = 'String';
print(alpha.runtimeType); // prints String
alpha = 1;
print(alpha.runtimeType); // prints int
You can't do that with var. With var the compiler will infer the type, and it's fixed after that:
var beta = 'String';
print(beta.runtimeType);
beta = 1; // error: A value of type 'int' can't be assigned to a variable of type 'String'.
print(beta.runtimeType);
When you try to do "Your code is so " + beta you use the + operator of your String with an int paramter: beta.
You can see in the documentation that the + operator of String only accepts a String:
String operator +(String other);
If you wanted to use that operator you would have to convert the int variable to String:
print('Your code is so ' + beta.toString() + ' ' + alpha);
That's not remarkably beautiful. Instead of concatenation try string interpolation:
print('Your code is so $beta $alpha');

Why am I getting, "Cannot implicitly convert type 'void' to 'object'" with this code (EPPlus)?

I was using this code to populate a cell in a spreadsheet using EPPlus:
using (var footerMonth1Cell = prodUsageWorksheet.Cells[columnFooterRow, MONTH1_COL])
{
footerMonth1Cell.Value = monthsTruncatedYears[0];
footerMonth1Cell.Style.Font.Size = DATA_FONT_SIZE;
footerMonth1Cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
}
It was working fine, I thought, but a user complained that it was producing "green triangles" in the cells. "monthsTruncatedYears" is a generic list of string.
So I added this helper function:
public static void SetValueIntOrStr(this ExcelRangeBase range, object value)
{
string strVal = value.ToString();
if (!String.IsNullOrEmpty(strVal))
{
double dVal;
int iVal;
if (double.TryParse(strVal, out dVal))
range.Value = dVal;
else if (Int32.TryParse(strVal, out iVal))
range.Value = iVal;
else
range.Value = strVal;
}
else
range.Value = null;
}
...which I got from here, and then tried to refactor the original code to call that helper function like so:
using (var footerMonth1Cell = prodUsageWorksheet.Cells[columnFooterRow, MONTH1_COL])
{
footerMonth1Cell.Value = SetValueIntOrStr(footerMonth1Cell, monthsTruncatedYears[0]);
footerMonth1Cell.Style.Font.Size = DATA_FONT_SIZE;
footerMonth1Cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Right;
}
However, it won't compile, telling me, "Cannot implicitly convert type 'void' to 'object'"
Since the second arg passed to SetValueIntOrStr(), namely "value", is of type object, I assume that is the problem. So why does the compiler apparently view monthsTruncatedYears[0] as being void? In the legacy code I assigned it as the value to the cell, and it wasn't void at that time, so...?!?
I tried casting the second arg to object like so:
footerMonth1Cell.Value = ReportRunnerConstsAndUtils.SetValueIntOrStr(footerMonth1Cell, object(monthsTruncatedYears[0]));
...but that won't compute, either, with "Invalid expression term 'object'"
...and this similar attempt:
footerMonth1Cell.Value = ReportRunnerConstsAndUtils.SetValueDoubleOrIntOrStr(footerMonth1Cell, monthsTruncatedYears[0] as object);
...elicits, "Cannot implicitly convert type 'void' to 'object'"
Note that the helper method is actually misnamed in the borrowed code; instead of "SetValueIntOrStr" it should be "SetValueDoubleOrIntOrStr"
The problem is the line
footerMonth1Cell.Value = SetValueIntOrStr(footerMonth1Cell, monthsTruncatedYears[0]);
SetValueIntOrStr does not return any value (void) and therefore cannot be used to assign a value to the footerMonth1Cell.Value.
This would be valid code because the Value property is already changed inside the function:
SetValueIntOrStr(footerMonth1Cell, monthsTruncatedYears[0]);

Why does the mutable StringBuilder behave like the immutable string when a reference is changed?

The "C# 4.0 IN A NUTSHELL" 4th edition book by the Albaharis states on page 249:
". . . calling object.ReferenceEquals guarantees normal referential equality."
So, I decided to test this out.
First I tried value types like this.
int aa1 = 5;
int aa2 = aa1;
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And just as I expected, the result was false:
object.ReferenceEquals(aa1, aa2) is: False
Life was good.
Then I tried a mutable reference type like this.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And just as I expected, the result was true
object.ReferenceEquals(sblr1, sblr2) is: True
Life was still good.
Then I figured that since it is a mutable reference type, then if I change one variable to null, then both should be null.
So I tried the following.
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr1 = null;
MessageBox.Show("object.ReferenceEquals(sblr1,sblr2) is: " + object.ReferenceEquals(sblr1, sblr2));
And I expected them to both be null.
But the result I got was False:
object.ReferenceEquals(sblr1, sblr2) is: False
Now life was not so good.
I thought that if it overrode the memory location of sblr1, then it would be overriding the memory location of sblr2 also.
Then I thought that maybe they were pointing to two different nulls, so I tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
System.Text.StringBuilder sblr2 = sblr1;
sblr2 = null;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2);
But here, only one was pointing to a null like this.
sblr1 == aaa and sblr2 ==
Only one was null.
It was displaying the behavior I'd expect from an immutable reference type like a string object.
With a string object, I can do something like this:
string aa1 = "aaX";
string aa2 = "aaX";
MessageBox.Show("object.ReferenceEquals(aa1,aa2) is: " + object.ReferenceEquals(aa1, aa2));
And they will both reference the same thing like this.
object.ReferenceEquals(aa1, aa2) is: True
because "aaX" only gets written to the assembly once.
But if I do this:
string aa1 = "aaX";
string aa2 = "aaX";
aa1 = null;
MessageBox.Show("After aa1 is null(" + aa1 + "), then aa2 is: " + aa2);
Then they point to different things like this:
After aa1 is null (), then aa2 is: aaX
That's because string objects are immutable. The memory location doesn't get overriden. Rather, the variable points to a different location in Heap memory where the new value exists.
Changing aa1 to null in the above example means that aa1 will point to a different location on the Heap memory.
Why then is the mutable reference type behaving just the same as the immutable reference type?
Edit 4:03PM and 4:08
I've recently tried this:
System.Text.StringBuilder sblr1 = new System.Text.StringBuilder();
sblr1.Append("aaa");
// sblr1 and sblr2 should now both point to the same location on the Heap that has "aaa".
System.Text.StringBuilder sblr2 = sblr1;
System.Text.StringBuilder sblr3 = new System.Text.StringBuilder();
sblr3.Append("bbb");
sblr1 = sblr3;
MessageBox.Show("sblr1 == " + sblr1 + " and sblr2 == " + sblr2 + " and sblr3 == " + sblr3);
Which gave me:
sblr1 == bbb and sblr2 == aaa and sblr3 == bbb
That's more like the result I was expecting.
I see now, thanks to the comments, that I abscent mindedly expected null to act like a memory location.
I thought that if it overrode the memory location of sblr1, then it would be overriding the memory location of sblr2 also.
This is your misunderstanding.
When you write this:
System.Text.StringBuilder sblr2 = sblr1;
You're assigning the sblr2 variable to be a reference to the same instance of StringBuilder as the one pointed to by sblr1. The two variables now point to the same reference.
You then write:
sblr1 = null;
This changes the sblr1 variable to now be a null reference. You didn't change the instance in memory at all.
This has nothing to do with whether the reference is a mutable type or not. You're changing the variables, not the instance which they are referencing.
As for your string example:
That's because string objects are immutable. The memory location doesn't get overridden
This actually is not true. The fact that you're setting one string variable to null doesn't really have anything to do with the string being immutable. That's a separate concern.
Why then is the mutable reference type behaving just the same as the immutable reference type?
The behavior you're seeing has nothing to do with mutability. It is the standard behavior for all reference types (whether immutable or mutable). Mutability is a different issue.
The main issue with mutability is this:
Suppose you have a class, like so:
class Foo
{
public int Bar { get; set; }
}
If you write this:
Foo a = new Foo();
a.Bar = 42;
Foo b = a;
b.Bar = 54;
Console.WriteLine(a.Bar); // Will print 54, since you've changed the same mutable object
With immutable types, this can't happen, since you can't change Bar - instead, if you make an immutable class:
class Baz
{
public Baz(int bar) { this.Bar = bar; }
public int Bar { get; private set; }
}
You would need to write:
Baz a = new Baz(42);
Baz b = a;
// This isn't legal now:
// b.Bar = 54;
// So you'd write:
b = new Baz(54); // Creates a new reference
Alternatively, you could make the class return a new reference on a "change" operation, ie:
class Baz
{
public Baz(int bar) { this.Bar = bar; }
public int Bar { get; private set; }
public Baz Alter(int newValue) { return new Baz(newValue); } // May copy other data from "this"
}
Then when you'd write:
Baz a = new Baz(42);
Baz b = a.Alter(54); // b is now a new instance
This is what happens with string - all of the methods return a new instance, since a string is immutable, so you can never "change" the existing copy.
This has nothing to do with mutability. The rules involved here are the same for all reference types. A non-ref non-out variable (or member, or slot in a collection) of a reference type is a reference (duh). That means it refers to some object. It does not refer to another reference, or to a location where another reference is (e.g. to a variable). When you assign to a variable (or member, or slot in a collection), you change what reference is in that place; you do not overwrite any part of any object (except, of course, the member you assign to, if it's a member).
In your code, there are two variables srbl1 and srbl2, each of which stores a reference to the same string builder object. Assigning to either changes overwrites one of those reference (e.g. with null, or with a reference to a different object).
Changing a reference is just changing what something refers to. It doesn't change the object itself.
One way to look at it is to imagine an array of integers:
int[] foo = new int[] {0, 1, 2, 3, 4, 5};
You can create two indexes that refer to items in the array:
int ix = 1;
int iy = ix;
And then foo[ix] == foo[iy].
If you then write foo[ix] = 42, then foo[ix] == foo[iy] is still true because you changed the value that the indexes referred to.
But if you change the index so that ix = 3, then ix and iy are referring to different things.
Reference types work exactly the same way.
When you write sblr1 = new StringBuilder(), you've created a new StringBuilder object instance and made sblr1 point to it. If you then write sblr2 = sblr1, you're just making sblr2 point to the same thing. And then sblr1 = null just says, "sblr1 isn't pointing to anything anymore." It doesn't actually affect the item it refers to, just as changing the index to an array doesn't affect the value of the item being indexed.

How can I define a Dictionary with string key in AS3?

How can I define a Dictionary with string key in AS3? and how to do read operation?
for example:
var Dic:Dictionary = new Dictionary();
Dic["Exhausted"] = "He who talks more is sooner exhausted, please keep smiling :)";
String str = str.substring(8,str.length-1); // == str = "Exhausted";
trace('Dic[' + str + '] = ' + Dic[str]);
the output is Dic[Exhausted] = undefined???!!
why?
I think you have a syntax error on this line:
String str = str.substring(8,str.length-1);
If you just use this :
var d:Dictionary = new Dictionary();
d["Exhausted"] = "He who talks more is sooner exhausted, please keep smiling :)";
trace(d["Exhausted"]);
You can see it's all fine.
The problem with var str:String = str.substring(8,str.length-1); is that you define a String named "str": var str:String, but you assign a value which is the result of the substring() method called on str and of cours str does not exist yet when you call substring on it.
Not sure if this makes sense: you define str as the result of applying substring on str.
The actionscript compiler should've complained btw:
expected a definition keyword (such as function) after attribute String, not str.
Just a wild guess, but would you happen to have str defined somewhere else in your code and you just update str again using str before using it ? In which case, you shouldn't redefine, str, you should simply assign a new value.
e.g.
//somewhere else
var str:String = "12345678Exhausted";
//further down
var Dic:Dictionary = new Dictionary();
Dic["Exhausted"] = "He who talks more is sooner exhausted, please keep smiling :)";
str = str.substring(8,str.length); // == str = "Exhausted";
trace('Dic[' + str + '] = ' + Dic[str]);
Also, another syntax error is how you define str:
should be var str:String (as2/as3 syntax), not String str(java/c++/etc. style)

Default Value for Closure Parameters in Groovy

Is there some way to use default parameters values with closures in Groovy?
This is what I tried so far:
class Persona {
String name
Persona( String name ) {
this.name = name
}
String salute( String salute = "Hola" ) {
salute + ' ' + this.name
}
}
Persona.metaClass.salute2 = {
String salute = "Hola" ->
salute + ' ' + name
}
p = new Persona( 'john' )
print p.salute()
print p.salute2()
which gives me the following result:
Hola johnnull john
It seems like the call to salute2() is ignoring the salute default value "Hola".
Your code is working fine as you expected with Groovy 1.6-RC2.
I don't believe Groovy has a direct way to do what you're asking.
The way to simulate this is for "salute2" to be a closure that defines another closure inside it (the one that currently concatenates the "salute" and "name" variables, where "salute" is a closure parameter)), and then calls that closure, sending the value "Hola".

Resources