Yo @zep,
I realize returning nil
out of bounds is less "friendly"-seeming, but after reading another post in here, I realized it's way more useful.
For one thing, it should make this work:
plain_text = "my thing that is mine" label = "" for c in all(plain_text) do if c == ' ' then label ..= '_' else label ..= c end end print( label ) -- "my_thing_that_is_mine" |
(Right now it never stops because the iterator keeps seeing ""
instead of the nil
it needs to terminate.)
And for another, returning a nil is much more likely to alert a programmer that their code is probably malfunctioning than returning an empty string. Accessing out of bounds is usually erroneous and should therefore trigger errors.
I realize some apps are probably already abusing the fact that you get an empty string when referencing past the end of the string, but really that's a bad programming pattern to be teaching people anyway. It's lazy, you should know where the end of the string is and stop there instead of expecting the OS/API to be your nanny and stop you from walking off of a cliff.
Presumably this should apply to negative offsets as well, meaning negative offsets big enough to go back past the start of the string.
Side note: I realize that having all()
even work somewhat is just a happy side effect of having indexable strings, but hey, some of the best discoveries are unexpected.
(It'd be nice if ipairs()
worked too, but I think that's less reasonable to ask for, since I expect it'd be more work under the hood to add support.)
Actually, now that I think about it, it seems way more consistent/orthogonal too. When you reference a table sequence out of bounds you also get nil
, and the indexed strings are mostly behaving like sequences of single-char strings, e.g. indexing "hello"
acts like you're indexing a table like this: {'h','e','l','l','o'}
.
I like the consistent/orthogonal argument. lua uses nil really effectively and it makes sense here -- you're either returned the character you were looking for, or nothing.
a possible counterargument: string.sub
returns empty strings when you go out of bounds (https://www.lua.org/manual/5.4/manual.html#pdf-string.sub), but this maybe makes more sense because it can return strings of any length, and the empty string is a nice "nothing" value in that context. especially since one index can be in-bounds and the other might be out-of-bounds. in contrast, pico-8's mystr[i]
returns either 1 result or nothing, and I think nil makes more sense there as a "nothing" value
pico-8's ord
as well as lua's string.byte
both return nil on out-of-bounds indexes
luau has some nice minimal syntax additions to lua, but they don't seem to have added string indexing afaict, darn.
I dunno, it's a hard decision. I'm glad I'm not the one that has to make it! IMO consistency/orthogonality/language-predictability is the important thing, but it's not 100% clear which choice is the more consistent one here... still, I'm +1 overall
I feel kinda indifferent but if I did use this string indexing more I use falsey lookups all the time in my logic so I think it makes sense
There wasn't any good reason to go for "" except to match sub() behaviour, and I much prefer all of these arguments for nil. Especially the emergent all(str) pattern. (ha!)
Also I think it is easily worth a bit of backwards compatibility breakage -- I'll add this for 0.2.5d
Ah, I'm glad that it's mostly agreed upon and that, indeed, zep approves. Thanks everyone! :)
[Please log in to post a comment]