CSharpRepl icon indicating copy to clipboard operation
CSharpRepl copied to clipboard

Add automatic variables that represent previously evaluated values

Open waf opened this issue 3 years ago • 4 comments

Feature Description

It'd be nice to have automatic variables that represent previous prompt results.

There are two possible approaches (they aren't mutually exclusive):

Counting Forwards

Count forwards from the start, e.g. line0, line1, line2, etc. We'd probably want to change the prompt from > to lineN > so it's easy to see what a given line would reference. A downside of this is that it's a more complex UI:

line0> 5 + 3
8
line1> 17 * 2
34
line2> line0 + line1
42

Probably want a command line switch to disable this feature, in case people don't want the extra noise.

Counting backwards

Have automatic variables that always represent the previous line, and the line before that (e.g. last, last2, etc).

  • A benefit of this is that it wouldn't require a change to the prompt
  • A downside is that it can get confusing to figure out what you've historically run, as the variables will have a different value on each line. It also somewhat breaks history, because if you run a line from history that references these last variables, the result will be different.

I'm currently planning to implement only Counting Forwards

To my knowledge, roslyn scripting does not support dynamically adding to the ScriptGlobals type, so it might be a bit tricky to implement. We'd also want to ensure that these lines show up in intellisense.

waf avatar Jun 29 '21 14:06 waf

I quite like the way IPython does this: https://jakevdp.github.io/PythonDataScienceHandbook/01.04-input-output-history.html

tl;dr: _ references the last result (same as in the normal Python REPL and Ruby's irb), __ the second to last, and ___ the third to last. Additionally, all outputs can be referenced via Out[n].

citizen428 avatar Sep 05 '21 13:09 citizen428

Underscore syntax would interfere with C# discards (https://docs.microsoft.com/en-US/dotnet/csharp/fundamentals/functional/discards). That cannot be used.

But I probably like the Out[n] syntax.

kindermannhubert avatar Feb 27 '22 22:02 kindermannhubert

Both Ruby and Python use _ for discards in normal code but also for the last result in the REPL, hence the suggestion. In both languages _ is just a normal identifier though. Ruby for example reassigns _ after each expression was evaluated:

irb(main):001:0> a, _, c = [1,2,3] # assignments return their RHS
=> [1, 2, 3]
irb(main):002:0> _
=> [1, 2, 3]
irb(main):003:0> a
=> 1
irb(main):004:0> c
=> 3
irb(main):005:0> _
=> 3

It's very possible that the same wouldn't work in C# though, I didn't check that. Out[n] is probably the better choice anyway.

citizen428 avatar Feb 28 '22 03:02 citizen428

E.g. this code won't compile when _ is redefined because of types mismatch:

public void M(int _)
{
    _ =  DateTime.Now.ToString();
}

While this compiles successfully:

public void M()
{
    _ = DateTime.Now.ToString();
}

kindermannhubert avatar Feb 28 '22 13:02 kindermannhubert