y_nelson 2.3.7 → 2.3.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d8ae630804969be734da51a5b79f46d4ecca69b
4
- data.tar.gz: 56a6b0a5c3271882bfd872c4c99de8046703c105
3
+ metadata.gz: 2664cdfd13c78e426981d4688093b62d0c8a5847
4
+ data.tar.gz: 2a9f8441a7000c7f4640004016bb8e62d7b41f5e
5
5
  SHA512:
6
- metadata.gz: f8db0f66ffda5c2e43dd179b5f7d2360a67c4662f578ed165a29eadacee87ac07d72f5052229e884f070872402aeb791a4e5d69cfd6af83432ef79521b56181a
7
- data.tar.gz: 3d571c38e86c48b3c5f0b881406821c25d858c5c03826c51bcee5b0f036f417eda6a3a6fa80e862ce74d2cef71d919bba9edde88c9edc531049fb0182180a4de
6
+ metadata.gz: 3f56f249ed3febb90312dc724d2a6243b007c03a1a0629f31d65b0830e4e5760870e2f9904133d62cda42457edc93811bd9426666d8c205555731ad65d5e2846
7
+ data.tar.gz: d9a006d4579878f48e3470b0bdee3823c2379c6da5e637bc0d14d63ce4ff4b0e6023aafa4bae4f40cd73362491a0ace9dcb1119875abc0e2f2f2bbe63b29c095
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'yzz'
4
4
  require 'y_petri'
5
- require 'y_support/kde'
6
5
 
7
6
  require 'graphviz'
8
7
 
@@ -137,7 +137,9 @@ class YNelson::Agent
137
137
  }
138
138
 
139
139
  γ.output png: "zz.png" # Generate output image
140
- YSupport::KDE.show_file_with_kioclient File.expand_path( '.', "zz.png" )
140
+
141
+ # The last line only works on KDE systems.
142
+ show_file_with_kioclient File.expand_path( '.', "zz.png" )
141
143
 
142
144
  # main = γ.add_nodes( "main", shape: "box" )
143
145
  # parse = γ.add_nodes( "parse", fillcolor: "yellow", style: "rounded,filled", shape: "diamond" )
@@ -315,4 +317,13 @@ class YNelson::Agent
315
317
  .define_singleton_method name.to_sym do ::YTed::SHEETS[name] end
316
318
  return ::YTed::SHEETS[name]
317
319
  end
320
+
321
+ private
322
+
323
+ # Open a file with kioclient (using KDE file-viewer associations).
324
+ #
325
+ def show_file_with_kioclient( fɴ_with_path )
326
+ # TODO: This is a system-dependent method.
327
+ system "sleep 0.2; kioclient exec 'file:%s'" % fɴ_with_path
328
+ end
318
329
  end
@@ -1,4 +1,4 @@
1
1
  module YNelson
2
- VERSION = "2.3.7"
2
+ VERSION = "2.3.8"
3
3
  DEBUG = false
4
4
  end
@@ -100,7 +100,7 @@ end
100
100
  # @c4 = ϝ { |a0, b0, c0| a0 + b0 + c0 }
101
101
  # new_zz_row @c4
102
102
  # end
103
-
103
+ #
104
104
  # it "should have #make_transitions" do
105
105
  # tt = make_transitions
106
106
  # assert_equal 1, tt.size
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: y_nelson
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.7
4
+ version: 2.3.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - boris
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-28 00:00:00.000000000 Z
11
+ date: 2016-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: yzz
@@ -98,12 +98,9 @@ files:
98
98
  - ".gitignore"
99
99
  - ACKNOWLEDGMENT.txt
100
100
  - Gemfile
101
- - Introduction_to_Ruby_for_YPetri_and_YNelson_Users.lyx
102
101
  - Introduction_to_Ruby_for_YPetri_and_YNelson_Users.pdf
103
- - Introduction_to_YPetri_and_YNelson.lyx
104
102
  - Introduction_to_YPetri_and_YNelson.pdf
105
103
  - LICENSE.txt
106
- - Object_model_of_YPetri_and_YNelson.lyx
107
104
  - Object_model_of_YPetri_and_YNelson.pdf
108
105
  - README.md
109
106
  - Rakefile
@@ -1,3265 +0,0 @@
1
- #LyX 2.1 created this file. For more info see http://www.lyx.org/
2
- \lyxformat 474
3
- \begin_document
4
- \begin_header
5
- \textclass article
6
- \use_default_options false
7
- \maintain_unincluded_children false
8
- \language english
9
- \language_package default
10
- \inputencoding auto
11
- \fontencoding global
12
- \font_roman default
13
- \font_sans default
14
- \font_typewriter default
15
- \font_math auto
16
- \font_default_family default
17
- \use_non_tex_fonts false
18
- \font_sc false
19
- \font_osf false
20
- \font_sf_scale 100
21
- \font_tt_scale 100
22
- \graphics default
23
- \default_output_format default
24
- \output_sync 0
25
- \bibtex_command default
26
- \index_command default
27
- \paperfontsize default
28
- \spacing single
29
- \use_hyperref false
30
- \papersize default
31
- \use_geometry true
32
- \use_package amsmath 1
33
- \use_package amssymb 1
34
- \use_package cancel 1
35
- \use_package esint 1
36
- \use_package mathdots 1
37
- \use_package mathtools 1
38
- \use_package mhchem 1
39
- \use_package stackrel 1
40
- \use_package stmaryrd 1
41
- \use_package undertilde 1
42
- \cite_engine natbib
43
- \cite_engine_type authoryear
44
- \biblio_style plainnat
45
- \use_bibtopic false
46
- \use_indices false
47
- \paperorientation portrait
48
- \suppress_date false
49
- \justification true
50
- \use_refstyle 0
51
- \index Index
52
- \shortcut idx
53
- \color #008000
54
- \end_index
55
- \leftmargin 2.2cm
56
- \topmargin 3cm
57
- \rightmargin 2.2cm
58
- \bottommargin 3cm
59
- \secnumdepth 3
60
- \tocdepth 3
61
- \paragraph_separation indent
62
- \paragraph_indentation default
63
- \quotes_language english
64
- \papercolumns 1
65
- \papersides 1
66
- \paperpagestyle default
67
- \tracking_changes false
68
- \output_changes false
69
- \html_math_output 0
70
- \html_css_as_file 0
71
- \html_be_strict false
72
- \end_header
73
-
74
- \begin_body
75
-
76
- \begin_layout Title
77
- Introduction to Ruby for YNelson Users
78
- \end_layout
79
-
80
- \begin_layout Standard
81
- For
82
- \family typewriter
83
- YNelson
84
- \family default
85
- users, basic Ruby syntax is necessary.
86
- This document is a primer to Ruby for
87
- \family typewriter
88
- YNelson
89
- \family default
90
- users.
91
- This documents should be used in the same way as
92
- \family typewriter
93
- YNelson
94
- \family default
95
- tutorial (Introduction to
96
- \family typewriter
97
- YNelson
98
- \family default
99
- ) – that is, get an
100
- \emph on
101
- irb
102
- \emph default
103
- session running, and type all the examples in by yourself.
104
- You might also wish to install
105
- \family typewriter
106
- YNelson
107
- \family default
108
- by by typing "
109
- \family typewriter
110
- gem install y_nelson
111
- \family default
112
- " from your command line.
113
- Since many of the code samples here rely heavily on each other, you may
114
- consider to do this document in one session.
115
- On the other hand, if you happen to be a Ruby hacker, you do not need to
116
- continue reading this document at all.
117
- This document is not a replacement for a Ruby textbook.
118
- For those, who want more thorough introduction to the language, I recommend
119
- the document
120
- \begin_inset CommandInset href
121
- LatexCommand href
122
- target "http://www.rubyist.net/~slagell/ruby/index.html"
123
-
124
- \end_inset
125
-
126
- , or one of the many Ruby textbooks.
127
- \end_layout
128
-
129
- \begin_layout Part*
130
- Variables and constants
131
- \end_layout
132
-
133
- \begin_layout Standard
134
- In Ruby, everything
135
- \begin_inset Foot
136
- status open
137
-
138
- \begin_layout Plain Layout
139
- Almost everything.
140
- Non-objects include eg.
141
- variables or argument fields.
142
- \end_layout
143
-
144
- \end_inset
145
-
146
- is an
147
- \emph on
148
- \color red
149
- object
150
- \emph default
151
- \color inherit
152
- .
153
- Objects can be assigned to
154
- \emph on
155
- \color red
156
- variables
157
- \emph default
158
- \color inherit
159
- or
160
- \emph on
161
- \color red
162
- constants
163
- \emph default
164
- \color inherit
165
- .
166
- Ruby constants
167
- \color red
168
- must always start with capital letter
169
- \color inherit
170
- .
171
- Variables starting with small letter are
172
- \emph on
173
- \color red
174
- local variables
175
- \emph default
176
- \color inherit
177
- .
178
- (Other types of variables are
179
- \emph on
180
- \color red
181
- instance variables
182
- \emph default
183
- \color inherit
184
- ,
185
- \emph on
186
- \color red
187
- class variables
188
- \emph default
189
- \color inherit
190
- and
191
- \emph on
192
- \color red
193
- global constants
194
- \emph default
195
- \color inherit
196
- ; this is not important at the moment.)
197
- \end_layout
198
-
199
- \begin_layout LyX-Code
200
- alpha = 1
201
- \end_layout
202
-
203
- \begin_layout LyX-Code
204
- #=> 1
205
- \end_layout
206
-
207
- \begin_layout LyX-Code
208
- beta = [1, 2]
209
- \end_layout
210
-
211
- \begin_layout LyX-Code
212
- #=> [1, 2]
213
- \end_layout
214
-
215
- \begin_layout LyX-Code
216
- Gamma = { x: 1, y: 2, z: 3 }
217
- \end_layout
218
-
219
- \begin_layout LyX-Code
220
- #=> {:x=>1, :y=>2, :z=>3}
221
- \end_layout
222
-
223
- \begin_layout Standard
224
- You can check this using
225
- \family typewriter
226
- \color red
227
- defined?
228
- \family default
229
- \color inherit
230
- operator:
231
- \end_layout
232
-
233
- \begin_layout LyX-Code
234
- defined? alpha
235
- \end_layout
236
-
237
- \begin_layout LyX-Code
238
- #=> "local-variable"
239
- \end_layout
240
-
241
- \begin_layout LyX-Code
242
- defined? Gamma
243
- \end_layout
244
-
245
- \begin_layout LyX-Code
246
- #=> "constant"
247
- \end_layout
248
-
249
- \begin_layout Part*
250
- Code lines and comments
251
- \end_layout
252
-
253
- \begin_layout Standard
254
- Comments are denoted by
255
- \family typewriter
256
- #
257
- \family default
258
- sign.
259
- Anything on the line following the
260
- \family typewriter
261
- #
262
- \family default
263
- sign is ignored:
264
- \end_layout
265
-
266
- \begin_layout LyX-Code
267
- puts
268
- \begin_inset Quotes eld
269
- \end_inset
270
-
271
- Hello world!
272
- \begin_inset Quotes erd
273
- \end_inset
274
-
275
- # this line prints the words
276
- \begin_inset Quotes eld
277
- \end_inset
278
-
279
- Hello world!
280
- \begin_inset Quotes erd
281
- \end_inset
282
-
283
-
284
- \end_layout
285
-
286
- \begin_layout Standard
287
- Ruby lines can be written with or without semicolons:
288
- \end_layout
289
-
290
- \begin_layout LyX-Code
291
- a = "with";
292
- \end_layout
293
-
294
- \begin_layout LyX-Code
295
- b = "without"
296
- \end_layout
297
-
298
- \begin_layout LyX-Code
299
- puts [ a, b ].join " or "
300
- \end_layout
301
-
302
- \begin_layout Standard
303
- Semicolon is compulsory only when two or more logical lines are crammed
304
- together like this:
305
- \end_layout
306
-
307
- \begin_layout LyX-Code
308
- a =
309
- \begin_inset Quotes eld
310
- \end_inset
311
-
312
- Hello
313
- \begin_inset Quotes eld
314
- \end_inset
315
-
316
- ; b =
317
- \begin_inset Quotes eld
318
- \end_inset
319
-
320
- world!
321
- \begin_inset Quotes erd
322
- \end_inset
323
-
324
- ; puts a + ' ' + b
325
- \end_layout
326
-
327
- \begin_layout Part*
328
- Methods
329
- \end_layout
330
-
331
- \begin_layout Standard
332
- Different classes respond to different
333
- \emph on
334
- \color red
335
- methods
336
- \emph default
337
- \color inherit
338
- , and respond to them differently:
339
- \end_layout
340
-
341
- \begin_layout LyX-Code
342
- beta.
343
- \color red
344
- size
345
- \end_layout
346
-
347
- \begin_layout LyX-Code
348
- #=> 2
349
- \end_layout
350
-
351
- \begin_layout LyX-Code
352
- Gamma.size
353
- \end_layout
354
-
355
- \begin_layout LyX-Code
356
- #=> 3
357
- \end_layout
358
-
359
- \begin_layout LyX-Code
360
- Gamma.
361
- \color red
362
- keys
363
- \end_layout
364
-
365
- \begin_layout LyX-Code
366
- #=> [:x, :y, :z]
367
- \end_layout
368
-
369
- \begin_layout LyX-Code
370
- Gamma.
371
- \color red
372
- values
373
- \end_layout
374
-
375
- \begin_layout LyX-Code
376
- #=> [1, 2, 3]
377
- \end_layout
378
-
379
- \begin_layout LyX-Code
380
- beta.keys
381
- \end_layout
382
-
383
- \begin_layout LyX-Code
384
- #=> NoMethodError: undefined method `keys' for [1, 2]:Array
385
- \end_layout
386
-
387
- \begin_layout Standard
388
- Methods can be defined by
389
- \family typewriter
390
- \color red
391
- def
392
- \family default
393
- \color inherit
394
- keyword:
395
- \end_layout
396
-
397
- \begin_layout LyX-Code
398
-
399
- \color red
400
- def
401
- \color inherit
402
- average( a, b )
403
- \end_layout
404
-
405
- \begin_layout LyX-Code
406
- ( a + b ).
407
- \color red
408
- to_f
409
- \color inherit
410
- / 2
411
- \end_layout
412
-
413
- \begin_layout LyX-Code
414
-
415
- \color red
416
- end
417
- \end_layout
418
-
419
- \begin_layout LyX-Code
420
- #=> nil
421
- \end_layout
422
-
423
- \begin_layout LyX-Code
424
- average( 2, 3 )
425
- \end_layout
426
-
427
- \begin_layout LyX-Code
428
- #=> 2.5
429
- \end_layout
430
-
431
- \begin_layout Standard
432
- In the code example above, '
433
- \family typewriter
434
- to_f
435
- \family default
436
- ' method performs conversion of an integer into a floating point number,
437
- which is not important.
438
- \end_layout
439
-
440
- \begin_layout Part*
441
- Classes
442
- \end_layout
443
-
444
- \begin_layout Standard
445
- Every object belongs to some
446
- \emph on
447
- \color red
448
- class
449
- \emph default
450
- \color inherit
451
- (object type):
452
- \end_layout
453
-
454
- \begin_layout LyX-Code
455
- alpha.
456
- \color red
457
- class
458
- \end_layout
459
-
460
- \begin_layout LyX-Code
461
- #=>
462
- \color red
463
- Fixnum
464
- \end_layout
465
-
466
- \begin_layout LyX-Code
467
- beta.class
468
- \end_layout
469
-
470
- \begin_layout LyX-Code
471
- #=>
472
- \color red
473
- Array
474
- \end_layout
475
-
476
- \begin_layout LyX-Code
477
- Gamma.class
478
- \end_layout
479
-
480
- \begin_layout LyX-Code
481
- #=>
482
- \color red
483
- Hash
484
- \end_layout
485
-
486
- \begin_layout Standard
487
- New classes can be defined with
488
- \family typewriter
489
- \color red
490
- class
491
- \family default
492
- \color inherit
493
- keyword.
494
- The methods defined inside the class will become the
495
- \emph on
496
- \color red
497
- instance methods
498
- \emph default
499
- \color inherit
500
- of that class:
501
- \end_layout
502
-
503
- \begin_layout LyX-Code
504
- class Dog
505
- \end_layout
506
-
507
- \begin_layout LyX-Code
508
- def speak!
509
- \end_layout
510
-
511
- \begin_layout LyX-Code
512
-
513
- \color red
514
- puts
515
- \color inherit
516
- "Bow wow!"
517
- \end_layout
518
-
519
- \begin_layout LyX-Code
520
- end
521
- \end_layout
522
-
523
- \begin_layout LyX-Code
524
- end
525
- \end_layout
526
-
527
- \begin_layout LyX-Code
528
- #=> nil
529
- \end_layout
530
-
531
- \begin_layout LyX-Code
532
- Spot = Dog.
533
- \color red
534
- new
535
- \end_layout
536
-
537
- \begin_layout LyX-Code
538
- #=> #<Dog:0x9c214ac>
539
- \end_layout
540
-
541
- \begin_layout LyX-Code
542
- Spot.speak!
543
- \end_layout
544
-
545
- \begin_layout LyX-Code
546
- #=> Bow wow!
547
- \end_layout
548
-
549
- \begin_layout LyX-Code
550
- class Cat
551
- \end_layout
552
-
553
- \begin_layout LyX-Code
554
- def speak!
555
- \end_layout
556
-
557
- \begin_layout LyX-Code
558
- puts "Meow"
559
- \end_layout
560
-
561
- \begin_layout LyX-Code
562
- end
563
- \end_layout
564
-
565
- \begin_layout LyX-Code
566
- end
567
- \end_layout
568
-
569
- \begin_layout LyX-Code
570
- #=> nil
571
- \end_layout
572
-
573
- \begin_layout LyX-Code
574
- Lisa = Cat.new
575
- \end_layout
576
-
577
- \begin_layout LyX-Code
578
- #=> #<Cat:0x98efb80>
579
- \end_layout
580
-
581
- \begin_layout LyX-Code
582
- Lisa.speak!
583
- \end_layout
584
-
585
- \begin_layout LyX-Code
586
- #=> Meow
587
- \end_layout
588
-
589
- \begin_layout Standard
590
- These two classes now represent respectively dogs and cats in your irb session.
591
- In the code above, you could notice '
592
- \family typewriter
593
- new
594
- \family default
595
- ' method, used to create instances from the defined classes, and '
596
- \family typewriter
597
- puts
598
- \family default
599
- ' method, used to simply print characters on the screen.
600
- \end_layout
601
-
602
- \begin_layout Part*
603
- Strings, Symbols, Arrays and Hashes
604
- \end_layout
605
-
606
- \begin_layout Standard
607
- For
608
- \family typewriter
609
- YPetri
610
- \family default
611
- users, it will be especially necessary to learn more about
612
- \emph on
613
- \color red
614
- strings
615
- \emph default
616
- \color inherit
617
- ,
618
- \emph on
619
- \color red
620
- symbols
621
- \emph default
622
- \color inherit
623
- ,
624
- \emph on
625
- \color red
626
- arrays
627
- \emph default
628
- \color inherit
629
- ,
630
- \emph on
631
- \color red
632
- hashes
633
- \emph default
634
- \color inherit
635
- , and how to define and read
636
- \emph on
637
- \color red
638
- closures
639
- \emph default
640
- \color inherit
641
- (aka.
642
-
643
- \emph on
644
- anonymous functions
645
- \emph default
646
- ).
647
- Strings and symbols are among the most basic Ruby objects, while arrays
648
- and hashes are important in understanding
649
- \emph on
650
- \color red
651
- argument passing
652
- \emph default
653
- \color inherit
654
- to methods and closures.
655
-
656
- \series bold
657
- \color blue
658
- Understanding argument passing and closure writing is essential in using
659
- YPetri DSL.
660
- \end_layout
661
-
662
- \begin_layout Section*
663
- Strings
664
- \end_layout
665
-
666
- \begin_layout Standard
667
- A string is simply a sequence of characters, which can be defined using
668
- single or double quotes (
669
- \family typewriter
670
- \color red
671
- '
672
- \family default
673
- \color inherit
674
- or
675
- \family typewriter
676
- \color red
677
- "
678
- \family default
679
- \color inherit
680
- ):
681
- \end_layout
682
-
683
- \begin_layout LyX-Code
684
- my_string = 'Hello world!'
685
- \end_layout
686
-
687
- \begin_layout LyX-Code
688
- #=> "Hello world!"
689
- \end_layout
690
-
691
- \begin_layout LyX-Code
692
- my_string.class
693
- \end_layout
694
-
695
- \begin_layout LyX-Code
696
- #=>
697
- \color red
698
- String
699
- \end_layout
700
-
701
- \begin_layout Standard
702
- Strings are mutable (can be changed):
703
- \end_layout
704
-
705
- \begin_layout LyX-Code
706
- my_string.
707
- \color red
708
- object_id
709
- \end_layout
710
-
711
- \begin_layout LyX-Code
712
- #=> 81571950
713
- \end_layout
714
-
715
- \begin_layout LyX-Code
716
- 7.
717
- \color red
718
- times
719
- \color inherit
720
-
721
- \color red
722
- do
723
- \color inherit
724
- my_string.
725
- \color red
726
- chop!
727
- \color inherit
728
-
729
- \color red
730
- end
731
- \end_layout
732
-
733
- \begin_layout LyX-Code
734
- #=> 7
735
- \end_layout
736
-
737
- \begin_layout LyX-Code
738
- my_string
739
- \end_layout
740
-
741
- \begin_layout LyX-Code
742
- #=> "Hello"
743
- \end_layout
744
-
745
- \begin_layout LyX-Code
746
- my_string.object_id
747
- \end_layout
748
-
749
- \begin_layout LyX-Code
750
- #=> 81571950
751
- \end_layout
752
-
753
- \begin_layout Standard
754
- Above, you can newly notice
755
- \family typewriter
756
- times
757
- \family default
758
- method,
759
- \family typewriter
760
- do ...
761
- end
762
- \family default
763
- block, and
764
- \family typewriter
765
- chop!
766
- \family default
767
- method that removes the last character from
768
- \family typewriter
769
- my_string
770
- \family default
771
- 7 times, until only
772
- \family typewriter
773
- "Hello"
774
- \family default
775
- remains.
776
- But the important thing is that as
777
- \family typewriter
778
- object_id
779
- \family default
780
- method shows,
781
- \family typewriter
782
- my_string
783
- \family default
784
- is still the same object (same
785
- \emph on
786
- \color red
787
- object id
788
- \emph default
789
- \color inherit
790
- ), although the contents is changed.
791
- \end_layout
792
-
793
- \begin_layout LyX-Code
794
- my_string
795
- \color red
796
- <<
797
- \color inherit
798
- "Spot!"
799
- \end_layout
800
-
801
- \begin_layout LyX-Code
802
- #=> "Hello Spot!"
803
- \end_layout
804
-
805
- \begin_layout LyX-Code
806
- my_string.object_id
807
- \end_layout
808
-
809
- \begin_layout LyX-Code
810
- #=> 81571950
811
- \end_layout
812
-
813
- \begin_layout Standard
814
- Again,
815
- \family typewriter
816
- <<
817
- \family default
818
- operator changed the contents, but the object id remained the same.
819
- \end_layout
820
-
821
- \begin_layout Section*
822
- Symbols
823
- \end_layout
824
-
825
- \begin_layout Standard
826
- Unlike strings, symbols are immutable – they never change.
827
- They are written with colon (
828
- \family typewriter
829
- \color red
830
- :
831
- \family default
832
- \color inherit
833
- ):
834
- \end_layout
835
-
836
- \begin_layout LyX-Code
837
- :Spot.class
838
- \end_layout
839
-
840
- \begin_layout LyX-Code
841
- #=>
842
- \color red
843
- Symbol
844
- \end_layout
845
-
846
- \begin_layout Section*
847
- Arrays
848
- \end_layout
849
-
850
- \begin_layout Standard
851
- As seen earlier, they can be defined with square brackets
852
- \family typewriter
853
- []
854
- \family default
855
- .
856
- Square brackets are also used to address the array elements, counting from
857
- 0.
858
- \end_layout
859
-
860
- \begin_layout LyX-Code
861
- my_array = [ Spot, Lisa ]
862
- \end_layout
863
-
864
- \begin_layout LyX-Code
865
- #=> [#<Dog:0x9c214ac>, #<Cat:0x98efb80>]
866
- \end_layout
867
-
868
- \begin_layout LyX-Code
869
- my_array[0]
870
- \end_layout
871
-
872
- \begin_layout LyX-Code
873
- #=> #<Dog:0x9c214ac>
874
- \end_layout
875
-
876
- \begin_layout Standard
877
- Negative numbers can be used to address the elements from the end of the
878
- array:
879
- \end_layout
880
-
881
- \begin_layout LyX-Code
882
- my_array[-1]
883
- \end_layout
884
-
885
- \begin_layout LyX-Code
886
- #=> #<Cat:0x98efb80>
887
- \end_layout
888
-
889
- \begin_layout LyX-Code
890
- my_array[-2]
891
- \end_layout
892
-
893
- \begin_layout LyX-Code
894
- #=> #<Dog:0x9c214ac>
895
- \end_layout
896
-
897
- \begin_layout Section*
898
- Hashes
899
- \end_layout
900
-
901
- \begin_layout Standard
902
- As for hashes, there are two ways of defining them.
903
- The first way uses
904
- \emph on
905
- \color red
906
- Ruby rocket
907
- \emph default
908
- \color inherit
909
- (
910
- \family typewriter
911
- \color red
912
- =>
913
- \family default
914
- \color inherit
915
- ):
916
- \end_layout
917
-
918
- \begin_layout LyX-Code
919
- h1 = { Spot => "dog", Lisa => "cat" }
920
- \end_layout
921
-
922
- \begin_layout LyX-Code
923
- #=> {#<Dog:0x9c214ac>=>"dog", #<Cat:0x98efb80>=>"cat"}
924
- \end_layout
925
-
926
- \begin_layout LyX-Code
927
- h1[ Lisa ]
928
- \end_layout
929
-
930
- \begin_layout LyX-Code
931
- #=> "cat"
932
- \end_layout
933
-
934
- \begin_layout LyX-Code
935
- h1[ Spot ]
936
- \end_layout
937
-
938
- \begin_layout LyX-Code
939
- #=> "dog"
940
- \end_layout
941
-
942
- \begin_layout Standard
943
- The second way is possible only when the keys are symbols.
944
- It is done by shifting the colon to the right side of the symbol:
945
- \end_layout
946
-
947
- \begin_layout LyX-Code
948
- h2 = { dog: Spot, cat: Lisa }
949
- \end_layout
950
-
951
- \begin_layout LyX-Code
952
- #=> {:dog=>#<Dog:0x9c214ac>, :cat=>#<Cat:0x98efb80>}
953
- \end_layout
954
-
955
- \begin_layout LyX-Code
956
- h2[:dog]
957
- \end_layout
958
-
959
- \begin_layout LyX-Code
960
- #=> #<Dog:0x9c214ac>
961
- \end_layout
962
-
963
- \begin_layout Part*
964
- Code blocks and Closures
965
- \end_layout
966
-
967
- \begin_layout Standard
968
-
969
- \emph on
970
- \color red
971
- Code blocks
972
- \emph default
973
- \color inherit
974
- , or simply
975
- \emph on
976
- \color red
977
- blocks
978
- \emph default
979
- \color inherit
980
- , are pieces of code enclosed by
981
- \family typewriter
982
- \color red
983
- do
984
- \family default
985
- \color inherit
986
- /
987
- \family typewriter
988
- \color red
989
- end
990
- \family default
991
- \color inherit
992
- pair, or by curly brackets
993
- \family typewriter
994
- \color red
995
- {}
996
- \family default
997
- \color inherit
998
- .
999
- Code blocks can be passed to methods:
1000
- \end_layout
1001
-
1002
- \begin_layout LyX-Code
1003
- [1, 2, 3, 4].map
1004
- \color red
1005
- { |
1006
- \color inherit
1007
- n
1008
- \color red
1009
- |
1010
- \color inherit
1011
- n + 3
1012
- \color red
1013
- }
1014
- \end_layout
1015
-
1016
- \begin_layout LyX-Code
1017
- #=> [4, 5, 6, 7]
1018
- \end_layout
1019
-
1020
- \begin_layout LyX-Code
1021
- my_array.
1022
- \color red
1023
- each
1024
- \color inherit
1025
- do
1026
- \color red
1027
- |
1028
- \color inherit
1029
- member
1030
- \color red
1031
- |
1032
- \color inherit
1033
- member.speak! end
1034
- \end_layout
1035
-
1036
- \begin_layout LyX-Code
1037
- #=> Bow wow!
1038
- \end_layout
1039
-
1040
- \begin_layout LyX-Code
1041
- Meow
1042
- \end_layout
1043
-
1044
- \begin_layout Standard
1045
- In the first case, '
1046
- \family typewriter
1047
- map
1048
- \family default
1049
- ' method was passed a block specifying addition of 3.
1050
- In the second case, '
1051
- \family typewriter
1052
- each
1053
- \family default
1054
- ' method was passed a block calling
1055
- \family typewriter
1056
- speak!
1057
- \family default
1058
- method on the array elements.
1059
- Please note the pipe, or vertical line charecters (
1060
- \color red
1061
- |
1062
- \color inherit
1063
- ), that delimit the block arguments (both blocks above happen to have only
1064
- one argument).
1065
- Code blocks can be understood as anonymous functions – a way of specifying
1066
- an operation, when one does not want to write a method for it.
1067
- Their semantics corresponds to
1068
- \emph on
1069
- lambda calculus
1070
- \emph default
1071
- .
1072
- \end_layout
1073
-
1074
- \begin_layout Section*
1075
- Return values
1076
- \end_layout
1077
-
1078
- \begin_layout Standard
1079
- Code blocks (and actually, all Ruby statements) have return value.
1080
- With code blocks, the return value will typically be the last statement:
1081
- \end_layout
1082
-
1083
- \begin_layout LyX-Code
1084
- [1, 2, 3, 4].map { |v|
1085
- \end_layout
1086
-
1087
- \begin_layout LyX-Code
1088
- v + 3 # this value will be ignored
1089
- \end_layout
1090
-
1091
- \begin_layout LyX-Code
1092
- v - 1 # last value of the block will be returned
1093
- \end_layout
1094
-
1095
- \begin_layout LyX-Code
1096
- }
1097
- \end_layout
1098
-
1099
- \begin_layout LyX-Code
1100
- #=> [0, 1, 2, 3]
1101
- \end_layout
1102
-
1103
- \begin_layout Section*
1104
- Closures
1105
- \end_layout
1106
-
1107
- \begin_layout Standard
1108
- A block packaged for future use is called a
1109
- \emph on
1110
- \color red
1111
- closure
1112
- \emph default
1113
- \color inherit
1114
- .
1115
- Ruby closures come in two flavors:
1116
- \family typewriter
1117
- \color red
1118
- proc
1119
- \family default
1120
- \color inherit
1121
- and
1122
- \family typewriter
1123
- \color red
1124
- lambda
1125
- \family default
1126
- \color inherit
1127
- .
1128
- They are created by passing a block to the
1129
- \family typewriter
1130
- proc
1131
- \family default
1132
- /
1133
- \family typewriter
1134
- lambda
1135
- \family default
1136
- keyword:
1137
- \end_layout
1138
-
1139
- \begin_layout LyX-Code
1140
- my_proc =
1141
- \color red
1142
- proc
1143
- \color inherit
1144
- do |organism| organism.speak! end
1145
- \end_layout
1146
-
1147
- \begin_layout LyX-Code
1148
- #=> #<Proc:0x952674c@(irb):136>
1149
- \end_layout
1150
-
1151
- \begin_layout LyX-Code
1152
- my_lambda =
1153
- \color red
1154
- lambda
1155
- \color inherit
1156
- do |organism| organism.speak! end
1157
- \end_layout
1158
-
1159
- \begin_layout LyX-Code
1160
- #=> #<Proc:0x942faf0@(irb):137 (lambda)>
1161
- \end_layout
1162
-
1163
- \begin_layout Standard
1164
- Once defined, they can be reused in code.
1165
- Notice the ampersand (
1166
- \family typewriter
1167
- \color red
1168
- &
1169
- \family default
1170
- \color inherit
1171
- ) indicating block reuse:
1172
- \end_layout
1173
-
1174
- \begin_layout LyX-Code
1175
- my_array.each
1176
- \color red
1177
- &
1178
- \color inherit
1179
- my_proc
1180
- \end_layout
1181
-
1182
- \begin_layout LyX-Code
1183
- #=> Bow wow!
1184
- \end_layout
1185
-
1186
- \begin_layout LyX-Code
1187
- Meow
1188
- \end_layout
1189
-
1190
- \begin_layout LyX-Code
1191
- my_array.each &my_lambda
1192
- \end_layout
1193
-
1194
- \begin_layout LyX-Code
1195
- #=> Bow wow!
1196
- \end_layout
1197
-
1198
- \begin_layout LyX-Code
1199
- Meow
1200
- \end_layout
1201
-
1202
- \begin_layout Standard
1203
- Closures can also be called alone, a little bit like methods:
1204
- \end_layout
1205
-
1206
- \begin_layout LyX-Code
1207
- my_proc.
1208
- \color red
1209
- call
1210
- \color inherit
1211
- ( Spot )
1212
- \end_layout
1213
-
1214
- \begin_layout LyX-Code
1215
- #=> Bow wow!
1216
- \end_layout
1217
-
1218
- \begin_layout LyX-Code
1219
- my_lambda.call( Lisa )
1220
- \end_layout
1221
-
1222
- \begin_layout LyX-Code
1223
- #=> Meow
1224
- \end_layout
1225
-
1226
- \begin_layout Standard
1227
- Instead of
1228
- \family typewriter
1229
- call
1230
- \family default
1231
- keyword, you can just use dot before the parenthesis to call closures:
1232
- \end_layout
1233
-
1234
- \begin_layout LyX-Code
1235
- my_proc
1236
- \color red
1237
- .
1238
- \color inherit
1239
- ( Lisa )
1240
- \end_layout
1241
-
1242
- \begin_layout LyX-Code
1243
- #=> Meow
1244
- \end_layout
1245
-
1246
- \begin_layout LyX-Code
1247
- my_lambda.( Spot )
1248
- \end_layout
1249
-
1250
- \begin_layout LyX-Code
1251
- #=> Bow wow!
1252
- \end_layout
1253
-
1254
- \begin_layout Standard
1255
- Differences between
1256
- \family typewriter
1257
- proc
1258
- \family default
1259
- and
1260
- \family typewriter
1261
- lambda
1262
- \family default
1263
- closures are minor.
1264
- For
1265
- \family typewriter
1266
- YNelson
1267
- \family default
1268
- users, the most noticeable difference will be, that
1269
- \family typewriter
1270
- proc
1271
- \family default
1272
- less finicky about its arguments than
1273
- \family typewriter
1274
- lambda
1275
- \family default
1276
- :
1277
- \end_layout
1278
-
1279
- \begin_layout LyX-Code
1280
- my_proc.( Lisa, "garbage" )
1281
- \end_layout
1282
-
1283
- \begin_layout LyX-Code
1284
- #=> Meow
1285
- \end_layout
1286
-
1287
- \begin_layout LyX-Code
1288
- my_lambda.( Lisa, "garbage" )
1289
- \end_layout
1290
-
1291
- \begin_layout LyX-Code
1292
- #=> ArgumentError: wrong number of arguments (2 for 1)
1293
- \end_layout
1294
-
1295
- \begin_layout Standard
1296
- Finally, let us notice the alternative syntax for defining lambdas:
1297
- \end_layout
1298
-
1299
- \begin_layout LyX-Code
1300
- my_lambda = lambda do |organism| organism.speak! end
1301
- \end_layout
1302
-
1303
- \begin_layout LyX-Code
1304
- my_lambda = lambda { |organism| oranism.speak! }
1305
- \end_layout
1306
-
1307
- \begin_layout LyX-Code
1308
- my_lambda =
1309
- \color red
1310
- ->
1311
- \color inherit
1312
- organism do organism.speak! end
1313
- \end_layout
1314
-
1315
- \begin_layout LyX-Code
1316
- my_lambda = -> orgnism { organism.speak! }
1317
- \end_layout
1318
-
1319
- \begin_layout Standard
1320
- All of the four above statements define exactly the same thing.
1321
- \end_layout
1322
-
1323
- \begin_layout Section*
1324
- Passing arguments
1325
- \end_layout
1326
-
1327
- \begin_layout Standard
1328
- Earlier, we have defined method
1329
- \family typewriter
1330
- average
1331
- \family default
1332
- , expecting two arguments.
1333
- If wrong number of arguments is supplied,
1334
- \family typewriter
1335
- ArgumentError
1336
- \family default
1337
- will ensue:
1338
- \end_layout
1339
-
1340
- \begin_layout LyX-Code
1341
- average( 3, 5 )
1342
- \end_layout
1343
-
1344
- \begin_layout LyX-Code
1345
- #=> 4
1346
- \end_layout
1347
-
1348
- \begin_layout LyX-Code
1349
- average( 3, 5, 8 )
1350
- \end_layout
1351
-
1352
- \begin_layout LyX-Code
1353
- #=> ArgumentError: wrong number of arguments (3 for 2)
1354
- \end_layout
1355
-
1356
- \begin_layout Standard
1357
- Obviously, this is not a very nice behavior when it comes to averages.
1358
- It is a general situation, that when calling more advanced methods, we
1359
- need to modify their behavior, or pass more complicated structures to them.
1360
- This is seen eg.
1361
- with
1362
- \family typewriter
1363
- YNelson::Transition
1364
- \family default
1365
- constructors, and will be further encountered in
1366
- \family typewriter
1367
- YCell
1368
- \family default
1369
- and
1370
- \family typewriter
1371
- YChem
1372
- \family default
1373
- DSLs.
1374
- Furthermore,
1375
- \family typewriter
1376
- YNelson
1377
- \family default
1378
- users have to be able to write their own closures, because that is how
1379
-
1380
- \emph on
1381
- functions
1382
- \emph default
1383
- of
1384
- \emph on
1385
- functional transitions
1386
- \emph default
1387
- are specified.
1388
- In other words,
1389
- \family typewriter
1390
- \series bold
1391
- YNelson
1392
- \family default
1393
- users have to master argument passing from both user and programmer side
1394
- \series default
1395
- .
1396
- There is no way around this.
1397
- With functional Petri nets, one cannot avoid writing functions.
1398
- It is possible to avoid using
1399
- \family typewriter
1400
- YNelson
1401
- \family default
1402
- , but it is not possible to avoid learning to write functions.
1403
- Every simulator of functional Petri nets brings with itself some sort of
1404
- function language, which one has to learn.
1405
- With
1406
- \family typewriter
1407
- YNelson
1408
- \family default
1409
- , this is the language of Ruby closures.
1410
- \end_layout
1411
-
1412
- \begin_layout Section*
1413
- Optional arguments
1414
- \end_layout
1415
-
1416
- \begin_layout Standard
1417
- Arguments with prescribed default value are optional.
1418
- Let us write an improved
1419
- \family typewriter
1420
- average
1421
- \family default
1422
- method that can accept either 2 or 3 arguments:
1423
- \end_layout
1424
-
1425
- \begin_layout LyX-Code
1426
- def average( a, b, c
1427
- \color red
1428
- =
1429
- \color inherit
1430
- nil )
1431
- \end_layout
1432
-
1433
- \begin_layout LyX-Code
1434
-
1435
- \color red
1436
- #
1437
- \color inherit
1438
- If c argument was not given, it will default to nil
1439
- \end_layout
1440
-
1441
- \begin_layout LyX-Code
1442
-
1443
- \color red
1444
- if
1445
- \color inherit
1446
- c
1447
- \color red
1448
- ==
1449
- \color inherit
1450
- nil
1451
- \color red
1452
- then
1453
- \end_layout
1454
-
1455
- \begin_layout LyX-Code
1456
- ( a + b ).to_f / 2
1457
- \end_layout
1458
-
1459
- \begin_layout LyX-Code
1460
-
1461
- \color red
1462
- else
1463
- \end_layout
1464
-
1465
- \begin_layout LyX-Code
1466
- ( a + b + c ).to_f / 3
1467
- \end_layout
1468
-
1469
- \begin_layout LyX-Code
1470
-
1471
- \color red
1472
- end
1473
- \end_layout
1474
-
1475
- \begin_layout LyX-Code
1476
- end
1477
- \end_layout
1478
-
1479
- \begin_layout LyX-Code
1480
- #=> nil
1481
- \end_layout
1482
-
1483
- \begin_layout LyX-Code
1484
- average( 3, 5 )
1485
- \end_layout
1486
-
1487
- \begin_layout LyX-Code
1488
- #=> 4
1489
- \end_layout
1490
-
1491
- \begin_layout LyX-Code
1492
- average( 3, 5, 8 )
1493
- \end_layout
1494
-
1495
- \begin_layout LyX-Code
1496
- #=> 5.333333333333333
1497
- \end_layout
1498
-
1499
- \begin_layout LyX-Code
1500
- average( 1, 2, 3, 4 )
1501
- \end_layout
1502
-
1503
- \begin_layout LyX-Code
1504
- #=> ArgumentError: wrong number of arguments (4 for 3)
1505
- \end_layout
1506
-
1507
- \begin_layout Standard
1508
- The default value for
1509
- \family typewriter
1510
- c
1511
- \family default
1512
- argument is prescribed using single equals sign (
1513
- \family typewriter
1514
- \color red
1515
- =
1516
- \family default
1517
- \color inherit
1518
- ).
1519
- Apart from that, you can notice
1520
- \family typewriter
1521
- \color red
1522
- if
1523
- \family default
1524
- \color inherit
1525
- ...
1526
-
1527
- \family typewriter
1528
- \color red
1529
- then
1530
- \family default
1531
- \color inherit
1532
- ...
1533
-
1534
- \family typewriter
1535
- \color red
1536
- else
1537
- \family default
1538
- \color inherit
1539
- ...
1540
-
1541
- \family typewriter
1542
- \color red
1543
- end
1544
- \family default
1545
- \color inherit
1546
- statement, which needs no explanation, equality test (double equals sign,
1547
-
1548
- \family typewriter
1549
- \color red
1550
- ==
1551
- \family default
1552
- \color inherit
1553
- ), used to test whether
1554
- \family typewriter
1555
- c
1556
- \family default
1557
- contains
1558
- \family typewriter
1559
- :pochi
1560
- \family default
1561
- symbol (indicating missing value), and comment character (octothorpe aka.
1562
- sharp,
1563
- \family typewriter
1564
- \color red
1565
- #
1566
- \family default
1567
- \color inherit
1568
- ).
1569
- Comment character
1570
- \family typewriter
1571
- \color red
1572
- #
1573
- \family default
1574
- \color inherit
1575
- causes all characters until the end of the line to be ignored by Ruby.
1576
- All code lines, exception the obvious ones, should have comments.
1577
- \end_layout
1578
-
1579
- \begin_layout Section*
1580
- Variable-length argument lists
1581
- \end_layout
1582
-
1583
- \begin_layout Standard
1584
- We will now improve our
1585
- \family typewriter
1586
- average
1587
- \family default
1588
- method, so that it can calculate averages of any number of arguments.
1589
- For this, we will use asterisk (
1590
- \family typewriter
1591
- \color red
1592
- *
1593
- \family default
1594
- \color inherit
1595
- ) syntactic modifier, also known as
1596
- \emph on
1597
- splash
1598
- \emph default
1599
- .
1600
- The asterisk will cause a method to collect the arguments into an array.
1601
- Let's try it out first:
1602
- \end_layout
1603
-
1604
- \begin_layout LyX-Code
1605
- def examine_arguments( x,
1606
- \color red
1607
- *
1608
- \color inherit
1609
- aa )
1610
- \end_layout
1611
-
1612
- \begin_layout LyX-Code
1613
- puts "x is a
1614
- \color red
1615
- #{
1616
- \color inherit
1617
- x.class
1618
- \color red
1619
- }
1620
- \color inherit
1621
- ."
1622
- \end_layout
1623
-
1624
- \begin_layout LyX-Code
1625
- puts "aa is #{aa.class} of #{aa.size} elements."
1626
- \end_layout
1627
-
1628
- \begin_layout LyX-Code
1629
- end
1630
- \end_layout
1631
-
1632
- \begin_layout LyX-Code
1633
- #=> nil
1634
- \end_layout
1635
-
1636
- \begin_layout Standard
1637
- Method examine arguments takes one normal argument (
1638
- \family typewriter
1639
- x
1640
- \family default
1641
- ), and collects the rest of the arguments into an array (
1642
- \family typewriter
1643
- aa
1644
- \family default
1645
- ), thanks to the splash modifier.
1646
- (Apart from that, you can notice string interpolation using
1647
- \family typewriter
1648
- #{ ...
1649
- }
1650
- \family default
1651
- notation in the above code.) Then it prints the class of
1652
- \family typewriter
1653
- x
1654
- \family default
1655
- , class of
1656
- \family typewriter
1657
- aa
1658
- \family default
1659
- (which should be an array), and the number of elements after
1660
- \family typewriter
1661
- x
1662
- \family default
1663
- .
1664
- \end_layout
1665
-
1666
- \begin_layout LyX-Code
1667
- examine_arguments( 1 )
1668
- \end_layout
1669
-
1670
- \begin_layout LyX-Code
1671
- #=> x is a Fixnum.
1672
- \end_layout
1673
-
1674
- \begin_layout LyX-Code
1675
- aa is Array of 0 elements.
1676
- \end_layout
1677
-
1678
- \begin_layout LyX-Code
1679
- nil
1680
- \end_layout
1681
-
1682
- \begin_layout LyX-Code
1683
- examine_arguments( :hello, nil, 3, 5, "garbage" )
1684
- \end_layout
1685
-
1686
- \begin_layout LyX-Code
1687
- #=> x is a Symbol.
1688
- \end_layout
1689
-
1690
- \begin_layout LyX-Code
1691
- aa is Array of 4 elements.
1692
- \end_layout
1693
-
1694
- \begin_layout LyX-Code
1695
- nil
1696
- \end_layout
1697
-
1698
- \begin_layout Standard
1699
- With this, we can go on to define our improved average method:
1700
- \end_layout
1701
-
1702
- \begin_layout LyX-Code
1703
- def average( *aa )
1704
- \end_layout
1705
-
1706
- \begin_layout LyX-Code
1707
- aa.
1708
- \color red
1709
- reduce( :+ )
1710
- \color inherit
1711
- .to_f / aa.size
1712
- \end_layout
1713
-
1714
- \begin_layout LyX-Code
1715
- end
1716
- \end_layout
1717
-
1718
- \begin_layout LyX-Code
1719
- #=> nil
1720
- \end_layout
1721
-
1722
- \begin_layout LyX-Code
1723
- average 3, 5, 7, 11
1724
- \end_layout
1725
-
1726
- \begin_layout LyX-Code
1727
- #=> 6.5
1728
- \end_layout
1729
-
1730
- \begin_layout Standard
1731
- You can also newly notice
1732
- \family typewriter
1733
- reduce( :+ )
1734
- \family default
1735
- method, used to calculate the sum of the
1736
- \family typewriter
1737
- aa
1738
- \family default
1739
- array.
1740
- To also practice closures, let us define a lambda doing the same as the
1741
-
1742
- \family typewriter
1743
- average
1744
- \family default
1745
- method above:
1746
- \end_layout
1747
-
1748
- \begin_layout LyX-Code
1749
- avg = lambda { |*aa| aa.reduce( :+ ).to_f / aa.size }
1750
- \end_layout
1751
-
1752
- \begin_layout LyX-Code
1753
- #=> #<Proc:0x9dbd220@(irb):208 (lambda)>
1754
- \end_layout
1755
-
1756
- \begin_layout LyX-Code
1757
- avg.( 11, 7, 5, 3 )
1758
- \end_layout
1759
-
1760
- \begin_layout LyX-Code
1761
- #=> 6.5
1762
- \end_layout
1763
-
1764
- \begin_layout Section*
1765
- Named arguments
1766
- \end_layout
1767
-
1768
- \begin_layout Standard
1769
- The main purpose of named arguments is to make the interface (or DSL) easier
1770
- to remember, and the code easier to read.
1771
- Easy-to-read code is a crucial requirement for scalable development.
1772
- In Ruby methods, named arguments can be specified
1773
- \color red
1774
- as hash pairs in the method call
1775
- \color inherit
1776
- :
1777
- \end_layout
1778
-
1779
- \begin_layout LyX-Code
1780
- def density( x: 1, y: 1, z: 1, weight: 1 )
1781
- \end_layout
1782
-
1783
- \begin_layout LyX-Code
1784
- weight.to_f / ( x * y * z )
1785
- \end_layout
1786
-
1787
- \begin_layout LyX-Code
1788
- end
1789
- \end_layout
1790
-
1791
- \begin_layout LyX-Code
1792
- #=> nil
1793
- \end_layout
1794
-
1795
- \begin_layout LyX-Code
1796
- density( x: 2, y: 2, z: 2, weight: 10 )
1797
- \end_layout
1798
-
1799
- \begin_layout LyX-Code
1800
- #=> 1.25
1801
- \end_layout
1802
-
1803
- \begin_layout Standard
1804
- The above method calculates mean density of boxes of certain height, width,
1805
- length and weight.
1806
- Double splash (
1807
- \family typewriter
1808
- \color red
1809
- **
1810
- \family default
1811
- \color inherit
1812
- ) can be used to collect all the options in a hash.
1813
- Let's use it to define a closure that does exactly the same thing as the
1814
- method
1815
- \family typewriter
1816
- density
1817
- \family default
1818
- we have just defined, in a slightly different way:
1819
- \end_layout
1820
-
1821
- \begin_layout LyX-Code
1822
- dens_closure =
1823
- \color red
1824
- ->
1825
- \color inherit
1826
- **nn do
1827
- \end_layout
1828
-
1829
- \begin_layout LyX-Code
1830
- nn[:weight].to_f / ( nn[:x] * nn[:y] * nn[:z] ) end
1831
- \end_layout
1832
-
1833
- \begin_layout LyX-Code
1834
- #=> #<Proc:0x9a5d60c@(irb):241 (lambda)>
1835
- \end_layout
1836
-
1837
- \begin_layout LyX-Code
1838
- dens_closure.( x: 2, y: 2, z: 2, weight: 10 )
1839
- \end_layout
1840
-
1841
- \begin_layout LyX-Code
1842
- #=> 1.25
1843
- \end_layout
1844
-
1845
- \begin_layout Standard
1846
- Above, note the alternative syntax for lambdas:
1847
- \family typewriter
1848
- -> arg do ...
1849
- end
1850
- \family default
1851
- is the same as
1852
- \family typewriter
1853
- lambda do |arg| ...
1854
- end
1855
- \family default
1856
- .
1857
- Having hereby introduced the named arguments, let us notice hash-collecting
1858
- behavior for square bracket (
1859
- \family typewriter
1860
- []
1861
- \family default
1862
- ) array constructor syntax.
1863
- \end_layout
1864
-
1865
- \begin_layout Section*
1866
- Hash-collecting behavior of square brackets
1867
- \end_layout
1868
-
1869
- \begin_layout Standard
1870
- In more complicated method argument structures, it can be advantageous to
1871
- take use of the hash-collecting by square brackets.
1872
- It is normal for curly braces to create hashes:
1873
- \end_layout
1874
-
1875
- \begin_layout LyX-Code
1876
- h = { x: 2, y: 3, z: 4 }
1877
- \end_layout
1878
-
1879
- \begin_layout LyX-Code
1880
- #=> {:x=>2, :y=>3, :z=>4}
1881
- \end_layout
1882
-
1883
- \begin_layout LyX-Code
1884
- h.class
1885
- \end_layout
1886
-
1887
- \begin_layout LyX-Code
1888
- #=> Hash
1889
- \end_layout
1890
-
1891
- \begin_layout Standard
1892
- However, square brackets, that generally create arrays, are also
1893
- \color red
1894
- able to collect hashes just like the argument fields with named arguments
1895
- \color inherit
1896
- :
1897
- \end_layout
1898
-
1899
- \begin_layout LyX-Code
1900
- a0 = [ 1, 2, 3 ]
1901
- \end_layout
1902
-
1903
- \begin_layout LyX-Code
1904
- #=> [1, 2, 3]
1905
- \end_layout
1906
-
1907
- \begin_layout LyX-Code
1908
- a0.class
1909
- \end_layout
1910
-
1911
- \begin_layout LyX-Code
1912
- #=> Array
1913
- \end_layout
1914
-
1915
- \begin_layout LyX-Code
1916
- a1 = [ 1, 2, 3, x: 2, y: 3, z: 4 ]
1917
- \end_layout
1918
-
1919
- \begin_layout LyX-Code
1920
- #=> [1, 2, 3, {:x=>2, :y=>3, :z=>4}]
1921
- \end_layout
1922
-
1923
- \begin_layout LyX-Code
1924
- a1.class
1925
- \end_layout
1926
-
1927
- \begin_layout LyX-Code
1928
- #=> Array
1929
- \end_layout
1930
-
1931
- \begin_layout LyX-Code
1932
- a1.map &:class
1933
- \end_layout
1934
-
1935
- \begin_layout LyX-Code
1936
- #=> [Fixnum, Fixnum, Fixnum, Hash]
1937
- \end_layout
1938
-
1939
- \begin_layout LyX-Code
1940
- a1[-1]
1941
- \end_layout
1942
-
1943
- \begin_layout LyX-Code
1944
- #=> {:x=>2, :y=>3, :z=>4}
1945
- \end_layout
1946
-
1947
- \begin_layout Standard
1948
- In other words, if there are any trailing
1949
- \family typewriter
1950
- key/value
1951
- \family default
1952
- pairs inside square brackets, they will be collected into a hash, which
1953
- will become the last element of the array.
1954
- This possibility to mix ordered elements with
1955
- \family typewriter
1956
- key/value
1957
- \family default
1958
- pairs is used eg.
1959
- in
1960
- \family typewriter
1961
- YCell
1962
- \family default
1963
-
1964
- \family typewriter
1965
- enzyme
1966
- \family default
1967
- constructor method.
1968
- \end_layout
1969
-
1970
- \begin_layout Section*
1971
- Arity
1972
- \end_layout
1973
-
1974
- \begin_layout Standard
1975
- Every closure and every method has arity, which is basically the number
1976
- of input arguments.
1977
- (Closures with 0 arguments are null
1978
- \emph on
1979
- ary
1980
- \emph default
1981
- , with 1 argument un
1982
- \emph on
1983
- ary
1984
- \emph default
1985
- , with 2 arguments bin
1986
- \emph on
1987
- ary
1988
- \emph default
1989
- , with 3 arguments tern
1990
- \emph on
1991
- ary
1992
- \emph default
1993
- etc.
1994
- – therefrom
1995
- \emph on
1996
- arity
1997
- \emph default
1998
- .)
1999
- \end_layout
2000
-
2001
- \begin_layout LyX-Code
2002
- doubler = lambda { |a| a * 2 }
2003
- \end_layout
2004
-
2005
- \begin_layout LyX-Code
2006
- #=> #<Proc:0xa19b5b8@(irb):1 (lambda)>
2007
- \end_layout
2008
-
2009
- \begin_layout LyX-Code
2010
- doubler.call( 3 )
2011
- \end_layout
2012
-
2013
- \begin_layout LyX-Code
2014
- #=> 6
2015
- \end_layout
2016
-
2017
- \begin_layout LyX-Code
2018
- doubler.arity
2019
- \end_layout
2020
-
2021
- \begin_layout LyX-Code
2022
- #=> 1
2023
- \end_layout
2024
-
2025
- \begin_layout LyX-Code
2026
- adder = -> p, q { p + q }
2027
- \end_layout
2028
-
2029
- \begin_layout LyX-Code
2030
- #=> #<Proc:0xa27d940@(irb):6 (lambda)>
2031
- \end_layout
2032
-
2033
- \begin_layout LyX-Code
2034
- adder.call( 5, 6 )
2035
- \end_layout
2036
-
2037
- \begin_layout LyX-Code
2038
- #=> 11
2039
- \end_layout
2040
-
2041
- \begin_layout LyX-Code
2042
- adder.arity
2043
- \end_layout
2044
-
2045
- \begin_layout LyX-Code
2046
- #=> 2
2047
- \end_layout
2048
-
2049
- \begin_layout LyX-Code
2050
- scaler = -> number, p, q { number * ( q.to_f / p ) }
2051
- \end_layout
2052
-
2053
- \begin_layout LyX-Code
2054
- #=> #<Proc:0xa2825e4@(irb):7 (lambda)>
2055
- \end_layout
2056
-
2057
- \begin_layout LyX-Code
2058
- scaler.call( 10, 2, 3 )
2059
- \end_layout
2060
-
2061
- \begin_layout LyX-Code
2062
- #=> 15.0
2063
- \end_layout
2064
-
2065
- \begin_layout LyX-Code
2066
- scaler.arity
2067
- \end_layout
2068
-
2069
- \begin_layout LyX-Code
2070
- #=> 3
2071
- \end_layout
2072
-
2073
- \begin_layout LyX-Code
2074
- constant_function = -> { 42 }
2075
- \end_layout
2076
-
2077
- \begin_layout LyX-Code
2078
- #=> #<Proc:0xa2825e4@(irb):7 (lambda)>
2079
- \end_layout
2080
-
2081
- \begin_layout LyX-Code
2082
- constant_function.call
2083
- \end_layout
2084
-
2085
- \begin_layout LyX-Code
2086
- #=> 42
2087
- \end_layout
2088
-
2089
- \begin_layout LyX-Code
2090
- constant_function.arity
2091
- \end_layout
2092
-
2093
- \begin_layout LyX-Code
2094
- #=> 0
2095
- \end_layout
2096
-
2097
- \begin_layout Standard
2098
- Closures / methods with variable length arguments indicate this by reporting
2099
- negative arity:
2100
- \end_layout
2101
-
2102
- \begin_layout LyX-Code
2103
- summation = -> *array { array.reduce( :+ ) }
2104
- \end_layout
2105
-
2106
- \begin_layout LyX-Code
2107
- #=> #<Proc:0xa296ddc@(irb):9 (lambda)>
2108
- \end_layout
2109
-
2110
- \begin_layout LyX-Code
2111
- summation.call( 1, 2, 3, 4 )
2112
- \end_layout
2113
-
2114
- \begin_layout LyX-Code
2115
- #=> 10
2116
- \end_layout
2117
-
2118
- \begin_layout LyX-Code
2119
- summation.arity
2120
- \end_layout
2121
-
2122
- \begin_layout LyX-Code
2123
- #=> -1
2124
- \end_layout
2125
-
2126
- \begin_layout LyX-Code
2127
- array_scale = -> *a, coeff { a.map { |e| e * coeff } }
2128
- \end_layout
2129
-
2130
- \begin_layout LyX-Code
2131
- #=> #<Proc:0xa2a9edc@(irb):12 (lambda)>
2132
- \end_layout
2133
-
2134
- \begin_layout LyX-Code
2135
- array_scale.call( 1, 2, 3, 4, 7 )
2136
- \end_layout
2137
-
2138
- \begin_layout LyX-Code
2139
- #=> [7, 14, 21, 28]
2140
- \end_layout
2141
-
2142
- \begin_layout LyX-Code
2143
- array_scale.arity
2144
- \end_layout
2145
-
2146
- \begin_layout LyX-Code
2147
- #=> -2
2148
- \end_layout
2149
-
2150
- \begin_layout Section*
2151
- Return value
2152
- \end_layout
2153
-
2154
- \begin_layout Standard
2155
- The last statement in a closure or method becomes the return value.
2156
- In methods and lambda-type closures, return statement can also be used
2157
- explicitly:
2158
- \end_layout
2159
-
2160
- \begin_layout LyX-Code
2161
- divider = -> u, v {
2162
- \end_layout
2163
-
2164
- \begin_layout LyX-Code
2165
- if v == 0 then
2166
- \end_layout
2167
-
2168
- \begin_layout LyX-Code
2169
- return :division_by_zero # explicit return
2170
- \end_layout
2171
-
2172
- \begin_layout LyX-Code
2173
- end
2174
- \end_layout
2175
-
2176
- \begin_layout LyX-Code
2177
- u.to_f / v # implicit return - last statement
2178
- \end_layout
2179
-
2180
- \begin_layout LyX-Code
2181
- }
2182
- \end_layout
2183
-
2184
- \begin_layout LyX-Code
2185
- #=> #<Proc:0xa21e878@(irb):15 (lambda)>
2186
- \end_layout
2187
-
2188
- \begin_layout LyX-Code
2189
- divider.call( 15, 3 )
2190
- \end_layout
2191
-
2192
- \begin_layout LyX-Code
2193
- #=> 5.0
2194
- \end_layout
2195
-
2196
- \begin_layout LyX-Code
2197
- divider.call( 15, 0 )
2198
- \end_layout
2199
-
2200
- \begin_layout LyX-Code
2201
- #=> :division_by_zero
2202
- \end_layout
2203
-
2204
- \begin_layout LyX-Code
2205
- experimental_closure = proc {
2206
- \end_layout
2207
-
2208
- \begin_layout LyX-Code
2209
- 42 # ignored
2210
- \end_layout
2211
-
2212
- \begin_layout LyX-Code
2213
- 41 # returned
2214
- \end_layout
2215
-
2216
- \begin_layout LyX-Code
2217
- }
2218
- \end_layout
2219
-
2220
- \begin_layout LyX-Code
2221
- #=> #<Proc:0xa249460@(irb):28>
2222
- \end_layout
2223
-
2224
- \begin_layout LyX-Code
2225
- experimental_closure.call
2226
- \end_layout
2227
-
2228
- \begin_layout LyX-Code
2229
- #=> 41
2230
- \end_layout
2231
-
2232
- \begin_layout LyX-Code
2233
- experimental_lambda = lambda {
2234
- \end_layout
2235
-
2236
- \begin_layout LyX-Code
2237
- 1 # ignored
2238
- \end_layout
2239
-
2240
- \begin_layout LyX-Code
2241
- return 3 # returned
2242
- \end_layout
2243
-
2244
- \begin_layout LyX-Code
2245
- 7 # never executed
2246
- \end_layout
2247
-
2248
- \begin_layout LyX-Code
2249
- }
2250
- \end_layout
2251
-
2252
- \begin_layout LyX-Code
2253
- #=> #<Proc:0xa3200dc@(irb):38 (lambda)>
2254
- \end_layout
2255
-
2256
- \begin_layout LyX-Code
2257
- experimental_lambda.call
2258
- \end_layout
2259
-
2260
- \begin_layout LyX-Code
2261
- #=> 3
2262
- \end_layout
2263
-
2264
- \begin_layout Section*
2265
- Return value arity
2266
- \end_layout
2267
-
2268
- \begin_layout Standard
2269
- It is possible to return more than one value
2270
- \begin_inset Foot
2271
- status open
2272
-
2273
- \begin_layout Plain Layout
2274
- Technically, methods and closures always return exactly 1 object – multiple
2275
- values are returned via a single array object.
2276
- But pragmatically, and especially with respect to
2277
- \family typewriter
2278
- YPetri
2279
- \family default
2280
- , the notion of return value arity is useful.
2281
- \end_layout
2282
-
2283
- \end_inset
2284
-
2285
- .
2286
- For example:
2287
- \end_layout
2288
-
2289
- \begin_layout LyX-Code
2290
- mult_table = -> number {
2291
- \end_layout
2292
-
2293
- \begin_layout LyX-Code
2294
- [1, 2, 3, 4, 5].map { |e| e * number }
2295
- \end_layout
2296
-
2297
- \begin_layout LyX-Code
2298
- }
2299
- \end_layout
2300
-
2301
- \begin_layout LyX-Code
2302
- #=> #<Proc:0xa36a0d8@(irb):55 (lambda)>
2303
- \end_layout
2304
-
2305
- \begin_layout Standard
2306
- This closure returns 5 values.
2307
- We can receive them by using a simultaneous assignment statement:
2308
- \end_layout
2309
-
2310
- \begin_layout LyX-Code
2311
- by_one, by_two, by_three, by_four, by_five = mult_table.call( 7 )
2312
- \end_layout
2313
-
2314
- \begin_layout LyX-Code
2315
- #=> [7, 14, 21, 28, 35]
2316
- \end_layout
2317
-
2318
- \begin_layout LyX-Code
2319
- by_one
2320
- \end_layout
2321
-
2322
- \begin_layout LyX-Code
2323
- #=> 7
2324
- \end_layout
2325
-
2326
- \begin_layout LyX-Code
2327
- by_two
2328
- \end_layout
2329
-
2330
- \begin_layout LyX-Code
2331
- #=> 14
2332
- \end_layout
2333
-
2334
- \begin_layout LyX-Code
2335
- by_five
2336
- \end_layout
2337
-
2338
- \begin_layout LyX-Code
2339
- #=> 35
2340
- \end_layout
2341
-
2342
- \begin_layout Standard
2343
- Or we can simply collect them in an array:
2344
- \end_layout
2345
-
2346
- \begin_layout LyX-Code
2347
- collection = mult_table.( 3 )
2348
- \end_layout
2349
-
2350
- \begin_layout LyX-Code
2351
- #=> [3, 6, 9, 12, 15]
2352
- \end_layout
2353
-
2354
- \begin_layout Standard
2355
- In
2356
- \family typewriter
2357
- YNelson
2358
- \family default
2359
- , it sometimes becomes necessary to write closures with higher return arity
2360
- (returning more than one value).
2361
- This is normally done by returning an array.
2362
- Also, lambda return statement can be used to return multiple values:
2363
- \end_layout
2364
-
2365
- \begin_layout LyX-Code
2366
- constant_vector = -> { return 1, 2, 3 }
2367
- \end_layout
2368
-
2369
- \begin_layout LyX-Code
2370
- #=> #<Proc:0xa3cb338@(irb):72 (lambda)>
2371
- \end_layout
2372
-
2373
- \begin_layout LyX-Code
2374
- x, y, z = constant_vector.call
2375
- \end_layout
2376
-
2377
- \begin_layout LyX-Code
2378
- #=> [1, 2, 3]
2379
- \end_layout
2380
-
2381
- \begin_layout LyX-Code
2382
- x
2383
- \end_layout
2384
-
2385
- \begin_layout LyX-Code
2386
- #=> 1
2387
- \end_layout
2388
-
2389
- \begin_layout LyX-Code
2390
- y
2391
- \end_layout
2392
-
2393
- \begin_layout LyX-Code
2394
- #=> 2
2395
- \end_layout
2396
-
2397
- \begin_layout LyX-Code
2398
- z
2399
- \end_layout
2400
-
2401
- \begin_layout LyX-Code
2402
- #=> 3
2403
- \end_layout
2404
-
2405
- \begin_layout Part*
2406
-
2407
- \family typewriter
2408
- YSupport
2409
- \family default
2410
- library
2411
- \end_layout
2412
-
2413
- \begin_layout Standard
2414
- Finally, having introduced the basic Ruby syntax, let us mention
2415
- \family typewriter
2416
- YSupport
2417
- \family default
2418
- gem (gem = published Ruby library), that collects the assets (modules,
2419
- classes, methods...) of general concern in use by
2420
- \family typewriter
2421
- YPetri
2422
- \family default
2423
- /
2424
- \family typewriter
2425
- YNelson
2426
- \family default
2427
- .
2428
- Of these, a particular mention goes to
2429
- \family typewriter
2430
- NameMagic
2431
- \family default
2432
- , widely used in
2433
- \family typewriter
2434
- YPetri
2435
- \family default
2436
- ,
2437
- \family typewriter
2438
- YNelson
2439
- \family default
2440
- and
2441
- \family typewriter
2442
- SY
2443
- \family default
2444
- (physical units) libraries.
2445
- \end_layout
2446
-
2447
- \begin_layout Section*
2448
-
2449
- \family typewriter
2450
- NameMagic
2451
- \end_layout
2452
-
2453
- \begin_layout Standard
2454
- In software engineering,
2455
- \emph on
2456
- magic
2457
- \emph default
2458
- is a technical term for irregular side effects of language expressions.
2459
- The problem that
2460
- \family typewriter
2461
- NameMagic
2462
- \family default
2463
- solves is, that objects (such as chemical species encoded in
2464
- \family typewriter
2465
- YNelson
2466
- \family default
2467
- ) are frequently named, and naming them is an annoying chore.
2468
- Consider a simple case:
2469
- \end_layout
2470
-
2471
- \begin_layout LyX-Code
2472
- class Student
2473
- \end_layout
2474
-
2475
- \begin_layout LyX-Code
2476
- attr_accessor :name
2477
- \end_layout
2478
-
2479
- \begin_layout LyX-Code
2480
- def initialize name: nil
2481
- \end_layout
2482
-
2483
- \begin_layout LyX-Code
2484
- @name = name
2485
- \end_layout
2486
-
2487
- \begin_layout LyX-Code
2488
- end
2489
- \end_layout
2490
-
2491
- \begin_layout LyX-Code
2492
- end
2493
- \end_layout
2494
-
2495
- \begin_layout Standard
2496
- Now, to create named
2497
- \family typewriter
2498
- Student
2499
- \family default
2500
- instances, one has to mention
2501
- \family typewriter
2502
- :name
2503
- \family default
2504
- named argument in the constructor, and frequently, the same name has to
2505
- be mentioned twice, such as when assigning to constants or variables:
2506
- \end_layout
2507
-
2508
- \begin_layout LyX-Code
2509
- richard = Student.new( name: "Richard" )
2510
- \end_layout
2511
-
2512
- \begin_layout LyX-Code
2513
- richard.name
2514
- \end_layout
2515
-
2516
- \begin_layout LyX-Code
2517
- #=> "Richard"
2518
- \end_layout
2519
-
2520
- \begin_layout Standard
2521
- In Ruby, we can notice that some objects have built-in capability to be
2522
- named simply by constant assignment:
2523
- \end_layout
2524
-
2525
- \begin_layout LyX-Code
2526
- foo = Class.new
2527
- \end_layout
2528
-
2529
- \begin_layout LyX-Code
2530
- foo.name
2531
- \end_layout
2532
-
2533
- \begin_layout LyX-Code
2534
- #=> nil
2535
- \end_layout
2536
-
2537
- \begin_layout LyX-Code
2538
- Car = foo
2539
- \end_layout
2540
-
2541
- \begin_layout LyX-Code
2542
- foo.name
2543
- \end_layout
2544
-
2545
- \begin_layout LyX-Code
2546
- #=> "Car"
2547
- \end_layout
2548
-
2549
- \begin_layout Standard
2550
- Magically, upon assigning
2551
- \family typewriter
2552
- Car = foo
2553
- \family default
2554
- , the object referred to by the
2555
- \family typewriter
2556
- foo
2557
- \family default
2558
- variable received an attribute
2559
- \family typewriter
2560
- name
2561
- \family default
2562
- , with value set to "
2563
- \family typewriter
2564
- Car
2565
- \family default
2566
- ".
2567
- This standard behavior is termed
2568
- \emph on
2569
- constant magic
2570
- \emph default
2571
- .
2572
-
2573
- \family typewriter
2574
- NameMagic
2575
- \family default
2576
- mixin (part of
2577
- \family typewriter
2578
- YSupport
2579
- \family default
2580
- ) extends this standard behavior to any chosen object, and also takes care
2581
- of keeping the instance registry and doing general naming related chores
2582
- for its includers:
2583
- \end_layout
2584
-
2585
- \begin_layout LyX-Code
2586
- require 'y_support/name_magic'
2587
- \end_layout
2588
-
2589
- \begin_layout LyX-Code
2590
-
2591
- \end_layout
2592
-
2593
- \begin_layout LyX-Code
2594
- class Chemical
2595
- \end_layout
2596
-
2597
- \begin_layout LyX-Code
2598
- include NameMagic
2599
- \end_layout
2600
-
2601
- \begin_layout LyX-Code
2602
- end
2603
- \end_layout
2604
-
2605
- \begin_layout LyX-Code
2606
-
2607
- \end_layout
2608
-
2609
- \begin_layout LyX-Code
2610
- NaCl = Chemical.new
2611
- \end_layout
2612
-
2613
- \begin_layout LyX-Code
2614
- NaCl.name
2615
- \end_layout
2616
-
2617
- \begin_layout LyX-Code
2618
- #=> "NaCl"
2619
- \end_layout
2620
-
2621
- \begin_layout Standard
2622
- It might seem like a small thing, but in a big file full of complicated
2623
- statements, it really matters whether you have to write each time "
2624
- \family typewriter
2625
- NaCl = Chemical.new( name: NaCl )
2626
- \family default
2627
- ", or just "
2628
- \family typewriter
2629
- NaCl = Chemical.new
2630
- \family default
2631
- ".
2632
-
2633
- \family typewriter
2634
- NameMagic
2635
- \family default
2636
- is a part of
2637
- \family typewriter
2638
- YSupport
2639
- \family default
2640
- library accompanying
2641
- \family typewriter
2642
- YPetri
2643
- \family default
2644
- and
2645
- \family typewriter
2646
- YNelson
2647
- \family default
2648
- .
2649
- You can install
2650
- \family typewriter
2651
- YSupport
2652
- \family default
2653
- from the command line by "
2654
- \family typewriter
2655
- gem install y_support
2656
- \family default
2657
- ".
2658
- \end_layout
2659
-
2660
- \begin_layout Part*
2661
- Other essential concepts
2662
- \end_layout
2663
-
2664
- \begin_layout Standard
2665
- There are a few more essential concepts of Ruby that
2666
- \family typewriter
2667
- YNelson
2668
- \family default
2669
- users should be familiar with, such as namespaces and parametrized subclassing.
2670
- Code examples in this section are slightly more complicated, and also,
2671
- they make use of
2672
- \family typewriter
2673
- YSupport
2674
- \family default
2675
- gem.
2676
- Install
2677
- \family typewriter
2678
- YSupport
2679
- \family default
2680
- by typing
2681
- \family typewriter
2682
- gem install y_support
2683
- \family default
2684
- in your command line before studying code examples in this section.
2685
- \end_layout
2686
-
2687
- \begin_layout Section*
2688
- Namespaces
2689
- \end_layout
2690
-
2691
- \begin_layout Standard
2692
- In Ruby, namespaces are known as modules (objects of
2693
- \family typewriter
2694
- Module
2695
- \family default
2696
- class).
2697
- These objects are containers for constants and method definitions.
2698
- For example, let us imagine that we want to define constants, classes and
2699
- methods related to the game of chess.
2700
- We could simply define them in the command line, without any considerations,
2701
- We could do it directly, but that way, all of them would be defined in
2702
- the root of Ruby namespace – on
2703
- \family typewriter
2704
- Object
2705
- \family default
2706
- class.
2707
- The reason why this is not a good idea is the same as the reason why it
2708
- is not a good idea to put all your files in the root of your filesystem.
2709
- Chess-related terms such as
2710
- \family typewriter
2711
- Field
2712
- \family default
2713
- or
2714
- \family typewriter
2715
- Piece
2716
- \family default
2717
- could collide with concepts from other domains not related to chess.
2718
- For that reason, we will collect all the chess-related assets into a single
2719
- namespace:
2720
- \end_layout
2721
-
2722
- \begin_layout LyX-Code
2723
- module Chess
2724
- \end_layout
2725
-
2726
- \begin_layout LyX-Code
2727
- class Board < Array
2728
- \end_layout
2729
-
2730
- \begin_layout LyX-Code
2731
- SIZE = 8 # standard chessboard
2732
- \end_layout
2733
-
2734
- \begin_layout LyX-Code
2735
-
2736
- \end_layout
2737
-
2738
- \begin_layout LyX-Code
2739
- class Field # chessboard field
2740
- \end_layout
2741
-
2742
- \begin_layout LyX-Code
2743
- attr_accessor :contents
2744
- \end_layout
2745
-
2746
- \begin_layout LyX-Code
2747
- end
2748
- \end_layout
2749
-
2750
- \begin_layout LyX-Code
2751
-
2752
- \end_layout
2753
-
2754
- \begin_layout LyX-Code
2755
- def self.new # constructs 8 × 8 array of arrays
2756
- \end_layout
2757
-
2758
- \begin_layout LyX-Code
2759
- super( SIZE, Array.new( SIZE ) { Field.new } )
2760
- \end_layout
2761
-
2762
- \begin_layout LyX-Code
2763
- end
2764
- \end_layout
2765
-
2766
- \begin_layout LyX-Code
2767
- # chessboard is defined here
2768
- \end_layout
2769
-
2770
- \begin_layout LyX-Code
2771
- end
2772
- \end_layout
2773
-
2774
- \begin_layout LyX-Code
2775
-
2776
- \end_layout
2777
-
2778
- \begin_layout LyX-Code
2779
- Piece = Class.new # chess piece
2780
- \end_layout
2781
-
2782
- \begin_layout LyX-Code
2783
- Pawn = Class.new Piece # chess pawn
2784
- \end_layout
2785
-
2786
- \begin_layout LyX-Code
2787
- Knight = Class.new Piece # chess knight
2788
- \end_layout
2789
-
2790
- \begin_layout LyX-Code
2791
- Rook = Class.new Piece # chess rook
2792
- \end_layout
2793
-
2794
- \begin_layout LyX-Code
2795
- # etc.
2796
- \end_layout
2797
-
2798
- \begin_layout LyX-Code
2799
- end
2800
- \end_layout
2801
-
2802
- \begin_layout Standard
2803
- We then access the contents of the namespace in the way similar to the way
2804
- we address the files in the filesystem:
2805
- \end_layout
2806
-
2807
- \begin_layout LyX-Code
2808
- Chess::Board # namespace Chess, constant Board
2809
- \end_layout
2810
-
2811
- \begin_layout LyX-Code
2812
- Chess::Piece # namespace Chess, constant Piece
2813
- \end_layout
2814
-
2815
- \begin_layout LyX-Code
2816
- Chess::Pawn # namespace Chess, constant Pawn
2817
- \end_layout
2818
-
2819
- \begin_layout LyX-Code
2820
- Chess::Board::SIZE # namespace Chess::Board, constant SIZE
2821
- \end_layout
2822
-
2823
- \begin_layout LyX-Code
2824
- Chess::Board::Field # namespace Chess::Board, constant Field
2825
- \end_layout
2826
-
2827
- \begin_layout LyX-Code
2828
- # etc.
2829
- \end_layout
2830
-
2831
- \begin_layout Standard
2832
- Let us note that in the above example,
2833
- \family typewriter
2834
- Board
2835
- \family default
2836
- ,
2837
- \family typewriter
2838
- Piece
2839
- \family default
2840
- ,
2841
- \family typewriter
2842
- Pawn
2843
- \family default
2844
- are merely constants of the namespace
2845
- \family typewriter
2846
- Chess
2847
- \family default
2848
- .
2849
- Similarly, in
2850
- \family typewriter
2851
- YPetri
2852
- \family default
2853
- , when talking about
2854
- \family typewriter
2855
- YPetri::Place
2856
- \family default
2857
- ,
2858
- \family typewriter
2859
- YPetri::Transition
2860
- \family default
2861
- or
2862
- \family typewriter
2863
- YPetri::Net
2864
- \family default
2865
- , it means constants
2866
- \family typewriter
2867
- Place
2868
- \family default
2869
- ,
2870
- \family typewriter
2871
- Transition
2872
- \family default
2873
- and
2874
- \family typewriter
2875
- Net
2876
- \family default
2877
- belonging to the module
2878
- \family typewriter
2879
- YPetri
2880
- \family default
2881
- and containing the relevant class objects.
2882
- But each of these classes is a namespace of its own, that can have constants
2883
- defined on it.
2884
- For example,
2885
- \family typewriter
2886
- YPetri::Simulation
2887
- \family default
2888
- has constants
2889
- \family typewriter
2890
- YPetri::Simulation::PlaceRepresentation
2891
- \family default
2892
- and
2893
- \family typewriter
2894
- YPetri::Simulation::TransitionRepresentation
2895
- \family default
2896
- , representing copies of the net's places and transitions when executed
2897
- inside a
2898
- \family typewriter
2899
- Simulation
2900
- \family default
2901
- instance.
2902
- \end_layout
2903
-
2904
- \begin_layout Section*
2905
- Parametrized subclassing
2906
- \end_layout
2907
-
2908
- \begin_layout Standard
2909
- One of the core techniques used in
2910
- \family typewriter
2911
- YNelson
2912
- \family default
2913
- /
2914
- \family typewriter
2915
- YPetri
2916
- \family default
2917
- domain model is parametrized subclassing.
2918
- Literature on the topic does exist, but the concept is best explained on
2919
- examples:
2920
- \end_layout
2921
-
2922
- \begin_layout LyX-Code
2923
- require 'y_support/all'
2924
- \end_layout
2925
-
2926
- \begin_layout LyX-Code
2927
-
2928
- \end_layout
2929
-
2930
- \begin_layout LyX-Code
2931
- class Human
2932
- \end_layout
2933
-
2934
- \begin_layout LyX-Code
2935
- include NameMagic # allows humans to be named easily
2936
- \end_layout
2937
-
2938
- \begin_layout LyX-Code
2939
- end
2940
- \end_layout
2941
-
2942
- \begin_layout Standard
2943
- Humans generally live in settlements.
2944
- Let us create class
2945
- \family typewriter
2946
- Village
2947
- \family default
2948
- representing settlements.
2949
- \end_layout
2950
-
2951
- \begin_layout LyX-Code
2952
- class Village
2953
- \end_layout
2954
-
2955
- \begin_layout LyX-Code
2956
- include NameMagic # allows villages to be named easily
2957
- \end_layout
2958
-
2959
- \begin_layout LyX-Code
2960
- end
2961
- \end_layout
2962
-
2963
- \begin_layout Standard
2964
- At this point, we are standing in front of the problem of making humans
2965
- associated with their settlements.
2966
- One way to do it is to make each
2967
- \family typewriter
2968
- Human
2969
- \family default
2970
- instance remember which settlement they belong to.
2971
- This approach, which you can certainly imagine well even without demonstration,
2972
- is in common use.
2973
- But we have a more powerful approach at our disposal – subclassing.
2974
- This is how we can define a subclass of humans living in London:
2975
- \end_layout
2976
-
2977
- \begin_layout LyX-Code
2978
- London = Village.new
2979
- \end_layout
2980
-
2981
- \begin_layout LyX-Code
2982
-
2983
- \end_layout
2984
-
2985
- \begin_layout LyX-Code
2986
- class Londoner
2987
- \color red
2988
- <
2989
- \color inherit
2990
- Human # using < sign
2991
- \end_layout
2992
-
2993
- \begin_layout LyX-Code
2994
- def self.settlement; London end # let the class know its city
2995
- \end_layout
2996
-
2997
- \begin_layout LyX-Code
2998
- end
2999
- \end_layout
3000
-
3001
- \begin_layout LyX-Code
3002
-
3003
- \end_layout
3004
-
3005
- \begin_layout LyX-Code
3006
- John = Londoner.new
3007
- \end_layout
3008
-
3009
- \begin_layout LyX-Code
3010
- John.class.settlement #=> London
3011
- \end_layout
3012
-
3013
- \begin_layout Standard
3014
- To make it easier to ask humans about their settlement, let's reopen class
3015
-
3016
- \family typewriter
3017
- Human
3018
- \family default
3019
- and delegate method
3020
- \family typewriter
3021
- #settlement
3022
- \family default
3023
- to the class:
3024
- \end_layout
3025
-
3026
- \begin_layout LyX-Code
3027
- class Human
3028
- \end_layout
3029
-
3030
- \begin_layout LyX-Code
3031
- def settlement; self.class.settlement end
3032
- \end_layout
3033
-
3034
- \begin_layout LyX-Code
3035
- end
3036
- \end_layout
3037
-
3038
- \begin_layout Standard
3039
- Alternative syntax for subclassing is this:
3040
- \end_layout
3041
-
3042
- \begin_layout LyX-Code
3043
- Dublin = Village.new
3044
- \end_layout
3045
-
3046
- \begin_layout LyX-Code
3047
-
3048
- \end_layout
3049
-
3050
- \begin_layout LyX-Code
3051
- Dubliner = Class.new Human do # using argument to Class.new
3052
- \end_layout
3053
-
3054
- \begin_layout LyX-Code
3055
- def self.settlement; Dublin end
3056
- \end_layout
3057
-
3058
- \begin_layout LyX-Code
3059
- end
3060
- \end_layout
3061
-
3062
- \begin_layout LyX-Code
3063
-
3064
- \end_layout
3065
-
3066
- \begin_layout LyX-Code
3067
- Finnegan = Dubliner.new
3068
- \end_layout
3069
-
3070
- \begin_layout LyX-Code
3071
- Finnegan.class.settlement #=> Dublin
3072
- \end_layout
3073
-
3074
- \begin_layout LyX-Code
3075
-
3076
- \end_layout
3077
-
3078
- \begin_layout Standard
3079
- Simply, each settlement has its own class of humans – its inhabitants.
3080
- But since there are many settlements, it is inconvenient to manually define
3081
- the inhabitant class for each of them.
3082
- We therefore make each village automatically construct its own subclass
3083
- of
3084
- \family typewriter
3085
- Human
3086
- \family default
3087
- and parametrize it with
3088
- \family typewriter
3089
- settlement
3090
- \family default
3091
- attribute.
3092
-
3093
- \family typewriter
3094
- YSupport
3095
- \family default
3096
- supports parametrized subclassing with method
3097
- \family typewriter
3098
- #param_class
3099
- \family default
3100
- , and makes it easy to construct a PS of
3101
- \family typewriter
3102
- Human
3103
- \family default
3104
- for each
3105
- \family typewriter
3106
- Village
3107
- \family default
3108
- istance.
3109
- \end_layout
3110
-
3111
- \begin_layout LyX-Code
3112
- class Village # reopening the class defined earlier
3113
- \end_layout
3114
-
3115
- \begin_layout LyX-Code
3116
- def initialize # defining a constructor
3117
- \end_layout
3118
-
3119
- \begin_layout LyX-Code
3120
- param_class( { Human: Human }, with: { settlement: self } )
3121
- \end_layout
3122
-
3123
- \begin_layout LyX-Code
3124
- end
3125
- \end_layout
3126
-
3127
- \begin_layout LyX-Code
3128
- end
3129
- \end_layout
3130
-
3131
- \begin_layout Standard
3132
- Each village has now its own PS of
3133
- \family typewriter
3134
- Human
3135
- \family default
3136
- .
3137
- \end_layout
3138
-
3139
- \begin_layout LyX-Code
3140
- Stockholm, Riga, Canberra = 3.times.map { Village.new }
3141
- \end_layout
3142
-
3143
- \begin_layout LyX-Code
3144
- Stockholm.Human # class of Stockholm citizens
3145
- \end_layout
3146
-
3147
- \begin_layout LyX-Code
3148
- Riga.Human # class of Riga citizens
3149
- \end_layout
3150
-
3151
- \begin_layout LyX-Code
3152
- Canberra.Human # class of Vilnius citizens
3153
- \end_layout
3154
-
3155
- \begin_layout LyX-Code
3156
- Stockholm.Human == Riga.Human #=> false
3157
- \end_layout
3158
-
3159
- \begin_layout LyX-Code
3160
-
3161
- \end_layout
3162
-
3163
- \begin_layout LyX-Code
3164
- Fred = Stockholm.Human.new # Stockholm citizen constructor
3165
- \end_layout
3166
-
3167
- \begin_layout LyX-Code
3168
- Fred.class.settlement #=> Stockholm
3169
- \end_layout
3170
-
3171
- \begin_layout Standard
3172
- We say that PS of
3173
- \family typewriter
3174
- Human
3175
- \family default
3176
- class
3177
- \emph on
3178
- depends
3179
- \emph default
3180
- on
3181
- \family typewriter
3182
- Village
3183
- \family default
3184
- .
3185
- The advantage is that instances of the PS of
3186
- \family typewriter
3187
- Human
3188
- \family default
3189
- don't need to be explicitly told which village do they belong to, and have
3190
- easy access to the assets of its owner
3191
- \family typewriter
3192
- Village
3193
- \family default
3194
- instance.
3195
- The concept of parametrized subclassing is actually very simple.
3196
- \end_layout
3197
-
3198
- \begin_layout Section*
3199
- Convenience methods
3200
- \end_layout
3201
-
3202
- \begin_layout Standard
3203
- Convenience methods are methods in which the consistency of the behavior
3204
- is traded for syntax sweetness.
3205
- Convenience methods may do entirely different things for different argument
3206
- sets.
3207
- For example, in
3208
- \family typewriter
3209
- YPetri
3210
- \family default
3211
- , (a Petri net gem on which
3212
- \family typewriter
3213
- YNelson
3214
- \family default
3215
- depends, you can install it by "
3216
- \family typewriter
3217
- gem install y_petri
3218
- \family default
3219
- ", if you haven't done so yet),
3220
- \family typewriter
3221
- Place#marking
3222
- \family default
3223
- without arguments simply returns the place's marking.
3224
- But with arguments, it can be used to define a guard:
3225
- \end_layout
3226
-
3227
- \begin_layout LyX-Code
3228
- require 'y_petri' and include YPetri
3229
- \end_layout
3230
-
3231
- \begin_layout LyX-Code
3232
- A = Place marking: 42
3233
- \end_layout
3234
-
3235
- \begin_layout LyX-Code
3236
- A.marking # Simply returns its marking
3237
- \end_layout
3238
-
3239
- \begin_layout LyX-Code
3240
- # But with different arguments, same method can be used to
3241
- \end_layout
3242
-
3243
- \begin_layout LyX-Code
3244
- # define a guard.
3245
- \end_layout
3246
-
3247
- \begin_layout LyX-Code
3248
- A.marking "must never be above 100" do |m| m <= 100 end
3249
- \end_layout
3250
-
3251
- \begin_layout LyX-Code
3252
- A.marking = 99 # no problem
3253
- \end_layout
3254
-
3255
- \begin_layout LyX-Code
3256
- A.marking = 101 # YPetri::GuardError is raised
3257
- \end_layout
3258
-
3259
- \begin_layout Standard
3260
- Convenience methods are especially suited for non-reusable code, but their
3261
- use may sometimes be efficient also in reusable code.
3262
- \end_layout
3263
-
3264
- \end_body
3265
- \end_document