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

Code before:
            };
            let record = record.to_mut().into_spanned(internal_span);
            fill_record(record, &mut default_value, columns, default_when_empty)
                .map(|x| x.into_pipeline_data().set_metadata(metadata))
        } else if matches!(
            input,
            PipelineData::ListStream(..) | PipelineData::Value(Value::List { .. }, _)
        ) {
            let mut output_list: Vec<Value> = vec![];
            for mut item in input {
                if let Value::Record {
                    val: ref mut record,
                    internal_span,
                } = item
                {
                    let record = record.to_mut().into_spanned(internal_span);
                    item = fill_record(record, &mut default_value, columns, default_when_empty)?;
                }
                output_list.push(item);
            }
            let ls = ListStream::new(
                output_list.into_iter(),
                call.head,
                engine_state.signals().clone(),
            );
            Ok(PipelineData::ListStream(ls, metadata))
        // If columns are given, but input does not use columns, return an error
        } else {
            Err(ShellError::PipelineMismatch {
                exp_input_type: "record, table".to_string(),
                dst_span: input_span,
                src_span: input_span,
            })
        }
    // Otherwise, if no column name is given, check if value is null
    // or an empty string, list, or record when --empty is passed
    } else if input.is_nothing()
        || (default_when_empty
            && matches!(input, PipelineData::Value(ref value, _) if value.is_empty()))
    {
        default_value.pipeline_data()
    } else if default_when_empty && matches!(input, PipelineData::ListStream(..)) {
        let PipelineData::ListStream(ls, metadata) = input else {
            unreachable!()
        };
        let span = ls.span();
        let mut stream = ls.into_inner().peekable();
        if stream.peek().is_none() {
            return default_value.pipeline_data();
        }


Review comment (suggestion):
```suggestion
            // Potential enhancement: add another branch for Value::List,
            // and collect the iterator into a Result<Value::List, ShellError>
            // so we can preemptively return an error for collected lists
            Ok(input
                .into_iter()
                .map(move |item| {
                    let span = item.span();
                    if let Value::Record { val, .. } = item {
                        fill_record(
                            val.into_owned(),
                            span,
                            &mut default_value,
                            columns.as_slice(),
                            default_when_empty,
                        )
                        .unwrap_or_else(|err| Value::error(err, head))
                    } else {
                        item
                    }
                })
                .into_pipeline_data_with_metadata(head, engine_state.signals().clone(), metadata))
```

I think we should try to maintain streaming when possible. While you used a `ListStream` before, the entire stream was implicitly collected by the `for` loop. By using `map` on the `PipelineData` iterator, we can keep the stream intact.

Code after:
            )
            .map(|x| x.into_pipeline_data_with_metadata(metadata))
        } else if matches!(
            input,
            PipelineData::ListStream(..) | PipelineData::Value(Value::List { .. }, _)
        ) {
            // Potential enhancement: add another branch for Value::List,
            // and collect the iterator into a Result<Value::List, ShellError>
            // so we can preemptively return an error for collected lists
            let head = call.head;
            Ok(input
                .into_iter()
                .map(move |item| {
                    let span = item.span();
                    if let Value::Record { val, .. } = item {
                        fill_record(
                            val.into_owned(),
                            span,
                            &mut default_value,
                            columns.as_slice(),
                            default_when_empty,
                        )
                        .unwrap_or_else(|err| Value::error(err, head))
                    } else {
                        item
                    }
                })
                .into_pipeline_data_with_metadata(head, engine_state.signals().clone(), metadata))
        // If columns are given, but input does not use columns, return an error
        } else {
            Err(ShellError::PipelineMismatch {
                exp_input_type: "record, table".to_string(),
                dst_span: input_span,
                src_span: input_span,
            })
        }
    // Otherwise, if no column name is given, check if value is null
    // or an empty string, list, or record when --empty is passed
    } else if input.is_nothing()
        || (default_when_empty
            && matches!(input, PipelineData::Value(ref value, _) if value.is_empty()))
    {
        default_value.pipeline_data()
    } else if default_when_empty && matches!(input, PipelineData::ListStream(..)) {
        let PipelineData::ListStream(ls, metadata) = input else {
            unreachable!()
        };
        let span = ls.span();
        let mut stream = ls.into_inner().peekable();
        if stream.peek().is_none() {
            return default_value.pipeline_data();