[RFC]: add support for defining and using macros in the REPL
- Dominant language
- JavaScript
- Stars
- 6k
- Forks
- 1.3k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 611
Description
### Description
This RFC proposes adding macro support in the REPL. To allow users to define macros, we could add a command having the following signature:
```
macro( name, body )
```
where
- `name`: macro name (e.g., `FOR`) and may include named parameters
- `body`: macro body
E.g.,
```
In [1]: macro( 'FOR', 'for ( let i = 0; i < 10; i++ ) {' );
```
would define a macro for define the conditions of a `for` loop. To use, a user would type
```
In [2]: FOR
```
followed by ENTER in order to expand the macro. Note, in this proposal, hitting ENTER should not cause the macro body to execute; only for the macro to expand.
To parameterize the above macro, we could do
```
In [3]: macro( 'FORN(N)', 'for ( let i = 0; i < N; i++ ) {' );
```
where `N` is a macro parameter. To use,
```
In [4]: FORN( 100 )
```
would, after hitting ENTER, expand to
```
In [5]: for ( let i = 0; i < 100; i++ ) {<|>
```
where `<|>` is the cursor.
### Related Issues
No.
### Questions
- Do we want to support recursive macro definitions? My guess is no, at least to start, as that makes things rather complex. It is doable, I suppose. Just keep performing macro substitution until one can no longer find macro definitions.
- What should happen when a user embeds a MACRO among other expressions:
```
In [1]: foo; FOR console.log( i ); }; beep
```
Presumably, we'd need to check for the presence of macros BEFORE attempting to evaluate a line. If a macro is found, then we must expand and then the user needs to press ENTER again in order to execute.
- Are there any built-in macros we'd want to support?
- Longer term, we'd probably want to support allowing a user to define macros at REPL instantiation (e.g., through configuration or a startup file).
- IPython also allows defining macros based on line number(s). Would we want to support something similar? This assumes that line numbers are displayed (i.e., that a user has not changed the input prompt). If we chose to support, would we support via a different API or overload the same API?
- We'd want to be careful regarding substitution. For example, if a macro has a parameter `N`, we'd need to avoid replacing the N in `fooNbar`. This may be tricky to get right, so may be worth studying how C macro parameter substitution works and consider emulating. As another idea, we could support a macro string syntax similar to template strings or `@stdlib/string/format`, where there's a special markup for placeholders which should be replaced by provided arguments.
### Other
- Magic support in IPython: https://ipython.readthedocs.io/en/stable/interactive/magics.html?highlight=magic#magic-macro
- C style macros:
- https://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC10
- https://gcc.gnu.org/onlinedocs/cppinternals/Macro-Expansion.html
### Checklist
- [X] I have read and understood the [Code of Conduct](https://github.com/stdlib-js/stdlib/blob/develop/CODE_OF_CONDUCT.md).
- [X] Searched for existing issues and pull requests.
- [X] The issue name begins with `RFC:`.
Contributor guide
Assessment
This issue has not been assessed yet.