# Slurping in not final position

**URL:** <https://discourse.julialang.org/t/slurping-in-not-final-position/102784>\
**Category:** General Usage\
**Tags:** function-parameters, destructuring\
**Created:** [August 14, 2023, 9:12am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784 "2023-08-14T09:12:03Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 9:12am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/1 "2023-08-14T09:12:03Z")

</div>

I was running the roames notebook exercises, in an attempt to fix this:

> Create a more generic `reduce2` function that works recursively over a tuple

For the operations `+` and `*`, being associative, simulate the operation in this direction 1\*(2\*(3\*(4))) or on the contrary (((1)\*2)\*3)\*4, the result is the same.  
However, wanting to extend the result also to the operations (-) and (/) I tried to create the second structure, i.e. ((((1/2)/3)/4)/5) which is the one adopted by the library `reduce` function.  
In the absence of slurping in a not final position, I had to use this somewhat convoluted method.

```julia
reduce3(f, t::Tuple)= _r(f,reverse(t)...) 
_r(f,(x,))=x
_r(f,h,t...)=f(reduce3(f,reverse(t)),h) 

```

I’ve tried using non-trailing slurping, which I thought was possible in version 1.9 of julia, also as function arguments as well as for assigning values to multiple variables.

Why was this possibility not extended to function arguments?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 14, 2023, 9:31am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/2 "2023-08-14T09:31:06Z")

</div>

With “non-trailing slurping”, are you referring to something like this:

```julia
f(a, b..., c, d) = # something

```

? If not, which syntax exactly are you referring to?

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 9:41am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/3 "2023-08-14T09:41:54Z")

</div>

