Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ and [[ keep attributes #275

Merged
merged 4 commits into from
Mar 25, 2021
Merged

[ and [[ keep attributes #275

merged 4 commits into from
Mar 25, 2021

Conversation

krlmlr
Copy link
Contributor

@krlmlr krlmlr commented Mar 16, 2021

This would be easier and faster if vctrs was an imported package, because we could then use vec_restore().

Do you see strong reasons against importing vctrs? We don't necessarily need to change the class hierarchy, although by inheriting from "vctrs_vctr" a lot of code here would be obsolete or could be changed.

@codecov
Copy link

codecov bot commented Mar 16, 2021

Codecov Report

Merging #275 (597861d) into master (dcbe2dd) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Current head 597861d differs from pull request most recent head fc61144. Consider uploading reports for the commit fc61144 to get more accurate results
Impacted file tree graph

@@           Coverage Diff           @@
##           master     #275   +/-   ##
=======================================
  Coverage   94.40%   94.41%           
=======================================
  Files          18       18           
  Lines         876      877    +1     
=======================================
+ Hits          827      828    +1     
  Misses         49       49           
Impacted Files Coverage Δ
R/conversion.R 87.95% <100.00%> (-0.29%) ⬇️
R/make_units.R 90.08% <100.00%> (+0.25%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9039083...fc61144. Read the comment docs.

@Enchufa2
Copy link
Member

Thanks. What is the interest in preserving other attributes? This PR breaks quantities.

About importing vctrs, we would like to remain compatible, but also to work independently with minimum dependencies.

@edzer
Copy link
Member

edzer commented Mar 16, 2021

I agree that minimizing the number of hard dependencies is critical for this package. Also, vctrs seems to be pretty dynamic so this would keep everyone quite busy. Once vctrs has reached stability and is rock-solid, and importing it would bring strong advantages (simplifying code could be one!) we could reconsider this.

@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 17, 2021

Fair enough.

The motivation here is to support custom formatting for numbers with units, as a follow-up to #273. See https://pillar.r-lib.org/dev/articles/numbers.html#units for a specific example.

I wasn't aware that the "units" class is actually intended to be used as mixin to other classes such as "errors". In this case it makes much more sense to only carry over the attributes that we care about. Once we've settled on attribute names, I'll update the PR.

@krlmlr krlmlr marked this pull request as draft March 17, 2021 04:49
@Enchufa2
Copy link
Member

I see. And wouldn't make more sense to prepend a new class---say, pillar---to take care of those attributes independently of what the main class does? That would be much more robust to changes here and in other packages. Within the r-quantities framework, errors and units are just responsible for their own attributes, and the quantities package coordinates them without expecting any one of them to be aware of the other. For us this is much easier to maintain.

@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 24, 2021

We could also treat units and quantities as main classes if they support wrapping of classed objects. This means replacing (at least in units) most of not all instances of unclass() with a call to strip_class() :

strip_class <- function(x) {
  if (identical(x, "units")) {
    unclass(x)
  } else {
    class(x) <- setdiff(class(x), "units")
    x
  }
}

Would you support a change like this?

The alternative -- prepending a class -- doesn't look useful at the first glance.

In a branch in pillar I have:

library(pillar)
library(units)
#> udunits database from /usr/share/xml/udunits/udunits2.xml

set_units(1:3, km) + set_units(1:3, m)
#> Units: [km]
#> [1] 1.001 2.002 3.003
num(1:3, notation = "sci") + 1:3
#> <tibble_num(sci)[3]>
#> [1] 2.00e0 4.00e0 6.00e0

# Doesn't work, looks difficult to fix
num(set_units(1:3, km), notation = "sci") + set_units(1:3, m)
#> Warning: Incompatible methods ("+.vctrs_vctr", "Ops.units") for "+"
#> <tibble_num(sci)[3]>
#> [1] 2.00e0 4.00e0 6.00e0

# Maybe...
set_units.tibble_num <- function(x, ...) {
  unclassed <- x
  class(unclassed) <- NULL
  out <- set_units(unclassed, ...)
  class(out) <- c(class(out), class(x))
  out
}

set_units(num(1:3, notation = "sci"), km)
#> Units: [km]
#> <tibble_num(sci)[3]>
#> [1] 1.00e0 2.00e0 3.00e0

# Ops.units uses unclass() but shouldn't?
set_units(num(1:3), km) + set_units(1:3, m)
#> Units: [km]
#> [1] 1.001 2.002 3.003

Created on 2021-03-24 by the reprex package (v1.0.0)

It would be much easier if units preserved the "pillar" attribute on subsetting, which contains only information related to display. Not perfect object-oriented programming, just much easier and achieves the desired result. I'll update the PR.

R/make_units.R Outdated Show resolved Hide resolved
Co-authored-by: Iñaki Ucar <iucar@fedoraproject.org>
@Enchufa2
Copy link
Member

Where is this num constructor/class? I would like to play with it. I would like to better understand the set of use cases you have in mind for them, and what's the role of pillar and tibble in them. Because, from the initial proposal, I understood that you were just interested in defining formatting options in tibbles, which I see as the last step of an analysis, but then I see that you are also operating with num (!). So you could end up with something e.g. like

num(1:3, label = "") + num(1:3, label = "$")

which makes no sense to me.

@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 24, 2021

Thanks. It's in the docs-num branch in pillar.

I'd like to argue that applying formatting early in the analysis solves a few problems:

  • Better display along the way if the standard formatting doesn't work for one reason or another
  • Display format is automatically applied to all end results: plots, tables, ...

When combining two num()s, the LHS wins. The currency example is misleading, I agree -- we could throw an error if both LHS and RHS have different labels.

@Enchufa2 Enchufa2 marked this pull request as ready for review March 24, 2021 10:22
@Enchufa2
Copy link
Member

Ok, being aware of the pillar attribute is a sensible thing to do, because we provide a pillar_shaft method, and this change is compatible upstream with quantities. If that is enough for the purposes of formatting, I'm ok with this change. However,

  • one concern is that setting a label should be incompatible with units, which could only be solved in set_num_opts.
  • another concern is how these formatting options would play with the errors class, but that's another battle.

If @edzer has no further concerns/comments, I can merge this.

@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 24, 2021

  • I agree that the label provided by units should have precedence.
  • For errors I would suggest a compound pillar where the number is formatted as usual and the error is a separate pillar shaft class. I can provide guidance or a pull request.

@Enchufa2
Copy link
Member

Merging, thanks!

For errors, some guidance on how a compound pillar looks like would be helpful.

@Enchufa2 Enchufa2 merged commit c644c3f into r-quantities:master Mar 25, 2021
@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 25, 2021

See pillar:::new_array_pillar() for an example: arrays show their first slice and a continuation marker. This looks a little too cumbersome for now, we might provide helpers in pillar.

@krlmlr
Copy link
Contributor Author

krlmlr commented Mar 25, 2021

Thanks for taking this! The "pillar" attribute looks a little ugly right now when a units object is printed, I'll send another PR soon.

@Enchufa2
Copy link
Member

Unless we want something fancier, just dropping the attribute before calling NextMethod works (1d6260c).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants