Is there things like intent(in), intent(out) in Julia?

In Fortran, we can specify intent(in), intent(out) for the arguments of function/subroutine, and this can help preventing bug, and possible help the compiler to do optimization.

I learned from kargl in Fortran discourse that (unfortunately his comments disappeared), and i can only remember the things like,

subroutine f(x,y)
real, intent(in) :: x
real, intent(out) :: y
integer :: i
do i=1,10
    y = sin(x)
enddo
return
end

intent(in) means x is basically ‘read-only’, its value cannot be changed in the subroutine. While intent(out) means y’s value can be changed.
Besides doing some protection for arguments, they might be some performance gain.

I cannot explain very well why, but I remember kargl said something like, adding intent(in) for x, and intent(out) for y, and realizing that sin is a pure function, it definitely can help the compiler to realized that it should just calculate

y=sin(x)

Only once. If I do not add intent(in) for x and intent(out) for y, there is a possibility that the compiler will do really do the stupid loop 100 times.

In Fortran, intent property is optional, but it is encouraged to use them whenever possible. There are obviously more deep reason that Fortran committee design the intent property, but I am not capable of explain it.

Anyway, just curious, in Julia is there similar stuff that can do some protection on the arguments (prevent the values of some arguments being accidently changed by mistake)?

Thanks in advance!

I’m surprised about that since the compiler needs to check the correctness of the intent anyway so it doesn’t feel like that should give any more information.

In Julia, there is the convention of adding a ! to the end of a function that mutates an argument and has that argument be the first one, see Style Guide · The Julia Language.

3 Likes

You can use

if you want to enforce this.

3 Likes

I think it matters when one wants to modify more than one object in a function. Without intent one has to check whether the second parameter will also be modified, then the third, so on until a parameter is found to be constant. It affects readability.
It might be better to pack all non-constant parameters into one struct, but I’m not sure.

1 Like

Note that there is a fundamental difference between Julia and Fortran in this regard, if the variables are immutable (a concept somewhat extraneous to Fortran). In Fortran, something like this mutates the input variable:

double precision function f(x)
    double precision :: x
    x = 2*x
    f = sin(x)
end function f

program main
    double precision :: x, y, f
    x = 1.
    y = f(x)
    write(*,*) x
end program main
% gfortran mut.f90 -o mut
% ./mut
   2.0000000000000000  

While in Julia it does not:

julia> function f(x) 
           x = 2*x
           y = sin(x)
           return y
       end
f (generic function with 1 method)

julia> x = 1.
1.0

julia> f(x)
0.9092974268256817

julia> x
1.0

This means that the type of information that intent(in) may provide to the compiler is given in Julia by default for immutable variables (and race-free, etc).

If these differences make any difference to performance is not clear to me, possibly in some very specific cases there are performance differences, as there may be with the use of intent(in) in Fortran.

4 Likes

Variables/bindings can only be constant (and only if they are global, as local constants are not implemented). Only objects/values are immutable. I think the difference here is a little more subtle.

In Fortran, f(x) means that the parameter x inside f becomes a reference to variable x outside of f (at least in this example), and attributing a new value to the parameter inside the function will alter the x outside.

In Julia, f(x) always mean that you are binding the value of x to a new binding inside f (that, in this case, happens to have the same name), therefore, attributing something new to the x will just change what this new name, that only exists inside the function, point to.

Obviously, you see change if the x outside the function holds a mutable value, but both in Fortran and Julia floating-point values/objects are immutable (you cannot change what 1.0 means). So in this case, it is impossible for Julia to change something out of the function, while for Fortran that takes a reference, it is possible.

3 Likes

Thanks, my terminology accuracy is less than acceptable. All that is what I tried to illustrate.

1 Like