SICP Exercise 1.3: Sum of squares of two largest numbers out of three, Rust Version The exercise 1.3 of the book Structure and Interpretation of Computer Programs asks the following:


  Exercise 1.3.  Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.


My answer is this:

#![feature(core)]
use std::cmp;

fn sum_square_largest(x:f64, y:f64, z:f64) -&gt; f64 {
    match partial_min_three(x, y, z) {
        Some(a) =&gt;  x * x + y * y + z * z - a * a,
        None =&gt; 0.0_f64/0.0_f64
    }
}

fn partial_min_three&lt;T&gt;(v1: T, v2: T, v3: T) -&gt; Option&lt;T&gt; where T: PartialOrd&lt;T&gt; {
    match cmp::partial_min(v2, v3) {
        Some(x) =&gt; cmp::partial_min(v1, x),
        None =&gt; None
    }
}


Rust is the language I know less, I would really appreciate your advice.
I find it always pays to be tidy and conscientious about spacing. Here, I'd add spaces after the : in the argument declaration

// fn sum_square_largest(x:f64, y:f64, z:f64) -&gt; f64 {
fn sum_square_largest(x: f64, y: f64, z: f64) -&gt; f64 {


Next, I'd wrap the where clause onto the next line. where clauses often get large, so I find it best to let them have breathing room, and only put one type per line:

// fn partial_min_three&lt;T&gt;(v1: T, v2: T, v3: T) -&gt; Option&lt;T&gt; where T: PartialOrd&lt;T&gt; {
fn partial_min_three&lt;T&gt;(v1: T, v2: T, v3: T) -&gt; Option&lt;T&gt;
    where T: PartialOrd&lt;T&gt;
{


Checking for Some or None and doing something is a common pattern. In this case, you can use Option::and_then:

// match partial_min(v2, v3) {
//     Some(x) =&gt; partial_min(v1, x),
//     None =&gt; None
// }
partial_min(v2, v3).and_then(|x| partial_min(v1, x))


Programming is often about clarity in expressing your intentions, and I doubt that the majority of programmers immediately know what 0 / 0 is for floating point numbers. You should be explicit:

// None =&gt; 0.0_f64/0.0_f64
None =&gt; std::f64::NAN,


Again, we can use existing patterns to deal with checking for Some / None. This time, we can use Option::map:

// match partial_min_three(x, y, z) {
//     Some(a) =&gt; x * x + y * y + z * z - a * a,
//     None =&gt; std::f64::NAN,
// } 
partial_min_three(x, y, z)
    .map(|a| x * x + y * y + z * z - a * a)
    .unwrap_or(std::f64::NAN)


I disagree with your choice of NaN as a magic value. Magic values drive me crazy, and Rust has great choices for avoiding them - Option and Result!

fn sum_square_largest(x: f64, y: f64, z: f64) -&gt; Option&lt;f64&gt; {
    partial_min_three(x, y, z)
        .map(|a| x * x + y * y + z * z - a * a)
}


I'd probably create a tiny function for squaring. It's likely to get inlined, so I'm not worried about performance, just readability:

.map(|a| square(x) + square(y) + square(z) - square(a))


All together (playpen):

fn sum_square_largest(x: f64, y: f64, z: f64) -&gt; Option&lt;f64&gt; {
    partial_min_three(x, y, z)
        .map(|a| square(x) + square(y) + square(z) - square(a))
}

fn partial_min_three&lt;T&gt;(v1: T, v2: T, v3: T) -&gt; Option&lt;T&gt;
    where T: PartialOrd&lt;T&gt;
{
    partial_min(v2, v3).and_then(|x| partial_min(v1, x))
}

fn square(x: f64) -&gt; f64 { x * x }

// Copied from the standard library as it is currently unstable
// and the beta doesn't allow unstable features
use std::cmp::Ordering;
fn partial_min&lt;T: PartialOrd&gt;(v1: T, v2: T) -&gt; Option&lt;T&gt; {
    match v1.partial_cmp(&amp;v2) {
        Some(Ordering::Less) | Some(Ordering::Equal) =&gt; Some(v1),
        Some(Ordering::Greater) =&gt; Some(v2),
        None =&gt; None
    }
}

fn main() {
    let z = sum_square_largest(1.0, 2.0, 3.0);
    println!("{:?}", z);
}