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