2015-11-18 7 views
9

Aşağıdaki örnek programda, map2 tanımlamak zorunda kalmamın bir yolu var mı? Ayrıca Haskell konuşan insanlar içinİki seçeneği "birleştirmek" için herhangi bir yol var mı?

fn map2<T, U, V, F: Fn(T, U) -> V>(f: F, a: Option<T>, b: Option<U>) -> Option<V> { 
    match a { 
     Some(x) => match b { 
      Some(y) => Some(f(x, y)), 
      None => None, 
     }, 
     None => None, 
    } 
} 

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |a, b| { 
     a + b 
    }; 
    let res = map2(f, a, b); 
    println!("{:?}", res); 
    // prints Some(15) 
} 

, ben "Kullandığımız yerine Rust liftM2 herhangi bir araç var mı?" Bu soru da şeklinde ifade edilebilir tahmin

cevap

12

Ben liftM2 doğrudan fonksiyon eşdeğer var inanmıyorum ama böyle Option::and_then ve Option::map birleştirebilirsiniz:

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |a, b| { 
     a + b 
    }; 

    println!("{:?}", a.and_then(|a| b.map(|b| f(a, b)))); 
} 

Çıktı: Sen Option gerçeğini kullanabilirsiniz

Some(15) 
+0

Teşekkür bulunuyor Bunu bir veya iki kez yapmak. Yine de, bazı durumlarda, işlevi tanımlamak için yine de buna değer. –

4

s yinelenebilir. Her iki seçeneğin üzerinde yineleyin, bunları bir araya getirin ve ortaya çıkan yineleyiciyi işlevinize göre eşleyin.

fn main() { 
    let a = Some(5); 
    let b = Some(10); 
    let f = |(a, b)| { 
     a + b 
    }; 
    let res = a.iter().zip(b.iter()).map(f).next(); 
    println!("{:?}", res); 
    // prints Some(15) 
} 

Bu

f bir modifikasyonu gereklidir, bu yüzden bağımsız değişkenler tek tuple-değişken birleştirilir. f'u değiştirmeden, |args| f.call(args) üzerinden doğrudan eşleştirerek, ancak specify the closure kind of f olmalıdır.

+0

alternatif: 'harita (| (a, b) | f (a, b))' – sellibitze

+0

evet, işlev çağrısını tekrar etmekten kaçınmaya çalışıyordum. Eğer tekrar ediyorsanız, o zaman Dogbert'in çözümü en iyisidir. –

2

tek satıra gidebilecek bilmiyorum ama tupleda eşleştirerek iç içe match önleyebilirsiniz : o aslında sadece gerektiğinde için oldukça iyi bir çözüm

let a = Some(5); 
let b = Some(10); 
let f = |a, b| { 
    a + b 
}; 
let res = match (a, b) { 
    (Some(a), Some(b)) => Some(f(a, b)), 
    _ => None, 
}; 
println!("{:?}", res); 
// prints Some(15)