Why are immutable types passed by copying? - julia

In the documentation on types, it says:
An object with an immutable type is passed around (both in assignment statements and in function calls) by copying, whereas a mutable type is passed around by reference.
What's the purpose of copying an entire object when the object can't be changed? Why not just copy the reference?
Also, when I try to test this with
struct Foo
bar::Int
end
x = Foo(10)
y = x
pointer_from_objref(x) # Ptr{Void} #0x00000001141ea760
pointer_from_objref(y) # Ptr{Void} #0x00000001141ea760
it suggest that the objects are the same. Am I misunderstanding this?
Thanks for the help!

pointer_from_objref does not work as you think on immutable types. The results depends on the context you call it from.
Try something like
function test(x) return pointer_from_objref(x) end
println(test(x))
println(test(y))
I'm actually quite surprised that it even worked, considering that the source tries to trow an error for immutable arguments.
For your really small immutable, a copy (or just keeping the value in a registrer) is actually much cheaper than going the detour of a pointer (A pointer is the same size as an int and obviously also needs to be copied to a function call).

Related

In (Free) Pascal, can a function return a value that can be modified without dereference?

In Pascal, I understand that one could create a function returning a pointer which can be dereferenced and then assign a value to that, such as in the following (obnoxiously useless) example:
type ptr = ^integer;
var d: integer;
function f(x: integer): ptr;
begin
f := #x;
end;
begin
f(d)^ := 4;
end.
And now d is 4.
(The actual usage is to access part of a quite complicated array of records data structure. I know that a class would be better than an array of nested records, but it isn't my code (it's TeX: The Program) and was written before Pascal implementations supported object-orientation. The code was written using essentially a language built on top of Pascal that added macros which expand before the compiler sees them. Thus you could define some macro m that takes an argument x and expands into thearray[x + 1].f1.f2 instead of writing that every time; the usage would be m(x) := somevalue. I want to replicate this functionality with a function instead of a macro.)
However, is it possible to achieve this functionality without the ^ operator? Can a function f be written such that f(x) := y (no caret) assigns the value y to x? I know that this is stupid and the answer is probably no, but I just (a) don't really like the look of it and (b) am trying to mimic exactly the form of the macro I mentioned above.
References are not first class objects in Pascal, unlike languages such as C++ or D. So the simple answer is that you cannot directly achieve what you want.
Using a pointer as you illustrated is one way to achieve the same effect although in real code you'd need to return the address of an object whose lifetime extends beyond that of the function. In your code that is not the case because the argument x is only valid until the function returns.
You could use an enhanced record with operator overloading to encapsulate the pointer, and so encapsulate the pointer dereferencing code. That may be a good option, but it very much depends on your overall problem, of which we do not have sight.

Hidden remote function call of a local binding in ocaml

