Почему бы не определить функции как одноэлементные функции? - PullRequest
1 голос
/ 30 июня 2019

Рассмотрим определение одиночной функции , найденной в бесформенном репо:

/** Polymorphic function selecting an arbitrary element from a non-empty `Set`. */
object choose extends (Set ~> Option) {
  def apply[T](s : Set[T]) = s.headOption 
}

Сравните ее с традиционным синтаксисом def в следующем примере:

package utils

object UtilWithASingleMethod {
  def isSatisfyingSomePredicate(foo: Foo): Boolean = ???
}

против

package utils

object isSatisfyingSomePredicate extends (Foo => Boolean) {
  def apply(foo: Foo): Boolean = ???
}

Обратите внимание, что сайт вызова теперь становится

isSatisfyingSomePredicate(foo)

вместо

UtilWithASingleMethod.isSatisfyingSomePredicate(foo)

или

import UtilWithASingleMethod._

isSatisfyingSomePredicate(foo)

ЛичноПакет, UtilWithASingleMethod кажется вынужденным просто использовать знакомый синтаксис def, но не добавляет никакой полезной информации.

Помимо субъективных недостатков, таких как незнакомость или путаница с объектом + стиль применения, используемый в фабричном шаблонеЕсть ли какие-либо технические недостатки с определениями одноэлементных функций?

1 Ответ

5 голосов
/ 30 июня 2019

Причина, по которой им пришлось создавать одноэлементные объекты в связанном файле, заключается в том, что это были не функции , а полиморфные функции , т. Е. У них был метод apply[T](a: F[T]): G[T], которыйколичественно определяется параметром типа T.Это просто не требуется для обычных функций, все, что он делает, это добавляет издержки на вызов метода apply для одноэлементного объекта foo вместо непосредственного вызова метода foo.Это также не поможет вам «избежать» пакетов и импорта, потому что вы все равно хотите, чтобы этот объект был в каком-то пакете, вы не хотите помещать его в корневой пакет по умолчанию.

Если вы хотитечтобы избежать «принудительного» пространства имен UtilWithASingleMethod, добавьте isSatisfyingSomePredicate непосредственно к util:

package object util {
  def isSatisfyingSomePredicate(foo: Foo): Boolean = ???
}

Этот метод становится доступным, как только вы импортируете util._.

...