Simon Urbanek a écrit :

On Nov 30, 2009, at 16:07 , Guillaume Yziquel wrote:

Simon Urbanek a écrit :

And it goes then to my other question: How can you pass to eval a LANGSXP where the CAR is an *anonymous* function, no SYMSXP involved?
You just pass it as value of the call. I suspect the reason it doesn't work is in your code, not in the facility (note that the link above is useless since the construction is mystery - if you were constructing it right, it would work ;)).

The small example you gave just works out fine with the framework I've been building so far:

yziq...@seldon:~$ ocaml-batteries
        Objective Caml version 3.11.1

      _________________________________
     |       | |                       |
    [| +     | | Batteries Included  - |
     |_______|_|_______________________|
      _________________________________
     |                       | |       |
     | -    Type '#help;;'   | |     + |]
     |_______________________|_|_______|


# #require "R.interpreter";;
# let show x = R.Pretty.t_of_sexp x;;
val show : R.sexp -> R.PrettyTypes.t = <fun>
# open R.PrettyTypes;;

This is administrativia.

# let r_f_unevaluated = R.parse_sexp "function(x) x + 1";;
val r_f_unevaluated : R.sexp = <abstr>
# let r_f = R.eval_langsxp r_f_unevaluated;;
val r_f : R.sexp = <abstr>
# show r_f_unevaluated;;
- : R.PrettyTypes.t =
CALL (SYMBOL (Some ("function", SPECIAL)),
 [(NULL, LIST [(ARG "x", PLACE)]);
  (NULL,
   CALL (SYMBOL (Some ("+", BUILTIN)), [(NULL, ARG "x"); (NULL, Unknown)]));
  (NULL, STRINGS ["function(x) x + 1"])])
# show r_f;;
- : R.PrettyTypes.t =
CLOSURE
 {formals = LIST [(ARG "x", PLACE)];
  clos_env = ENV {frame = NULL; hashtab = NULL}}

So after evaluating the parsed output of "function(x) x + 1", you indeed get a pure closure. So far so good.

# let x = R.parse_sexp "11";;
val x : R.sexp = <abstr>
# R.sexptype x;;
- : R.sexptype = R.RealSxp

Here's the argument, 11.

# let call = R.langsxp_of_list [r_f; x] 2;;
val call : R.lang R.sxp = <abstr>
# show call;;
- : R.PrettyTypes.t =
CALL
 (CLOSURE
   {formals = LIST [(ARG "x", PLACE)];
    clos_env = ENV {frame = NULL; hashtab = NULL}},
 [(NULL, Unknown)])

Here's the call that is built out of the closure and 11. For construction details, the C function is given at the bottom.

# let y = R.eval_langsxp call;;
val y : R.sexp = <abstr>

And it gets correctly evaluated. So this is fine. In fact, it works on the majority of the things I try. So I guess I've been building it fine. What's not fine is the following, from the quantmod package:

# let s = R.string "YHOO";;
val s : string R.t = <abstr>

s is a STRSXP vector containing only one string: "YHOO".

# let g = R.force (R.symbol "getSymbols");;
val g : 'a R.t = <abstr>

g is the getSymbols function from quantmod. From the help(getSymbols) invocation:

Usage:

getSymbols(Symbols = NULL, env = .GlobalEnv,
                reload.Symbols = FALSE,
                verbose = FALSE,
                warnings = TRUE,
                src = "yahoo",
                symbol.lookup = TRUE,
                auto.assign = TRUE,
                ...)

So I try out getSymbols("YHOO"). It works out fine, and returns silently in the R toplevel.

But, from my binding:

# R.eval_langsxp (R.langsxp_of_list [g; s] 2);;
Erreur dans as.character(sc[[1]]) : cannot coerce type 'closure' to vector of type 'character'
Exception: Failure "OCaml-R error in r_eval_sxp C stub.".

Here are the values of s and g:

# show s;;
- : R.PrettyTypes.t = STRINGS ["YHOO"]
# show g;;
- : R.PrettyTypes.t =
CLOSURE
 {formals =
   LIST
    [(ARG "Symbols", NULL); (ARG "env", Unknown);
     (ARG "reload.Symbols", Unknown); (ARG "verbose", Unknown);
     (Unknown, Unknown); (ARG "src", STRINGS ["yahoo"]);
     (ARG "symbol.lookup", Unknown); (ARG "auto.assign", Unknown);
     (ARG "...", PLACE)];
  clos_env = ENV {frame = NULL; hashtab = Unknown}}

For the sake of exhaustivity, here's the C functions that I wrote to make function calls:

CAMLprim value r_eval_sxp (value sexp_list) {
  CAMLparam1(sexp_list);
  SEXP e;
  int error = 0;
  PROTECT(e = R_tryEval(Sexp_val(sexp_list), R_GlobalEnv, &error));
  UNPROTECT(1);
  if (error) caml_failwith("OCaml-R error in r_eval_sxp C stub.");
  CAMLreturn(Val_sexp(e));
}

and

CAMLprim value r_langsxp_of_list (value l, value n) {
  CAMLparam2(l, n);
  CAMLlocal1(l_cursor);
  SEXP s, t;
  PROTECT(t = s = Rf_allocList(Int_val(n)));
  SET_TYPEOF(s, LANGSXP);
  int first_time = 1;
  l_cursor = l;
  while (l_cursor && Is_block(l_cursor)) {
    if (first_time) {first_time = 0;} else {t = CDR(t);}
    SETCAR(t, Sexp_val(Field(l_cursor, 0)));
    l_cursor = Field(l_cursor, 1);
  }
  UNPROTECT(1);
  CAMLreturn(Val_sexp(s));
}

So I'm almost constructing LANGSXP lists in the way you do.

One last thing, concerning the use of promises. If I do install, findVar, without forcing the resulting promise, and then construct the call, I get a failure:

# R.eval_langsxp (R.langsxp_of_list [(R.symbol "str"); (R.symbol "lm")] 2);;
Erreur dans function (object, ...) : function générique incorrecte dans 'UseMethod'
Exception: Failure "OCaml-R error in r_eval_sxp C stub.".

If I force the promises:

# R.eval_langsxp (R.langsxp_of_list [(R.force (R.symbol "str")); (R.force (R.symbol 
"lm"))] 2);;
function (formula, data, subset, weights, na.action, method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL, offset, ...) - : R.sexp = <abstr>

It works.

So you may say that "I'm not constructing it right", I still believe that describing precisely what kind of arguments is accepted by eval would a good thing.

All the best,

--
     Guillaume Yziquel
http://yziquel.homelinux.org/

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to