diff --git a/builtin.c b/builtin.c index f291a95e..1eee5bb5 100644 --- a/builtin.c +++ b/builtin.c @@ -90,6 +90,25 @@ static void f_divide(jv input[], jv output[]) { } } +static void f_add(jv input[], jv output[]) { + jv array = input[0]; + if (jv_get_kind(array) != JV_KIND_ARRAY) { + output[0] = jv_invalid_with_msg(jv_string_fmt("Cannot add elements of an %s", + jv_kind_name(jv_get_kind(array)))); + } else if (jv_array_length(jv_copy(array)) == 0) { + output[0] = jv_null(); + } else { + jv sum = jv_array_get(jv_copy(array), 0); + for (int i = 1; i < jv_array_length(jv_copy(array)); i++) { + jv x = jv_array_get(jv_copy(array), i); + jv add_args[] = {jv_null(), x, sum}; + f_plus(add_args, &sum); + } + output[0] = sum; + } + jv_free(array); +} + static void f_equal(jv input[], jv output[]) { jv_free(input[0]); output[0] = jv_bool(jv_equal(input[2], input[1])); @@ -185,6 +204,7 @@ static struct cfunction function_list[] = { {f_equal, "_equal", CALL_BUILTIN_3_1}, {f_length, "length", CALL_BUILTIN_1_1}, {f_type, "type", CALL_BUILTIN_1_1}, + {f_add, "add", CALL_BUILTIN_1_1}, }; static struct symbol_table cbuiltins = {function_list, sizeof(function_list)/sizeof(function_list[0])}; diff --git a/docs/content/3.manual/manual.yml b/docs/content/3.manual/manual.yml index 417432b4..10998dce 100644 --- a/docs/content/3.manual/manual.yml +++ b/docs/content/3.manual/manual.yml @@ -321,6 +321,43 @@ sections: input: '[[1,2], "string", {"a":2}, null]' output: [2, 6, 1, 0] + - title: `map(x)` + body: | + + For any filter `x`, `map(x)` will run that filter for each + element of the input array, and produce the outputs a new + array. `map(.+1)` will increment each element of an array of numbers. + + `map(x)` is equivalent to `[.[] | x]`. In fact, this is how + it's defined. + + examples: + - program: 'map(.+1)' + input: '[1,2,3]' + output: ['[2,3,4]'] + + - title: `add` + body: | + + The filter `add` takes as input an array, and produces as + output the elements of the array added together. This might + mean summed, concatenated or merged depending on the types + of the elements of the input array - the rules are the same + as those for the `+` operator (described above). + + If the input is an empty array, `add` returns `null`. + + examples: + - program: add + input: '["a","b","c"]' + output: ["abc"] + - program: add + input: '[1, 2, 3]' + output: [6] + - program: add + input: '[]' + output: ["null"] + - title: `tonumber` body: | diff --git a/testdata b/testdata index 7357ccb2..8a289973 100644 --- a/testdata +++ b/testdata @@ -211,6 +211,10 @@ null null [1,2,3,4] +map(add) +[[], [1,2,3], ["a","b","c"], [[3],[4,5],[6]], [{"a":1}, {"b":2}, {"a":3}]] +[null, 6, "abc", [3,4,5,6], {"a":3, "b": 2}] + # # User-defined functions # Oh god.