3
\$\begingroup\$

This is my first time trying Rust. I wrote this code to compute the greater common divisor of 2 integers. Any advice to improve it? Am I using modularity/reference/borrow/dereference the correct way?

File src/gcd.rs:

// calculate the gcd of two integers
// https://en.wikipedia.org/wiki/Greatest_common_divisor

pub fn gcd(a: &i64, b: &i64) -> i64 {
    let mut _a = *a;
    let mut _b = *b;
    while _b != 0 {
        let tmp = _a;
        _a = _b;
        _b = tmp % _b;
    }
    _a
}

#[cfg(test)]
mod tests {
    use ::gcd;

    #[test]
    fn test_gcd() {
        assert_eq!(gcd::gcd(&60, &168), 12);
        assert_eq!(gcd::gcd(&1071, &1029), 21);
    }
}

File src/main.rs:

mod gcd;

fn main() {
    println!("gcd({}, {}) = {}", 60, 168, gcd::gcd(&60, &168)); 
}

Directory structure:

$ tree
.
├── Cargo.lock
├── Cargo.toml
├── src
│   ├── gcd.rs
│   └── main.rs
└── target
    ├── ...
\$\endgroup\$
  • \$\begingroup\$ Rolled back Rev 3 → 2. If you have difficulty understanding an answer, please write a comment on that answer. \$\endgroup\$ – 200_success Feb 3 '18 at 17:57
  • \$\begingroup\$ @Jamal: how to write properly formatted question in the comments?? \$\endgroup\$ – Nicolas C Feb 3 '18 at 18:51
  • \$\begingroup\$ @NicolasC: Just the way you've already done it (comments don't make code appear the exact same way as they do in posts). \$\endgroup\$ – Jamal Feb 3 '18 at 18:52
2
\$\begingroup\$
  1. You do not need to take the numbers by reference.
  2. Do not put an underscore at the beginning of the variable name. A variable name beginning with _ is used to say to the compiler that the variable is unused.

Otherwise, I see no issues in your code. Here is the solution taking account of my comments:

pub fn gcd(mut a: i64, mut b: i64) -> i64 {
    while b != 0 {
        let tmp = a;
        a = b;
        b = tmp % b;
    }
    a
}

#[cfg(test)]
mod tests {
    use ::gcd;

    #[test]
    fn test_gcd() {
        assert_eq!(gcd(60, 168), 12);
        assert_eq!(gcd(1071, 1029), 21);
    }
}

Further explanations:

Why do I need to use let a = instead of let mut a = when calling it?

Not sure if my explanation is legit, but when you give a thing to another function, this function can do whatever it wants to this thing: it can take it as mutable or not. That is not anymore the problem of the previous owner.

Which type of variables should and should not be passed by reference?

This is a very broad question. I advice you to think things differently. In Rust, you can give a thing, or only lend it (the thing is borrowed). The general answer is: if you do not need anymore the thing, or if the receiver needs a full control on it, give it away.

In this specific case, the thing is copyable and small (as small as a reference, in fact). So, borrow it does not give any advantage: just take it (or take a copy) and do not bother with references.

\$\endgroup\$
  • 1
    \$\begingroup\$ It's probably worth pointing out that you can (and did) put the mut in the argument list. That's not obvious to many newcomers. \$\endgroup\$ – Shepmaster Jan 31 '18 at 13:40
  • \$\begingroup\$ Thanks for your answer!! Some questions about making the gcd function parameters mutable; assuming I'm calling it with the following: let a = 60; let b = 168; println!("gcd({}, {}) = {}", a, b, gcd::gcd(a, b)); - why do I need to use let a = instead of let mut a = when calling it? - why aren't the values of a and b modified by side effect of the function (that's why I did a defensive copy in the first place)? - which type of variables should and should not be passed by reference? \$\endgroup\$ – Nicolas C Feb 3 '18 at 18:50
  • 1
    \$\begingroup\$ @NicolasC Simply said, to the right of the : you specify how the data is passed to the function and to the left you describe how the function should interpret that data. \$\endgroup\$ – CodesInChaos Feb 5 '18 at 12:55
  • \$\begingroup\$ @NicolasC I answered your question 1 and 3, not sure about what you meant in the 2nd one, though. \$\endgroup\$ – Boiethios Feb 5 '18 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.