From 7528094e12b1ced6f614e0cf3188442dfda2183a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sat, 12 Sep 2020 01:40:52 -0500 Subject: [PATCH] Allow folding with tables. (#2538) --- crates/nu-cli/src/commands/is_empty.rs | 8 +++++- crates/nu-cli/src/commands/reduce.rs | 31 +++++++++++++++++++++--- crates/nu-cli/tests/commands/is_empty.rs | 10 +++----- crates/nu-cli/tests/commands/reduce.rs | 20 +++++++++++++++ crates/nu-protocol/src/value.rs | 6 ++--- 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/crates/nu-cli/src/commands/is_empty.rs b/crates/nu-cli/src/commands/is_empty.rs index a6ec5ef90f..32a0e1024e 100644 --- a/crates/nu-cli/src/commands/is_empty.rs +++ b/crates/nu-cli/src/commands/is_empty.rs @@ -50,9 +50,16 @@ async fn is_empty( args: CommandArgs, registry: &CommandRegistry, ) -> Result { + let name_tag = args.call_info.name_tag.clone(); let registry = registry.clone(); let (IsEmptyArgs { rest }, input) = args.process(®istry).await?; + if input.is_empty() { + return Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::boolean(true).into_value(name_tag), + ))); + } + Ok(input .map(move |value| { let value_tag = value.tag(); @@ -72,7 +79,6 @@ async fn is_empty( (_, _) => IsEmptyFor::Value, } } else { - // let no_args = vec![]; let mut arguments = rest.iter().rev(); let replacement_if_true = match arguments.next() { Some(arg) => arg.clone(), diff --git a/crates/nu-cli/src/commands/reduce.rs b/crates/nu-cli/src/commands/reduce.rs index 638c01e3e7..514a26a1cb 100644 --- a/crates/nu-cli/src/commands/reduce.rs +++ b/crates/nu-cli/src/commands/reduce.rs @@ -138,7 +138,19 @@ async fn reduce( let row = each::make_indexed_item(input.0 + ioffset, input.1); async { - let f = acc?.into_vec().await[0].clone(); + let values = acc?.drain_vec().await; + + let f = if values.len() == 1 { + let value = values + .get(0) + .ok_or_else(|| ShellError::unexpected("No value to update with"))?; + value.clone() + } else if values.is_empty() { + UntaggedValue::nothing().into_untagged_value() + } else { + UntaggedValue::table(&values).into_untagged_value() + }; + scope.vars.insert(String::from("$acc"), f); process_row(block, Arc::new(scope), context, row).await } @@ -154,9 +166,20 @@ async fn reduce( let context = Arc::clone(&context); async { - scope - .vars - .insert(String::from("$acc"), acc?.into_vec().await[0].clone()); + let values = acc?.drain_vec().await; + + let f = if values.len() == 1 { + let value = values + .get(0) + .ok_or_else(|| ShellError::unexpected("No value to update with"))?; + value.clone() + } else if values.is_empty() { + UntaggedValue::nothing().into_untagged_value() + } else { + UntaggedValue::table(&values).into_untagged_value() + }; + + scope.vars.insert(String::from("$acc"), f); process_row(block, Arc::new(scope), context, row).await } }) diff --git a/crates/nu-cli/tests/commands/is_empty.rs b/crates/nu-cli/tests/commands/is_empty.rs index 6929a58d04..da65947132 100644 --- a/crates/nu-cli/tests/commands/is_empty.rs +++ b/crates/nu-cli/tests/commands/is_empty.rs @@ -40,8 +40,7 @@ fn adds_value_provided_for_columns_that_are_empty() { [ {"boost": 1, "check": []}, {"boost": 1, "check": ""}, - {"boost": 1, "check": {}}, - {"boost": null, "check": ["" {} [] ""]} + {"boost": 1, "check": {}} ] "#, @@ -58,7 +57,7 @@ fn adds_value_provided_for_columns_that_are_empty() { "# )); - assert_eq!(actual.out, "8"); + assert_eq!(actual.out, "6"); }) } @@ -72,8 +71,7 @@ fn value_emptiness_check() { "are_empty": [ {"check": []}, {"check": ""}, - {"check": {}}, - {"check": ["" {} [] ""]} + {"check": {}} ] } "#, @@ -91,6 +89,6 @@ fn value_emptiness_check() { "# )); - assert_eq!(actual.out, "4"); + assert_eq!(actual.out, "3"); }) } diff --git a/crates/nu-cli/tests/commands/reduce.rs b/crates/nu-cli/tests/commands/reduce.rs index 123f5e947a..2e226ff1be 100644 --- a/crates/nu-cli/tests/commands/reduce.rs +++ b/crates/nu-cli/tests/commands/reduce.rs @@ -62,6 +62,26 @@ fn reduce_numbered_example() { assert_eq!(actual.out, "1"); } +#[test] +fn folding_with_tables() { + let actual = nu!( + cwd: ".", pipeline( + r#" + echo [10 20 30 40] + | reduce -f [] { + with-env [value $it] { + echo $acc | append $(= 10 * $(= $nu.env.value | str to-int)) + } + } + | math sum + | echo $it + "# + ) + ); + + assert_eq!(actual.out, "1000"); +} + #[test] fn error_reduce_fold_type_mismatch() { let actual = nu!( diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index 4cf7e061ad..2daa937c29 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -385,12 +385,10 @@ impl Value { value: UntaggedValue::Primitive(p), .. } => p.is_empty(), - t - @ Value { - value: UntaggedValue::Table(_), + value: UntaggedValue::Table(rows), .. - } => t.table_entries().all(|row| row.is_empty()), + } => rows.is_empty(), r @ Value {