iex forgets bindings when interrupted
Closed this issue · 5 comments
Elixir and Erlang/OTP versions
Erlang/OTP 27 [erts-15.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Elixir 1.17.3 (compiled with Erlang/OTP 27)
Operating system
Linux 6.12.1_1 #1 SMP PREEMPT_DYNAMIC Sun Nov 24 23:14:58 UTC 2024 x86_64 GNU/Linux
Current behavior
iex forgets bindings when interrupted (via i from the ^G menu):
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = 123
123
iex(2)> a
123
iex(3)> f = fn f -> f.(f) end
#Function<42.39164016/1 in :erl_eval.expr/6>
iex(4)> f.(f)
User switch command (type h for help)
--> i 1
--> c 1
** (EXIT) interrupted
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(4)> a
error: undefined variable "a"
└─ iex:4
** (CompileError) cannot compile code (errors have been logged)
iex(4)>
Expected behavior
I had assumed this would not happen, because it does not in erl:
Erlang/OTP 27 [erts-15.1.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit:ns]
Eshell V15.1.1 (press Ctrl+G to abort, type help(). for help)
1> A = 123.
123
2> A.
123
3> F = fun(F) -> F(F) end.
#Fun<erl_eval.42.39164016>
4> F(F).
User switch command (type h for help)
--> i 1
--> c 1
** exception exit: killed
5> A.
123
6>
This does not appear to be filed as an open or closed issue anywhere, so I am filing it now.
Just iex
from the terminal.
The infinite loop is important. If you're not actually interrupting anything with your interrupt, it won't happen, as you show above.
I don't really know anything about how iex is put together at runtime, but you lose binds, imports, probably other environmental things.
Oh, of course, the loop being required makes sense. Thank you!
Yeah, I see why it works in Erlang, they automatically spawn a new process:
Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
1> A = 123.
123
2> self().
<0.88.0>
3> self().
<0.88.0>
4> F = fun(F) -> F(F) end.
#Fun<erl_eval.42.39164016>
5> F(F).
User switch command (type h for help)
--> i 1
--> c 1
** exception exit: killed
6> self().
<0.94.0>
In Elixir, we decided that changing the process behind the scenes would be surprising behaviour. Things that you had set up, such as monitors, messages, or links, will either be broken or missing. So I am not sure we want to make this trade-off here too. :(
I will close this for now, glad to reopen if people feel strongly and have good arguments, but I think the safest is to keep the evlauation tied to the process. Thanks for the report!