# 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.

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

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

fn partial_min_three<T>(v1: T, v2: T, v3: T) -> Option<T> where T: PartialOrd<T> {
match cmp::partial_min(v2, v3) {
Some(x) => cmp::partial_min(v1, x),
None => 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) -> f64 {
fn sum_square_largest(x: f64, y: f64, z: f64) -> 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<T>(v1: T, v2: T, v3: T) -> Option<T> where T: PartialOrd<T> {
fn partial_min_three<T>(v1: T, v2: T, v3: T) -> Option<T>
where T: PartialOrd<T>
{


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) => partial_min(v1, x),
//     None => 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 => 0.0_f64/0.0_f64
None => 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) => x * x + y * y + z * z - a * a,
//     None => 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) -> Option<f64> {
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) -> Option<f64> {
partial_min_three(x, y, z)
.map(|a| square(x) + square(y) + square(z) - square(a))
}

fn partial_min_three<T>(v1: T, v2: T, v3: T) -> Option<T>
where T: PartialOrd<T>
{
partial_min(v2, v3).and_then(|x| partial_min(v1, x))
}

fn square(x: f64) -> 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<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
match v1.partial_cmp(&v2) {
Some(Ordering::Less) | Some(Ordering::Equal) => Some(v1),
Some(Ordering::Greater) => Some(v2),
None => None
}
}

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