# Reference or copy: segment of an array as function argument

**URL:** <https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331>\
**Category:** Performance\
**Created:** [January 12, 2018, 9:50pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331 "2018-01-12T21:50:31Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![SepandMeenu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sepandmeenu/32/8846_2.png) [@SepandMeenu](https://discourse.julialang.org/u/SepandMeenu)\
**Post date:** [January 12, 2018, 9:50pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/1 "2018-01-12T21:50:31Z")

</div>

Sometimes, a segment of an array needs to be used as an argument to a function; e.g., consider searching for `x` in a part of an (sorted) array `A`:

```julia
searchsortedfirst(A[5:end], x)

```

Does this way produce a new copy of the corresponding segment of the array; i.e., `A[5:end]`?  
If so, is there a better way to preclude that copy?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 12, 2018, 9:59pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/2 "2018-01-12T21:59:04Z")

</div>

> [@SepandMeenu](#):
>
> Does this way produce a new copy of the corresponding segment of the array; i.e., A[5:end]?

Yes

> [@SepandMeenu](#):
>
> If so, is there a better way to preclude that copy?

`@view A[5:end]`

---

<div class="post-metadata">

**Author:** ![SepandMeenu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sepandmeenu/32/8846_2.png) [@SepandMeenu](https://discourse.julialang.org/u/SepandMeenu)\
**Post date:** [January 16, 2018, 3:24pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/3 "2018-01-16T15:24:59Z")

</div>

I have tried several ways according to your suggestion:

1. `searchsortedfirst( @view A[5:end] , x0)`  
produces the following error:

> ArgumentError: Invalid use of @view macro: argument must be a reference expression A[…].

1. `vA = @view A[5:end]; searchsortedfirst(vA, x0)`  
works as expected.

2. `vA = view(A, 5:end)`  
produces the following error

> syntax: missing last argument in “5:” range expression

I do not see especially why case 3 does not work.  
Could you please elaborate on that?

---

<div class="post-metadata">

**Author:** ![jmert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jmert/32/3161_2.png) [@jmert](https://discourse.julialang.org/u/jmert)\
**Post date:** [January 16, 2018, 3:34pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/4 "2018-01-16T15:34:27Z")

</div>

In (1), the problem is that the expression is parsed like `searchsortedfirst(@view(A[5:end], x0))`, i.e. the two arguments are taken together. Just add explicit parantheses to the first argument — `searchsortedfirst(@view(A[5:end]), x0)` instead.

For (3), the macro and function call versions need to differ since `end` is not valid in an arbitrary function call argument (i.e. it needs the context of the array indexing to be automatically lowered to valid code). The correct form would look something like `vA = view(A, 5:endof(A))`.

---

<div class="post-metadata">

**Author:** ![SepandMeenu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sepandmeenu/32/8846_2.png) [@SepandMeenu](https://discourse.julialang.org/u/SepandMeenu)\
**Post date:** [January 16, 2018, 4:18pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/5 "2018-01-16T16:18:12Z")

</div>

clear explanation. thanks a lot.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 16, 2018, 4:48pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/6 "2018-01-16T16:48:22Z")

</div>

Using a view has the problem that it allocates on julia 0.6. If you need to construct these views in an inner loop, then this will mean trouble. Luckily the thing you are asking for is already provided in sort.jl; use the following:

`searchsortedfirst(A, x, 5, length(A), Base.Order.ForwardOrdering()) - 5 + 1`

---

<div class="post-metadata">

**Author:** ![SepandMeenu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sepandmeenu/32/8846_2.png) [@SepandMeenu](https://discourse.julialang.org/u/SepandMeenu)\
**Post date:** [January 16, 2018, 7:58pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/7 "2018-01-16T19:58:02Z")

</div>

could you please explain the expression you have provided?  
`Base.Order.ForwardOrdering()` and `- 5 + 1`, in particular.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [January 16, 2018, 8:25pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/8 "2018-01-16T20:25:19Z")

</div>

`searchsortedfirst(A, x, lo, hi, order)` searches only in the interval `lo:hi`. In order to get the same result as for the view, you need to shift the indices again, i.e. subtract `(lo-1)`. You can also use this version to speed up the search, if you already know something about the position of your target.

For some unclear reason, this variant is not exported with all the fancy default argument bells-and-whistles. This means that you need to provide the order explicitly. This is done by `Base.Order.ForwardOrdering()`, which is the default used by `searchsortedfirst(A, x)`. If you used keyword parameters (e.g. `searchsortedfirst(A, x; by=fun)`) then you would need to look into sort.jl in order to see how to provide these.

---

<div class="post-metadata">

**Author:** ![SepandMeenu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sepandmeenu/32/8846_2.png) [@SepandMeenu](https://discourse.julialang.org/u/SepandMeenu)\
**Post date:** [January 16, 2018, 8:40pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/9 "2018-01-16T20:40:34Z")

</div>

thanks for the elaboration.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 16, 2018, 9:32pm UTC](https://discourse.julialang.org/t/reference-or-copy-segment-of-an-array-as-function-argument/8331/10 "2018-01-16T21:32:32Z")

</div>

And of course, benchmark if all these complications end up actually making a difference in performance.
