Skip to content

semantics of slice, now and future (plus near term bug fixes) #276

Description

@cartazio

cc @Shimuuar @lehins

My interpretation of slice, which may not be the universal one, but I believe reflects a common intent, is when I write

import Data.Vector as V
...
V.slice startIx runlength vec

i'm always like "what?! I wanted to write an inclusive coordinate interval"

V.slice startIx endIx vec

if the user's semantics is "i want/need this interval", throwing an error and promptly aborting is the only option i can see for the current type signature when that interval doesn't exist.

I'd even go further, and suspect that currently

  1. slice with the base index and runlength api we currently have is arecurrent gotcha

  2. any semantics that doesn't relate to the coordinate interval one might be problematical (though, there are some cut semantical tricks if we think about the coordinates in a modulus sorta sense, a la -1 et al in python sequences, but thats not the current topic)

Activity

  1. lehins commented on Jan 30, 2020

    @lehins
    Contributor

    If I understand you correctly, you mean that in the V.slice startIx endIx vec example if either of startIx endIx are incorrect (negative, out of bounds, etc.) we should throw an error, right?

    If that is what desired, it is fine by me, but keep in mind that it will prevent fusion! In other words, you can't throw an error if you don't ask for the vector length, because without forcing the vector you will not know it.

    I personally don't care which way we swing: error/no error, but what is very important I think is that we are consistent, regardless if slicing operator fuses or not! Having an error in ghci, but no error with -O1 is unacceptable.

    One alternative approach we could pursue is adding something like safeSlice, that fuses as well as fixes the arguments to prevent errors.

  2. cartazio commented on Jan 30, 2020

    @cartazio
    ContributorAuthor

    @lehins fusion isn't always good! Matrix Multiply :)

  3. lehins commented on Jan 30, 2020

    @lehins
    Contributor

    Of course, that is why I chose to have manual fusion in massiv, this way it is up to the user to fuse computation, if such fusion is possible.

    But that's not the case in vector, so it is up to us to decide. What you are suggesting would be very easy to achieve, all we gotta do is remove this rewrite rule:

    "slice/new [Vector]" forall i n p.
    slice i n (new p) = new (New.slice i n p)

  4. cartazio commented on Jan 30, 2020

    @cartazio
    ContributorAuthor

    I hate tradeoffs. grrrrr.

  5. cartazio commented on Jan 31, 2020

    @cartazio
    ContributorAuthor

    i'm going to be a bit slow in digesting this/ looking back through the related discussions.

  6. lehins commented on Jan 31, 2020

    @lehins
    Contributor

    I think it is worth linking to this comment that has a comparison to list and all previous issues with slice: #257 (comment)

    Also worth noting. That it is already possible to implement slice i n = take n . drop i which will have the non-error semantics. So, maybe it is not even worth worrying about it, except possibly improving the docs describing the options.

  7. added this to the 0.13 milestone on Jun 11, 2020
  8. Shimuuar commented on Apr 7, 2021

    @Shimuuar
    Contributor

    What I think about this. Changing slice from index & length to start index & end index is out of question. Too much code will break. Adding another variant of slice is of course possible. It's trivially implemented in terms of current slice.

    Another question is whether slice should be made total as was proposed in #257 (comment)

  9. lehins commented on May 21, 2022

    @lehins
    Contributor

    I think we all agree that changing semantics of slice is dangerous. Starting with 0.12.1 slice will throw an error on invalid offset and size. If we want to add a total version of slice we can do that in the future or users can just rely on take n . drop i whenever such semantics are desired.

    I think we can close this ticket. This is the consistent output we get for slice starting with 0.12.1 when looking at examples in this #257 (comment):

    ==================================================
    slice (Vector.Boxed current - fused): [1,2,3,4,5]
       normal: [2,3,4]
       negative ix: 
    invalid slice (-2,2,5)
       negative size: 
    invalid slice (2,-2,5)
       negative ix and size: 
    invalid slice (-2,-1,5)
       too large ix: 
    invalid slice (6,2,5)
       too large size: 
    invalid slice (2,6,5)
       too large ix size: 
    invalid slice (6,6,5)
    ==================================================
    slice (Vector.Primitive current - fused): [1,2,3,4,5]
       normal: [2,3,4]
       negative ix: 
    invalid slice (-2,2,5)
       negative size: 
    invalid slice (2,-2,5)
       negative ix and size: 
    invalid slice (-2,-1,5)
       too large ix: 
    invalid slice (6,2,5)
       too large size: 
    invalid slice (2,6,5)
       too large ix size: 
    invalid slice (6,6,5)
    ==================================================
    slice (Vector current - unfused): [1,2,3,4,5]
       normal: [2,3,4]
       negative ix: 
    invalid slice (-2,2,5)
       negative size: 
    invalid slice (2,-2,5)
       negative ix and size: 
    invalid slice (-2,-1,5)
       too large ix: 
    invalid slice (6,2,5)
       too large size: 
    invalid slice (2,6,5)
       too large ix size: 
    invalid slice (6,6,5)
    
  10. cartazio commented on May 22, 2022

    @cartazio
    ContributorAuthor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions