[SOLVED] What is the zsh idiom for using functions that can return success or failure as well as a list

Issue

I am looking for the "best way" or the accepted zsh idiom for creating and using functions that can return success or failure as well as a list or other text value.

Currently I am doing this:

function happy
{
    local happy_list=( a b c d )

    if true ; then
        echo $happy_list
        return 0
    else
        return 1
    fi
}

function sad
{
    local sad_list=( a b c d )

    if false ; then
        echo $sad_list
        return 0
    else
        return 1
    fi
}

echo happy
if happy_result=( $( happy ) ) ; then
    echo '$?:' $?
    echo '$#happy_result' $#happy_result
    echo '$happy_result' $happy_result
    echo '$happy_list:' $happy_list
else
    echo '!?!?!?!?'
fi

echo
echo sad
if sad_result=( $( sad ) ) ; then
    echo '!?!?!?!?'
else
    echo '$?:' $?
    echo '$#sad_result' $#sad_result
    echo '$sad_result:' $sad_result
    echo '$sad_list:' $sad_list
fi

which results in

happy
$?: 0
$#happy_result 4
$happy_result a b c d
$happy_list:

sad
$?: 1
$#sad_result 0
$sad_result:
$sad_list:

Is there a cleaner method? In particular the foo=( $( func ) ) syntax seems it could be improved since the list is already created in the func.

Update to moderator: I believe now this is a duplicate of this question and my preferred answer (if anyone cares) is this answer. The suggestion in Meta was to close and merge. I don’t know how to do the merge. Can a moderator help me out?

Solution

The usual idiom in zsh is to return scalar results in the $REPLY variable and array results in the $reply array:

all-files-in() {
  reply=( $^@/*(ND) )
  (( $#reply ))
}

if all-files-in /foo /bar; then
  print -r there were files: $reply
else
  print -ru2 there were none
fi

Another approach is for the caller to specify the name of the variable where to store the result and use eval or the P parameter expansion flag to do indirect assignments.

all-files-in() {
  eval $1='( $^@[2,-1]/*(ND) )
  (( $#'$1' ))'
}

if all-files-in files /foo /bar; then
  print -r there were files: $files
else
  print -ru2 there were none
fi

Answered By – Stephane Chazelas

Answer Checked By – Katrina (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.