Как создать функцию n переменных (Юлия)

Для фиксированного n я хотел бы создать функцию с n переменными

f(x_1, ..., x_n)

Например, если n=3, я хотел бы создать такой алгоритм, чтобы

f(x_1, x_2, x_3) = x_1 + x_2 + x_3

Было бы очень неплохо иметь алгоритм для каждого n:

f(x_1, ..., x_n) = x_1 + ... + x_n

Я не знаю, как объявить функцию и как создать переменные n.

Спасибо за помощь,


person Tio Miserias    schedule 22.02.2021    source источник


Ответы (2)


В Джулии вы можете просто сделать

function f(x...)
     sum(x)
end

И сейчас:

julia> f(1,2,3)
6

Обратите внимание, что внутри функции f x отображается как Tuple, поэтому вы можете делать все, что хотите (включая запрос типа элементов и т. д.).

В более общем смысле вы можете определить function f(x...;y...). Давайте попробуем

function f(x...;y...)
    @show x
    @show Dict(y)
end

А теперь запустите его:

julia> f(1,2,"hello";a=22, b=777)
x = (1, 2, "hello")
Dict(y) = Dict(:a => 22, :b => 777)
Dict{Symbol, Int64} with 2 entries:
  :a => 22
  :b => 777

Наконец, другим (возможно, менее элегантным) способом может быть:

g(v::NTuple{3,Int}) = sum(v)

Это заставляет v быть 3-элементом Tuple, а g вызываться как g((1,2,3)).

person Przemyslaw Szufel    schedule 22.02.2021
comment
И если вы хотите, чтобы функция f(x_1,x_2,...,x_n) = x_i для некоторого 1 \leq i\leq n. Как ты это делаешь? - person Tio Miserias; 23.02.2021
comment
Если вам нужна функция с, скажем, 55 параметрами Int, вы можете сгенерировать ее с параметрами macro, но я бы сказал, что использование макросов в таком сценарии является излишним, а не хорошим юлианским стилем. Менее элегантным способом может быть g(v::NTuple{3,Int}) = sum(v), который можно назвать g((1,2,3)). Надеюсь, это поможет. - person Przemyslaw Szufel; 23.02.2021
comment
@Tio Для этого вы можете сделать f(x...) = x[i], но ИМХО это немного странно. - person Benoit Pasquier; 23.02.2021
comment
Вы можете использовать Base.Cartesian (см. документы), но я полностью согласен с авторами выше, что вам лучше использовать кортежи для таких вещей. Вместо того, чтобы передавать много аргументов, просто передайте один аргумент кортежа. - person tholy; 23.02.2021

Если ваш n небольшой, вы можете сделать это вручную благодаря множественной диспетчеризации.

julia> f(x) = x + 1   # Method definition for one variable.
f (generic function with 1 method)

julia> f(x, y) = x + y + 1   # Method definition for two variables.
f (generic function with 2 methods)

julia> f(2)
3

julia> f(2, 4)
7

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

julia> g(x) = sum(x)   # Add all the elements
g (generic function with 1 method)

julia> h(x) = x[end - 1]   # Return the second to last element
h (generic function with 1 method)

julia> g([10, 11, 12])
33

julia> h([10, 11, 12])
11

Если вы предпочитаете, чтобы функция принимала произвольное количество входных данных, а не один Tuple или Vector, как вы написали в исходном вопросе, вам следует определить метод для функций с оператором ..., как показано ниже. Обратите внимание, что тела определений функций и выходные данные функций точно такие же, как и раньше. Таким образом, хлюпающий оператор ... используется только для синтаксического удобства. Приведенные ниже функции по-прежнему работают на Tuple x. Аргументы функции просто вводятся в кортеж, прежде чем делать что-либо еще. Также обратите внимание, что вы можете одновременно определить оба вышеуказанных и приведенных ниже метода, чтобы пользователь мог выбрать любой метод ввода.

julia> g(x...) = sum(x)   # Add all the variables
g (generic function with 2 methods)

julia> h(x...) = x[end - 1]   # Return the second to last variable
h (generic function with 2 methods)

julia> g(10, 11, 12)
33

julia> h(10, 11, 12)
11

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

julia> q(x) = 2 * x   # Double the input
q (generic function with 1 method)

julia> q(x...) = q(sum(x)) # Add all the inputs and call the function again on the result
q (generic function with 2 methods)

julia> q(3)
6

julia> q(3, 4, 5)
24
person Nathan Boyer    schedule 23.02.2021