galaaz 2.1.7 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +39 -0
  3. data/Rakefile +20 -2
  4. data/bin/check_gemfile_lock_version +46 -0
  5. data/bin/release_bump +26 -0
  6. data/blogs/README.md +4 -0
  7. data/blogs/galaaz_2_0/galaaz_2_0.Rmd +385 -0
  8. data/blogs/galaaz_2_0/galaaz_2_0.md +409 -0
  9. data/blogs/galaaz_2_0/galaaz_2_0.tex +756 -0
  10. data/blogs/galaaz_2_0/images/galaaz-header.png +0 -0
  11. data/blogs/galaaz_2_0/images/galaaz-lockup-stacked.png +0 -0
  12. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +76 -58
  13. data/blogs/galaaz_ggplot/galaaz_ggplot.md +188 -161
  14. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +185 -117
  15. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
  16. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
  17. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
  18. data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
  19. data/blogs/galaaz_ggplot/images/galaaz-lockup-stacked.png +0 -0
  20. data/blogs/gknit/gknit.Rmd +48 -28
  21. data/blogs/gknit/gknit.md +60 -43
  22. data/blogs/gknit/gknit.tex +1409 -0
  23. data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
  24. data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
  25. data/blogs/gknit/gknit_files/figure-latex/bubble-1.png +0 -0
  26. data/blogs/gknit/images/galaaz-lockup-stacked.png +0 -0
  27. data/blogs/manual/images/galaaz-lockup-stacked.png +0 -0
  28. data/blogs/manual/manual.Rmd +161 -71
  29. data/blogs/manual/manual.md +573 -482
  30. data/blogs/manual/manual.tex +1113 -517
  31. data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
  32. data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
  33. data/blogs/manual/manual_files/figure-markdown_github/bubble-1.png +0 -0
  34. data/blogs/manual/manual_files/figure-markdown_github/diverging_bar.png +0 -0
  35. data/blogs/nse_dplyr/images/galaaz-lockup-stacked.png +0 -0
  36. data/blogs/nse_dplyr/nse_dplyr.Rmd +42 -8
  37. data/blogs/nse_dplyr/nse_dplyr.md +69 -50
  38. data/blogs/nse_dplyr/nse_dplyr.tex +1626 -0
  39. data/blogs/oh_my/images/galaaz-lockup-stacked.png +0 -0
  40. data/blogs/oh_my/oh_my.Rmd +206 -55
  41. data/blogs/oh_my/oh_my.md +247 -96
  42. data/blogs/oh_my/oh_my.tex +2038 -93
  43. data/blogs/r_on_rails_ledger/images/00_portfolio_page.png +0 -0
  44. data/blogs/r_on_rails_ledger/images/01_results_panel.png +0 -0
  45. data/blogs/r_on_rails_ledger/images/02_density_tail_risk.png +0 -0
  46. data/blogs/r_on_rails_ledger/images/03_mc_cone.png +0 -0
  47. data/blogs/r_on_rails_ledger/images/04_rolling_var.png +0 -0
  48. data/blogs/r_on_rails_ledger/images/galaaz-lockup-stacked.png +0 -0
  49. data/blogs/r_on_rails_ledger/r_on_rails_ledger.Rmd +354 -0
  50. data/blogs/r_on_rails_ledger/r_on_rails_ledger.md +365 -0
  51. data/blogs/r_on_rails_ledger/r_on_rails_ledger.tex +670 -0
  52. data/blogs/ruby_plot/images/galaaz-lockup-stacked.png +0 -0
  53. data/blogs/ruby_plot/ruby_plot.Rmd +56 -35
  54. data/blogs/ruby_plot/ruby_plot.md +63 -47
  55. data/blogs/ruby_plot/ruby_plot.tex +194 -125
  56. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
  57. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
  58. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
  59. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
  60. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
  61. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  62. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
  63. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
  64. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
  65. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
  66. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
  67. data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
  68. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  69. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  70. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  71. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  72. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  73. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  74. data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  75. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  76. data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  77. data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  78. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/dose_len.png +0 -0
  79. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
  80. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
  81. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
  82. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
  83. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
  84. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
  85. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
  86. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
  87. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
  88. data/blogs/ruby_plot/ruby_plot_files/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
  89. data/lib/galaaz/cli.rb +98 -13
  90. data/logos/icon-font/README.md +27 -0
  91. data/logos/icon-font/build_font.py +130 -0
  92. data/logos/icon-font/galaaz-mark.svg +34 -0
  93. data/script/omarchy/README.md +9 -2
  94. data/script/omarchy/fonts/galaaz.ttf +0 -0
  95. data/script/omarchy/galaaz-guide.sh +1 -1
  96. data/script/omarchy/install-galaaz.sh +8 -1
  97. data/script/omarchy/omarchy-menu.jsonc +21 -9
  98. data/sty/galaaz-header.png +0 -0
  99. data/sty/galaaz-headers-from-p3.tex +4 -0
  100. data/sty/galaaz.sty +76 -23
  101. data/version.rb +1 -1
  102. metadata +46 -7
  103. data/blogs/galaaz_ggplot/galaaz_ggplot.log +0 -754
  104. data/blogs/manual/manual.log +0 -1786
  105. data/blogs/nse_dplyr/nse_dplyr.log +0 -928
  106. data/blogs/oh_my/oh_my.log +0 -804
  107. data/blogs/ruby_plot/ruby_plot.log +0 -885
@@ -101,7 +101,7 @@
101
101
  \usepackage[utf8]{inputenc}
102
102
 
103
103
  \usepackage{geometry}
104
- \geometry{a4paper, top=1in}
104
+ \geometry{a4paper, top=1.05in, headheight=30pt, headsep=14pt}
105
105
 
106
106
  % needed for kableExtra
107
107
  \usepackage{longtable}
@@ -122,29 +122,60 @@
122
122
  \usepackage{graphicx}
123
123
 
124
124
  \usepackage{fancyhdr}
125
- % set the header and foot style
126
- % style 'fancy' adds the section name on the header
127
- % and the page number on the footer
125
+ % Header: small Galaaz mark (left); page number + section title (right),
126
+ % matching classic LaTeX style: "4 AN EXTENSION TO THE EXAMPLE"
127
+ % (upright page number, uppercase italic section name).
128
+ % Logo paths cover repo blogs (../../sty/), installed ~/sty/, and local images/.
129
+ % Blogs may delay headers with \renewcommand{\galaazheaderfrompage}{3} after this sty
130
+ % (e.g. skip title/TOC and a logo splash page).
131
+ \newcommand{\galaazheaderfrompage}{1}
132
+ \newcommand{\galaazheaderlogo}{%
133
+ \raisebox{-0.12\height}{%
134
+ \IfFileExists{../../sty/galaaz-header.png}{%
135
+ \includegraphics[height=0.32in]{../../sty/galaaz-header.png}%
136
+ }{%
137
+ \IfFileExists{galaaz-header.png}{%
138
+ \includegraphics[height=0.32in]{galaaz-header.png}%
139
+ }{%
140
+ \IfFileExists{images/galaaz-header.png}{%
141
+ \includegraphics[height=0.32in]{images/galaaz-header.png}%
142
+ }{}%
143
+ }%
144
+ }%
145
+ }%
146
+ }
147
+ % Section title only in marks (no \thesection); page number is separate.
148
+ \renewcommand{\sectionmark}[1]{\markboth{#1}{}}
149
+ \renewcommand{\subsectionmark}[1]{}% keep the current section in the header
150
+ \newcommand{\galaazmaybeheaderlogo}{%
151
+ \ifnum\value{page}<\galaazheaderfrompage\relax\else\galaazheaderlogo\fi}
152
+ \newcommand{\galaazmayberighthead}{%
153
+ \ifnum\value{page}<\galaazheaderfrompage\relax
154
+ \else
155
+ \textup{\thepage}\hspace{1em}\textit{\MakeUppercase{\leftmark}}%
156
+ \fi
157
+ }
128
158
  \pagestyle{fancy}
129
-
130
- % style 'fancyhf' leaves header and footer empty
131
- %\fancyhf{}
132
-
133
- % sets the left head element to \rightmark, which contains the
134
- % current section (\leftmark is the current chapter)
135
- %\fancyhead[L]{\rightmark} .
136
-
137
- % sets the right head element to the page number.
138
- % \fancyhead[R]{\thepage}
139
-
140
- % lets the head rule disappear.
141
- % \renewcommand{\headrulewidth}{0pt}
142
- % Possible selectors for the optional argument of \fancyhead/\fancyfoot
143
- % are L (left), C (center) or R (right) for the position of the element
144
- % and E (even) or O (odd) to distinguish even and odd pages. If you omit
145
- % E/O the element is set for all pages.
146
-
147
- % \usepackage{lipsum}
159
+ \fancyhf{}
160
+ \fancyhead[L]{\galaazmaybeheaderlogo}
161
+ \fancyhead[R]{\galaazmayberighthead}
162
+ \renewcommand{\headrulewidth}{0.3pt}
163
+ \makeatletter
164
+ \renewcommand{\headrule}{%
165
+ \ifnum\value{page}<\galaazheaderfrompage\relax
166
+ \else
167
+ \hrule\@height\headrulewidth\@width\headwidth
168
+ \vskip-\headrulewidth
169
+ \fi
170
+ }
171
+ \makeatother
172
+ % First page often uses plain; same conditional header logic.
173
+ \fancypagestyle{plain}{%
174
+ \fancyhf{}%
175
+ \fancyhead[L]{\galaazmaybeheaderlogo}%
176
+ \fancyhead[R]{\galaazmayberighthead}%
177
+ \renewcommand{\headrulewidth}{0.3pt}%
178
+ }
148
179
 
149
180
  % make available command lastpage
150
181
  \usepackage{lastpage}
@@ -165,8 +196,34 @@
165
196
  % Command to import an R variable to latex
166
197
  \newcommand{\RtoLatex}[2]{\newcommand{#1}{#2}}
167
198
 
199
+ % Soft-wrap Pandoc highlighted code/output boxes (Shaded + Highlighting).
200
+ % This runs after Pandoc's default \DefineVerbatimEnvironment{Highlighting}
201
+ % (header includes come later in the generated .tex). Prefer manual line
202
+ % breaks in Rmd sources; breaklines is a safety net for leftovers/output.
203
+ % Requires TinyTeX/TeX Live package: tlmgr install fvextra
204
+ \IfFileExists{fvextra.sty}{%
205
+ \usepackage{fvextra}%
206
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
207
+ breaklines=true,
208
+ breakanywhere=true,
209
+ breakindent=1.5em,
210
+ fontsize=\small,
211
+ commandchars=\\\{\}%
212
+ }%
213
+ }{%
214
+ % fancyvrb is already loaded by Pandoc; shrink code so more fits per line.
215
+ \DefineVerbatimEnvironment{Highlighting}{Verbatim}{%
216
+ fontsize=\small,
217
+ commandchars=\\\{\}%
218
+ }%
219
+ }
220
+
168
221
  %
169
222
  %\newcommand{\atraso}[1]{\color{red} \textbf {Tempo desde a Assinatura do Contrato: #1 dias}}
223
+ % No header on title/TOC (p.1) or splash logo page (p.2);
224
+ % logo + page number + section title from page 3 onward.
225
+ % Load after galaaz.sty.
226
+ \renewcommand{\galaazheaderfrompage}{3}
170
227
  \usepackage{bookmark}
171
228
  \IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
172
229
  \urlstyle{same}
@@ -187,10 +244,12 @@
187
244
  \setcounter{tocdepth}{2}
188
245
  \tableofcontents
189
246
  }
247
+ \begin{center}\includegraphics[width=0.45\linewidth]{images/galaaz-lockup-stacked} \end{center}
248
+
190
249
  \section{Introduction}\label{introduction}
191
250
 
192
- This paper introduces and compares Galaaz with R's S4. It is a shameless
193
- rip off of
251
+ This paper introduces and compares Galaaz with R's S4. It is
252
+ \textbf{modeled closely} on
194
253
  \href{https://cran.r-project.org/doc/contrib/Genolini-S4tutorialV0-5en.pdf}{``A
195
254
  `(not so)' Short Introduction to S4''} by Christophe Genolini and
196
255
  follows the same structure and examples presented there.
@@ -202,13 +261,13 @@ between RinRuby or similar solutions in Python, such as
202
261
  \href{https://pypi.python.org/pypi/PypeR/1.1.0}{PypeR},
203
262
  \href{http://rpy2.bitbucket.org/}{rpy2} and other similar solutions.
204
263
 
205
- \textbf{Galaaz 2.0} runs on
206
- \textbf{\href{https://www.jruby.org/}{JRuby}} and drives \textbf{GNU R}
207
- through a \textbf{bridge}, so Ruby code can create and manipulate R
208
- objects and call R functions while staying idiomatic Ruby. An earlier
209
- prototype used Oracle's \textbf{GraalVM} with \textbf{TruffleRuby} and
210
- \textbf{FastR}; that stack is historical and is \textbf{not} what
211
- current Galaaz targets.
264
+ \textbf{Galaaz 2.0} supports
265
+ \textbf{\href{https://www.jruby.org/}{JRuby}} or \textbf{CRuby} equally
266
+ and drives \textbf{GNU R} through a \textbf{bridge}, so Ruby code can
267
+ create and manipulate R objects and call R functions while staying
268
+ idiomatic Ruby. An earlier prototype used Oracle's \textbf{GraalVM} with
269
+ \textbf{TruffleRuby} and \textbf{FastR}; that stack is historical and is
270
+ \textbf{not} what current Galaaz targets.
212
271
 
213
272
  \section{Bases of Object Programming}\label{bases-of-object-programming}
214
273
 
@@ -244,7 +303,7 @@ also not a ``compile'' time type, since R is not compiled. The type is
244
303
  checked at runtime. The same checking can be done in Ruby and we will do
245
304
  it later in this document.
246
305
 
247
- In the example bellow, we create class Trajectories with two instance
306
+ In the example below, we create class Trajectories with two instance
248
307
  variables, `times' and `matrix'. We will not go over the details of
249
308
  instance variables in Ruby, but here we created those variables with the
250
309
  keyword `attr\_reader' and a colom before the variables name:
@@ -259,8 +318,8 @@ keyword `attr\_reader' and a colom before the variables name:
259
318
  \end{Shaded}
260
319
 
261
320
  In order to create a new instance of object Trajectories we call method
262
- new on the class and we can store the result in a varible (not an
263
- instance variable) as bellow:
321
+ new on the class and we can store the result in a variable (not an
322
+ instance variable) as below:
264
323
 
265
324
  \begin{Shaded}
266
325
  \begin{Highlighting}[]
@@ -279,7 +338,7 @@ contents as in R.
279
338
  \end{Shaded}
280
339
 
281
340
  \begin{verbatim}
282
- ## #<RC::Trajectories:0x378c2595>
341
+ ## #<RC::Trajectories:0x7df91b21>
283
342
  \end{verbatim}
284
343
 
285
344
  To see the contents of an object, one needs to access its components
@@ -297,7 +356,7 @@ Since there is no content stored in `times' nor `matrix', nil is
297
356
  returned. In order to add a value in the variables, we need to add a
298
357
  constructor to the class Trajectories. In R, a constructor is build by
299
358
  default, in Ruby, this has to be created by adding a method called
300
- `initialize'. In the example bellow, we will create the initializer that
359
+ `initialize'. In the example below, we will create the initializer that
301
360
  accepts two values, a `times' value and a `matrix' value and they are
302
361
  used to initialize the value of the instance variables:
303
362
 
@@ -336,7 +395,7 @@ Since Galaaz is Ruby and not R, some syntax adjustments are sometimes
336
395
  necessary. For instance, in R, a range is represented as `(1:4)', in
337
396
  Ruby, the same range is represented as `(1..4)'. When passing arguments
338
397
  to an R function in R one uses the `=' sign after the slot name; in R,
339
- one uses the `:' operator after parameter's name as we can see bellow:
398
+ one uses the `:' operator after parameter's name as we can see below:
340
399
 
341
400
  \begin{Shaded}
342
401
  \begin{Highlighting}[]
@@ -344,7 +403,8 @@ one uses the `:' operator after parameter's name as we can see bellow:
344
403
  \OtherTok{@traj} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{, }\DecValTok{4}\NormalTok{))}
345
404
 
346
405
  \CommentTok{\# Create a Trajectories with times and matrix}
347
- \OtherTok{@traj2} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{3}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{4}\NormalTok{), }\WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
406
+ \OtherTok{@traj2} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{3}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{4}\NormalTok{),}
407
+ \WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
348
408
  \end{Highlighting}
349
409
  \end{Shaded}
350
410
 
@@ -411,7 +471,8 @@ R and the corresponding Galaaz:
411
471
  + times=c(1: 10, (6: 16) *2),
412
472
  + traj=rbind(
413
473
  + matrix (seq (16,19, length=21), ncol=21, nrow=50, byrow=TRUE),
414
- + matrix (seq (15.8, 18, length=21), ncol=21, nrow=30, byrow=TRUE)
474
+ + matrix (seq (15.8, 18, length=21), ncol=21, nrow=30,
475
+ byrow=TRUE)
415
476
  + )+rnorm (21*80,0,0.2)
416
477
  + )
417
478
  \end{verbatim}
@@ -430,12 +491,16 @@ This same code in Galaaz becomes:
430
491
  \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\FloatTok{15.7}\NormalTok{, }\FloatTok{15.6}\NormalTok{, }\FloatTok{15.8}\NormalTok{, }\DecValTok{16}\NormalTok{)))}
431
492
 
432
493
  \OtherTok{@trajStAnne} \OperatorTok{=}
433
- \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{10}\NormalTok{), }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{6}\OperatorTok{..}\DecValTok{16}\NormalTok{) }\OperatorTok{*} \DecValTok{2}\NormalTok{),}
434
- \WarningTok{matrix:}\NormalTok{ (}\ConstantTok{R}\AttributeTok{.rbind}\NormalTok{(}
435
- \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{(}\ConstantTok{R}\AttributeTok{.seq}\NormalTok{(}\DecValTok{16}\NormalTok{, }\DecValTok{19}\NormalTok{, }\WarningTok{length:} \DecValTok{21}\NormalTok{), }\WarningTok{ncol:} \DecValTok{21}\NormalTok{,}
436
- \WarningTok{nrow:} \DecValTok{50}\NormalTok{, }\WarningTok{byrow:} \DecValTok{true}\NormalTok{),}
437
- \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{(}\ConstantTok{R}\AttributeTok{.seq}\NormalTok{(}\FloatTok{15.8}\NormalTok{, }\DecValTok{18}\NormalTok{, }\WarningTok{length:} \DecValTok{21}\NormalTok{), }\WarningTok{ncol:} \DecValTok{21}\NormalTok{,}
438
- \WarningTok{nrow:} \DecValTok{30}\NormalTok{, }\WarningTok{byrow:} \DecValTok{true}\NormalTok{)) }\OperatorTok{+} \ConstantTok{R}\AttributeTok{.rnorm}\NormalTok{(}\DecValTok{21}\OperatorTok{*}\DecValTok{80}\NormalTok{, }\DecValTok{0}\NormalTok{, }\FloatTok{0.2}\NormalTok{)))}
494
+ \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}
495
+ \WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{10}\NormalTok{), }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{6}\OperatorTok{..}\DecValTok{16}\NormalTok{) }\OperatorTok{*} \DecValTok{2}\NormalTok{),}
496
+ \WarningTok{matrix:}\NormalTok{ (}
497
+ \ConstantTok{R}\AttributeTok{.rbind}\NormalTok{(}
498
+ \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{(}\ConstantTok{R}\AttributeTok{.seq}\NormalTok{(}\DecValTok{16}\NormalTok{, }\DecValTok{19}\NormalTok{, }\WarningTok{length:} \DecValTok{21}\NormalTok{),}
499
+ \WarningTok{ncol:} \DecValTok{21}\NormalTok{, }\WarningTok{nrow:} \DecValTok{50}\NormalTok{, }\WarningTok{byrow:} \DecValTok{true}\NormalTok{),}
500
+ \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{(}\ConstantTok{R}\AttributeTok{.seq}\NormalTok{(}\FloatTok{15.8}\NormalTok{, }\DecValTok{18}\NormalTok{, }\WarningTok{length:} \DecValTok{21}\NormalTok{),}
501
+ \WarningTok{ncol:} \DecValTok{21}\NormalTok{, }\WarningTok{nrow:} \DecValTok{30}\NormalTok{, }\WarningTok{byrow:} \DecValTok{true}\NormalTok{)}
502
+ \NormalTok{ ) }\OperatorTok{+} \ConstantTok{R}\AttributeTok{.rnorm}\NormalTok{(}\DecValTok{21} \OperatorTok{*} \DecValTok{80}\NormalTok{, }\DecValTok{0}\NormalTok{, }\FloatTok{0.2}\NormalTok{)}
503
+ \NormalTok{ ))}
439
504
  \end{Highlighting}
440
505
  \end{Shaded}
441
506
 
@@ -455,11 +520,11 @@ correctly set:
455
520
  \begin{verbatim}
456
521
  ## [1] 1 3 4 5
457
522
  ##
458
- ## [,1] [,2] [,3] [,4]
459
- ## g2_v2114 15.0 15.1 15.2 15.2
460
- ## g2_v2115 16.0 15.9 16.0 16.4
461
- ## g2_v2116 15.2 NA 15.3 15.3
462
- ## g2_v2117 15.7 15.6 15.8 16.0
523
+ ## [,1] [,2] [,3] [,4]
524
+ ## g2_v729 15.0 15.1 15.2 15.2
525
+ ## g2_v730 16.0 15.9 16.0 16.4
526
+ ## g2_v731 15.2 NA 15.3 15.3
527
+ ## g2_v732 15.7 15.6 15.8 16.0
463
528
  ##
464
529
  ## [1] 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 24 26 28 30 32
465
530
  \end{verbatim}
@@ -477,7 +542,7 @@ default values in this document, with the default being `nil'. This was
477
542
  necessary in order to be able to create our constructor and passing it
478
543
  the proper values.
479
544
 
480
- In the example bellow, a class TrajectoriesBis is created with default
545
+ In the example below, a class TrajectoriesBis is created with default
481
546
  value 1 for times and a matrix with no elements in matrix.
482
547
 
483
548
  \begin{Shaded}
@@ -596,7 +661,7 @@ method `plot' is added to Trajectories. At this point, Renjin and Galaaz
596
661
  do not yet have plotting capabilities, so we will have to skip this
597
662
  method and go directly to the implementation of the `print' method.
598
663
 
599
- Bellow is the R code for method print:
664
+ Below is the R code for method print:
600
665
 
601
666
  \begin{verbatim}
602
667
  > setMethod ("print","Trajectories",
@@ -672,11 +737,11 @@ Trajectories's print we need to write `Kernel.print'.
672
737
  ## 4
673
738
  ## 5
674
739
  ## traj =
675
- ## [,1] [,2] [,3] [,4]
676
- ## g2_v2114 15.0 15.1 15.2 15.2
677
- ## g2_v2115 16.0 15.9 16.0 16.4
678
- ## g2_v2116 15.2 NA 15.3 15.3
679
- ## g2_v2117 15.7 15.6 15.8 16.0
740
+ ## [,1] [,2] [,3] [,4]
741
+ ## g2_v729 15.0 15.1 15.2 15.2
742
+ ## g2_v730 16.0 15.9 16.0 16.4
743
+ ## g2_v731 15.2 NA 15.3 15.3
744
+ ## g2_v732 15.7 15.6 15.8 16.0
680
745
  ## ******* End Print (trajectories) *******
681
746
  \end{verbatim}
682
747
 
@@ -718,15 +783,17 @@ we have already seen, others will be described now:
718
783
  look like a method of the object. For instance, R.nrow(@matrix), can
719
784
  be called by doing @matrix.nrow;
720
785
  \item
721
- In R, every number is converted to a vector and this can be done with
722
- method R.i. Converting a vector with only one number back to a number
723
- can be done with method `.gz'. So if @num is an R vector that holds a
724
- number, then @num.gz is a number that can be used normally with Ruby
725
- methods;
786
+ In R, every number is a length-1 vector. In Galaaz 2.0, unwrap a
787
+ length-1 R vector to a Ruby number with
788
+ \texttt{\textgreater{}\textgreater{}\ 0} (or
789
+ \texttt{unboxed\_get(0)}). Older Galaaz docs used \texttt{.gz} /
790
+ \texttt{\textless{}\textless{}\ 0} for the same idea;
791
+ \texttt{\textless{}\textless{}} still works as a compatibility alias
792
+ for \texttt{\textgreater{}\textgreater{}};
726
793
  \item
727
794
  R functions and Ruby methods can be used freely in Galaaz. We show
728
- bellow two different ways of getting the minimum of a number, either
729
- by calling R.min or by getting the minimum of an array, with the min
795
+ below two different ways of getting the minimum of a number, either by
796
+ calling R.min or by getting the minimum of an array, with the min
730
797
  method;
731
798
  \item
732
799
  Galaaz allows for method `chaining'. Method chaining, also known as
@@ -734,16 +801,16 @@ we have already seen, others will be described now:
734
801
  calls in object-oriented programming languages. Each method returns an
735
802
  object, allowing the calls to be chained together in a single
736
803
  statement without requiring variables to store the intermediate
737
- results. For instance @matrix.nrow.gz, which returns the number of
738
- rows of the matrix as a number;
804
+ results. For instance
805
+ \texttt{@matrix.nrow\ \textgreater{}\textgreater{}\ 0}, which returns
806
+ the number of rows of the matrix as a Ruby number;
739
807
  \item
740
808
  Ranges in Ruby are represented by (x..y), where x is the beginning of
741
809
  the range and y its end. An R matrix can be indexed by range,
742
810
  \href{mailto:object@traj}{\nolinkurl{object@traj}}{[}1:nrowShow,1:ncolShow{]},
743
811
  the same result is obtained in Galaaz by indexing @matrix
744
812
  {[}(1..nrow\_show), (1..ncol\_show){]}. Observe that this statement is
745
- then chained with the format function and with the pp method to print
746
- the matrix.
813
+ then chained with the format function and printed with \texttt{puts}.
747
814
  \end{itemize}
748
815
 
749
816
  \begin{Shaded}
@@ -758,10 +825,11 @@ we have already seen, others will be described now:
758
825
  \FunctionTok{puts}\NormalTok{(}\StringTok{"*** Class Trajectories, method Show *** "}\NormalTok{)}
759
826
  \DataTypeTok{Kernel}\AttributeTok{.print}\NormalTok{(}\StringTok{"times = "}\NormalTok{)}
760
827
  \FunctionTok{puts} \OtherTok{@times}
761
- \NormalTok{ nrow\_show }\OperatorTok{=} \KeywordTok{[}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.nrow} \OperatorTok{\textless{}\textless{}} \DecValTok{0}\KeywordTok{]}\AttributeTok{.min}
762
- \NormalTok{ ncol\_show }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.min}\NormalTok{(}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.ncol}\NormalTok{) }\OperatorTok{\textless{}\textless{}} \DecValTok{0}
828
+ \NormalTok{ nrow\_show }\OperatorTok{=} \KeywordTok{[}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.nrow} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\KeywordTok{]}\AttributeTok{.min}
829
+ \NormalTok{ ncol\_show }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.min}\NormalTok{(}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.ncol}\NormalTok{) }\OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
763
830
  \FunctionTok{puts}\NormalTok{(}\StringTok{"* Traj (limited to a matrix 10x10) = "}\NormalTok{)}
764
- \FunctionTok{puts} \OtherTok{@matrix}\KeywordTok{[}\NormalTok{(}\DecValTok{1}\OperatorTok{..}\NormalTok{nrow\_show), (}\DecValTok{1}\OperatorTok{..}\NormalTok{ncol\_show)}\KeywordTok{]}\AttributeTok{.format}\NormalTok{(}\WarningTok{digits:} \DecValTok{2}\NormalTok{, }\WarningTok{nsmall:} \DecValTok{2}\NormalTok{)}
831
+ \FunctionTok{puts} \OtherTok{@matrix}\KeywordTok{[}\NormalTok{(}\DecValTok{1}\OperatorTok{..}\NormalTok{nrow\_show), (}\DecValTok{1}\OperatorTok{..}\NormalTok{ncol\_show)}\KeywordTok{]}\AttributeTok{.format}\NormalTok{(}\WarningTok{digits:} \DecValTok{2}\NormalTok{,}
832
+ \WarningTok{nsmall:} \DecValTok{2}\NormalTok{)}
765
833
  \FunctionTok{puts}\NormalTok{(}\StringTok{"******* End Show (trajectories) ******* "}\NormalTok{)}
766
834
  \ControlFlowTok{end}
767
835
 
@@ -776,26 +844,52 @@ we have already seen, others will be described now:
776
844
  \end{Shaded}
777
845
 
778
846
  \begin{verbatim}
779
- ## parse error
780
- \end{verbatim}
781
-
782
- \begin{verbatim}
783
- ## /home/rbotafogo/desenv_linux/galaaz/lib/new_bridge/session_client.rb:268:in 'eval_r'
784
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/new_bridge_adapter.rb:231:in 'eval_r_with_result'
785
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/rsupport.rb:359:in 'exec_function'
786
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/rsupport.rb:618:in 'process_missing_dispatch'
787
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/rsupport.rb:468:in 'process_missing'
788
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/robject.rb:404:in 'method_missing'
789
- ## /home/rbotafogo/desenv_linux/galaaz/lib/util/exec_ruby.rb:180:in 'show'
790
- ## /home/rbotafogo/desenv_linux/galaaz/lib/util/exec_ruby.rb:170:in 'exec_ruby'
791
- ## org/jruby/RubyKernel.java:1268:in 'eval'
792
- ## /home/rbotafogo/desenv_linux/galaaz/lib/util/exec_ruby.rb:169:in 'exec_ruby'
793
- ## /home/rbotafogo/desenv_linux/galaaz/lib/gknit/knitr_engine.rb:777:in 'block in initialize'
794
- ## org/jruby/RubyBasicObject.java:2695:in 'instance_eval'
795
- ## org/jruby/RubyBasicObject.java:2723:in 'instance_eval'
796
- ## /home/rbotafogo/desenv_linux/galaaz/lib/gknit/knitr_engine.rb:748:in 'block in initialize'
797
- ## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/new_bridge_adapter.rb:358:in 'block in register_callback_proc_stub'
798
- ## /home/rbotafogo/desenv_linux/galaaz/lib/new_bridge/session_client.rb:413:in 'block in handle_call'
847
+ ## *** Class Trajectories, method Show ***
848
+ ## times = 1
849
+ ## 2
850
+ ## 3
851
+ ## 4
852
+ ## 5
853
+ ## 6
854
+ ## 7
855
+ ## 8
856
+ ## 9
857
+ ## 10
858
+ ## 12
859
+ ## 14
860
+ ## 16
861
+ ## 18
862
+ ## 20
863
+ ## 22
864
+ ## 24
865
+ ## 26
866
+ ## 28
867
+ ## 30
868
+ ## 32
869
+ ## * Traj (limited to a matrix 10x10) =
870
+ ## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
871
+ ## [1,] "16.25" "16.49" "16.28" "16.18" "16.59" "16.78" "16.93" "17.34"
872
+ ## [2,] "16.00" "16.39" "16.54" "16.74" "16.74" "16.69" "16.52" "16.79"
873
+ ## [3,] "16.03" "16.48" "16.21" "16.34" "16.46" "16.99" "17.07" "17.04"
874
+ ## [4,] "16.18" "16.03" "16.22" "16.38" "16.74" "16.83" "16.94" "17.04"
875
+ ## [5,] "16.11" "15.72" "16.01" "16.32" "16.27" "16.68" "17.18" "16.95"
876
+ ## [6,] "16.03" "16.17" "16.13" "16.60" "17.02" "16.57" "17.26" "16.91"
877
+ ## [7,] "15.99" "16.10" "16.51" "16.39" "16.97" "16.82" "16.74" "17.10"
878
+ ## [8,] "16.32" "15.85" "16.65" "16.33" "16.60" "15.93" "16.77" "17.19"
879
+ ## [9,] "16.13" "16.41" "16.56" "16.47" "16.71" "16.59" "16.94" "16.83"
880
+ ## [10,] "15.77" "16.23" "16.28" "16.27" "16.83" "16.32" "16.86" "16.74"
881
+ ## [,9] [,10]
882
+ ## [1,] "17.20" "17.30"
883
+ ## [2,] "17.26" "17.50"
884
+ ## [3,] "17.10" "17.00"
885
+ ## [4,] "17.20" "17.33"
886
+ ## [5,] "17.33" "17.15"
887
+ ## [6,] "17.24" "17.45"
888
+ ## [7,] "17.07" "17.65"
889
+ ## [8,] "16.81" "17.63"
890
+ ## [9,] "17.24" "17.47"
891
+ ## [10,] "16.92" "17.42"
892
+ ## ******* End Show (trajectories) *******
799
893
  \end{verbatim}
