r-spatial/sf

Big bang (`!!!`) operator use

vincenzocoia opened this issue · 3 comments

Hello, I'd like to use the big bang (!!!) operator with the function st_sf() as a way of adding features to a spatial object, and thought others might, too. Normally, the rlang::exec() function is a nice workaround, but this gives undesirable results. See below for my use case, a demo of the problem, and a proposed solution. I'm happy to submit a pull request if that's preferable.

Why

The big bang would be useful for the function I'm writing, where features are input as a list (the ... is being used for something else).

Reproducible example of the issue

library(sf)
#> Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE

Make a sfc object

library(rlang)
x <- st_sfc(st_point(c(0, 1)))

Add features the usual way

st_sf(x, a = 1, b = 2)
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1
#> CRS:           NA
#>   a b           x
#> 1 1 2 POINT (0 1)

Add features with the big bang: doesn't work.

f <- list(a = 1, b = 2)
try(st_sf(x, !!!f))
#> Error in !f : invalid argument type

Use rlang's exec() to allow the big bang: attributes have awful names

exec("st_sf", x, !!!f)
#> Simple feature collection with 1 feature and 2 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1
#> CRS:           NA
#>   a b
#> 1 1 2
#>   c..structure.list.structure.c.0..1...class...c...XY......POINT......sfg...........class...c...sfc_POINT......sfc.....precision...0..bbox...structure.c.xmin...0......ymin...1..xmax...0..ymax...1...class.....bbox.....crs...structure.list.........input. ...
#> 1                                                                                                                                                                                                                                                    POINT (0 1)

Created on 2024-07-10 with reprex v2.1.0

Proposed Solution

You could change the first line of the source of st_sf from

x <- list(...)

to

x <- rlang::list2(...)

You could even keep rlang under Suggests with a bit more code.

These are not features, rows, but fields, columns. rlang syntax is superfluous for most users.

The cost of this would be to elevate rlang from a suggested to a required dependency, because without doing that you can forget the majority of the tests, making the tests meaningless when running without suggested packages.

Since you're on the tidy track, why not use

st_sf(tibble(x, !!!f))

?

st_sf(tibble(x, !!!f))

Great solution, thanks!