Binding a single value within a for comprehension
The Learn You a Haskell tutorial has an example of using a let
binder in a list comprehension:
calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]
The function takes a list of height/weight pairs, and returns a list of the corresponding body-mass indices that exceed some limit, eg:
ghci> calcBmis [(70, 1.85), (50, 2.00), (130, 1.62)]
[49.53513183965858]
What's interesting to me here is that the value bmi
that is bound within the comprehension can be used both in a guard and in the resulting expression. The only way I know how to do something similar in Scala is to write:
def cal开发者_如何学JAVAcBmis(xs : Seq[(Double,Double)]) =
for((w,h) <- xs ; bmi <- Some(w / (h*h)) if bmi >= 25.0) yield bmi
Having to wrap my value in a Some
here feels wrong. Anyone knows of a better way?
Yes, there is such syntax.
def calcBmis(xs : Seq[(Double,Double)]) =
for((w,h) <- xs ; bmi = w / (h*h); if bmi >= 25.0) yield bmi
One-liner alternative (but not comprehension):
calcBmis.map(wh => wh._1/(wh._2*wh._2)).filter(_>=25.0)
I've just copied om-nom-nom's answer to show how you can lay it out using curly braces without the semicolons; it's a bit clearer this way
def calcBmis(xs : Seq[(Double,Double)]) = for { (w,h) <- xs
bmi = w / (h*h)
if bmi >= 25.0 } yield bmi
and instead of using tuples, I'd use a case
expression (again, requires curly braces)
xs map {case (w, h) => w / (h * h)} filter {_ >= 25.0}
精彩评论