rust/src/doc/trpl/method-syntax.md
Kevin Yap 8f61814641 Standardize punctuation & formatting of TRPL
This commit is an attempt to standardize the use of punctuation and
formatting in "The Rust Programming Language" as discussed in #19823.

- Convert bold text to italicized textcwhen referring to terminology.
- Convert single-quoted text to italicized or double-quoted text,
  depending on context.
- Use double quotes only in the case of scare quotes or quotations.
2015-01-08 17:15:26 -08:00

2.4 KiB

% Method Syntax

Functions are great, but if you want to call a bunch of them on some data, it can be awkward. Consider this code:

baz(bar(foo(x)));

We would read this left-to right, and so we see "baz bar foo." But this isn't the order that the functions would get called in, that's inside-out: "foo bar baz." Wouldn't it be nice if we could do this instead?

x.foo().bar().baz();

Luckily, as you may have guessed with the leading question, you can! Rust provides the ability to use this method call syntax via the impl keyword.

Here's how it works:

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

fn main() {
    let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
    println!("{}", c.area());
}

This will print 12.566371.

We've made a struct that represents a circle. We then write an impl block, and inside it, define a method, area. Methods take a special first parameter, &self. There are three variants: self, &self, and &mut self. You can think of this first parameter as being the x in x.foo(). The three variants correspond to the three kinds of thing x could be: self if it's just a value on the stack, &self if it's a reference, and &mut self if it's a mutable reference. We should default to using &self, as it's the most common.

Finally, as you may remember, the value of the area of a circle is π*r². Because we took the &self parameter to area, we can use it just like any other parameter. Because we know it's a Circle, we can access the radius just like we would with any other struct. An import of π and some multiplications later, and we have our area.

You can also define methods that do not take a self parameter. Here's a pattern that's very common in Rust code:

# #![allow(non_shorthand_field_patterns)]
struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl Circle {
    fn new(x: f64, y: f64, radius: f64) -> Circle {
        Circle {
            x: x,
            y: y,
            radius: radius,
        }
    }
}

fn main() {
    let c = Circle::new(0.0, 0.0, 2.0);
}

This static method builds a new Circle for us. Note that static methods are called with the Struct::method() syntax, rather than the ref.method() syntax.