I agree that it should work like #sub for substrings, except that it does not count characters, but fields (or pieces), So to return to all fields (including with their delimiters) after the limit in the last selected part, just pass the limit as -1 (which is already used with a single position parameter).
Otherwise the default limit should be the position+1 (which ensures that there will always be one field returned and no delimiter in it).
If we specify position+2 as the limit, there will be at most 2 fields (and a single delimiter between them): any one of the two fields could be empty); there will be one delimiter return unless the second field is missing (i.e. there's no delimiter at all in the source text after the given starting position, just one field not followed by any delimiter, or none because the source text does not contain at least position delimiters).
Using #explode for getting more than 1 field (by using the limit parameter) is unreliable and gives unpredictable results where we don't know how many fields are actually present in the source text (i.e. if the source text contains more fields than expected than just fields between position and position+limit).
Say you just want to extract the 2 first fields of the text by using "position=0" and "limit=2", for now, you may get:
- 2 fields with a single delimiter (only if the source text contains exactly two fields with a single delimiter between them), or
- just one (the text is too short and does not contain any delimiter, the result may even be an empty string if the source text is empty), or
- an arbitrary number of fields (with as many delimiters than the source text);
i.e. the returned text will be always the same as the input!
You don't have that problem when you just want 1 field (for that you just pass position and no limit at all).
The default limit should then be the same as if we passed limit=position+1; but for now this is not the case: with an explicit limit=position+1, we always get all fields present starting at the given position up to the end of the source text (i.e. what we would expect with limit=-1).
For now the only workaround to detect that you got more fields than expected, is to make a test by making a 2nd call to #explode with the same source text, but passing "position=limit", but NO "limit=" parameter: if what it returns is effectively empty, this means that the first call returned at most (limit-position) fields, separated by at most (limit-position) occurences of the delimiter (but there may be fewer fields and one less delimiters between them, with each field possibly empty between these delimiters).
- Option for counting the effectively detected fields in the specified range
Now if you expect to find exactly the given number of fields and delimiters in the output, you need another way to count delimiters in the result, but "#explode" does not propose it (there could be an optional parameter to "#explode" saying what to return: a substring of the source text by default, or the count of fields detected between the two specified positions (counting fields) position and position+limit:
E.g. with "{{#explode:text|delimiter|position|limit|R}}
Such use of the "R" parameter (for raw) could be an alternative to not just detect the starting position (counted in characters in the whole text) of the first occurence of a substring, but actually to detect and count the number of occurences of that substring (specified as a delimiter for "#explode:") of the source text (in the range specified by position and limit and counted in terms of occurences of the delimiter), e.g. "{{#explode:text|delimiter|R}}
would count how many delimiters are present in the whole text and return it as a decimal integer. (The "R" option mimics what happens in other parser functions, e.g. to get the number of members in a specified category and return the value as a raw unformatted integer number).
- Other possible extensions (may not be necessary in a first implementation)
Optionally, using "N" instead of "R" could format that number in user's locale (you could as well specify a locale code like "en" or "fr", or a code like the empty string "" to use the default language of the local wiki, or "." for the locale of the local page if it has been set in its metadata) instead of returning the raw unformatted number (suitable for use in "#expr:" or "#ifexpr: "), but this is not really necessary as there's a separate parser function for that, and we don't need to repeat other parameters given to "#explode:".
Another possibly useful (but optional) parameter would be a parameter specifying by what we want to replace the delimiters in the results, e.g. |by=, 
to replace delimiters by a comma and space. But this could still be done as well by a separate call to another external parser function to make these replacements; however it requires passing again the separator to this replacement call, and it may just be performed more efficiently and with little efforts within "#explode:" itself, because it actually explodes the source text into an array of fields, but then really reassembles them into a single string using (by default) the same delimiter as the one used to explode the text. This optional "by=" parameter would have no effect if you use the extra "N" or "R" parameters as they actually never return any substrings from the source text, but just a single number.
We could use |by=
with an empty value to remove all delimiters between the extracted field in the result, however the default value when |by=
is not explicitly passed must be the same as the specified delimiter (meaning that delimiters won't be replaced or deleted in the reassembled output), to preserve the compatiblity.
- Currently unspecified behaviours
For the position, if it is negative it is clearly described as meaning positions counted negatively, backward from the end of the string at position -1, so if you want to get at most the last two fields of a given text, you can use "{{#explode:text|delimiter|-3}}
. But when the source text has less fields than expected (two fields in this example), the behavior is not clearly specified: does it return as many fields than those actually present in the text starting at the given position (because you could not count backward past the start of the source text but you return all those that were counted inclusively), or an empty string (not enough delimiters found), or two fields anyway (by appending an extra delimiter in the result)?
Another thing that is still not specified is what happens when this time the given limit is negative. In my opinion, this could return the empty string, but the backward counting rule used for the starting position could be applied too (meaning that it indicates fields counted in the opposite direction than the direction specified by the position). If the limit is zero, the result should always be an empty string.
Finally, it is not well described what happens when the position or limit is specified but as an empty parameter. In my opinon they should default respectively. to 0 (counting from the start of the text) and -1 (as many as needed to scan all fields from the starting position, so here it sets the limit the end of the text because the starting position 0 at start of text is scanned in the forward direction), as if these two parameters were not specified and used the same defaults.
Now, what is is also not clearly specified is what happens when this time the delimiter is empty:
- is it invalid and returns an error text, or does it return an empty string (or maybe "0" with the "N" or "R" options), or
- does it mean that it delimits and count individual characters (as if each one was suffixed by an empty delimiter), so that we can explode a text character by character and return them in a list separated by the string specified in "by=" (and terminated if the range specified by position and "limit"" scans past the end of text; if the scan is performed backward because the position is negative, all would occur as if each field was prefixed by an empty delimiter) —meaning that if the "by=" parameter is omitted or empty, the result would be the same as with "#len:" with the "N" or "R" options, or the same as the input text in absence of a range specidied by position and limit, or the same as "#sub:" otherwise?