[ESS] Fw: [O] Missing newline in R code causes Org-Mode eval to hang

Vitalie Spinu spinuvit.list at gmail.com
Mon Oct 24 23:31:10 CEST 2011


On Sat, Oct 22, 2011 at 9:37 PM, Martin Maechler
<maechler at stat.math.ethz.ch> wrote:
> On Tue, Oct 18, 2011 at 20:00, Vitalie Spinu <spinuvit.list at gmail.com> wrote:
>> I can reproduce your problem with plain ess. With ess-tracebug
>> (http://code.google.com/p/ess-tracebug/) it works smoothly.
>


> well... can you tell us *how* you reproduce the problem?

Along the same lines as in Mike's email. Boils down to executing


#+begin_src R
   cat("a b")
   print("c")
#+end_src

from .org buffer (C-c C-c).

I tracked it down and it turns that it a mixture of org-babel mistake and ess
bug.

Org-babel uses 'ess-eval-buffer' which is an user level command
(i.e. depends on the notorious 'ess-eval-visibly-p'). That means that if
ess-eval-visibly-p is t (which is the default) the ess-eval-linewise is
called. But that one is the slowest and most unreliable command in the whole
ESS!

Developers relying on ESS should use ess-command, or at least let-bind
ess-eval-visibly-p to nil in their code.

The bug on ESS side is in ess-eval-linewise. Create an .R script only with

cat("a b")
print("c")

and evaluate it visibly - emacs hangs.

The problem is with the waiting-for-the-prompt loop which ess-eval-linewise uses
(inferior-ess-prompt). The loop is stuck at "a b>" which is not considered a
valid prompt. As it seems to me, the only solution is to simplify the regexp.

> or even better point us to the (ess-help archive of the) report you
> mention below?

My report concerned ess-command which can be found here
http://thread.gmane.org/gmane.emacs.ess.general/4947

Two reproducible examples follow.

1) ess-command hangs emacs:

(ess-command    "tf<-function(N){
N}\n")


2) ess-command outputs  part of the R-output to inferior-ess:

(ess-command "
lm_test <- function (formula, data, subset, weights, na.action, method = 'qr',
          model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
          contrasts = NULL, offset, ...)
{
    cl <- match.call()
    mf <- match.call(expand.dots = FALSE)
    m <- match(c('formula', 'data', 'subset', 'weights', 'na.action',
                 'offset'), names(mf), 0L)
    mf <- mf[c(1L, m)]
    mf$drop.unused.levels <- TRUE
    mf[[1L]] <- as.name('model.frame')
    mf <- eval(mf, parent.frame())
    if (method == 'model.frame')
        return(mf)
    else if (method != 'qr')
        warning(gettextf('method is not supported. Using',
                         method), domain = NA)
    mt <- attr(mf, 'terms')
    y <- model.response(mf, 'numeric')
    w <- as.vector(model.weights(mf))
    if (!is.null(w) && !is.numeric(w))
        stop('weights must be a numeric vector')
    offset <- as.vector(model.offset(mf))
    if (!is.null(offset)) {
        if (length(offset) != NROW(y))
            stop(gettextf('number of offsets is %d, should equal %d
(number of observations)',
                          length(offset), NROW(y)), domain = NA)
    }
    if (is.empty.model(mt)) {
        x <- NULL
        z <- list(coefficients = if (is.matrix(y)) matrix(, 0,
                    3) else numeric(0L), residuals = y, fitted.values = 0 *
                  y, weights = w, rank = 0L, df.residual = if
(!is.null(w)) sum(w !=
                                               0) else if
(is.matrix(y)) nrow(y) else length(y))
        if (!is.null(offset)) {
            z$fitted.values <- offset
            z$residuals <- y - offset
        }
    }
    else {
        x <- model.matrix(mt, mf, contrasts)
        z <- if (is.null(w))
            lm.fit(x, y, offset = offset, singular.ok = singular.ok,
                   ...)
        else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok,
                     ...)
    }
    class(z) <- c(if (is.matrix(y)) 'mlm', 'lm')
    z$na.action <- attr(mf, 'na.action')
    z$offset <- offset
    z$contrasts <- attr(x, 'contrasts')
    z$xlevels <- .getXlevels(mt, mf)
    z$call <- cl
    z$terms <- mt
    if (model)
        z$model <- mf
    if (ret.x)
        z$x <- x
    if (ret.y)
        z$y <- y
    if (!qr)
        z$qr <- NULL
    z
}
str(iris)
")



> If this is a bug *with a fix* it would really make sense to be fixed
> "upstreams", no?

I gave a couple of ideas of how to modify the prompt regexp in the
original post.

A more radical approach would be to adopt the ess-tracebug method of checking
for process being busy is to check for ">" at the end of each output directly in
the proces-filter and mark the process variable 'ready accordingly. Please see
inferior-ess-dbg-output-filter, ess-command2 and ess-wait-for-process and in the
code.

Best,
Vitalie.



More information about the ESS-help mailing list