> [@Sukera](#):
>
> With “non-trailing slurping”, are you referring to something like this:

yes I tried to use this expression

```julia
_r(f,t...,h) =...

```

I take the opportunity to ask another question.  
Why do the following two definitions seem equivalent?

```julia
julia> g((x,))=x^2
g (generic function with 1 method)

julia> g(2)
4

julia> g(x)=x^2
g (generic function with 1 method)

julia> g(2)
4

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 14, 2023, 9:45am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/4 "2023-08-14T09:45:38Z")

</div>

> [@rocco\_sprmnt21](#):
>
> yes I tried to use this expression
> 
> ```julia
> _r(f,t...,h) =...
> 
> ```

If you allow slurping in non-trailing position, the following two method definitions would always be ambiguous:

```julia
f(a, b, c..., d) = # something
f(a, b..., c, d) = # something

```

There are lots of possible combinations to get such an ambiguity, so I think that’s why it’s likely not supported.

> [@rocco\_sprmnt21](#):
>
> I take the opportunity to ask another question.  
> Why do the following two definitions seem equivalent?

Because `g((x,)) = ...` is the same as `g(x,) = ...`, which is the same as `g(x) = ...`.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 9:55am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/5 "2023-08-14T09:55:37Z")

</div>

Thank you!  
On the main question (that of slurping) I have to think about it calmly.  
For the secondary question: why don’t the same parsing rules hold for the case of a tuple with two elements?

```julia
julia> g((x,y))=x+y
g (generic function with 1 method)

julia> g(x,y)=x+y
g (generic function with 2 methods)

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [August 14, 2023, 10:07am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/6 "2023-08-14T10:07:47Z")

</div>

> [@Sukera](#):
>
> Because `g((x,)) = ...` is the same as `g(x,) = ...`, which is the same as `g(x) = ...`.

No, it’s not the same. The first one does tuple destructuring, the last one doesn’t.

```julia
julia> f1((x,)) = x^2
f1 (generic function with 1 method)

julia> f2(x) = x^2
f2 (generic function with 1 method)

julia> f1((2, 3))
4

julia> f2((2, 3))
ERROR: MethodError: no method matching ^(::Tuple{Int64, Int64}, ::Int64)

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 10:13am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/7 "2023-08-14T10:13:17Z")

</div>

So the two expressions (two methods!??!, why only one method then?)) are equivalent only for input of a single element?

```julia
julia> g((x,))=x.^2
g (generic function with 1 method)

julia> 

julia> g(((2,3),))
(4, 9)

julia> g(3)
9

julia> g(2,3)
ERROR: MethodError: no method matching g(::Int64, ::Int64)

julia> g(x)=x.^2
g (generic function with 1 method)

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [August 14, 2023, 10:21am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/8 "2023-08-14T10:21:46Z")

</div>

> [@rocco\_sprmnt21](#):
>
> So the two expressions (two methods!??!, why only one method then?))

Both `g(x) = ...` and `g((x,)) = ...` define `g(::Any)`, so the one defined last overwrites the first one.

> [@rocco\_sprmnt21](#):
>
> equivalent only for input of a single element?

That’s a side effect of numbers being iterable, so you can destructure a single scalar.

```julia
julia> f((x,)) = x
f (generic function with 1 method)

julia> f(1)
1

julia> f("foo")
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)

julia> struct Foo end

julia> f(Foo())
ERROR: MethodError: no method matching iterate(::Foo)

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 10:45am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/9 "2023-08-14T10:45:16Z")

</div>

I don’t want to abuse your availability, but I also try to ask the reason for the following results:

```julia
julia> t,h...=1
1

julia> t
1

julia> h
Base.Iterators.Rest{Int64, Nothing}(1, nothing)

julia> t...,h=1
1

julia> t
Int64[]

julia> h
1

julia> k,t...,h = 1
ERROR: ArgumentError: The iterator only contains 0 elements, but at least 1 were requested.

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [August 14, 2023, 11:15am UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/10 "2023-08-14T11:15:11Z")

</div>

> [@rocco\_sprmnt21](#):
>
> ```julia
> julia> t,h...=1
> 1
> 
> julia> t
> 1
> 
> julia> h
> Base.Iterators.Rest{Int64, Nothing}(1, nothing)
> 
> ```

This assigns the first element to `t`, and the rest to `h`. In this case, `h` is empty, as there is only one element on the right-hand side.

> [@rocco\_sprmnt21](#):
>
> ```julia
> julia> t...,h=1
> 1
> 
> julia> t
> Int64[]
> 
> julia> h
> 1
> 
> ```

In this case, the last element is assigned to `h`, and the elements before that are assigned to `t`. Since there is only one element on the right, `t` is empty.

> [@rocco\_sprmnt21](#):
>
> ```julia
> julia> k,t...,h = 1
> ERROR: ArgumentError: [...]
> 
> ```

In this case, the first element is assigned to `k`, the last to `h`, and the ones in between to `t`. However, as there is only one element on the right-hand side, the operation leads to an error. This assignment expects at least two values on the right.

```julia
julia> k, t..., h = 1,2
(1, 2)

julia> t
()

julia> k
1

julia> h
2

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 14, 2023, 2:19pm UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/11 "2023-08-14T14:19:33Z")

</div>

Okay. I understand. Although I’m still curious as to why` t...` is `Int[]` in one case, `Base.Iterators.Rest{Int64, Nothing}(1, nothing)` in another, and yet another `()`.

In the meantime I have found, by trial and error, a way to simulate slurping even in non-final position

```julia
julia> reduce4(f, t::Tuple)= _r(f,t...) 
reduce4 (generic function with 1 method)

julia> _r(f,x)=x
_r (generic function with 1 method)

julia> _r(f,(t...,h)...)=f(reduce4(f,t),h)
_r (generic function with 2 methods)

julia> reduce4(*, (1,2,3,4,5))
120

julia> reduce4(+, (1,2,3,4,5))
15

julia> reduce4(-, (1,2,3,4,5))
-13

julia> reduce4(/, (1,2,3,4,5))
0.008333333333333333

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 15, 2023, 12:45pm UTC](https://discourse.julialang.org/t/slurping-in-not-final-position/102784/12 "2023-08-15T12:45:10Z")

</div>

> [@Sukera](#):
>
> If you allow slurping in non-trailing position, the following two method definitions would always be ambiguous:
> 
> ```julia
> f(a, b, c..., d) = # something
> f(a, b..., c, d) = # something
> 
> ```
> 
> There are lots of possible combinations to get such an ambiguity, so I think that’s why it’s likely not supported.

!
