Когда использовать частично прикладные функции
Примечание: перейдите к "Вопросу" ниже, если вы просто хотите пропустить контекст
Когда вы беседуете о Scala, я в значительной степени даю "игрушечные проблемы", подобные приведенным ниже, в качестве примеров частично прикладных функций.
def multiply(x:Int, y:Int): Int = x * y
val x5 = multiply(5, _:Int)
x5(10) //produces 50
Этот пример помогает, однако мне сложно объяснить общее "это когда вы узнаете, когда использовать частично прикладную функцию".
Вопрос. У каждого есть свой способ успешного объяснения частично прикладных функций, которые действительно попадают домой для разработчиков Java (или других OO)?
Ответы
Ответ 1
Предположим, вы хотите применить налог с продаж.
def withTax(cost: Float, state: String) = { /* Some complicated lookup table */ }
Теперь предположим, что вы хотите сделать кучу покупок в Нью-Йорке.
val locallyTaxed = withTax(_: Float, "NY")
val costOfApples = locallyTaxed(price("apples"))
Вы получаете максимальное повторное использование кода из исходного метода, но максимальное удобство для повторяющихся задач не должно указывать параметры, которые (локально) всегда одинаковы.
Люди часто пытаются решить это с помощью implicits:
def withTax(cost: Float)(implicit val state: String) = ...
Не делай этого! (Не без тщательного рассмотрения.) Трудно следить за тем, какой неявный val случается вокруг в то время. С частично примененными функциями вы получаете такую же экономию при наборе текста, плюс вы знаете, какой из них вы используете, потому что вы вводите имя каждый раз, когда используете его!
Ответ 2
В Java вы часто передаете первые (или более) аргументы частично применяемой функции конструктору класса. Пример Rex может выглядеть примерно так:
class TaxProvider {
final String state;
TaxProvider(String state) {
this.state = state;
}
double getTaxedCost(double cost) {
return ... // look up tax for state and apply to cost
}
}
TaxProvider locallyTaxed = new TaxProvider("NY")
double costOfApples = locallyTaxed.getTaxedCost(price("apples"))
Ответ 3
Я предполагаю, что Scala имеет состав функции, это то, что частично прикладывает функции.
Другим пунктом являются функции более высокого порядка, такие как filter
, которые берут предикат, и их использование, как в:
filter (<42) list -- sorry, don't speak Scala
Предикат часто является частью частично применяемой функции. То же самое верно для map
, fold
и т.д.