Const member function vs const return type - constants

In D I can specify const functions, like in c++:
struct Person {
string name;
// these two are the same?
const string getConstName() { return name; }
string getConstName2() const { return name; }
}
It seems that the above two are the same meaning. Is it true?
If so how can I return a const string rather than define a const function?

The two are identical. Function attributes can go on either side of a function. e.g.
pure Bar foo() {...}
and
Bar foo() pure {...}
are identical. The same goes for pure, nothrow, const, etc. This is probably fine for most attributes, but it becomes quite annoying when const, immutable, or inout is involved, because they can all affect the return type. In order for those attributes to affect the return type, parens must be used. e.g.
const(Bar) foo() {...}
returns a const Bar, whereas
Bar foo const {...}
and
const Bar foo() {...}
return a mutable Bar, but the member function itself is const. In most cases what you want is probably either
Bar foo() {...}
or
const(Bar) foo() const {...}
since it's frequently the case that having a const member function forces you to return const (particularly if you're returning a member variable), but you can have any combination of const between the member function and its return type just so long as it works with what the function is doing (e.g. returning a mutable reference to a member variable doesn't work from a const function).
Now personally, I wish that putting const on the left-hand side were illegal, particularly when the excuse that all function attributes can go on either side of the function isn't really true anyway (e.g. static, public, and private don't seem to be able to go on the right-hand side), but unfortunately, that's the way it is at this point, and I doubt that it's going to change, because no one has been able to convince Walter Bright that it's a bad idea to let const go on the left.
However, it is generally considered bad practice to put const, immutable, or inout on the left-hand side of the function unless they're using parens and thus affect the return type, precisely because if they're on the left without parens, you immediately have to question whether the programmer who did it meant to modify the function or the return type. So, allowing it on the left is pretty pointless (aside perhaps for generic code, but it's still not worth allowing it IMHO).

Related

Difference between static and const variable in Dart

Check these two examples:
static const inside of class:
class SessionStorage {
static const String _keySessionExist = 'storage.key';
}
Just a const outside of the class:
const String _keySessionExist = 'storage.key';
class SessionStorage {
}
Is there any difference or implications between having a static const variable inside of a class or just having it declared as const outside of it in Dart?
Maybe the compiled code changes?
Which one is more performant?
Which one should we follow if the variable is private to the file?
The declaration for cons must be using const. You have to declare it as static const rather than just const.
static, final, and const mean entirely distinct things in Dart:
static means a member is available on the class itself instead of on instances of the class. That's all it means, and it isn't used for anything else. static modifies members.
final means single-assignment: a final variable or field must have an initializer. Once assigned a value, a final variable's value cannot be changed. final modifies variables.
const has a meaning that's a bit more complex and subtle in Dart. const modifies values. You can use it when creating collections, like const [1, 2, 3], and when constructing objects (instead of new) like const Point(2, 3). Here, const means that the object's entire deep state can be determined entirely at compile time and that the object will be frozen and completely immutable.
Const objects have a couple of interesting properties and restrictions:
They must be created from data that can be calculated at compile time. A const object does not have access to anything you would need to calculate at runtime. 1 + 2 is a valid const expression, but new DateTime.now() is not.
They are deeply, transitively immutable. If you have a final field containing a collection, that collection can still be mutable. If you have a const collection, everything in it must also be const, recursively.
They are canonicalized. This is sort of like string interning: for any given const value, a single const object will be created and re-used no matter how many times the const expression(s) are evaluated. In other words:
getConst() => const [1, 2];
main() {
var a = getConst();
var b = getConst();
print(a === b); // true
}
I think Dart does a pretty good job of keeping the semantics and the keywords nicely clear and distinct. (There was a time where const was used both for const and final. It was confusing.) The only downside is that when you want to indicate a member that is single-assignment and on the class itself, you have to use both keywords: static final.
Also:
I suggest you to have a look at this question
What is the difference between the "const" and "final" keywords in Dart?
Is there any difference or implications between having a static const variable inside of a class or just having it declared as const outside of it in Dart?
The obvious difference is that the static version must be referenced with the class name. Other than the change in name resolution, the should be the same.
Maybe the compiled code changes?
Which one is more performant?
They're both compile-time constants. There shouldn't be any difference.
Which one should we follow if the variable is private to the file?
If you want something that's private to a Dart library (which usually means the file), then prefix it with _. It doesn't matter whether it's global or static.

Does there exist REAL pass by reference in any language?

As far as I know there's no pass by reference in c and java essentially passes everything by value, there're dozens of stack overflow posts discussing about this.
Now I wonder that is there any example of REAL call by reference? Because during function call the value of all parameters (including pointers or mutable object identifiers) are always copied to local variables in callee's frame, in that sense everything surely passes by value.
Sure, there is. For example, C♯ has pass-by-reference. In order for pass-by-reference to occur, both the method parameter in the parameter list at the declaration site as well as the method call argument in the argument list at the call site must be annotated with the ref modifier. The same applies to Visual Basic.NET (here, the modifier is ByRef, I believe.)
C++ also has pass-by-reference, the modifier is &. PHP also has pass-by-reference and uses the same modifier. The same applies to E.
Rust also offers call-by-reference.
In contrast to all the languages listed above, where pass-by-value is the default and pass-by-reference has to be explicitly requested, Fortran II is a pass-by-reference language.
Now I wonder that is there any example of REAL call by reference? Because during function call the value of all parameters (including pointers or mutable object identifiers) are always copied to local variables in callee's frame, in that sense everything surely passes by value.
What you describe is pass-by-value. That's not pass-by-reference. With pass-by-reference, the reference itself is passed, not the value that is referenced.
Here is an example in C♯ that demonstrates pass-by-value of a value type, pass-by-value of a reference type, pass-by-reference of a value type, and pass-by-reference of a reference type:
struct MutableCell
{
public string value;
}
class Program
{
static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
IsCSharpPassByValue(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
}
}

When does Chapel pass by reference and when by constant?

I am looking for examples of Chapel passing by reference. This example works but it seems like bad form since I am "returning" the input. Does this waste memory? Is there an explicit way to operate on a class?
class PowerPuffGirl {
var secretIngredients: [1..0] string;
}
var bubbles = new PowerPuffGirl();
bubbles.secretIngredients.push_back("sugar");
bubbles.secretIngredients.push_back("spice");
bubbles.secretIngredients.push_back("everything nice");
writeln(bubbles.secretIngredients);
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
bubbles = kickAss(bubbles);
writeln(bubbles.secretIngredients);
And it produces the output
sugar spice everything nice
sugar spice everything nice Chemical X
What is the most efficient way to use a function to modify Bubbles?
Whether Chapel passes an argument by reference or not can be controlled by the argument intent. For example, integers normally pass by value but we can pass one by reference:
proc increment(ref x:int) { // 'ref' here is an argument intent
x += 1;
}
var x:int = 5;
increment(x);
writeln(x); // outputs 6
The way that a type passes when you don't specify an argument is known as the default intent. Chapel passes records, domains, and arrays by reference by default; but of these only arrays are modifiable inside the function. ( Records and domains pass by const ref - meaning they are passed by reference but that the function they are passed to cannot modify them. Arrays pass by ref or const ref depending upon what the function does with them - see array default intent ).
Now, to your question specifically, class instances pass by "value" by default, but Chapel considers the "value" of a class instance to be a pointer. That means that instead of allowing a field (say) to be mutated, passing a class instance by ref just means that it could be replaced with a different class instance. There isn't currently a way to say that a class instance's fields should not be modifiable in the function (other than making them to be explicitly immutable data types).
Given all of that, I don't see any inefficiencies with the code sample you provided in the question. In particular, here:
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
the argument accepting b will receive a copy of the pointer to the instance and the return b will return a copy of that pointer. The contents of the instance (in particular the secretIngredients array) will remain stored where it was and won't be copied in the process.
One more thing:
This example works but it seems like bad form since I am "returning" the input.
As I said, this isn't really a problem for class instances or integers. What about an array?
proc identity(A) {
return A;
}
var A:[1..100] int;
writeln(identity(A));
In this example, the return A in identity() actually does cause a copy of the array to be made. That copy wasn't created when passing the array in to identity(), since the array was passed by with a const ref intent. But, since the function returns something "by value" that was a reference, it's necessary to copy it as part of returning. See also arrays return by value by default in the language evolution document.
In any case, if one wants to return an array by reference, it's possible to do so with the ref or const ref return intent, e.g.:
proc refIdentity(ref arg) ref {
return arg;
}
var B:[1..10] int;
writeln(refIdentity(B));
Now there is no copy of the array and everything is just referring to the same B.
Note though that it's currently possible to write programs that return a reference to a variable that no longer exists. The compiler includes some checking in that area but it's not complete. Hopefully improvements in that area are coming soon.

Possible to check a value is a compile time constant in Rust?

There are cases when inline functions or macros will expand into a lot of code. However, when used with constants, dead branches can be optimized away.
I could add a comment in the code:
// foo arg is always a constant, dead branches will be removed
But I'd rather add some kind of static assertion to ensure this is always the case.
Is there a way in Rust to check if a value is a compile time constant?
Something like GCC's __builtin_constant_p?
If the type of the value or expression is fixed and known in advance, you can define a local constant and initialize it with the value or expression. If you don't otherwise use the constant, prefix its name with an underscore to suppress compiler warnings about the constant being unused. This only works with macros, though.
const _ASSERT_COMPILE_TIME_CONSTANT: i32 = $arg;
The nightly compiler also supports defining "const functions", i.e. functions that can be used in contexts where the compiler requires an expression that can be evaluated at compile time. The body of those functions are subject to restrictions, but call sites of const functions that don't need to be evaluated at compile time can pass expressions that cannot be evaluated at compile time as arguments, so defining a const function doesn't provide the guarantee you're asking for.
If the type of the value or expression cannot be specified in the macro, then we can't omit it, as const requires that the type be specified. However, we can use a generic const function that returns a fixed type in a const initializer!
// at the beginning of the crate
#![feature(const_fn)]
// in the macro's body
const fn _swallow<T>(_x: T) { () }
const _ASSERT_COMPILE_TIME_CONSTANT: () = _swallow($arg);
To add to #Francis answer, this is a macro that can be used to ensure constant value.
macro_rules! ensure_const_expr {
($value:expr, $t:ty) => {
{
const _IGNORE: $t = $value;
}
}
}
// in a functions body
ensure_const_expr!(some_variable, i32);
Note the extra braces are needed so multiple uses don't fail with:
error: a value named `_IGNORE` has already been defined in this block

What is the difference between immutable and const member functions?

The D programming language reference shows two examples in the Declarations and Type Qualifiers section, so these are both possible:
struct S
{
int method() const
{
//const stuff
}
}
struct S
{
int method() immutable
{
//immutable stuff
}
}
From the docs:
Const member functions are functions that are not allowed to change any part of the object through the member function's this reference.
And:
Immutable member functions are guaranteed that the object and anything referred to by the this reference is immutable.
I've found this question, but all the answers are talking about data types, not storage classes. Same goes for the D const FAQ, even though it's an interesting read.
So what is the difference between the two definitions above? Are there expressions that can replace //const stuff and be legal but not //immutable stuff?
immutable methods may only be called on immutable objects. They can work with the guarantee* that their object (this) will not change, ever.
const methods may be called on const, immutable, or mutable objects. They guarantee that they themselves will not change their object, but other references may change the object.
I'd go with const unless you have a good reason to need immutable, as const functions are callable with all three mutability storage classes.
* At the type system level, anyway. Mutating an immutable object is possible, but causes undefined behavior.