1

Disclaimer: I am pushing R to its technical limits here, for fun and profit.

The :: operator is, well, an operator. It's defined as

> `::`
function (pkg, name)  
{
  pkg <- as.character(substitute(pkg))
  name <- as.character(substitute(name))
  getExportedValue(pkg, name)
}

Which means that a::b is equivalent to `::`(a, b).

For this reason, a::b::c should be equivalent to `::`(a, `::`(b, c)), or `::`(`::`(a, b), c) depending on precedence rules, exactly as the `+` operator.

Nevertheless, it seems not to work:

> a::b::c
Error: unexpected '::' in "a::b::"

Of course there's a substitute in the middle, which complicates things, but it seems more like a parsing error. I also tried with using parentheses, such as (a::b)::c, but it still does not work.

I don't see why, considering that a::b::c should not be different from a + b + c when it comes to parsing.

Is the :: operator treated differently by the parser? If yes, why?

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
  • 2
    I agree that a syntax error is surprising rather than some other error. But is there a valid use-case where `a::b::c` should **not** be an error? – Gregor Thomas Jul 10 '23 at 14:57
  • @GregorThomas pushing the language beyond its arbitrary limitations? – Stefano Borini Jul 10 '23 at 14:58
  • 2
    That doesn't answer the question. Can you give an example of `a`, `b`, and `c` where `a::b::c` might be expected to "work"? "Work" as in not give an error, but some sort of result? And what result would you expect? – Gregor Thomas Jul 10 '23 at 14:59
  • Yes, it's treated differently by the parser. You can see it around https://github.com/wch/r-source/blob/688f12cc9627c38ae10c4f597010da3f7142a487/src/main/gram.y#L504 It only expects a symbol after the operator, not a general expression. Thus you can't "stack" them. – MrFlick Jul 10 '23 at 15:01
  • a b and c are namespaces. When you create a package mypkg, you are defining an implicit namespace called with the name of the package itself: mypkg, and populate that namespace with the exported symbols from your module code. However, this is an arbitrary limitation, and I am trying to break that. I want to be able to override the :: operator to enable subpackage namespaces. – Stefano Borini Jul 10 '23 at 15:01
  • 2
    When I run `::`, I obtain `function (pkg, name) .Primitive("::")` and not what you showed in the question. What am I missing? – B. Christian Kamgang Jul 10 '23 at 15:02
  • @MrFlick thanks. Do you know if they are planning to extend this limitation to the grammar? Do they have a PEP-like process to propose enhancements to the language? – Stefano Borini Jul 10 '23 at 15:02
  • 1
    @B.ChristianKamgang Most likely the OP is using an older version of R. In more recent versions it was re-written to be a primitive function like you show for performance reasons. – MrFlick Jul 10 '23 at 15:02
  • 4
    The `r-devel` mailing list is probably the best place to initiate a conversation about a change to the parser. [You can read the answers here for quite a bit of discussion about the process](https://stackoverflow.com/q/8065835/903061). You won't see much there to encourage you - the R-Core team is very conservative about making changes to base R; I doubt they will see "pushing past arbitrary limitations" as a compelling reason. I'd suggest being prepared to make a case with examples of useful capabilities that are not possible through other methods. – Gregor Thomas Jul 10 '23 at 15:11
  • 1
    I'm not certain I see the immediate utility of "subpackage namespaces". Can you explain what functionality that adds over R's regular namespace and search path management? – r2evans Jul 10 '23 at 15:37
  • @r2evans the fact that every other language in the world has it? – Stefano Borini Jul 13 '23 at 12:10
  • Jokes about cliffs and lemmings and such ... seriously, I'm not criticizing the concept, I'm trying to find the utility in a sense that R will benefit from. For instance, is the first step to having R support different versions of the same package? That is, namespace A is using dplyr-1.0 whereas namespace B is using dplyr-1.1? (Obviously this is not _easily_ done with R, lots of complications.) This notion is not a goal in and of itself, I suspect you're going for specific behavior that only subpackage namespacing can support. – r2evans Jul 13 '23 at 12:44
  • @r2evans cliffs and lemmings only apply when the language this is coming from doesn't suck. That said, there are many reasons why subpackages are useful. E.g. I could separate different algorithms according to subtypes, or in shiny I could separate reactive functions under shiny::reactives::reactiveValues etc vs shiny::widgets::numericInput. Logical namespacing has always been part of any languages. Assuming you can cram everything in one namespace is delusional, especially when your package becomes large. Clearly, if you only write three functions in your package, you are unlikely to need it. – Stefano Borini Jul 14 '23 at 14:51
  • Okay, I see where we were talking in circles. My notion was keeping a "package as a namespace", so subnesting namespaces to me was only about nesting packages. Your notion is to nest _portions_ of a package/namespace, so that for instance one could import only a portion of a Package. We have the ability to do something like `import(stats, except=c(filter, lag))`, but not a better mechanism for batches/categories of functions. Clear goal, I too wish it were possible. Thanks for the discussion ... and this would very much need to go on R-core to have any hope of implementation. – r2evans Jul 14 '23 at 16:33
  • 1
    (FYI, I assume you're mostly kidding with your *"doesn't suck"* comment. R is old, it is certainly krufty and full of inconsistencies, but stone-throwing like that should normally come with a smiley or some softening comment.) – r2evans Jul 14 '23 at 16:36
  • @r2evans python is equally old (actually older), but this doesn't mean it hasn't evolved. R certainly has evolved, but some things by now should be standard. R is poorly designed for scalability, but the modern needs are of a language that can scale. The consequences of this obtuse approach is to give people a language that is being used to determine if medicines, genetics, economics, and other critical data analysis tasks with code that is not meant to scale at that size. It is a duty of the R core team to provide a language that can scale and ensure quality of the produced code. – Stefano Borini Jul 25 '23 at 14:53
  • @StefanoBorini, while R itself came later, its design was clearly to clone S, which started on the 70s, well before python, so the architecture of R predates python. Admittedly, though, that debate is a red herring: it's been decades for both, and I agree that updates are not really meeting "modern computing needs". – r2evans Jul 25 '23 at 17:35

0 Answers0