From Martin Maechler <maechler@stat.math.ethz.ch>  Wed Jan 22 10:41:02 2003
From: Martin Maechler <maechler@stat.math.ethz.ch> (Martin Maechler)
Date: Wed Jan 22 10:41:02 2003
Subject: [Rd] Methods package is now attached by default
In-Reply-To: <Pine.A41.4.44.0301211438000.144514-100000@homer07.u.washington.edu>
References: <Pine.GSO.4.10.10301211356280.15902-100000@quetelet.stat.ucla.edu>
 <Pine.A41.4.44.0301211438000.144514-100000@homer07.u.washington.edu>
Message-ID: <15918.26387.343935.156038@gargle.gargle.HOWL>

>>>>> "TL" == Thomas Lumley <tlumley@u.washington.edu>
>>>>>     on Tue, 21 Jan 2003 14:49:58 -0800 (PST) writes:

    TL> On Tue, 21 Jan 2003, Roger Peng wrote:
    >> I was looking at the examples in the `optim' help page
    >> and I think one of them does not quite work.  In
    >> particular, this example:

(Note to all readers : We are talking about "R-devel" (aka R-pre-pre-1.7.0)


    >> ## "wild" function , global minimum at about -15.81515 
    >> fw <- function (x) 10*sin(0.3*x)*sin(1.3*x^2) + 0.00001*x^4
    >> + 0.2*x+80 
    >> plot(fw, -50, 50, n=1000, main = "optim() minimising `wild function'")
    >> 
    >> While it executes, I think it produces the wrong plot.
    >> The call to plot indicates that it should be plotted from
    >> x values of -50 to 50 but the resulting plot goes from 0
    >> to 50.  However, if I call
    >> 
    >> plot.function(fw,-50,50, n=1000, main="optim() minimising ..")
    >> 
    >> then that plot appears to be correct.  I figured this had
    >> something to do with the method dispatching on functions.

    TL> Not quite, because it doesn't use method dispatching --
    TL> it calls plot.function explicitly.

   { yeah, but Roger is right "in spirit":  The reason it is called
     explicitly from the generic, is the fact that plot.function()'s
     arg.list doesn't match the generic at all... 
   }

    TL> I think it's a thinko in editing.  plot() went from

   plot<- function (x, ...)
   {
      if (is.null(attr(x, "class")) && is.function(x)) {
	  if ("ylab" %in% names(list(...)))
	      plot.function(x, ...)
	  else plot.function(x, ylab = paste(deparse(substitute(x)),
	      "(x)"), ...)
      }
      else UseMethod("plot")
   }

   TL> to

  plot<-function (x, y, ...)
  {
      if (is.null(attr(x, "class")) && is.function(x)) {
	  if ("ylab" %in% names(list(...)))
	      plot.function(x, ...)
	  else plot.function(x, ylab = paste(deparse(substitute(x)),
	      "(x)"), ...)
      }
      else UseMethod("plot")
  }

>> but the extra argument `y' never got passed down to plot.function. It
>> should be something like

  plot <- function (x, y, ...)
  {
      if (is.null(attr(x, "class")) && is.function(x)) {
	  if ("ylab" %in% names(list(...)))
	      plot.function(x,y, ...)
	  else plot.function(x, y, ylab = paste(deparse(substitute(x)),
	      "(x)"), ...)
      }
      else UseMethod("plot")
  }

----
Good idea  {been there, tried other stuff many months ago...}
but it doesn't solve the compatibility problem completely:

Try, e.g.,

plot(sin, 4, 6)
plot(sin, to = 10) ## old behavior would have plotted from 0 to 10

and I think John Chambers and/or I found out quite a while ago that
it's almost impossible to become really compatible to the old behavior
when you include the automatically generated `ylab' and consider 
named and positional arguments their defaults.

Since March 2002, I have the following 
in src/library/methods/R/plot.R
and I think found to work it (almost ? entirely?) correctly,
but had never committed it since I always found it was really an
ugly hack for a generic function definition:


## 2-argument (dispatching)
plot <- function (x, y, ...)
{
    if (is.null(attr(x, "class")) && is.function(x)) {
        nms <- names(list(...))
        ## need to pass `y' to plot.function() when positionally matched
        if(missing(y)) # set to defaults {could use formals(plot.default)}:
            y <- { if (!"from" %in% nms) 0 else
                   if (!"to"   %in% nms) 1 else
                   if (!"xlim" %in% nms) NULL }
        if ("ylab" %in% nms)
            plot.function(x,  y, ...)
        else plot.function(x, y,
                           ylab = paste(deparse(substitute(x)), "(x)"), ...)
    }
    else UseMethod("plot")
}

---

maybe I should commit this version to R-devel after all?

Martin Maechler <maechler@stat.math.ethz.ch>	http://stat.ethz.ch/~maechler/
Seminar fuer Statistik, ETH-Zentrum  LEO C16	Leonhardstr. 27
ETH (Federal Inst. Technology)	8092 Zurich	SWITZERLAND
phone: x-41-1-632-3408		fax: ...-1228			<><



[Rd] Methods package is now attached by default
Martin Maechler