qi(1): Builtins #154

Open
opened 2024-08-04 09:43:59 -06:00 by emma · 3 comments
Owner

I don't like the shell built-in shift.

  • It seems to mainly exist as an equivalent to the C idiom ++argv; --argc; which is (given the benefit of >30 years of hindsight since C89) a complicating and not very readable way to save memory processing arguments.

  • Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.

  • It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.

  • It's inflexible; it can only be used for the one task of shifting through arguments.

shift is the only real way to iterate over arguments ($1, $2, $3...) in shell. Particularly with the following idiom:

argv0="$0" # save $0
while test -n "$1" # while there is a remaining argument to use
    do
    printf '%s argument: %s\n' "$argv0" "$1" # example use
    shift # <--- boo!
done

What if variables could hold the names of other variables? Not like pointers in C but simply:

foo = 5;
# 5 is a string; this is still stringly typed like sh

bar = foo;

out "$[bar]";
# out means echo (no options allowed)
# the [square brackets] mean expand what is inside bar
# and then use that variable
# $[bar] becomes
# $foo because bar == "foo"

This could be used for better argument usage:

seq 1 $# \
| for i { out "$0 argument: $[i]" }

for in this example is a shell built-in that, for each line in standard input, sets the given variable (in this case i) to that line's content before running the commands in the curly braces. seq(1) in this usage prints a new-line delimited list of integers in the sequence described in its arguments. out is an analogue to echo(1) as currently being described in #27.

This might be a terrible idea that can be used to write terrible scripts. Also, there is no real concept of betta(1) yet, so I'm basing my examples off sh(1p).

Originally posted by @trinity in #8 (comment)

I don't like the shell built-in `shift`. - It seems to mainly exist as an equivalent to the C idiom `++argv; --argc;` which is (given the benefit of >30 years of hindsight since C89) a complicating and not very readable way to save memory processing arguments. - Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this. - It necessitates storing `"$0"` as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do. - It's inflexible; it can only be used for the one task of shifting through arguments. `shift` is the only real way to iterate over arguments (`$1`, `$2`, `$3`...) in shell. Particularly with the following idiom: ```sh argv0="$0" # save $0 while test -n "$1" # while there is a remaining argument to use do printf '%s argument: %s\n' "$argv0" "$1" # example use shift # <--- boo! done ``` What if variables could hold the names of other variables? Not like pointers in C but simply: ``` foo = 5; # 5 is a string; this is still stringly typed like sh bar = foo; out "$[bar]"; # out means echo (no options allowed) # the [square brackets] mean expand what is inside bar # and then use that variable # $[bar] becomes # $foo because bar == "foo" ``` This could be used for better argument usage: ``` seq 1 $# \ | for i { out "$0 argument: $[i]" } ``` `for` in this example is a shell built-in that, for each line in standard input, sets the given variable (in this case `i`) to that line's content before running the commands in the curly braces. [seq(1)](https://www.man7.org/linux/man-pages/man1/seq.1.html) in this usage prints a new-line delimited list of integers in the sequence described in its arguments. `out` is an analogue to echo(1) as currently being described in #27. This might be a terrible idea that can be used to write terrible scripts. Also, there is no real concept of betta(1) yet, so I'm basing my examples off sh(1p). _Originally posted by @trinity in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2873_
Author
Owner

It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do.

shift(1) does not modify the value of $0, actually. From shift(1p):

DESCRIPTION
       The positional parameters shall be shifted. Positional parameter 1
       shall be assigned the value of parameter (1+n), parameter 2 shall be
       assigned the value of parameter (2+n), and so on. The parameters
       represented by the numbers "$#" down to "$#-n+1" shall be unset, and
       the parameter '#' is updated to reflect the new number of positional
       parameters.

       The value n shall be an unsigned decimal integer less than or equal to
       the value of the special parameter '#'.  If n is not given, it shall be
       assumed to be 1. If n is 0, the positional and special parameters are
       not changed.

Originally posted by @emma in #8 (comment)

> It necessitates storing "$0" as a new shell variable to be able to continue using it, which shell authors writing diagnostics messages and following good practice always want to do. shift(1) does not modify the value of `$0`, actually. From shift(1p): ``` DESCRIPTION The positional parameters shall be shifted. Positional parameter 1 shall be assigned the value of parameter (1+n), parameter 2 shall be assigned the value of parameter (2+n), and so on. The parameters represented by the numbers "$#" down to "$#-n+1" shall be unset, and the parameter '#' is updated to reflect the new number of positional parameters. The value n shall be an unsigned decimal integer less than or equal to the value of the special parameter '#'. If n is not given, it shall be assumed to be 1. If n is 0, the positional and special parameters are not changed. ``` _Originally posted by @emma in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2875_
Author
Owner

Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this.

