Dear Julia colleagues,
In June, I wondered on this newsgroup why Julia lacks an 'inarg'
specification for functions. The two major languages used nowadays for
scientific programming, namely Fortran and C++, both provide mechanisms to
declare that a function argument is read-only by the function. Indeed,
this was added to Fortran late in its life, so one assumes that there is
some bitter experience underlying the decision to include it in Fortran.
(Matlab has only inargs, at least until you get to relatively advanced
programming techniques, so this is not an issue.)
Stefan Karpinski provided a convincing explanation for why inarg and outarg
specifications have been omitted from the Julia core. Now that I am
slightly more familiar with Julia, I would like to make a proposal for
inarg that would not require changes to the core language. The proposal
would, however, entail substantial additional code, so it is intended for
some version of Julia in the future.
Here is the proposal: suppose fn is a function that takes an array input
"a" and wants to declare it to be read-only. Then at the beginning of the
function before any of the arguments gets used, there would be an
assignment statement like this:
function fn(a::AbstractArray{Int,1})
a = readonly(a)
The way this would work is as follows: Julia would have new types, mostly
invisible to the user, like ReadOnlyArray which would have a setindex!
method that would throw an error, Then there would be methods like
readonly{T.N}(a::Array{T,N}) that would use 'reinterpret' to change the
Array to a ReadOnlyArray. A programmer who wanted to write a function that
could take either arrays or readonlyarrays as inputs would have to declare
abstract argument types like DenseArray or AbstractArray. The user would
not, in general, have to worry about the read-only types; the situation
when a user would have to worry about them is if he/she wants to develop a
read-only version of his/her own data structure that internally uses the
standard containers.
This proposal has several advantages:
(1) The above mechanism enforces the read-only property of a since fn no
longer has access to the initial (writeable) definition of a.
(2) The above mechanism, if adopted as an idiom, could be easily spotted by
program analysis tools that could then make optimizations based on the fact
that a is read-only.
(3) There is hardly any performance penalty for this mechanism.
But obviously there is one big disadvantage:
(1) For each of the standard containers, a new read-only version would have
to be written. Furthermore, there would also have to be an abstract type
to serve as a common parent. E.g. there is currently no abstract parent
for Set (although there is an open discussion about that matter on github).
and a second minor disadvantage
(2) The enforcement of read-only would probably would not work recursively,
e.g., if a were an array of arrays. In fact C++ has a similar gap in its
'const' mechanism.
-- Steve Vavasis