2016-10-25 4 views
0

In vielen Sprachen (Fortran, Matlab/Octave, Julia usw.) wird ein Ausdruck wie sum(array,n) die Werte eines Arrays entlang der n: ten Dimension summieren und ein Array mit einer unteren Dimensionalität ausgeben. Gibt es in Rust etwas Ähnliches?Sum-Array entlang der Dimension

Ich habe versucht:

fn main() { 
    let arr1: [f64; 5] = [1.1, 1.2, 2.3, 3.4, 4.5555]; 
    println!("this {}", arr1.iter().sum()) 
} 

mit diesem Fehler:

error[E0282]: unable to infer enough type information about `_` 
--> src/main.rs:3:37 
    | 
3 |  println!("this {}", arr1.iter().sum()) 
    |          ^^^ cannot infer type for `_` 
<std macros>:2:27: 2:58 note: in this expansion of format_args! 
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>) 
src/main.rs:3:5: 3:43 note: in this expansion of println! (defined in <std macros>) 
    | 
    = note: type annotations or generic parameter binding required 
+3

Die Fehlermeldung scheint klar genug zu sein: Übergeben Sie entweder das Ergebnis von 'sum()' an eine Bindung des expliziten Typs ('f64') oder fügen Sie den Typ Annotation (' sum :: () ') hinzu. Welcher Teil davon ist Ihnen weniger klar? –

+1

Ok, ein bisschen hilfreich-aggressiv? Aber du hast einen Punkt. Der Beitrag wurde jedoch freundlicherweise bearbeitet, wobei die Fehlermeldung auf die richtige umgestellt wurde. Die Codezeilen, die ich gepostet habe, waren am Ende eines ansonsten funktionalen Skripts, aber diese Tatsache scheint die Fehlermeldung, die ich nicht erwartet hatte, verändert zu haben. –

+1

Schau, dass ich nicht aggressiv sein wollte, aber ich habe tatsächlich deine eigene Interpretation der Fehlermeldung in deiner Frage erwartet. Ich war zu Recht neugierig, warum du es nicht verstanden hast.Eine gute Chance ist, dass Sie mehr als die Antwort benötigen, um ähnliche Probleme in der Zukunft zu überwinden. –

Antwort

3

In diesem Fall müssen Sie explizit müssen Art der Elemente angeben:

println!("this {}", arr1.iter().sum::<f64>()) 

Sie waren ganz in der Nähe:)

Eine weitere Option, die von @ E_net4 vorgeschlagen wurden getrennt verwenden Bindung:

let res: f64 = arr1.iter().sum(); 
println!("this {}", res) 
+0

Ich benutze 'rustc 1.7.0' aus den Ubuntu apt-repositories, und bekomme:' test.rs:19:29: 19:34 error: Verwendung der Unstable-Bibliothek Feature 'iter_arith': Grenzen wurden kürzlich geändert (siehe Problem # 27739) '. –

+4

@ JonatanÖström du solltest updaten! Im Moment ist 1.12.1 das neueste und es stellt ungefähr 30 zusätzliche Wochen Arbeit dar, die auf den Compiler angewendet wurde; einschließlich besserer Fehlermeldungen. – Shepmaster

+0

Ich habe es vor einer Stunde auf dieser Maschine installiert, also sollte ich wohl einen anderen Kanal benutzen. –

1

Die „nicht genügend Typinformationen über _ schließen“ Fehlermeldung in einigen anderen Fragen erläutert. Siehe Error: unable to infer enough type information about `_`; type annotations or generic parameter binding required und Unable to infer enough type information about _; type annotations or generic parameter binding required. Im Grunde bedeutet dies, dass der Compiler nicht genügend Informationen hat, um alle Typparameter in einer Funktion oder einem Datentyp anzugeben.

Dennoch, dieser spezielle Fall einige Verwirrung hervorrufen kann: warum nicht Iterator.sum() schließt nur die Typen der resultierenden Summe an den Item des Iterators? Durch die Addition von f64 s erwarten wir f64 als Ergebnis, oder? Nun, das Verfahren sum ist tatsächlich wie folgt definiert:

fn sum<S>(self) -> S 
    where S: Sum<Self::Item> 

Wo S eine andere Art von sum Funktion implementiert (siehe trait Sum), die einen Iterator nimmt:

pub trait Sum<A = Self> { 
    fn sum<I>(iter: I) -> Self where I: Iterator<Item=A>; 
} 

Diese Eigenschaft gibt uns die Freiheit zu fassen Zahlen und Verweise auf gleiche Zahlen:

static MAGIC_CODE: u32 = 0xDEADBEEF; 
static BLAND_CODE: u32 = 0x1234ABCD; 

fn main() { 

    let sum1: u32 = vec![MAGIC_CODE, BLAND_CODE] // vec! infers to Vec<u32> 
     .into_iter().sum(); 

    let sum2 = vec![&MAGIC_CODE, &BLAND_CODE] // vec! infers to Vec<&u32> 
     .into_iter().sum::<u32>(); 


    assert_eq!(sum1, sum2); 
} 

Auf der anderen Seite bedeutet dies auch, dass th Die Definition einer Summe wird lockerer: Jeder andere Datentyp, der Sum<u32> (oder Sum<&u32>) implementiert, könnte seinen Platz in dem obigen Code einnehmen, was zu der oben erwähnten Mehrdeutigkeit führt. Für die Zwecke der Demonstration, stellt dieser Code auch:

use std::iter::Sum; 

struct Accumulator(bool); 

impl Sum<u32> for Accumulator { 
    fn sum<I: Iterator<Item = u32>>(mut iter: I) -> Self { 
     Accumulator(iter.any(|v| v != 0)) 
    } 
} 

fn main() { 
    let sum3: Accumulator = { 
     let data = vec![MAGIC_CODE, BLAND_CODE]; 

     data.into_iter().sum() 
    }; 

    assert!(sum3.0); 
} 

Full code on Playground.

Verwandte Themen