Fantom

Login | Register

List.getSafe #844

brian
1 Dec 2009

In working with URI paths, I keep wanting to have a method on List that will get a given index, but return a default value instead of throwing IndexErr when the index is out of range.

To be consistent with Map.get would could add a parameter to get. But that would change the requiring return type of List.get to be V? instead of V - something I don't think we want to do for type inference reasons.

So I'm considering adding a new method to List - just not sure what to call it:

V? getDef(Int index, V? def := null)

Anybody come up with a better name than getDef?

jodastephen
2 Dec 2009

I've used getQuiet() for similar ideas elsewhere.

liamstask
2 Dec 2009

maybe getOrDef() ?

andy
2 Dec 2009

I think getDef is fine.

ivan
2 Dec 2009

Maybe safeGet?

Edit: or tryGet?

brian
2 Dec 2009

Actually I like getSafe better than getDef

KevinKelley
2 Dec 2009

"getDef" sounds kind of like "get the default value", so getOrDef could be argued, but that's starting to get pedantic; getSafe seems concise and correct to me.

+1 getSafe

brian
2 Dec 2009

done - changeset

Andy was asking for a sliceSafe also. I'm not so sure about that one. What do others think?

helium
2 Dec 2009

Versions that return null instead of throwing an exception of many operations might be useful. If you have such a version you can easily build the one with a default yourself. If there is a sliceSafe that returns null instead of throwing IndexErr you can do:

foo := aList.sliceSafe(3..<7) ?: [1, 2, 3]

Similarly you now have two almost equal ways of using getSafe:

bar := aList.getSafe(index, default)

baz := aList.getSafe(index) ?: default

andy
2 Dec 2009

I like getSafe.

@helium - We started that convention before we had the elvis operator, and I agree its awkward to have both. Its not used in awhole lot of places, but we should prob take a look and do it consistently one way or the other. Maps has been one my #1 use case (tho we have the same issue with List.first/last off the top of my head):

x := map["foo"] ?: "bar"
x := map.get("foo", "bar")

qualidafial
2 Dec 2009

I vote to include the optional parameter for a fallback value--remember null is a valid value for list elements.

brian
2 Dec 2009

I vote to include the optional parameter for a fallback value--remember null is a valid value for list elements.

Are you talking about an optional param on get? Null is only an potential item if the list was declared with a nullable type. Consider this example:

V get(Int)      // orig sig
V? get(Int,V?)  // adding def param to get

list := ["a", "b"]
x := list[2]
x = null // compile time error right now

Right now the local variable x is typed as Str. But if we changed List.get to return V?, then that local would now be typed as Str?. That didn't seem like an acceptable change for this case, which is why I wanted provide this functionality in another method.

helium
2 Dec 2009

I vote to include the optional parameter for a fallback value--remember null is a valid value for list elements.

You're right. Using Option / Maybe which can nest let's you forget about those problems with null. So simply forget my last post.

qualidafial
2 Dec 2009

@brian: Just to clarify, what I'm saying is that we do need the second parameter and it cannot be replaced with elvis since the semantics are different:

Int?[] foo := [1,null,2]

bar := foo.getSafe(-2, 4)
echo(bar) // "null" since -2 is a valid index and null is the value at that index

This is semantically distinct from the elvis expression:

bar := foo.getSafe(-2) ?: 4
echo(bar) // "4" since ?: getSafe returns null, and elvis replaces null with the rhs

brian
2 Dec 2009

Just to clarify, what I'm saying is that we do need the second parameter and it cannot be replaced with elvis since the semantics are different:

Oh you are talking about getSafe - yeap that makes perfect sense

brian
12 Dec 2009

Promoted to ticket #844 and assigned to brian

brian
12 Dec 2009

Ticket resolved in 1.0.48

Login or Register to Reply

Back | All Topics