2010-10-28 13 views
7

Oto trochę kodu Scala, aby zsumować wartości od 1 do 9, które są podzielne przez 3 lub 5. Dlaczego linia 5 zwraca jednostkę, a nie typ Boolean?Dlaczego ta linia Scala zwraca jednostkę?

object Sample { 

    def main(args : Array[String]) { 
     val answer = (1 until 10).foldLeft(0) ((result, current) => { 
      if ((current % 3 == 0) || (current % 5 == 0)) { 
       result + current 
      } 
     }) 

     println(answer) 
    } 

} 
+0

potęga chce tag ten projekt-Eulera -spool ... –

+0

Przepraszam, nie chciałem psuć. Naprawdę nie myślałem o tym, kiedy opublikowałem. Chciałbym go edytować, ale nie mogę edytować innych odpowiedzi. – Mike

Odpowiedz

11

Wyrażenie if ma typ Jednostki, ponieważ nie istnieje żadna klauzula else. Tak więc czasami nie zwraca nic (Unit), więc całe wyrażenie ma typ Unit.

(Zakładam, że oznaczało zapytać, dlaczego nie powrócić Int, nie Boolean)

+0

Masz rację. Nie zdawałem sobie sprawy z tego, co się właściwie dzieje - jestem naprawdę nowy w zakresie programowania funkcjonalnego. Jaki jest najlepszy sposób, aby sobie z tym poradzić? Dodawanie else z wynikiem + 0? – Mike

+0

przenieś część 'result +' z bloku 'if' (nie ma potrzeby jej powtarzania) i ustaw' result + if (...) current else 0' –

+0

Dzięki za banda. :) – Mike

8

Oto moje rozwiązanie:

scala> val answer = (1 until 10) filter(current => (current % 3 == 0) || (current % 5 == 0)) sum 
answer: Int = 23 

Wskazówka filtr zamiast jeśli tych.

Kolejny w jeszcze bardziej idiomatyczne Scala:

(for(x <- 1 until 10 if x % 3 == 0 || x % 5 == 0) yield x) sum 
+1

+1 Kolejna świetna odpowiedź. Dziękuję za pomoc w nauce kilku różnych sposobów. – Mike

9

Czy kiedykolwiek być zbyt idiomatyczne? TAK MOŻEMY!

Set(3,5).map(k => Set(0 until n by k:_*)).flatten.sum 

[Edytuj]

sugestia Daniela wygląda lepiej:

Set(3,5).flatMap(k => 0 until n by k).sum 
+2

Czy nie byłoby lepiej po prostu użyć 'flatMap'? –

+4

W rzeczywistości, jeśli to zrobisz, możesz nawet skrócić go do 'Set (3,5) .flatMap (k => 0 do n przez k) .sum'. –

+0

Niezły. Bardzo ... err .. arytmetyczna :) – pedrofurla

4

Najbliższy kod roboczych, co zrobiłeś to:

object Euler { 
    def main(args : Array[String]) { 
     val answer = (1 until 10).foldLeft(0) ((result, current) => 
      if ((current % 3 == 0) || (current % 5 == 0)) 
       result + current 
      else 
       result 
     ) 

     println(answer) 
    } 
}