SlideShare a Scribd company logo
1 of 34
R6パッケージの紹介:機能と実装
Tokyo.R #46 2015-02-21
@__nakamichi__
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
1
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
2
R6パッケージとは
• Rの新しいオブジェクト指向システム
• 作者:Winston Changさん@RStudio
• R言語のコアではなくパッケージとして実装
• 主にRStudio関係のパッケージで
利用されている
– dplyr
– httr
– shiny
3
R6パッケージとは
• 既に3つもOOシステムがあるのに,なぜまたもう1つ?
– S3, S4, RC (Reference Class)
• R6の特徴
– より「普通の」オブジェクト指向っぽい
• 「普通の」= Java, C++, Python, etc.
• RCと同様のreference semantics
• フィールド,メソッドにpublic / private が指定可能
• パッケージをまたいだ継承が可能
– RCより速くて軽い
– 設計・実装が単純
• Rの基本的な機能だけを使って実装されている
4
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
5
6
既存のOOシステム
• S3
– クラスはclass属性として個別のオブジェクトに対して設定
• フォーマルなクラス定義はない
• 継承もclass属性で行う
– メソッドはジェネリック関数
john <- list(name = "John", age = 40)
class(john) <- c("Employee", "Person")
# printはジェネリック関数
print
#> function (x, ...)
#> UseMethod("print")
# メソッド定義
print.Person <- function(x) {
paste0("こんにちは,", x$name, "です.")
}
# printで実際に呼ばれるのはprint.Person
print(john)
#> [1] "こんにちは,Johnです."
7
既存のOOシステム
• S4
– S3よりフォーマルで厳密なクラス定義
– スロット(フィールド)には@でアクセス
# クラス定義
setClass("Person",
slots = list(name = "character", age = "numeric"))
# containsで継承
setClass("Employee", contains = "Person"
slots = list(boss = "Person"))
# new()でオブジェクト作成
alice <- new("Person", name = "Alice", age = 40)
john <- new("Employee", name = "John", age = 20, boss = alice)
# @でスロットにアクセス
alice@age
#> [1] 40
# クラス定義にないスロットは作れない
alice@age <- '40'
#> Error in checkAtAssignment("Person", "age", "character") : ...
alice@sex <- "female"
#> Error in checkAtAssignment("Person", "sex", "character") : ...
8
既存のOOシステム
• S4
– メソッドはジェネリック関数
– copy-on-modify semantics: オブジェクトは変更不能(immutable)
# ジェネリック関数
setGeneric("greet", function(x) {
standardGeneric("greet")
})
# メソッドの実装
setMethod("greet",
signature = c(x = "Person"),
definition = function(x) {
paste0("こんにちは,", x@name, "です.")
})
greet(john)
#> [1] "こんにちは,Johnです."
# aliceとalice2は別人
alice2 <- alice
alice2@age <- 50
alice2@age
#> [1] 50
alice@age
#> [1] 40
age=50
name=“alice”
age=40
name=“alice”
Person alice
Person alice2
copy on modify
9
既存のOOシステム
• RC (Reference Class)
– メソッドはオブジェクトに属する
– フィールドとメソッドには$でアクセス
# クラス定義
Person <- setRefClass("Person",
# フィールド定義
fields = list(name = “character”,
age = "numeric", hair = "character"),
# メソッド定義
methods = list(
# オブジェクトの初期化関数
# フィールドへの代入は<<-か.selfを使う
initialize = function(name, age, hair) {
name <<- name
.self$age <- age
.self$hair <- hair
},
set_hair = function(hair) {
.self$hair <- hair
},
greet = function() {
paste0("こんにちは,", name, "です.")
})
)
# オブジェクト作成
alice <- Person$new("Alice", 40, "red")
# $でメソッドアクセス
alice$greet()
# 継承はcontains引数で
Employee <- setRefClass("Employee",
contains = "Person",
methods = list(
# メソッドオーバーライド
greet = function() {
paste0("こんにちは,会社員の",
name, "です.")
})
)
john <- Employee$new("John", 25, "black")
john$greet()
#> [1] "こんにちは,会社員のJohnです."
10
既存のOOシステム
• RC (Reference Class)
– reference semantics: オブジェクトは変更可能(mutable)
– 「普通の」OOP言語っぽい
name = “john”
age = 25
hair = “green”
Employee john
Employee john2
john$hair
#> [1] "black"
# johnとjohn2は同じ人
john2 <- john
john2$set_hair("green")
john$hair
#> [1] "green“
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
11
12
R6の機能
• クラス定義
– syntaxはRCに類似しているが,より簡潔
– フィールドとメソッドを分けずに全てpublic引数に記述すればよい
– RCと異なり,フィールドの型は指定できない
# クラス定義
Person <- R6Class("Person",
# publicでフィールドとメソッドを両方設定する
public = list(
# RCと異なり,変数の型ではなくデフォルト値を設定
name = NA,
hair = "black",
# オブジェクトの初期化関数
# オブジェクト自身にはselfでアクセス
initialize = function(name, hair) {
self$name <- name
self$hair <- hair
},
set_hair = function(hair) {
self$hair <- hair
},
greet = function() {
paste0("こんにちは,", self$name, "です.")
})
)
13
R6の機能
• オブジェクト作成
– $new()メソッドで作成
– reference semantics
# オブジェクト作成
alice <- Person$new("Alice", “black")
# フィールド,メソッドには$でアクセス
alice$hair
#> [1] "black"
alice$greet()
#> こんにちは,Aliceです.
alice$set_hair("red")
# クラス定義にないフィールドは作れない
alice$age <- 40
#> Error in alice$age <- 40 : ...
# aliceとalice2は同一人物
alice2 <- alice
alice2$set_hair("blue")
alice$hair
#> [1] "blue"
name=“alice”
hair=“blue”
Person alice
Person alice2
14
R6の機能
• public/private
– R6ではprivateフィールド,メソッドを作ることができる
• RCにはない機能
• オブジェクト自身のメソッドからしかアクセスできない
• (selfではなく)privateを通じてアクセスする
# privateを持つクラス
Person <- R6Class("Person",
private = list(age = NA, # 年齢はprivate
# 年齢のgetter
get_age = function() private$age),
public = list(name = NA, hair = "black",
initialize = function(name,hair,age) {
# 中略
# メソッドからはprivateフィールドが見える
private$age <- age
},
set_hair = function(hair) { #略 },
greet = function() { #略 },
# 外向け年齢はサバを読む
show_age = function() {
private$get_age() - 5
})
)
# オブジェクト作成
alice <- Person$new("Alice", "red", 40)
# age, get_age()は外からは見えない
alice$age
#> NULL
alice$get_age()
#> Error: attempt to apply non-function
alice$show_age()
#> [1] 35
15
R6の機能
• 継承
– スーパークラスを inherit 引数で指定
– スーパークラスのメソッドはsuperを通じて呼べる
– パッケージをまたいだ継承が可能(portable class, RCではできない)
# inheritで継承
Employee <- R6Class("Employee",
inherit = Person,
private = list(tsurami = 0), # つらみ
public = list(
# メソッドオーバーライド
initialize = function(name, hair, age, tsurami) {
# スーパークラスはsuperで呼ぶ
super$initialize(name, hair, age)
private$tsurami <- tsurami
},
work = function() { private$tsurami <- private$tsurami + 1},
greet = function() {
if(private$tsurami > 5) paste0("社畜の", self$name, "です!")
else super$greet()
})
)
# Johnは社畜
john <- Employee$new("John", "black", 35, tsurami = 10)
john$greet()
#> 社畜のJohnです!
16
R6の機能
• パフォーマンス
– R6はRCより速くて軽い
# RCとR6のパフォーマンス比較
library(microbenchmark)
# 適当なクラスを定義
R6 <- R6Class("R6", public = list(
x = NULL,
initialize = function(x = 1) self$x <- x,
inc = function(n = 1) self$x <- self$x + n)
)
RC <- setRefClass("RC",
fields = list(x = "numeric"),
methods = list(
initialize = function(x = 1) x <<- x,
inc = function(n = 1) x <<- x + n)
)
# オブジェクト生成
microbenchmark(
r6 <- R6$new(x = 100),
rc <- RC$new(x = 100))
#> Unit: microseconds
#> expr median neval
#> r6 <- R6$new(x = 100) 84.7825 100
#> rc <- RC$new(x = 100) 405.3950 100
# メソッド呼び出し
microbenchmark(r6$inc(), rc$inc())
#> Unit: microseconds
#> expr median neval
#> r6$inc() 16.065 100
#> rc$inc() 62.918 100
# オブジェクトサイズ
pryr::object_size(r6)
#> 3.94 kB
pryr::object_size(rc)
#> 465 kB
17
R6の機能
• ここまでのまとめ
• R6はRCと同様, reference semantics のOOシステム
• R6は「普通の」オブジェクト指向っぽい
– 簡潔なsyntax
– public/privateの区別
– パッケージをまたいだ継承
• R6はRCより速くて軽い
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
18
19
R6の中身をのぞいてみる
• R6の仕組みを知りたい
– R6Class()や$new()って何?
– public / private の仕組みは?
• 実はR6の実装は意外と簡単
– Rの基本的な機能だけで実装できる
• 要は,reference semantics を持つデータ構造を
「普通の」OOPのオブジェクトらしく見えるように
仕立てあげればよい
• reference semanticsを持つデータ構造
=「環境」
20
Rにおける環境
• 環境(environment) = 関数を構成する要素のひとつ
– Rの関数の3つの構成要素
• formals: 引数
• body: 関数本体
• environment: 変数(名前)をオブジェクトに結びつけるデータ構造
g
x 1
g
x 2
environment(g) <- e
e
f <- function() {
x <- 1
function() {
x + 1
}
}
g <- f()
environment(g)
#> <environment: 0x0000000013ddc1b8>
# gは親環境にxを探しに行く
g()
#> [1] 2
# gの環境を変更する
e <- new.env()
e$x <- 2
environment(g) <- e
g()
#> [1] 3
<environment: 0x0000000013ddc1b8>
21
Rにおける環境
• 環境は2つの要素からなる
– フレーム:名前をオブジェクトに結びつける
– 親環境(parent environment)
• 関数は親環境を辿っていって名前を探す
y <- 2
f <- function() {
x <- 1
function() {
x + y
}
}
h <- f()
h()
#> [1] 3
environment(h)
#> <environment: 0x000000001424c380>
parent.env(environment(h))
#> <environment: R_GlobalEnv>
h x 1
<environment: 0x000000001424c380>
y 2
globalenv()
parent.env()
22
Rにおける環境
• 環境 ≃ reference semantics を持つリスト
– 関数とは無関係に,便利なデータ構造としても使える
– 環境がだんだん「オブジェクト」に見えてきたような…
# 環境e1を作成
e1 <- new.env()
e1$x <- 1
e1$x
#> [1] 1
# e2を変更するとe1も変わる
e2 <- e1
e2$x <- 2
e1$x
#> [1] 2
# 関数に渡した環境自体が変更される
g <- function(e) {
e$y <- 3
}
g(e1)
e1$y
#> [1] 3
# リストl1を作成
l1 <- list()
l1$x <- 1
l1$x
#> [1] 1
# l2を変更してもl1はそのまま
l2 <- l1
l2$x <- 2
l1$x
#> [1] 1
# 関数に渡したリスト自体は不変
f <- function(l) {
l$y <- 3
}
f(l1)
l1$y
#> NULL
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
23
24
R6Class()の実装
• R6Class()の戻り値は?
Person <- R6Class("Person",
private = list(age = NA,
get_age = function() private$age),
public = list(name = NA, hair = "black",
initialize = function(name, hair, age) {
self$name <- name
self$hair <- hair
private$age <- age
},
set_hair = function(hair) {
self$hair <- hair
},
greet = function() {
paste0("こんにちは,", self$name, "です.")
},
show_age = function() {
private$get_age() - 5
})
)
Person
#> <Person> object generator
#> Public:
#> name: NA
#> hair: black
#> initialize: function
#> set_hair: function
#> greet: function
#> show_age: function
#> Private:
#> age: NA
#> get_age: function
#> Parent env: <environment: R_GlobalEnv>
#> Lock: TRUE
#> Portable: TRUE
25
R6Class()の実装
• R6Class() の戻り値=環境
– R6Class()の引数やnew()を要素に持つgenerator環境がR6クラスの実体
# encapsulate()はR6Classの親環境をcapsuleにする
R6Class <- encapsulate(function(classname = NULL,
public = list(), private = NULL, inherit = NULL, ...) {
# ジェネレータオブジェクトの作成
generator <- new.env(parent = capsule)
generator$self <- generator # selfはgenerator自身
generator$classname <- classname
generator$public_fields <- get_nonfunctions(public)
generator$private_fields <- get_nonfunctions(private)
generator$public_methods <- get_functions(public)
generator$private_methods <- get_functions(private)
# generator_funsはnewを含む関数のリスト
# generator_funcs$newの環境をgeneratorにする
generator_funs <- assign_func_envs(generator_funs, generator)
# generator_funs$newをgenerator$new にコピー
list2env2(generator_funs, generator)
class(generator) <- "R6ClassGenerator"
generator
})
26
R6Class()の実装
generator [Person]
R6Class
self
classname
public_fields
public_methods
private_methods
private_fields
new function
“Person”
R6パッケージ内部の
ユーティリティ関数群
capsule
list(name=NA, ...)
list(initialize =
function(name, ...),
...)
NULL
list(age=NA, ...)
Person <- R6Class()
R6Class()の引数
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
27
28
$new()の実装
• $new()の戻り値=環境
– R6オブジェクトの実体はpublic_bind_env環境
– generatorからpublic_bind_envにフィールドとメソッドをコピーする
# publicフィールド・メソッドのみ,継承なしの場合
generator_funs$new <- function(...) {
# publicオブジェクトの束縛環境を作成
public_bind_env <- new.env(parent = emptyenv(), hash = FALSE)
# メソッドの環境を作成
enclos_env <- new.env(parent = parent_env, hash = FALSE)
# selfの実体はpublic_bind_env
enclos_env$self <- public_bind_env
# generator$public_methodsの環境をenclos_envにして
# public_bind_envにコピー
public_methods <- assign_func_envs(public_methods, enclos_env)
# フィールドとメソッドをpublic環境にコピー
list2env2(public_methods, envir = public_bind_env)
list2env2(public_fields, envir = public_bind_env)
# オブジェクト初期化
public_bind_env$initialize(...)
public_bind_env
}
29
$new()の実装
public_fieldsと
public_methodsのコピー
generator [Person]
self
classname
public_fields
public_methods
private_methods
private_fields
new
function
alice <- Person$new()
initialize
set_hair
name
greet
hair
function
function
function
“black”
“Alice”
enclos_env
public_bind_env
[alice]
self
emptyenv()
30
$new()の実装
• privateがある場合:privateをpublicと別の環境として作成
enclos_env
public_fieldsと
public_methodsのコピー
initialize
set_hair
name
greet
hair
function
function
function
“black”
“Alice”
public_bind_env
[alice]
self
emptyenv()
private_fieldsと
private_methodsのコピー
get_age
age
function
40
private_bind_env
private
31
$new()の実装
• スーパークラスがある場合:superをpublicとは別の環境として作成
enclos_env
public_fieldsと
public_methodsのコピー
initialize
set_hair
name
greet
hair
function
function
function
“black”
“Alice”
public_bind_env
[john]
self
emptyenv()
super_bind_env
super
super_enclos_env
self
super
greetfunction
スーパークラスの
スーパークラスを
参照
スーパークラスの
public_fieldsと
public_methodsのコピー
• R6パッケージとは
• R6を使う
– 既存のオブジェクト指向システム(S3, S4, RC)
– R6の機能
• R6の中身をのぞいてみる
– Rにおける環境
– R6Class()の実装
– $new()の実装
• まとめ
32
まとめ
• R6は新しいオブジェクト指向システム
• R6の特徴
– 「普通の」オブジェクト指向っぽい
• reference semantics
• public / private
– RCより速くて軽い
• R6の実装
– 環境を活用したシンプルな実装
• 参考
– Introduction to R6 Classes
• http://cran.r-project.org/web/packages/R6/vignettes/Introduction.html
– Advanced R – Environments
• http://adv-r.had.co.nz/Environments.html
33

More Related Content

What's hot

『バックドア基準の入門』@統数研研究集会
『バックドア基準の入門』@統数研研究集会『バックドア基準の入門』@統数研研究集会
『バックドア基準の入門』@統数研研究集会takehikoihayashi
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力imuyaoti
 
ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)医療IT数学同好会 T/T
 
不均衡データのクラス分類
不均衡データのクラス分類不均衡データのクラス分類
不均衡データのクラス分類Shintaro Fukushima
 
第4回DARM勉強会 (構造方程式モデリング)
第4回DARM勉強会 (構造方程式モデリング)第4回DARM勉強会 (構造方程式モデリング)
第4回DARM勉強会 (構造方程式モデリング)Yoshitake Takebayashi
 
Rによる高速処理 まだfor使ってるの?
Rによる高速処理 まだfor使ってるの?Rによる高速処理 まだfor使ってるの?
Rによる高速処理 まだfor使ってるの?jundoll
 
構造方程式モデルによる因果探索と非ガウス性
構造方程式モデルによる因果探索と非ガウス性構造方程式モデルによる因果探索と非ガウス性
構造方程式モデルによる因果探索と非ガウス性Shiga University, RIKEN
 
ベイズ統計入門
ベイズ統計入門ベイズ統計入門
ベイズ統計入門Miyoshi Yuya
 
DARM勉強会第3回 (missing data analysis)
DARM勉強会第3回 (missing data analysis)DARM勉強会第3回 (missing data analysis)
DARM勉強会第3回 (missing data analysis)Masaru Tokuoka
 
指数分布とポアソン分布のいけない関係
指数分布とポアソン分布のいけない関係指数分布とポアソン分布のいけない関係
指数分布とポアソン分布のいけない関係Nagi Teramo
 
【解説】 一般逆行列
【解説】 一般逆行列【解説】 一般逆行列
【解説】 一般逆行列Kenjiro Sugimoto
 
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展Shiga University, RIKEN
 
数式を綺麗にプログラミングするコツ #spro2013
数式を綺麗にプログラミングするコツ #spro2013数式を綺麗にプログラミングするコツ #spro2013
数式を綺麗にプログラミングするコツ #spro2013Shuyo Nakatani
 
MCMCでマルチレベルモデル
MCMCでマルチレベルモデルMCMCでマルチレベルモデル
MCMCでマルチレベルモデルHiroshi Shimizu
 
ベイズ統計学の概論的紹介
ベイズ統計学の概論的紹介ベイズ統計学の概論的紹介
ベイズ統計学の概論的紹介Naoki Hayashi
 
CRAN Rパッケージ BNSLの概要
CRAN Rパッケージ BNSLの概要CRAN Rパッケージ BNSLの概要
CRAN Rパッケージ BNSLの概要Joe Suzuki
 
Rでisomap(多様体学習のはなし)
Rでisomap(多様体学習のはなし)Rでisomap(多様体学習のはなし)
Rでisomap(多様体学習のはなし)Kohta Ishikawa
 

What's hot (20)

『バックドア基準の入門』@統数研研究集会
『バックドア基準の入門』@統数研研究集会『バックドア基準の入門』@統数研研究集会
『バックドア基準の入門』@統数研研究集会
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力
 
MICの解説
MICの解説MICの解説
MICの解説
 
Rで学ぶロバスト推定
Rで学ぶロバスト推定Rで学ぶロバスト推定
Rで学ぶロバスト推定
 
ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)ベイズ機械学習(an introduction to bayesian machine learning)
ベイズ機械学習(an introduction to bayesian machine learning)
 
不均衡データのクラス分類
不均衡データのクラス分類不均衡データのクラス分類
不均衡データのクラス分類
 
第4回DARM勉強会 (構造方程式モデリング)
第4回DARM勉強会 (構造方程式モデリング)第4回DARM勉強会 (構造方程式モデリング)
第4回DARM勉強会 (構造方程式モデリング)
 
Rによる高速処理 まだfor使ってるの?
Rによる高速処理 まだfor使ってるの?Rによる高速処理 まだfor使ってるの?
Rによる高速処理 まだfor使ってるの?
 
構造方程式モデルによる因果探索と非ガウス性
構造方程式モデルによる因果探索と非ガウス性構造方程式モデルによる因果探索と非ガウス性
構造方程式モデルによる因果探索と非ガウス性
 
ベイズ統計入門
ベイズ統計入門ベイズ統計入門
ベイズ統計入門
 
Stan超初心者入門
Stan超初心者入門Stan超初心者入門
Stan超初心者入門
 
DARM勉強会第3回 (missing data analysis)
DARM勉強会第3回 (missing data analysis)DARM勉強会第3回 (missing data analysis)
DARM勉強会第3回 (missing data analysis)
 
指数分布とポアソン分布のいけない関係
指数分布とポアソン分布のいけない関係指数分布とポアソン分布のいけない関係
指数分布とポアソン分布のいけない関係
 
【解説】 一般逆行列
【解説】 一般逆行列【解説】 一般逆行列
【解説】 一般逆行列
 
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展
構造方程式モデルによる因果推論: 因果構造探索に関する最近の発展
 
数式を綺麗にプログラミングするコツ #spro2013
数式を綺麗にプログラミングするコツ #spro2013数式を綺麗にプログラミングするコツ #spro2013
数式を綺麗にプログラミングするコツ #spro2013
 
MCMCでマルチレベルモデル
MCMCでマルチレベルモデルMCMCでマルチレベルモデル
MCMCでマルチレベルモデル
 
ベイズ統計学の概論的紹介
ベイズ統計学の概論的紹介ベイズ統計学の概論的紹介
ベイズ統計学の概論的紹介
 
CRAN Rパッケージ BNSLの概要
CRAN Rパッケージ BNSLの概要CRAN Rパッケージ BNSLの概要
CRAN Rパッケージ BNSLの概要
 
Rでisomap(多様体学習のはなし)
Rでisomap(多様体学習のはなし)Rでisomap(多様体学習のはなし)
Rでisomap(多様体学習のはなし)
 

Viewers also liked

Python におけるドメイン駆動設計(戦術面)の勘どころ
Python におけるドメイン駆動設計(戦術面)の勘どころPython におけるドメイン駆動設計(戦術面)の勘どころ
Python におけるドメイン駆動設計(戦術面)の勘どころJunya Hayashi
 
Prophet入門【理論編】Facebookの時系列予測ツール
Prophet入門【理論編】Facebookの時系列予測ツールProphet入門【理論編】Facebookの時系列予測ツール
Prophet入門【理論編】Facebookの時系列予測ツールhoxo_m
 
Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?Takayuki Shimizukawa
 
Prophet入門【R編】Facebookの時系列予測ツール
Prophet入門【R編】Facebookの時系列予測ツールProphet入門【R編】Facebookの時系列予測ツール
Prophet入門【R編】Facebookの時系列予測ツールhoxo_m
 
Prophet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールProphet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールhoxo_m
 
Python入門 : 4日間コース社内トレーニング
Python入門 : 4日間コース社内トレーニングPython入門 : 4日間コース社内トレーニング
Python入門 : 4日間コース社内トレーニングYuichi Ito
 

Viewers also liked (7)

Python におけるドメイン駆動設計(戦術面)の勘どころ
Python におけるドメイン駆動設計(戦術面)の勘どころPython におけるドメイン駆動設計(戦術面)の勘どころ
Python におけるドメイン駆動設計(戦術面)の勘どころ
 
Prophet入門【理論編】Facebookの時系列予測ツール
Prophet入門【理論編】Facebookの時系列予測ツールProphet入門【理論編】Facebookの時系列予測ツール
Prophet入門【理論編】Facebookの時系列予測ツール
 
Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?Pythonはどうやってlen関数で長さを手にいれているの?
Pythonはどうやってlen関数で長さを手にいれているの?
 
Prophet入門【R編】Facebookの時系列予測ツール
Prophet入門【R編】Facebookの時系列予測ツールProphet入門【R編】Facebookの時系列予測ツール
Prophet入門【R編】Facebookの時系列予測ツール
 
Prophet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツールProphet入門【Python編】Facebookの時系列予測ツール
Prophet入門【Python編】Facebookの時系列予測ツール
 
TokyoR42_around_chaining
TokyoR42_around_chainingTokyoR42_around_chaining
TokyoR42_around_chaining
 
Python入門 : 4日間コース社内トレーニング
Python入門 : 4日間コース社内トレーニングPython入門 : 4日間コース社内トレーニング
Python入門 : 4日間コース社内トレーニング
 

Similar to R6パッケージの紹介―機能と実装

Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Shintaro Fukushima
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと Haruka Ozaki
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2Atsuo Yamasaki
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類Tetsuya Hasegawa
 
Apache Spark チュートリアル
Apache Spark チュートリアルApache Spark チュートリアル
Apache Spark チュートリアルK Yamaguchi
 
R6 classes
R6 classesR6 classes
R6 classeshiroki84
 
Ruby on Rails on MySQL チューニング入門
Ruby on Rails on MySQL チューニング入門Ruby on Rails on MySQL チューニング入門
Ruby on Rails on MySQL チューニング入門だいすけ さとう
 
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみましたEucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみましたEtsuji Nakai
 
メタメタプログラミングRuby
メタメタプログラミングRubyメタメタプログラミングRuby
メタメタプログラミングRubyemasaka
 
RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会Nao Minami
 
Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道Shinsuke Sugaya
 
10分で分かるRパッケージの作り方
10分で分かるRパッケージの作り方10分で分かるRパッケージの作り方
10分で分かるRパッケージの作り方Yohei Sato
 
知って得する標準関数の使い方
知って得する標準関数の使い方知って得する標準関数の使い方
知って得する標準関数の使い方Soudai Sone
 
10分で分かるr言語入門ver2.10 14 1101
10分で分かるr言語入門ver2.10 14 110110分で分かるr言語入門ver2.10 14 1101
10分で分かるr言語入門ver2.10 14 1101Nobuaki Oshiro
 
10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 Nobuaki Oshiro
 

Similar to R6パッケージの紹介―機能と実装 (20)

Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)Rあんなときこんなとき(tokyo r#12)
Rあんなときこんなとき(tokyo r#12)
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
 
[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2[東京] JapanSharePointGroup 勉強会 #2
[東京] JapanSharePointGroup 勉強会 #2
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類
 
d3sparql.js
d3sparql.js d3sparql.js
d3sparql.js
 
Apache Spark チュートリアル
Apache Spark チュートリアルApache Spark チュートリアル
Apache Spark チュートリアル
 
R6 classes
R6 classesR6 classes
R6 classes
 
Ruby on Rails on MySQL チューニング入門
Ruby on Rails on MySQL チューニング入門Ruby on Rails on MySQL チューニング入門
Ruby on Rails on MySQL チューニング入門
 
HaskellDB
HaskellDBHaskellDB
HaskellDB
 
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみましたEucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
EucalyptusのHadoopクラスタとJaqlでBasket解析をしてHiveとの違いを味わってみました
 
メタメタプログラミングRuby
メタメタプログラミングRubyメタメタプログラミングRuby
メタメタプログラミングRuby
 
RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会RailsエンジニアのためのSQLチューニング速習会
RailsエンジニアのためのSQLチューニング速習会
 
Project lambda
Project lambdaProject lambda
Project lambda
 
Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道
 
10分で分かるRパッケージの作り方
10分で分かるRパッケージの作り方10分で分かるRパッケージの作り方
10分で分かるRパッケージの作り方
 
知って得する標準関数の使い方
知って得する標準関数の使い方知って得する標準関数の使い方
知って得する標準関数の使い方
 
Python opt
Python optPython opt
Python opt
 
10分で分かるr言語入門ver2.10 14 1101
10分で分かるr言語入門ver2.10 14 110110分で分かるr言語入門ver2.10 14 1101
10分で分かるr言語入門ver2.10 14 1101
 
10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 

R6パッケージの紹介―機能と実装

  • 2. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 1
  • 3. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 2
  • 4. R6パッケージとは • Rの新しいオブジェクト指向システム • 作者:Winston Changさん@RStudio • R言語のコアではなくパッケージとして実装 • 主にRStudio関係のパッケージで 利用されている – dplyr – httr – shiny 3
  • 5. R6パッケージとは • 既に3つもOOシステムがあるのに,なぜまたもう1つ? – S3, S4, RC (Reference Class) • R6の特徴 – より「普通の」オブジェクト指向っぽい • 「普通の」= Java, C++, Python, etc. • RCと同様のreference semantics • フィールド,メソッドにpublic / private が指定可能 • パッケージをまたいだ継承が可能 – RCより速くて軽い – 設計・実装が単純 • Rの基本的な機能だけを使って実装されている 4
  • 6. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 5
  • 7. 6 既存のOOシステム • S3 – クラスはclass属性として個別のオブジェクトに対して設定 • フォーマルなクラス定義はない • 継承もclass属性で行う – メソッドはジェネリック関数 john <- list(name = "John", age = 40) class(john) <- c("Employee", "Person") # printはジェネリック関数 print #> function (x, ...) #> UseMethod("print") # メソッド定義 print.Person <- function(x) { paste0("こんにちは,", x$name, "です.") } # printで実際に呼ばれるのはprint.Person print(john) #> [1] "こんにちは,Johnです."
  • 8. 7 既存のOOシステム • S4 – S3よりフォーマルで厳密なクラス定義 – スロット(フィールド)には@でアクセス # クラス定義 setClass("Person", slots = list(name = "character", age = "numeric")) # containsで継承 setClass("Employee", contains = "Person" slots = list(boss = "Person")) # new()でオブジェクト作成 alice <- new("Person", name = "Alice", age = 40) john <- new("Employee", name = "John", age = 20, boss = alice) # @でスロットにアクセス alice@age #> [1] 40 # クラス定義にないスロットは作れない alice@age <- '40' #> Error in checkAtAssignment("Person", "age", "character") : ... alice@sex <- "female" #> Error in checkAtAssignment("Person", "sex", "character") : ...
  • 9. 8 既存のOOシステム • S4 – メソッドはジェネリック関数 – copy-on-modify semantics: オブジェクトは変更不能(immutable) # ジェネリック関数 setGeneric("greet", function(x) { standardGeneric("greet") }) # メソッドの実装 setMethod("greet", signature = c(x = "Person"), definition = function(x) { paste0("こんにちは,", x@name, "です.") }) greet(john) #> [1] "こんにちは,Johnです." # aliceとalice2は別人 alice2 <- alice alice2@age <- 50 alice2@age #> [1] 50 alice@age #> [1] 40 age=50 name=“alice” age=40 name=“alice” Person alice Person alice2 copy on modify
  • 10. 9 既存のOOシステム • RC (Reference Class) – メソッドはオブジェクトに属する – フィールドとメソッドには$でアクセス # クラス定義 Person <- setRefClass("Person", # フィールド定義 fields = list(name = “character”, age = "numeric", hair = "character"), # メソッド定義 methods = list( # オブジェクトの初期化関数 # フィールドへの代入は<<-か.selfを使う initialize = function(name, age, hair) { name <<- name .self$age <- age .self$hair <- hair }, set_hair = function(hair) { .self$hair <- hair }, greet = function() { paste0("こんにちは,", name, "です.") }) ) # オブジェクト作成 alice <- Person$new("Alice", 40, "red") # $でメソッドアクセス alice$greet() # 継承はcontains引数で Employee <- setRefClass("Employee", contains = "Person", methods = list( # メソッドオーバーライド greet = function() { paste0("こんにちは,会社員の", name, "です.") }) ) john <- Employee$new("John", 25, "black") john$greet() #> [1] "こんにちは,会社員のJohnです."
  • 11. 10 既存のOOシステム • RC (Reference Class) – reference semantics: オブジェクトは変更可能(mutable) – 「普通の」OOP言語っぽい name = “john” age = 25 hair = “green” Employee john Employee john2 john$hair #> [1] "black" # johnとjohn2は同じ人 john2 <- john john2$set_hair("green") john$hair #> [1] "green“
  • 12. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 11
  • 13. 12 R6の機能 • クラス定義 – syntaxはRCに類似しているが,より簡潔 – フィールドとメソッドを分けずに全てpublic引数に記述すればよい – RCと異なり,フィールドの型は指定できない # クラス定義 Person <- R6Class("Person", # publicでフィールドとメソッドを両方設定する public = list( # RCと異なり,変数の型ではなくデフォルト値を設定 name = NA, hair = "black", # オブジェクトの初期化関数 # オブジェクト自身にはselfでアクセス initialize = function(name, hair) { self$name <- name self$hair <- hair }, set_hair = function(hair) { self$hair <- hair }, greet = function() { paste0("こんにちは,", self$name, "です.") }) )
  • 14. 13 R6の機能 • オブジェクト作成 – $new()メソッドで作成 – reference semantics # オブジェクト作成 alice <- Person$new("Alice", “black") # フィールド,メソッドには$でアクセス alice$hair #> [1] "black" alice$greet() #> こんにちは,Aliceです. alice$set_hair("red") # クラス定義にないフィールドは作れない alice$age <- 40 #> Error in alice$age <- 40 : ... # aliceとalice2は同一人物 alice2 <- alice alice2$set_hair("blue") alice$hair #> [1] "blue" name=“alice” hair=“blue” Person alice Person alice2
  • 15. 14 R6の機能 • public/private – R6ではprivateフィールド,メソッドを作ることができる • RCにはない機能 • オブジェクト自身のメソッドからしかアクセスできない • (selfではなく)privateを通じてアクセスする # privateを持つクラス Person <- R6Class("Person", private = list(age = NA, # 年齢はprivate # 年齢のgetter get_age = function() private$age), public = list(name = NA, hair = "black", initialize = function(name,hair,age) { # 中略 # メソッドからはprivateフィールドが見える private$age <- age }, set_hair = function(hair) { #略 }, greet = function() { #略 }, # 外向け年齢はサバを読む show_age = function() { private$get_age() - 5 }) ) # オブジェクト作成 alice <- Person$new("Alice", "red", 40) # age, get_age()は外からは見えない alice$age #> NULL alice$get_age() #> Error: attempt to apply non-function alice$show_age() #> [1] 35
  • 16. 15 R6の機能 • 継承 – スーパークラスを inherit 引数で指定 – スーパークラスのメソッドはsuperを通じて呼べる – パッケージをまたいだ継承が可能(portable class, RCではできない) # inheritで継承 Employee <- R6Class("Employee", inherit = Person, private = list(tsurami = 0), # つらみ public = list( # メソッドオーバーライド initialize = function(name, hair, age, tsurami) { # スーパークラスはsuperで呼ぶ super$initialize(name, hair, age) private$tsurami <- tsurami }, work = function() { private$tsurami <- private$tsurami + 1}, greet = function() { if(private$tsurami > 5) paste0("社畜の", self$name, "です!") else super$greet() }) ) # Johnは社畜 john <- Employee$new("John", "black", 35, tsurami = 10) john$greet() #> 社畜のJohnです!
  • 17. 16 R6の機能 • パフォーマンス – R6はRCより速くて軽い # RCとR6のパフォーマンス比較 library(microbenchmark) # 適当なクラスを定義 R6 <- R6Class("R6", public = list( x = NULL, initialize = function(x = 1) self$x <- x, inc = function(n = 1) self$x <- self$x + n) ) RC <- setRefClass("RC", fields = list(x = "numeric"), methods = list( initialize = function(x = 1) x <<- x, inc = function(n = 1) x <<- x + n) ) # オブジェクト生成 microbenchmark( r6 <- R6$new(x = 100), rc <- RC$new(x = 100)) #> Unit: microseconds #> expr median neval #> r6 <- R6$new(x = 100) 84.7825 100 #> rc <- RC$new(x = 100) 405.3950 100 # メソッド呼び出し microbenchmark(r6$inc(), rc$inc()) #> Unit: microseconds #> expr median neval #> r6$inc() 16.065 100 #> rc$inc() 62.918 100 # オブジェクトサイズ pryr::object_size(r6) #> 3.94 kB pryr::object_size(rc) #> 465 kB
  • 18. 17 R6の機能 • ここまでのまとめ • R6はRCと同様, reference semantics のOOシステム • R6は「普通の」オブジェクト指向っぽい – 簡潔なsyntax – public/privateの区別 – パッケージをまたいだ継承 • R6はRCより速くて軽い
  • 19. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 18
  • 20. 19 R6の中身をのぞいてみる • R6の仕組みを知りたい – R6Class()や$new()って何? – public / private の仕組みは? • 実はR6の実装は意外と簡単 – Rの基本的な機能だけで実装できる • 要は,reference semantics を持つデータ構造を 「普通の」OOPのオブジェクトらしく見えるように 仕立てあげればよい • reference semanticsを持つデータ構造 =「環境」
  • 21. 20 Rにおける環境 • 環境(environment) = 関数を構成する要素のひとつ – Rの関数の3つの構成要素 • formals: 引数 • body: 関数本体 • environment: 変数(名前)をオブジェクトに結びつけるデータ構造 g x 1 g x 2 environment(g) <- e e f <- function() { x <- 1 function() { x + 1 } } g <- f() environment(g) #> <environment: 0x0000000013ddc1b8> # gは親環境にxを探しに行く g() #> [1] 2 # gの環境を変更する e <- new.env() e$x <- 2 environment(g) <- e g() #> [1] 3 <environment: 0x0000000013ddc1b8>
  • 22. 21 Rにおける環境 • 環境は2つの要素からなる – フレーム:名前をオブジェクトに結びつける – 親環境(parent environment) • 関数は親環境を辿っていって名前を探す y <- 2 f <- function() { x <- 1 function() { x + y } } h <- f() h() #> [1] 3 environment(h) #> <environment: 0x000000001424c380> parent.env(environment(h)) #> <environment: R_GlobalEnv> h x 1 <environment: 0x000000001424c380> y 2 globalenv() parent.env()
  • 23. 22 Rにおける環境 • 環境 ≃ reference semantics を持つリスト – 関数とは無関係に,便利なデータ構造としても使える – 環境がだんだん「オブジェクト」に見えてきたような… # 環境e1を作成 e1 <- new.env() e1$x <- 1 e1$x #> [1] 1 # e2を変更するとe1も変わる e2 <- e1 e2$x <- 2 e1$x #> [1] 2 # 関数に渡した環境自体が変更される g <- function(e) { e$y <- 3 } g(e1) e1$y #> [1] 3 # リストl1を作成 l1 <- list() l1$x <- 1 l1$x #> [1] 1 # l2を変更してもl1はそのまま l2 <- l1 l2$x <- 2 l1$x #> [1] 1 # 関数に渡したリスト自体は不変 f <- function(l) { l$y <- 3 } f(l1) l1$y #> NULL
  • 24. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 23
  • 25. 24 R6Class()の実装 • R6Class()の戻り値は? Person <- R6Class("Person", private = list(age = NA, get_age = function() private$age), public = list(name = NA, hair = "black", initialize = function(name, hair, age) { self$name <- name self$hair <- hair private$age <- age }, set_hair = function(hair) { self$hair <- hair }, greet = function() { paste0("こんにちは,", self$name, "です.") }, show_age = function() { private$get_age() - 5 }) ) Person #> <Person> object generator #> Public: #> name: NA #> hair: black #> initialize: function #> set_hair: function #> greet: function #> show_age: function #> Private: #> age: NA #> get_age: function #> Parent env: <environment: R_GlobalEnv> #> Lock: TRUE #> Portable: TRUE
  • 26. 25 R6Class()の実装 • R6Class() の戻り値=環境 – R6Class()の引数やnew()を要素に持つgenerator環境がR6クラスの実体 # encapsulate()はR6Classの親環境をcapsuleにする R6Class <- encapsulate(function(classname = NULL, public = list(), private = NULL, inherit = NULL, ...) { # ジェネレータオブジェクトの作成 generator <- new.env(parent = capsule) generator$self <- generator # selfはgenerator自身 generator$classname <- classname generator$public_fields <- get_nonfunctions(public) generator$private_fields <- get_nonfunctions(private) generator$public_methods <- get_functions(public) generator$private_methods <- get_functions(private) # generator_funsはnewを含む関数のリスト # generator_funcs$newの環境をgeneratorにする generator_funs <- assign_func_envs(generator_funs, generator) # generator_funs$newをgenerator$new にコピー list2env2(generator_funs, generator) class(generator) <- "R6ClassGenerator" generator })
  • 28. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 27
  • 29. 28 $new()の実装 • $new()の戻り値=環境 – R6オブジェクトの実体はpublic_bind_env環境 – generatorからpublic_bind_envにフィールドとメソッドをコピーする # publicフィールド・メソッドのみ,継承なしの場合 generator_funs$new <- function(...) { # publicオブジェクトの束縛環境を作成 public_bind_env <- new.env(parent = emptyenv(), hash = FALSE) # メソッドの環境を作成 enclos_env <- new.env(parent = parent_env, hash = FALSE) # selfの実体はpublic_bind_env enclos_env$self <- public_bind_env # generator$public_methodsの環境をenclos_envにして # public_bind_envにコピー public_methods <- assign_func_envs(public_methods, enclos_env) # フィールドとメソッドをpublic環境にコピー list2env2(public_methods, envir = public_bind_env) list2env2(public_fields, envir = public_bind_env) # オブジェクト初期化 public_bind_env$initialize(...) public_bind_env }
  • 30. 29 $new()の実装 public_fieldsと public_methodsのコピー generator [Person] self classname public_fields public_methods private_methods private_fields new function alice <- Person$new() initialize set_hair name greet hair function function function “black” “Alice” enclos_env public_bind_env [alice] self emptyenv()
  • 33. • R6パッケージとは • R6を使う – 既存のオブジェクト指向システム(S3, S4, RC) – R6の機能 • R6の中身をのぞいてみる – Rにおける環境 – R6Class()の実装 – $new()の実装 • まとめ 32
  • 34. まとめ • R6は新しいオブジェクト指向システム • R6の特徴 – 「普通の」オブジェクト指向っぽい • reference semantics • public / private – RCより速くて軽い • R6の実装 – 環境を活用したシンプルな実装 • 参考 – Introduction to R6 Classes • http://cran.r-project.org/web/packages/R6/vignettes/Introduction.html – Advanced R – Environments • http://adv-r.had.co.nz/Environments.html 33