[R] [EXTERNAL] Re: unexpected 'else' in " else"

Jorgen Harmse JH@rm@e @end|ng |rom roku@com
Fri Oct 21 20:01:50 CEST 2022


Thank you. I knew it had nothing to do with the choice of environment, but I thought I had seen such unwrapped code working in files in a previous version. Maybe I misremembered. Incidentally, there is nothing special about braces: anything that makes the statement incomplete will do.

Regards,
Jorgen.


> evalq( if (FALSE)

  cat("This shouldn't happen.\n")

else

  cat("Everything is fine.\n"),

+ .GlobalEnv

+ )

Everything is fine.

> x <- 1:5

> x[ if(FALSE) 1L

+    else 2L

+  ]

[1] 2


From: Andrew Simmons <akwsimmo using gmail.com>
Date: Friday, 21October, 2022 at 11:20
To: Jorgen Harmse <JHarmse using roku.com>
Cc: r-help using r-project.org <r-help using r-project.org>
Subject: [EXTERNAL] Re: [R] unexpected 'else' in " else"
The code working inside stats::weighted.residuals has nothing to do
with being evaluated in a different environment than globalenv() and
has nothing to do with being inside a package.
The reason the code works inside stats::weighted.residuals is because
the function body is wrapped with braces. You can try it yourself:

local({
    FILE <- tempfile(fileext = ".R")
    on.exit(unlink(FILE, force = TRUE, expand = FALSE), add = TRUE,
after = FALSE)
    writeLines("if (TRUE) \n    'evaluating cons.expr'\nelse
'evaluating alt.expr'", FILE)
    writeLines(readLines(FILE))
    try(source(FILE, local = TRUE, echo = TRUE, verbose = FALSE))
})

If you try entering it as a function, it still fails:

local({
    FILE <- tempfile(fileext = ".R")
    on.exit(unlink(FILE, force = TRUE, expand = FALSE), add = TRUE,
after = FALSE)
    writeLines("function () \nif (TRUE) \n    'evaluating
cons.expr'\nelse 'evaluating alt.expr'", FILE)
    writeLines(readLines(FILE))
    try(source(FILE, local = TRUE, echo = TRUE, verbose = FALSE))
})

But R packages use sys.source() instead of source() to run R code, but
it still fails if you run it:

local({
    FILE <- tempfile(fileext = ".R")
    on.exit(unlink(FILE, force = TRUE, expand = FALSE), add = TRUE,
after = FALSE)
    writeLines("if (TRUE) \n    'evaluating cons.expr'\nelse
'evaluating alt.expr'", FILE)
    writeLines(readLines(FILE))
    try(sys.source(FILE, envir = environment()))
})

The part that matters is that the function body is wrapped with
braces. `if` statements inside braces or parenthesis (or possibly
brackets) will continue looking for `else` even after `cons.expr` and
a newline has been fully parsed, but will not otherwise.

On Fri, Oct 21, 2022 at 10:39 AM Jorgen Harmse via R-help
<r-help using r-project.org> wrote:
>
> Andrew Simmons is correct but doesn't explain why the code works in the package. This is one of only two differences I have found between running code at the command line and running it from a file. (The other difference is that code in a file is often executed in an environment other than .GlobalEnv. There is some related sugar around packages that usually makes things work the way a user would want.) At the command line, R executes code whenever RETURN could be interpreted as the end of a statement. "If(�.) �. RETURN" is ambiguous: will it be followed by "else", or is it a complete statement? If it's in a file or wrapped in a block or other structure that obviously hasn't ended yet then R will wait to see the next line of input, but if it could be a complete statement then not executing it would cause a lot of frustration for users. Once the statement is executed, R expects another statement, and no statement begins with "else". (Maybe the interpreter could be enhanced to keep the "if" open under some conditions, but I haven't thought it through. In particular, "if" without "else" is NULL if the condition is FALSE, so it might be necessary to undo an assignment, and that seems very difficult.)
>
> Regards,
> Jorgen Harmse.
>
>
> On Fri., Oct. 21, 2022, 05:29 Jinsong Zhao, <jszhao using yeah.net> wrote:
>
> > Hi there,
> >
> > The following code would cause R error:
> >
> >  > w <- 1:5
> >  > r <- 1:5
> >  >         if (is.matrix(r))
> > +             r[w != 0, , drop = FALSE]
> >  >         else r[w != 0]
> > Error: unexpected 'else' in "        else"
> >
> > However, the code:
> >          if (is.matrix(r))
> >              r[w != 0, , drop = FALSE]
> >          else r[w != 0]
> > is extracted from stats::weighted.residuals.
> >
> > My question is why the code in the function does not cause error?
> >
> > Best,
> > Jinsong
> >
> > ______________________________________________
> > R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide
> > http://www.R-project.org/posting-guide.html
> > and provide commented, minimal, self-contained, reproducible code.
> >
>
>         [[alternative HTML version deleted]]
>
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> R-help using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
>
> ------------------------------
>
> End of R-help Digest, Vol 236, Issue 19
> ***************************************
>
>         [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.

	[[alternative HTML version deleted]]



More information about the R-help mailing list