Repository: nushell/nushell
File: crates/nu-command/src/filters/default.rs (Rust)

Code before:
            _ => DefaultValue::Calculated(value),
        }
    }

    fn value(&mut self) -> Result<Value, ShellError> {
        match self {
            DefaultValue::Uncalculated(engine_state, stack, closure) => {
                let closure_eval = ClosureEvalOnce::new(engine_state, stack, closure.item.clone());
                let value = closure_eval
                    .run_with_input(PipelineData::Empty)?
                    .into_value(closure.span)?;
                *self = DefaultValue::Calculated(value.clone());
                Ok(value)
            }
            DefaultValue::Calculated(value) => Ok(value.clone()),
        }
    }

    fn pipeline_data(&mut self) -> Result<PipelineData, ShellError> {
        self.value().map(|x| x.into_pipeline_data())
    }
}

/// Given a record, fill missing columns with a default value
fn fill_record(
    record: Spanned<&mut Record>,
    default_value: &mut DefaultValue,
    columns: &[String],
    empty: bool,
) -> Result<Value, ShellError> {
    for col in columns {
        if let Some(val) = record.item.get_mut(col) {
            if matches!(val, Value::Nothing { .. }) || (empty && val.is_empty()) {
                *val = default_value.value()?;
            }
        } else {
            record.item.push(col.clone(), default_value.value()?);
        }
    }
    Ok(Value::record(record.item.clone(), record.span))
}

#[cfg(test)]
mod test {
    use crate::Upsert;

    use super::*;

    #[test]
    fn test_examples() {
        use crate::test_examples_with_commands;

Review comment (suggestion):
```suggestion
enum DefaultValue {
    Uncalculated(Spanned<ClosureEval>),
    Calculated(Value),
}

impl DefaultValue {
    fn new(engine_state: &EngineState, stack: &Stack, value: Value) -> Self {
        let span = value.span();
        match value {
            Value::Closure { val, .. } => {
                let closure_eval = ClosureEval::new(engine_state, stack, *val);
                DefaultValue::Uncalculated(closure_eval.into_spanned(span))
            }
            _ => DefaultValue::Calculated(value),
        }
    }

    fn value(&mut self) -> Result<Value, ShellError> {
        match self {
            DefaultValue::Uncalculated(closure) => {
                let value = closure
                    .item
                    .run_with_input(PipelineData::Empty)?
                    .into_value(closure.span)?;
                *self = DefaultValue::Calculated(value.clone());
                Ok(value)
            }
            DefaultValue::Calculated(value) => Ok(value.clone()),
        }
    }

    fn pipeline_data(&mut self) -> Result<PipelineData, ShellError> {
        self.value().map(|x| x.into_pipeline_data())
    }
}
```

In order to pass `DefaultValue` into the closure used for `map`, we can't have a reference to EngineState or Stack. Therefore, we have to use `ClosureEval` here, which does unfortunately clone `EngineState` and `Stack`, but I think this is a reasonable tradeoff to preserve streaming (this is how e.g., the `each` command works)

Code after:
                let closure_eval = ClosureEval::new(engine_state, stack, *val);
                DefaultValue::Uncalculated(closure_eval.into_spanned(span))
            }
            _ => DefaultValue::Calculated(value),
        }
    }

    fn value(&mut self) -> Result<Value, ShellError> {
        match self {
            DefaultValue::Uncalculated(closure) => {
                let value = closure
                    .item
                    .run_with_input(PipelineData::Empty)?
                    .into_value(closure.span)?;
                *self = DefaultValue::Calculated(value.clone());
                Ok(value)
            }
            DefaultValue::Calculated(value) => Ok(value.clone()),
        }
    }

    fn pipeline_data(&mut self) -> Result<PipelineData, ShellError> {
        self.value().map(|x| x.into_pipeline_data())
    }
}

/// Given a record, fill missing columns with a default value
fn fill_record(
    mut record: Record,
    span: Span,
    default_value: &mut DefaultValue,
    columns: &[String],
    empty: bool,
) -> Result<Value, ShellError> {
    for col in columns {
        if let Some(val) = record.get_mut(col) {
            if matches!(val, Value::Nothing { .. }) || (empty && val.is_empty()) {
                *val = default_value.value()?;
            }
        } else {
            record.push(col.clone(), default_value.value()?);
        }
    }
    Ok(Value::record(record, span))
}

#[cfg(test)]
mod test {
    use crate::Upsert;

    use super::*;