20

I'm trying to make my code ask me for a "TRUE" or "FALSE" value before proceeding.

It currently works fine if I run it one line at a time, however when I run all the code at once in RStudio it simply proceeds without waiting for user input and records a value of "" for my parameter.

raw <- readline("TRUE or FALSE -- this is a validation run: ")


if (raw == "F" | raw == "FALSE" | raw == "False"){
validation <- F
} else{
  validation <- T
}
rm(raw)

Ideally, I would like an answer that works regardless of how I run it -- RScript, source within RStudio, or running it (i.e. selecting the code and pressing run or ctrl-enter).

7
  • you could check all the possibilities of f/F/false/False/FALSE/fasle/etc with if (toupper(unlist(strsplit(raw, ''))[1]) == 'F')
    – rawr
    Nov 24, 2014 at 19:27
  • 1
    Caution: readline is only for use in interactive mode.
    – IRTFM
    Nov 24, 2014 at 19:37
  • @BondedDust Ah, ok, so I need readLines then?
    – Hack-R
    Nov 24, 2014 at 19:42
  • 1
    readLines is not set up for a prompt. You need to describe how this will be used. Using Rscript is different than interactive use. You need to answer the first comment question. If you are "in RStudio", then most people would assume its for interactive console use. Just don't assume you can use it with Rscript or running from a system command line.
    – IRTFM
    Nov 24, 2014 at 19:49
  • @BondedDust Well, I am in RStudio now like I was saying, though I'd certainly like a solution that would be robust to any of those ways of running it. Is that impossible?
    – Hack-R
    Nov 24, 2014 at 19:53

4 Answers 4

26

If you want to do this in interactive mode then you already have answers but not for use with Rscript. For that instance you need to send messages to the console with cat:

If this test file is named 'prompt.r' and is in the directory where you are working in a system console session:

cat("a string please: ");
a <- readLines("stdin",n=1);
cat("You entered")
 str(a);
cat( "\n" )

Then you can run it from the command line as

$ Rscript prompt.r

If you want an all-purpose script then this would run your script under interactive conditions and my script for non-interactive ones:

if (interactive() ){raw <- 
             readline("TRUE or FALSE -- this is a validation run: ")

                if (raw == "F" | raw == "FALSE" | raw == "False"){
               validation <- F
                 } else{
                     validation <- T
                       }
           rm(raw)  } else{
#  non-interactive
cat("a string please: ");
a <- readLines("stdin",n=1);
cat("You entered")
 str(a);
cat( "\n" )}
3
  • Is there a better way to combine interactive mode and script mode?
    – jtianling
    Nov 1, 2017 at 9:32
  • An answer to a request for a "better" solution requires some sort of software metric that is currently not being expressed.
    – IRTFM
    Nov 1, 2017 at 19:03
  • 2
    Don't know what's you mean, at least, in python and ruby, you don't need to separate the two way.
    – jtianling
    Nov 2, 2017 at 2:16
17

Are you running the code by highlighting the lines and clicking run? If so, that could be your problem because R is line-by-line entering your code in the terminal.

Instead, write your script (or comment out the parts you're not testing) and click the source button. Then R waits for user response instead of inputting the line after readline() into readline().

I had the same problem as you, which prompted me to look for an answer. But then I tried this different method of executing the code and it worked.

1
  • This actually solved my problem, as long as the original code is being sourced, readLines() seems to stop and wait for user input. Feb 23, 2017 at 3:10
3

The reason why readline is "not waiting for input" is, according to the manual (?readline):

In non-interactive use the result is as if the response was RETURN and the value is "".

You have stumbled on one of the "surprising" features of R.

<rant> Why readline() works in "interactive mode" only is a complete mystery for me, since it's a perfectly acceptable use case to ask for user input from within a script. Python, for instance, gives you the input(prompt) function which you may invoke whenever you need it. </rant>

A relatively convenient way of getting around this mess is to define a function ("Every programming problem can be solved by yet another level of indirection"...):

user.input <- function(prompt) {
  if (interactive()) {
    return(readline(prompt))
  } else {
    cat(prompt)
    return(readLines("stdin", n=1))
  }
}

A positive side-effect is that you can add all sorts of nice input validation in user.input(). But I doubt that that was the intention behind the bizarre behaviour of readline().

1

Although it requires interactive mode, I found the askYesNo() function within the utils package to provide a nice, simple user interface for TRUE/FALSE (or more accurately Yes/No) questions. For example, the following code would produce the following dialog.

Yes No Dialog

  • Yes returns TRUE
  • No returns FALSE
  • Cancel returns NA

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.