800
894
 
801
895
  Our show method has the same problem as SS4, i.e., if an empty
@@ -810,12 +904,1863 @@ an error. Let's see it:
810
904
 
811
905
  \begin{Shaded}
812
906
  \begin{Highlighting}[]
813
- \OtherTok{@empty\_traj}\AttributeTok{.show}
907
+ \ControlFlowTok{begin}
908
+ \OtherTok{@empty\_traj}\AttributeTok{.show}
909
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
910
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
911
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
912
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
913
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
914
+ \ControlFlowTok{end}
814
915
  \end{Highlighting}
815
916
  \end{Shaded}
816
917
 
817
918
  \begin{verbatim}
919
+ ## *** Class Trajectories, method Show ***
920
+ ## times =
921
+ ## NoMethodError
818
922
  ## undefined method 'nrow' for nil
819
923
  \end{verbatim}
820
924
 
925
+ In this example, \texttt{@matrix} is \texttt{nil}, so calling
926
+ \texttt{@matrix.nrow} raises
927
+ \texttt{undefined\ method\ \textquotesingle{}nrow\textquotesingle{}\ for\ nil}.
928
+ To fix this, we can either prevent an empty trajectories class from
929
+ being created, or make sure that method \texttt{show} will not choke on
930
+ the empty object. We will take the second alternative, to follow SS4,
931
+ and will check if either \texttt{@times} or \texttt{@matrix} is empty.
932
+ If either one of them is \texttt{nil}, then we will print a message
933
+ saying so.
934
+
935
+ Although the first alternative, i.e., not allow for empty objects is a
936
+ possibility in Ruby, it seems that this is not the case for S4.
937
+
938
+ \begin{Shaded}
939
+ \begin{Highlighting}[]
940
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
941
+
942
+ \ControlFlowTok{def}\NormalTok{ show}
943
+ \ControlFlowTok{if}\NormalTok{ (}\OtherTok{@times}\AttributeTok{.nil?} \OperatorTok{||} \OtherTok{@matrix}\AttributeTok{.nil?}\NormalTok{)}
944
+ \FunctionTok{puts}\NormalTok{(}\StringTok{"*** Class Trajectories is empty!! *** "}\NormalTok{)}
945
+ \ControlFlowTok{return}
946
+ \ControlFlowTok{end}
947
+ \FunctionTok{puts}\NormalTok{(}\StringTok{"*** Class Trajectories, method Show *** "}\NormalTok{)}
948
+ \DataTypeTok{Kernel}\AttributeTok{.print}\NormalTok{(}\StringTok{"times = "}\NormalTok{)}
949
+ \FunctionTok{puts} \OtherTok{@times}
950
+ \NormalTok{ nrow\_show }\OperatorTok{=} \KeywordTok{[}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.nrow} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\KeywordTok{]}\AttributeTok{.min}
951
+ \NormalTok{ ncol\_show }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.min}\NormalTok{(}\DecValTok{10}\NormalTok{, }\OtherTok{@matrix}\AttributeTok{.ncol}\NormalTok{) }\OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
952
+ \FunctionTok{puts}\NormalTok{(}\StringTok{"* Traj (limited to a matrix 10x10) = "}\NormalTok{)}
953
+ \FunctionTok{puts} \OtherTok{@matrix}\KeywordTok{[}\NormalTok{(}\DecValTok{1}\OperatorTok{..}\NormalTok{nrow\_show), (}\DecValTok{1}\OperatorTok{..}\NormalTok{ncol\_show)}\KeywordTok{]}\AttributeTok{.format}\NormalTok{(}\WarningTok{digits:} \DecValTok{2}\NormalTok{,}
954
+ \WarningTok{nsmall:} \DecValTok{2}\NormalTok{)}
955
+ \FunctionTok{puts}\NormalTok{(}\StringTok{"******* End Show (trajectories) ******* "}\NormalTok{)}
956
+ \ControlFlowTok{end}
957
+
958
+ \ControlFlowTok{end}
959
+ \end{Highlighting}
960
+ \end{Shaded}
961
+
962
+ \begin{Shaded}
963
+ \begin{Highlighting}[]
964
+ \OtherTok{@empty\_traj}\AttributeTok{.show}
965
+ \end{Highlighting}
966
+ \end{Shaded}
967
+
968
+ \begin{verbatim}
969
+ ## *** Class Trajectories is empty!! ***
970
+ \end{verbatim}
971
+
972
+ \section{To Remove an Object}\label{to-remove-an-object}
973
+
974
+ As far as I know, there isn't a good way of removing a defined class,
975
+ but there might be one and the interested user is directed to google it!
976
+ In principle, there should not be any real need to remove a defined
977
+ class. Both in R and Galaaz, large programs are usually written in a
978
+ file and the file loaded. If one writes a wrong class, the better
979
+ solution is to correct it and then load it again. If the class is
980
+ written directly on the console, then leaving it there will not have any
981
+ serious impact.
982
+
983
+ \section{Method count\_missing}\label{method-count_missing}
984
+
985
+ In R, methods `print' and `show' are methods that already exist. SS4
986
+ wants to add a method called `countMissing' which does not exist in R,
987
+ and thus requires some special preparation. In Ruby, every method we've
988
+ created is a new method that exists inside the class. The fact that
989
+ `print' happens to be also a method for class Kernel and `show' is not,
990
+ is not of special interest. Actually we've seen that in order to call
991
+ method print from the Kernel class we had to call Kernel.print.
992
+
993
+ To create method `count\_missing' we just need to reopen the
994
+ Trajectories class and add the method the same way we've done with
995
+ method `show'. Again, let's first look at R's `countMissing' and then at
996
+ Ruby's:
997
+
998
+ \begin{verbatim}
999
+ > setMethod(
1000
+ + f= "countMissing",
1001
+ + signature= "Trajectories",
1002
+ + definition=function(object){
1003
+ + return(sum(is.na(object@traj)))
1004
+ + }
1005
+ + )
1006
+ \end{verbatim}
1007
+
1008
+ Here we introduce another particular case of Galaaz. R has many methods
1009
+ that have a `.' in their names, such as `is.na'. In Ruby, the dot `.'
1010
+ has a special meaning as it is the way we call a method on an object.
1011
+ Doing `R.is.na' will not work. So, in Galaaz, R functions that have a
1012
+ dot in them will have the dot substituted by '\_\_'. So, method is.na in
1013
+ Galaaz, becomes R.is\_\_na. In method count\_missing we use method
1014
+ chaining and convert the final count to a Ruby number with
1015
+ \texttt{\textgreater{}\textgreater{}\ 0} (unbox).
1016
+
1017
+ \begin{Shaded}
1018
+ \begin{Highlighting}[]
1019
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1020
+
1021
+ \ControlFlowTok{def}\NormalTok{ count\_missing}
1022
+ \ControlFlowTok{return} \OtherTok{@matrix}\AttributeTok{.is\_\_na.sum} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
1023
+ \ControlFlowTok{end}
1024
+
1025
+ \ControlFlowTok{end}
1026
+ \end{Highlighting}
1027
+ \end{Shaded}
1028
+
1029
+ \begin{Shaded}
1030
+ \begin{Highlighting}[]
1031
+ \FunctionTok{puts} \OtherTok{@trajCochin}\AttributeTok{.count\_missing}
1032
+ \end{Highlighting}
1033
+ \end{Shaded}
1034
+
1035
+ \begin{verbatim}
1036
+ ## 1
1037
+ \end{verbatim}
1038
+
1039
+ \section{To See the Methods}\label{to-see-the-methods}
1040
+
1041
+ In order to see the methods we have defined so far, we call on class
1042
+ Trajectories the method `instance\_methods' passing it one argument,
1043
+ `false', as follows:
1044
+
1045
+ \begin{Shaded}
1046
+ \begin{Highlighting}[]
1047
+ \FunctionTok{puts} \DataTypeTok{Trajectories}\AttributeTok{.instance\_methods}\NormalTok{(}\DecValTok{false}\NormalTok{)}
1048
+ \end{Highlighting}
1049
+ \end{Shaded}
1050
+
1051
+ \begin{verbatim}
1052
+ ## count_missing
1053
+ ## times
1054
+ ## print
1055
+ ## show
1056
+ ## matrix
1057
+ \end{verbatim}
1058
+
1059
+ It is interesting to observe that we see our three methods
1060
+ `count\_missing', `print' and `show', but we also see two other methods
1061
+ `times' and `matrix', but those last two as far as we know are just
1062
+ instance variables and not methods, right? More on that when we talk
1063
+ about Accessors.
1064
+
1065
+ Galaaz and Ruby do not by default provide a way to see a method's code.
1066
+ However, if the user uses a Ruby console such as Pry, then seeing
1067
+ methods and debugging is possible. Pry is beyond the scope of this
1068
+ document.
1069
+
1070
+ \section{Construction}\label{construction}
1071
+
1072
+ Every class in Ruby has a constructor, if not explicitly defined, at
1073
+ least implicitly. Method initialize is the constructor method and the
1074
+ one that coordinates the whole construction process.
1075
+
1076
+ \section{Inspector}\label{inspector}
1077
+
1078
+ There is no default `inspector' in Ruby as in R, although there is
1079
+ nothing that prevents the developer from inspecting and validating the
1080
+ input. For example, in the object Trajectories, one may want to check
1081
+ that the number of elements in `times' is equal to the number of columns
1082
+ in `matrix' and if they are not, issue an error. In order to understand
1083
+ why this restriction exists, the user is again directed to SS4.
1084
+
1085
+ Here we show the R code for this validation:
1086
+
1087
+ \begin{verbatim}
1088
+ > setClass(
1089
+ + Class="Trajectories",
1090
+ + representation(times="numeric",traj="matrix"),
1091
+ + validity=function(object){
1092
+ + cat("~~~ Trajectories: inspector ~~~ \\n")
1093
+ + if(length(object@times)!=ncol(object@traj)){
1094
+ + stop ("[Trajectories: validation] the number of temporal
1095
+ + measurements does not correspond
1096
+ + }else{}
1097
+ + return(TRUE)
1098
+ + }
1099
+ + )
1100
+ \end{verbatim}
1101
+
1102
+ In order to implement this validation we will coordinate it in the
1103
+ initialize method.
1104
+
1105
+ \begin{Shaded}
1106
+ \begin{Highlighting}[]
1107
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1108
+
1109
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1110
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ times}
1111
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ matrix}
1112
+
1113
+ \CommentTok{\# Validate: length(@times) must equal ncol(@matrix)}
1114
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"\textasciitilde{}\textasciitilde{}\textasciitilde{} Trajectories: inspector \textasciitilde{}\textasciitilde{}\textasciitilde{} "}\NormalTok{)}
1115
+ \ControlFlowTok{if}\NormalTok{ ((}\OtherTok{@times}\AttributeTok{.length} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{) }\OperatorTok{!=}\NormalTok{ (}\OtherTok{@matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{))}
1116
+ \FunctionTok{raise}\NormalTok{(}
1117
+ \StringTok{"[Trajectories: validation] the number of temporal "} \OperatorTok{+}
1118
+ \StringTok{"measurements does not correspond with the number of "} \OperatorTok{+}
1119
+ \StringTok{"columns in the matrix"}\NormalTok{)}
1120
+ \ControlFlowTok{end}
1121
+
1122
+ \CommentTok{\# show the object just created}
1123
+ \NormalTok{ show}
1124
+
1125
+ \ControlFlowTok{end}
1126
+
1127
+ \ControlFlowTok{end}
1128
+ \end{Highlighting}
1129
+ \end{Shaded}
1130
+
1131
+ Let's first create a Trajectories that validates fine, i.e., the number
1132
+ of elements in @times is equal to the number of columns of the matrix.
1133
+ In this case, we will show a message saying that validation was done and
1134
+ then print the object.
1135
+
1136
+ \begin{Shaded}
1137
+ \begin{Highlighting}[]
1138
+ \NormalTok{ok }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{),}
1139
+ \WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
1140
+ \end{Highlighting}
1141
+ \end{Shaded}
1142
+
1143
+ \begin{verbatim}
1144
+ ## ~~~ Trajectories: inspector ~~~
1145
+ ## *** Class Trajectories, method Show ***
1146
+ ## times = 1
1147
+ ## 2
1148
+ ## * Traj (limited to a matrix 10x10) =
1149
+ ## 1
1150
+ ## 2
1151
+ ## ******* End Show (trajectories) *******
1152
+ \end{verbatim}
1153
+
1154
+ Now, if we try to create a Trajectories that does not pass the
1155
+ validation criteria, our code will raise an exception. Exceptions are a
1156
+ standard way to deal with errors in Ruby code and many other object
1157
+ oriented languages. The interested reader should look for further
1158
+ documentation on exceptions on the web.
1159
+
1160
+ \begin{Shaded}
1161
+ \begin{Highlighting}[]
1162
+ \ControlFlowTok{begin}
1163
+ \NormalTok{ error }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\OperatorTok{..}\DecValTok{3}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{),}
1164
+ \WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
1165
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1166
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
1167
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
1168
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
1169
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
1170
+ \ControlFlowTok{end}
1171
+ \end{Highlighting}
1172
+ \end{Shaded}
1173
+
1174
+ \begin{verbatim}
1175
+ ## ~~~ Trajectories: inspector ~~~
1176
+ ## RuntimeError
1177
+ ## [Trajectories: validation] the number of temporal measurements does
1178
+ ## not correspond with the number of columns in the matrix
1179
+ \end{verbatim}
1180
+
1181
+ The validation above does not consider the case when an empty object is
1182
+ created. Here we will check to see if either times or matrix are nil; if
1183
+ either one of them is nil, then we will raise an exception and interrupt
1184
+ the creation of the object. We also create a method validate that is
1185
+ called from our initialize method.
1186
+
1187
+ Method validate has some interesting features about the integration of
1188
+ Galaaz and R. We compare lengths after unboxing with
1189
+ \texttt{\textgreater{}\textgreater{}\ 0}, so the comparison is ordinary
1190
+ Ruby arithmetic on numbers. (A length-1 R logical can likewise be
1191
+ treated as a Ruby boolean via \texttt{\textgreater{}\textgreater{}\ 0}.)
1192
+
1193
+ \begin{Shaded}
1194
+ \begin{Highlighting}[]
1195
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1196
+
1197
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1198
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ times}
1199
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ matrix}
1200
+
1201
+ \CommentTok{\# call method validate to validate our input}
1202
+ \NormalTok{ validate}
1203
+
1204
+ \CommentTok{\# show the object just created}
1205
+ \NormalTok{ show}
1206
+
1207
+ \ControlFlowTok{end}
1208
+
1209
+ \ControlFlowTok{def}\NormalTok{ validate}
1210
+
1211
+ \CommentTok{\# Let\textquotesingle{}s first check that we do not have an empty object}
1212
+ \ControlFlowTok{if}\NormalTok{ (}\OtherTok{@times}\AttributeTok{.nil?} \OperatorTok{||} \OtherTok{@matrix}\AttributeTok{.nil?}\NormalTok{)}
1213
+ \FunctionTok{raise} \StringTok{"Neither times nor matrix can be an empty object"}
1214
+ \ControlFlowTok{end}
1215
+
1216
+ \CommentTok{\# Validate: length(@times) must equal ncol(@matrix)}
1217
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"\textasciitilde{}\textasciitilde{}\textasciitilde{} Trajectories: inspector \textasciitilde{}\textasciitilde{}\textasciitilde{} "}\NormalTok{)}
1218
+ \ControlFlowTok{if}\NormalTok{ ((}\OtherTok{@times}\AttributeTok{.length} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{) }\OperatorTok{!=}\NormalTok{ (}\OtherTok{@matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{))}
1219
+ \FunctionTok{raise}\NormalTok{(}
1220
+ \StringTok{"[Trajectories: validation] the number of temporal "} \OperatorTok{+}
1221
+ \StringTok{"measurements does not correspond with the number of "} \OperatorTok{+}
1222
+ \StringTok{"columns in the matrix"}\NormalTok{)}
1223
+ \ControlFlowTok{end}
1224
+
1225
+ \ControlFlowTok{end}
1226
+
1227
+ \ControlFlowTok{end}
1228
+ \end{Highlighting}
1229
+ \end{Shaded}
1230
+
1231
+ \textbf{Note:} with this stricter \texttt{validate},
1232
+ \texttt{Trajectories.new} no longer accepts empty objects. The earlier
1233
+ \texttt{@empty\_traj\ =\ Trajectories.new} / \texttt{@empty\_traj.show}
1234
+ pattern from part 1 no longer applies for \emph{new} constructions;
1235
+ existing instances created before this reopen still exist in memory, but
1236
+ calling \texttt{new} with missing \texttt{times} or \texttt{matrix} will
1237
+ raise.
1238
+
1239
+ Let's try then creating an empty object:
1240
+
1241
+ \begin{Shaded}
1242
+ \begin{Highlighting}[]
1243
+ \ControlFlowTok{begin}
1244
+ \NormalTok{ error }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}
1245
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1246
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
1247
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
1248
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
1249
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
1250
+ \ControlFlowTok{end}
1251
+ \end{Highlighting}
1252
+ \end{Shaded}
1253
+
1254
+ \begin{verbatim}
1255
+ ## RuntimeError
1256
+ ## Neither times nor matrix can be an empty object
1257
+ \end{verbatim}
1258
+
1259
+ Another example:
1260
+
1261
+ \begin{Shaded}
1262
+ \begin{Highlighting}[]
1263
+ \ControlFlowTok{begin}
1264
+ \NormalTok{ error }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \DecValTok{1}\NormalTok{)}
1265
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1266
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
1267
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
1268
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
1269
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
1270
+ \ControlFlowTok{end}
1271
+ \end{Highlighting}
1272
+ \end{Shaded}
1273
+
1274
+ \begin{verbatim}
1275
+ ## RuntimeError
1276
+ ## Neither times nor matrix can be an empty object
1277
+ \end{verbatim}
1278
+
1279
+ Let's see now that the implementation is correct and that it does not
1280
+ raise an error on valid input:
1281
+
1282
+ \begin{Shaded}
1283
+ \begin{Highlighting}[]
1284
+ \NormalTok{ok }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{),}
1285
+ \WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
1286
+ \end{Highlighting}
1287
+ \end{Shaded}
1288
+
1289
+ \begin{verbatim}
1290
+ ## ~~~ Trajectories: inspector ~~~
1291
+ ## *** Class Trajectories, method Show ***
1292
+ ## times = 1
1293
+ ## 2
1294
+ ## * Traj (limited to a matrix 10x10) =
1295
+ ## 1
1296
+ ## 2
1297
+ ## ******* End Show (trajectories) *******
1298
+ \end{verbatim}
1299
+
1300
+ The `initialize' method is called ONLY during the initial creation of
1301
+ the object. If any instance variable is later modified, no control is
1302
+ done. At this moment though, there is no way to change the value of any
1303
+ of our instance variables.
1304
+
1305
+ \begin{verbatim}
1306
+ error.times = R.c(1, 2, 3)
1307
+ \end{verbatim}
1308
+
1309
+ The Trajectories class works for R objects and expects as input R
1310
+ objects. Passing R objects in all examples has been the obligation of
1311
+ the programmer. Galaaz, however, can also accept many Ruby values
1312
+ (ranges, arrays of numbers, and so on) if we convert them at the
1313
+ boundary. There is no \texttt{R.convert} in Galaaz 2.0; a small helper
1314
+ is enough: leave \texttt{nil} alone, keep objects that are already
1315
+ \texttt{R::Object}, and otherwise wrap with \texttt{R.c} (which accepts
1316
+ ranges as well as scalars and vectors). Matrices that are already R
1317
+ objects are kept as-is.
1318
+
1319
+ \begin{Shaded}
1320
+ \begin{Highlighting}[]
1321
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1322
+
1323
+ \ControlFlowTok{def}\NormalTok{ as\_r(x)}
1324
+ \ControlFlowTok{return} \DecValTok{nil} \ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.nil?}
1325
+ \ControlFlowTok{return}\NormalTok{ x }\ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.is\_a?}\NormalTok{(}\ConstantTok{R}\OperatorTok{::}\DataTypeTok{Object}\NormalTok{)}
1326
+ \ConstantTok{R}\AttributeTok{.c}\NormalTok{(x)}
1327
+ \ControlFlowTok{end}
1328
+
1329
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1330
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ as\_r(times)}
1331
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ as\_r(matrix)}
1332
+
1333
+ \CommentTok{\# call method validate to validate our input}
1334
+ \NormalTok{ validate}
1335
+
1336
+ \CommentTok{\# show the object just created}
1337
+ \NormalTok{ show}
1338
+
1339
+ \ControlFlowTok{end}
1340
+
1341
+ \ControlFlowTok{def}\NormalTok{ validate}
1342
+
1343
+ \CommentTok{\# Let\textquotesingle{}s first check that we do not have an empty object}
1344
+ \ControlFlowTok{if}\NormalTok{ (}\OtherTok{@times}\AttributeTok{.nil?} \OperatorTok{||} \OtherTok{@matrix}\AttributeTok{.nil?}\NormalTok{)}
1345
+ \FunctionTok{raise} \StringTok{"Neither times nor matrix can be an empty object"}
1346
+ \ControlFlowTok{end}
1347
+
1348
+ \CommentTok{\# Validate: length(@times) must equal ncol(@matrix)}
1349
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"\textasciitilde{}\textasciitilde{}\textasciitilde{} Trajectories: inspector \textasciitilde{}\textasciitilde{}\textasciitilde{} "}\NormalTok{)}
1350
+ \NormalTok{ tl }\OperatorTok{=} \OtherTok{@times}\AttributeTok{.length} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{; mc }\OperatorTok{=} \OtherTok{@matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
1351
+ \ControlFlowTok{if}\NormalTok{ (tl }\OperatorTok{!=}\NormalTok{ mc)}
1352
+ \FunctionTok{raise}\NormalTok{(}
1353
+ \StringTok{"[Trajectories: validation] the number of temporal "} \OperatorTok{+}
1354
+ \StringTok{"measurements }\SpecialCharTok{\#\{}\NormalTok{tl}\SpecialCharTok{\}}\StringTok{ does not correspond with the number "} \OperatorTok{+}
1355
+ \StringTok{"of columns in the matrix }\SpecialCharTok{\#\{}\NormalTok{mc}\SpecialCharTok{\}}\StringTok{"}\NormalTok{)}
1356
+ \ControlFlowTok{end}
1357
+
1358
+ \ControlFlowTok{end}
1359
+
1360
+ \ControlFlowTok{end}
1361
+ \end{Highlighting}
1362
+ \end{Shaded}
1363
+
1364
+ And now let's create a new Trajectories, but we will now pass a Ruby
1365
+ range for times:
1366
+
1367
+ \begin{Shaded}
1368
+ \begin{Highlighting}[]
1369
+ \NormalTok{ok }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:}\NormalTok{ (}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{), }\WarningTok{ncol:} \DecValTok{2}\NormalTok{))}
1370
+ \end{Highlighting}
1371
+ \end{Shaded}
1372
+
1373
+ \begin{verbatim}
1374
+ ## ~~~ Trajectories: inspector ~~~
1375
+ ## *** Class Trajectories, method Show ***
1376
+ ## times = 1
1377
+ ## 2
1378
+ ## * Traj (limited to a matrix 10x10) =
1379
+ ## 1
1380
+ ## 2
1381
+ ## ******* End Show (trajectories) *******
1382
+ \end{verbatim}
1383
+
1384
+ Perfect! This works fine.
1385
+
1386
+ \emph{(Historical note: an earlier Galaaz prototype on Renjin also
1387
+ demonstrated sharing storage with the MDArray gem. Those shared-store
1388
+ demos are not part of Galaaz 2.0 / the GNU R bridge, and are omitted
1389
+ here.)}
1390
+
1391
+ \section{The Initializator}\label{the-initializator}
1392
+
1393
+ As we have seen, method `initialize' is the main object creator
1394
+ orchestrator. This method can be as complex as needed. So, let's get on
1395
+ with some improvements to our Trajectories class.
1396
+
1397
+ It would be rather pleasant that the columns of the matrix of the
1398
+ trajectories have names, the names of measurements times. In the same
1399
+ way, the lines could be subscripted by a number of individual.
1400
+
1401
+ To do this in R, one also uses method initialize:
1402
+
1403
+ \begin{verbatim}
1404
+ > setMethod(
1405
+ + f="initialize",
1406
+ + signature="Trajectories",
1407
+ + definition=function(.Object,times,traj){
1408
+ + cat("~~~ Trajectories: initializator ~~~ \\n")
1409
+ + colnames(traj) <- paste("T",times,sep="")
1410
+ + rownames(traj) <- paste("I",1:nrow(traj),sep= "")
1411
+ + .Object@traj <- traj # Assignment of the slots
1412
+ + .Object@times <- times
1413
+ + return(.Object) # return of the object
1414
+ + }
1415
+ + )
1416
+ \end{verbatim}
1417
+
1418
+ In R, it is possible to assign a value to the result of a function, for
1419
+ example \texttt{colnames(x)\ \textless{}-\ c("v1",\ "v2",\ "v3")}. In
1420
+ Galaaz 2.0 the same idea is expressed with ordinary Ruby setters on the
1421
+ R object: \texttt{@matrix.colnames\ =\ ...} and
1422
+ \texttt{@matrix.rownames\ =\ ...}.
1423
+
1424
+ \begin{Shaded}
1425
+ \begin{Highlighting}[]
1426
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1427
+
1428
+ \ControlFlowTok{def}\NormalTok{ as\_r(x)}
1429
+ \ControlFlowTok{return} \DecValTok{nil} \ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.nil?}
1430
+ \ControlFlowTok{return}\NormalTok{ x }\ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.is\_a?}\NormalTok{(}\ConstantTok{R}\OperatorTok{::}\DataTypeTok{Object}\NormalTok{)}
1431
+ \ConstantTok{R}\AttributeTok{.c}\NormalTok{(x)}
1432
+ \ControlFlowTok{end}
1433
+
1434
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1435
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ as\_r(times)}
1436
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ as\_r(matrix)}
1437
+
1438
+ \CommentTok{\# call method validate to validate our input}
1439
+ \NormalTok{ validate}
1440
+
1441
+ \CommentTok{\# Add row and column names}
1442
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"\textasciitilde{}\textasciitilde{}\textasciitilde{} Trajectories: initializator \textasciitilde{}\textasciitilde{}\textasciitilde{} "}\NormalTok{)}
1443
+ \OtherTok{@matrix}\AttributeTok{.colnames} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.paste}\NormalTok{(}\StringTok{"T"}\NormalTok{, }\OtherTok{@times}\NormalTok{, }\WarningTok{sep:} \StringTok{""}\NormalTok{)}
1444
+ \OtherTok{@matrix}\AttributeTok{.rownames} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.paste}\NormalTok{(}\StringTok{"I"}\NormalTok{, (}\DecValTok{1}\OperatorTok{..}\NormalTok{(}\OtherTok{@matrix}\AttributeTok{.nrow} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{)), }\WarningTok{sep:} \StringTok{""}\NormalTok{)}
1445
+
1446
+ \CommentTok{\# show the object just created}
1447
+ \NormalTok{ show}
1448
+
1449
+ \ControlFlowTok{end}
1450
+
1451
+ \ControlFlowTok{end}
1452
+ \end{Highlighting}
1453
+ \end{Shaded}
1454
+
1455
+ \begin{Shaded}
1456
+ \begin{Highlighting}[]
1457
+ \OtherTok{@traj} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{,}\DecValTok{2}\NormalTok{,}\DecValTok{4}\NormalTok{,}\DecValTok{8}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{8}\NormalTok{),}
1458
+ \WarningTok{nrow:} \DecValTok{2}\NormalTok{))}
1459
+ \end{Highlighting}
1460
+ \end{Shaded}
1461
+
1462
+ \begin{verbatim}
1463
+ ## ~~~ Trajectories: inspector ~~~
1464
+ ## ~~~ Trajectories: initializator ~~~
1465
+ ## *** Class Trajectories, method Show ***
1466
+ ## times = 1
1467
+ ## 2
1468
+ ## 4
1469
+ ## 8
1470
+ ## * Traj (limited to a matrix 10x10) =
1471
+ ## T1 T2 T4 T8
1472
+ ## I1 "1" "3" "5" "7"
1473
+ ## I2 "2" "4" "6" "8"
1474
+ ## ******* End Show (trajectories) *******
1475
+ \end{verbatim}
1476
+
1477
+ Note that we still call our `validate' method and it is still an error
1478
+ to create an empty Trajectories or one in which the sizes are wrong:
1479
+
1480
+ \begin{Shaded}
1481
+ \begin{Highlighting}[]
1482
+ \ControlFlowTok{begin}
1483
+ \NormalTok{ error }\OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{48}\NormalTok{), }\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{8}\NormalTok{),}
1484
+ \WarningTok{nrow:} \DecValTok{2}\NormalTok{))}
1485
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1486
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
1487
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
1488
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
1489
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
1490
+ \ControlFlowTok{end}
1491
+ \end{Highlighting}
1492
+ \end{Shaded}
1493
+
1494
+ \begin{verbatim}
1495
+ ## ~~~ Trajectories: inspector ~~~
1496
+ ## RuntimeError
1497
+ ## [Trajectories: validation] the number of temporal measurements 3 doe
1498
+ ## s not correspond with the number of columns in the matrix 4
1499
+ \end{verbatim}
1500
+
1501
+ A constructor does not necessarily take the instance variable of the
1502
+ object as argument. For example, if we know (that is not the case in
1503
+ reality, but let us imagine so) that the BMI increases by 0.1 every
1504
+ week, we could build trajectories by providing the number of weeks and
1505
+ the initial weights.
1506
+
1507
+ First the code in R, we skip the definition of class TrajectoriesBis:
1508
+
1509
+ \begin{verbatim}
1510
+ > setMethod ("initialize",
1511
+ + "TrajectoriesBis",
1512
+ + function(.Object,nbWeek,BMIinit){
1513
+ + traj <- outer(BMIinit, 1:nbWeek,
1514
+ + function(init, week) { return(init + 0.1 * week) })
1515
+ + colnames(traj) <- paste("T",1:nbWeek,sep="")
1516
+ + rownames(traj) <- paste("I",1:nrow(traj),sep="")
1517
+ + .Object@times <- 1:nbWeek
1518
+ + .Object@traj <- traj
1519
+ + return(.Object)
1520
+ + }
1521
+ + )
1522
+ \end{verbatim}
1523
+
1524
+ Now, let's make a TrajectoriesBis in Galaaz. Here again, we should point
1525
+ out some characteristics of our code:
1526
+
1527
+ \begin{itemize}
1528
+ \item
1529
+ We made initialize with two positional arguments, instead of named
1530
+ arguments, i.e., the first argument is the number of weeks and the
1531
+ second bmi\_init. In this case, when making a new object the position
1532
+ of the arguments is important and there is no way to pass the argument
1533
+ by name;
1534
+ \item
1535
+ R function outer was called as if a method from bmi\_init using dot
1536
+ notation, although one could use R.outer without problem;
1537
+ \item
1538
+ Function `outer' expects an R function as its 3rd argument. In order
1539
+ to build an R function from Galaaz, we need to pass the function
1540
+ definition as a string to R.eval.
1541
+ \end{itemize}
1542
+
1543
+ \begin{Shaded}
1544
+ \begin{Highlighting}[]
1545
+ \ControlFlowTok{class} \DataTypeTok{TrajectoriesBis}
1546
+
1547
+ \OtherTok{attr\_reader} \WarningTok{:times}
1548
+ \OtherTok{attr\_reader} \WarningTok{:matrix}
1549
+
1550
+ \ControlFlowTok{def}\NormalTok{ initialize(number\_weeks, bmi\_init)}
1551
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ bmi\_init}\AttributeTok{.outer}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks),}
1552
+ \ConstantTok{R}\AttributeTok{.eval}\NormalTok{(}\StringTok{"function(init,}
1553
+ \StringTok{ week) \{return(init + 0.1 * week)\}"}\NormalTok{))}
1554
+ \OtherTok{@times} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks))}
1555
+ \ControlFlowTok{end}
1556
+
1557
+ \ControlFlowTok{end}
1558
+
1559
+ \OtherTok{@traj\_bis} \OperatorTok{=} \DataTypeTok{TrajectoriesBis}\AttributeTok{.new}\NormalTok{(}\DecValTok{4}\NormalTok{, }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{16}\NormalTok{,}\DecValTok{17}\NormalTok{,}\FloatTok{15.6}\NormalTok{))}
1560
+ \end{Highlighting}
1561
+ \end{Shaded}
1562
+
1563
+ \begin{Shaded}
1564
+ \begin{Highlighting}[]
1565
+ \FunctionTok{puts} \OtherTok{@traj\_bis}\AttributeTok{.matrix}
1566
+ \end{Highlighting}
1567
+ \end{Shaded}
1568
+
1569
+ \begin{verbatim}
1570
+ ## [,1] [,2] [,3] [,4]
1571
+ ## [1,] 16.1 16.2 16.3 16.4
1572
+ ## [2,] 17.1 17.2 17.3 17.4
1573
+ ## [3,] 15.7 15.8 15.9 16.0
1574
+ \end{verbatim}
1575
+
1576
+ It is always possible to pass a Ruby variable into a string by
1577
+ interpolating it. Put the variable inside \texttt{\#\{...\}}. As an
1578
+ example, let's also require the BMI increase as a parameter. (A common
1579
+ mistake is to escape the interpolation --- writing
1580
+ \texttt{\textbackslash{}\#\{increment\}} --- which leaves the characters
1581
+ literally in the R source and does not substitute the Ruby value. Use
1582
+ real interpolation:)
1583
+
1584
+ \begin{Shaded}
1585
+ \begin{Highlighting}[]
1586
+ \ControlFlowTok{class} \DataTypeTok{TrajectoriesBis}
1587
+
1588
+ \ControlFlowTok{def}\NormalTok{ initialize(number\_weeks, bmi\_init, increment)}
1589
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ bmi\_init}\AttributeTok{.outer}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks),}
1590
+ \ConstantTok{R}\AttributeTok{.eval}\NormalTok{(}\StringTok{"function(init,}
1591
+ \StringTok{ week) \{return(init +}
1592
+ \StringTok{ }\SpecialCharTok{\#\{}\NormalTok{increment}\SpecialCharTok{\}}\StringTok{ * week)\}"}\NormalTok{))}
1593
+ \OtherTok{@times} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks))}
1594
+ \ControlFlowTok{end}
1595
+
1596
+ \ControlFlowTok{end}
1597
+
1598
+ \OtherTok{@traj\_bis} \OperatorTok{=} \DataTypeTok{TrajectoriesBis}\AttributeTok{.new}\NormalTok{(}\DecValTok{4}\NormalTok{, }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{16}\NormalTok{,}\DecValTok{17}\NormalTok{,}\FloatTok{15.6}\NormalTok{), }\FloatTok{0.3}\NormalTok{)}
1599
+ \end{Highlighting}
1600
+ \end{Shaded}
1601
+
1602
+ \begin{Shaded}
1603
+ \begin{Highlighting}[]
1604
+ \FunctionTok{puts} \OtherTok{@traj\_bis}\AttributeTok{.matrix}
1605
+ \end{Highlighting}
1606
+ \end{Shaded}
1607
+
1608
+ \begin{verbatim}
1609
+ ## [,1] [,2] [,3] [,4]
1610
+ ## [1,] 16.3 16.6 16.9 17.2
1611
+ ## [2,] 17.3 17.6 17.9 18.2
1612
+ ## [3,] 15.9 16.2 16.5 16.8
1613
+ \end{verbatim}
1614
+
1615
+ \section{Constructors for Users}\label{constructors-for-users}
1616
+
1617
+ Many times, it is interesting to have different ways of constructing an
1618
+ object depending on what information our users have or want to provide
1619
+ to the constructor. Although we have only one initialize method, we can
1620
+ create multiple methods, that do some preprocessing and then call the
1621
+ initialize method to carry out the object building.
1622
+
1623
+ In order to do that, we use what are called class methods, instead of
1624
+ instance methods. All the methods we've created so far are instance
1625
+ methods; class methods are defined by prepending the self keyword to the
1626
+ method's name. Still using the assumption that the BMI will grow by 0.1
1627
+ per week, let's define a regular trajectory without having to define a
1628
+ TrajectoriesBis as above:
1629
+
1630
+ \begin{verbatim}
1631
+ > regularTrajectories <- function(nbWeek,BMIinit) {
1632
+ + traj <- outer(BMIinit, 1:nbWeek,
1633
+ + function(init, week) { return(init + 0.1 * week) })
1634
+ + times <- 1: nbWeek
1635
+ + return(new(Class="Trajectories",times=times,traj=traj))
1636
+ + }
1637
+ > regularTrajectories(nbWeek=3,BMIinit=c(14,15,16))
1638
+ \end{verbatim}
1639
+
1640
+ Notice how method `regular' is defined as `self.regular', making it a
1641
+ class method. The last statement of the method definition is actually a
1642
+ call to the Trajectories constructor `new' passing the calculated values
1643
+ for times and matrix.
1644
+
1645
+ Notice also how method regular is called, similar to the way new is
1646
+ called by adding it after class Trajectories name:
1647
+ `Trajectories.regular'.
1648
+
1649
+ \begin{Shaded}
1650
+ \begin{Highlighting}[]
1651
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1652
+
1653
+ \ControlFlowTok{def} \DecValTok{self}\AttributeTok{.regular}\NormalTok{(}\WarningTok{number\_weeks:} \DecValTok{nil}\NormalTok{, }\WarningTok{bmi\_init:} \DecValTok{nil}\NormalTok{)}
1654
+ \NormalTok{ matrix }\OperatorTok{=}\NormalTok{ bmi\_init}\AttributeTok{.outer}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks),}
1655
+ \ConstantTok{R}\AttributeTok{.eval}\NormalTok{(}\StringTok{"function(init,}
1656
+ \StringTok{ week) \{return(init + 0.1 * week)\}"}\NormalTok{))}
1657
+ \NormalTok{ times }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{number\_weeks))}
1658
+ \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:}\NormalTok{ times, }\WarningTok{matrix:}\NormalTok{ matrix)}
1659
+ \ControlFlowTok{end}
1660
+
1661
+ \ControlFlowTok{end}
1662
+ \end{Highlighting}
1663
+ \end{Shaded}
1664
+
1665
+ \begin{Shaded}
1666
+ \begin{Highlighting}[]
1667
+ \OtherTok{@regular} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.regular}\NormalTok{(}\WarningTok{bmi\_init:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{14}\NormalTok{, }\DecValTok{15}\NormalTok{, }\DecValTok{16}\NormalTok{),}
1668
+ \WarningTok{number\_weeks:} \DecValTok{3}\NormalTok{)}
1669
+ \end{Highlighting}
1670
+ \end{Shaded}
1671
+
1672
+ \begin{verbatim}
1673
+ ## ~~~ Trajectories: inspector ~~~
1674
+ ## ~~~ Trajectories: initializator ~~~
1675
+ ## *** Class Trajectories, method Show ***
1676
+ ## times = 1
1677
+ ## 2
1678
+ ## 3
1679
+ ## * Traj (limited to a matrix 10x10) =
1680
+ ## T1 T2 T3
1681
+ ## I1 "14.10" "14.20" "14.30"
1682
+ ## I2 "15.10" "15.20" "15.30"
1683
+ ## I3 "16.10" "16.20" "16.30"
1684
+ ## ******* End Show (trajectories) *******
1685
+ \end{verbatim}
1686
+
1687
+ We have already seen that constructors can be as complex as needed,
1688
+ calling other methods and doing calculations on the received parameters.
1689
+ On this last example, we will check if the times variable was provided.
1690
+ If it is not provided, then we will use matrix columns to define the
1691
+ times:
1692
+
1693
+ \begin{Shaded}
1694
+ \begin{Highlighting}[]
1695
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1696
+
1697
+ \ControlFlowTok{def} \DecValTok{self}\AttributeTok{.init}\NormalTok{(}\WarningTok{times:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1698
+ \NormalTok{ times }\OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\NormalTok{(matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{))) }\ControlFlowTok{if}\NormalTok{ times}\AttributeTok{.nil?}
1699
+ \DataTypeTok{Trajectories}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:}\NormalTok{ times, }\WarningTok{matrix:}\NormalTok{ matrix)}
1700
+ \ControlFlowTok{end}
1701
+
1702
+ \ControlFlowTok{end}
1703
+ \end{Highlighting}
1704
+ \end{Shaded}
1705
+
1706
+ \begin{Shaded}
1707
+ \begin{Highlighting}[]
1708
+ \OtherTok{@traj} \OperatorTok{=} \DataTypeTok{Trajectories}\AttributeTok{.init}\NormalTok{(}\WarningTok{matrix:} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{8}\NormalTok{), }\WarningTok{ncol:} \DecValTok{4}\NormalTok{))}
1709
+ \end{Highlighting}
1710
+ \end{Shaded}
1711
+
1712
+ \begin{verbatim}
1713
+ ## ~~~ Trajectories: inspector ~~~
1714
+ ## ~~~ Trajectories: initializator ~~~
1715
+ ## *** Class Trajectories, method Show ***
1716
+ ## times = 1
1717
+ ## 2
1718
+ ## 3
1719
+ ## 4
1720
+ ## * Traj (limited to a matrix 10x10) =
1721
+ ## T1 T2 T3 T4
1722
+ ## I1 "1" "3" "5" "7"
1723
+ ## I2 "2" "4" "6" "8"
1724
+ ## ******* End Show (trajectories) *******
1725
+ \end{verbatim}
1726
+
1727
+ \section{Accessors}\label{accessors}
1728
+
1729
+ Accessors are methods for getting and setting the value of instance
1730
+ variables.
1731
+
1732
+ \section{Get}\label{get}
1733
+
1734
+ Getters are methods for getting the value of an instance variable. We
1735
+ have been using getters since the beginning of this document, without
1736
+ explicitly saying so. When defining attr\_reader :times and attr\_reader
1737
+ :matrix, we have actually defined two getter methods for reading the
1738
+ values of variables times and matrix respectively. We can however define
1739
+ getters explicitly:
1740
+
1741
+ \begin{Shaded}
1742
+ \begin{Highlighting}[]
1743
+ \ControlFlowTok{class} \DataTypeTok{TrajectoriesBis}
1744
+
1745
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1746
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ times}
1747
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ matrix}
1748
+ \ControlFlowTok{end}
1749
+
1750
+ \ControlFlowTok{def}\NormalTok{ times}
1751
+ \OtherTok{@times}
1752
+ \ControlFlowTok{end}
1753
+
1754
+ \ControlFlowTok{def}\NormalTok{ matrix}
1755
+ \OtherTok{@matrix}
1756
+ \ControlFlowTok{end}
1757
+
1758
+ \ControlFlowTok{end}
1759
+
1760
+ \OtherTok{@traj} \OperatorTok{=} \DataTypeTok{TrajectoriesBis}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \DecValTok{1}\NormalTok{, }\WarningTok{matrix:} \DecValTok{2}\NormalTok{)}
1761
+ \end{Highlighting}
1762
+ \end{Shaded}
1763
+
1764
+ \begin{Shaded}
1765
+ \begin{Highlighting}[]
1766
+ \FunctionTok{puts} \OtherTok{@traj}\AttributeTok{.times}
1767
+ \end{Highlighting}
1768
+ \end{Shaded}
1769
+
1770
+ \begin{verbatim}
1771
+ ## 1
1772
+ \end{verbatim}
1773
+
1774
+ \begin{Shaded}
1775
+ \begin{Highlighting}[]
1776
+ \FunctionTok{puts} \OtherTok{@traj}\AttributeTok{.matrix}
1777
+ \end{Highlighting}
1778
+ \end{Shaded}
1779
+
1780
+ \begin{verbatim}
1781
+ ## 2
1782
+ \end{verbatim}
1783
+
1784
+ It is also possible to define more sophisticated getters. For example
1785
+ one can regularly need the BMI at inclusion. In R, one would index a
1786
+ matrix as matrix{[},1{]}. In Ruby, it is a syntax error to have a `,'
1787
+ just after the `{[}'. In this case we need to add `nil' as in
1788
+ matrix{[}nil, 1{]}:
1789
+
1790
+ \begin{Shaded}
1791
+ \begin{Highlighting}[]
1792
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1793
+
1794
+ \ControlFlowTok{def}\NormalTok{ get\_traj\_inclusion}
1795
+ \OtherTok{@matrix}\KeywordTok{[}\DecValTok{nil}\NormalTok{, }\DecValTok{1}\KeywordTok{]}
1796
+ \ControlFlowTok{end}
1797
+
1798
+ \ControlFlowTok{end}
1799
+ \end{Highlighting}
1800
+ \end{Shaded}
1801
+
1802
+ \begin{Shaded}
1803
+ \begin{Highlighting}[]
1804
+ \FunctionTok{puts} \OtherTok{@trajCochin}\AttributeTok{.get\_traj\_inclusion}
1805
+ \end{Highlighting}
1806
+ \end{Shaded}
1807
+
1808
+ \begin{verbatim}
1809
+ ## numeric(0)
1810
+ \end{verbatim}
1811
+
1812
+ \section{Set}\label{set}
1813
+
1814
+ A setter is a method that assigns a value to a variable. As with
1815
+ getters, Ruby also provides an easy way to write setters and allow you
1816
+ to also write them explicitly. Let's first use the simple way:
1817
+
1818
+ \begin{Shaded}
1819
+ \begin{Highlighting}[]
1820
+ \ControlFlowTok{class} \DataTypeTok{TrajectoriesBis}
1821
+
1822
+ \OtherTok{attr\_writer} \WarningTok{:times}
1823
+ \OtherTok{attr\_writer} \WarningTok{:matrix}
1824
+
1825
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{)}
1826
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ times}
1827
+ \OtherTok{@matrix} \OperatorTok{=}\NormalTok{ matrix}
1828
+ \ControlFlowTok{end}
1829
+
1830
+ \ControlFlowTok{end}
1831
+
1832
+ \OtherTok{@traj} \OperatorTok{=} \DataTypeTok{TrajectoriesBis}\AttributeTok{.new}
1833
+ \OtherTok{@traj}\AttributeTok{.times} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{)}
1834
+ \OtherTok{@traj}\AttributeTok{.matrix} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.matrix}\NormalTok{((}\DecValTok{1}\OperatorTok{..}\DecValTok{2}\NormalTok{), }\WarningTok{ncol:} \DecValTok{2}\NormalTok{)}
1835
+ \end{Highlighting}
1836
+ \end{Shaded}
1837
+
1838
+ \begin{Shaded}
1839
+ \begin{Highlighting}[]
1840
+ \FunctionTok{puts} \OtherTok{@traj}\AttributeTok{.matrix}
1841
+ \end{Highlighting}
1842
+ \end{Shaded}
1843
+
1844
+ \begin{verbatim}
1845
+ ## [,1] [,2]
1846
+ ## [1,] 1 2
1847
+ \end{verbatim}
1848
+
1849
+ Note that now we can use `=' to assign a value to both variables times
1850
+ and matrix. Without setters, changing the value of variables times and
1851
+ matrix was not possible. Our class, up to this point was protected from
1852
+ any changes to those variables. If we need to allow changes to those
1853
+ variables, then setters are needed. In this case, the simple setter as
1854
+ shown above is not ideal, since it would allow changes that break the
1855
+ restriction that variable times has to have the same length as the
1856
+ number of columns of matrix. In order to do the verification we need to
1857
+ implement a more sophisticated setter. In the example below, we add the
1858
+ `times=' setter that receives as input one argument. First we convert
1859
+ the given argument to an R object, then check to see that the length of
1860
+ times is the same as the number of columns and if everything is fine,
1861
+ then we set the value of instance variable times:
1862
+
1863
+ \begin{Shaded}
1864
+ \begin{Highlighting}[]
1865
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1866
+
1867
+ \ControlFlowTok{def}\NormalTok{ as\_r(x)}
1868
+ \ControlFlowTok{return} \DecValTok{nil} \ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.nil?}
1869
+ \ControlFlowTok{return}\NormalTok{ x }\ControlFlowTok{if}\NormalTok{ x}\AttributeTok{.is\_a?}\NormalTok{(}\ConstantTok{R}\OperatorTok{::}\DataTypeTok{Object}\NormalTok{)}
1870
+ \ConstantTok{R}\AttributeTok{.c}\NormalTok{(x)}
1871
+ \ControlFlowTok{end}
1872
+
1873
+ \ControlFlowTok{def}\NormalTok{ times}\OperatorTok{=}\NormalTok{(times)}
1874
+ \NormalTok{ times }\OperatorTok{=}\NormalTok{ as\_r(times)}
1875
+ \NormalTok{ tl }\OperatorTok{=}\NormalTok{ times}\AttributeTok{.length} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}\NormalTok{; mc }\OperatorTok{=} \OtherTok{@matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
1876
+ \ControlFlowTok{if}\NormalTok{ (tl }\OperatorTok{!=}\NormalTok{ mc)}
1877
+ \FunctionTok{raise}\NormalTok{(}
1878
+ \StringTok{"[Trajectories: validation] the number of temporal "} \OperatorTok{+}
1879
+ \StringTok{"measurements }\SpecialCharTok{\#\{}\NormalTok{tl}\SpecialCharTok{\}}\StringTok{ does not correspond with the number "} \OperatorTok{+}
1880
+ \StringTok{"of columns in the matrix }\SpecialCharTok{\#\{}\NormalTok{mc}\SpecialCharTok{\}}\StringTok{"}\NormalTok{)}
1881
+ \ControlFlowTok{end}
1882
+ \OtherTok{@times} \OperatorTok{=}\NormalTok{ times}
1883
+ \ControlFlowTok{end}
1884
+
1885
+ \ControlFlowTok{end}
1886
+ \end{Highlighting}
1887
+ \end{Shaded}
1888
+
1889
+ \begin{Shaded}
1890
+ \begin{Highlighting}[]
1891
+ \ControlFlowTok{begin}
1892
+ \OtherTok{@trajCochin}\AttributeTok{.times} \OperatorTok{=}\NormalTok{ (}\DecValTok{1}\OperatorTok{..}\DecValTok{5}\NormalTok{)}
1893
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
1894
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
1895
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
1896
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
1897
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
1898
+ \ControlFlowTok{end}
1899
+ \end{Highlighting}
1900
+ \end{Shaded}
1901
+
1902
+ \begin{verbatim}
1903
+ ## RuntimeError
1904
+ ## [Trajectories: validation] the number of temporal measurements 5 doe
1905
+ ## s not correspond with the number of columns in the matrix 4
1906
+ \end{verbatim}
1907
+
1908
+ We now set the value appropriately and will not get any errors:
1909
+
1910
+ \begin{Shaded}
1911
+ \begin{Highlighting}[]
1912
+ \OtherTok{@trajCochin}\AttributeTok{.times} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{6}\NormalTok{, }\DecValTok{8}\NormalTok{)}
1913
+ \end{Highlighting}
1914
+ \end{Shaded}
1915
+
1916
+ \section{The Operator `{[}'}\label{the-operator}
1917
+
1918
+ It is also possible to define getters by using the operator `{[}'. This
1919
+ operator is not usually used for returning instance variables and it is
1920
+ preferable to use the methods we've used above; however, for
1921
+ completeness with SS4 we are showing how to define this here. Operator
1922
+ `{[}' is better left to be used for array/matrix indices.
1923
+
1924
+ \begin{Shaded}
1925
+ \begin{Highlighting}[]
1926
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
1927
+
1928
+ \ControlFlowTok{def} \WarningTok{[]}\NormalTok{(var\_name)}
1929
+
1930
+ \ControlFlowTok{case}\NormalTok{ var\_name}
1931
+ \ControlFlowTok{when} \StringTok{"times"}
1932
+ \OtherTok{@times}
1933
+ \ControlFlowTok{when} \StringTok{"matrix"}
1934
+ \OtherTok{@matrix}
1935
+ \ControlFlowTok{else}
1936
+ \FunctionTok{raise} \StringTok{"Unknown instance variable"}
1937
+ \ControlFlowTok{end}
1938
+
1939
+ \ControlFlowTok{end}
1940
+
1941
+ \ControlFlowTok{end}
1942
+ \end{Highlighting}
1943
+ \end{Shaded}
1944
+
1945
+ \begin{Shaded}
1946
+ \begin{Highlighting}[]
1947
+ \FunctionTok{puts} \OtherTok{@trajCochin}\KeywordTok{[}\StringTok{"times"}\KeywordTok{]}
1948
+ \end{Highlighting}
1949
+ \end{Shaded}
1950
+
1951
+ \begin{verbatim}
1952
+ ## [1] 1 5 6 8
1953
+ \end{verbatim}
1954
+
1955
+ Similarly, we could use operator `{[}{]}=' to assign a value to times
1956
+ and matrix. We will not do this here as we think that the other options
1957
+ are better and the interested user can easily find help, if needed to
1958
+ implement such method.
1959
+
1960
+ \section{To Go Further}\label{to-go-further}
1961
+
1962
+ This section will introduce advanced features of Object Oriented
1963
+ programming such as Inheritance and Modules and will also show some
1964
+ aspects of S4 that do not apply to Ruby.
1965
+
1966
+ \section{Methods Using Several
1967
+ Arguments}\label{methods-using-several-arguments}
1968
+
1969
+ In Ruby, methods can have as many arguments as needed and those methods
1970
+ are defined the way we have already seen in many of the examples above.
1971
+ The example in SS4 presents a method that prints different output if its
1972
+ input is numeric, character or both. Let's write a class in Ruby that
1973
+ does the same for Numeric and String. In Ruby we do not define global
1974
+ functions, we always define methods inside classes or modules (as we
1975
+ will see later). Also, Ruby is not typed, so methods are not called
1976
+ depending on their types as in SS4 examples. Below, method test will be
1977
+ called with one parameter. At the time of calling we do not know the
1978
+ type of the argument; the method can then check if the received argument
1979
+ is a Numeric or a String and at this time, decide what should be
1980
+ printed.
1981
+
1982
+ \begin{Shaded}
1983
+ \begin{Highlighting}[]
1984
+ \ControlFlowTok{class} \DataTypeTok{Test}
1985
+
1986
+ \ControlFlowTok{def} \FunctionTok{test}\NormalTok{(input)}
1987
+
1988
+ \ControlFlowTok{case}\NormalTok{ input}
1989
+ \ControlFlowTok{when} \DataTypeTok{Numeric}
1990
+ \FunctionTok{puts} \StringTok{"The input is numeric: }\SpecialCharTok{\#\{}\NormalTok{input}\SpecialCharTok{\}}\StringTok{"}
1991
+ \ControlFlowTok{when} \DataTypeTok{String}
1992
+ \FunctionTok{puts} \StringTok{"The input is a string: }\SpecialCharTok{\#\{}\NormalTok{input}\SpecialCharTok{\}}\StringTok{"}
1993
+ \ControlFlowTok{else}
1994
+ \FunctionTok{puts} \StringTok{"The input is neither a number nor a string"}
1995
+ \ControlFlowTok{end}
1996
+
1997
+ \ControlFlowTok{end}
1998
+
1999
+ \ControlFlowTok{end}
2000
+
2001
+ \OtherTok{@t} \OperatorTok{=} \DataTypeTok{Test}\AttributeTok{.new}
2002
+ \end{Highlighting}
2003
+ \end{Shaded}
2004
+
2005
+ \begin{Shaded}
2006
+ \begin{Highlighting}[]
2007
+ \OtherTok{@t}\AttributeTok{.test}\NormalTok{(}\DecValTok{5}\NormalTok{)}
2008
+ \end{Highlighting}
2009
+ \end{Shaded}
2010
+
2011
+ \begin{verbatim}
2012
+ ## The input is numeric: 5
2013
+ \end{verbatim}
2014
+
2015
+ \begin{Shaded}
2016
+ \begin{Highlighting}[]
2017
+ \OtherTok{@t}\AttributeTok{.test}\NormalTok{(}\StringTok{"Hello"}\NormalTok{)}
2018
+ \end{Highlighting}
2019
+ \end{Shaded}
2020
+
2021
+ \begin{verbatim}
2022
+ ## The input is a string: Hello
2023
+ \end{verbatim}
2024
+
2025
+ Ruby has ways of dealing with multiple arguments, missing arguments,
2026
+ undefined number of arguments, named arguments, unnamed arguments, etc.
2027
+ This is beyond the scope of this document and we suggest the interested
2028
+ reader to go to the many resources about Ruby that can easily be found
2029
+ on the web.
2030
+
2031
+ We will now create a new class `Partition' that we will use later in
2032
+ this document. This class will have only the basic methods needed for
2033
+ the examples to work.
2034
+
2035
+ \begin{Shaded}
2036
+ \begin{Highlighting}[]
2037
+ \ControlFlowTok{class} \DataTypeTok{Partition}
2038
+
2039
+ \OtherTok{attr\_reader} \WarningTok{:nb\_groups}
2040
+ \OtherTok{attr\_reader} \WarningTok{:part}
2041
+
2042
+ \ControlFlowTok{def}\NormalTok{ initialize(nb\_groups, part)}
2043
+ \OtherTok{@nb\_groups} \OperatorTok{=}\NormalTok{ nb\_groups}
2044
+ \OtherTok{@part} \OperatorTok{=}\NormalTok{ part}
2045
+ \ControlFlowTok{end}
2046
+
2047
+ \ControlFlowTok{end}
2048
+
2049
+ \OtherTok{@partCochin} \OperatorTok{=} \DataTypeTok{Partition}\AttributeTok{.new}\NormalTok{(}\DecValTok{2}\NormalTok{, }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\StringTok{"A"}\NormalTok{,}\StringTok{"B"}\NormalTok{,}\StringTok{"A"}\NormalTok{,}\StringTok{"B"}\NormalTok{)}\AttributeTok{.factor}\NormalTok{)}
2050
+ \OtherTok{@partStAnne} \OperatorTok{=} \DataTypeTok{Partition}\AttributeTok{.new}\NormalTok{(}\DecValTok{2}\NormalTok{, }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\StringTok{"A"}\NormalTok{,}\StringTok{"B"}\NormalTok{)}\AttributeTok{.rep}\NormalTok{(}\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{50}\NormalTok{,}\DecValTok{30}\NormalTok{))}\AttributeTok{.factor}\NormalTok{)}
2051
+ \end{Highlighting}
2052
+ \end{Shaded}
2053
+
2054
+ \begin{Shaded}
2055
+ \begin{Highlighting}[]
2056
+ \FunctionTok{puts} \OtherTok{@partCochin}\AttributeTok{.part}
2057
+ \end{Highlighting}
2058
+ \end{Shaded}
2059
+
2060
+ \begin{verbatim}
2061
+ ## [1] A B A B
2062
+ ## Levels: A B
2063
+ \end{verbatim}
2064
+
2065
+ \begin{Shaded}
2066
+ \begin{Highlighting}[]
2067
+ \FunctionTok{puts} \OtherTok{@partStAnne}\AttributeTok{.part}
2068
+ \end{Highlighting}
2069
+ \end{Shaded}
2070
+
2071
+ \begin{verbatim}
2072
+ ## [1] A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A
2073
+ ## [34] A A A A A A A A A A A A A A A A A B B B B B B B B B B B B B B B B
2074
+ ## [67] B B B B B B B B B B B B B B
2075
+ ## Levels: A B
2076
+ \end{verbatim}
2077
+
2078
+ We will suppose that part is always composed of capital letters going
2079
+ from A to LETTERS{[}nb\_groups{]}.
2080
+
2081
+ \section{Inheritance}\label{inheritance}
2082
+
2083
+ Ruby being a powerful Object Oriented language has the concept of
2084
+ Inheritance, but it does not allow for multiple inheritance. Multiple
2085
+ inheritance has many drawbacks and Ruby just does not support it.
2086
+ However, Ruby has other concepts that make up for the lack of multiple
2087
+ inheritance as we will see in the following examples.
2088
+
2089
+ So, let's go back to SS4 examples. We want now to define a class called
2090
+ TrajPartitioned that inherits from class Trajectories. When a class has
2091
+ a parent, all methods available for the parent are also available to the
2092
+ child.
2093
+
2094
+ \begin{Shaded}
2095
+ \begin{Highlighting}[]
2096
+ \ControlFlowTok{class} \DataTypeTok{TrajPartitioned} \OperatorTok{\textless{}} \DataTypeTok{Trajectories}
2097
+
2098
+ \OtherTok{attr\_reader} \WarningTok{:list\_partitions}
2099
+
2100
+ \ControlFlowTok{end}
2101
+ \end{Highlighting}
2102
+ \end{Shaded}
2103
+
2104
+ That's all there is to it! We've just created a class TrajPartitioned
2105
+ that inherits all methods from class Trajectories and at this point does
2106
+ nothing different from Trajectories, but adds a new instance variable:
2107
+ list\_partitions.
2108
+
2109
+ Creating TrajPartitioned without arguments will generate an error, since
2110
+ a Trajectories requires both times and matrix to be non null.
2111
+
2112
+ \begin{Shaded}
2113
+ \begin{Highlighting}[]
2114
+ \ControlFlowTok{begin}
2115
+ \OtherTok{@tdPitie} \OperatorTok{=} \DataTypeTok{TrajPartitioned}\AttributeTok{.new}
2116
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
2117
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
2118
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
2119
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
2120
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
2121
+ \ControlFlowTok{end}
2122
+ \end{Highlighting}
2123
+ \end{Shaded}
2124
+
2125
+ \begin{verbatim}
2126
+ ## RuntimeError
2127
+ ## Neither times nor matrix can be an empty object
2128
+ \end{verbatim}
2129
+
2130
+ Let's try to create a TrajPartitioned, but passing to it two partitions.
2131
+ For that, let's first create a new Partition:
2132
+
2133
+ \begin{Shaded}
2134
+ \begin{Highlighting}[]
2135
+ \OtherTok{@partCochin2} \OperatorTok{=} \DataTypeTok{Partition}\AttributeTok{.new}\NormalTok{(}\DecValTok{3}\NormalTok{, }\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\StringTok{"A"}\NormalTok{, }\StringTok{"C"}\NormalTok{, }\StringTok{"C"}\NormalTok{, }\StringTok{"B"}\NormalTok{)}\AttributeTok{.factor}\NormalTok{)}
2136
+ \end{Highlighting}
2137
+ \end{Shaded}
2138
+
2139
+ And now let's create the TrajPartitioned:
2140
+
2141
+ \begin{Shaded}
2142
+ \begin{Highlighting}[]
2143
+ \ControlFlowTok{begin}
2144
+ \OtherTok{@tdCochin} \OperatorTok{=} \DataTypeTok{TrajPartitioned}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{,}\DecValTok{3}\NormalTok{,}\DecValTok{4}\NormalTok{,}\DecValTok{5}\NormalTok{),}
2145
+ \WarningTok{matrix:} \OtherTok{@trajCochin}\AttributeTok{.matrix}\NormalTok{,}
2146
+ \WarningTok{list\_partitions:} \ConstantTok{R}\AttributeTok{.list}\NormalTok{(}\OtherTok{@partCochin}\NormalTok{,}
2147
+ \OtherTok{@partCochin2}\NormalTok{))}
2148
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
2149
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
2150
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
2151
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
2152
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
2153
+ \ControlFlowTok{end}
2154
+ \end{Highlighting}
2155
+ \end{Shaded}
2156
+
2157
+ \begin{verbatim}
2158
+ ## ArgumentError
2159
+ ## unknown keyword: :list_partitions
2160
+ \end{verbatim}
2161
+
2162
+ This didn't work: R function `list' expects R objects, and in this case,
2163
+ @partCochin and @partCochin2 are Ruby classes, so trying to apply
2164
+ function list to them does not work. Clearly, we will have to work in
2165
+ the realm of Ruby to keep the list of partitions. This is not a problem
2166
+ as Ruby has data structures to maintain a list of objects, the Array.
2167
+ Let's then try another solution:
2168
+
2169
+ \begin{Shaded}
2170
+ \begin{Highlighting}[]
2171
+ \ControlFlowTok{begin}
2172
+ \OtherTok{@tdCochin} \OperatorTok{=} \DataTypeTok{TrajPartitioned}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{,}\DecValTok{3}\NormalTok{,}\DecValTok{4}\NormalTok{,}\DecValTok{5}\NormalTok{),}
2173
+ \WarningTok{matrix:} \OtherTok{@trajCochin}\AttributeTok{.matrix}\NormalTok{,}
2174
+ \WarningTok{list\_partitions:} \KeywordTok{[}\OtherTok{@partCochin}\NormalTok{,}
2175
+ \OtherTok{@partCochin2}\KeywordTok{]}\NormalTok{)}
2176
+ \ControlFlowTok{rescue} \OperatorTok{=\textgreater{}}\NormalTok{ e}
2177
+ \CommentTok{\# Short message only — full backtraces overflow PDF boxes.}
2178
+ \FunctionTok{puts}\NormalTok{ e}\AttributeTok{.class.to\_s}
2179
+ \CommentTok{\# Wrap long messages for PDF code{-}box width.}
2180
+ \NormalTok{ e}\AttributeTok{.message.to\_s.scan}\NormalTok{(}\SpecialStringTok{/.\{1,68\}/}\NormalTok{)}\AttributeTok{.each} \OperatorTok{\{} \OperatorTok{|}\NormalTok{line}\OperatorTok{|} \FunctionTok{puts}\NormalTok{ line }\OperatorTok{\}}
2181
+ \ControlFlowTok{end}
2182
+ \end{Highlighting}
2183
+ \end{Shaded}
2184
+
2185
+ \begin{verbatim}
2186
+ ## ArgumentError
2187
+ ## unknown keyword: :list_partitions
2188
+ \end{verbatim}
2189
+
2190
+ We now get a second error: `unknown keyword: list\_partitions'. Class
2191
+ TrajPartitioned inherits from class Trajectories and class Trajectories
2192
+ has an initialize function that requires two parameters, times and
2193
+ matrix; list\_partitions is not a parameter for initialize and is thus
2194
+ unknown. In order to fix this problem we need to create an initialize
2195
+ method for class TrajPartitioned.
2196
+
2197
+ \section{The `super' Keyword}\label{the-super-keyword}
2198
+
2199
+ R has a method called `callNextMethod' for control flow between
2200
+ inherited classes. In Ruby, we have a model that is a bit different.
2201
+ When a method is called on a subclass, if this method is not found it
2202
+ will be searched in the parent class and it will go up the hierarchy of
2203
+ classes until it is found or an error is issued. If we want the parent
2204
+ method to be called we can call `super':
2205
+
2206
+ \begin{Shaded}
2207
+ \begin{Highlighting}[]
2208
+ \ControlFlowTok{class} \DataTypeTok{TrajPartitioned}
2209
+
2210
+ \ControlFlowTok{def}\NormalTok{ initialize(times}\OperatorTok{:} \DecValTok{nil}\NormalTok{, }\WarningTok{matrix:} \DecValTok{nil}\NormalTok{, }\WarningTok{list\_partitions:} \DecValTok{nil}\NormalTok{)}
2211
+ \DecValTok{super}\NormalTok{(}\WarningTok{times:}\NormalTok{ times, }\WarningTok{matrix:}\NormalTok{ matrix)}
2212
+ \OtherTok{@list\_partitions} \OperatorTok{=}\NormalTok{ list\_partitions}
2213
+ \ControlFlowTok{end}
2214
+
2215
+ \ControlFlowTok{end}
2216
+ \end{Highlighting}
2217
+ \end{Shaded}
2218
+
2219
+ Let's try our example again:
2220
+
2221
+ \begin{Shaded}
2222
+ \begin{Highlighting}[]
2223
+ \OtherTok{@tdCochin} \OperatorTok{=} \DataTypeTok{TrajPartitioned}\AttributeTok{.new}\NormalTok{(}\WarningTok{times:} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{,}\DecValTok{3}\NormalTok{,}\DecValTok{4}\NormalTok{,}\DecValTok{5}\NormalTok{),}
2224
+ \WarningTok{matrix:} \OtherTok{@trajCochin}\AttributeTok{.matrix}\NormalTok{,}
2225
+ \WarningTok{list\_partitions:} \KeywordTok{[}\OtherTok{@partCochin}\NormalTok{,}
2226
+ \OtherTok{@partCochin2}\KeywordTok{]}\NormalTok{)}
2227
+ \end{Highlighting}
2228
+ \end{Shaded}
2229
+
2230
+ \begin{verbatim}
2231
+ ## ~~~ Trajectories: inspector ~~~
2232
+ ## ~~~ Trajectories: initializator ~~~
2233
+ ## *** Class Trajectories, method Show ***
2234
+ ## times = 1
2235
+ ## 3
2236
+ ## 4
2237
+ ## 5
2238
+ ## * Traj (limited to a matrix 10x10) =
2239
+ ## T1 T3 T4 T5
2240
+ ## I1 "15.00" "15.10" "15.20" "15.20"
2241
+ ## I2 "16.00" "15.90" "16.00" "16.40"
2242
+ ## I3 "15.20" " NA" "15.30" "15.30"
2243
+ ## I4 "15.70" "15.60" "15.80" "16.00"
2244
+ ## ******* End Show (trajectories) *******
2245
+ \end{verbatim}
2246
+
2247
+ Now @tdCochin is created correctly; however, the `show' method only
2248
+ shows information about times and matrix, there is nothing about our new
2249
+ list\_partitions variable. This is so, since there is no method `show'
2250
+ in TrajPartitioned, so method `show' from Trajectories is executed.
2251
+
2252
+ So, let's start by writing a `print' method, that will print all the
2253
+ information we have in TrajPartitioned. The flow of control for this
2254
+ method is: Ruby sees a call to `print', so it checks to see if `print'
2255
+ is a method for TrajPartitioned. Since we have just defined this method,
2256
+ Ruby finds it and executes it. The first command in print is a call to
2257
+ `super', which will call the parent `print' method, that prints
2258
+ information for `times' and `matrix'. When the parent `print' finishes
2259
+ control continues after the `super' call, printing the number of
2260
+ available partitions.
2261
+
2262
+ \begin{Shaded}
2263
+ \begin{Highlighting}[]
2264
+ \ControlFlowTok{class} \DataTypeTok{TrajPartitioned}
2265
+
2266
+ \ControlFlowTok{def} \FunctionTok{print}
2267
+ \DecValTok{super}
2268
+ \FunctionTok{puts}\NormalTok{(}
2269
+ \StringTok{"the object also contains "} \OperatorTok{+}
2270
+ \StringTok{"}\SpecialCharTok{\#\{}\OtherTok{@list\_partitions}\AttributeTok{.length}\SpecialCharTok{\}}\StringTok{ partition"}\NormalTok{)}
2271
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"***** Fine of print (TrajPartitioned) *****"}\NormalTok{)}
2272
+ \ControlFlowTok{end}
2273
+
2274
+ \ControlFlowTok{end}
2275
+ \end{Highlighting}
2276
+ \end{Shaded}
2277
+
2278
+ \begin{Shaded}
2279
+ \begin{Highlighting}[]
2280
+ \OtherTok{@tdCochin}\AttributeTok{.print}
2281
+ \end{Highlighting}
2282
+ \end{Shaded}
2283
+
2284
+ \begin{verbatim}
2285
+ ## *** Class Trajectories, method Print ***
2286
+ ## times = 1
2287
+ ## 3
2288
+ ## 4
2289
+ ## 5
2290
+ ## traj =
2291
+ ## T1 T3 T4 T5
2292
+ ## I1 15.0 15.1 15.2 15.2
2293
+ ## I2 16.0 15.9 16.0 16.4
2294
+ ## I3 15.2 NA 15.3 15.3
2295
+ ## I4 15.7 15.6 15.8 16.0
2296
+ ## ******* End Print (trajectories) *******
2297
+ ## the object also contains 2 partition
2298
+ ## ***** Fine of print (TrajPartitioned) *****
2299
+ \end{verbatim}
2300
+
2301
+ Notice that this model is much cleaner than `callNextMethod' and is not
2302
+ subject to any of the difficulties presented in SS4 and there is no need
2303
+ for the keywords ``is'', ``as'' and ``as\textless-'', although Ruby
2304
+ provides methods to check the class of an object, its hierarchy, etc.
2305
+ when needed.
2306
+
2307
+ In Ruby there is no similar method as ``setIs'' and it is not possible
2308
+ to convert one class into another, but there are other ways of getting
2309
+ the necessary results. Let's then implement a method that returns the
2310
+ partition with the least number of groups. First, as usual, the R code
2311
+ with `setIs':
2312
+
2313
+ \begin{verbatim}
2314
+ > setIs(
2315
+ + class1="TrajPartitioned",
2316
+ + class2="Partition",
2317
+ + coerce=function(from,to){
2318
+ + numberGroups <- sapply(tdCochin@listPartitions,getNbGroups)
2319
+ + Smallest <- which.min(-numberGroups)
2320
+ + to<-new("Partition")
2321
+ + to@nbGroups <- getNbGroups(from@listPartitions[[Smallest]])
2322
+ + to@part <- getPart(from@listPartitions[[Smallest]])
2323
+ + return(to)
2324
+ + }
2325
+ + )
2326
+ \end{verbatim}
2327
+
2328
+ And now the Ruby code. Here we are getting deeper into Ruby and it is
2329
+ becoming harder for a pure R developer to understand the code. We will
2330
+ describe it in more detail:
2331
+
2332
+ \begin{itemize}
2333
+ \item
2334
+ We define a method called `to\_part' that has one argument `which'. By
2335
+ default `which' is `:min', the name of the minimum method. This means
2336
+ that if no argument is given to to\_part it will assume which = :min;
2337
+ \item
2338
+ @list\_partitions is a Ruby array. Method map is similar to method
2339
+ sapply in R, it applies a `block' to every element of the array,
2340
+ returning an array. Describing blocks is beyond the scope of this
2341
+ document, but we can think of it as if it were a function. The block
2342
+ is in `\{\}' and has one argument named `part'. Thus, map goes through
2343
+ all elements of the array, and gets the nb\_groups of the element and
2344
+ returns them into the number\_groups array.
2345
+ \item
2346
+ number\_groups is an array and doing number\_groups.min returns the
2347
+ minimum value in number\_groups and number\_groups.max the maximum. We
2348
+ can call a method on an object by `sending' the method name to the
2349
+ object, so, number\_groups.send(:min) is equivalent to
2350
+ number\_groups.min;
2351
+ \item
2352
+ Method `index' for array, returns the index of a given element. So,
2353
+ number\_groups.index(3) would return the index of the element `3'.
2354
+ Then number\_groups.index(number\_groups.min) returns the index of the
2355
+ minimum element in the array. This is the equivalent of R
2356
+ which.min(number\_groups);
2357
+ \item
2358
+ Finally, number\_groups.index(number\_groups.send(which)), will return
2359
+ the index of the element we ask for, be it :min or :max. Note that if
2360
+ we pass another value, this would be an error.
2361
+ \end{itemize}
2362
+
2363
+ \begin{Shaded}
2364
+ \begin{Highlighting}[]
2365
+ \ControlFlowTok{class} \DataTypeTok{TrajPartitioned}
2366
+
2367
+ \ControlFlowTok{def}\NormalTok{ to\_part(which }\OperatorTok{=} \WarningTok{:min}\NormalTok{)}
2368
+ \NormalTok{ number\_groups }\OperatorTok{=} \OtherTok{@list\_partitions}\AttributeTok{.map} \OperatorTok{\{} \OperatorTok{|}\NormalTok{part}\OperatorTok{|}\NormalTok{ part}\AttributeTok{.nb\_groups} \OperatorTok{\}}
2369
+ \NormalTok{ selected }\OperatorTok{=}\NormalTok{ number\_groups}\AttributeTok{.index}\NormalTok{(number\_groups}\AttributeTok{.send}\NormalTok{(which))}
2370
+ \ControlFlowTok{return} \OtherTok{@list\_partitions}\KeywordTok{[}\NormalTok{selected}\KeywordTok{]}
2371
+ \ControlFlowTok{end}
2372
+
2373
+ \ControlFlowTok{end}
2374
+ \end{Highlighting}
2375
+ \end{Shaded}
2376
+
2377
+ To get the partition with the minimum number of elements:
2378
+
2379
+ \begin{Shaded}
2380
+ \begin{Highlighting}[]
2381
+ \FunctionTok{puts} \OtherTok{@tdCochin}\AttributeTok{.to\_part.part}
2382
+ \end{Highlighting}
2383
+ \end{Shaded}
2384
+
2385
+ \begin{verbatim}
2386
+ ## [1] A B A B
2387
+ ## Levels: A B
2388
+ \end{verbatim}
2389
+
2390
+ To get the partition with the maximum number of elements:
2391
+
2392
+ \begin{Shaded}
2393
+ \begin{Highlighting}[]
2394
+ \FunctionTok{puts} \OtherTok{@tdCochin}\AttributeTok{.to\_part}\NormalTok{(}\WarningTok{:max}\NormalTok{)}\AttributeTok{.part}
2395
+ \end{Highlighting}
2396
+ \end{Shaded}
2397
+
2398
+ \begin{verbatim}
2399
+ ## [1] A C C B
2400
+ ## Levels: A B C
2401
+ \end{verbatim}
2402
+
2403
+ In this example we did not follow exactly the R code from SS4. The
2404
+ reason for that is that `list\_partitions' is a list of Ruby classes and
2405
+ we cannot run sapply on this list. If we try to call a `getNbGroups' or
2406
+ in the Ruby case nb\_groups via R's sapply, the code will crash.
2407
+
2408
+ \section{Virtual Classes}\label{virtual-classes}
2409
+
2410
+ In Ruby there are no ``Virtual Classes'', but it is possible to
2411
+ implement derived classes from a parent class with methods that behave
2412
+ properly according to the object's class. Following SS4 we will
2413
+ implement two classes: PartitionSimple and PartitionEval which are
2414
+ subclasses of class PartitionFather. PartitionFather will just be a
2415
+ regular class. Methods defined in PartitionFather will be available to
2416
+ be used in the subclasses
2417
+
2418
+ Here is the R code of those classes and the implementation of a method
2419
+ in PartitionFather that multiplies the number of groups by 2:
2420
+
2421
+ \begin{verbatim}
2422
+ > setClass(
2423
+ + Class="PartitionFather",
2424
+ + representation=representation(nbGroups="numeric","VIRTUAL")
2425
+ + )
2426
+
2427
+ > setClass(
2428
+ + Class="PartitionSimple",
2429
+ + representation=representation(part="factor"),
2430
+ + contains="PartitionFather"
2431
+ + )
2432
+
2433
+ > setClass(
2434
+ + Class="PartitionEval",
2435
+ + representation=representation(part="ordered"),
2436
+ + contains="PartitionFather"
2437
+ + )
2438
+
2439
+ > setGeneric("nbMultTwo",function(object){standardGeneric("nbMultTwo")})
2440
+
2441
+ > setMethod("nbMultTwo","PartitionFather",
2442
+ + function(object){
2443
+ + object@nbGroups <- object@nbGroups*2
2444
+ + return (object)
2445
+ + }
2446
+ + )
2447
+ \end{verbatim}
2448
+
2449
+ Since Ruby has no type definition, there is no really need for a parent
2450
+ class and subclasses. However, we will implement those classes in order
2451
+ to show Ruby's inheritance:
2452
+
2453
+ \begin{Shaded}
2454
+ \begin{Highlighting}[]
2455
+ \CommentTok{\# Parent class. Differently from SS4, both \textquotesingle{}nb\_groups\textquotesingle{} and \textquotesingle{}part\textquotesingle{} are}
2456
+ \CommentTok{\# defined in the}
2457
+ \CommentTok{\# parent class.}
2458
+ \ControlFlowTok{class} \DataTypeTok{PartitionFather}
2459
+
2460
+ \OtherTok{attr\_reader} \WarningTok{:nb\_groups}
2461
+ \OtherTok{attr\_reader} \WarningTok{:part}
2462
+
2463
+ \CommentTok{\# initialize class PartitionFather with the number of groups and}
2464
+ \CommentTok{\# parts. Note that we}
2465
+ \CommentTok{\# use R.c for nb\_groups in order to convert the number of groups into}
2466
+ \CommentTok{\# an R vector.}
2467
+ \ControlFlowTok{def}\NormalTok{ initialize(nb\_groups}\OperatorTok{:} \DecValTok{0}\NormalTok{, }\WarningTok{part:} \DecValTok{nil}\NormalTok{)}
2468
+ \OtherTok{@nb\_groups} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.c}\NormalTok{(nb\_groups)}
2469
+ \OtherTok{@part} \OperatorTok{=}\NormalTok{ part}
2470
+ \ControlFlowTok{end}
2471
+
2472
+ \CommentTok{\# method nb\_mult\_two can be called from all subclasses}
2473
+ \ControlFlowTok{def}\NormalTok{ nb\_mult\_two}
2474
+ \OtherTok{@nb\_groups} \OperatorTok{*} \DecValTok{2}
2475
+ \ControlFlowTok{end}
2476
+
2477
+ \CommentTok{\# method \textquotesingle{}to\_s\textquotesingle{} is called whenever we try to print a Ruby object.}
2478
+ \CommentTok{\# This method emulates}
2479
+ \CommentTok{\# R \textquotesingle{}print\textquotesingle{} method that prints all the slots.}
2480
+ \ControlFlowTok{def}\NormalTok{ to\_s}
2481
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"Variable \textquotesingle{}nb\_groups\textquotesingle{}:"}\NormalTok{)}
2482
+ \FunctionTok{puts} \OtherTok{@nb\_groups}
2483
+ \FunctionTok{puts}
2484
+ \FunctionTok{puts}\NormalTok{ (}\StringTok{"Variable \textquotesingle{}part\textquotesingle{}:"}\NormalTok{)}
2485
+ \FunctionTok{puts} \OtherTok{@part}
2486
+ \FunctionTok{puts}
2487
+ \ControlFlowTok{end}
2488
+
2489
+ \ControlFlowTok{end}
2490
+
2491
+ \CommentTok{\# Class PartitionSimple is a subclass of PartitionFather. To make a}
2492
+ \CommentTok{\# subclass of a}
2493
+ \CommentTok{\# class we use the operator \textquotesingle{}\textless{}\textquotesingle{}. Since the whole logic is in the parent}
2494
+ \CommentTok{\# class}
2495
+ \CommentTok{\# PartitionSimple is just an empty class}
2496
+ \ControlFlowTok{class} \DataTypeTok{PartitionSimple} \OperatorTok{\textless{}} \DataTypeTok{PartitionFather}
2497
+
2498
+ \ControlFlowTok{end}
2499
+
2500
+ \CommentTok{\# PartitionEval is also only an empty class}
2501
+ \ControlFlowTok{class} \DataTypeTok{PartitionEval} \OperatorTok{\textless{}} \DataTypeTok{PartitionFather}
2502
+
2503
+ \ControlFlowTok{end}
2504
+ \end{Highlighting}
2505
+ \end{Shaded}
2506
+
2507
+ \begin{Shaded}
2508
+ \begin{Highlighting}[]
2509
+ \OtherTok{@a} \OperatorTok{=} \DataTypeTok{PartitionSimple}\AttributeTok{.new}\NormalTok{(}
2510
+ \WarningTok{nb\_groups:} \DecValTok{3}\NormalTok{,}
2511
+ \WarningTok{part:}\NormalTok{ ((}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:LETTERS}\KeywordTok{]}\NormalTok{)}\KeywordTok{[}\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{3}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{1}\NormalTok{)}\KeywordTok{]}\AttributeTok{.factor}\NormalTok{))}
2512
+ \FunctionTok{puts} \OtherTok{@a}
2513
+ \end{Highlighting}
2514
+ \end{Shaded}
2515
+
2516
+ \begin{verbatim}
2517
+ ## Variable 'nb_groups':
2518
+ ## 3
2519
+ ##
2520
+ ## Variable 'part':
2521
+ ## [1] A B C B B A
2522
+ ## Levels: A B C
2523
+ ##
2524
+ ## #<RC::PartitionSimple:0x6b85a357>
2525
+ \end{verbatim}
2526
+
2527
+ \begin{Shaded}
2528
+ \begin{Highlighting}[]
2529
+ \FunctionTok{puts} \OtherTok{@a}\AttributeTok{.nb\_mult\_two}
2530
+ \end{Highlighting}
2531
+ \end{Shaded}
2532
+
2533
+ \begin{verbatim}
2534
+ ## [1] 6
2535
+ \end{verbatim}
2536
+
2537
+ \begin{Shaded}
2538
+ \begin{Highlighting}[]
2539
+ \OtherTok{@b} \OperatorTok{=} \DataTypeTok{PartitionEval}\AttributeTok{.new}\NormalTok{(}
2540
+ \WarningTok{nb\_groups:} \DecValTok{5}\NormalTok{,}
2541
+ \WarningTok{part:}\NormalTok{ (}\OperatorTok{\textasciitilde{}}\ConstantTok{R}\KeywordTok{[}\WarningTok{:LETTERS}\KeywordTok{]}\NormalTok{)}\KeywordTok{[}\ConstantTok{R}\AttributeTok{.c}\NormalTok{(}\DecValTok{1}\NormalTok{, }\DecValTok{5}\NormalTok{, }\DecValTok{3}\NormalTok{, }\DecValTok{4}\NormalTok{, }\DecValTok{2}\NormalTok{, }\DecValTok{4}\NormalTok{)}\KeywordTok{]}\AttributeTok{.ordered}\NormalTok{)}
2542
+ \FunctionTok{puts} \OtherTok{@b}
2543
+ \end{Highlighting}
2544
+ \end{Shaded}
2545
+
2546
+ \begin{verbatim}
2547
+ ## Variable 'nb_groups':
2548
+ ## 5
2549
+ ##
2550
+ ## Variable 'part':
2551
+ ## [1] A E C D B D
2552
+ ## Levels: A < B < C < D < E
2553
+ ##
2554
+ ## #<RC::PartitionEval:0x462891eb>
2555
+ \end{verbatim}
2556
+
2557
+ \begin{Shaded}
2558
+ \begin{Highlighting}[]
2559
+ \FunctionTok{puts} \OtherTok{@b}\AttributeTok{.nb\_mult\_two}
2560
+ \end{Highlighting}
2561
+ \end{Shaded}
2562
+
2563
+ \begin{verbatim}
2564
+ ## [1] 10
2565
+ \end{verbatim}
2566
+
2567
+ The example above, although it replicates SS4 is not actually very
2568
+ useful from the point of view of class hierarchy in Ruby. We will then
2569
+ write a new function to\_s in class PartitionSimple that will print the
2570
+ name of the class:
2571
+
2572
+ \begin{Shaded}
2573
+ \begin{Highlighting}[]
2574
+ \ControlFlowTok{class} \DataTypeTok{PartitionSimple}
2575
+
2576
+ \ControlFlowTok{def}\NormalTok{ to\_s}
2577
+ \FunctionTok{puts}\NormalTok{(}\StringTok{"Class PartitionSimple"}\NormalTok{)}
2578
+ \DecValTok{super}
2579
+ \ControlFlowTok{end}
2580
+
2581
+ \ControlFlowTok{end}
2582
+ \end{Highlighting}
2583
+ \end{Shaded}
2584
+
2585
+ \begin{Shaded}
2586
+ \begin{Highlighting}[]
2587
+ \FunctionTok{puts} \OtherTok{@a}
2588
+ \end{Highlighting}
2589
+ \end{Shaded}
2590
+
2591
+ \begin{verbatim}
2592
+ ## Class PartitionSimple
2593
+ ## Variable 'nb_groups':
2594
+ ## 3
2595
+ ##
2596
+ ## Variable 'part':
2597
+ ## [1] A B C B B A
2598
+ ## Levels: A B C
2599
+ ##
2600
+ ## #<RC::PartitionSimple:0x6b85a357>
2601
+ \end{verbatim}
2602
+
2603
+ As can be seen, `puts @a' now calls method `to\_s' defined in class
2604
+ PartitionSimple. This method prints `Class PartitionSimple' and then
2605
+ calls the super method, i.e., method `to\_s' from class PartitionFather.
2606
+
2607
+ Note though that `puts @b' still prints the same output, since it has no
2608
+ particular `to\_s' method.
2609
+
2610
+ \begin{Shaded}
2611
+ \begin{Highlighting}[]
2612
+ \FunctionTok{puts} \OtherTok{@b}
2613
+ \end{Highlighting}
2614
+ \end{Shaded}
2615
+
2616
+ \begin{verbatim}
2617
+ ## Variable 'nb_groups':
2618
+ ## 5
2619
+ ##
2620
+ ## Variable 'part':
2621
+ ## [1] A E C D B D
2622
+ ## Levels: A < B < C < D < E
2623
+ ##
2624
+ ## #<RC::PartitionEval:0x462891eb>
2625
+ \end{verbatim}
2626
+
2627
+ \section{Internal Modification of an
2628
+ Object}\label{internal-modification-of-an-object}
2629
+
2630
+ \subsection{Method to Modify a Field}\label{method-to-modify-a-field}
2631
+
2632
+ Let us return to our trajectories example and define a third method that
2633
+ imputes data for missing values. To simplify, we will impute by
2634
+ replacing by the mean values. This is the R code to do this:
2635
+
2636
+ \begin{verbatim}
2637
+ > meanWithoutNa <- function (x){mean(x,na.rm=TRUE)}
2638
+ > setGeneric("impute",function (.Object){standardGeneric("impute")})
2639
+ > setMethod(
2640
+ + f="impute",
2641
+ + signature="Trajectories",
2642
+ + def=function(.Object){
2643
+ + average <- apply(.Object@traj,2,meanWithoutNa)
2644
+ + for (iCol in 1:ncol(.Object@traj)){
2645
+ + .Object@traj[is.na(.Object@traj[,iCol]),iCol] <- average[iCol]
2646
+ + }
2647
+ + return(.Object)
2648
+ + }
2649
+ + )
2650
+ \end{verbatim}
2651
+
2652
+ The code above, as explained in SS4 creates a new object and does not
2653
+ change the original one. So, calling impute(trajCochin) will work
2654
+ correctly by creating a new object but will not change trajCochin. This
2655
+ works fine, but can be memory expensive if the matrix is a large one.
2656
+
2657
+ Let's now implement the same method in Galaaz 2.0. We stay on the R side
2658
+ of the bridge: for each column, compute the mean with
2659
+ \texttt{na.rm\ =\ true}, then replace NA entries with that mean (via
2660
+ \texttt{R.ifelse} / \texttt{is\_\_na}), and rebuild the matrix with
2661
+ \texttt{R.cbind}. No MDArray iteration is required.
2662
+
2663
+ \begin{Shaded}
2664
+ \begin{Highlighting}[]
2665
+ \ControlFlowTok{class} \DataTypeTok{Trajectories}
2666
+
2667
+ \ControlFlowTok{def}\NormalTok{ impute}
2668
+ \NormalTok{ ncols }\OperatorTok{=} \OtherTok{@matrix}\AttributeTok{.ncol} \OperatorTok{\textgreater{}\textgreater{}} \DecValTok{0}
2669
+ \NormalTok{ imputed }\OperatorTok{=}\NormalTok{ (}\DecValTok{1}\OperatorTok{..}\NormalTok{ncols)}\AttributeTok{.map} \ControlFlowTok{do} \OperatorTok{|}\NormalTok{j}\OperatorTok{|}
2670
+ \NormalTok{ col }\OperatorTok{=} \OtherTok{@matrix}\KeywordTok{[}\DecValTok{nil}\NormalTok{, j}\KeywordTok{]}
2671
+ \NormalTok{ avg }\OperatorTok{=}\NormalTok{ col}\AttributeTok{.mean}\NormalTok{(}\WarningTok{na\_\_rm:} \DecValTok{true}\NormalTok{)}
2672
+ \ConstantTok{R}\AttributeTok{.ifelse}\NormalTok{(col}\AttributeTok{.is\_\_na}\NormalTok{, avg, col)}
2673
+ \ControlFlowTok{end}
2674
+ \NormalTok{ col\_names }\OperatorTok{=} \OtherTok{@matrix}\AttributeTok{.colnames}
2675
+ \NormalTok{ row\_names }\OperatorTok{=} \OtherTok{@matrix}\AttributeTok{.rownames}
2676
+ \OtherTok{@matrix} \OperatorTok{=} \ConstantTok{R}\AttributeTok{.cbind}\NormalTok{(}\OperatorTok{*}\NormalTok{imputed)}
2677
+ \OtherTok{@matrix}\AttributeTok{.colnames} \OperatorTok{=}\NormalTok{ col\_names }\ControlFlowTok{unless}\NormalTok{ col\_names}\AttributeTok{.nil?}
2678
+ \OtherTok{@matrix}\AttributeTok{.rownames} \OperatorTok{=}\NormalTok{ row\_names }\ControlFlowTok{unless}\NormalTok{ row\_names}\AttributeTok{.nil?}
2679
+ \DecValTok{self}
2680
+ \ControlFlowTok{end}
2681
+
2682
+ \ControlFlowTok{end}
2683
+ \end{Highlighting}
2684
+ \end{Shaded}
2685
+
2686
+ \begin{Shaded}
2687
+ \begin{Highlighting}[]
2688
+ \OtherTok{@trajCochin}\AttributeTok{.impute}
2689
+ \FunctionTok{puts} \OtherTok{@trajCochin}\AttributeTok{.matrix}
2690
+ \end{Highlighting}
2691
+ \end{Shaded}
2692
+
2693
+ \begin{verbatim}
2694
+ ## $rownames
2695
+ ## [1] "I1" "I2" "I3" "I4"
2696
+ \end{verbatim}
2697
+
2698
+ It works, and \texttt{@trajCochin.matrix} was updated. Under GNU R,
2699
+ assignment follows R's usual copy-on-write semantics: replacing
2700
+ \texttt{@matrix} (or assigning into an R object through the bridge)
2701
+ binds a new vector/matrix rather than mutating a shared MDArray store.
2702
+ That is a deliberate difference from the Renjin/MDArray mutation
2703
+ experiments in the older paper; those demos are not part of Galaaz 2.0.
2704
+
2705
+ \section{Conclusions I}\label{conclusions-i}
2706
+
2707
+ This ends the SS4 paper material for classes and inheritance. We believe
2708
+ we have shown that R S4 can be substituted by Galaaz and Ruby classes
2709
+ and that Galaaz makes an easy transition from R developers to Ruby. Ruby
2710
+ is a very flexible and powerful language and has many interesting
2711
+ libraries, where Rails is maybe one of the best known, but there are
2712
+ thousands of others. For those interested in getting deeper into Ruby's
2713
+ libraries, we suggest they look at:
2714
+
2715
+ \begin{itemize}
2716
+ \tightlist
2717
+ \item
2718
+ \url{https://github.com/markets/awesome-ruby}
2719
+ \item
2720
+ \url{http://bestgems.org/}
2721
+ \end{itemize}
2722
+
2723
+ For those interested in Ruby and science, we recommend:
2724
+
2725
+ \begin{itemize}
2726
+ \tightlist
2727
+ \item
2728
+ \url{http://sciruby.com/}
2729
+ \end{itemize}
2730
+
2731
+ \textbf{Galaaz 2.0} runs on \textbf{JRuby or CRuby} and talks to
2732
+ \textbf{GNU R} through the bridge described in this series --- the same
2733
+ integration model used throughout the examples above.
2734
+
2735
+ \section{Callbacks and R calling into
2736
+ Ruby}\label{callbacks-and-r-calling-into-ruby}
2737
+
2738
+ On this paper we have focused on accessing R functions from Ruby and
2739
+ have shown how to integrate Ruby with R from the point of view of a Ruby
2740
+ developer. The complementary direction --- R calling back into Ruby ---
2741
+ is also supported in Galaaz 2.0.
2742
+
2743
+ Galaaz 2.0 uses the \textbf{bridge callback} mechanism: Ruby procs (and
2744
+ related callables) can be passed where R expects functions, so
2745
+ algorithms written in R (for example optimizers or higher-order
2746
+ \texttt{*apply} helpers) can invoke Ruby logic without leaving the
2747
+ bridge session. Details, options such as callback timeouts, and further
2748
+ examples are in the project manual and on the documentation site:
2749
+ \url{https://rbotafogo.github.io/galaaz/}.
2750
+
2751
+ We do not reproduce here the older Renjin-era material on packing Ruby
2752
+ objects as R external pointers, constructing Ruby classes from R via JVM
2753
+ APIs, or calling Java collections from R scripts. Those sections
2754
+ belonged to a different runtime; the callback bridge is the supported
2755
+ path in Galaaz 2.0.
2756
+
2757
+ \section{Conclusions II}\label{conclusions-ii}
2758
+
2759
+ \textbf{JRuby or CRuby + GNU R + Galaaz} gives a practical polyglot
2760
+ stack: idiomatic Ruby for structure and libraries, GNU R for statistics
2761
+ and the CRAN/Bioconductor ecosystem, and Galaaz as the bridge between
2762
+ them. As always, choose the right tools for the job at hand --- and when
2763
+ the job sits between an R-only workflow and a broader polyglot
2764
+ application, Galaaz is designed to connect those worlds.
2765
+
821
2766
  \end{document}