Makra print!
, println!
, eprint!
, eprintln!
, write!
, writeln!
i format!
stanowią szczególny przypadek, nie zachowuje się jak normalne rzeczy zrobić ze względu na wygodę. Fakt, że w milczeniu odbierają odniesienia, jest częścią tej różnicy.
fn main() {
let x = 5;
println!("{}", x);
}
go uruchomić poprzez rustc -Z unstable-options --pretty expanded
na nocnej kompilator i możemy zobaczyć co println!
rozszerza się:
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
fn main() {
let x = 5;
::io::_print(::std::fmt::Arguments::new_v1(
{
static __STATIC_FMTSTR: &'static [&'static str] = &["", "\n"];
__STATIC_FMTSTR
},
&match (&x,) {
(__arg0,) => {
[
::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt),
]
}
},
));
}
uporządkowany dużo, to w ten sposób:
use std::fmt;
use std::io;
fn main() {
let x = 5;
io::_print(fmt::Arguments::new_v1(
&["", "\n"];
&[fmt::ArgumentV1::new(&x, fmt::Display::fmt)],
));
}
Zanotuj &x
.
Jeśli napiszesz println!("{}", &x)
, będziesz miał do czynienia z dwoma poziomami referencji; ma to taki sam skutek, ponieważ istnieje implementacja std::fmt::Display
dla &T
, gdzie T
implementuje Display
(pokazane jako impl<'a, T> Display for &'a T where T: Display + ?Sized
), które właśnie ją przekazuje. Równie dobrze można napisać &&&&&&&&&&&&&&&&&&&&&&&x
.
Nie rozumiem, dlaczego nazwałbyś te makra "specjalnym przypadkiem". Ten rodzaj niejawnego przekazywania referencji może zostać zaimplementowany dla dowolnego makra. –
@MarkusUnterwaditzer: Oczywiście, ale chodzi o to, że wygląda normalnie, ale nie jest. I oczywiście, inne makra również mogą stać się specjalnymi przypadkami. Faktem jest, że zdecydowanie odradza się go w ogóle. –