在S3中模拟多个调度(用于3个签名参数)

时间:2019-09-12 09:35:50

标签: r oop dispatch multidispatch

我知道R中不同的OO系统的一般ins and outs,并且我会尽可能/尽可能地一直呆在S3中。

但是,对multiple dispatch的需求一直困扰着我在专业项目中的工作,过去一直使我进入S4。

但是我拒绝接受我找不到多重分发àS4的S3 仿真,它至少能够支持我避免非系统性data drift的主要用例:

  1. 我的分析程序会创建数据结构,然后发布给利益相关方,供他们使用,作为某些数据管道的一部分
  2. 通常我会发布到MongoDB之类的DBMS,因此我的结构在某种程度上表现出来,可以/应该被认为是数据库模式
  3. 我遵循“提早发布,经常发布”的方法来保持敏捷,因此自然会随着时间的推移经常改变“事物”
  4. 随着数据结构的不断发展,我想明确地描述该结构,以便定义内部迁移例程和/或使利益相关者了解他们在数据库中处理的是哪个版本的数据结构

如果我要通过某种版本控制方案描述数据结构(这是迄今为止我能想到的最好的方法),那么我基本上需要将我的方法基于关于方法分派的三个签名参数:

  1. 一个用于给定数据转换任务的输入(类)
  2. 一个用于输入(类)的版本
  3. 一个用于输出版本(类)

尽职调查

除了我读过的OO field guide

我的方法

针对input_classoutput_class的基于S3的顺序方法,它们都可以在结构上随时间演变,这是由诸如v1,{{1 }}等

步骤1:定义必要的基本组件

v2

步骤2:为# Generic that dispatches on `x` new_output_class <- function(x, schema_version_in, schema_version_out, ...) { UseMethod("new_output_class", x) } # Generic that dispatches on 'schema_version_in' and # can thus be used to define distinct methods for # different versions of 'input_class' new_output_class__input_class <- function(x, schema_version_in, schema_version_out, ...) { UseMethod("new_output_class__input_class", schema_version_in) } # Generic that dispatches on 'schema_version_out' and # can thus be used to define distinct methods for # different versions of 'output_class' for inputs of class `input_class` # with version class `v1` new_output_class__input_class__v1 <- function(x, schema_version_in, schema_version_out, ...) { UseMethod("new_output_class__input_class__v1", schema_version_out) } # Top-level method for dispatch based on `input_class` new_output_class.input_class <- function( x, schema_version_in, schema_version_out ) { message("Level 1: method for `input_class`") new_output_class__input_class(x, schema_version_in, schema_version_out) } input_class = v1的初始情况定义方法

output_class = v1

步骤3:处理从library(magrittr) library(stringr) # Method for `input_class` of version `v1` new_output_class__input_class.v1 <- function( x, schema_version_in, schema_version_out ) { # message("Sub-level 1: `input_class/in:v1`") message(stringr::str_glue("Level 2: method for `input_class/in:{schema_version_in}`")) new_output_class__input_class__v1(x, schema_version_in, schema_version_out) } # Method for `output_class` of version `v1` for inputs # of `input_class` of version `v1` new_output_class__input_class__v1.v1 <- function( x, schema_version_in, schema_version_out ) { message(stringr::str_glue("Level 3: method for `input_class/in:{schema_version_in}/out:{schema_version_out}`")) structure(x, class = c(stringr::str_glue("output_class_{schema_version_out}"), "output_class") ) } x <- structure(letters[1:3], class = "input_class") schema_version_of_x <- structure("v1", class = "v1") schema_version_of_new_output <- structure("v1", class = "v1") new_output_class(x, schema_version_of_x, schema_version_of_new_output) # Level 1: method for `input_class` # Level 2: method for `input_class/in:v1` # Level 3: method for `input_class/in:v1/out:v1` # [1] "a" "b" "c" # attr(,"class") # [1] "output_class_v1" "output_class" output_class的演变

v2

步骤4:处理从# Method for `output_class` of version `v2` for inputs # of `input_class` of version `v1` new_output_class__input_class__v1.v2 <- function( x, schema_version_in, schema_version_out ) { message(stringr::str_glue("Level 3: method for `input_class/in:{schema_version_in}/out:{schema_version_out}`")) structure(x %>% rep(2), class = c(stringr::str_glue("output_class_{schema_version_out}"), "output_class") ) } schema_version_of_new_output <- structure("v2", class = "v2") new_output_class(x, schema_version_of_x, schema_version_of_new_output) # Level 1: method for `input_class` # Level 2: method for `input_class/in:v1` # Level 3: method for `input_class/in:v1/out:v2` # [1] "a" "b" "c" "a" "b" "c" # attr(,"class") # [1] "output_class_v2" "output_class" input_class的演变

v2

专业人士

  1. 有效
  2. 是S3
  3. 这是系统的

缺点

  1. 它比任何基于S4的解决方案都要冗长
  2. 我一点都不喜欢

有人在S3中提出了更好的多调度模拟吗?

0 个答案:

没有答案