Возврат функции в методе

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

Еще раз начнем с постановки проблемы:

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

Начнем с простого шага: greet не принимает никаких входных параметров, а просто создает функцию и возвращает её.

Учитывая это утверждение, можно начать создавать greet. Известно, что это будет метод:

def greet()

Также известно, что этот метод должен возвращать функцию, которая:

Следовательно, эта функция имеет тип String => Unit:

def greet(): String => Unit = ???
             --------------

Теперь нужно создать тело метода. Возвращаемая функция соответствует следующему описанию:

(name: String) => println(s"Hello, $name")

Добавляем эту функцию в тело метода:

def greet(): String => Unit = 
  (name: String) => println(s"Hello, $name")

Поскольку метод возвращает функцию, мы получаем ее, вызывая greet().

val greetFunction = greet()

Теперь можно вызвать greetFunction:

greetFunction("Joe")
// Hello, Joe

Доработка метода

Метод greet() был бы более полезным, если бы была возможность задавать приветствие. Например, передать его в качестве параметра методу greet() и использовать внутри println:

def greet(theGreeting: String): String => Unit = 
  (name: String) => println(s"$theGreeting, $name")

Теперь, при вызове этого метода, процесс становится более гибким, потому что приветствие можно изменить. Вот как это выглядит, когда создается функция из этого метода:

val sayHello = greet("Hello")

Выходные данные подписи типа показывают, что sayHello — это функция, которая принимает входной параметр String и возвращает Unit. Так что теперь, при передаче sayHello строки, печатается приветствие:

sayHello("Joe")
// Hello, Joe

Приветствие можно менять для создания новых функций:

val sayCiao = greet("Ciao")
sayCiao("Isabella")
// Ciao, Isabella

val sayHola = greet("Hola")
sayHola("Carlos")
// Hola, Carlos

Более реалистичный пример

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

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

Созданный метод должен:

Кроме того, поскольку эта функция печатает заданную строку, известно, что она имеет тип String => Unit. С помощью этой информации сигнатура метода должна выглядеть так:

def createGreetingFunction(desiredLanguage: String): String => Unit = ???

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

(name: String) => println(s"Hello, $name")
(name: String) => println(s"Bonjour, $name")

Для большей читабельности дадим этим анонимным функциям имена и назначим двум переменным:

val englishGreeting = (name: String) => println(s"Hello, $name")
val frenchGreeting = (name: String) => println(s"Bonjour, $name")

Теперь все, что осталось, это вернуть englishGreeting, если desiredLanguage — английский, и вернуть frenchGreeting, если desiredLanguage — французский. Один из способов сделать это - pattern matching:

def createGreetingFunction(desiredLanguage: String): String => Unit =
  val englishGreeting = (name: String) => println(s"Hello, $name")
  val frenchGreeting = (name: String) => println(s"Bonjour, $name")
  desiredLanguage match
    case "english" => englishGreeting
    case "french" => frenchGreeting

Обратите внимание, что возврат значения функции из метода ничем не отличается от возврата строкового или целочисленного значения.

Вот как createGreetingFunction создает функцию приветствия на французском языке:

val greetInFrench = createGreetingFunction("french")
greetInFrench("Jonathan")
// Bonjour, Jonathan

И вот как - на английском:

val greetInEnglish = createGreetingFunction("english")
greetInEnglish("Joe")
// Hello, Joe

Ссылки: