#scala
#scala
Вопрос:
Я пытаюсь написать код Scala, чтобы получить список функций из клиентского кода и составить его, используя цепной подход, и, наконец, применить составленную функцию, и я могу это сделать.. Но я чувствую, что делаю это не функционально, поскольку я объявляю функциональную переменную с «var» в Test.scala (ниже) и продолжаю создавать функции поверх нее. Я считаю, что должен быть лучший подход, и любые рекомендации и предложения помогут мне
Test.scala
case class Test(val int: Int){
private final var function : Int => Int = (i: Int) => i
def composeFunction( f: Int => Int) : this.type = {
function = function.andThen(f);
this;
}
def applyFunction : Int = {
function(int)
}
}
Клиентский код: Main.scala
val c = new Test(6)
.composeFunction((i: Int) => i *2)
.composeFunction((i: Int) => i *4)
.composeFunction((i: Int) => i *6)
.applyFunction
Комментарии:
1. Я объявил функцию с именем «function» в Test.scala с поведением по умолчанию ((i: Int) => i), потому что, если клиент не вызывает «composeFunction», тогда «функция» должна выводить входное значение как есть
Ответ №1:
val c = Some(6)
.map((i: Int) => i *2)
.map((i: Int) => i *4)
.map((i: Int) => i *6)
.get
используйте библиотеку cats, если вам нужна отложенная оценка
val lazyEval = Eval.later(6)
.map((i: Int) => i *2)
.map((i: Int) => i *4)
.map((i: Int) => i *6)
.value
Ответ №2:
Аналогичная функциональная композиция может быть достигнута путем многократного применения A):T1=>A» rel=»nofollow noreferrer»> andThen
подобных:
val c = ((i: Int) => i * 2) andThen ((i: Int) => i * 4) andThen ((i: Int) => i * 6)
c(6) // res0: Int = 288
Ответ №3:
Если вы хотите избежать мутаций, лучше всего (только?)способ заключается в создании измененной копии данных, которые вы хотите изменить.
Например
final case class Test(int: Int, function: Int => Int = identity){
def composeFunction(f: Int => Int): Test =
this.copy(function = this.function.andThen(f))
def applyFunction: Int =
function(this.int)
}
val c = Test(6)
.composeFunction(i => i * 2)
.composeFunction(i => i * 4)
.composeFunction(i => i * 6)
.applyFunction // 288.
Однако, честно говоря, этот дизайн кажется мне странным.
Может быть, не было бы лучше иметь список функций, сократить его с помощью andThen и, наконец, применить результирующую функцию?
Комментарии:
1. Наличие его в виде списка было моим первым вариантом, но я хотел сохранить порядок функций, который присутствует в клиентском коде.. Я боюсь, что наличие функций в списке изменит порядок.. ListBuffers сохраняет порядок?
2. Неизменяемый
List
в Scala сохраняет порядок, изменяемыйListBuffer
также сохраняет порядок (особенно потому, что под капотом aListBuffer
находятся два неизменяемыхLists
) . Так что да, вам не стоит беспокоиться об этом.
Ответ №4:
Вы можете получить результат, связав только одну функцию
case class Test(int: Int){
def applyFunction(f: Int => Int): Test = {
this.copy(f(int))
}
}
// test
val c = Test(6)
.applyFunction((i: Int) => i * 2)
.applyFunction((i: Int) => i * 4)
.applyFunction((i: Int) => i * 6)
.int
println(c)
вывод:
288