Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

Juan Telleria Ruiz de Aguirre
Dear R Developers,

###
# Context:
###

When managing Search Path Conflicts (See:
https://developer.r-project.org/Blog/public/2019/03/19/managing-search-path-conflicts/index.html),
with:

options(conflicts.policy = "strict")

We get the following behaviour when loading a package (Eg: dplyr):

library(dplyr)
## Error: Conflicts attaching package ‘dplyr’:
##
## The following objects are masked from ‘package:stats’:
##
##     filter, lag
##
## The following objects are masked from ‘package:base’:
##
##     intersect, setdiff, setequal, union

So we would have to solve the conflict by writing:

library(dplyr,
        mask.ok = c("filter", "lag",
                    "intersect", "setdiff", "setequal",
                    "union"))

So my feature request proposals:

###
# Feature Request 1: Interactive Session
###

Would it be possible to raise an input prompt, which asks user for an
action to be taken as regards conflicts?

This would make the package loading process more dynamic when being
loaded for first time in an interactive session (Eg: R Notebook). An
example:

The first time the package is loaded:

options(conflicts.policy = "strict", conflicts.policy.ask = TRUE)

library(dplyr)

Executes iteratively the code, in order to ask the user for action
(See toy example):

opt <- readline(prompt="1: mask.ok; 2: exclude. Choose: ")

if (opt == "1"){

  txt <- sprintf(
    fmt = "conflictRules(pkg = '%s' , mask.ok = '%s')",
    "package.name",
    "variable.name"
  )

  eval(parse(text = txt))

  message(txt)

} else if(opt == "2"){

  txt <- sprintf(
    fmt = "conflictRules(pkg = '%s' , exclude = '%s')",
    "package.name",
    "variable.name"
  )

  eval(parse(text = txt))

  message(txt)

}

And afterwards, a message is printed with the selected
"conflictRules()" Configuration for the dynamic setup.

The user will only have to put the printed pre-configured
"conflictRules()" setup into his code, and when re-executing, the
input prompt asking for action will not be raised back again.

Such behaviour is similar in spirit to how 'conflicted' R package
works, which prints for example, for dplyr::filter :

Error: [conflicted] `filter` found in 2 packages.
Either pick the one you want with `::`
* dplyr::filter
* stats::filter
Or declare a preference with `conflict_prefer()`
* conflict_prefer("filter", "dplyr")
* conflict_prefer("filter", "stats")

Where the user will only have to copy "conflict_prefer("filter",
"dplyr")" and paste it into his script. The difference, is that with:
options(conflicts.policy = "strict", conflicts.policy.ask = TRUE),
such message is printed at package load.

I would put the required code within the library() function with the
following conditional:
...
if (length(conflicts)) {
   if(getOption("conflicts.policy.ask") == TRUE){
      ...
   }
}
...

###
# Feature Request 2: Source Execution
###

Another alternative, which could apply when executing the .R file from
source, would be to suggest the user a default conflictRules() setup:

options(conflicts.policy = "strict")
library(dplyr)

# Error: Conflicts attaching package ‘dplyr’:
#
# The following objects are masked from ‘package:stats’:
#
#     filter, lag
#
# The following objects are masked from ‘package:base’:
#
#     intersect, setdiff, setequal, union
#
# Declare preference with `conflictRules()` before loading:
#     * conflictRules("dplyr", mask.ok = list(stats = TRUE, base = TRUE))
#     * conflictRules("dplyr", mask.ok = list(stats = c("filter",
"lag"), base = c("intersect", "setdiff", "setequal", "union")))
#     * conflictRules("dplyr", exclude = c("filter", "lag",
"intersect", "setdiff", "setequal", "union"))

In this case, the error message would have to be extended with
sensible suggested defaults.

Thanks,
Juan

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

luke-tierney
You can get what you are asking for now in R 4.0.0 with
globalCallingHandlers and using the packageConflictError object that
is signaled. This should get you started:

```
options(conflicts.policy = "strict")

packageConflictError

handle_conflicts <- function(e) {
     cat(conditionMessage(e))
     opt <- readline(prompt="1: mask.ok; 2: exclude. Choose: ")
     if (opt == "1")
         conflictRules(e$package, mask.ok = as.character(unlist(e$conflicts)))
     else if (opt == "2")
         conflictRules(e$package, exclude = as.character(unlist(e$conflicts)))
     stop("unresolved conflicts") ## ideal invode a restart here
}

globalCallingHandlers(packageConflictError = handle_conflicts)

library(dplyr)
```

An IDE could provide a more sophisticated interface, like a dialog
allowing separate choices for each conflict. But this is best left up
to the IDE or the user.

The one addition to library that might be worth considering is to
provide a restart for the handler to invoke.

Best,

luke

On Wed, 20 May 2020, Juan Telleria Ruiz de Aguirre wrote:

> Dear R Developers,
>
> ###
> # Context:
> ###
>
> When managing Search Path Conflicts (See:
> https://developer.r-project.org/Blog/public/2019/03/19/managing-search-path-conflicts/index.html),
> with:
>
> options(conflicts.policy = "strict")
>
> We get the following behaviour when loading a package (Eg: dplyr):
>
> library(dplyr)
> ## Error: Conflicts attaching package ‘dplyr’:
> ##
> ## The following objects are masked from ‘package:stats’:
> ##
> ##     filter, lag
> ##
> ## The following objects are masked from ‘package:base’:
> ##
> ##     intersect, setdiff, setequal, union
>
> So we would have to solve the conflict by writing:
>
> library(dplyr,
>        mask.ok = c("filter", "lag",
>                    "intersect", "setdiff", "setequal",
>                    "union"))
>
> So my feature request proposals:
>
> ###
> # Feature Request 1: Interactive Session
> ###
>
> Would it be possible to raise an input prompt, which asks user for an
> action to be taken as regards conflicts?
>
> This would make the package loading process more dynamic when being
> loaded for first time in an interactive session (Eg: R Notebook). An
> example:
>
> The first time the package is loaded:
>
> options(conflicts.policy = "strict", conflicts.policy.ask = TRUE)
>
> library(dplyr)
>
> Executes iteratively the code, in order to ask the user for action
> (See toy example):
>
> opt <- readline(prompt="1: mask.ok; 2: exclude. Choose: ")
>
> if (opt == "1"){
>
>  txt <- sprintf(
>    fmt = "conflictRules(pkg = '%s' , mask.ok = '%s')",
>    "package.name",
>    "variable.name"
>  )
>
>  eval(parse(text = txt))
>
>  message(txt)
>
> } else if(opt == "2"){
>
>  txt <- sprintf(
>    fmt = "conflictRules(pkg = '%s' , exclude = '%s')",
>    "package.name",
>    "variable.name"
>  )
>
>  eval(parse(text = txt))
>
>  message(txt)
>
> }
>
> And afterwards, a message is printed with the selected
> "conflictRules()" Configuration for the dynamic setup.
>
> The user will only have to put the printed pre-configured
> "conflictRules()" setup into his code, and when re-executing, the
> input prompt asking for action will not be raised back again.
>
> Such behaviour is similar in spirit to how 'conflicted' R package
> works, which prints for example, for dplyr::filter :
>
> Error: [conflicted] `filter` found in 2 packages.
> Either pick the one you want with `::`
> * dplyr::filter
> * stats::filter
> Or declare a preference with `conflict_prefer()`
> * conflict_prefer("filter", "dplyr")
> * conflict_prefer("filter", "stats")
>
> Where the user will only have to copy "conflict_prefer("filter",
> "dplyr")" and paste it into his script. The difference, is that with:
> options(conflicts.policy = "strict", conflicts.policy.ask = TRUE),
> such message is printed at package load.
>
> I would put the required code within the library() function with the
> following conditional:
> ...
> if (length(conflicts)) {
>   if(getOption("conflicts.policy.ask") == TRUE){
>      ...
>   }
> }
> ...
>
> ###
> # Feature Request 2: Source Execution
> ###
>
> Another alternative, which could apply when executing the .R file from
> source, would be to suggest the user a default conflictRules() setup:
>
> options(conflicts.policy = "strict")
> library(dplyr)
>
> # Error: Conflicts attaching package ‘dplyr’:
> #
> # The following objects are masked from ‘package:stats’:
> #
> #     filter, lag
> #
> # The following objects are masked from ‘package:base’:
> #
> #     intersect, setdiff, setequal, union
> #
> # Declare preference with `conflictRules()` before loading:
> #     * conflictRules("dplyr", mask.ok = list(stats = TRUE, base = TRUE))
> #     * conflictRules("dplyr", mask.ok = list(stats = c("filter",
> "lag"), base = c("intersect", "setdiff", "setequal", "union")))
> #     * conflictRules("dplyr", exclude = c("filter", "lag",
> "intersect", "setdiff", "setequal", "union"))
>
> In this case, the error message would have to be extended with
> sensible suggested defaults.
>
> Thanks,
> Juan
>
> ______________________________________________
> [hidden email] mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu
______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

Abby Spurdle
> An IDE could provide a more sophisticated interface, like a dialog
> allowing separate choices for each conflict. But this is best left up
> to the IDE or the user.

An IDE (or other user interface) should not alter the behavior of R,
especially the installing/loading/attaching of packages.

There are some possible exceptions:
(1) The global option for width.
(2) Output that would normally appear in a separate window.
(3) Maybe others...

But only as non-defaults, with consent from the user.
Also, while exception (2) may have an intuitive appeal, it's risky business...

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

luke-tierney
Providing a way to more easily resolve situations that otherwise would
be errors is a reasonable thing for an IDE to do. I would prefer is
such things were optional and off by default, but other way not.

If an IDE does this and you don't approve then you don't have to use
it.

Best,

luke

On Wed, 20 May 2020, Abby Spurdle wrote:

>> An IDE could provide a more sophisticated interface, like a dialog
>> allowing separate choices for each conflict. But this is best left up
>> to the IDE or the user.
>
> An IDE (or other user interface) should not alter the behavior of R,
> especially the installing/loading/attaching of packages.
>
> There are some possible exceptions:
> (1) The global option for width.
> (2) Output that would normally appear in a separate window.
> (3) Maybe others...
>
> But only as non-defaults, with consent from the user.
> Also, while exception (2) may have an intuitive appeal, it's risky business...
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

Abby Spurdle
On Thu, May 21, 2020 at 10:37 AM <[hidden email]> wrote:
> Providing a way to more easily resolve situations that otherwise would
> be errors is a reasonable thing for an IDE to do.

In principle, yes.
However, I note that the word "easily" could mean different things to
different people.
Certain IDE* (not naming any names, and not distinguishing between
singular/plural), introduce bugs and other problems, by altering R's
behavior.

Also, if they absolutely must change things, perhaps the first thing
they should change is the error messages:

    I'm sorry, this program didn't work.
    It could be R's fault, but probably is the IDE's fault.
    Please do NOT post a message on R-help saying:
        Why did R crash?
    Without first running your code via a terminal.

> I would prefer is
> such things were optional and off by default, but other way not.

That's good to hear.

> If an IDE does this and you don't approve then you don't have to use
> it.

Yes.
And please let statistics and data science students know that.

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

Juan Telleria Ruiz de Aguirre
In reply to this post by luke-tierney
Thank you Mr. Tierney!

Using globalCallingHandlers() to directly handle
"packageConflictError" is an excellent idea!

The benefits I see for such an implementation are:
* The patch would be contained within the Conflict Error Handler,
which should reduce any side effects with an eventual implementation.
* And by making its usage optional, by setting for example
options(conflicts.policy.ask = TRUE), in should neither affect any
packages nor other base code.

Hope it allows R Users to work in a more agile manner, and guide R
Students through best practices of variable conflict handling in an
educative manner.

Thanks,
Juan

> You can get what you are asking for now in R 4.0.0 with
> globalCallingHandlers and using the packageConflictError object that
> is signaled. This should get you started:
>
> ```
> options(conflicts.policy = "strict")
>
> packageConflictError
>
> handle_conflicts <- function(e) {
>      cat(conditionMessage(e))
>      opt <- readline(prompt="1: mask.ok; 2: exclude. Choose: ")
>      if (opt == "1")
>          conflictRules(e$package, mask.ok = as.character(unlist(e$conflicts)))
>      else if (opt == "2")
>          conflictRules(e$package, exclude = as.character(unlist(e$conflicts)))
>      stop("unresolved conflicts") ## ideal invode a restart here
> }
>
> globalCallingHandlers(packageConflictError = handle_conflicts)
>
> library(dplyr)
> ```
>
> An IDE could provide a more sophisticated interface, like a dialog
> allowing separate choices for each conflict. But this is best left up
> to the IDE or the user.
>
> The one addition to library that might be worth considering is to
> provide a restart for the handler to invoke.
>
> Best,
>
> luke
>

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

luke-tierney
I looks like you may have misunderstood my post so just to make sure:
There will be no patch to R to support this.

If this is something you want for yourself, then I have shown you how
you can do it.  You can put the code in a startup file if you like.

If you want your students to have this, then you can prepare a startup
file for them that does this.

Best,

luke

On Thu, 21 May 2020, Juan Telleria Ruiz de Aguirre wrote:

> Thank you Mr. Tierney!
>
> Using globalCallingHandlers() to directly handle
> "packageConflictError" is an excellent idea!
>
> The benefits I see for such an implementation are:
> * The patch would be contained within the Conflict Error Handler,
> which should reduce any side effects with an eventual implementation.
> * And by making its usage optional, by setting for example
> options(conflicts.policy.ask = TRUE), in should neither affect any
> packages nor other base code.
>
> Hope it allows R Users to work in a more agile manner, and guide R
> Students through best practices of variable conflict handling in an
> educative manner.
>
> Thanks,
> Juan
>
>> You can get what you are asking for now in R 4.0.0 with
>> globalCallingHandlers and using the packageConflictError object that
>> is signaled. This should get you started:
>>
>> ```
>> options(conflicts.policy = "strict")
>>
>> packageConflictError
>>
>> handle_conflicts <- function(e) {
>>      cat(conditionMessage(e))
>>      opt <- readline(prompt="1: mask.ok; 2: exclude. Choose: ")
>>      if (opt == "1")
>>          conflictRules(e$package, mask.ok = as.character(unlist(e$conflicts)))
>>      else if (opt == "2")
>>          conflictRules(e$package, exclude = as.character(unlist(e$conflicts)))
>>      stop("unresolved conflicts") ## ideal invode a restart here
>> }
>>
>> globalCallingHandlers(packageConflictError = handle_conflicts)
>>
>> library(dplyr)
>> ```
>>
>> An IDE could provide a more sophisticated interface, like a dialog
>> allowing separate choices for each conflict. But this is best left up
>> to the IDE or the user.
>>
>> The one addition to library that might be worth considering is to
>> provide a restart for the handler to invoke.
>>
>> Best,
>>
>> luke
>>
>

--
Luke Tierney
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:   [hidden email]
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel
Reply | Threaded
Open this post in threaded view
|

Re: [External] Feature Request: User Prompt + Message First Execution when "Managing Search Path Conflicts"

Juan Telleria Ruiz de Aguirre
Got it, thank you for pointing out the solution then.

Best,
Juan

______________________________________________
[hidden email] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel