On 6/3/25 11:57 AM, Koichi Murase wrote:
xx. <( and >( can now be used in function names.

What is the background of this change? This was added in commit
315095ad, and to the best of my knowledge, an email on the mailing
list in the same period and related to this change would be Ref. [1]
from kre.

I wrote:

"There's no good reason to reduce the possible function namespace below
what's allowed for external commands."


[1] https://lists.gnu.org/archive/html/bug-bash/2023-02/msg00007.html

There is a very good reason to allow function names to contain almost
any character at all. [...]

However, the interpretation of the bare `<(' and `>(' in Bash 5.3
seems to contradict the design discussed in Ref. [1].

Because it was kre's message and suggestion.

Bash 5.3
interprets the bare <( and >( as an introducer of process
substitutions, and the defined function has the source code of the
parsed process substitution.

   $ bash-devel -c '<(echo hello) () { echo hello; }; declare -F'
   declare -f <(echo hello)

That's the function name. In general, a function name is a WORD that
does not undergo any word expansions, not even quote removal. Previous
versions of bash used to audit function names for prohibited characters;
bash-5.3 reduces the number of prohibited characters.


However, Ref. [1] discusses the function definition of the form like «
'<()' () { ...; } » (instead of « <() () { ...; } » which was
Implemented in Bash 5.3):

OK.


Note that no expansions are specified to happen on the function name
in a function definition, so $var() isn't ever going to create a function
named by the value of var - you need eval for that.   Because of that
the NetBSD shell requires any function definition which contains something
that looks like a var/command/arith expansion to be quoted such as to make
it clear the user knows that isn't going to happen - we'd reject the $var()
case, but allow '$var'() or \$var() (but not "$var"() - "\$var"() works
however.)

Bash doesn't perform quote removal on function names.


In Bash 5.3, the defined function name isn't even the literal process
substitution, but a somewhat prettified version (which is non-trivial
to predict):

   $ bash-devel -c $'<(\n  # ignored\necho          hello\n) () { echo
hello; }; declare -F'
   declare -f <(echo hello)

The idea is that you parse a word as a potential process substitution,
which requires calling the parser to determine whether or not it's valid
and where the closing paren appears. At that point, you don't know
whether or not it's going to be used as a function name. Process
substitutions and command substitutions are reconstituted as an equivalent
text version of the parsed command, which in this case leaks through to
the word that's used as the function name.

What would be the use case of this feature, and what is the rationale
for this design?

The rationale is to expand the function namespace closer to that of
commands. There isn't anything forcing you to use them.

The current behavior doesn't seem to make sense to me. If it was
implemented after Ref. [1], « '<(echo hello)' () { echo hello; } »
should have been supported but not « <(echo hello) () { echo hello;
}.».

But that would have required bash to perform quote removal on function
names, and I wasn't going to go that far.


Ref. [1] argued that "$" expansions should not happen in the function
name in the function definition, but in my opinion, there is room to
optionally support expansions in the function names of function
definitions (such as « "$namespace::func"() { ...; } » as I suggested
a few times on the mailing list in the past).

OK, but that's not what we're doing here, and I wasn't willing to go
that far for bash-5.3.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    c...@case.edu    http://tiswww.cwru.edu/~chet/

Reply via email to