Связывание одного значения в пределах для понимания

В руководстве Learn You a Haskell есть пример использование let связывателя в понимании списка:

calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]

Функция принимает список пар рост / вес и возвращает список соответствующих индексов массы тела, которые превышают некоторый предел, например:

ghci> calcBmis [(70, 1.85), (50, 2.00), (130, 1.62)]
[49.53513183965858]

Что меня интересует, так это то, что значение bmi, связанное с пониманием, может использоваться как в охраннике, так и в результирующем выражении. Единственный способ сделать что-то подобное в Scala - это написать:

def calcBmis(xs : Seq[(Double,Double)]) =
  for((w,h) <- xs ; bmi <- Some(w / (h*h)) if bmi >= 25.0) yield bmi

Мне кажется неправильным заключать здесь мое значение в Some. Кто-нибудь знает лучший способ?


person Philippe    schedule 30.09.2011    source источник


Ответы (2)


Да, такой синтаксис есть.

def calcBmis(xs : Seq[(Double,Double)]) =
  for((w,h) <- xs ; bmi = w / (h*h); if bmi >= 25.0) yield bmi

Однострочная альтернатива (но не понимание):

calcBmis.map(wh => wh._1/(wh._2*wh._2)).filter(_>=25.0)
person om-nom-nom    schedule 30.09.2011
comment
Хорошо, мне не хватало полуколонки :) В свою защиту, эта клавиша почти никогда не используется на моей клавиатуре, когда я пишу код Scala. - person Philippe; 30.09.2011

Я только что скопировал ответ om-nom-nom, чтобы показать, как вы можете расположить его, используя фигурные скобки без точек с запятой; так немного яснее

def calcBmis(xs : Seq[(Double,Double)]) = for { (w,h) <- xs 
                                                bmi = w / (h*h)
                                                if bmi >= 25.0 } yield bmi

и вместо использования кортежей я бы использовал выражение case (опять же, требует фигурных скобок)

xs map {case (w, h) => w / (h * h)} filter {_ >= 25.0}
person Luigi Plinge    schedule 30.09.2011