Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Imported functions created with Vectorize() do not work. #35

Closed
wlandau-lilly opened this issue Apr 28, 2017 · 0 comments
Closed

Imported functions created with Vectorize() do not work. #35

wlandau-lilly opened this issue Apr 28, 2017 · 0 comments
Assignees

Comments

@wlandau-lilly
Copy link
Collaborator

wlandau-lilly commented Apr 28, 2017

Current behavior

> library(drake)
> f = Vectorize(function(x){
+ x + 1
+ }, "x")
> myplan = plan(y = f(1:10))
> make(myplan)
import c
import as.list
import character
import do.call
import eval
import FUN
could not find FUN
import is.null
import lapply
import length
import list
import match.call
import parent.frame
import SIMPLIFY
could not find SIMPLIFY
import USE.NAMES
could not find USE.NAMES
import vectorize.args
could not find vectorize.args
import f
build y
Error in match(x, table, nomatch = 0L) :
  object 'vectorize.args' not found

Easy workaround

Enclose your vectorized function in a wrapper function.

> library(drake)
> h = function(z){
+   f = Vectorize(function(x){
+    x + 1
+   }, "x")
+   f(z)
+ }
> myplan = plan(y = h(1:10))
> make(myplan)
import Vectorize
import h
build y
> readd(y)
 [1]  2  3  4  5  6  7  8  9 10 11
>

Root cause

  • R uses lexical scoping, which affects how non-local variables of functions are found. Non-local variables are found in the environment where the function was originally defined (parent.env()), not the environment where the function is called (parent.frame()).
  • f() was defined with Vectorize(), so it has non-local variables SIMPLIFY, USE.NAMES, etc. in its closure. You can verify this with ls(environment(f)). See Hadley's intro to function environments.
  • In make(), drake creates its own special environment from scratch and assigns all imported functions to that environment. (Otherwise, calls to nested imported functions fail.) Thus, all symbols like SIMPLIFY and USE.NAMES are looked up in an environment different than the original environment(f).

Solution

Sathish solved this specific scenario on StackOverflow. However, this is just one of a handful of edge cases due to the root cause above. To make behavior more predictable, drake needs to stop micromanaging environments and functions altogether and just work in the user's environment. See #37.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant