Behavior of first and last filter operators when zero items requested

To make a long story short I was using a variable to get the last n items of a list and noticed something that feels wrong to me. The calculation that sets the variable will often set the variable to zero. For other values of n last<n> will return the last n items in the list but if n=0 the entire list is returned when it would make more sense to return nothing (which is what I would like it to do). Some trivial test wiki text-

\define theNum() 3

\define zero() 0

\define theList()  A B C D E F G H I J

Last:

2: {{{ [enlist<theList>last[2]] }}}

nothing: {{{ [enlist<theList>last[]] }}}

<<theNum>>: {{{ [enlist<theList>last<theNum>] }}}

<<zero>>: {{{ [enlist<theList>last<zero>] }}}

First:

2: {{{ [enlist<theList>first[2]] }}}

nothing: {{{ [enlist<theList>first[]] }}}

<<theNum>>: {{{ [enlist<theList>first<theNum>] }}}

<<zero>>: {{{ [enlist<theList>first<zero>] }}}

gives these results:

Last:

2: IJ

nothing: J

3: HIJ

0: ABCDEFGHIJ

First:

2: AB

nothing: A

3: ABC

0:

So first[] behaves in the way I’d expect, you calculate that you need a certain number of items from the beginning of the list and if that number turns out to be zero, you get no items, but last[] gives you the whole list under the same circumstances.

I’ve “solved” my problem by coding a special case using a compare operator but because of the calculation and a bunch of other manipulation of the list, it’s a bit of a mess, so I don’t need a solution but I am wondering if there is something I’m missing.

Is there an easy way to get the last n items from a list when n can be zero?

Does the behavior of last[0], especially when compared to first[0] feel like a problem?

I think this is a bug in the implementation. There might be backwards compatibility constraints to fixing it, though it seems unlikely anyone would be relying on this behaviour. If you have a GitHub account, please report a bug: Issues · Jermolene/TiddlyWiki5 · GitHub

Thanks for confirming my suspicions. As an end user I try my best not to think that I have found a bug because 99% of the time, that isn’t true. Also thanks for the link. I programmed in the dark ages before Github and had no idea how to report a bug.

I may have stumbled onto the source of the issue that I wanted to mention here (though I did weave it into the bug report). In the documentation it states that limit is a synonym for first and !limit is a synonym for last. I think that might have led to problems when implemented.

First neither pair are true synonyms since they have different default values. According to the documentation first[] and last[] default to first[1] and last[1] respectively but limit[] defaults to limit[0], same for !limit obviously. So first[] /= limit[] and last[] /= !limit[], so I don’t think they should be considered synonyms.

However, if limit[] returns nothing (and that is what it does) it might be logical for !limit[] to return everything, which, when I tested, is exactly what it does. So !limit[] makes some sense as the opposite of limit[] but then really should not be thought of as a synonym for last[0] which ought to return nothing. I don’t know the history but I suspect that somewhere along the way when !limit was defined as the opposite of limit it introduced a bug into last with which it probably shares some code since it is supposed to be a synonym.

So right now-

first[N] gives the first N items for all N=0 or greater
first[] is the same as first[1]

last[N] gives the last N items for all N>0 and the entire list for N=0
last[] is the same as last[1]

limit[N] gives the first N items for all N=0 or greater and is stated to be a synonym for first but isn’t because limit[] is the same as limit[0] and returns no items

!limit[N] gives the last N items for all N>0 and is stated to be a synonym for last but isn’t because !limit[] returns all items while last[] returns the last item

!limit[0] and last[0] both return all items

!limit implies it being something of the opposite of limit and limit[0] returns nothing, so it does seem somewhat reasonable that !limit[0] returns everything.

The behavior and documentation I would expect are-

first[N] gives the first N items for all N=0 or greater
first[] is the same as first[1]

last[N] gives the last N items for all N=0 or greater
last[] is the same as last[1]

limit[N] gives the first N items for all N=0 or greater and is not stated to be a synonym for first because limit[] is the same as limit[0] and returns no items while first is the same as first[1] and returns 1 item

!limit[N] gives the last N items for all N>0 and is not stated to be a synonym for last because !limit[] does not return the last item while last[] returns the last item

Whether it is better for !limit[0] to be the opposite of limit[0] and therefore return everything or make it return nothing in keeping with the thought that 0 should mean nothing, not everything, I don’t have a strong feeling for. If return everything is the answer it would be another reason that !limit and last are not synonyms if last[0] is fixed to return nothing

I hope I’ve made sense!