mirror of
https://github.com/nushell/nushell.git
synced 2025-06-20 09:58:15 +02:00
Make reduce -n
more sensible (#4791)
This commit is contained in:
parent
088d19ad47
commit
fac086c826
@ -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;
|
||||||
@ -62,25 +64,15 @@ impl Command for Reduce {
|
|||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
example: r#"[ one longest three bar ] | reduce -n { |it, acc|
|
example: r#"[ one longest three bar ] | reduce -n { |it, acc|
|
||||||
if ($it.item | str length) > ($acc | str length) {
|
if ($it.item | str length) > ($acc | str length) {
|
||||||
$it.item
|
$it.item
|
||||||
} else {
|
} else {
|
||||||
$acc
|
$acc
|
||||||
}
|
}
|
||||||
}"#,
|
}"#,
|
||||||
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()],
|
val: "longest".to_string(),
|
||||||
vals: vec![
|
|
||||||
Value::Int {
|
|
||||||
val: 3,
|
|
||||||
span: Span::test_data(),
|
|
||||||
},
|
|
||||||
Value::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,84 +115,70 @@ 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);
|
|
||||||
|
|
||||||
// if the acc coming from previous iter is indexed, drop the index
|
for (idx, x) in input_iter.enumerate() {
|
||||||
let acc = if let Value::Record { cols, vals, .. } = &acc {
|
stack.with_env(&orig_env_vars, &orig_env_hidden);
|
||||||
if cols.len() == 2 && vals.len() == 2 {
|
// if the acc coming from previous iter is indexed, drop the index
|
||||||
if cols[0].eq("index") && cols[1].eq("item") {
|
acc = if let Value::Record { cols, vals, .. } = &acc {
|
||||||
vals[1].clone()
|
if cols.len() == 2 && vals.len() == 2 {
|
||||||
} else {
|
if cols[0].eq("index") && cols[1].eq("item") {
|
||||||
acc
|
vals[1].clone()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
acc
|
acc
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(var) = block.signature.get_positional(0) {
|
|
||||||
if let Some(var_id) = &var.var_id {
|
|
||||||
let it = if numbered {
|
|
||||||
Value::Record {
|
|
||||||
cols: vec!["index".to_string(), "item".to_string()],
|
|
||||||
vals: vec![
|
|
||||||
Value::Int {
|
|
||||||
val: idx as i64 + off,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
x,
|
|
||||||
],
|
|
||||||
span,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
x
|
|
||||||
};
|
|
||||||
|
|
||||||
stack.add_var(*var_id, it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(var) = block.signature.get_positional(1) {
|
|
||||||
if let Some(var_id) = &var.var_id {
|
|
||||||
stack.add_var(*var_id, acc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
};
|
||||||
|
|
||||||
let v = match eval_block(
|
if let Some(var) = block.signature.get_positional(0) {
|
||||||
engine_state,
|
if let Some(var_id) = &var.var_id {
|
||||||
&mut stack,
|
let it = if numbered {
|
||||||
block,
|
Value::Record {
|
||||||
PipelineData::new(span),
|
cols: vec!["index".to_string(), "item".to_string()],
|
||||||
redirect_stdout,
|
vals: vec![
|
||||||
redirect_stderr,
|
Value::Int {
|
||||||
) {
|
val: idx as i64 + off,
|
||||||
Ok(v) => v.into_value(span),
|
span,
|
||||||
Err(error) => Value::Error { error },
|
},
|
||||||
};
|
x,
|
||||||
|
],
|
||||||
|
span,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
};
|
||||||
|
|
||||||
if numbered {
|
stack.add_var(*var_id, it);
|
||||||
// make sure the output is indexed
|
|
||||||
Value::Record {
|
|
||||||
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)
|
if let Some(var) = block.signature.get_positional(1) {
|
||||||
.into_pipeline_data())
|
if let Some(var_id) = &var.var_id {
|
||||||
|
stack.add_var(*var_id, acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
acc = eval_block(
|
||||||
|
engine_state,
|
||||||
|
&mut stack,
|
||||||
|
block,
|
||||||
|
PipelineData::new(span),
|
||||||
|
redirect_stdout,
|
||||||
|
redirect_stderr,
|
||||||
|
)?
|
||||||
|
.into_value(span);
|
||||||
|
|
||||||
|
if let Some(ctrlc) = &ctrlc {
|
||||||
|
if ctrlc.load(Ordering::SeqCst) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(acc.with_span(span).into_pipeline_data())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
"#
|
"#
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user