inim-repl / INim

Interactive Nim Shell / REPL / Playground

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Variables don't persist

iacore opened this issue · comments

how to reproduce the bug

First, have a file named test.nim:

const foo* = 1

Then: do this in inim

> import test
> var a = foo
> a
1
# now, edit `test.nim` to make foo 2
> a
2

I don't quite understand the bug here, but you must remember that unlike python, there's no 'runtime' for variables to persist in.
Behind the scenes we add all typed lines to a file, and compile that file.

Can you explain more?

The example is counter intuitive, since var a = foo should set a to 1 until I change it. (see REPL of Python and Ruby)

Instead, a is changed to 2 without explicit setting a to 2.

Agreed. It is counter-intuitive.

However, I believe what @0atman is saying is, whenever you type a line of code, that line is added to a source file somewhere and the source file is recompiled and executed. So every time you enter a line of code, it is literally as if you just entered all the lines, right then, in one operation.

Therefore, of course the value of a changes to reflect the value of foo; just as it would if you re-entered import test and let a = foo after the edit.

Of course, this means the longer you continue at the REPL, the slower and slower compilation will become. Doesn't strike me as a particularly viable solution, to be honest.

What we must remember is that there's NO compiler execution happening apart from the read loop between lines.
There's no 'runtime', there's no 'shell', there's no long-running language like in Python.

inim-repl is a best effort, given the constraints of the nim language. Any language that has no persistent runtime for variables to hang around in would behave the same.

Should we fake it to be similar to python? I'm not sure. That could cause some edge cases for people who assume nim will behave like nim.

I'd be interested to hear thoughts on the matter 😃

Depends. Fake it how, exactly?

Is my assumption correct? As in, the REPL currently works like this:

Loop {
  Read a line from the user
  Append line to a temporary file (that already contains all previous lines)
  Compile and execute the temporary file
  Print the output of the execution
}

In which case, how do you avoid printing output from previous lines? Why didn't the second a in the OP's example print:

1
2

Do you perhaps modify the previous lines to be unable to produce output? Like, set STDOUT to null or something until the last line is reached, then set it back?

I think having a REPL that re-runs all previous commands every time you type something is a Bad Idea™. Suppose there are important commands higher up? Like file deletions or non-idempotent actions?

I think it might make more sense to let the user enter multiple lines, then type :run or something. Make it explicit.

And also have a :reset or :clear to drop all previous lines. Maybe more fine-grained control.