Преобразование выражения в польскую запись в Scala

Я хотел бы преобразовать выражение, такое как: a.meth(b) к функции типа (A, B) => C который выполняет это точное вычисление.

Моя лучшая попытка до сих пор была в этом направлении:

def polish[A, B, C](symb: String): (A, B) => C = { (a, b) =>
// reflectively check if "symb" is a method defined on a
// if so, reflectively call symb, passing b
}

И затем используйте это так:

def flip[A, B, C](f : (A, B) => C): (B, A) => C = {(b, a) => f(a,b)}
val op = flip(polish("::"))
def reverse[A](l: List[A]): List[A] = l reduceLeft op

Как вы можете видеть, это довольно уродливо, и вам приходится много проверять тип вручную.

Есть ли альтернатива?

1 ответ

Вы можете легко достичь этого с простым старым полиморфизмом подтипа. Просто объявите интерфейс

trait Iface[B, C] {
    def meth(b: B): C
}

Тогда вы могли бы реализовать polish без труда

def polish[B, C](f: (Iface[B, C], B) => C): (Iface[B, C], B) => C = { (a, b) =>
    f(a, b)
}

Использование его абсолютно безопасно

object IfaceImpl extends Iface[String, String] {
    override def meth(b: String): String = b.reverse
}

polish((a: Iface[String, String], b: String) => a meth b)(IfaceImpl, "hello")

Обновить:

На самом деле, вы можете достичь этого, используя только замыкания

def polish[A, B, C](f: (A, B) => C): (A, B) => C = f

class Foo {
  def meth(b: String): String = b.reverse
}

polish((_: Foo) meth (_: String))(new Foo, "hello")

Или без вспомогательной функции вообще:)

val polish = identity _ // Magic at work

((_: Foo) meth (_: String))(new Foo, "hello")
Другие вопросы по тегам