On Wed, 3 Sept 2025 at 07:17, Koichi Murase <[email protected]> wrote:

> 2025年9月3日(水) 1:21 Martin D Kealey <[email protected]>:
> > I really like this approach, but I suspect it will lead to a need
> > for something akin to Perl's "use" or "BEGIN" keywords to execute
> > code as soon as they're fully parsed, even if the encoding block
> > hasn't finished parsing.
> >
> > Then we could write something like this:
> >
> > >>MyLib.bash<<
> > shopt -s lexical
> > myfunc() {
> >   BEGIN { shopt -s extglob; }
> >   echo *(.)foo  #  safe because « shopt -s extglob » runs before parsing
> this line
> > }
>
> Hmm, it seems different from what I have in my mind.


To be fair, BEGIN { LIST;} is overly general, but if it could be
implemented then almost everything else can be done with ordinary shell
functions, meaning we can experiment and see what works best in practice.

In part I formulated this construct as a response to the idea that “shopt”
or “local” could do double duty as both a parse-time controls (necessarily
being keywords) *and* run-time commands, depending on whether its arguments
include an option such as “-l”; I see that as problematic.

I would rather see a new, separate keyword, though not necessarily as
general as “BEGIN”; one alternative could be:

use shopt -s extglob

where « use » is a new keyword, taking « shopt » as a fixed first argument
indicating that the following args are new-style options.

Errors while handling « use » declarations would be handled similarly to
syntax errors, but hopefully with more helpful error messages.

What is the "lexical" option in the above example?

Do you mean by the "lexical" option a feature to use the lexical scoping
> for existing shell options (including `extglob')?


I was assuming there would need to be *something* to say "use the new
style"; I wrote « shopt -s lexical » just as a fill-in until we figure out
exactly how this should work.

There especially needs to be a trigger that enables new keywords (or
converts existing commands into keywords), unless we're going to accept new
keywords that are intentionally obscure to minimise the risk of conflict
with command names in existing scripts.

I didn't mean to switch the scoping of existing shell options,
> but I meant that the scoping of new language-level options should be
> *fixed* to lexical scoping.
>

In addition there needs to be some way to block all outer options from
influencing how an inner file is parsed, and preferably without changing
how the outer file sources the inner file (because pluggability is
desirable).

My idea is to force a consistent behavior within a file, so that the
> "language-level" options should be set up at the top level around the
> beginning of the file, and all loops and functions in the file should
> be written using the same "verson of Bash language" (defined by a set
> of language-level options).


For options that principally affect parsing, I agree; just put them at the
top of the file.

But for options that affect behaviour, such as noglob or globasciiranges or
nounset, there are reasonable cases where different behaviour is necessary
in different parts of the same file, and so tighter lexical scope is
desirable.

If a shell option needs to be switched within a single function, it
> implies that the option provides two distinct features (where the
> result with one side of the option cannot be easily achieved with the
> other side of the option) and a function wants to use both features.
>


> In this case, the two distinct features shouldn't be provided through
> a shell option, but they should have distinct ways to call.
>

In general I'd agree, but for something as fundamental as globbing, that's
kinda awkward.


If a lexically scoped version *[of an existing globally scoped option] *is
> needed,
> it should be given a new name like « shopt -s parse_extglob », though
> how it should interact with `extglob' would require further
> consideration.
>

I would rather that lexical options and global options simply exist in
separate namespaces, so it's clear from context which is intended, even if
they have the same names.

Considering the case where we want to use both
> types of variables in a single function, I don't think it should be
> introduced through a shell option.


Actually I agree. I've been looking more closely at ksh lately, and in
particular its namespace feature.

If Bash had namespaces then we could simply have lexically scoped variables
in their own namespace, and then it's just a matter of nominating or
implying the default namespace for a function, or explicitly specifying
which when using the variable.

I would similarly suggest that there be an implicit per-file namespace as
well, at least for files that opt into the new scheme.

> Maybe « function foo -o compat=60 -o extglob -o nullglob … { …; } »?
>
> With that syntax, Zsh defines multiple functions of the same content,
>

Aww sheesh. Zsh is a great idea, a fresh implementation devoid of
historical baggage, but then it adds stuff like this in ways that clobber
potential extension spaces. IMO some zsh extensions are NOT worth emulating.

I'm not sure if we want a similar feature in the future, but at least,
> I think we want to avoid a confusing syntax as much as possible.
>

I would strongly prefer a syntax that didn't comprise multiple statements
that have to be executed in sequence.
Ideally the same syntax would work if/when we add lexically scoped
functions.

Or if it *has* to be that way, the function body should come last, so it's
not usable until all attributes are attached.

> With « -o compat=60 » in my example we then only need a list of
> > options that don't match, rather than all of them.
>
> That seems a valid solution.


Thanks

-Martin

Reply via email to