Skip to content

Weird currying behavior when returning a partially-applied function from another function #5978

@tantmd

Description

@tantmd

Currying a function across more than two lets gives the wrong result.

let f1 = func a b c -> a + b + c
let f2 = func a b -> f1 a b
let f3 = func a -> f2 a

from t | derive {
  y = (((f3 100) 20) 3),
  z = ((f2 100 20) 3),
}

I thought y and z should be equivalent but they aren't.

SELECT
  *,
  100 + 20 + 20 AS y,
  100 + 20 + 3  AS z
FROM t

y's c is 20 (the value of b) instead of 3.

The weird thing is it works for the 4th param.

let f1 = func a b c d -> a + b + c + d
let f2 = func a b -> f1 a b
let f3 = func a -> f2 a

from t | derive {
  y = (((f3 100) 20) 3 4),
  z = ((f2 100 20) 3 4),
}
SELECT
  *,
  100 + 20 + 20 + 4 AS y,
  100 + 20 + 3 + 4  AS z
FROM t

Looking at

let param_name = format!("_partial_{i}");
.
A function returning a partially-applied func seems to wrap it with a wrapper func and pass the remaining params through as _partial_i. Somehow f3's wrapper ends up shadowing f2's wrapper.

Guessing d is fine because d gets stored as _partial_1 while c is _partial_0, so d doesn't collide with f3's own _partial_0 from its partial application, but c does.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions