How do I choose how to pass a variable by value or reference using Crystal ?
Exemple : I would like to pass a Struct by reference and not by Value ( the documentation explains that it is passed by Value while classes are passed by reference ).
You can't choose. You just need to keep in mind that object which is a Value passed by value, other objects passed by reference.
Struct is a Value and passed by value. You should prefer using structs for immutable data types. However, mutable structs are still allowed in Crystal and actually this example demonstrates how to mutate it using a method. In short:
struct Mutable
property value
def initialize(#value : Int32)
end
end
def change(mutable)
mutable.value = 2
mutable
end
mut = Mutable.new 1
mut = change(mut)
mut.value # => 2
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What's the difference between passing by reference vs. passing by value?
I read that in C arguments are passed by value, but what's is the difference between passing arguments by value (like in C) or by refencence (like C++ - C#)?
What's the difference between a pointer and a reference?
void with_ptr(int *i)
{ *i = 0; }
void with_ref(int &i)
{ i = 0; }
In these cases are modified both value? If yes, why C++ allows to pass arguments by reference? I think it is not clear inside the function that the i value could be modified.
what's is the difference between passing arguments by value or by reference
If you pass by value, changes to the variable will be local to the function, since the value is copied when calling the function. Modifications to reference arguments will propagate to the original value.
What's the difference between a pointer and a reference?
The difference is largely syntactic, as you have seen in your code. Furthermore, a pointer can be reassigned to point to something else (unless it’s declared const), while a reference can’t; instead, assigning to a reference is going to assign to the referenced value.
I think it is not clear inside the function that the i value could be modified.
On the contrary, it’s absolutely clear: the function signature tells you so.
There’s actually a case to be made that it’s not clear outside the function. That’s why original versions of C# for instance mandated that you explicitly annotate any by-reference calling with ref (i.e. f(ref x) instead of plain f(x)). This would be similar to calling a function in C++ using f(&x) to make it clear that a pointer is passed.
But in recent versions of C#, the use of ref for calling was made optional since it didn’t confer enough of an advantage after all.
Consider this:
1) Passing by reference provides more simple element access i instead of *i
2) Generally you cannot pass null reference to a method, but can pass a null pointer
3) You can't change the address of reference, but can change it for a pointer(although, as pointer itself passed by value, this change will be discarded upon function exit)
Hope, this helped a bit
Actually, in the first case, you can't modify the argument. The pointer itself is immutable, you can only modify the value it points to.
If yes, why C++ allows to pass arguments by reference?
Because pointers can very easily be miss-used. References should almost always be prefered. For your case, what if you pass a NULL to with_ptr? You'll get undefined behavior, which is not possible if you use with_ref.
I think it is not clear inside the function that the i value could be modified.
It is very clear. If you see a function that takes a parameter by non-const reference, you can assume it will be changed.
I think that a method can only change an argument's value, if this is passed by reference. If you pass a argument by value in a method, then whatever change you make to its value, this will no be available in the parent method.
As far as I know, I think the reference is safer to use in a sense that it can't be modified (always points to the same thing), and should be initialized if it's a local variable. Pointer, however, can be change to point to somewhere else.
int x = 10;
int &y = x;
int *p = &x;
p++; //Legal if you know what's next
y++; // Increases the value of x. Now x = y = 11;
As my two cents, I think reference variables are mere alternative names for the same memory address by which it was initialized. This also explains pretty nice:
http://www.dgp.toronto.edu/~patrick/csc418/wi2004/notes/PointersVsRef.pdf
I don't sure in which case I should store a returned value of a function by value, reference or const reference.
As I see it, function can return:
(1) by value, if the variable inside is local, and the returned value will be r-value.
(2) by reference, if the variable inside keep existing (for example member field of class), and the
returned value will be l-value ref.
when store it outside:
auto& a = getVar(); // should be done **only** if the func returning by ref
auto a = getVar(); // can be done in both cases
const auto& a = getVar(); // can be done in both cases
is it true or am I missing something? is it getting more compilcated when moving? are they cases I didn't think about?
edit:
I understand it is different in case I want a copy to work with or the object itself. but still need some guidelines please to make order in this issue
In C++ a program can pass a reference, not value to a function.
void incrementInt(int &x)
{
++x;
}
Does OCaml offer this same functionality?
No, there is no strict equivalent.
There are refs, which are like pointers to new-allocated memory, and there are records, arrays, objects and values of other compound data types, that are passed "by object reference", which again means they act like pointer to new-allocated memory.
However there's no equivalent to a pointer to a variable or a C++ reference.
There would be no distinguishable difference between pass-by-value and pass-by-reference in OCaml, because it's impossible to assign to a variable in OCaml. For example, your ++x is impossible in OCaml.
The difference between pass-by-value and pass-by-reference is in what happens when a parameter is assigned to inside the called function -- in pass-by-value, it has no effect on the passed variable (if a variable was passed); in pass-by-reference, it has the same effect as assignment to the passed variable in the calling scope. In OCaml, you cannot assign to a variable, so this distinction does not exist. If OCaml were "pass-by-reference", it would work the exact same way as if it were "pass-by-value".
You can pass around references to mutable data structures, and use this to share state between functions, but this has nothing to do with pass-by-reference, as you can do this in pass-by-value-only languages like C and Java.
In OCaml, parameters are passed by value. A value by itself can be mutable, or immutable. The former can be modified by a callee, and it will be seen by the caller. Immutable value, obviously, can't be modified. The mutability of a value is defined by its type. Most of the value types in OCaml are immutable. The notable exceptions are arrays and strings (in the newer version of OCaml stings became immutable, but let's skip this topic). For example, values of type int are immutable. This is quite natural -- if you have the number 5 it is always the number 5, you can't mutate it. However, you can put this number into a mutable cell and pass this cell to a function. So that the function, can change the contents of the cell. Note, we are not changing the number itself, we are just putting another number into the same cell, e.g.,
type cell = {
mutable value : int;
}
let incr x =
x.value <- x.value + 1
The incr function takes a value from a cell, creates a new value by incrementing it, and then puts the new value into the cell.
We can parametrize type cell, so that it can contain a value of any type, e.g.,
type 'a cell = {
mutable value : 'a;
}
In fact, the ref type actually looks the same (modulo name). It is defined in the standard library as follows;
type 'a ref = {
mutable contents : 'a;
}
The notion of passing by a reference was created by languages that leaked their own abstractions and made it necessary to a programmer to understand how parameters are passed to a function. In OCaml, you can forget this as a nightmare. Every parameter in OCaml takes only one machine word and is passed via a register, or via the stack if there are too many parameters. From a C programmer perspective, every value is a scalar or a pointer. Integers and unary constructors (variants) are passed as scalars, where compound data types, are always passed by a pointer.
The closest, could be:
let x=ref 3;;
let incrementInt x =
x := !x+1;;
incrementInt x;;
# !x;;
- : int = 4
As said sepp2k, it is not the same.
if I have a function set up similarly to this:
update_value(const int& old_value, const int& new_value){
}
What if I need to get the value of old_value and new_value and use these values in a mutable variable?
I can't dereference with a *pointer. How do I work around this?
First of all your question is not so clear and I dont know why you want to use mutable keyword.Mutable keyword can be used only for class member variables.
Regarding your question,in the comment you mentioned that you want to access some index of the array based on the passed arguments.Since you are not changing passed argument value you can directly use your passed argument in the accessing array value.
I'm using the D language, and would like to get the default value of a generic type, similar to the way default(T) works in C#. Is this possible? If not - what are the possible workarounds?
I think T.init might be what you're looking for.
Every type in D has a default value. It's accessed via the type's init property. int.init, float.init, Object.init, etc. In the case of a templated type, it's still the init property. For example, if you had the generic type T, it would be T.init.
init is generally the closest to an error value that the type has. For integral types, it's 0. For bool, it's false. For floating point types, it's NaN. For character types, it's \u00FF. For references (i.e. classes) and pointers, it's null. And in the case of structs, it's whatever the value that its member variables are directly initialized to are. e.g. In the case of
struct S
{
int a = 17;
bool b;
}
S.init would be an instance of S whose a was 17 and b was false. Of particular note, the need for the init property is the reason that structs in D cannot have default constructors. Their default state - that is, their init property - must be known at compile time, whereas a constructor would be run at runtime, so the default value of a struct can't be created with a constructor, and so, while structs can have constructors, they can't have default constructors.
In the case of enums, the init property depends on the sort of enum that it is. A manifest constant such as
enum i = 7;
would have the same init property as its type (int in this case), since you didn't really create a new type. However, for enums which actually create a new type, e.g.
enum E { a = 7, b = 17 };
the default value is the first value in the enum. In this case, E.init would be a.
Arrays are where it gets a bit interesting though. The init property for dynamic arrays and associative arrays is null. However, when you allocate memory for an array (be it static or dynamic), each element is initialized to its type's init property. So, with arrays, you have both the matter of their init value and the init value of their elements.
In any case, the generic way to get the default value of a type is T.init where T is the type that you want the default value of - be it a specific type or a template parameter.
Re enum, according to codepad.org:
enum Foo {
a = 3,
b = 2,
}
import std.stdio;
void main() { writef("%d", Foo.init); }
gives:
3