# Converting a multivariate function to a single variate function

**URL:** <https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661>\
**Category:** New to Julia\
**Tags:** functions\
**Created:** [March 9, 2019, 6:23am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661 "2019-03-09T06:23:15Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [March 9, 2019, 6:23am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/1 "2019-03-09T06:23:15Z")

</div>

I want to convert a multivariate function into a single variable function. Aka to perform partial differentiation. While my attempt works but it is such an ugly kludge. Is there a better way of doing this?

```julia
func1(x,y) = 3.0*x + 7.0*y^2.0

function create1Dfunction(func::Function,vector::Vector,varnum::Int64)
    len = length(vector)
    if 1 <= varnum <= len
        codestring = "("
        for i in 1:len
            if i == varnum
                codestring = codestring * "x"
            else
                codestring = codestring * string(vector[i])
            end
            if i < len
                codestring = codestring * ", "
            end
        end
        codestring = codestring * ")"
        # println(codestring)
        subexpr = Meta.parse(codestring)
        expr = :( x -> $func($subexpr...) )
        # println(expr)
        local OneDimensionalFunc = eval(expr)
        return OneDimensionalFunc
    else
        println("Error, parameter number $(varnum) does not exists")
    end
end

# We want to convert func1(x,y) to g(x) = x -> func1(3.1,x)
println("func1(3.1,7.8) = ",func1(3.1,7.8))
g = create1Dfunction(func1,[3.1,7.8],2)
println("g(7.8) = ",g(7.8))

```

Output

```julia
Starting Julia...
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _ | |
  | | |_| | | | (_| | | Version 1.0.3 (2018-12-18)
 _/ |\ ___|_|_|\__ _| | Official https://julialang.org/ release
|__/ |

func1(3.1,7.8) = 435.18
g(7.8) = 435.18

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 9, 2019, 6:34am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/2 "2019-03-09T06:34:38Z")

</div>

How about just this:

```julia
julia> func1(x, y) = 3.0*x + 7.0*y^2.0
func1 (generic function with 1 method)

julia> g(x) = func1(3.1, x)
g (generic function with 1 method)

julia> func1(3.1, 7.8)
435.18

julia> g(7.8)
435.18

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [March 9, 2019, 6:35am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/3 "2019-03-09T06:35:51Z")

</div>

What if my function have 26 variables and I want to convert it to a single variable function on variable number 21? And fill the rest with the value [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26] and I don’t want to do it by hand. And I don’t know the value of the vector of numbers to replace them with at compile time but only at runtime.

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [March 9, 2019, 6:56am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/4 "2019-03-09T06:56:43Z")

</div>

Ah, I see. Here’s an option without dynamic code generation:

```julia
oned(f, args, pos) = x -> f(ntuple(i -> i == pos ? x : args[i], length(args))...)

f(x, y) = 3.0*x + 7.0*y^2

g = oned(f, [3.1, 7.8], 2)

```

And now:

```julia
julia> f(3.1, 7.8)
435.18

julia> g(7.8)
435.18

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [March 9, 2019, 8:02am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/5 "2019-03-09T08:02:24Z")

</div>

> [@bennedich](#):
>
> oned(f, args, pos) = x -\> f(ntuple(i -\> i == pos ? x : args[i], length(args))…)

Thank you very much. That worked and is a lot shorter

```julia
function oned(f::Function, args::Vector, pos::Int64)
    return x -> f(ntuple(i -> i == pos ? x : args[i], length(args))...)
end
h = oned(func1,[3.1,7.8],2)
println("h(7.8) = ",h(7.8))

```

Output

```julia
Starting Julia...
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _ | |
  | | |_| | | | (_| | | Version 1.0.3 (2018-12-18)
 _/ |\ ___|_|_|\__ _| | Official https://julialang.org/ release
|__/ |

func1(3.1,7.8) = 435.18
g(7.8) = 435.18
h(7.8) = 435.18

```

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [March 9, 2019, 8:19am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/6 "2019-03-09T08:19:00Z")

</div>

Please check my final version of the program

```julia
func1(x,y) = 3.0 * x + 7.0 * y ^ 2.0
func2(X) = 3.0 * X[1] + 7.0 * X[2] ^ 2.0

function create1Dfunction(func::Function,args::Vector,pos::Int64;FuncType::String="MultiParameters")
    if 1 <= pos <= length(args)
        if FuncType == "MultiParameters"
            return x -> func( ntuple(i -> i == pos ? x : args[i], length(args))... )
        else
            return x -> func( ntuple(i -> i == pos ? x : args[i], length(args)) )
        end
    else
        println("Error! Parameter number $(pos) does not exists")
        return x -> Nothing
    end
end

# We want to convert func(x,y) to g(x) = x -> func1(3.1,x)
println("func1(3.1,7.8) = ",func1(3.1,7.8))
g = create1Dfunction(func1,[3.1,7.8],2)
println("g(7.8) = ",g(7.8))
h = create1Dfunction(func2,[3.1,7.8],2,FuncType="VectorParameters")
println("h(7.8) = ",h(7.8))

```

Output

```julia
func1(3.1,7.8) = 435.18
g(7.8) = 435.18
h(7.8) = 435.18

```

---

<div class="post-metadata">

**Author:** ![Yannik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yannik/32/47957_2.png) [@Yannik](https://discourse.julialang.org/u/Yannik)\
**Post date:** [August 9, 2024, 8:42am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/7 "2024-08-09T08:42:06Z")

</div>

you could also [splat](https://docs.julialang.org/en/v1/base/base/#...) the vector

```julia
f(a,b,c,d,e,f,g) = a+b+c+d+e+f+g
g(a) = f(a,[1,2,3,4,5,6]...)
g(3) #24

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 9, 2024, 6:41pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/8 "2024-08-09T18:41:30Z")

</div>

Another option could be to add a method to the function `foo` using keyword arguments with the same names:

```julia
foo(a,b,c,d,e,f,g) = a + b + c + d + e + f + g

foo(;a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0, g=7.0) = foo(a,b,c,d,e,f,g)

# Examples:
foo(c=-25) # 0.0
foo(d=0) # 24.0

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [August 9, 2024, 7:50pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/9 "2024-08-09T19:50:11Z")

</div>

My package CallableExpressions.jl supports constructing evaluatable expression, and partial evaluation of these expressions. Several other packages offer different approaches to solving similar problems. A PR by @MilesCranmer, solving this problem, was also recently merged, to be released with Julia v1.12:

> <https://github.com/JuliaLang/julia/pull/54653>
>
> This PR generalises \`Base.Fix1\` and \`Base.Fix2\` to \`Base.Fix{n}\`, to allow fixin…g a single positional argument of a function.
> 
> With this change, the implementation of these is simply
> 
> \`\`\`julia
> const Fix1{F,T} = Fix{1,F,T}
> const Fix2{F,T} = Fix{2,F,T}
> \`\`\`
> 
> Along with the PR I also add a larger suite of unittests for all three of these functions to complement the existing tests for \`Fix1\`/\`Fix2\`.
> 
> \### Context
> 
> There are multiple motivations for this generalization.
> \*\*By creating a more general \`Fix{N}\` type, there is no preferential treatment of certain types of functions:\*\*
> 
> \- (i) No limitation that you can only fix positions 1-2. You can now fix any position \`n\`.
> \- (ii) No asymmetry between 2-argument and n-argument functions. You can now fix an argument for functions with any number of arguments.
> \- (iii) ~~No asymmetry between positional arguments and keyword arguments. You can now fix a keyword argument.~~
> 
> 
> Think of this like if \`Base\` only had \`Vector{T}\` and \`Matrix{T}\`, and you wished to generalise it to \`Array{T,N}\`.
> It is an analogous situation here: \`Fix1\` and \`Fix2\` are now \*aliases\* of \`Fix{N}\`.
> 
> \- \*\*Convenience\*\*:
> - \`Base.Fix1\` and \`Base.Fix2\` are useful shorthands for creating simple anonymous functions without compiling new functions.
> - They are very common throughout the Julia ecosystem as a shorthand for filling arguments:
> - \`Fix1\` https://github.com/search?q=Base.Fix1+language%3Ajulia&type=code
> - \`Fix2\` https://github.com/search?q=Base.Fix2+language%3Ajulia&type=code
> \- \*\*Less Compilation\*\*:
> - Using \`Fix\*\` reduces the need for compilation of repeatedly-used anonymous functions (which can often trigger compilation of new functions).
> \- \*\*Type Stability\*\*:
> - \`Fix\`, like \`Fix1\` and \`Fix2\`, captures variables in a struct, encouraging users to use a functional paradigm for closures, preventing any potential type instabilities from boxed variables within an anonymous function.
> \- \*\*Easier Functional Programming\*\*:
> - Allows for a stronger functional programming paradigm by supporting partial functions with \_any number of arguments\_.
> 
> Note that this refactors \`Fix1\` and \`Fix2\` to be equal to \`Fix{1}\` and \`Fix{2}\` respectively, rather than separate structs. This is backwards compatible.
> 
> Also note that this does not constrain future generalisations of \`Fix{n}\` for multiple arguments. \`Fix{1,F,T}\` is the clear generalisation of \`Fix1{F,T}\`, so this isn't major new syntax choices. But in a future PR you could have, e.g., \`Fix{(n1,n2)}\` for multiple arguments, and it would still be backwards-compatible with this.
> 
> \### Details
> 
> As the names suggest, \`Fix1\` and \`Fix2\`, they can only inject arguments at the first and second index. Furthermore, they are also constrained to work on 2-argument functions exclusively. It seems at various points there had been interest in extending this (see links below) but nobody had gotten around to it so far.
> 
> This implementation of \`Base.Fix\` generalises the form as follows:
> 
> \> \`Fix{n}(f, x)\`
> 
> \> A type representing a partially-applied version of a function \`f\`, with the argument
> \> "x" fixed at argument \`n::Int\` or keyword \`kw::Symbol\`.
> \> In other words, \`Fix{3}(f, x)\` behaves similarly to
> \> \`(y1, y2, y3) -\> f(y1, y2, x, y3)\` for the 4-argument function \`f\`.
> 
> 
> With this more general type, I also rewrite \`Fix1\` and \`Fix2\` in this PR.
> 
> \`\`\`julia
> const Fix1{F,T} = Fix{1,F,T}
> const Fix2{F,T} = Fix{2,F,T}
> \`\`\`
> 
> With \`Fix{n}\`, the code which is executed is roughly as follows:
> 
> \`\`\`julia
> function (f::Fix{N})(args...; kws...) where {N}
> return f.f(args\[begin:begin+(N-2)\]..., f.x, args\[begin+(N-1):end\]...; kws...)
> end
> \`\`\`
> 
> This means that the captured variable \`x\` is inserted at the \`N\`-th position. Keywords are also captured and inserted at the end.
> 
> This adds several unittests, a docstring, as well as type stability checks, for which it seems to succeed.
> 
> I also run the new \`Fix1\` and \`Fix2\` test suites added by this PR on the \`Fix\` version of each struct.
> 
> \### Examples
> 
> \*\*Simple examples:\*\*
> 
> To fix the argument \`f\` with an anonymous function:
> 
> \`\`\`julia
> with\_f = (a, b, c, d, e, g, h, i, j, k) -\> my\_func(a, b, c, d, e, f, g, h, i, j, k)
> \`\`\`
> 
> whereas now it becomes:
> 
> \`\`\`julia
> with\_f = Base.Fix{6}(my\_func, f)
> \`\`\`
> 
> I have some usecases like this in SymbolicRegression.jl. I want to fix a single option in a function, and then repeatedly call that function throughout some loop with different input. \`Fix1\` and \`Fix2\` are not general enough for this as they only allow 2-argument functions.
> 
> A more common use-case I have is to set \`MIME"text/plain"\` in \`print\` for tests, which can now be done as \`Fix\` is no longer limited to 2 arguments:
> 
> \`\`\`julia
> s = sprint(Fix{2}(print, MIME"text/plain"()), my\_object)
> \`\`\`
> 
> without needing to re-compile at each instance.
> 
> 
> \*\*\<details\>\<summary\>In a reduction:\</summary\>\*\*
> 
> Fix1 and Fix2 are useful for short lambda functions like
> 
> \`\`\`julia
> sum(Base.Fix1(\*, 2), \[1, 2, 3, 4, 5\])
> \`\`\`
> 
> to reduce compilation and often improve type stability.
> 
> With this new change, you aren't limited to only 2-arg functions, so you can use things like fma in this context:
> 
> \`\`\`julia
> sum(Base.Fix{2}(Base.Fix{3}(fma, 2.0), 0.5), \[1, 2, 3, 4, 5\])
> \`\`\`
> 
> where this will evaluate as x -\> affine(x, 0.5, 2.0).
> 
> Another example is a mapreduce, where you would typically want to fix the map and reduction in applying:
> 
> \`\`\`julia
> sum(
> Base.Fix{1}(Base.Fix{1}(mapreduce, abs), \*),
> \[\[1, -1\], \[2, -3, 4\], \[5\]\]
> )
> \`\`\`
> 
> \</details\>
> 
> \*\*\<details\>\<summary\>In data processing pipelines:\</summary\>\*\*
> 
> Fix can be used to set any number of arguments, and of course also be chained together repeatedly as there is no restriction on 2-arg functions. It makes functional programming easier than with only Fix1 and Fix2.
> 
> For example, in a processing pipeline:
> 
> \`\`\`julia
> using CSV, DataFrames
> 
> affine(a, b, c) = a .+ b .\* c
> 
> affine\_transform\_df(path) = (
> CSV.read(path, DataFrame)
> |\> dropmissing
> |\> Fix{1}(filter, :id =\> ==(7)) # Use like Fix2
> |\> Fix{2}(Fix{3}(affine, 2.0), 0.5) # Multiple args
> |\> Fix{2}(getproperty, :a)
> )
> 
> affine\_transform\_df("data.csv")
> \`\`\`
> 
> \</details\>
> 
> \*\*\<details\>\<summary\>For dispatching on keyword-fixed functions:\</summary\>\*\*
> 
> Say that I would like to dispatch on
> \`sum\` for some type, if \`dims\` is set to an integer. You can do this as follows:
> 
> \`\`\`julia
> struct MyType
> x::Float64
> end
> 
> function (f::Base.Fix{:dims,typeof(sum),Int64})(ar::AbstractArray{MyType})
> return sum(ar; dims=f.k.dims)
> end
> \`\`\`
> 
> which would result in any use of \`Fix(sum; dims=1)\` operating on
> \`Vector{MyType}\` to call this special function.
> 
> \</details\>
> 
> \*\*\<details\>\<summary\>Real-world examples\*\*
> 
> I would like to use this in my code. Here are some examples:
> 
> \</summary\>
> 
> 
> 
> \- https://github.com/MilesCranmer/SymbolicRegression.jl/blob/ea03242d099aa189cad3612291bcaf676d77451c/src/InterfaceDynamicExpressions.jl#L177-L191
> \- https://github.com/MilesCranmer/DataDrivenDiffEq.jl/blob/ba70d94dd851d5880fa670d6325296512b7435b3/src/solve/koopman.jl#L140
> \- https://github.com/MilesCranmer/pysr\_paper/blob/b30687433fb32d3b9784fbedb1480d947dc46fc0/animations/optimization\_example.jl#L33
> \- https://github.com/MilesCranmer/DispatchDoctor.jl/blob/02b46f6060c84c632dedf5e602dd3ca6a2c72d95/src/stabilization.jl#L212
> \- https://github.com/MilesCranmer/DispatchDoctor.jl/blob/02b46f6060c84c632dedf5e602dd3ca6a2c72d95/src/stabilization.jl#L222
> \- https://github.com/MilesCranmer/DispatchDoctor.jl/blob/02b46f6060c84c632dedf5e602dd3ca6a2c72d95/src/stabilization.jl#L233
> \- https://github.com/MilesCranmer/UniAdminTools.jl/blob/0f523364fc0f43446ff7c31f6ae3acf6c1ea927f/src/mergescore.jl#L289-L292
> \- https://github.com/MilesCranmer/DataDrivenDiffEq.jl/blob/ba70d94dd851d5880fa670d6325296512b7435b3/docs/examples/5\_michaelis\_menten.jl#L30
> \- https://github.com/MilesCranmer/DispatchDoctor.jl/blob/02b46f6060c84c632dedf5e602dd3ca6a2c72d95/test/llvm\_ir\_tests.jl#L8
> 
> For example,
> 
> \`\`\`julia
> function michaelis\_menten(X::AbstractMatrix, p, t::AbstractVector)
> reduce(hcat, map((x,ti)-\>michaelis\_menten(x, p, ti), eachcol(X), t))
> end
> \`\`\`
> 
> which could now be done with \`map(Fix{2}(michaelis\_menten, p), eachcol(X), t)\`, reducing compilation costs, and avoiding any potential issues with capturing variables in the closure.
> 
> Another one would be this:
> 
> \`\`\`julia
> candidate\_info\_data = DataFrame((
> name = string.(candidates),
> score = (x -\> round(x, digits = 3)).(summary\_scores.mean),
> uncertainty = (x -\> round(x, digits = 2)).(summary\_scores.std),
> q25 = (x -\> round(x, digits = 3)).(summary\_scores\_q\[!, "25.0%"\]),
> q75 = (x -\> round(x, digits = 3)).(summary\_scores\_q\[!, "75.0%"\]),
> ))
> \`\`\`
> 
> with this you could write \`Fix(round; digits=3)\` and not need to re-compile an anonymous function for each new outer method.
> 
> \</details\>
> 
> 
> 
> \### Features in other languages
> 
> Here are some of the most related features in other languages (all that I could find; there's probably more)
> 
> \#### Groovy's \`.ncurry\`
> 
> \<details\>\<summary\>(Expand)\</summary\>
> 
> In Apache Groovy there is the \`\<function\>.ncurry(index, args...)\` to insert arguments at a given index. This syntax is semantically identical to \`Base.Fix\`.
> 
> From the \[documentation\](https://web.archive.org/web/20240522202230/https://groovy-lang.org/closures.html#\_index\_based\_currying)
> \> In case a closure accepts more than 2 parameters, it is possible to set an arbitrary parameter using ncurry:
> \>
> \> \`\`\`groovy
> \> def volume = { double l, double w, double h -\> l\*w\*h }
> \> def fixedWidthVolume = volume.ncurry(1, 2d)
> \> assert volume(3d, 2d, 4d) == fixedWidthVolume(3d, 4d)
> \> def fixedWidthAndHeight = volume.ncurry(1, 2d, 4d)
> \> assert volume(3d, 2d, 4d) == fixedWidthAndHeight(3d)
> \> \`\`\`
> \>
> \> 1. the \`volume\` function defines 3 parameters
> \> 2. \`ncurry\` will set the second parameter (index = 1) to 2d, creating a new volume function which accepts length and height
> \> 3. that function is equivalent to calling \`volume\` omitting the width
> \> 4. it is also possible to set multiple parameters, starting from the specified index
> \> 5. the resulting function accepts as many parameters as the initial one minus the number of parameters set by \`ncurry\`
> 
> \</details\>
> 
> \#### Python's \`functools.partial\`
> 
> \<details\>\<summary\>(Expand)\</summary\>
> 
> In Python, there is no differentiating between args and kwargs – every function can be passed kwargs. Therefore, \`functools.partial\` is semantically similar to \`Fix\`:
> 
> \`\`\`python
> def f(a, b, c, d):
> return a + b \* c - d
> 
> f\_with\_b = functools.partial(f, b=2.0)
> 
> f\_with\_b(1.0, d=3.0)
> \`\`\`
> 
> which would be equivalent to \`Fix{2}(f, 2.0)\`.
> 
> \</details\>
> 
> \#### C++'s \`std::bind\`
> 
> \<details\>\<summary\>(Expand)\</summary\>
> 
> In modern C++, one can use \`std::bind\` to insert \[placeholders\](https://en.cppreference.com/w/cpp/utility/functional/bind). This is semantically closer to an anonymous function in Julia, though it \*binds\* the arguments in a way similar to \`Fix1\` and \`Fix2\` do:
> 
> \`\`\`cpp
> void f(int n1, int n2, int n3, const int& n4, int n5);
>  
> int main() {
> using namespace std::placeholders
> 
> auto f2 = std::bind(f, \_3, std::bind(g, \_3), \_3, 4, 5);
> f2(10, 11, 12) // f(12, g(12), 12, 4, 5)
> }
> \`\`\`
> 
> \</details\>
> 
> The C++ approach was also briefly mentioned on discourse \[back in 2018\](https://discourse.julialang.org/t/fix1-analogue-of-base-fix2/10161/12).
> 
> \---
> 
> Closes:
> 
> \- https://github.com/JuliaLang/julia/issues/50553
> \- https://github.com/JuliaLang/julia/issues/36181
> 
> Related issues:
> 
> \- Initial discussion on Fix1 on \[discourse\](https://discourse.julialang.org/t/fix1-analogue-of-base-fix2/10161/9) which @tpapp added in https://github.com/JuliaLang/julia/pull/26708
> \- https://github.com/JuliaLang/julia/issues/15276
> 
> Other approaches:
> 
> \- \[FixArgs.jl\](https://github.com/goretkin/FixArgs.jl) which stemmed out of https://github.com/JuliaLang/julia/issues/36181
> - Note that this package takes a \*\*much\*\* different and more extensive approach to this problem using macros (see \[docs\](https://goretkin.github.io/FixArgs.jl/dev/#Symbolic-computation-and-lazy-evaluation)), so is likely not in-scope for merging to \`Base\`. I have written the \`Base.Fix\` in this PR from scratch based on the same patterns as \`Fix1\` and \`Fix2\` but with varargs.
> \- \[AccessorsExtra.jl\](https://github.com/JuliaAPlavin/AccessorsExtra.jl)
> - The \`FixArgs\` implementation in this package is much more closely related to this PR. It works in a similar way although though stores the full signature with a \`Placeholder()\` set to the replaced arg.
> \- \[FastBroadcast.jl\](https://github.com/YingboMa/FastBroadcast.jl) defines an identical (aside from keywords) struct \[here\](https://github.com/YingboMa/FastBroadcast.jl/blob/9077379705b3d7d1677188c1e18d841daccdbe18/src/FastBroadcast.jl#L14-L18) for internal use
> 
> Semi-related issues:
> 
> \- https://github.com/JuliaLang/julia/issues/554
> \- https://github.com/JuliaLang/julia/issues/5571
> \- https://github.com/JuliaLang/julia/pull/24990
> \- https://github.com/JuliaLang/julia/pull/36093 
> \---
> 
> \- \*\*Edit 1\*\*: ~~Made \`Fix\` work for \`Vararg\` so that you can insert multiple arguments at the specified index.~~
> \- \*\*Edit 2\*\*: Added keyword ~~s~~ to \`Fix\`.
> \- \*\*Edit 3\*\*: Switched from \`Fix(f, Val(1), arg)\` syntax to \`Fix{1}(f, arg)\`.
> \- \*\*Edit 4\*\*: After triage, added back the keyword argument ~~s~~ , and rewrote \`Fix1\` and \`Fix2\` in terms of \`Fix\`.
> \- \*\*Edit 5\*\*: Added some validation checks for repeated keywords and non-\`Int64\` \`n\`
> \- \*\*Edit 6\*\*: Restricted the number of keyword arguments OR arguments to 1, and made struct more minimal.
> \- \*\*Edit 7\*\*: After second triage, various cleanup and simplification of code
> \- \*\*Edit 8\*\*: Removed the keyword argument. Now \`Fix{n}\` is exclusively for a single positional keyword argument.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 9, 2024, 9:03pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/10 "2024-08-09T21:03:23Z")

</div>

This thread is _ancient_, but this should be done using tuples instead:

```julia
create1arg(f, args::Tuple, pos::Integer) = x -> f(Base.setindex(args, x, pos)...) 

```

And then distinguish the vector-arg version like this

```julia
create1arg(f, args::Vector, pos::Integer) = x -> f(setindex!(args, x, pos)) 

```

Or some non-mutating version of this.

_Don’t_ splat vectors, btw.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 9, 2024, 9:07pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/11 "2024-08-09T21:07:06Z")

</div>

> [@DNF](#):
>
> This thread is _ancient_

Our grannies too. Can we continue to visit them, please.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 9, 2024, 9:13pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/12 "2024-08-09T21:13:55Z")

</div>

Okay, but at some point it’s more for one’s own sake, than theirs.

---

<div class="post-metadata">

**Author:** ![Yannik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yannik/32/47957_2.png) [@Yannik](https://discourse.julialang.org/u/Yannik)\
**Post date:** [August 13, 2024, 11:44am UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/13 "2024-08-13T11:44:02Z")

</div>

> _Don’t_ splat vectors, btw.

Could you elaborate? Are there any drawbacks or hidden problems?

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [August 13, 2024, 12:21pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/14 "2024-08-13T12:21:29Z")

</div>

> [@Why is the splat operator slow?](https://discourse.julialang.org/t/why-is-the-splat-operator-slow/77928):
>
> I was doing some benchmarks and got these results: julia\> using BenchmarkTools julia\> f1(itr) = collect(itr) f1 (generic function with 1 method) julia\> f2(itr) = [itr...] f2 (generic function with 1 method) julia\> gen = (x for x in 1:1000) Base.Generator{UnitRange{Int64}, typeof(identity)}(identity, 1:1000) julia\> @btime f1($gen); 910.000 ns (1 allocation: 7.94 KiB) julia\> @btime f2($gen); 80.200 μs (1988 allocations: 84.44 KiB) Why is the splat operator slower than the collect functi…

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [August 13, 2024, 12:57pm UTC](https://discourse.julialang.org/t/converting-a-multivariate-function-to-a-single-variate-function/21661/15 "2024-08-13T12:57:05Z")

</div>

> [@Yannik](#):
>
> `g(a) = f(a,[1,2,3,4,5,6]...)`

The size of a `Vector` is not part of the type, so the compiler doesn’t know which method of `f` to call. In principle, I guess (but don’t know), that when you have a literal vector like above (`[1,2,3,4,5,6]`) the length could be known, by constant propagation or something.

But in general, the compiler only sees `f(::Int, (::Vector{Int})...)` and that’s no good.

Splatting a tuple or a StaticArray, on the other hand, is fine, since then compiler knows the size: `f(::Int, (::NTuple{5, Int})...)` is just the same as `f(::Int, ::Int, ::Int, ::Int, ::Int, ::Int)`. (Well, I mean in pseudocode, since it’s not actually valid syntax.)
