# \[ANN\] OneTwoMany.jl

**URL:** <https://discourse.julialang.org/t/ann-onetwomany-jl/101623>\
**Category:** Package Announcements\
**Created:** [July 14, 2023, 1:13pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623 "2023-07-14T13:13:59Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 1:13pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/1 "2023-07-14T13:13:59Z")

</div>

I’ve put together a tiny package [OneTwoMany.jl](https://github.com/JuliaArrays/OneTwoMany.jl) - that provides a function `getsecond`, as well as functions `first_and_rest` and `first_second_rest`.

Julia provides the functions `first` and `last` , but not `second` (except for `Dates.second` , which is about seconds in time). `last` can be used to access the second element of a `Tuple` with two elements or a `Pair` , but `getsecond` is clearer semantically. With tuples, it is also safer in cases where the upstream code that generates the tuple might change and generate longer tuples in the future.

The package is [currently being registered](https://github.com/JuliaRegistries/General/pull/87489). I couldn’t find a `getsecond` in any central lightweight package, but if this duplicates something similar, please let me know before registration is complete. 🙂

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [July 14, 2023, 1:58pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/2 "2023-07-14T13:58:03Z")

</div>

Cool package! Any reason not to have `getthird`, `getforth`, etc?

---

<div class="post-metadata">

**Author:** ![tlienart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlienart/32/7640_2.png) [@tlienart](https://discourse.julialang.org/u/tlienart)\
**Post date:** [July 14, 2023, 2:30pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/3 "2023-07-14T14:30:00Z")

</div>

I was wondering how you’d handle strings and your

```julia
getsecond(str::AbstractString) = str[begin+1]

```

seems potentially a bit dangerous:

```julia
julia> s = "∀∃α"; getsecond(s)
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'∀', [4]=>'∃'
Stacktrace:
 [1] string_index_err(s::String, i::Int64)
   @ Base ./strings/string.jl:12
 [2] getindex_continued(s::String, i::Int64, u::UInt32)
   @ Base ./strings/string.jl:248
 [3] getindex
   @ ./strings/string.jl:241 [inlined]
 [4] getsecond(str::String)
   @ Main ./REPL[9]:1
 [5] top-level scope
   @ REPL[10]:1

```

I’d suggest using `str[nextind(str, 1)]`:

```julia
julia> getsecond(str::AbstractString) = str[nextind(str, 1)];

julia> getsecond(s)
'∃': Unicode U+2203 (category Sm: Symbol, math)

```

(as would probably be expected I imagine)

---

<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:** [July 14, 2023, 2:32pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/4 "2023-07-14T14:32:20Z")

</div>

> [@mrufsvold](#):
>
> Cool package! Any reason not to have `getthird`, `getforth`, etc?

You can use

```julia
nth(itr, n) = first(Iterators.drop(itr, n-1))

```

to get the `n`-th element of an iterator.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 2:33pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/5 "2023-07-14T14:33:35Z")

</div>

> [@mrufsvold](#):
>
> Cool package! Any reason not to have `getthird`, `getforth`, etc?

I’d say the first element of a collection is the one that is requested directly most often, if only a single element is accessed. Then the second one. After that, in my personal experience, direct access to only one element is less common. One doesn’t see `x[3]` or `x[4]` that much in code, compared to `x[1]` and `x[2]`.

---

<div class="post-metadata">

**Author:** ![tlienart](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tlienart/32/7640_2.png) [@tlienart](https://discourse.julialang.org/u/tlienart)\
**Post date:** [July 14, 2023, 2:35pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/6 "2023-07-14T14:35:23Z")

</div>

I always forget about `Iterators`… if you use that solution you can remove the special casing on `AbstractString`:

```julia
julia> s = "∀∃α"
"∀∃α"

julia> nth(itr, n) = first(Iterators.drop(itr, n-1))
nth (generic function with 1 method)

julia> nth(s, 2)
'∃': Unicode U+2203 (category Sm: Symbol, math)

```

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 2:36pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/7 "2023-07-14T14:36:55Z")

</div>

> [@tlienart](#):
>
> I was wondering how you’d handle strings and your

You make a good point there @tlienart.

~~I’m a bit torn about this. On the one hand, users should expect `getsecond(x)` to do the same as `x[2]` (for collections with one-based indexing). On the other hand, retrieving whole unicode characters from strings is certainly more useful.~~

I agree, we should return the second element from a viewpoint of iteration for strings, not `getindex(s,2)`.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [July 14, 2023, 2:46pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/8 "2023-07-14T14:46:21Z")

</div>

> [@stevengj](#):
>
> You can use
> 
> ```julia
> nth(itr, n) = first(Iterators.drop(itr, n-1))
> 
> ```
> 
> to get the `n`-th element of an iterator.

Totally, but all of these index accessing functions are just niceties. You could define your own `first` after all!

> [@oschulz](#):
>
> One doesn’t see `x[3]` or `x[4]` that much in code, compared to `x[1]` and `x[2]`.

I agree it’s less than common, but given that Haskell has `first` through `ninth` before switching to `nth`, at least some people find it useful.

Anyway, I’m not here to debate the line where having a name for an index access function becomes useful. I was just curious 😄

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 3:45pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/9 "2023-07-14T15:45:29Z")

</div>

If people have use cases for `getthird`, `getfourth` and so on, the package is certainly open for expansion (as long as it stays very lightweight).

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [July 14, 2023, 5:39pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/10 "2023-07-14T17:39:54Z")

</div>

> [@oschulz](#):
>
> first\_and\_rest

Maybe, also worth to extend Base.tail() to more types? Then I guess this function won’t be necessary (:

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [July 14, 2023, 6:33pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/11 "2023-07-14T18:33:30Z")

</div>

```julia
help?> Iterators.peel
  peel(iter)

  Returns the first element and an iterator over the remaining elements.

  If the iterator is empty return nothing (like iterate).

  │ Julia 1.7
  │
  │ Prior versions throw a BoundsError if the iterator is empty.

  See also: Iterators.drop, Iterators.take.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> (a, rest) = Iterators.peel("abc");
  
  julia> a
  'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
  
  julia> collect(rest)
  2-element Vector{Char}:
   'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
   'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

```

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 8:43pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/12 "2023-07-14T20:43:16Z")

</div>

> [@jar1](#):
>
> ```julia
> help?> Iterators.peel
> peel(iter)
> 
> ```

Thanks @jar1 - good point, I should use that to implement `first_and_rest` and possiblity also `first_second_rest` for iterators.

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 14, 2023, 8:44pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/13 "2023-07-14T20:44:10Z")

</div>

> [@aplavin](#):
>
> Base.tail() to more types?

Ah, the times I’ve wished for a generic, offical and exported `tail` in Julia. 🙂

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [July 14, 2023, 11:25pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/14 "2023-07-14T23:25:55Z")

</div>

> [@oschulz](#):
>
> Ah, the times I’ve wished for a generic, offical and exported `tail` in Julia. 🙂

`Base.tail` is in the julia docs, doesn’t it mean the function is as official as it gets?  
As for “generic”, maybe all it takes is someone making a PR to Julia extending tail to more types?

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 15, 2023, 4:22pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/15 "2023-07-15T16:22:26Z")

</div>

> [@aplavin](#):
>
> `Base.tail` is in the julia docs

Oh, you’re right, it is documented now (didn’t use to be in the “olden” days).

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 17, 2023, 3:01pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/16 "2023-07-17T15:01:14Z")

</div>

I’ve updated OneTwoMany with the improved string handling suggested by @tlienart (thanks!).

---

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 17, 2023, 3:02pm UTC](https://discourse.julialang.org/t/ann-onetwomany-jl/101623/17 "2023-07-17T15:02:25Z")

</div>

> [@oschulz](#):
>
> Thanks @jar1 - good point, I should use that to implement `first_and_rest` and possiblity also `first_second_rest` for iterators.

I’ll keep the current implementation for now - it throws an exception for empty iterators, while `peel` returns `nothing`.
