elm-community / array-extra

convenience functions for working with Array

Home Page:http://package.elm-lang.org/packages/elm-community/array-extra/latest

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get/set that take negative arguments?

sindikat opened this issue · comments

Array.get and Array.set return Nothing if given negative argument. (See also core's Native/Array.js).

There might be reasons to leave this behavior as is. For example, current get semantics allow you to countdown and once you hit Nothing, you know that you fully traversed the array right to left, IOW, you did hit the left edge of the array. Do people use that kind of behavior?

I, coming from Python, think, however, that Array.get and Array.set supporting negative arguments make them much more versatile and convenient to use. Negative arguments mean you can get or set from the end of the array. Again, if lists's length is 5, you can't have below -5 as an argument, as this also constitutes index-out-of-bound.

I use my variant of Array.get all the time now, and this is how I defined it in Elm:

get2 : Int -> Array a -> Maybe a
get2 n a =
  let
    len = Array.length a
  in
    if n < 0 && abs n <= len
    then Array.get (len + n) a
    else Array.get n a

I however think it should be defined on the level of Native/Array.js in the core some day. I also plan to write set and update versions of this too.

My question is, do you want that function in Array.Extra? And how should we call it? I think it's safe to call it just get, because there won't be any namespace collision (Array.get against Array.Extra.get), and people will notice from the namespace, that these functions might have slightly different behavior. Also there's chance this function would be added into the core.

Do you agree? If not, what name could we give to a variant of Array.get that accepts negative arguments?

Eish, well this calls for some discussion I suppose. I'm not sure how to get everyone involved, perhaps you could point people on mailinglist to this issue?

One thing I will mention is that I always import extras like this:

import Array
import Array.Extra as Array

...so that I'm pretty much assuming that things in Array.Extra might one day make it into Array and I'm not thinking about it too much. For that reason I'm not terribly fond of clashing names.

I also sometimes tell people that if they'd like to experiment with a radical / philosophical departure from the core API it might be worth just doing an entirely new package. E.g. elm-array-wrap or elm-array-circular (Array.Wrap or Array.Circular respectively). That way you could explore that idea for a whole range of different functions and -extra stuff will be somewhat more likely to be promoted to core.

I'm not sure whether or not that's the best thing to do in this case, it sort of depends on your goals - whether it's more experimental or you feel a practical need for wrapping. I recommended something like this before for https://github.com/circuithub/elm-list-extra/pull/4 which I think was the right call in that particular case.

I brought up negative arguments for get/set in elm-lang/core/issues.

Due to name collision I want to place get/set that accept negative arguments to Array.Experimental, to start using it internally. However this change is very attractive and might end up in core (Array.slice already supports negative arguments).

Ah, thanks for pointing out Array.slice and opening an issue against core. Since there's some acceptance already I'd be happy to accept this with get/set renamed.

Umm...

  • getAt / setAt ?
  • getSafe / setSafe ?
commented

I believe element & elementReplace in elm-linear-direction follow a better approach, as they make the direction explicit.
element ( Down, 0 ) for example would return the last argument.

Let's include a link and explanation in the next version! Anyone objections?