шаблон кредита scala, необязательный параметр функции - PullRequest
5 голосов
/ 08 сентября 2011

У меня есть шаблон ссуды, который применяет функцию n раз, где 'i' - это возрастающая переменная. «Иногда», я хочу, чтобы переданная функция имела доступ к «i» .... но я не хочу требовать, чтобы все переданные функции требовали определения параметра для принятия «i». Пример ниже ...

def withLoaner = (n:Int) => (op:(Int) => String) => {
  val result = for(i <- 1 to n) yield op(i)
  result.mkString("\n")
}

def bob = (x:Int) => "bob" // don't need access to i. is there a way use () => "bob" instead?
def nums = (x:Int) => x.toString // needs access to i, define i as an input param

println(withLoaner(3)(bob))

println(withLoaner(3)(nums))

1 Ответ

11 голосов
/ 08 сентября 2011
def withLoaner(n: Int) = new {
  def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n")
  def apply(op: () => String) : String = apply{i: Int => op()}
}

(не уверен, как это связано с шаблоном займа)

Редактировать Небольшое объяснение, как требуется в комментарии.

Не уверен, что ты знаешь и не знаешь о scala и что ты не понимаешь в этом коде.извините, если что я просто излагаю очевидное.

Во-первых, программа scala состоит из признаков / классов (также одноэлементного объекта) и методов.Все, что делается, делается методами (оставляя конструктор в стороне).Функции (в отличие от методов) являются экземплярами (подтипами) различных признаков FunctionN (N количество аргументов).Каждый из них имеет метод apply, который является реальной реализацией.Если вы напишите

val inc = {i: Int => i + 1}

, он будет десагадирован на

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1}

(определяет анонимный класс, расширяющий Function1, с данным методом apply и создающим экземпляр)

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

С другой стороны, функции являются значениями первых классов (их можно передавать как аргументы, возвращать как результат), а методы - нет.При необходимости они автоматически преобразуются в функции, однако при этом могут возникать некоторые крайние ситуации.Если метод предназначен исключительно для использования в качестве значения функции, а не для вызова в качестве метода, может быть лучше написать функцию.

Функция f с ее методом apply вызывается с f(x) вместо f.apply(x) (что тоже работает), потому что функция scala desugars вызывает нотацию для значения (значение, сопровождаемое скобками)и 0 или более аргументов) для вызова метода apply.f(x) является синтаксическим сахаром для f.apply(x).Это работает независимо от типа f, не обязательно должен быть одним из FunctionN.

То, что делается в withLoaner, - это возвращение объекта (анонимного типа, но можно было бы определить класс отдельно и вернуть его экземпляр).У объекта есть два метода apply, один из которых принимает Int => String, другой - () => String.Когда вы делаете withLoaner(n)(f), это означает withLoaner(n).apply(f).Выбирается подходящий метод применения, если f имеет правильный тип для одного из них, в противном случае ошибка компиляции.

На всякий случай, если вам интересно, withLoaner(n) не означает withLoaner.apply(n) (или никогда не остановится, это может означать withLoaner.apply.apply(n)), поскольку withLoaner - это метод, а не значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...