Mặc dù Rust rất, rất hiếm khi cạnh tranh trong các cuộc thi golf mã (Java thường ngắn hơn), nhưng vẫn có thể thú vị khi chơi golf. Một số thủ thuật để làm cho mã Rust ngắn hơn là gì?
Xin vui lòng chỉ gửi một mẹo trong mỗi câu trả lời.
Mặc dù Rust rất, rất hiếm khi cạnh tranh trong các cuộc thi golf mã (Java thường ngắn hơn), nhưng vẫn có thể thú vị khi chơi golf. Một số thủ thuật để làm cho mã Rust ngắn hơn là gì?
Xin vui lòng chỉ gửi một mẹo trong mỗi câu trả lời.
Câu trả lời:
Một đóng cửa:
|n|n+1
ngắn hơn một hàm:
fn f(n:i32)->i32{n+1}
Đóng cửa dài hơn một câu lệnh cần niềng răng nhưng vẫn ngắn hơn nhiều so với chức năng.
Giả sử bạn có một số x thực hiện IntoIterator Trait và bạn cần gọi một hàm f lấy chỉ mục của một phần tử và tham chiếu đến nó. Cách tiêu chuẩn để làm điều này là
x.iter().enumerate().map(f)
thay vào đó bạn có thể làm
(0..).zip(x).map(f)
và tự cứu mình không chỉ là người liệt kê dài bất thường mà còn là lời kêu gọi lặp lại!
Nếu bạn cần nhiều biến có thể thay đổi, nó có thể lãng phí rất nhiều không gian khai báo chúng và khởi tạo chúng, vì mỗi yêu cầu từ khóa mut và bạn không thể làm bất cứ điều gì như a = b = c = 0. Một giải pháp sau đó là khai báo một mảng có thể thay đổi
let mut a=[0;5];
Bạn dành thêm 3 byte mỗi lần bạn sử dụng chúng so với một biến thông thường:
a[0]+=1;
nhưng nó thường có thể vẫn còn giá trị nó.
Sử dụng bộ dữ liệu cho cùng một mẹo thường là một lựa chọn thậm chí tốt hơn:
let mut t=(1,4,"this", 0.5, 'c');
Điều này có lợi thế là tiết kiệm một byte cho mỗi lần sử dụng so với mảng:
t.0=2
Nó cũng cho phép chúng có nhiều loại khác nhau. Về nhược điểm, nó đòi hỏi nhiều ký tự hơn để khởi tạo.
&str
sangString
Không bao giờ làm những điều này:
s.to_string() // 13 bytes
s.to_owned() // 12 bytes
Cái này luôn ngắn hơn:
s.repeat(1) // 11 bytes
Nếu s
là một chuỗi bằng chữ:
format!(s) // 10 bytes
Ví dụ: sử dụng format!("")
thay vìString::new()
để lưu 2 byte.
Nếu kiểu suy luận hoạt động:
s.into() // 8 bytes
Khi sử dụng định dạng chuỗi chẳng hạn với print!()
, người ta có thể sử dụng cả hai trình định dạng được đánh số và không đánh số để lưu một byte cho mỗi mục để định dạng:
Hiển thị tốt nhất với một ví dụ:
fn main(){
print!("{}{}{}. Yes, {0}{}{2}. All you other{1}{2}s are just imitating.",
"I'm",
" Slim",
" Shady",
" the real");
}
Đầu ra nào:
I'm Slim Shady. Yes, I'm the real Shady. All you other Slim Shadys are just imitating.
Vì vậy, các trình định dạng không đánh số sẽ được gán cho các mục theo thứ tự, điều này cho phép bạn bỏ qua chỉ mục trên chúng. Lưu ý rằng bạn chỉ có thể sử dụng một định dạng không đánh số cho mỗi mục để định dạng, sau đó nó sẽ được sử dụng hết.
Sau khi xem xét nhiều thứ khác nhau, tôi nghĩ đó thường là cách ngắn nhất để lấy một dòng. Dòng này có một dòng mới, nó có thể được loại bỏ bằng cách cắt ( .trim()
) hoặc nếu điều đó không thể được thực hiện bằng cách cắt.
let y=&mut"".into();std::io::stdin().read_line(y);
Đối với nhiều dòng, lines
iterator có thể được sử dụng, dòng lặp không kết thúc ở dòng mới. Một nhập khẩu toàn cầu là cần thiết để nhập khẩu BufRead
, cần thiết lines
để có sẵn cho StdinLock<'_>
loại.
use std::io::*;let y=stdin();y.lock().lines()
Trong các hàm trả về ()
, trong đó biểu thức cuối cùng cũng thuộc loại ()
, bạn không cần theo dõi ;
:
fn main(){print!("Hello, world!")}