# Question on tuple

**URL:** https://discourse.julialang.org/t/question-on-tuple/17210
**Category:** New to Julia
**Created:** [November 6, 2018, 10:38am UTC](https://discourse.julialang.org/t/question-on-tuple/17210 "2018-11-06T10:38:16Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)
#### Post date: [November 6, 2018, 10:38am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/1 "2018-11-06T10:38:17Z")

</div>

Hi,  
From an arbitrary sized tuple of int like

```julia
t=(3,4,5,7)

```

I dont know how to create a function returning

```julia
(prod(t),prod(t[2:end]),prod(t[3:end]),prod(t[4:end]))

```

that is  
` (420, 140, 35, 7)`  
Any hints ?

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [November 6, 2018, 10:57am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/2 "2018-11-06T10:57:04Z")

</div>

A generated function? But if your tuple is long, the efficiency gains may not materialize (benchmark). FWIW, since `*` is type stable, I would go with vectors even for short ones.

---

<div class="post-metadata">

### Author: ![tomaklutfu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomaklutfu/32/2411_2.png) [@tomaklutfu](https://discourse.julialang.org/u/tomaklutfu)
#### Post date: [November 6, 2018, 11:10am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/3 "2018-11-06T11:10:24Z")

</div>

This works but it would be better if `cumprod` would accept tuple as `prod`.

```julia
julia> (reverse(cumprod([reverse(t)...]))...,)
(420, 140, 35, 7)

```

---

<div class="post-metadata">

### Author: ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)
#### Post date: [November 6, 2018, 11:32am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/4 "2018-11-06T11:32:13Z")

</div>

> [@tomaklutfu](#):
>
> (reverse(cumprod([reverse(t)…]))…,)

Nice. Thank you very much

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [November 6, 2018, 11:37am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/5 "2018-11-06T11:37:00Z")

</div>

This only infers up to tuple-length of 3:

```julia
f(out, t::Tuple{}) = (out, ())
f(out, t) = f( (out..., prod(t)), Base.tail(t) )
f(t) = f((), t)[1]
f((3,4,5,7))
@code_warntype f((3,4,5)) # good
@code_warntype f((3,4,5,7)) # bad

```

Is there a way to avoid that?

---

<div class="post-metadata">

### Author: ![tomaklutfu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomaklutfu/32/2411_2.png) [@tomaklutfu](https://discourse.julialang.org/u/tomaklutfu)
#### Post date: [November 6, 2018, 11:38am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/6 "2018-11-06T11:38:15Z")

</div>

I have to warn you that this is not an efficient way. As @Tamas_Papp suggests it can be better to use `Vector` as `t`.

---

<div class="post-metadata">

### Author: ![fabiangans](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabiangans/32/2624_2.png) [@fabiangans](https://discourse.julialang.org/u/fabiangans)
#### Post date: [November 6, 2018, 11:52am UTC](https://discourse.julialang.org/t/question-on-tuple/17210/7 "2018-11-06T11:52:24Z")

</div>

No idea, I was trying this simultaneously and it does infer, although you have to reverse the tuple first…

```julia
function tuplecumprod(p,t::NTuple{N,Int}) where N
  m = t[1]*p
  (m,tuplecumprod(m,Base.tail(t))...)
end
tuplecumprod(p,t::Tuple{})=()
tuplecumprod(t)=tuplecumprod(1,t)

```

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [November 6, 2018, 12:57pm UTC](https://discourse.julialang.org/t/question-on-tuple/17210/8 "2018-11-06T12:57:23Z")

</div>

Ah, yes, that’s better and nicer:

```julia
g(t::NTuple{1}) = t
g(t) where M = (prod(t), g(Base.tail(t))...)

```

However, it does far too many multiplications, and for some reason still allocates.

Yours is much faster:

```julia
julia> t = Tuple(1:20);

julia> @btime g($t)
  1.032 μs (39 allocations: 3.73 KiB)
(2432902008176640000, 2432902008176640000, 1216451004088320000, 405483668029440000, 101370917007360000, 20274183401472000, 3379030566912000, 482718652416000, 60339831552000, 6704425728000, 670442572800, 60949324800, 5079110400, 390700800, 27907200, 1860480, 116280, 6840, 380, 20)

julia> @btime reverse(tuplecumprod(reverse($t)))
  14.642 ns (0 allocations: 0 bytes)
(2432902008176640000, 2432902008176640000, 1216451004088320000, 405483668029440000, 101370917007360000, 20274183401472000, 3379030566912000, 482718652416000, 60339831552000, 6704425728000, 670442572800, 60949324800, 5079110400, 390700800, 27907200, 1860480, 116280, 6840, 380, 20)

```

Looks like that is the best solution. (Maybe you could do a PR to add your method to `cumprod`?)

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [November 6, 2018, 1:46pm UTC](https://discourse.julialang.org/t/question-on-tuple/17210/10 "2018-11-06T13:46:53Z")

</div>

> [@Tamas\_Papp](#):
>
> A generated function?

You often don’t need a generated function for this kind of thing: you can just splat the tuple into arguments and then use recursion that inlines at compile-time. For example, the following seems to generate fast inlined code with no loops:

```julia
revcumprod() = ()
revcumprod(x) = (x,)
function revcumprod(x, rest...)
    prest = revcumprod(rest...)
    return (x*first(prest), prest...)
end

revcumprod((3,4,5,7)...)

```

Of course, you probably wouldn’t want to do this for very long tuples, but if you have very long tuples then you might be using the wrong data structure anyway.

---

<div class="post-metadata">

### Author: ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)
#### Post date: [November 6, 2018, 3:20pm UTC](https://discourse.julialang.org/t/question-on-tuple/17210/11 "2018-11-06T15:20:27Z")

</div>

Whow, the last two versions are really fast (and produce the same assembly code).  
Thank you very much for your help. I learn a lot from this.

In particular, inspired by the proposed solutions, I have obtain a strong acceleration for my computations by replacing sub-tuple computation **from shape[2:end] to Base.tail(shape)** (more than 10x faster).

---

<div class="post-metadata">

### Author: ![system](https://global.discourse-cdn.com/julialang/original/3X/1/2/12829a7ba92b924d4ce81099cbf99785bee9b405.png) [@system](https://discourse.julialang.org/u/system)
#### Post date: [November 18, 2018, 3:22pm UTC](https://discourse.julialang.org/t/question-on-tuple/17210/12 "2018-11-18T15:22:50Z")

</div>

This topic was automatically closed 12 days after the last reply. New replies are no longer allowed.
