Skip to content

Commit

Permalink
Fix manual entry for new namespaced evaluation
Browse files Browse the repository at this point in the history
  • Loading branch information
vspinu committed Jul 23, 2016
1 parent e0e3163 commit 5141f42
Showing 1 changed file with 32 additions and 140 deletions.
172 changes: 32 additions & 140 deletions doc/ess.texi
Original file line number Diff line number Diff line change
Expand Up @@ -2523,7 +2523,7 @@ packages:
@menu
* ESS tracebug:: Visual debugging, breakpoints, tracing, watch etc.
* Editing documentation:: Tools to edit R documentation
* ESS developer:: Develop your packages on the fly
* Namespaced Evaluation:: Develop your packages on the fly
@end menu

@node ESS tracebug
Expand Down Expand Up @@ -2866,152 +2866,44 @@ the Roxygen start string.
string.
@end table

@node ESS developer
@section ESS developer
@node Namespaced Evaluation
@section Namespaced Evaluation
@cindex ess developer

Usual ESS evaluation commands, @xref{Evaluating code}, send portions of
the current buffer for the evaluation in the current environment
(usually @code{R_GlobalEnv}). Often, when developing packages with
namespaces, it is necessary to evaluate code directly in the package's
environment or its namespace. The @code{ess-developer} utility provides
such a functionality with minimal disruption of the usual ESS work-flow.

