I would like to define a certain function that takes a vector as input and does some computations that involving varying just one of the entries. For example, if the input vector is a
, I would like to compute f(a)
whlie “pretending” that a[1] = 0
.
One way to do this is b = copy(a); b[1] = 0, f(b)
, but this requires copying a
each time I call f
. The problem is that I will need to do this many times, letting a[1] = 0.0
, a[1] = 0.1
, etc., and then similar for a[2]
(think numerical integration).
Here is a working but inefficient function that creates copies:
# Desired behavior, but makes a bunch of copies
function foo(a::Vector)
for m in 0:0.1:1
b = copy(a)
b[1] = m
# do some computations on b
@show b
end
end
foo(rand(3))
#=
b = [0.0, 0.70594453750852, 0.21204039022374865]
b = [0.1, 0.70594453750852, 0.21204039022374865]
b = [0.2, 0.70594453750852, 0.21204039022374865]
b = [0.3, 0.70594453750852, 0.21204039022374865]
b = [0.4, 0.70594453750852, 0.21204039022374865]
b = [0.5, 0.70594453750852, 0.21204039022374865]
b = [0.6, 0.70594453750852, 0.21204039022374865]
b = [0.7, 0.70594453750852, 0.21204039022374865]
b = [0.8, 0.70594453750852, 0.21204039022374865]
b = [0.9, 0.70594453750852, 0.21204039022374865]
b = [1.0, 0.70594453750852, 0.21204039022374865]
=#
Here I use let
to avoid making copies, but I have to tuple-unpack the vector, so it only works for vectors of length 3:
# Working version using let; avoids copying, but only
# works for 3-vectors
function bar(z::Vector)
a, b, c = z
for m in 0:0.1:1
let a = m
# do some computations
@show [a, b, c]
end
end
end
bar(rand(3))
#=
[a, b, c] = [0.0, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.1, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.2, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.3, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.4, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.5, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.6, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.7, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.8, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [0.9, 0.2899170892058196, 0.9979264085173909]
[a, b, c] = [1.0, 0.2899170892058196, 0.9979264085173909]
=#
Here is what I would really like to do:
# Attempt to do this without making so many copies of a
function baz(a::Vector)
for m in 0:0.1;1
let a = a, a[1] = m
# do some computations on a
@show a
end
end
end
baz(rand(3))
#=
syntax: invalid let syntax around In[66]:4
Stacktrace:
[1] top-level scope at In[66]:2
[2] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091
=#
Am I on the right track? Is there a better way to accomplish this task?