What's the idiomatic way of returning an array in a zsh function?

Hap*_*ace 4 zsh array function

I have this function,

rpargs () {
    local i
    args=()
    for i in "$@"
    do
        test -e "$i" && args+="$(realpath --canonicalize-existing -- "$i")"  || args+="$i"
    done
}
Run Code Online (Sandbox Code Playgroud)

And I want to return args. The only ways I can think of are either to printf '%s\0' and then split it via expansion flags (0@), or to use a global like the code above.

Sté*_*las 8

zsh's return builtin can only return a 32bit signed integer like the _exit() system call. While that's better than most other Bourne-like shells, that still can't return arbitrary strings or list of strings like the rc/es shells. The return status is more about returning a success/failure indication.

Here, alternatively, you can have the function take the name of the array to fill in as argument, like:

myfunc() {
  local arrayname=$1; shift
  # ...
  eval $arrayname'=("$elements[@]")'
  # the returned $? will be 0 here for success unless that eval command
  # fails.
}

myfunc myarray other args
Run Code Online (Sandbox Code Playgroud)

Your printf '%s\0' approach wouldn't work for array elements that contain NULs.

相反,您可以使用qq参数扩展标志来引用输出上的元素,以及输入上的z(解析引号)和Q(删除引用),例如:

myfunc() {
   # ...
   print -r -- ${(qq)elements}
}

myarray=("${(@Q)${(z)$(myfunc)}}")
Run Code Online (Sandbox Code Playgroud)

但除了不太清晰之外,它的效率也较低,因为它意味着myfunc除了引用/取消引用之外,还需要分叉一个进程并通过管道传输输出。


psp*_*int 6

惯用的方法是只使用reply数组。如果需要,您可以使用该(P)标志并在其名称传递给函数的数组中返回:

myfunc() {
  local arrayname=${1:-reply}; shift
  # ...
  : ${(PA)arrayname::="${args[@]}"}
}
Run Code Online (Sandbox Code Playgroud)