Skip to content

Lambda and Variable Expressions and BoundExpressions - #9257

Open
mhk197 wants to merge 27 commits into
developfrom
mk/lambda-variables
Open

Lambda and Variable Expressions and BoundExpressions#9257
mhk197 wants to merge 27 commits into
developfrom
mk/lambda-variables

Conversation

@mhk197

@mhk197 mhk197 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Add Variable expressions and standalone lambda syntax for future higher-order functions.

  • Add named Variable references and Scope bindings (name -> dtype), rejecting duplicate names.
  • Bind variables into typed BoundExpression::Variable nodes.
  • Add Lambda and BoundLambda as callable syntax/types owned by higher-order functions.
    Lambdas are deliberately not Expression variants: they do not have an array dtype or generic
    array-execution semantics.
  • Keep generic Expression machinery focused on array values: scalar functions, root, and
    variables.
  • Add protobuf round-tripping for variables and standalone lambdas, plus display, validity, and
    binding coverage.
  • Update expression consumers to reject detached variables when no runtime binding environment is
    available.

This establishes the type/binding representation; a future HOF vtable will supply parameter dtypes,
bind and optimize the lambda body, and evaluate it against its parameter arrays.

@codspeed-hq

codspeed-hq Bot commented Aug 7, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 1.18%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 1992 untouched benchmarks
⏩ 89 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation compress_fsst[(1000, 64, 8)] 1 ms 1.2 ms -12.2%
Simulation eq_pushdown_low_match 1.6 ms 1.4 ms +11.22%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing mk/lambda-variables (09e0c14) with develop (204d1d4)2

Open in CodSpeed

Footnotes

  1. 89 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on develop (f8d4db9) during the generation of this report, so 204d1d4 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@mhk197
mhk197 force-pushed the mk/lambda-variables branch from e41b484 to c077107 Compare August 7, 2026 03:06
@mhk197 mhk197 added the changelog/feature A new feature label Aug 7, 2026
@mhk197 mhk197 changed the title lambdas and variables Lambda and Variable Expressions and BoundExpressions Aug 7, 2026
@mhk197
mhk197 marked this pull request as ready for review August 10, 2026 20:56
@mhk197
mhk197 force-pushed the mk/lambda-variables branch from 752dc14 to 1ce48c3 Compare August 12, 2026 00:50
@mhk197
mhk197 force-pushed the mk/lambda-variables branch from 893ab28 to 1fb9ad6 Compare August 12, 2026 17:06
use crate::expr::analysis::BooleanLabels;
use crate::expr::label_tree;

pub fn label_is_fallible(expr: &Expression) -> BooleanLabels<'_> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should expand this doc str its all about well typed expressions

return if expr.is_root() {
scope.names().iter().cloned().collect()
} else {
vec![]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this?

match self {
BoundExpression::Scalar { children, .. } => f(&mut children.iter()),
BoundExpression::Root { .. } => f(&mut std::iter::empty()),
_ => f(&mut std::iter::empty()),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you leave this enum as closed?

Comment on lines +72 to +81
pub struct BoundLambda {
/// The parameters and their dtypes: the argument side of the function type.
params: Box<[Variable]>,
param_dtypes: Box<[DType]>,
body: Arc<BoundExpression>,
}

impl BoundLambda {
/// The variables this lambda binds, in declaration order.
pub fn params(&self) -> &[Variable] {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I use this it its not a BoundExpression?


/// The name of a value bound in a [`Scope`](crate::expr::Scope).
#[derive(Clone, Debug)]
pub struct Variable(Arc<str>);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think need to be able to go from a series of FieldNames to a series of Variable efficently. Does this allow that?

Base automatically changed from mk/bound-expression-enum to develop August 13, 2026 10:25
mhk197 added 12 commits August 13, 2026 11:25
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
…ialization docs

Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Variable and Lambda get reserved expression ids alongside Root, so the
unbound tree stays fully serializable. Variable carries its name in
VariableOpts; Lambda carries its params in LambdaOpts and its body as its
single proto child. All three reserved ids resolve before the registry
lookup.

Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
mhk197 added 15 commits August 13, 2026 11:25
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants