1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Some builtins are unnecessarily special (fix #521)

This commit is contained in:
Nicolas Williams
2014-08-01 00:20:30 -05:00
parent a7878a8d1a
commit a2f99d43c3
2 changed files with 59 additions and 11 deletions

View File

@ -935,9 +935,9 @@ static const char* const jq_builtins[] = {
"def from_entries: map({(.key): .value}) | add | .//={};",
"def with_entries(f): to_entries | map(f) | from_entries;",
"def reverse: [.[length - 1 - range(0;length)]];",
"def indices(i): if type == \"array\" and (i|type) == \"array\" then .[i] elif type == \"array\" then .[[i]] else .[i] end;",
"def index(i): if type == \"array\" and (i|type) == \"array\" then .[i] elif type == \"array\" then .[[i]] else .[i] end | .[0];",
"def rindex(i): if type == \"array\" and (i|type) == \"array\" then .[i] elif type == \"array\" then .[[i]] else .[i] end | .[-1:][0];",
"def indices(i): i as $i | if type == \"array\" and ($i|type) == \"array\" then .[$i] elif type == \"array\" then .[[$i]] else .[$i] end;",
"def index(i): i as $i | if type == \"array\" and ($i|type) == \"array\" then .[$i] elif type == \"array\" then .[[$i]] else .[$i] end | .[0];",
"def rindex(i): i as $i | if type == \"array\" and ($i|type) == \"array\" then .[$i] elif type == \"array\" then .[[$i]] else .[$i] end | .[-1:][0];",
"def paths: path(recurse(if (type|. == \"array\" or . == \"object\") then .[] else empty end))|select(length > 0);",
"def paths(node_filter): . as $dot|paths|select(. as $p|$dot|getpath($p)|node_filter);",
"def any: reduce .[] as $i (false; . or $i);",
@ -966,10 +966,10 @@ static const char* const jq_builtins[] = {
"def values: arrays, objects, booleans, numbers, strings;",
"def scalars: select(. == null or . == true or . == false or type == \"number\" or type == \"string\");",
"def leaf_paths: paths(scalars);",
"def join(x): reduce .[] as $i (\"\"; . + (if . == \"\" then $i else x + $i end));",
"def join(x): x as $x | reduce .[] as $i (\"\"; . + (if . == \"\" then $i else $x + $i end));",
"def flatten: reduce .[] as $i ([]; if $i | type == \"array\" then . + ($i | flatten) else . + [$i] end);",
"def flatten(x): reduce .[] as $i ([]; if $i | type == \"array\" and x > 0 then . + ($i | flatten(x-1)) else . + [$i] end);",
"def range(x): range(0;x);",
"def flatten(x): x as $x | reduce .[] as $i ([]; if $i | type == \"array\" and $x > 0 then . + ($i | flatten($x-1)) else . + [$i] end);",
"def range(x): x as $x | range(0;$x);",
// regular expressions:
"def match(re; mode): _match_impl(re; mode; false)|.[];",
"def match(val): (val|type) as $vt | if $vt == \"string\" then match(val; null)"
@ -989,18 +989,21 @@ static const char* const jq_builtins[] = {
" else error( $vt + \" not a string or array\") end;",
// range/3, with a `by` expression argument
"def range(init; upto; by): "
" def _range: "
" if (by > 0 and . < upto) or (by < 0 and . > upto) then ., ((.+by)|_range) else . end; "
" if by == 0 then init else init|_range end | select((by > 0 and . < upto) or (by < 0 and . > upto));",
" init as $init |"
" upto as $upto |"
" by as $by |"
" def _range: "
" if ($by > 0 and . < $upto) or ($by < 0 and . > $upto) then ., ((.+$by)|_range) else . end; "
" if $by == 0 then $init else $init|_range end | select(($by > 0 and . < $upto) or ($by < 0 and . > $upto));",
// generic iterator/generator
"def while(cond; update): "
" def _while: "
" if cond then ., (update | _while) else empty end; "
" try _while catch if .==\"break\" then empty else . end;",
"def limit(n; exp): if n < 0 then exp else foreach exp as $item ([n, null]; if .[0] < 1 then break else [.[0] -1, $item] end; .[1]) end;",
"def limit(n; exp): n as $n | if $n < 0 then exp else foreach exp as $item ([$n, null]; if .[0] < 1 then break else [.[0] -1, $item] end; .[1]) end;",
"def first(g): foreach g as $item ([false, null]; if .[0]==true then break else [true, $item] end; .[1]);",
"def last(g): reduce g as $item (null; $item);",
"def nth(n; g): if n < 0 then error(\"nth doesn't support negative indices\") else last(limit(n + 1; g)) end;",
"def nth(n; g): n as $n | if $n < 0 then error(\"nth doesn't support negative indices\") else last(limit($n + 1; g)) end;",
"def first: .[0];",
"def last: .[-1];",
"def nth(n): .[n];",

View File

@ -246,6 +246,51 @@ null
10
[0,9,0,5,"nth doesn't support negative indices"]
#
# Check that various builtins evalute all arguments where appropriate,
# doing cartesian products where appropriate.
#
# Check that limit does work for each value produced by n!
[limit(5,7; range(9))]
null
[0,1,2,3,4,0,1,2,3,4,5,6]
# Same check for nth
[nth(5,7; range(9;0;-1))]
null
[4,2]
# Same check for range/3
[range(0,1,2;4,3,2;2,3)]
null
[0,2,0,3,0,2,0,0,0,1,3,1,1,1,1,1,2,2,2,2]
# Same check for range/1
[range(3,5)]
null
[0,1,2,0,1,2,3,4]
# Same check for index/1, rindex/1, indices/1
[(index(",","|"), rindex(",","|")), indices(",","|")]
"a,b|c,d,e||f,g,h,|,|,i,j"
[1,3,22,19,[1,5,7,12,14,16,18,20,22],[3,9,10,17,19]]
# Same check for join/1
join(",","/")
["a","b","c","d"]
"a,b,c,d"
"a/b/c/d"
# Same check for flatten/1
flatten(-1,3,2,1)
[0, [1], [[2]], [[[3]]]]
[0,[1],[[2]],[[[3]]]]
[0,1,2,3]
[0,1,2,[3]]
[0,1,[2],[[3]]]
#
# Slices
#