difference between range(2,5) and range(2;5)

Viewed 59

Template

range(2;5)

producing:

2
3
4

isn't that interesting, as this is explained by manual. However for imperative-style programmer is only matter of time, when he will mistakenly separate parameters by comma (actually I misread the manual, so this was my first attempt), and try template:

range(2, 5)

producing surprising:

0
1
0
1
2
3
4

What is that? How is it defined/explained?

2 Answers

The "comma" operator (as in 2,5) produces a stream. So 2,5 emits two integers, which is why [2,5] evaluates to an array of two integers.

In general, if E/1 has been defined using a form equivalent to def E($x): (i.e., as a "regular" function), then E(a,b) emits the stream E(a) followed by the stream E(b).

And indeed range/1 has been defined as a "regular function".

Non-regular functions

Here's an example of a non-regular function:

# Emit a single JSON object ("bow" is short for "bag of words")
def bow(stream): 
  reduce stream as $word ({}; .[($word|tostring)] += 1);

Notice that the function argument here (stream) is passed to reduce, which of course handles its first argument in a special way.

Since def E($x): is equivalent to def E(x): x as $x, defining bow as

def bow($s): reduce $s as $word ({}; .[($word|tostring)] += 1);

would have completely different (and useless) semantics.

peak's answer is correct, but I feel it glazes over the most basic part of the answer... the comma is simply not used to separate function args in jq, because it's "already taken" and jq has very little syntax overloading.

Because all functions implicitly take a stream (input as .) and evaluate to a stream, a very large number of functions are syntactically 0-adic (e.g. tostring), and the majority of the rest are syntactically 1-adic (e.g. split(str) which takes the separator as an argument, and the values to be split using that separator implicitly). For the rare functions like range and sub that take more than one explicit argument, the semicolon is used as a separator, not the comma.

And since jq isn't a statement-oriented language, that's almost the only use of the semicolon. The only other place it shows up is to mark the end of a function definition, which doesn't cause much confusion.

Related