summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Dolan <mu@netsoc.tcd.ie>2012-12-29 16:50:58 +0000
committerStephen Dolan <mu@netsoc.tcd.ie>2012-12-29 16:52:26 +0000
commite0cda536f331b0fc53b493069dce70bb32de9a8b (patch)
tree1b0a0abe8e20417c71f1cd0ce2ac822294eee7cf
parentd5fdf70434a243e6f3bd6967dbc2d28c9144cb29 (diff)
Make null + foo return foo, rather than an error.
This also allows 'add' to be implemented in jq rather than C.
-rw-r--r--builtin.c26
-rw-r--r--docs/content/3.manual/manual.yml9
-rw-r--r--testdata12
3 files changed, 29 insertions, 18 deletions
diff --git a/builtin.c b/builtin.c
index f5917cbe..b0c6c34c 100644
--- a/builtin.c
+++ b/builtin.c
@@ -45,7 +45,13 @@ static jv type_error2(jv bad1, jv bad2, const char* msg) {
static jv f_plus(jv input, jv a, jv b) {
jv_free(input);
- if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
+ if (jv_get_kind(a) == JV_KIND_NULL) {
+ jv_free(a);
+ return b;
+ } else if (jv_get_kind(b) == JV_KIND_NULL) {
+ jv_free(b);
+ return a;
+ } else if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
return jv_number(jv_number_value(a) +
jv_number_value(b));
} else if (jv_get_kind(a) == JV_KIND_STRING && jv_get_kind(b) == JV_KIND_STRING) {
@@ -104,22 +110,6 @@ static jv f_divide(jv input, jv a, jv b) {
}
}
-static jv f_add(jv array) {
- if (jv_get_kind(array) != JV_KIND_ARRAY) {
- return type_error(array, "cannot have its elements added");
- } else if (jv_array_length(jv_copy(array)) == 0) {
- jv_free(array);
- return jv_null();
- } else {
- jv sum = jv_array_get(jv_copy(array), 0);
- for (int i = 1; i < jv_array_length(jv_copy(array)); i++) {
- sum = f_plus(jv_null(), sum, jv_array_get(jv_copy(array), i));
- }
- jv_free(array);
- return sum;
- }
-}
-
static jv f_equal(jv input, jv a, jv b) {
jv_free(input);
return jv_bool(jv_equal(a, b));
@@ -495,7 +485,6 @@ static struct cfunction function_list[] = {
{(cfunction_ptr)f_contains, "contains", 2},
{(cfunction_ptr)f_length, "length", 1},
{(cfunction_ptr)f_type, "type", 1},
- {(cfunction_ptr)f_add, "add", 1},
{(cfunction_ptr)f_sort, "sort", 1},
{(cfunction_ptr)f_sort_by_impl, "_sort_by_impl", 2},
{(cfunction_ptr)f_group_by_impl, "_group_by_impl", 2},
@@ -551,6 +540,7 @@ static const char* jq_builtins[] = {
"def unique: group_by(.) | map(.[0]);",
"def max_by(f): _max_by_impl(map([f]));",
"def min_by(f): _min_by_impl(map([f]));",
+ "def add: fold null as $sum (.[] | $sum + .);",
"def del(f): delpaths([path(f)]);",
"def _assign(paths; value): value as $v | fold . as $obj (path(paths) as $p | $obj | setpath($p; $v));",
"def _modify(paths; update): fold . as $obj (path(paths) as $p | $obj | setpath($p; getpath($p) | update));",
diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml
index 1de1a387..fba7e4a7 100644
--- a/docs/content/3.manual/manual.yml
+++ b/docs/content/3.manual/manual.yml
@@ -356,6 +356,9 @@ sections:
the key-value pairs from both objects into a single
combined object. If both objects contain a value for the
same key, the object on the right of the `+` wins.
+
+ `null` can be added to any value, and returns the other
+ value unchanged.
examples:
- program: '.a + 1'
@@ -364,6 +367,12 @@ sections:
- program: '.a + .b'
input: '{"a": [1,2], "b": [3,4]}'
output: ['[1,2,3,4]']
+ - program: '.a + null'
+ input: '{"a": 1}'
+ output: ['1']
+ - program: '.a + 1'
+ input: '{}'
+ output: ['1']
- program: '{a: 1} + {b: 2} + {c: 3} + {a: 42}'
input: 'null'
output: ['{"a": 42, "b": 2, "c": 3}']
diff --git a/testdata b/testdata
index 224f0651..4a998d8e 100644
--- a/testdata
+++ b/testdata
@@ -205,6 +205,18 @@ null
15
19.0
+.+null
+{"a":42}
+{"a":42}
+
+null+.
+null
+null
+
+.a+.b
+{"a":42}
+42
+
[1,2,3] + [.]
null
[1,2,3,null]