After Chs 5 and 6 (see the reading club post here), we get a capstone quiz that covers ownership along with struts and enums.

So, lets do the quiz together! If you’ve done it already, revisiting might still be very instructive! I certainly thought these questions were useful “revision”.


I’ll post a comment for each question with the answer, along with my own personal notes (and quotes from The Book if helpful), behind spoiler tags.

Feel free to try to answer in a comment before checking (if you dare). But the main point is to understand the point the question is making, so share any confusions/difficulties too, and of course any corrections of my comments/notes!.

  • maegul (he/they)OPM
    link
    fedilink
    English
    arrow-up
    1
    ·
    6 months ago

    Q3: How fix

    Of the following fixes (highlighted in yellow), which fix best satisfies these three criteria:

    • The fixed function passes the Rust compiler,
    • The fixed function preserves the intention of the original code, and
    • The fixed function does not introduce unnecessary inefficiencies

    1:

    fn make_separator(user_str: &str) -> &str {
        if user_str == "" {
            let default = "=".repeat(10);
            &default
        } else {
            &user_str
        }
    }
    

    2:

    fn make_separator(user_str: String) -> String {
        if user_str == "" {
            let default = "=".repeat(10);
            default
        } else {
            user_str
        }
    }
    

    3:

    fn make_separator(user_str: &str) -> String {
        if user_str == "" {
            let default = "=".repeat(10);
            default
        } else {
            user_str.to_string()        
        }
    }
    
    Answer

    3

    • Return owned default
    • Convert user_str to a String to keep a consistent return type
    • Change return type to String
    • 2 is too restrictive in requiring use_str to be a String
    • 1 doesn’t solve the problem
    fn make_separator(user_str: &str) -> String {
        if user_str == "" {
            let default = "=".repeat(10);
            default
        } else {
            user_str.to_string()        
        }
    }
    

    Context: There is no valid way to return a pointer to a stack-allocated variable. The simple solution is therefore to change the return type to String and copy the input user_str into an owned string. However, requiring user_str to be a String would reduce the flexibility of the API, e.g. a caller could not call make_separator on a substring of a bigger string. It would also require callers to heap-allocate strings, e.g. they could not use a string literal like make_separator(“Rust”).

    The most idiomatic solution to this problem uses a construct you haven’t seen yet: Cow - Clone-on-write. The clone-on-write smart pointer would enable this function to return either an owned string or a string reference without a type error.

    • Interesting!!