简体   繁体   中英

Rust Ownership and Lifetimes using Combine

I've read the docs on ownership and lifetimes and I think I understand them but I'm having trouble with a specific bit of code.

I have a struct called Branch like this:

struct Branch {
    slot: u8,
    yaw: u8,
    pitch: u8,
    length: u8
}

I'm using the combine library (it's a parser combinator) to parse a string into a Branch. The parsers look like this:

let hex_re = Regex:new(r"[0-9a-fA-F]").unwrap();
let hex = || find(&hex_re).map(|s| u8::from_str_radix(s, 16));
let branch = |length: u8| {
    (hex(), hex(), hex())
        .map( |t| (t.0.unwrap(), t.1.unwrap(), t.2.unwrap()) )
        .map( |(slot,yaw,pitch)| Branch { slot, yaw, pitch, length } )
}

The parsers are fairly simple, the first hex takes a regular-expression which matches a single hexidecimal character and maps it into a u8. The second branch maps 3 hex characters into a Branch eg 3d2.

The problem arises when I call the parser branch(1).parse("3d2") , the compiler reports an error 'length' does not live long enough . I think I understand this error, if I'm not mistaken it's because length goes out of scope when the closure completes and so the length variable is deallocated even though it is still being used by the newly created Branch.

So, I tried to get around this by converting length: u8 to length: &u8 like so:

let branch = |len: &u8| {
    (hex(), hex(), hex())
        .map( |t| (t.0.unwrap(), t.1.unwrap(), t.2.unwrap()) )
        .map( |(slot,yaw,pitch)| Branch { slot, yaw, pitch, length: *len } )
};

// calling the parser
branch(&(1 as u8)).parse("3d2");

But that results in this error:

type of expression contains references that are not valid during the expression: `combine::combinator::Map<combine::combinator::Map<(combine::combinator::Map<combine::regex::Find<&regex::Regex, &str>, [closure@src\lsystem.rs:26:37: 26:70]>, combine::combinator::Map<combine::regex::Find<&regex::Regex, &str>, [closure@src\lsystem.rs:26:37: 26:70]>, combine::combinator::Map<combine::regex::Find<&regex::Regex, &str>, [closure@src\lsystem.rs:26:37: 26:70]>, combine::combinator::Map<combine::regex::Find<&regex::Regex, &str>, [closure@src\lsystem.rs:26:37: 26:70]>), [closure@src\lsystem.rs:30:19: 30:65]>, [closure@src\lsystem.rs:31:19: 31:80 length:&&u8]>`

I have no idea what this error is about. Any help would be much appreciated.

This solved it:

let hex_re = Regex:new(r"[0-9a-fA-F]").unwrap();
let hex = || find(&hex_re).map(|s| u8::from_str_radix(s, 16));
let branch = |length: u8| {
    (hex(), hex(), hex())
        .map( |t| (t.0.unwrap(), t.1.unwrap(), t.2.unwrap()) )
        .map( move |(slot,yaw,pitch)| Branch { slot, yaw, pitch, length } )
}

placing move on the second .map works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM