How are called in Julia terminology Int64, Float64,... vs Array{T,1}, Tuple{T1,T2,...}, Set{T},

Just to ask which is the correct terminology to differentiate Int64, Float64, Bool, Char, String (that I notices is not an Array of chars) on one side vs Array{T,N}, Tuple{T1,T2,…}, Set{T}, Dict{}…, and in general T1{T2} on the other side…

“primitive” vs “composite” ?
“immutable” vs “mutable” (but then Tuple is immmutable) ?
“simple” vs “container” ?

Container is a good term. But note that the two sets are not disjoint, as stored elements can be containers themselves, eg

[[1, 2], [3, 4]]

Mutability is an orthogonal concept.

The terminology can become somewhat fuzzy. Eg 1:10 can behave like a container (<: AbstractVector), but strictly speaking does not “contain” the integers between 1 and 10. But this does not matter, as the caller should not care.

Are you looking for “parametric” vs “non-parametric” types?

This is indeed called parametric types.

(Although the examples you list (Array, Set etc) are also all “collection” or “container” types.)

1 Like

I think container or collection is the concept I was interested to, as I am trying to understand the difference between name binding, copy() and deepcopy(), although I realised I do not need to use this difference:

I would state:

In order to unnecessarily copying large amount of data, Julia by default copies only the memory address of objects, unless the programmer explicitly request a so-called “deep” copy. In detail:

Equal sign (a=b)

  • performs a name binding, i.e. binds the entity (object) referenced by b also to the a identifier (variable name)
  • it results that:
    • if b then rebinds to some other object, a remains referenced to the original object
    • if the object referenced by b mutates (i.e. it internally changes), so does (being the same object) those referenced by a

a = copy(b)

  • create a new, “independent” copy of the object and bind it to a. This new object may however reference in turn other objects trough their memory address. In this case it is the memory address that is copied and not the referenced object itself.
  • it results that:
    • if the referenced objects are rebind to some other objects, the new object referenced by a maintains the reference to the original objects
    • if the referenced objects mutate, so do (being the same objects) those referenced by the new object referenced by a

a = deepcopy(b)

  • everything is deep copied recursively

This is a common misconception. What happens is that the language is free to copy or not copy objects for which the user cannot distinguish whether copying happened. This allows the compiler various optimizations.

You may be interested in past discussions like

but the bottom line is that deliberately leaving this unspecified and hidden from the user in normal circumstances is an important feature, and can be exploited by using immutables.