From: "Lawrence Velázquez" <vq@larryv.me>                                                                                     To: "Christoph Anton Mitterer" <calestyo@scientia.org>, "Emma Tebibyte" <emma@tebibyte.media>                                
Cc: <dash@vger.kernel.org>                                                                                                    Bcc:                                                                                                                         
Date: 2023-12-06 10:29 PM                                                                                                                                                                                                                                  
Subject: Re:                                                                                                                                                                                                                                               
                                                                                                                                                                                                                                                           
On Thu, Dec 7, 2023, at 12:00 AM, Christoph Anton Mitterer wrote:                                                                                                                                                                                          
> On Wed, 2023-12-06 at 21:40 -0700, Emma Tebibyte wrote:                                                                                                                                                                                                  
>> I found a bug in dash version 0.5.12 where when shifting more than                                                                                                                                                                                      
>> ?#,                                                                                                                                                                                                                                                     
>> the shell exits before evaluating a logical OR operator.                                                                                                                                                                                                
>                                                                                                                                                                                                                                                          
> AFAIU from POSIX this is perfectly valid behaviour:                                                                                                                                                                                                      
>                                                                                                                                                                                                                                                          
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift                                                                                                                                                                          
>                                                                                                                                                                                                                                                          
>> EXIT STATUS                                                                                                                                                                                                                                             
>> If the n operand is invalid or is greater than "$#", this may be                                                                                                                                                                                        
>> considered a syntax error and a non-interactive shell may exit; if                                                                                                                                                                                      
>> the shell does not exit in this case, a non-zero exit status shall                                                                                                                                                                                      
>> be returned. Otherwise, zero shall be returned.                                                                                                                                                                                                         
                                                                                                                                                                                                                                                           
See also Section 2.8.1 [*], which states that interactive shells                                                                                                                                                                                           
shall not exit on special built-in utility errors and that:                                                                                                                                                                                                
                                                                                                                                                                                                                                                           
        In all of the cases shown in the table where an interactive                                                                                                                                                                                        
        shell is required not to exit, the shell shall not perform                                                                                                                                                                                         
        any further processing of the command in which the error                                                                                                                                                                                           
        occurred.                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                           
[*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01                                                                                                                                                                 
                                                                                                                                                                                                                                                           
--                                                                                                                                                                                                                                                         
vq                                                                                                                                                                                                                                                             

Originally posted by @emma in #8 (comment)

> Its definition in POSIX makes it unintuitive for shell scripters. Emma should elaborate here when fae has time, fae has more experience with this. ``` From: "Lawrence Velázquez" <vq@larryv.me> To: "Christoph Anton Mitterer" <calestyo@scientia.org>, "Emma Tebibyte" <emma@tebibyte.media> Cc: <dash@vger.kernel.org> Bcc: Date: 2023-12-06 10:29 PM Subject: Re: On Thu, Dec 7, 2023, at 12:00 AM, Christoph Anton Mitterer wrote: > On Wed, 2023-12-06 at 21:40 -0700, Emma Tebibyte wrote: >> I found a bug in dash version 0.5.12 where when shifting more than >> ?#, >> the shell exits before evaluating a logical OR operator. > > AFAIU from POSIX this is perfectly valid behaviour: > > https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#shift > >> EXIT STATUS >> If the n operand is invalid or is greater than "$#", this may be >> considered a syntax error and a non-interactive shell may exit; if >> the shell does not exit in this case, a non-zero exit status shall >> be returned. Otherwise, zero shall be returned. See also Section 2.8.1 [*], which states that interactive shells shall not exit on special built-in utility errors and that: In all of the cases shown in the table where an interactive shell is required not to exit, the shell shall not perform any further processing of the command in which the error occurred. [*] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_01 -- vq ``` _Originally posted by @emma in https://git.tebibyte.media/bonsai/harakit/issues/8#issuecomment-2877_
emma added the
enhancement
help wanted
question
labels 2024-08-04 09:59:27 -06:00
emma added this to the `qi(1)` project 2024-08-04 09:59:29 -06:00
Owner

The only built-in commands I see as absolutely necessary are let (or a way to change the shell environment; see #152) and cd or chdir.

The argument that built-ins drastically speed up shell scripts by avoiding the overhead of spawning a new process is fair but doesn't sway me as built-ins are often a great source of confusion (echo -n foo and $(command -v foo) disagreeing is always weird).

The only built-in commands I see as absolutely necessary are `let` (or a way to change the shell environment; see #152) and `cd` or `chdir`. The argument that built-ins drastically speed up shell scripts by avoiding the overhead of spawning a new process is fair but doesn't sway me as built-ins are often a great source of confusion (`echo -n foo` and `$(command -v foo)` disagreeing is always weird).
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: bonsai/harakit#154
No description provided.