zatonovo / lambda.r

Functional programming in R
214 stars 14 forks source link

Function parameter matching bug #32

Open iwccsbfb opened 8 years ago

iwccsbfb commented 8 years ago

Example as below, lambda.r function is not working the same as R functions:

for function call f1(Sys.Date(), 1,2) , Sys.Date() should be matched to start by default. But it is not.

library(lambda.r) f1 (start = Sys.Date(), ...) %as% { vs <- list(...) print(vs) NULL } f1(Sys.Date(), 1,2) [[1]] [1] "2016-07-27" [[2]] [1] 1 [[3]] [1] 2 NULL f1(start = Sys.Date(), 1,2) [[1]] [1] 1 [[2]] [1] 2 NULL

f2 <- function(start = Sys.Date(), ...) { vs <- list(...) print(vs) NULL } f2(Sys.Date()-1, 1, 2) [[1]] [1] 1 [[2]] [1] 2 NULL f2(start = Sys.Date()-1, 1, 2) [[1]] [1] 1 [[2]] [1] 2 NULL

iwccsbfb commented 8 years ago

Issue fixed in the PR #33

iwccsbfb commented 8 years ago

Reference: https://cran.r-project.org/doc/manuals/R-lang.html#Argument-matching We can apply this parameter matching procedure:

  1. Exact matching
  2. Partial matching
  3. Positional matching
muxspace commented 8 years ago

In isolation it makes sense to follow same approach, although I'm not a fan of partial matching. Ensuring 1 and 3 behave consistently makes sense to me.

We also have to consider multiple function clauses, where the first matching function following the rules above are selected (with the caveat that the ellipsis argument is ignored). I need to look at the code to remember how things are done now, or if you can do that so we know the baseline, that would be great.

iwccsbfb commented 8 years ago

Found several other test cases that could fail. case 1: default value of one parameter is another parameter case 2: late binding. For this case, because we are applying polymorphism, it is nearly impossible to make the lambda.r function work the same way as R functions.

> f1(a = 1, b= a) %as% {
+     print(a)
+     print(b)
+ }
> f1()
[1] 1
[1] NA
[1] NA

> f2(a = 1, b) %as% {
+     print(a)
+ }
> f2()
Error in UseFunction(f2, "f2", ...) : No match for function 'f2()'

If we declare R function same as f2, it will work:


> f3 <- function(a = 1, b){
+     print(a)
+ }
> f3()
[1] 1
iwccsbfb commented 8 years ago

For the above case 1, things could be complicated. Here is an example of R function:

> f4 <- function(d = a + 2, c = b + d, b = a + 1, a = 1){
+     print(a)
+     print(b)
+     print(c)
+     print(d)
+ }
> f4()
[1] 1
[1] 2
[1] 5
[1] 3

I think R is creating a directed graph of parameters and then evaluate from the node with 0 degree. We can manually do the evaluation in this way. Or I think a better way is to execute the function directly with the calling string.

muxspace commented 8 years ago

Please number each function uniquely, so it is easier to reference. I changed your second f2 to f4 to reflect this.

For f2, this is correct behavior. If we want to be able to reason about functions, then the signatures must match. In R, even though no default value is provided for b, the function still executes. I disagree with these semantics, so for lambda.r the correct behavior is to fail.