Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: read eval print loop facilities #39165

Closed
gonzojive opened this issue May 20, 2020 · 6 comments
Closed

proposal: read eval print loop facilities #39165

gonzojive opened this issue May 20, 2020 · 6 comments

Comments

@gonzojive
Copy link

gonzojive commented May 20, 2020

Many languages offer read eval print loops (REPLs) that allow interactive development of computer programs. REPLs are useful and timeless, and Go should have one.

Go has survived without a REPL, perhaps because compilation speed has always been a project priority. Often full, repeated re-compilation and -execution is a good substitute for a REPL, but there are advantages to working with a runtime:

  1. For large programs, such as those that use big libraries like TensorFlow, linking and starting a new binary can be "slow." Say a minute. As fast as the compiler and linker are, most REPLs have milliseconds of latency from keyboard input until execution begins.

  2. When a large amount of data or state is present in the runtime, it may be be expensive, inconvenient, or infeasible to re-execute the altered program to observe the same state. During development of a web scraper, for instance, it may take half an hour to download a set of webpages again. The programmer could restructure the program to persist the data and load it, but this is an unnecessary burden. ML engineers routinely load large tables of data for interactive analysis in colab notebooks, a web-based repl.

The proposal is simple, perhaps too simple: REPLs are great, and go should have one. If a broad proposal is insufficient, I can attempt to work out more detail.


A brief note on my exploration so far:

One approach would be to extend the features of the plugin system to allow incremental definition of packages. The finality of a package is where I have struggled in implementing a REPL based on existing facilities: new methods cannot be defined, references cannot be made to unexported variables, and so forth. Could the plugin system allow a new version of a package to be installed that references existing internal package variables, functions, and types? Perhaps with restrictions, such as no replacement of existing functions, and packages that can be replaced need to be compiled with a special flag.

Without the ability to modify an existing package, it's already possible to use the plugin system to write a kind of go shell. For example, variables defined at top level can be put into a shell-managed package and referenced by manipulation of identifiers in the ast read by the shell. But this is all a bit clunky and limited. What we really want is to write a package like normal and add pieces of the package to the runtime as they are ready.

(I am not so concerned about supporting the deletion of a package or aspects of a package, but other languages do support such deletions at runtime with various limitations.)

@gopherbot gopherbot added this to the Proposal milestone May 20, 2020
@robpike
Copy link
Contributor

robpike commented May 20, 2020

See https://github.com/containous/yaegi.

@gonzojive
Copy link
Author

gonzojive commented May 20, 2020

Thanks. My experience with a repl is in Common Lisp (SBCL) where code is compiled and evaluated. The REPL solutions I have seen for Go seem to require writing an interpreter, not using the usual compilation pathway. Without compilation, the repl code can be slower, differ in subtle ways from compiled code, and overall feel second class.

The technical heart of the proposal, which is only implied at the moment, is being able to append to or replace parts of an existing package in a runtime.

@gonzojive gonzojive reopened this May 20, 2020
@ianlancetaylor
Copy link
Contributor

Do we really need plugins for a REPL? Since the compiler is fast, can't we simply recompile and re-run the file after each input line?

@gonzojive
Copy link
Author

gonzojive commented May 20, 2020

Do we really need plugins for a REPL? Since the compiler is fast, can't we simply recompile and re-run the file after each input line?

Are you referring to re-running the full executable? I mention in the original post why this may be inadequate for certain workflows - workflows that are common practice in other languages. Perhaps you are referring to something else.

@dpinela
Copy link
Contributor

dpinela commented May 21, 2020

Also, while the compiler is fast, it isn't instantaneous, so that approach gets slower the long you keep a REPL session open.

@rsc rsc added this to Incoming in Proposals (old) Jun 10, 2020
@rsc
Copy link
Contributor

rsc commented Aug 18, 2021

There are existing attempts at this, and you are welcome to build one as well.
This is not really a proposal though, or if it is it's more work than we will take on right now.
Will close as infeasible.

@rsc rsc closed this as completed Aug 18, 2021
@rsc rsc moved this from Incoming to Declined in Proposals (old) Aug 18, 2021
@golang golang locked and limited conversation to collaborators Aug 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Development

No branches or pull requests

6 participants