range(0; infinite)
pkoppstein opened this issue · comments
Currently this jq idiom won't work in jaq because range
requires its args to be integers. Although for practical purposes range(0; infinite|floor)
could typically be used, it's not the same thing because infinite|floor
is finite (which seems a bit problematic in itself, by the way), so it would be nice if jaq could make an exception for infinite
when presented as an argument to range
.
Of course 0|repeat(.+1)
could be used but that, it seems to me, lacks the convenience, familiarity and clarity of range
.
I am feeling against this. I tried to put my reasoning into the README:
The filter
range(m; n)
constructs a sequence of numbersm, m+1, ...
,
where any number must be smaller thann
.
In jq,m
andn
can be floating-point numbers, whereas
in jaq,m
andn
must be integers.
This is to avoid potential numerical stability problems.
That means that unlike in jq, you cannot use
range(m; infinite)
to generate the infinite sequencem, m+1, ...
.
However, you can usem | recurse(.+1)
to achieve the same in jaq.
The point is potential numerical stability problems. Accepting floating-point numbers as arguments to range
is of course convenient for users, because they can just write range(0; infinite)
. In jq, this is not a problem, because every number is floating-point. But in jaq's model, this does not make sense, because what numbers will this yield? Floating-point or integer numbers? Given that infinite
is clearly floating-point, this would make the whole sequence floating-point, which would be rather unexpected. Of course, we could just introduce a little exception here, as you suggest. But I think that each exception, as convenient as it might look at first, bears potential for a later WTF moment. jq has many WTF moments, and given that I want to avoid these as much as possible with jq, I opt for strictness over convenience here. I hope you understand. :)
@01mf02 wrote:
I am feeling against this.
I hope, therefore, that once I've addressed all your concerns as I think I can do, you will reopen this issue.
The main point is that you have read much too much into this ER. For range/2, the request is only for range(X; infinite), where X is an integer, to be allowed. Thus your concerns about numerical stability in particular all vanish.
I'd also point out that there is nothing in JSON to indicate whether infinite
should be regarded as a "float" or an "integer" or something else. In jq, we have some predicates like isinfinite
, but there is nothing to require that infinite
be regarded as a float. (Agreed, infinite
is pretty-printed as a float, but that's no more indicative than that nan
pretty-prints as null
.)
Agreed, surprises are to be avoided where possible, but the main surprise here is that range(0; infinite) is disallowed. As mentioned, both jq and gojq allow it (and gojq DOES make a sharp distinction between integers and floats).
(The secondary surprise of course is that infinite|floor
evaluates to an integer, but I am not sure what would work best for jaq - should infinite|floor
evaluate to nan
or raise an error, or ...?)
Hope you enjoyed your vacation!
@pkoppstein, I am happy to tell you that by cb743ef, the range
filter is implemented by definition, which will make range(n; infinite)
work as you described.
@01mf02 - Thanks for letting me know! Needless to say I'm also very glad that you didn't let the trees prevent you from seeing the forest!!!