To understand how ess-developer works you must be familiar with
namespace system in R. In a nutshell, all objects defined in a package
'foo' are stored in an environment called 'namespace:foo'. Parent
environment of 'namespace:foo' is an environment 'imports:foo' which
contains copies of all objects from other packages which 'foo'
imports. Parent environment of 'imports:foo' is the
'namespace:base'. Parent environment of 'namespace:base' is
.GlobalEnv. Thus functions and methods stored in 'namespace:foo' see all
the objects in .GlobalEnv unless shadowed by objects in 'imports:foo',
'namespace:base', or 'namespace:foo' itself. There is another
environment associated with 'foo' - 'package:foo'. This environment
stores *copies* of exported objects from 'namespace:foo' and is placed
on the search() path, i.e. if 'foo' is loaded and if you start with
.GlobalEnv and iteratively call parent.env() you will get eventually to
'package:foo'. Thus all methods and functions defined in .GlobalEnv can
"see" objects in 'package:foo' environment. See also
In non package files evaluation commands (@xref{Evaluating code}) send
portions of the current buffer environment (@code{R_GlobalEnv}. When
developing packages, ESS sends code to the corresponding package
namespace and (for visible objects) into package environment (visible on
search path). All objects that are assigned are displayed in the
minibuffer alongside the environment in which they are assigned.

Here is a short overview of how namespace and package environments work
in R. All objects defined in a package 'foo' are stored in an
environment called 'namespace:foo'. Parent environment of
'namespace:foo' is an environment 'imports:foo' which contains copies of
all objects from other packages which 'foo' imports. Parent environment
of 'imports:foo' is the 'namespace:base'. Parent environment of
'namespace:base' is .GlobalEnv. Thus functions and methods stored in
'namespace:foo' see all the objects in .GlobalEnv unless shadowed by
objects in 'imports:foo', 'namespace:base', or 'namespace:foo'
itself. There is another environment associated with 'foo' -
'package:foo'. This environment stores *copies* of exported objects from
'namespace:foo' and is placed on the search() path, i.e. if 'foo' is
loaded and if you start with .GlobalEnv and iteratively call
parent.env() you will get eventually to 'package:foo'. Thus all methods
and functions defined in .GlobalEnv can "see" objects in 'package:foo'
environment. See also
@uref{http://cran.r-project.org/doc/manuals/R-ints.html#Namespaces}.

In order to use ess-developer you must add names of the packages that
you are developing to @code{ess-developer-packages}. You can also do
that interactively with @kbd{C-c C-t C-a}. To remove packages from
@code{ess-developer-packages} use @kbd{C-c C-t C-r}. When developer mode
is on, the process mode line indicator displays a small or capital
letter "d".

If variable @code{ess-developer-activate-in-package} is @code{t} (the
default) @code{R-mode} will check after visiting the file whether or not
the file is part of the package. If visited file is part of a package
listed in @code{ess-developer-packages}, developer mode is activated
automatically.

Developer mode is usually activated on per-file basis and a small "d"
appears in the modeline. You can also activate ess-developer for all
buffers connected to current process. This is done by toggling
@code{ess-developer} in subprocess buffer. In this case a big "D" will
appear in the modeline.

@deffn Command ess-developer @var{val}
@kindex C-c C-t C-t
@kbd{C-c C-t C-t} Toggle developer mode on and off. If called from
script buffer, toggle developer on file-by-file basis. When called from
process buffer, toggle developer on per-process basis.
@end deffn

@deffn Command ess-developer-add-package @var{from-attached} @var{remove}
@kindex C-c C-t C-a
@kbd{C-c C-t C-a} Add a package to your development list (@code{ess-developer-packages}).
@end deffn
Ocasionally you want to evaluate into a package from a non-package file,
or the other way around, evaluate into @code{GlobalEnv} from inside a
package. In such cases @kbd{C-c C-t C-s} is your friend.

@deffn Command ess-developer-remove-package
@kindex C-c C-t C-r
@kbd{C-c C-t C-r} Remove a package from your development list.
@deffn Command ess-r-set-evaluation-env @var{arg}
@kindex C-c C-t C-s
@kbd{C-c C-t C-s} Set or unset the current evaluation environment (a package).
@end deffn

When you add a package to @code{ess-developer-packages}, ESS will ask
for loading command. By default there are two options @code{library} and
@code{load_all} from @code{devtools} package. You can configure this
behavior in @code{ess-developer-load-on-add-commands}. To explicitly
load the package containing current file use @kbd{C-c C-t l}.

@deffn Command ess-developer-load-package
@kindex C-c C-t l
@kbd{C-c C-t l} Load package with @code{load_all} utility from
@code{devtools} package.
@end deffn

When developer mode is on, ESS evaluation commands behave differently:

@itemize @bullet

@item @kbd{C-c C-l} (@code{ess-load-file}) asks for the package to source
into and inserts all redefined objects into the package:foo or
namespace:foo accordingly.

@itemize @minus

@item PLAIN OBJECTS and FUNCTIONS: @*
If the object is found in an environment (package:foo or
namespace:foo), and differs from the old one it is assigned into the
corresponding environment. If the object is not found it is assigned
into .GlobalEnv. The environment of functions is set to namespace:foo.

@item CLASSES: @*
Same as plain objects, with the difference that even if the class
definition is assigned into .GlobalEnv, it is still associated with the
package foo. Thus if you issue getClassDeff("foo") you will get a class
definition with the slot @@package pointing to package "foo".

@emph{Note:} Occasionally, after adding new classes you might get warnings
from "setClass". This is especially true if new class inherits or is
inherited by a class whose definition is not exported. You might get
something like:
@code{
Warning: Class "boo" is defined (with package slot ‘foo’) but no
metadata object found to revise subclass information---not exported?
}

You can safely ignore this warnings.

@item S4 METHODS: @*
Similarly to function definitions modified methods are assigned in the
local method table in the namespace:foo. New methods are assigned into
.GlobalEnv, but with the environment pointing to namespace:foo. There is
a subtle catch with method caching in R though. See the code in
etc/ESSR/developer.R for more details.

@c Note that if method or generic is exported the *same* table (which is an
@c environment) is present in package:foo.


@item S3 METHODS: @*
S3 methods are not automatically registered. You can register them
manually after you have inserted method_name.my_class into your package
environment using ess-developer, like follows:

registerS3method("method_name", "my_class", my_package:::method_name.my_class)

If you don't register your S3 method, R will call the registered (aka
cached) S3 method instead of the new method that ess-developer inserted
in the package environment.

@end itemize

@item @kbd{C-c C-r}(@code{ess-eval-region}) and functions that depend on
it (@code{ess-eval-paragraph}, @code{ess-eval-buffer} etc.), behave as
@code{ess-load-file}, but restrict the evaluation to the corresponding region.

@item @kbd{C-c C-f} (@code{ess-eval-function}) and friends check if the
current function's name can be found in a namespace:foo or package:foo
for a 'foo' from `ess-developer-packages'. If found, and new function
definition differs from the old one, the function is assigned into that
namespace. If not found, it is assigned into .GlobalEnv.
@end itemize


@node Extras
@chapter Other ESS features and tools

Expand Down

0 comments on commit 5141f42

Please sign in to comment.