Skip to content

Do not exit from 'es -e' due to assignments#279

Merged
jpco merged 1 commit into
wryun:masterfrom
jpco:falseassignments
May 25, 2026
Merged

Do not exit from 'es -e' due to assignments#279
jpco merged 1 commit into
wryun:masterfrom
jpco:falseassignments

Conversation

@jpco
Copy link
Copy Markdown
Collaborator

@jpco jpco commented May 25, 2026

When assignments were made to return values, this caused any shell running with the -e flag to exit whenever an assignment was performed.

While this isn't technically a bug in the sense of causing the shell to crash or violating the assumptions of an outside system, here's why I think it's obviously wrong:

  1. It's inconsistent with every other shell, including rc. Es inherited the -e flag from rc, but assignments in rc do not cause the shell to exit. Nor do they in bash, or zsh, or dash, or ksh, or tcsh.

  2. It's inconsistent with older versions of es: If you git checkout v0.84 and manage to get it to build, you'll find that assignments didn't cause the shell to exit back then. Yes, this is because back then they didn't produce a value, and now they do. However, in practical use assignments are thought of much less as value-producing commands and much more as, well, ways to modify variable values.

  3. It's unbelievably hard to use. A script that follows the current requirements of -e can only set values inside of let or local binders -- which is technically possible, but really unnecessarily tricky. For something that is effectively a convenience mechanism, this is a very strange way to be. Worse,

  4. It doesn't even work with built-in functions in initial.es. Both the vars function and the %background hook assign falsey values to variables (default flags and PIDs, respectively) on perfectly valid, successful calls, and have done so since (at least) 0.84. It is absurd to think that it was ever intended that vars and %background shouldn't be callable from an es -e script.

  5. At a high level, it just doesn't make much sense. As wryun put it, "[t]he way I think about '-e' is that it's trying to catch results you've ignored, and if you've assigned the result you haven't ignored it". Supposedly, -e is meant to be a "safety-by-default" convenience mechanism, but what possible safety is gained by disallowing assignments?

es -e is pretty obviously not exercised much, given #180 and what it mentions about while -- as written in initial.es today, the body of a while is run inside an if test, so it doesn't get es -e protection at all. So I think there is very little backwards compatibility to worry about.

This is technically adding an exception to the semantics of es -e, and the man page has had a couple sentence fragments added to account for that. However, it's a much more minor exception than the fact that the -e behavior is turned off (dynamically) in the test of an if, which tends to cause surprising behavior when that test calls other functions (see #176). So this mechanism is hardly conceptually "clean" anyway -- why not at least make it halfway useful and culturally compatible?

When assignments were made to return values, this caused any shell
running with the `-e' flag to exit whenever an assignment was performed.
This makes the `-e' flag effectively unusable.
@jpco jpco merged commit 98d2d71 into wryun:master May 25, 2026
1 check passed
@jpco jpco deleted the falseassignments branch May 25, 2026 13:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant