2012-03-22 2 views
0

У меня есть функция Foo, которая принимает булеву функциюScala булева функция абстракция

def foo(f:(_)=>Boolean) = //do something with f 

Я могу назвать Foo следующего

foo((x:Int) => x == 0) 

Теперь я хочу изменить Foo принять любую функцию, которая возвращает логическое значение , например. модифицированный foo должен работать в следующих случаях.

foo((x:Int, y:Int) => x == y) 
foo((x:Int, y:Int, z:Int) => x == y && y == z) 
foo((x:Double, y:Double, z:Double, p:Double) => x < y && y < z && z < p) 
//and so on... 

Моя первая попытка была изменить Foo следующим

def foo2(f:(_*)=>Boolean) = //do something with f 

Но это не работает.

+2

Что действительно делает «делать что-то с f»? Можете ли вы показать код? –

+0

@ н.м. Позвольте мне дать некоторый контекст. Это для плагина компилятора. Плагин компилятора извлечет логическую формулу из тела функции. Аргументами функций являются свободные переменные в формуле. – dips

+0

Кажется, вы вызываете функцию с неизвестным числом аргументов. Можете ли вы показать код? –

ответ

1

Что сказал @Nicolas.

Вы можете сделать код сайта звонка немного приятнее, используя Function.tupled.

scala> def foo[A](f: A => Boolean) = 0 
foo: [A](f: A => Boolean)Int 

scala> import Function.tupled 
import Function.tupled 

scala> foo(tupled((x: Int, y: Int) => x == y)) 
res0: Int = 0 

scala> foo(tupled((x: Int, y: Int, z: Int) => x < y && y < z)) 
res1: Int = 0 
+0

Спасибо. Это выглядит чисто. На данный момент это будет работать для меня. Одно дело отметить. Это не будет работать для функций с более чем 5 аргументами. В Function.scala _ есть примечание. «Эти функции имеют прорези для устаревания, но они находятся на удержании в ожидании вывода превосходного типа для тупирования анонимных функций». _ – dips

+0

@ dips, вещь с 5 аргументами не является фундаментальным ограничением. Вы можете написать свой собственный метод tupling так же, как написаны методы Function.tupled. – missingfaktor

+0

@ dips, более новый способ написать это 'f.tupled' (вместо старого' Function.tupled (f) ').Как отмечается в примечании, более старый способ более дружелюбен с типом inferer. – missingfaktor

4

ли это соответствовать вашим потребностям def foo[A](pred: A => Boolean)

Например:

def foo[A](pred: A => Boolean): A => Boolean = {x:A => 
    if (pred(x)) { 
    println("Yeah!") 
    true 
    } else { 
    false 
    } 
} 

А потом:

foo {xy:(Int, Int) => xy._1 == xy._2} 

foo {xyz:(Int, Int, Int) => xyz._1 == xyz._2 && xyz._2 == xyz._3} 
+0

Спасибо. Это сработает. Но ._1 немного неудобно. Дождитесь других ответов в течение нескольких дней. – dips

+0

К сожалению, в вашем примере указанные функции расширяют соответственно 'Function2' и' Function3', и эти черты и 'Function' не имеют общего суперкласса (кроме' Any'), поэтому вы не сможете найдите действительную подпись для своей функции. Вот почему вы должны играть с 'Tuple' и их '_x' нотациями. – Nicolas

1

Если вам нужно работать с более 5 аргументов, вы можете перегрузить foo для однако многих аргументов вам нужны. Scala (в настоящее время) может обрабатывать только функции до Function22, поэтому вы можете охватить все возможности с 22 строками кода и хорошим использованием сайта.

def foo[T](f: (T) => Boolean) = true 
def foo[T](f: (T, T) => Boolean) = true 
def foo[T](f: (T, T, T) => Boolean) = true 
def foo[T](f: (T, T, T, T) => Boolean) = true 
def foo[T](f: (T, T, T, T, T) => Boolean) = true 
// snip 
def foo[T](f: (T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T) => Boolean) = true 

Элегантный, нет. Работает, да.

Смежные вопросы