On Sat, Oct 15, 2016 at 7:58 PM, Marco Ippolito <maroloc...@gmail.com> wrote:
> On Sat, Oct 15, 2016 at 07:32:23PM +0800, konsolebox wrote:
>> On Sat, Oct 15, 2016 at 11:12 AM, Marco Ippolito <maroloc...@gmail.com> 
>> wrote:
>> > Bash has elegant and powerful constructs like `mapfile',
>> > yet it is missing something as easy as an array "pop".
>> >
>> > Extract the last value of an array at the same time as
>> > removing it from the array.
>> >
>> > Is this the best one can do?
>> >
>> > $ a=(1 2 3); v=${a[-1]}; unset 'a[-1]'; printf '%s\n' "$v" "${a[@]}"
>> >
>> > The 2-step approach gets tiresome after a while.
>> >
>> > For positional parameters, it _does_ have `shift'...
>> > ... maybe it could add a `pop`, somehow?
>> >
>> Since you're using Bash-4.3 (or 4.4), you can create a function that
>> uses declare -n:
>> $ function array_pop { declare -n __a=$1; __=${__a[-1]}; unset '__a[-1]'; }
>> $ a=(1 2 3); array_pop a; printf '%s\n' "$__" "${a[@]}"
>> 3
>> 1
>> 2
>> And my simple rule to using functions that process variables with -n:
>> don't pass variables that begin with two underscores.  There's another
>> way to avoid variable name conflicts, and that is to prefix the
>> reference variables with the name of the function itself, but I find
>> that already an overkill.
>> You can also improve the function by adding sanity checks, but that's
>> the basic concept of it.
>> --
>> konsolebox
> Nice function but there is something I dislike about it.
> I find the alteration of global state as a side-effect in contradiction with
> the notion of self-containment of functions, e.g.:
>     $ unset x; printf '|%s|\n' "$x"; f() { x=y; }; f; printf '|%s|\n' "$x"
>     ||
>     |y|
> The potential overwriting of a pre-existing identifier `__' is, in my eyes,
> undesirable.
> Shouldn't I be able to call a function without worrying about what it could do
> to my current scope? (This may be a debatable point for some).

Oh so you actually meant my use of __.  Sorry I just got used to that
practice.  I treat __ as a "volatile global variable" i.e., one should
expect that it can change on every call to another function.  I
prefer things done that way since it's more efficient, and/or is more
doable in older versions of bash.  This time I use it as a result
variable, but sometimes I use it as a common "iterator", or just a
temporary variable.

You can follow lolilolicon's suggestion if you want to pass another
variable that would store the value instead.

My version would be this:

function array_pop { declare -n __a=$1 __v=$2; __v=${__a[-1]}; unset
'__a[-1]'; }

By the way, please use "Reply to all" so your message would also be
sent to bug-bash.  You can also have that configured in Gmail so that
it would be the default behavior.


Reply via email to