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:
yziquel at 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 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:
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.".
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,
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.
It seems that Matjaz Kukar had the same kind of issue that I have with
usemethod:
http://tolstoy.newcastle.edu.au/R/devel/04/10/0902.html
I just remark two things from the resulting thread:
-1- He asks where to find a more precise documentation of the R API,
which is also something I'd be looking for,
-2- He has been suggested to use findVar1, which doesn't seem to be part
of the API.
Will be looking into findVar1, findFun, findVar, though I do not
understand why this fails in my case. Please feel free to enlighten me.
All the best,
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:
Replacing findfun by findvar works in this specific case. See below.
Could someone explain why findfun works while findvar doesn't? I've been
looking at the source code in envir.c, and it isn't really clear why one
way works while the other doesn't.
Is it possible, given a variable/function name, to determine if it
should use findFun or findVar? This would be helpful for the polymorphic
static typing of R values.
yziquel at seldon:~/git/ocamlr-quantmod$ ocaml-batteries
Objective Caml version 3.11.1
_________________________________
| | | |
[| + | | Batteries Included - |
|_______|_|_______________________|
_________________________________
| | | |
| - Type '#help;;' | | + |]
|_______________________|_|_______|
# #require "R.interpreter";;
# let show = R.Pretty.t_of_sexp;;
val show : R.sexp -> R.PrettyTypes.t = <fun>
findFun works.
# let str = R.findfun (R.install "str");;
val str : ('_a -> 'b) R.t = <abstr>
# let lm = R.findvar (R.install "lm");;
val lm : 'a R.promise = <abstr>
# R.eval [str; lm];;
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>
findVar doesn't.
# let str = R.findvar (R.install "str");;
val str : 'a R.promise = <abstr>
# R.eval [str; lm];;
Erreur dans function (object, ...) :
function g?n?rique incorrecte dans 'UseMethod'
Exception: Failure "OCaml-R error in r_eval_sxp C stub.".
#