Curiosity Question: Trusting Function Calls

Feel free to ignore. I hope I am not taking too much time. It’s a very end-usery perspective curiosity question. None of the computer languages that I know allow this. (maybe ancient fortran.)

let’s say that I am writing a program that imports some libraries. The libraries may be open-source or not. Now, as the user of a library that was written by someone else and that I am not sure I trust (perhaps because the writer has accidentally introduced a bug), is there a way that I, as the caller, can express that the function call should not be allowed to alter the objects with which I am calling it? [the !-exclamation function naming convention designates collaboratively the opposite—a hint that it will modify at least one of the arguments. it’s as if I want non-! named functions not be allowed to modify arguments.] and that it should not have global side effects, either?

this also seems linked to the problem of good user parallelization. functions that are designated/written/guaranteed not to have [global] side effects and that do not modify their arguments should be safe to parallelize. the compiler could help with warnings when one asks for parallel invocation of a function that is not designated safe in this way.

some of this functionality could be obtained by deep comparing objects before and after the call via a(utomatic) function wrap, but this would be at run-time rather than compile-time. it could be akin to bounds checking.

in any case, the ! syntax seems like a “hope” crutch. and should two !! designate functions that modify two arguments? what if the function modifies the object in argument 1 and argument 3? can I trust the absence of ‘!’ ? how do I name a function which calls another !-function that modifies an object inside the object?


PS: (With languages like C or perl, which have pointers, this is a different problem. For julia, it seems possible.)

PS: I do miss the ability to declare function arguments as ‘const’. I hope that it will appear sooner or later.

If you define your objects as structs then everywhere they go, they remain unchanged and any attempt to change one of their fields’ values directly will result in an error. It is possible to change the value within a collective field, e.g. within a struct that has a field that is a vanilla vector, one could alter the ith entry indirectly. Julia has some kinds of vectors that do not allow this, they are most appropriate for vectors of < 100 elements or so.

If you are using eg <: AbstractArray, you can implement a wrapper type that forwards methods for everything except setindex!. This will protect you from bugs in pure Julia, but not from direct memory manipulation (bugs or intentional, implemented in Julia or in a foreign library).

You can make a copy and compare for unit testing. I sometimes do this when I refactor code from mutating to non-mutating (and lament my tendency for premature optimization).

1 Like

If you really wanted to be able to guarantee that called code doesn’t affect the variables you provide it, as well as any mutable globals, you’d need to write a pass over the callee’s code_typed AST (recursively) and determine where writes occur. For calls to foreign libraries, if you know the library and functions ahead of time (like OpenBLAS or FFTW), then you could permit calls to certain functions and not others, depending on what variables they’re called with.