Make reduce -n more sensible (#4791)

This commit is contained in:
JT 2022-03-09 05:56:08 -05:00 committed by GitHub
parent 088d19ad47
commit fac086c826
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 91 deletions

View File

@ -1,3 +1,5 @@
use std::sync::atomic::Ordering;
use nu_engine::{eval_block, CallExt}; use nu_engine::{eval_block, CallExt};
use nu_protocol::ast::Call; use nu_protocol::ast::Call;
@ -69,19 +71,9 @@ impl Command for Reduce {
} }
}"#, }"#,
description: "Find the longest string and its index", description: "Find the longest string and its index",
result: Some(Value::Record { result: Some(Value::String {
cols: vec!["index".to_string(), "item".to_string()],
vals: vec![
Value::Int {
val: 3,
span: Span::test_data(),
},
Value::String {
val: "longest".to_string(), val: "longest".to_string(),
span: Span::test_data(), span: Span::test_data(),
},
],
span: Span::test_data(),
}), }),
}, },
] ]
@ -94,10 +86,6 @@ impl Command for Reduce {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
// TODO: How to make this interruptible?
// TODO: Change the vars to $acc and $it instead of $it.acc and $it.item
// (requires parser change)
let span = call.head; let span = call.head;
let fold: Option<Value> = call.get_flag(engine_state, stack, "fold")?; let fold: Option<Value> = call.get_flag(engine_state, stack, "fold")?;
@ -105,6 +93,7 @@ impl Command for Reduce {
let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?; let capture_block: CaptureBlock = call.req(engine_state, stack, 0)?;
let mut stack = stack.captures_to_stack(&capture_block.captures); let mut stack = stack.captures_to_stack(&capture_block.captures);
let block = engine_state.get_block(capture_block.block_id); let block = engine_state.get_block(capture_block.block_id);
let ctrlc = engine_state.ctrlc.clone();
let orig_env_vars = stack.env_vars.clone(); let orig_env_vars = stack.env_vars.clone();
let orig_env_hidden = stack.env_hidden.clone(); let orig_env_hidden = stack.env_hidden.clone();
@ -126,13 +115,12 @@ impl Command for Reduce {
)); ));
}; };
Ok(input_iter let mut acc = start_val;
.enumerate()
.fold(start_val, move |acc, (idx, x)| {
stack.with_env(&orig_env_vars, &orig_env_hidden);
for (idx, x) in input_iter.enumerate() {
stack.with_env(&orig_env_vars, &orig_env_hidden);
// if the acc coming from previous iter is indexed, drop the index // if the acc coming from previous iter is indexed, drop the index
let acc = if let Value::Record { cols, vals, .. } = &acc { acc = if let Value::Record { cols, vals, .. } = &acc {
if cols.len() == 2 && vals.len() == 2 { if cols.len() == 2 && vals.len() == 2 {
if cols[0].eq("index") && cols[1].eq("item") { if cols[0].eq("index") && cols[1].eq("item") {
vals[1].clone() vals[1].clone()
@ -173,37 +161,24 @@ impl Command for Reduce {
} }
} }
let v = match eval_block( acc = eval_block(
engine_state, engine_state,
&mut stack, &mut stack,
block, block,
PipelineData::new(span), PipelineData::new(span),
redirect_stdout, redirect_stdout,
redirect_stderr, redirect_stderr,
) { )?
Ok(v) => v.into_value(span), .into_value(span);
Err(error) => Value::Error { error },
};
if numbered { if let Some(ctrlc) = &ctrlc {
// make sure the output is indexed if ctrlc.load(Ordering::SeqCst) {
Value::Record { break;
cols: vec!["index".to_string(), "item".to_string()],
vals: vec![
Value::Int {
val: idx as i64 + off,
span,
},
v,
],
span,
} }
} else {
v
} }
}) }
.with_span(span)
.into_pipeline_data()) Ok(acc.with_span(span).into_pipeline_data())
} }
} }

View File

@ -70,7 +70,6 @@ fn reduce_numbered_integer_addition_example() {
r#" r#"
echo [1 2 3 4] echo [1 2 3 4]
| reduce -n { |it, acc| $acc + $it.item } | reduce -n { |it, acc| $acc + $it.item }
| get item
"# "#
) )
); );