2025年9月3日(水) 1:21 Martin D Kealey <mar...@kurahaupo.gen.nz>:
> 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. 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 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.

Suppose we want to add a hypothetical option to use PCRE for regex
matching in [[ str =~ regex ]], we add an option `shopt -s
parse_regex_pcre' (which doesn't affect the scoping of existing shell
options). (In case, I don't suggest adding the built-in support for
PCRE, but it's just an example.) Since how this new type of options is
applied is different from the traditional shopt options, it might
deserve a new builtin (other than `shopt' or `set'), but it is
generally avoided to add a new reserved word. Practically, while still
using `shopt', we can clarify that it is applied at the parsing time
by naming an option with a specific prefix (such as `parse_' and
`lex_').

  # MyLib.bash
  shopt -s parse_regex_pcre
  myfunc() {
    [[ foo =~ bar ]]
  }

> Admittedly extglob isn't an ideal example, since in practice one
> would just set it at the file level, but I'm trying to illustrate
> how it could change a setting during parsing.

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)..Although it is still technically possible
to switch `shopt -s/-u parse_regex_pcre' between function definitions
so that two functions use different rules, I don't think we want to
use two different behaviors within a single function by switching the
option in the middle of parsing a function.

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.

> Question: if file A sources for B, and file B sources file C, but
> only file B indicates it expects lexical option scoping, should file
> A and file C see each other's changes?

I think this is based on your assumption on `shopt -s lexical'. I
didn't intend an option like `lexical', and I don't think it is good
to provide a way to switch the scoping of options. It introduces
unnecessary confusions. New language-level options should *always* be
applied at the parsing time, and existing language-level options
should keep its current behavior for backward compatibility. It's too
late to change existing ones. If a lexically scoped version 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.

> While we're at it, please can we have lexically scopes variables in
> functions?

It is a different topic, and I don't think it is relevant to the
present discusssion. 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. As I wrote in a relevant thread in
the past, I think lexically-scoped variables should be provided
through a distinct way of declaration such as `local -l var' (as done
in Perl with `my').

> Maybe « function foo -o compat=60 -o extglob -o nullglob … { …; } »?

With that syntax, Zsh defines multiple functions of the same content,
which can be observed with the following command:

$ zsh -c 'function foo -o compat=60 -o extglob -o nullglob ... { echo;
}; declare -f'

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.

>> ». Note that in this example, one needs to explicitly unset an option
>> `zzz' by `+o zzz' because `zzz' might be turned on in the context
>> where `eval' is performed.
>
> 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.

--
Koichi

Reply via email to