Композиция частичных функций для уменьшения длины кода - PullRequest
0 голосов
/ 12 апреля 2019

Я хочу составить функции определенным образом, чтобы уменьшить длину кода

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


    val add3 = (a: Int, b:Int) => (c:Int) => a+b+c

    val composed = (a:Int, b:Int) => n:add3(a, b) => n(1) + n(2) + n(3)

Это было бы очень полезно, чтобы мне не приходилось каждый раз передавать a и b в качестве параметров.

Есть ли способ сделать это в Scala?

Ответы [ 2 ]

4 голосов
/ 12 апреля 2019

Я немного сбит с толку этими нотациями, такими как @Dima ... Но я прошел через этот вид ... пытаясь обработать частичные функции, записав интуитивный способ ... понять их?Это то, что вы делаете?Поэтому я постараюсь интерпретировать вас шаг за шагом.

Во-первых, мы должны прояснить вопрос о add3

Этот код, который вы дадите, может быть, просто для понимания, я думаю, выигралне компилируется в scala:

val add3 = (a: Int, b:Int)(c:Int) => a+b+c

Действительно, мы получаем в REPL:

ошибка: не является допустимым формальным параметром.Примечание: кортежи не могут быть непосредственно деструктурированы в параметрах метода или функции.Либо создайте один параметр, принимающий Tuple1, либо рассмотрите шаблон, соответствующий анонимной функции: `{case (param1, param1) => ...} val add3 = (a: Int, b: Int) (c: Int) =>a + b + c ^

Но, возможно, у меня есть идея, которую вы хотели предложить ...

add3 - это либо метод, подобный:

def add3Method (a: Int, b:Int)(c:Int) = a+b+c

, который затем может быть применен частично:

val add3 = add3Method _

Или это может быть напрямую такая функция, как:

val add3 = (a: Int, b:Int) => (c: Int) => a+b+c

В любом случае, она дает функцию типа (Int, Int) => Int => Int. Это то, что вы хотите?

Тогда мы должны прояснить вопрос о "composed"

Этот код, который вы даете, может быть, просто для понимания, я думаю,не будет компилироваться в scala ни :

val composed = (a:Int, b:Int) => n:add3(a, b) => n(1) + n(2) + n(3)

Но я могу ... Ну, по крайней мере, могла бы быть идея, которую вы хотели предложить тоже ...

(а) замыкание?

То, как ты это выражаешь, заставляет меня думать, что это замыкание, которое в конечном итоге означало бы, что composed имеет тип (Int, Int) => Int. Это то, что вы имели в виду?

(b) функция, которая принимает вид add3?

Или вы просто хотите, чтобы add3 был просто любымФункция того же типа для передачи на composed Я предполагаю, что (Int, Int) => Int => Int. Это то, что вы имели в виду?

Тогда у вас есть несколько способов определить "composed"

Либо с помощью отображения, либо с помощью промежуточной переменной.

замыкание, путь промежуточной переменной

val composedCI = (a:Int, b:Int) => { val n = add3(a,b); n(1) + n(2) + n(3)}

замыкание, способ отображения

val composedCM = (a:Int, b:Int) => (1 to 3).map(add3(a,b)).sum

, принимающий в качестве аргумента add3, путь промежуточной переменной

val composedTI = (a:Int, b:Int) => (myAdd3asAnArg: (Int, Int) => Int => Int) => { val n = myAdd3asAnArg(a,b); n(1) + n(2) + n(3) }

, принимающий в качествеаргумент add3, способ отображения

val composedTM = (a:Int, b:Int) => (myAdd3asAnArg: (Int, Int) => Int => Int) => (1 to 3).map(myAdd3asAnArg(a,b)).sum

Использование "composed"

println(composedCM(4,5))
println(composedCI(4,5))
println(composedTM(4,5)(add3))
println(composedTI(4,5)(add3))

даст

33
33
33
33

Надеюсь, это поможет ...

2 голосов
/ 12 апреля 2019

Я также не уверен, что именно вы имеете в виду, но именно так вы можете создать функцию, которая принимает:

  • g: функция, принимающая два или три целых числа, которая возвращает целое число (в вашем примере это будет add3)
  • f: функция, принимающая одно целое, которое возвращает целое число (в вашем примере это будет n)

и возвращает:

  • другая функция g (f), принимающая те же входные данные, что и g, но сначала применяющая f
// type aliases
type TwoOrThreeIntFn = (Int, Int) => Int => Int
type OneIntFn = Int => Int

// create a function that takes two functions and returns their composition
def composition(f: OneIntFn)(g: TwoOrThreeIntFn):TwoOrThreeIntFn = { (a:Int, b:Int) => (c:Int) =>  g(f(a), f(b))(f(c)) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...