43
Ruby リフレクション vol.3 KMC/Dept. Math., Kyoto U. 2011/09/10 (KMC/Dept. Math., Kyoto U.) Ruby リフレクション vol.3 2011/09/10 1 / 34

Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Rubyのリフレクション vol.3

大林一平

KMC/Dept. Math., Kyoto U.

2011/09/10

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 1 / 34

Page 2: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Agenda

自己紹介目標メタプログラミングについてRubyのメタプログラミングクラスと特異クラスModule#define method

define attr

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 2 / 34

Page 3: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

自己紹介

大林一平京大マイコンクラブ (KMC)

京都大学数学教室Ruby/SDL, RRSE

るりま

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 3 / 34

Page 4: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

目標

Rubyメタプログラミングに関する理解を深めること.私がRuby会議 2011でのLTの内容が理解できる程度をめざす.今回の話ではRubyのバージョンは 1.9.2を想定している

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 4 / 34

Page 5: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

メタプログラミング

メタプログラミングとは,プログラムをプログラムすること.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 5 / 34

Page 6: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

メタプログラミングの力

メタプログラミングで何ができるか?抽象化

I 通常の抽象化機構では実現できない種類の抽象化ができる

文法の拡張I 実現したいことをより「自然な書き方」で実現できる

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 6 / 34

Page 7: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

プログラムとは何か?

プログラム対象となるプログラムとは何か?

ソースコードAST

コンパイル済み実行バイナリ or バイトコード実行中のプログラム (実行時の状態)

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 7 / 34

Page 8: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

プログラムとは何か?

プログラム対象となるプログラムとは何か?ソースコードAST

コンパイル済み実行バイナリ or バイトコード実行中のプログラム (実行時の状態)

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 7 / 34

Page 9: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

ソースコードI ソースコードジェネレータI Cのマクロ

構文木/ASTI Lisp/SchemeのマクロI camlp4I C++のテンプレートもかなり特殊&限定的ながらここに含まれる

コンパイル済み実行バイナリ or バイトコードI Java関連ではわりとある

実行時の状態I 動的な言語ではこれが使えることが多い

これらのうち複数を組合せる場合もある

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 8 / 34

Page 10: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

また,実行前/実行時のいずれに実現するかでも分類できる

ソースコード生成I 実行前に生成→普通のコードジェネレータI 実行時に生成→ eval

構文木I Lisp/Schemeのマクロは実行前に構文木を操作するI LINQは実行時に構文木を見る

実行時環境は実行時にしか操れない実行前メタプログラミングは強力であるが,実行前の計算という実行時計算とは異なる計算モデルを持ち込むため,複雑になるという欠点がある.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 9 / 34

Page 11: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Rubyのメタプログラミング

基本的に実行時の操作I 実行前メタプログラミングのための特別の機能はないI 普通の Rubyプログラムの一部として実現されるI operationalに理解すれば良いので比較的わかりやすい

構文木の取得,操作は基本的にできないバイトコードも改変不可

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 10 / 34

Page 12: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

いつメタプログラミングするべきか

Rubyは十分高度で柔軟な抽象化機構をそなえているメタプログラミングはプログラムの理解を難しくするそのため,通常のスクリプティングでは必要ない高度な/特別な抽象化を必要とするのは,プログラムが大規模であったり,複数の人間がかかわるときライブラリとして高度な抽象化が必要な時などに有用

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 11 / 34

Page 13: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Rubyのメタプログラミングを学ぶために

Rubyの基本的なクラス (BasicObject, Object,Module, Class)が重要Rubyの内部構造について意識する

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 12 / 34

Page 14: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

クラス

クラスは以下の機能を持つオブジェクトであるメソッド,定数などを保持するメソッドを検索するそのクラスに属するオブジェクトを生成する

ここからオブジェクトを生成する機能を除いた機能を持つのがモジュールである.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 13 / 34

Page 15: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

メソッド呼びだし

Rubyではメソッド呼びだしは以下のように行なわれるオブジェクトの所属するクラスにメソッド探索を依頼する

I クラスは自分自身が保持しているメソッド群からその名前のものを探す

I もし見付からなかった場合は,スーパークラスに探索を依頼

もしメソッドが見付かったら,それを呼びだす見付からなかったら,method missingを呼びだす.

I 通常は,これが NoMethodError を生成する

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 14 / 34

Page 16: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異メソッドと特異クラス

ある一つのオブジェクトにしか定義されていないメソッドを特異メソッドと呼ぶ

I クラスメソッドはクラスオブジェクトの特異メソッドである

メソッドはクラスが保持するよって他のクラスと共有されないクラスが必要であるこれを特異クラスと呼ぶ実際にはリソースを節約するため,必要になるまでオブジェクトの特異クラスは生成されない

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 15 / 34

Page 17: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異メソッドと特異クラス

ある一つのオブジェクトにしか定義されていないメソッドを特異メソッドと呼ぶ

I クラスメソッドはクラスオブジェクトの特異メソッドである

メソッドはクラスが保持する

よって他のクラスと共有されないクラスが必要であるこれを特異クラスと呼ぶ実際にはリソースを節約するため,必要になるまでオブジェクトの特異クラスは生成されない

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 15 / 34

Page 18: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異メソッドと特異クラス

ある一つのオブジェクトにしか定義されていないメソッドを特異メソッドと呼ぶ

I クラスメソッドはクラスオブジェクトの特異メソッドである

メソッドはクラスが保持するよって他のクラスと共有されないクラスが必要である

これを特異クラスと呼ぶ実際にはリソースを節約するため,必要になるまでオブジェクトの特異クラスは生成されない

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 15 / 34

Page 19: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異メソッドと特異クラス

ある一つのオブジェクトにしか定義されていないメソッドを特異メソッドと呼ぶ

I クラスメソッドはクラスオブジェクトの特異メソッドである

メソッドはクラスが保持するよって他のクラスと共有されないクラスが必要であるこれを特異クラスと呼ぶ実際にはリソースを節約するため,必要になるまでオブジェクトの特異クラスは生成されない

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 15 / 34

Page 20: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異クラス

特異クラスを使うためには以下の文法を使う

class << obj

:

end

Object#singleton class というメソッドでオブジェクトの特異クラスを取り出すことができる.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 16 / 34

Page 21: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異クラス特異クラスは,以下のようにオブジェクトとそれが属するクラスの間に挟み込まれる.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 17 / 34

Page 22: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

特異クラスは,一般的には「クラスメソッド,モジュール関数,などの定義先」という使い方がなされる.また,様々なメタプログラミングのトリックのためにも用いられる.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 18 / 34

Page 23: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

演習問題

irbでObject#singleton classを呼びだしてみる.取り出した特異クラスを操作してみる

I instance methodsを呼びだしてみるI メソッドを定義する

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 19 / 34

Page 24: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

メソッド定義

メソッド定義は,通常,

class A

def f

:

end

:

end

というように,class ... end の間に,def ... end と書くことで行う.これによって,クラスAのメソッドテーブルに fを登録する.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 20 / 34

Page 25: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Module#define method

Module#define methodというメソッドでもメソッドを定義できる.使いかたは以下の通り

class A

define_method(:plus_1){|x| x+1}

end

これで 1を足した値を返すメソッドが定義される.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 21 / 34

Page 26: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

これにより,メソッドを定義するメソッドを定義できる

module A

def define_hello

define_method(:hello){ puts "Hello, world!" }

end

end

class B

extend A

define_hello

end

B.new.hello

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 22 / 34

Page 27: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Module#define methodのおもしろい所は,def ... endとは異なり,ローカル変数スコープを区切らないことである.

class A

y = 3

define_method(:plus_3){|x| x+y}

end

メソッドの実体を外からProcで持ってくることもできる所も興味深い.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 23 / 34

Page 28: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

演習問題

あるクラスに 0を返す zeroというメソッドをdefine methodsで定義するdefine zeroというメソッドを定義し,これを呼びだすと「そのクラスに 0を返す zeroというメソッドが定義される」ようにするdefine n というメソッドを定義し,これを呼びだすと「そのクラスに引数で渡したメソッドを返すnというメソッドが定義される」ようにする

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 24 / 34

Page 29: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

Module#define method応用編

ここまで話してきたことの応用として,クラス変数のようなものをクラス変数を使わずに定義するインスタンス変数のようなものをインスタンス変数を使わずに定義する

をやってみましょう.

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 25 / 34

Page 30: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

define method を使うと,クラス変数もどきを定義できるというのは,define method を嗜む Rubyist にはわりと良く知られた話です.

module A

def define_class_attr(name)

v = nil

define_method(name){ v }

define_method("#{name}="){|x| v = x}

end

end

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 26 / 34

Page 31: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

class X

extend A

define_class_attr :y

end

a = X.new

b = X.new

a.y = 2

a.y # => 2

b.y # => 2

b.y = 3

a.y # => 3

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 27 / 34

Page 32: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

では,インスタンス変数もどきは作れるか?

class Y

extend B

define_attr :z

end

a = Y.new

b = Y.new

a.z = 2

p a.z # => 2

p b.z # => nil

b.z = 3

p a.z # => 2

p b.z # => 3

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 28 / 34

Page 33: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

当然インスタンス変数は使わないとするI 値は適当な環境に保持させる

define attr の実行は一度しか行なわれないI すなわち各オブジェクトごとに環境を作ることはできない

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 29 / 34

Page 34: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

つまりオブジェクト毎に確実に呼ばれるメソッドを考える

new と initializeI initialize は何かと面倒I new を hook する

もう一つ存在するI 定義しようとしているメソッドそのもの

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 30 / 34

Page 35: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

つまりオブジェクト毎に確実に呼ばれるメソッドを考えるnew と initialize

I initialize は何かと面倒I new を hook する

もう一つ存在するI 定義しようとしているメソッドそのもの

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 30 / 34

Page 36: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

つまりオブジェクト毎に確実に呼ばれるメソッドを考えるnew と initialize

I initialize は何かと面倒I new を hook する

もう一つ存在する

I 定義しようとしているメソッドそのもの

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 30 / 34

Page 37: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

つまりオブジェクト毎に確実に呼ばれるメソッドを考えるnew と initialize

I initialize は何かと面倒I new を hook する

もう一つ存在するI 定義しようとしているメソッドそのもの

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 30 / 34

Page 38: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

というわけでこうなる

module B

def define_attr(name)

define_method(name) {

nil

}

define_method("#{name}="){|v|

singleton_class.module_eval {

define_method(name){ v }

define_method("#{name}="){|w| v = w}

}

v

}

end

end大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 31 / 34

Page 39: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

真面目にするんだったらスレッドについて考えましょう

I 要排他

そこまで真面目にするようなことか,という話もI marshaling で保存されない

define method で define methodI 共有される環境を好きに作れるI 他の使い道は何だろう?

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 32 / 34

Page 40: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

真面目にするんだったらスレッドについて考えましょう

I 要排他そこまで真面目にするようなことか,という話も

I marshaling で保存されない

define method で define methodI 共有される環境を好きに作れるI 他の使い道は何だろう?

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 32 / 34

Page 41: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

真面目にするんだったらスレッドについて考えましょう

I 要排他そこまで真面目にするようなことか,という話も

I marshaling で保存されないdefine method で define method

I 共有される環境を好きに作れるI 他の使い道は何だろう?

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 32 / 34

Page 42: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

質問

ご静聴ありがとうございました

質問をどうぞ

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 33 / 34

Page 43: Rubyのリフレクション vol - KMC · 2014-04-13 · メタプログラミングの力 メタプログラミングで何ができるか? 抽象化 I 通常の抽象化機構では実現できない種類の抽象化がで

代入するたびに再定義.

module D

def define_attr(name)

define_method(name) {

nil

}

define_method("#{name}="){|v|

singleton_class.module_eval {

define_method(name){ v }

}

v

}

end

end

大林一平 (KMC/Dept. Math., Kyoto U.) Ruby のリフレクション vol.3 2011/09/10 34 / 34