阶:引用上的对象实例的功能(Scala: Referencing functions on obje

2019-09-29 14:11发布

我有一类FOOS的集合,我们会打电话吧。 美孚有很多,我们想在酒吧级别聚集,像这样回国人数的方法:

  def attribute1(inputs: Map[Int, Double]) = 
foos.foldLeft(0d)((sum, foo) => sum + foo.attribute1(inputs(foo.id)))

为了聚合这些不同的属性,我可以有形式的n个函数

  def attributeN(inputs: Map[Int, Double]) = 
foos.foldLeft(0d)((sum, foo) => sum + foo.attributeN(inputs(foo.id)))

然而,这是丑陋的 - 我恨迭代和求和重复的事实。 我想是抽象的,所以我可以这样做:

def attribute1(inputs: Map[Int, Double]) = aggregate(Foo.attribute1, inputs)
private def aggregate(f: Double => Double) = foos.foldLeft(0d)((sum, foo) => sum + foo.f(inputs(foo.id)

当然,这不工作作为一个不能引用Foo.attribute1作为一个功能 - 。 是不是一个函数实例。

我已经基本上通过各种解决方案迷迷糊糊的,但每一个结果代码针对每个聚集方法至少冗长或复杂,因为我们所拥有的,没有帮手,我留下了迭代的重复。

我可能只是希望太多在这里,但我几乎可以肯定有一种优雅的方式做,这是斯卡拉是逃避我。 因此,任何在这里斯卡拉大师谁的答案的 - 在此先感谢!

Answer 1:

所以基本上你问的是一个方法,以解决多个实例的具体方法,对吗? 如果是这样,这是容易解决:

trait Foo {
  def id : Int
  def attribute1( x : Double ) : Double
}

def aggregate( f : (Foo, Double) => Double, inputs : Map[Int, Double] ) = 
  foos.foldLeft(0d)( (sum, foo) => sum + f(foo, inputs(foo.id)) )

def aggregateAttribute1(inputs: Map[Int, Double]) = 
  aggregate(_.attribute1(_), inputs)

该解决方案的关键在于_.attribute1(_)这是写作的一个sugarred方式

(foo, input) => foo.attribute1(input)


Answer 2:

我不知道我得到你想要做什么,而是在一个阶数返回法是这样的:

def attribute1 = 5

是一个函数。 嗯,有点...它可以被看作是与类型的函数() => Int (没有参数,返回一个整数)。 你只需要使用无所不在_告诉斯卡拉把attribute1到一个函数。 看看这有助于为出发点:

scala> class Foo {
     | def attribute1=5
     | def attribute2=2
     | }
defined class Foo

scala> val foo=new Foo
foo: Foo = Foo@4cbba0bd

// test takes a function of type () => Int and just applies it (note 
// the f() followed by () in the right-hand side to say we want to apply f
scala> def test(f: () => Int) = f()
test: (f: () => Int)Int

// the _ after foo.attribute1 tells scala that we want to use 
// res2.attribute as a function, not take its value 
scala> test(foo.attribute1 _)
res0: Int = 5


Answer 3:

建立在@尼基塔的答案,如果你想从你的无聊的方法去除更多的冗余,您可以咖喱的aggregate的方法:

def aggregate(f: (Foo, Double) => Double)(inputs: Map[Int, Double]): Double =
  foos.foldLeft(0d)((sum, foo) => sum + f(foo, inputs(foo.id)))

def aggregateAttribute1: Map[Int, Double] => Double =
  aggregate(_.attribute1(_))


文章来源: Scala: Referencing functions on object instances
标签: scala