y_petri 2.4.8 → 2.4.9

Sign up to get free protection for your applications and to get access to all the features.
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