-
-
Notifications
You must be signed in to change notification settings - Fork 684
Update variadic-functions concept docs
#3062
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
Open
BNAndras
wants to merge
1
commit into
exercism:main
Choose a base branch
from
BNAndras:update-variadic-functions-concept
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+50
−144
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,10 @@ | ||
| { | ||
| "blurb": "Variadic functions allow for an arbitrary number of arguments to be passed to a function.", | ||
| "authors": ["myworkcircle"], | ||
| "contributors": ["junedev"] | ||
| "blurb": "A variadic function accepts any number of arguments for its final parameter.", | ||
| "authors": [ | ||
| "myworkcircle" | ||
| ], | ||
| "contributors": [ | ||
| "BNAndras", | ||
| "junedev" | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,108 +1,43 @@ | ||||||||
| # About | ||||||||
|
|
||||||||
| Usually, functions in Go accept only a fixed number of arguments. | ||||||||
| However, it is also possible to write variadic functions in Go. | ||||||||
|
|
||||||||
| A variadic function is a function that accepts a variable number of arguments. | ||||||||
|
|
||||||||
| If the type of the last parameter in a function definition is prefixed by ellipsis `...`, then the function can accept any number of arguments for that parameter. | ||||||||
| Typically, functions accept only a fixed number of arguments. | ||||||||
| Prefix the last parameter's type with `...` to accept any number of trailing arguments: | ||||||||
|
|
||||||||
| ```go | ||||||||
| func find(a int, b ...int) { | ||||||||
| // ... | ||||||||
| func sum(nums ...int) int { | ||||||||
| total := 0 | ||||||||
| for _, n := range nums { | ||||||||
| total += n | ||||||||
| } | ||||||||
| return total | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| In the above function, parameter `b` is variadic and we can pass 0 or more arguments to `b`. | ||||||||
|
|
||||||||
| ```go | ||||||||
| find(5, 6) | ||||||||
| find(5, 6, 7) | ||||||||
| find(5) | ||||||||
| ``` | ||||||||
|
|
||||||||
| ~~~~exercism/caution | ||||||||
| The variadic parameter must be the last parameter of the function. | ||||||||
|
|
||||||||
| If you try to write code like this ... | ||||||||
| Inside the function, the variadic parameter is a slice: | ||||||||
|
|
||||||||
| ```go | ||||||||
| func find(...a int, b int) {} | ||||||||
| sum(1, 2, 3) // nums is []int{1, 2, 3} | ||||||||
| sum(1, 2, 3, 4) // nums is []int{1, 2, 3, 4} | ||||||||
| sum() // nums is []int{} | ||||||||
| ``` | ||||||||
|
|
||||||||
| ... it will fail to compile with the syntax error `cannot use ... with non-final parameter b.` | ||||||||
|
|
||||||||
| Imagine the function above would work and we pass multiple arguments. | ||||||||
| Then all those arguments will get assigned to `a` and nothing would be assigned to `b`. | ||||||||
| Hence, variadic parameter must be provided at the end. | ||||||||
| ~~~~ | ||||||||
|
|
||||||||
| The way variadic functions work is by converting the variable number of arguments to a slice of the type of the variadic parameter. | ||||||||
|
|
||||||||
| Here is an example of an implementation of a variadic function. | ||||||||
| A function can have non-variadic parameters before the variadic one: | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
|
||||||||
| ```go | ||||||||
| func find(num int, nums ...int) { | ||||||||
| fmt.Printf("type of nums is %T\n", nums) | ||||||||
|
|
||||||||
| for i, v := range nums { | ||||||||
| if v == num { | ||||||||
| fmt.Println(num, "found at index", i, "in", nums) | ||||||||
| return | ||||||||
| } | ||||||||
| func greet(greeting string, names ...string) { | ||||||||
| for _, name := range names { | ||||||||
| fmt.Printf("%s, %s!\n", greeting, name) | ||||||||
| } | ||||||||
|
|
||||||||
| fmt.Println(num, "not found in ", nums) | ||||||||
| } | ||||||||
|
|
||||||||
| func main() { | ||||||||
| find(89, 90, 91, 95) | ||||||||
| // Output: | ||||||||
| // type of nums is []int | ||||||||
| // 89 not found in [90 91 95] | ||||||||
|
|
||||||||
| find(45, 56, 67, 45, 90, 109) | ||||||||
| // Output: | ||||||||
| // type of nums is []int | ||||||||
| // 45 found at index 2 in [56 67 45 90 109] | ||||||||
|
|
||||||||
| find(87) | ||||||||
| // Output: | ||||||||
| // type of nums is []int | ||||||||
| // 87 not found in [] | ||||||||
| } | ||||||||
| ``` | ||||||||
|
|
||||||||
| In line `find(89, 90, 91, 95)` of the program above, the variable number of arguments to the find function are `90`, `91` and `95`. | ||||||||
| The `find` function expects a variadic int parameter after `num`. | ||||||||
| Hence these three arguments will be converted by the compiler to a slice of type `int` `[]int{90, 91, 95}` and then it will be passed to the find function as `nums`. | ||||||||
|
|
||||||||
| Sometimes you already have a slice and want to pass that to a variadic function. | ||||||||
| This can be achieved by passing the slice followed by `...`. | ||||||||
| That will tell the compiler to use the slice as is inside the variadic function. | ||||||||
| The step described above where a slice is created will simply be omitted in this case. | ||||||||
| ## Spreading a slice | ||||||||
|
|
||||||||
| ```go | ||||||||
| list := []int{1,2,3} | ||||||||
| find(1, list...) // "find" defined as shown above | ||||||||
| // Output: | ||||||||
| // type of nums is []int | ||||||||
| // 1 found at index 0 in [1 2 3] | ||||||||
| ``` | ||||||||
|
|
||||||||
| It is important to note that `...` is not an actual rest and spread operator in Go. | ||||||||
| For example, the following code does not compile. | ||||||||
| To pass a slice into the variadic parameter, follow it with `...`: | ||||||||
|
|
||||||||
| ```go | ||||||||
| func myFunc(a int, b int, c int) { | ||||||||
| // ... | ||||||||
| } | ||||||||
|
|
||||||||
| func main() { | ||||||||
| nums := []int{1, 2, 3} | ||||||||
| myFunc(nums...) | ||||||||
| } | ||||||||
| nums := []int{1, 2, 3} | ||||||||
| sum(nums...) // equivalent to sum(1, 2, 3) | ||||||||
| ``` | ||||||||
|
|
||||||||
| This results in `invalid use of ... in call to myFunc` because `myFunc` does not have a variadic parameter. | ||||||||
| `...` really only works in the specific scenarios explained above. | ||||||||
| `...` is only valid when passing a slice to a variadic parameter. | ||||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,76 +1,42 @@ | ||
| # Introduction | ||
|
|
||
| Usually, functions in Go accept only a fixed number of arguments. | ||
| However, it is also possible to write variadic functions in Go. | ||
|
|
||
| A variadic function is a function that accepts a variable number of arguments. | ||
|
|
||
| If the type of the last parameter in a function definition is prefixed by ellipsis `...`, then the function can accept any number of arguments for that parameter. | ||
| Prefix the last parameter's type with `...` to accept any number of trailing arguments: | ||
|
|
||
| ```go | ||
| func find(a int, b ...int) { | ||
| // ... | ||
| func sum(nums ...int) int { | ||
| total := 0 | ||
| for _, n := range nums { | ||
| total += n | ||
| } | ||
| return total | ||
| } | ||
| ``` | ||
|
|
||
| In the above function, parameter `b` is variadic and we can pass 0 or more arguments to `b`. | ||
| Inside the function, the variadic parameter is a slice: | ||
|
|
||
| ```go | ||
| find(5, 6) | ||
| find(5, 6, 7) | ||
| find(5) | ||
| sum(1, 2, 3) // nums is []int{1, 2, 3} | ||
| sum(1, 2, 3, 4) // nums is []int{1, 2, 3, 4} | ||
| sum() // nums is []int{} | ||
| ``` | ||
|
|
||
| ~~~~exercism/caution | ||
| The variadic parameter must be the last parameter of the function. | ||
| ~~~~ | ||
|
|
||
| The way variadic functions work is by converting the variable number of arguments to a slice of the type of the variadic parameter. | ||
|
|
||
| Here is an example of an implementation of a variadic function. | ||
| A function can have non-variadic parameters before the variadic one: | ||
|
|
||
| ```go | ||
| func find(num int, nums ...int) { | ||
| fmt.Printf("type of nums is %T\n", nums) | ||
|
|
||
| for i, v := range nums { | ||
| if v == num { | ||
| fmt.Println(num, "found at index", i, "in", nums) | ||
| return | ||
| } | ||
| func greet(greeting string, names ...string) { | ||
| for _, name := range names { | ||
| fmt.Printf("%s, %s!\n", greeting, name) | ||
| } | ||
|
|
||
| fmt.Println(num, "not found in ", nums) | ||
| } | ||
|
|
||
| func main() { | ||
| find(89, 90, 91, 95) | ||
| // Output: | ||
| // type of nums is []int | ||
| // 89 not found in [90 91 95] | ||
|
|
||
| find(45, 56, 67, 45, 90, 109) | ||
| // Output: | ||
| // type of nums is []int | ||
| // 45 found at index 2 in [56 67 45 90 109] | ||
|
|
||
| find(87) | ||
| // Output: | ||
| // type of nums is []int | ||
| // 87 not found in [] | ||
| } | ||
| ``` | ||
|
|
||
| In line `find(89, 90, 91, 95)` of the program above, the variable number of arguments to the find function are `90`, `91` and `95`. | ||
| The `find` function expects a variadic int parameter after `num`. | ||
| Hence these three arguments will be converted by the compiler to a slice of type `int` `[]int{90, 91, 95}` and then it will be passed to the find function as `nums`. | ||
| ## Spreading a slice | ||
|
|
||
| Sometimes you already have a slice and want to pass that to a variadic function. | ||
| This can be achieved by passing the slice followed by `...`. | ||
| That will tell the compiler to use the slice as is inside the variadic function. | ||
| The step described above where a slice is created will simply be omitted in this case. | ||
| To pass a slice into the variadic parameter, follow it with `...`: | ||
|
|
||
| ```go | ||
| list := []int{1,2,3} | ||
| find(1, list...) // "find" defined as shown above | ||
| nums := []int{1, 2, 3} | ||
| sum(nums...) // equivalent to sum(1, 2, 3) | ||
| ``` | ||
|
|
||
| `...` is only valid when passing a slice to a variadic parameter. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.