Hola. No de inmediato, pero me encantó Rust. Y este amor me llevó a los mares interminables del código sin ley. Acerca de lo que logré encontrar, debajo del corte.
Tipo de datos secretos
Si ha leído el libro Rust, probablemente recuerde un código de fragmento similar:
fn unwrap<T>(option: Option<T>) -> T{
let unwrapped = match option{
Some(val) => val,
None => panic!("This cannot be None!")
};
return unwrapped;
}
fn main() {
let unwrapped = unwrap(Some(0));
}
, . Option, , panic!. , ? , , T, ... ?
"!" . ? :
#![feature(never_type)]
use std::convert::TryInto;
#[derive(Debug)]
enum ConnectionError{
BrokenPipe,
BadId,
Other
}
struct Client;
struct Request;
struct Response;
impl Request{
pub fn build_response(&self) -> Response{
Response
}
}
fn get_request(id: i32) -> Result<(Client, Request), ConnectionError>{
match id % 2 == 0{
true => {
Ok((Client, Request))
},
false => {
Err(ConnectionError::BadId)
}
}
}
fn init_server() -> Result<!, ConnectionError>{
loop {
let (client, request) = get_request(5i32)?;
let resp = request.build_response();
};
}
fn main() {
let x: ! = init_server().unwrap();
}
, , nightly , "!" "()":
fn init_server() -> Result<(), ConnectionError>{
loop {
let (client, request) = get_request(5i32)?;
let resp = request.build_response();
};
}
fn main() {
let x = init_server().unwrap();
}
? , :
fn main() {
match init_server(){
Ok(v) => { println!("unreachable? {:?}", v); },
Err(_) => {}
};
}
, Ok(v) - . , , . , , , .
? , v
"". "!" , break
, continue
std::process::exit
.
, , . #![feature(never_type)]
? , , , . , , . panic, expect, todo unimplemented. "!"?
, . , .
Rust ( - , ) Fn
. - - ("closures" "", ), , . ?
, , , impl Trait. , , ...
use std::any::type_name;
fn type_of<T>(x: T) -> &'static str {
type_name::<T>()
}
fn callback() -> impl Fn(f32) -> f32{
|a| {
a*2.
}
}
fn main() {
let x = callback();
println!("{}", type_of(x));
}
: playground::callback::{{closure}}
. , , impl Fn(f32) -> f32
, , . , trait object, dyn. - , trait object, Box:
fn main() {
let x: Box<dyn Fn(f32) -> f32> = Box::new(callback());
println!("{}", type_of(x));
}
:
alloc::boxed::Box<dyn core::ops::function::Fn<(f32,)>+Output = f32>
: , , .
, :
use tokio; // 1.0.2
use tokio::task::JoinError;
use futures::prelude::*; // 0.3.12
async fn job1(){}
async fn job2(){
for i in 0..5{}
}
async fn job() -> Vec<impl Future<Output = Result<(), JoinError>>>{
vec![
tokio::spawn(async move{
job1().await;
}),
tokio::spawn(async move{
job2().await;
})]
}
#[tokio::main]
async fn main() {
let mut v = job();
}
, - tokio::spawn
tokio::task::JoinHandle
. , JoinHandle - , , async{}
, , async-, ?
let v = vec![
Box::new(async{}),
Box::new(async{
let cb = |x| x*2.;
let val = cb(1f32);
})
];
, , , ? . , . , .
El óxido, por bueno que sea, a veces puede hacer reflexionar. ¿Por qué no retiene la capacidad de cambio? ¿Por qué se volvió perezoso el cálculo funcional? ¿Por qué cargo crea carpetas extrañas con hashes para cada ocasión, en lugar de construir las mismas bibliotecas una vez (aunque, para ser justos, esto no es un problema del lenguaje en sí)? Sea como fuere, si escribir sobre ventajas es dispararse en el pie, escribir en un rast es intentar dispararse en el pie (y Dios no permita que use ffi en el proyecto, entonces los intentos pueden tener bastante éxito) .
El propósito de este artículo es intentar ahondar en el lenguaje, entender cómo funciona desde adentro, porque, como sabes, solo puedes amar a alguien que entiendes.