0

I dont understand what makes the different cases to work or not. I would have expected them to work all obviously.

  • funs2 and funs4 only close over the last value of n for some reason : they behave as if n was always 5.
  • funs3 captures each element of the sequence : it behaves as if n enumerated from 1 to 5, and mapped for each n to a different function, which will approximate the dataset differently (with increasing degree of freedom)

The script should be runnable directly in R with no dependance beside plyr.

Any clue ?

library(plyr)
f      <- function (x) { sin(2*pi*x) }
fnoisy <- function (x) {f(x) + 0.3*rnorm(1)}

x10 <- runif(10)
y10 <- aaply(x10,1,fnoisy)

curve(f,0,1,col="blue", ylim=c(-1.5,1.5))
points(x10, y10, col="red")

vdm <- function(x,n) outer( x, seq(0,n-1), "^" )

fitted <- function (n) { function(xtrain,ytrain) { w <- qr.solve(vdm(xtrain,n), ytrain) 
                                                   function (x) {  vdm(x,n) %*% w} } }


funs2 <- lapply(seq_len(5), function(n) {fitted(n)})          #does not work
funs3 <- lapply(seq_len(5), function(n) {print(n);fitted(n)}) #works
funs4 <- lapply(seq_len(5), fitted )                          #does not work

lapply(funs3, function(f) {ffitted <- f(x10,y10)
                           curve(ffitted,0,1,col="black", add=TRUE)})
nicolas
  • 9,549
  • 3
  • 39
  • 83
  • I'm sorry, but I'm having a hard time understanding exactly what you mean. Is the issue that the value of `n` is not what you expect when `fitted` is evaluated? It might help if you precisely explained what you expect, and exactly what is wrong. – joran Jul 08 '13 at 14:28
  • ok I will add some explanation – nicolas Jul 08 '13 at 14:28
  • 4
    I'm still a little unsure what your expected output is, but my guess is that you're seeing lazy evaluation. The `n` isn't evaluated until it's actually needed. In the case of `funs3`, your print call forces the evaluation of `n`. You could probably achieve the same effect by doing `force(n);fitted(n)`. – joran Jul 08 '13 at 14:34
  • +1 to joran, but your code looks like you tried to squeeze in as many (anonymous) functions as possible. As a result it's very difficult to understand. – Roland Jul 08 '13 at 14:40
  • 2
    `aaply(x10,1,fnoisy)` in place of `fnoisy(x10)` is bordering on the pathological, IMO. – Hong Ooi Jul 08 '13 at 14:41
  • looks like it, but I don't see where I would rely on side effect here. – nicolas Jul 08 '13 at 14:43
  • @HongOoi rnom() is defintely side effectful => I want to take 10 independant sample, not 1 applied to each entry. – nicolas Jul 08 '13 at 14:44
  • 1
    Um. 10 consecutive calls to `rnorm(1)` will get you _exactly the same numbers_ as `rnorm(10)`, for a given starting random seed. – Hong Ooi Jul 08 '13 at 14:47
  • 1
    That means you should use `fnoisy <- function (x) {f(x) + 0.3*rnorm(length(x)}`. And why don't you use the `sd` parameter of `rnorm` instead of multiplying with 0.3? That would make the code better to understand. – Roland Jul 08 '13 at 14:50
  • @Roland got it. Most mathematical and statistical functions in R are vectorised. You can get N independent random numbers faster and more easily with a single function call than with N function calls. – Hong Ooi Jul 08 '13 at 14:52
  • @HongOoi yes, so you'd advocate to use fnoisy <- function (x) {f(x) + 0.3*rnorm(length(x))}. now i get you. – nicolas Jul 08 '13 at 14:52
  • ah, posts crossed. yes that is better, well noted. – nicolas Jul 08 '13 at 14:53
  • 1
    @nicolas Functional programming doesn't mean that `function` needs to be in your code as often as possible. `y10 <- f(x) + rnorm(length(x),sd=0.3)` is perfectly okay. – Roland Jul 08 '13 at 14:56
  • @James that looks exactly like it. I wonder what its the cleanest way to get back normal function application semantic. – nicolas Jul 08 '13 at 15:00
  • closures strikes back. force() seems the best option to me. – vodka Jul 08 '13 at 15:02

0 Answers0