Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Questions arise while implementing list-ops exercise as library implementation #375

Closed
glennj opened this issue Aug 14, 2019 · 4 comments
Closed

Comments

@glennj
Copy link
Contributor

glennj commented Aug 14, 2019

I’m implementing list-ops as a library, and I've got some questions about the best way to proceed. Consider

source list_ops.sh
double() { echo $(( $1 * 2 ));}
list=( 1 2 3 4 )
list::map double list   # or
list::map double "${list[@]}"

Should the array be passed by name, or should the elements be passed? For a map function it doesn't really matter, but if the list function is something like intersection it would make more sense to pass 2 array names.

Also, struggling with the best way to return a result array:

  • the safest way is to force the user to pass an array name:
result=()
list::map double list result    # in some order
printf "%s\n" "${result[@]}"
  • the simpler method, command substitution, is subject to word splitting and globbing:
result=( $( list::map double list ) )
@glennj
Copy link
Contributor Author

glennj commented Aug 14, 2019

For testing, this is what I’ve got in the test script (pending this discussion): run receives an inline bash script.

@test "map non-empty list" {
    [[ $BATS_RUN_SKIPPED == true ]] || skip
    run bash -c '
        source list_ops.sh
        list=(1 3 5 7)
        incr () { echo $(( $1 + 1 )); }
        #result=( $(list::map incr "${list[@]}") )
        result=( $(list::map incr list) )
        echo "${result[*]}"
    '
    [[ $status -eq 0 ]]
    [[ $output == "2 4 6 8" ]]
}

@glennj
Copy link
Contributor Author

glennj commented Aug 14, 2019

Relates to #373

@glennj
Copy link
Contributor Author

glennj commented Aug 14, 2019

Just tried another take in the test file:

setup() { source list_ops.sh; }

@test "foo" {
    run bash -c '
        list=(1 3 5 7)
        incr () { echo $(( $1 + 1 )); }
        result=( $(list::map incr list) )
        echo "${result[*]}"
    '
    [[ $status -eq 0 ]]
    [[ $output == "2 4 6 8" ]]
}

The test failed due to the list::map function not existing in the child shell created by run.

This way of writing the tests forces the library to export -f each function.

Is that something a shell library should do?

@IsaacG
Copy link
Member

IsaacG commented Aug 14, 2019

bash sucks at this sort of thing. Consider using known list names. listA listB result. The function is responsible to read from those lists and write to that list.

The only real alternative is to pass variable names all over and use indirection.

@glennj glennj closed this as completed Jul 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants