One solution that I don’t think has been mentioned yet: using higher-order functions (HOF). In my experience, it is frequently the case that most of the code can be factored out, and only a small part of it needs to change. It can then be beneficial to factor out the large, common parts in a higher-order function; the small, “extra” part can then be passed as a function argument to the HOF.
Minimal example:
# A higher-order function to factor out all common code
julia> function common_parts(extra, x, y)
z = 2x + y # block A
z = extra(z) # extra block
z *= 3 # block B
end
common_parts (generic function with 1 method)
# No extra part: z = identity(z)
julia> fun(x, y) = common_parts(identity, x, y)
fun (generic function with 1 method)
# I tend to like the `do` block better, but you could also write
# gun(x, y) = common_parts(z -> z-5, x, y)
julia> gun(x, y) = common_parts(x, y) do z
z - 5
end
gun (generic function with 1 method)
julia> fun(1, 2)
12
julia> gun(1, 2)
-3