28
\$\begingroup\$

While Rust is very, very rarely competitive in code golfing competitions (Java is often shorter), it can still be fun to golf in. What are some tricks for making Rust code shorter?

Please post only one tip in each answer.

\$\endgroup\$

14 Answers 14

14
\$\begingroup\$

Use closures instead of functions

A closure:

|n|n+1

is shorter than a function:

fn f(n:i32)->i32{n+1}

Closures longer than one statement need braces but are still far shorter than a function.

| improve this answer | |
\$\endgroup\$
11
\$\begingroup\$

Converting &str to String

Never do these:

s.to_string()  // 13 bytes
s.to_owned()   // 12 bytes

This is always shorter:

s.repeat(1)    // 11 bytes

If s is a string literal:

format!(s)     // 10 bytes

For example: use format!("") instead of String::new() to save 2 bytes.

If type inference works:

s.into()       // 8 bytes
| improve this answer | |
\$\endgroup\$
10
\$\begingroup\$

Avoid .iter().enumerate()

Let's say you have some x that implements the IntoIterator Trait and you need to call a function f that takes the index of an element and a reference to it. The standard way of doing this is

x.iter().enumerate().map(f)

instead you can do

(0..).zip(x).map(f)

and save yourself not only the unusually long enumerate but also the call to iter!

| improve this answer | |
\$\endgroup\$
10
\$\begingroup\$

If you need many mutable variables, it can waste a lot of space declaring them and initializing them, since each requires the mut keyword and you can't do anything like a=b=c=0. A solution then is to declare a mutable array

let mut a=[0;5];

You spend 3 extra bytes each time you use them vs. a normal variable:

a[0]+=1;

but it can often still be worth it.

Using tuples for the same trick is often an even better option:

let mut t=(1,4,"this", 0.5, 'c');

This has the advantage of saving a byte on each use vs. the array:

t.0=2

It also lets them be of different types. On the downside, it requires more characters to initialize.

| improve this answer | |
\$\endgroup\$
6
\$\begingroup\$

When using string formatting for example with print!(), one can use both numbered and unnumbered formatters to save one byte per item to format:

Best shown with an example:

fn main(){
    print!("{}{}{}. Yes, {0}{}{2}. All you other{1}{2}s are just imitating.",
           "I'm",
           " Slim",
           " Shady",
           " the real");
}

Which outputs:

I'm Slim Shady. Yes, I'm the real Shady. All you other Slim Shadys are just imitating.

So the unnumbered formatters will get assigned to the items in order, this allows you to skip the index on them. Note that you can only use one unnumbered formatter per item to format, after that it will get used up.

| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

Reading lines

After considering various things, I think that is generally the shortest way to retrieve a line. The line has a newline, it can be removed by trimming (.trim()) or if that cannot be done by slicing.

let y=&mut"".into();std::io::stdin().read_line(y);

For multiple lines, lines iterator can be used, the iterated line doesn't end in newline then. A glob import is needed to import BufRead, needed for lines to be available for StdinLock<'_> type.

use std::io::*;let y=stdin();y.lock().lines()
| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

When using whole number floating point numbers, you can omit the trailing .0 to save one byte.

let a=1.

is 1 byte less than:

let a=1.0
| improve this answer | |
\$\endgroup\$
5
\$\begingroup\$

When working with strings with newlines in them, you save one byte if you use a literal line break in the source code vs having a \n in the string and/or using println.

print!("Hello
World!
");

is 2 bytes less than:

println!("Hello\nWorld!");
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Save another byte by using print with literal line break instead of println \$\endgroup\$ – JayXon Aug 2 at 1:44
  • 1
    \$\begingroup\$ @JayXon Holy shit 🤯, so obvious now when you said it. \$\endgroup\$ – ruohola Aug 2 at 9:48
4
\$\begingroup\$

Skipping trailing semicolons

In functions returning (), where the last expression is also of type (), you don't need the trailing ;:

fn main(){print!("Hello, world!")}
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Use closure parameter to define variable instead of let

{let(a,b)=(A,B);X}

can be replaced by

(|a,b|X)(A,B)

to save 5 bytes if the type of a and b can be inferred, it usually works when they are integers or are passed to another function directly in X.

This works well on 2 or more variables, but for a single variable, this could still save 2 bytes if it allows you to get rid of the {}.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Use ..=

Replace all ..i+1 with ..=i to save 1 byte, works on both array index a[i..=i] and range (0..=n)

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ clippy actually has a warning for this \$\endgroup\$ – betseg Feb 26 at 5:20
1
\$\begingroup\$

Replace all filter_map with flat_map

It works because:

  • filter_map takes a FnMut(Self::Item) -> Option<B>

  • flat_map takes a FnMut(Self::Item) -> impl IntoIterator

  • Option implements IntoIterator, which will return an iterator with one item for Some and empty iterator for None

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Declare multiple variables using pattern matching

(Somewhat of an extension of https://codegolf.stackexchange.com/a/99124/97519)

Using multiple let statements:

let a=x;let b=y;
let a=x;let b=y;let c=z;

Using a tuple match saves 1 char for 2 variables and 3 more chars for ever variable after:

let(a,b)=(x,y);
let(a,b,c)=(x,y,z);

Similarly, you can use array patterns for initializing multiple mutable variables to the same value (this works with immutable variables too but is pretty useless):

let[mut a,mut b]=[x;2];
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Why is the immutable version useless? \$\endgroup\$ – Wheat Wizard Jul 31 at 20:48
  • 1
    \$\begingroup\$ @AdHocGarfHunter why would you want to initialize two immutable variables to the same value? \$\endgroup\$ – Doorknob Jul 31 at 22:10
1
\$\begingroup\$

Prefer todo! over panic!

todo! is shorter than panic! by 1 byte, so prefer to use it if you need to panic and exit the program. It's also shorter than print! by a byte, so it can shorten your program if you can output to stderr instead of stdout.

todo!("optional message for stderr")
| improve this answer | |
\$\endgroup\$

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.