From what I understand, Elixir does not have referential transparency. I was still curious about it, though.
I discovered :erts_debug.same/2 in this reply which tells you if two pieces of data point to the same memory location or not. So I did a couple of tests:
The second example has me pretty dang satisfied that there is no referential transparency in Elixir (not that I didnāt believe itā¦), but whatās going on in the first one? Is that the compiler inlining the function?
Iām not at my computer now, but I recommend checking :beam_disasm.file(module). The map in the first one is almost certainly a literal stored as in a single place, so two calls will return the same reference to that literal.
The leela function probably newās a new map each time itās called, so thereās no way for the BEAM to know if they should be the same, since it could have been passed anything, let alone a string.
(Iāve tried several other inputs including bare code, code as strings, and different file paths)
What you are describing is what I assume is happening, but I was wondering how exactly it makes those decisions. Iām assuming the compiler can tell if the body of a function is static or not, but I just wanted to know for sure whatās going on. Iām guessing :beam_disasm can help me with this! The docs are a little sparse, but Iāll keep plugging away at it.
Elixir does not have referential transparency but I donāt think those examples prove or deny it.
Referential transparency means the compiler is able to inline those calls - but the compiler doesnāt necessarily have to. After all, you can think some calls may actually perform long running computations that would make them expensive to inline.
As you likely know, for a system to be referentially transparent, the compiler (and the developer) need to be able to recognize and separate code with side-effects from pure code.
Elixir and Erlang does not really tag functions with side-effects. The compiler also doesnāt look across modules, because of hot code reloading, so we canāt peak inside either. But the Erlang compiler does optimize literals and several functions from Erlangās stdlib if those particular functions are guaranteed to be pure.
Awesome, thanks for all that! That helps a bunch, especially around if the compiler is able to tag something as having side-effects or not. I donāt know a lot about compilers but am slowly learning a thing or two and I just like to know these things. I am still a little curious how the first example knows to point to the same memory after a function call, unless :erts_debug.same/2 doesnāt do exactly what I think it does.
Ah ok! I thought you were only talking functions from the standard lib so was a little confused but I got it now. Thanks so much for taking the time to explain!