-
Notifications
You must be signed in to change notification settings - Fork 409
Use coercion for arguments #29
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
Merged
Merged
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
302f5b4
Create str-vs-string section
3c12bc8
correct spelling of vowel
0a478cc
fix more typos
4aed435
Update str-vs-string.md
a38e09e
Add String vs Str link to readme
03caded
Fix typos
d6b6986
change title
86dcfd4
Generalize the str vs string idiom
366db72
Changing title to Use
simonsan 048c704
Remove unnecessary whitespace
simonsan cd9fbf0
Added to SUMMARY.md
simonsan 9c1a19b
Fixes from review
simonsan bf45e6c
Another fix from review
simonsan 783e9fc
fix from older review
simonsan ad68802
More fixes from review
simonsan 252f8f1
Merge branch 'master' into cbreeden-str-vs-string
simonsan 4a05a94
Merge branch 'master' into cbreeden-str-vs-string
simonsan 012addb
Update idioms/coercion-arguments.md
simonsan 66aed67
Making tests run successfully
simonsan d06c86b
Small restructure
simonsan c9057b7
Update idioms/coercion-arguments.md
simonsan 87985ca
Update idioms/coercion-arguments.md
simonsan e32db7d
Clear out testing of examples
simonsan 268a6d3
Merge branch 'master' into cbreeden-str-vs-string
simonsan 303bdba
Update idioms/coercion-arguments.md
simonsan 3b161c0
Update idioms/coercion-arguments.md
simonsan 45360aa
Update idioms/coercion-arguments.md
simonsan 136b9b0
Update idioms/coercion-arguments.md
simonsan 88d418c
Update idioms/coercion-arguments.md
simonsan f2266ba
Merge branch 'master' into cbreeden-str-vs-string
simonsan 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
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 |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| # Use borrowed types for arguments | ||
|
|
||
| ## Description | ||
|
|
||
| Using a target of a deref coercion can increase the flexibility of your code when you are deciding which argument type to use for a function argument. | ||
| In this way, the function will accept more input types. | ||
|
|
||
| For example; using `&str` instead of a `&String`, or `&[T]` in preference of `&Vec<T>`. This is not limited to slice-able or fat pointer types. In fact you should always prefer using the __borrowed type__ over __borrowing the owned type__, e.g., `&T` to `&Box<T>`. | ||
simonsan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Using borrowed types you can avoid layers of indirection for those instances where the owned type already provides a layer of indirection, as it will be illustrated in the following examples. For instance, a `String` has a layer of indirection, so a `&String` will have two layers of indrection. | ||
simonsan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| We can avoid this by using `&str` instead, and letting `&String` coerce to a `&str` whenever the function is invoked. | ||
|
|
||
| ## Example | ||
|
|
||
| For this example, we will illustrate some differences for using `&String` as a function argument versus using a `&str`, but the ideas apply as well to using `&Vec<T>` versus using a `&[T]` or using a `&T` versus a `&Box<T>`. | ||
|
|
||
| Consider an example where we wish to determine if a word contains three consecutive vowels. | ||
| We don't need to own the string to determine this, so we will take a reference. | ||
|
|
||
| The code might look something like this: | ||
|
|
||
| ```rust | ||
| fn three_vowels(word: &String) -> bool { | ||
| let mut vowel_count = 0; | ||
| for c in word.chars() { | ||
| match c { | ||
| 'a' | 'e' | 'i' | 'o' | 'u' => { | ||
| vowel_count += 1; | ||
| if vowel_count >= 3 { | ||
| return true | ||
| } | ||
| } | ||
| _ => vowel_count = 0 | ||
| } | ||
| } | ||
| false | ||
simonsan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| fn main() { | ||
| let ferris = "Ferris".to_string(); | ||
| let curious = "Curious".to_string(); | ||
| println!("{}: {}", ferris, three_vowels(&ferris)); | ||
| println!("{}: {}", curious, three_vowels(&curious)); | ||
|
|
||
| // Using a `&String` type in our arguent we will find the following example fails: | ||
| // println!("Ferris: {}", three_vowels("Ferris")); | ||
| // println!("Curious: {}", three_vowels("Curious")); | ||
|
|
||
| } | ||
| ``` | ||
marcoieni marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| This example fails because a `&str` type will not coerce to a `&String` type. | ||
| We can fix this by simply modifying the type for our argument. For instance, if we change our function declaration to: | ||
|
|
||
| ```rust, ignore | ||
| fn three_vowels(word: &str) -> bool { | ||
| ``` | ||
|
|
||
| then both of the previous examples will compile and print the same output. | ||
|
|
||
|
|
||
| ```bash | ||
| Ferris: false | ||
| Curious: true | ||
| ``` | ||
|
|
||
| But wait, that's not all! There is more to this story. | ||
| It's likely that you may say to yourself: that doesn't matter, I will never be using a `&'static str` as an input anways (as we did when we used `"Ferris"`). | ||
| Even ignoring this special example, you may still find that using `&str` will give you more flexibility than using a `&String`. | ||
|
|
||
| Let's now take an example where someone gives us a sentence, and we want to determine if any of the words in the sentence has a word that contains three consecutive vowels. | ||
| We probably should make use of the function we have already defined and simply feed in each word from the sentence. | ||
|
|
||
| An example of this could look like this: | ||
|
|
||
| ```rust | ||
| fn three_vowels(word: &str) -> bool { | ||
| let mut vowel_count = 0; | ||
| for c in word.chars() { | ||
| match c { | ||
| 'a' | 'e' | 'i' | 'o' | 'u' => { | ||
| vowel_count += 1; | ||
| if vowel_count >= 3 { | ||
| return true | ||
| } | ||
| } | ||
| _ => vowel_count = 0 | ||
| } | ||
| } | ||
| false | ||
| } | ||
|
|
||
| fn main() { | ||
| let sentence_string = | ||
| "Once upon a time, there was a friendly curious crab named Ferris".to_string(); | ||
| for word in sentence_string.split(' ') { | ||
| if three_vowels(word) { | ||
| println!("{} has three consecutive vowels!", word); | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| Running this example using our function declared with an argument type `&str` will yield | ||
|
|
||
| ```bash | ||
| curious has three consecutive vowels! | ||
| ``` | ||
|
|
||
| However, this example will not run when our function is declared with an argument type `&String`. | ||
| This is because string slices are a `&str` and not a `&String` which would require an allocation to be converted to `&String` which is not implicit, whereas converting from `String` to `&str` is cheap and implicit. | ||
|
|
||
simonsan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## See also | ||
|
|
||
| For more discussion on how to handle `String` and `&str` see [this blog series (2015)](https://web.archive.org/web/20201112023149/https://hermanradtke.com/2015/05/03/string-vs-str-in-rust-functions.html) by Herman J. Radtke III. | ||
simonsan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
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.
Uh oh!
There was an error while loading. Please reload this page.