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