Note that there are some explanatory texts on larger screens.

plurals
  1. POAttaching a temporary namespace to the search path
    primarykey
    data
    text
    <p>This question is sort of a follow up to this <a href="https://stackoverflow.com/questions/10947159/writing-robust-r-code-namespaces-masking-and-using-the-operator">post</a> as I'm still not fully convinced that, with respect to code robustness, it wouldn't be far better to make typing <code>namespace::foo()</code> habit instead of just typing <code>foo()</code> and praying you get the desired result ;-)</p> <h2>Actual question</h2> <p>I'm aware that this goes heavily against "standard R conventions", but let's just say I'm curious ;-) <strong>Is it possible to attach a temporary namespace to the search path somehow?</strong></p> <hr> <h2>Motivation</h2> <p>At a point where my package <code>mypkg</code> is still in "<em>devel stage</em>" (i.e. <strong>not a true R package yet</strong>):</p> <ul> <li>I'd like to source my functions into an environment <code>mypkg</code> instead of <code>.GlobalEnv</code></li> <li>then attach <code>mypkg</code> to the search path (as a true namespace if possible) </li> <li>in order to be able to call <code>mypkg::foo()</code> </li> </ul> <p>I'm perfectly aware that calling <code>::</code> has its downsides (it takes longer than simply typing a function's name and letting R handle the lookup implicitly) and/or might not be considered necessary due to the way <strong>a)</strong> R scans through the search path and <strong>b)</strong> packages may import their dependencies (i.e. using "Imports" instead of "Depends", not exporting certain functions etc). But I've seen my code crash at least twice due to the fact that some package has overwritten certain (base) functions, so I went from "blind trust" to "better-to-be-safe-than-sorry" mode ;-)</p> <h2>What I tried</h2> <p>AFAIU, namespaces are in principle nothing more than some special kind of environment</p> <pre><code>&gt; search() [1] ".GlobalEnv" "package:stats" "package:graphics" [4] "package:grDevices" "package:utils" "package:datasets" [7] "package:methods" "Autoloads" "package:base" &gt; asNamespace("base") &lt;environment: namespace:base&gt; </code></pre> <p>And there's the <code>attach()</code> function that attaches objects to the search path. So here's what I thought:</p> <pre><code>temp.namespace &lt;- new.env(parent=emptyenv()) attach(temp.namespace) &gt; asNamespace("temp.namespace") Error in loadNamespace(name) : there is no package called 'temp.namespace' </code></pre> <p>I guess I somehow have to work with <code>attachNamepace()</code> and figure out what this expects before it is called in in <code>library()</code>. Any ideas?</p> <hr> <h2>EDIT</h2> <p>With respect to Hadley's comment: I actually wouldn't care whether the attached environment is a full-grown namespace or just an ordinary environment as long as I could extend <code>::</code> <strong>while keeping the "syntactic sugering" feature</strong> (i.e. being able to call <code>pkg::foo()</code> instead of <code>"::"(pkg="pkg", name="foo")()</code>).</p> <p>This is how function <code>"::"</code> looks like:</p> <pre><code>&gt; get("::") function (pkg, name) { pkg &lt;- as.character(substitute(pkg)) name &lt;- as.character(substitute(name)) getExportedValue(pkg, name) } </code></pre> <p>This is what it should also be able to do in case R detects that <code>pkg</code> is in fact <strong>not</strong> a namespace but just some environment attached to the search path:</p> <pre><code>"::*" &lt;- function (pkg, name) { pkg &lt;- as.character(substitute(pkg)) name &lt;- as.character(substitute(name)) paths &lt;- search() if (!pkg %in% paths) stop(paste("Invalid namespace environment:", pkg)) pos &lt;- which(paths == pkg) if (length(pos) &gt; 1) stop(paste("Multiple attached envirs:", pkg)) get(x=name, pos=pos) } </code></pre> <p>It works, but there's no syntactic sugaring:</p> <pre><code>&gt; "::*"(pkg="tempspace", name="foo") function(x, y) x + y &gt; "::*"(pkg="tempspace", name="foo")(x=1, y=2) [1] 3 </code></pre> <p>How would I be able to call <code>pkg::*foo(x=1, y=2)</code> (disregarding the fact that <code>::*</code> is a really bad name for a function ;-))?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload