Skip to content

2018 002 Additional slice operations

John Reppy edited this page Sep 2, 2018 · 3 revisions

Proposal 2018-002

Additional slice operations

Author: John Reppy
Last revised: September 2, 2018
Status: proposed
Discussion: issue #25


This proposal adds operations to the vector and array slice strutures.

Synopsis

signature MONO_VECTOR_SLICE =
  sig
    ...
    val triml : int -> slice -> slice
    val trimr : int -> slice -> slice
    val splitAt : slice * int -> slice * slice
    val getVec : slice * int -> (vector * slice) option
  end

signature MONO_ARRAY_SLICE =
  sig
    ...
    val triml : int -> slice -> slice
    val trimr : int -> slice -> slice
    val splitAt : slice * int -> slice * slice
    val getVec : slice * int -> (vector * slice) option
  end

signature VECTOR_SLICE =
  sig
    ...
    val triml : int -> 'a slice -> 'a slice
    val trimr : int -> 'a slice -> 'a slice
    val splitAt : 'a slice * int -> 'a slice * 'a slice
    val getVec : 'a slice * int -> ('a vector * 'a slice) option
  end

signature ARRAY_SLICE =
  sig
    ...
    val triml : int -> 'a slice -> 'a slice
    val trimr : int -> 'a slice -> 'a slice
    val splitAt : 'a slice * int -> 'a slice * 'a slice
    val getVec : 'a slice * int -> ('a vector * 'a slice) option
  end

Description

The semantics of these operations is independent of the underlying slice and vector types, so we give a generic description.

  • triml n slice

removes `n` elements from the left end of the slice `s`. If `n` is greater than the number of elements in the slice, then the empty slice is returned.
  • trimr n slice

removes `n` elements from the right end of the slice `s`. If `n` is greater than the number of elements in the slice, then the empty slice is returned.
  • splitAt (slice, i)

returns the pair of slices `(slice1, slice2)`, where `slice1` contains the first `i` elements of `slice1` and `slice2` contains the rest of the elements. If `i` is negative or greater than the number of elements in the slice, then `Subscript` is raised. The underlying vector (or array) of `slice`, `slice1`, and `slice2` will be the same.
  • getVec (slice, n)

returns `SOME(v, rest)`, where `v` is a vector of the first `n` elements of `slice` and `rest` is the slice containing the remaining elements, assuming that `slice` has at least `n` elements. Otherwise, `NONE` is returned.

Discussion

These additional operations make manipulation of slices more convenient. They can be directly defined in terms of existing operations as follows:

fun triml n s = if (n < length s)
      then subslice(s, n, NONE)
      else subslice(s, length s, NONE)

fun trimr n s = if (n < length s)
      then subslice(s, 0, SOME(length s - n))
      else subslice(s, 0, SOME 0)

fun splitAt (s, i) = (subslice(s, 0, SOME i), subslice(s, i, NONE))

fun getVec (s, n) = if (n < length s)
      then let
        val (s1, s2) = splitAt (s, n)
        in
          SOME(vector s1, s2)
        end
      else NONE

Impact

This propsal adds new variables to existing basis modules. Most code should be unaffected, but there are a few uncommon situations where existing code will break. These situations include

  • code that opens an extended structure in a context where the new identifiers are already bound.

  • code that includes an extended signature in a context where the new identifiers are already bound.

  • structures that match the old signature, but do not include an implementation of the new operations.

Rationale

Currently, the processing of slices in a chunk-wise fashion is difficult; addition of these operations would make it more convenient (and slightly more efficient). The first three of these operations already exist in the Substring structure and the getVec operation is a natural generalization of getElem, so these operations are a natural extension to the slice structures.


History

  • [2018-09-02] Original proposal.

Clone this wiki locally