Given the following example for generating a lazy list number sequence:
type 'a lazy_list = Node of 'a * (unit -> 'a lazy_list);;
let make =
let rec gen i =
Node(i, fun() -> gen (i + 1))
in gen 0
;;
I asked myself the following questions when trying to understand how the example works (obviously I could not answer myself and therefore I am asking here)
When calling let Node(_, f) = make and then f(), why does the call of gen 1 inside f() succeed although gen is a local binding only existing in make?
Shouldn't the created Node be completely unaware of the existence of gen? (Obviously not since it works.)
How is a construction like this being handled by the compiler?
First of all, the questions that are asking have nothing to do with the concepts of lazy, so we can disregard this particular issue, to simplify the discussion.
As Jeffrey noted in the comment to your question, the answer is simple - it is a closure.
But let me extend it a little bit. Functional programming languages, as well as many other modern languages, including Python and C++, allows to define functions in a scope of another function and to refer to the variables available in the scope of the enclosing function. These variables are called captured variables, and the created functional object along with the captured values is called the closure.
From the compiler perspective, the implementation is rather simple (to understand). The closure is a normal value, that contains a code to be executed, as well as pointers to the extra values, that were captured from the outer scope. Since OCaml is a garbage collected language, the values are preserved, as they are referenced from a live object. In C++ the story is much more complicated, as C++ doesn't have the GC, but this is a completely different story.
Shouldn't the created Node be completely unaware of the existence of gen? (Obviously not since it works.)
The create Node is an object that has two pointers, a pointer to the initial object i, and a pointer to the anonymous function fun() -> gen (i + 1). The anonymous function has a pointer to the same initial object i. In our particular case, the i is an integer, so instead of being a pointer the i value is represented inline, but these are details that are irrelevant to the question.

What's the fastest way to cast Vector{T} (T<:A) to Vector{A}?

Suppose A is an abstract type, I have a function f{T<:A}(x::Vector{A}). So x could be type Vector{A} or Vector{B} where B <: A. In the middle of the function I would like to cast x to Vector{A} so it can be consumed by another function that requires that signature.
What's the best way to do that? At the moment I am doing x = collect(A, x). Is there a way to avoid copying if possible?
If at all possible, I'd just change your second function definition to be parametric like f. Enforcing this kind of container structure in method signatures is a big performance bug that doesn't gain you any functionality… and just makes them much harder to use.
That said, the best way to do this kind of conversion where you don't care if the output aliases the input is with convert(Vector{A}, x). This will be a no-op if x already isa Vector{A}, but otherwise it'll be just like collect. That's as good as it gets.
Here's why: two containers of types Vector{A} and Vector{B} cannot share the same memory if A !== B since it'd be possible to corrupt the data in the Vector{B} by assigning a non-B element to the array through the Vector{A}.

In OCaml, how do I re-assign a global variable inside a function

My program has the following global variable:
let a = (0.0,0.0);;
And the following, where eval e1 returns a string_of_float and somefunc e2 returns a tuple.
let rec output_expr = function
Binop(e1, op, e2) ->
let onDist = float_of_string(eval e1) and onDir = somefunc e2 in
let newA = onDir in (
fprintf oc "\n\t%s" ("blah");
fprintf oc "\n\t%s" ("blah");
fprintf oc "\n\t%s" ("blah");
let a = newA
)
Now, the code above gives me the following error:
Error: This expression has type bool
but an expression was expected of type unit
Command exited with code 2.
I want let a = newA to change the value of the global variable a. How can I do that?
To do it you need to make the value a reference,
let a = ref (0.0, 0.0)
then later that state can change by,
a := (1.0, 2.0);
In a functional world you would not want to have this global state. Sometimes it is very helpful, but in this particular case that is doubtful. You should pass the value a into your function and return a new value (a') that can be used subsequently; note that the value never changes, but new values take the place and are used in further computation.
In your particular case, I think you need to ask yourself why a function named output_expr modifies some global state, or returns anything but unit. But maybe this is a toy example for our consumption, so I will leave it at that.
You cannot assign to a variable (local or global is the same) in OCaml. There's simply no syntax in the language for it. In other words, variables in OCaml are what other languages call "constants" -- they get a value once in initialization, and that's it.
However, you can use a mutable data structure, which offers ways to modify its contents. Data structures are reference types, you can hold a reference to the data structure in a variable, and modify the contents, without needing to assign to the variable.
nlucaroni mentioned such a data structure, ref, which is a simple mutable cell holding a value of the desired type. There are other mutable data structures, like arrays, strings, and any record with mutable fields. Each has its own way of modifying the contents.
However, mutable state can mostly be avoided in functional programming, and if you are relying on mutable state, it may be an indication that you are not doing it the functional way.
In OCaml, values are immutable. You can't change the content of a value and should reorganize your code so that you don't need to.
Here your function output_expr should return the newA and this value should be used instead of a after that.
Actually you can have mutable variables using references but you should only use them if you know what you do and think they are better suited for a particular use case, never because you don't understand immutability.

Initialize an Empty Array of Tuples in Julia

I can't figure out how to initialize an empty array of tuples. The manual says:
The type of a tuple of values is the tuple of types of values... Accordingly, a tuple of types can be used anywhere a type is expected.
Yet this does not work:
myarray = (Int64,Int64)[]
But this does:
Int64[]
It would seem a type is expected in front of the empty square brackets, but the tuple type doesn't work. This <type>[] syntax is the only way I can find to get an empty typed Array (other methods seem to produce a bunch of #undef values). Is the only way to do it, and if it is, how can I type the Array with tuples?
BTW, my use case is creating an array of initially indeterminate length and pushing tuples onto it in a loop.
For people who look for the latest solution,
Tuple{Int, Int}[] works in v0.4
Also the verbose way Array{Tuple{Int, Int}}(0) works in v0.4 as well.
It creates a 0-element Array{Tuple{Int64,Int64},1}
Note that in v1.0 you'd need to write
Array{Tuple{Int, Int}}(undef, 0)
You can do Array((Int,Int),0) for this. It is probably feasible to add methods to getindex to make (Int,Int)[] work, but I'm not sure it's worth it. Feel free to open an issue.

Resources