y_nelson 2.1.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -65,7 +65,7 @@
65
65
  \begin_body
66
66
 
67
67
  \begin_layout Title
68
- Ruby for YNelson Users in 20 minutes
68
+ Introduction to Ruby for YNelson Users
69
69
  \end_layout
70
70
 
71
71
  \begin_layout Standard
@@ -74,29 +74,67 @@ For
74
74
  YNelson
75
75
  \family default
76
76
  users, basic Ruby syntax is necessary.
77
- This document provides the Ruby syntax primer for
77
+ This document is a primer to Ruby for
78
78
  \family typewriter
79
79
  YNelson
80
80
  \family default
81
81
  users.
82
-
83
- \series bold
84
- This document is better done in one session, as the provided code samples
85
- rely on each other.
82
+ This documents should be used in the same way as
83
+ \family typewriter
84
+ YNelson
85
+ \family default
86
+ tutorial (Introduction to
87
+ \family typewriter
88
+ YNelson
89
+ \family default
90
+ ) – that is, get an
91
+ \emph on
92
+ irb
93
+ \emph default
94
+ session running, and type all the examples in by yourself.
95
+ You might also wish to install
96
+ \family typewriter
97
+ YNelson
98
+ \family default
99
+ by by typing "
100
+ \family typewriter
101
+ gem install y_nelson
102
+ \family default
103
+ " from your command line.
104
+ Since many of the code samples here rely heavily on each other, you may
105
+ consider to do this document in one session.
106
+ On the other hand, if you happen to be a Ruby hacker, you do not need to
107
+ continue reading this document at all.
108
+ This document is not a replacement for a Ruby textbook.
109
+ For those, who want more thorough introduction to the language, I recommend
110
+ the document
111
+ \begin_inset CommandInset href
112
+ LatexCommand href
113
+ target "http://www.rubyist.net/~slagell/ruby/index.html"
86
114
 
87
- \series default
88
- If you are familiar with Ruby, you do not need to read this document at
89
- all.
90
- Those who want more thorough introduction to the language, I recommend
91
- http://www.rubyist.net/~slagell/ruby/index.html, or any of the many Ruby textbooks.
115
+ \end_inset
116
+
117
+ , or one of the many Ruby textbooks.
92
118
  \end_layout
93
119
 
94
- \begin_layout Subsection*
95
- Variables and Constants
120
+ \begin_layout Part*
121
+ Variables and constants
96
122
  \end_layout
97
123
 
98
124
  \begin_layout Standard
99
- In Ruby, everything is an
125
+ In Ruby, everything
126
+ \begin_inset Foot
127
+ status collapsed
128
+
129
+ \begin_layout Plain Layout
130
+ Almost everything.
131
+ Non-object include eg.
132
+ variables or argument fields.
133
+ \end_layout
134
+
135
+ \end_inset
136
+
137
+ is an
100
138
  \emph on
101
139
  \color red
102
140
  object
@@ -199,7 +237,85 @@ defined? Gamma
199
237
  #=> "constant"
200
238
  \end_layout
201
239
 
202
- \begin_layout Subsection*
240
+ \begin_layout Part*
241
+ Code lines and comments
242
+ \end_layout
243
+
244
+ \begin_layout Standard
245
+ Ruby lines can be written with or without semicolons:
246
+ \end_layout
247
+
248
+ \begin_layout LyX-Code
249
+ a = "with";
250
+ \end_layout
251
+
252
+ \begin_layout LyX-Code
253
+ b = "without"
254
+ \end_layout
255
+
256
+ \begin_layout LyX-Code
257
+ puts [ a, b ].join " or "
258
+ \end_layout
259
+
260
+ \begin_layout Standard
261
+ Semicolon is compulsory only when two or more logical lines are crammed
262
+ together like this:
263
+ \end_layout
264
+
265
+ \begin_layout LyX-Code
266
+ a =
267
+ \begin_inset Quotes eld
268
+ \end_inset
269
+
270
+ Hello
271
+ \begin_inset Quotes eld
272
+ \end_inset
273
+
274
+ ; b =
275
+ \begin_inset Quotes eld
276
+ \end_inset
277
+
278
+ world!
279
+ \begin_inset Quotes erd
280
+ \end_inset
281
+
282
+ ; puts a + b
283
+ \end_layout
284
+
285
+ \begin_layout Standard
286
+ Comments are denoted by
287
+ \family typewriter
288
+ #
289
+ \family default
290
+ sign.
291
+ Anything on the line following the
292
+ \family typewriter
293
+ #
294
+ \family default
295
+ sign is ignored:
296
+ \end_layout
297
+
298
+ \begin_layout LyX-Code
299
+ puts
300
+ \begin_inset Quotes eld
301
+ \end_inset
302
+
303
+ Hello world!
304
+ \begin_inset Quotes erd
305
+ \end_inset
306
+
307
+ # this line prints the words
308
+ \begin_inset Quotes eld
309
+ \end_inset
310
+
311
+ Hello world!
312
+ \begin_inset Quotes erd
313
+ \end_inset
314
+
315
+
316
+ \end_layout
317
+
318
+ \begin_layout Part*
203
319
  Methods
204
320
  \end_layout
205
321
 
@@ -312,7 +428,7 @@ to_f
312
428
  which is not important.
313
429
  \end_layout
314
430
 
315
- \begin_layout Subsection*
431
+ \begin_layout Part*
316
432
  Classes
317
433
  \end_layout
318
434
 
@@ -404,7 +520,7 @@ end
404
520
  \end_layout
405
521
 
406
522
  \begin_layout LyX-Code
407
- Pochi = Dog.
523
+ Spot = Dog.
408
524
  \color red
409
525
  new
410
526
  \end_layout
@@ -414,7 +530,7 @@ new
414
530
  \end_layout
415
531
 
416
532
  \begin_layout LyX-Code
417
- Pochi.speak!
533
+ Spot.speak!
418
534
  \end_layout
419
535
 
420
536
  \begin_layout LyX-Code
@@ -446,7 +562,7 @@ end
446
562
  \end_layout
447
563
 
448
564
  \begin_layout LyX-Code
449
- Tama = Cat.new
565
+ Lisa = Cat.new
450
566
  \end_layout
451
567
 
452
568
  \begin_layout LyX-Code
@@ -454,7 +570,7 @@ Tama = Cat.new
454
570
  \end_layout
455
571
 
456
572
  \begin_layout LyX-Code
457
- Tama.speak!
573
+ Lisa.speak!
458
574
  \end_layout
459
575
 
460
576
  \begin_layout LyX-Code
@@ -474,7 +590,7 @@ puts
474
590
  ' method, used to simply print characters on the screen.
475
591
  \end_layout
476
592
 
477
- \begin_layout Subsection*
593
+ \begin_layout Part*
478
594
  Strings, Symbols, Arrays and Hashes
479
595
  \end_layout
480
596
 
@@ -534,7 +650,7 @@ Understanding argument passing and closure writing is essential in using
534
650
  YPetri DSL.
535
651
  \end_layout
536
652
 
537
- \begin_layout Subsubsection*
653
+ \begin_layout Section*
538
654
  Strings
539
655
  \end_layout
540
656
 
@@ -670,11 +786,11 @@ my_string
670
786
  \color red
671
787
  <<
672
788
  \color inherit
673
- "Pochi!"
789
+ "Spot!"
674
790
  \end_layout
675
791
 
676
792
  \begin_layout LyX-Code
677
- #=> "Hello Pochi!"
793
+ #=> "Hello Spot!"
678
794
  \end_layout
679
795
 
680
796
  \begin_layout LyX-Code
@@ -693,7 +809,7 @@ Again,
693
809
  operator changed the contents, but the object id remained the same.
694
810
  \end_layout
695
811
 
696
- \begin_layout Subsubsection*
812
+ \begin_layout Section*
697
813
  Symbols
698
814
  \end_layout
699
815
 
@@ -709,7 +825,7 @@ Unlike strings, symbols are immutable – they never change.
709
825
  \end_layout
710
826
 
711
827
  \begin_layout LyX-Code
712
- :Pochi.class
828
+ :Spot.class
713
829
  \end_layout
714
830
 
715
831
  \begin_layout LyX-Code
@@ -718,7 +834,7 @@ Unlike strings, symbols are immutable – they never change.
718
834
  Symbol
719
835
  \end_layout
720
836
 
721
- \begin_layout Subsubsection*
837
+ \begin_layout Section*
722
838
  Arrays
723
839
  \end_layout
724
840
 
@@ -733,7 +849,7 @@ As seen earlier, they can be defined with square brackets
733
849
  \end_layout
734
850
 
735
851
  \begin_layout LyX-Code
736
- my_array = [ Pochi, Tama ]
852
+ my_array = [ Spot, Lisa ]
737
853
  \end_layout
738
854
 
739
855
  \begin_layout LyX-Code
@@ -769,7 +885,7 @@ my_array[-2]
769
885
  #=> #<Dog:0x9c214ac>
770
886
  \end_layout
771
887
 
772
- \begin_layout Subsubsection*
888
+ \begin_layout Section*
773
889
  Hashes
774
890
  \end_layout
775
891
 
@@ -791,7 +907,7 @@ Ruby rocket
791
907
  \end_layout
792
908
 
793
909
  \begin_layout LyX-Code
794
- h1 = { Pochi => "dog", Tama => "cat" }
910
+ h1 = { Spot => "dog", Lisa => "cat" }
795
911
  \end_layout
796
912
 
797
913
  \begin_layout LyX-Code
@@ -799,7 +915,7 @@ h1 = { Pochi => "dog", Tama => "cat" }
799
915
  \end_layout
800
916
 
801
917
  \begin_layout LyX-Code
802
- h1[ Tama ]
918
+ h1[ Lisa ]
803
919
  \end_layout
804
920
 
805
921
  \begin_layout LyX-Code
@@ -807,7 +923,7 @@ h1[ Tama ]
807
923
  \end_layout
808
924
 
809
925
  \begin_layout LyX-Code
810
- h1[ Pochi ]
926
+ h1[ Spot ]
811
927
  \end_layout
812
928
 
813
929
  \begin_layout LyX-Code
@@ -820,7 +936,7 @@ The second way is possible only when the keys are symbols.
820
936
  \end_layout
821
937
 
822
938
  \begin_layout LyX-Code
823
- h2 = { dog: Pochi, cat: Tama }
939
+ h2 = { dog: Spot, cat: Lisa }
824
940
  \end_layout
825
941
 
826
942
  \begin_layout LyX-Code
@@ -835,7 +951,7 @@ h2[:dog]
835
951
  #=> #<Dog:0x9c214ac>
836
952
  \end_layout
837
953
 
838
- \begin_layout Subsection*
954
+ \begin_layout Part*
839
955
  Code blocks and Closures
840
956
  \end_layout
841
957
 
@@ -946,7 +1062,7 @@ lambda calculus
946
1062
  .
947
1063
  \end_layout
948
1064
 
949
- \begin_layout Subsubsection*
1065
+ \begin_layout Section*
950
1066
  Return values
951
1067
  \end_layout
952
1068
 
@@ -975,7 +1091,7 @@ Code blocks (and actually, all Ruby statements) have return value.
975
1091
  #=> [0, 1, 2, 3]
976
1092
  \end_layout
977
1093
 
978
- \begin_layout Subsubsection*
1094
+ \begin_layout Section*
979
1095
  Closures
980
1096
  \end_layout
981
1097
 
@@ -1083,7 +1199,7 @@ my_proc.
1083
1199
  \color red
1084
1200
  call
1085
1201
  \color inherit
1086
- ( Pochi )
1202
+ ( Spot )
1087
1203
  \end_layout
1088
1204
 
1089
1205
  \begin_layout LyX-Code
@@ -1091,7 +1207,7 @@ call
1091
1207
  \end_layout
1092
1208
 
1093
1209
  \begin_layout LyX-Code
1094
- my_lambda.call( Tama )
1210
+ my_lambda.call( Lisa )
1095
1211
  \end_layout
1096
1212
 
1097
1213
  \begin_layout LyX-Code
@@ -1111,7 +1227,7 @@ my_proc
1111
1227
  \color red
1112
1228
  .
1113
1229
  \color inherit
1114
- ( Tama )
1230
+ ( Lisa )
1115
1231
  \end_layout
1116
1232
 
1117
1233
  \begin_layout LyX-Code
@@ -1119,7 +1235,7 @@ my_proc
1119
1235
  \end_layout
1120
1236
 
1121
1237
  \begin_layout LyX-Code
1122
- my_lambda.( Pochi )
1238
+ my_lambda.( Spot )
1123
1239
  \end_layout
1124
1240
 
1125
1241
  \begin_layout LyX-Code
@@ -1152,7 +1268,7 @@ lambda
1152
1268
  \end_layout
1153
1269
 
1154
1270
  \begin_layout LyX-Code
1155
- my_proc.( Tama, "garbage" )
1271
+ my_proc.( Lisa, "garbage" )
1156
1272
  \end_layout
1157
1273
 
1158
1274
  \begin_layout LyX-Code
@@ -1160,14 +1276,42 @@ my_proc.( Tama, "garbage" )
1160
1276
  \end_layout
1161
1277
 
1162
1278
  \begin_layout LyX-Code
1163
- my_lambda.( Tama, "garbage" )
1279
+ my_lambda.( Lisa, "garbage" )
1164
1280
  \end_layout
1165
1281
 
1166
1282
  \begin_layout LyX-Code
1167
1283
  #=> ArgumentError: wrong number of arguments (2 for 1)
1168
1284
  \end_layout
1169
1285
 
1170
- \begin_layout Subsection*
1286
+ \begin_layout Standard
1287
+ Finally, let us notice the alternative syntax for defining lambdas:
1288
+ \end_layout
1289
+
1290
+ \begin_layout LyX-Code
1291
+ my_lambda = lambda do |organism| organism.speak! end
1292
+ \end_layout
1293
+
1294
+ \begin_layout LyX-Code
1295
+ my_lambda = lambda { |organism| oranism.speak! }
1296
+ \end_layout
1297
+
1298
+ \begin_layout LyX-Code
1299
+ my_lambda =
1300
+ \color red
1301
+ ->
1302
+ \color inherit
1303
+ organism do organism.speak! end
1304
+ \end_layout
1305
+
1306
+ \begin_layout LyX-Code
1307
+ my_lambda = -> orgnism { organism.speak! }
1308
+ \end_layout
1309
+
1310
+ \begin_layout Standard
1311
+ All of the four above statements define exactly the same thing.
1312
+ \end_layout
1313
+
1314
+ \begin_layout Section*
1171
1315
  Passing arguments
1172
1316
  \end_layout
1173
1317
 
@@ -1256,7 +1400,7 @@ YNelson
1256
1400
  , this is the language of Ruby closures.
1257
1401
  \end_layout
1258
1402
 
1259
- \begin_layout Subsubsection*
1403
+ \begin_layout Section*
1260
1404
  Optional arguments
1261
1405
  \end_layout
1262
1406
 
@@ -1274,7 +1418,7 @@ def average( a, b, c
1274
1418
  \color red
1275
1419
  =
1276
1420
  \color inherit
1277
- :pochi )
1421
+ :spot )
1278
1422
  \end_layout
1279
1423
 
1280
1424
  \begin_layout LyX-Code
@@ -1282,7 +1426,7 @@ def average( a, b, c
1282
1426
  \color red
1283
1427
  #
1284
1428
  \color inherit
1285
- If c argument was not given, :pochi symbol will be assigned
1429
+ If c argument was not given, :spot symbol will be assigned
1286
1430
  \end_layout
1287
1431
 
1288
1432
  \begin_layout LyX-Code
@@ -1298,7 +1442,7 @@ if
1298
1442
  \color red
1299
1443
  ==
1300
1444
  \color inherit
1301
- :pochi
1445
+ :spot
1302
1446
  \color red
1303
1447
  then
1304
1448
  \color inherit
@@ -1431,7 +1575,7 @@ c
1431
1575
  All code lines, exception the obvious ones, should have comments.
1432
1576
  \end_layout
1433
1577
 
1434
- \begin_layout Subsubsection*
1578
+ \begin_layout Section*
1435
1579
  Variable-length argument lists
1436
1580
  \end_layout
1437
1581
 
@@ -1535,7 +1679,7 @@ examine_arguments( 1 )
1535
1679
  \end_layout
1536
1680
 
1537
1681
  \begin_layout LyX-Code
1538
- examine_arguments( :hello, :pochi, 3, 5, "garbage" )
1682
+ examine_arguments( :hello, :spot, 3, 5, "garbage" )
1539
1683
  \end_layout
1540
1684
 
1541
1685
  \begin_layout LyX-Code
@@ -1616,7 +1760,7 @@ avg.( 11, 7, 5, 3 )
1616
1760
  #=> 6.5
1617
1761
  \end_layout
1618
1762
 
1619
- \begin_layout Subsubsection*
1763
+ \begin_layout Section*
1620
1764
  Named arguments
1621
1765
  \end_layout
1622
1766
 
@@ -1717,7 +1861,7 @@ lambda do |arg| ...
1717
1861
  ) array constructor syntax.
1718
1862
  \end_layout
1719
1863
 
1720
- \begin_layout Subsubsection*
1864
+ \begin_layout Section*
1721
1865
  Hash-collecting behavior of square brackets
1722
1866
  \end_layout
1723
1867
 
@@ -1822,7 +1966,7 @@ enzyme
1822
1966
  constructor method.
1823
1967
  \end_layout
1824
1968
 
1825
- \begin_layout Subsection*
1969
+ \begin_layout Section*
1826
1970
  Arity
1827
1971
  \end_layout
1828
1972
 
@@ -2002,7 +2146,7 @@ array_scale.arity
2002
2146
  #=> -2
2003
2147
  \end_layout
2004
2148
 
2005
- \begin_layout Subsection*
2149
+ \begin_layout Section*
2006
2150
  Return value
2007
2151
  \end_layout
2008
2152
 
@@ -2120,12 +2264,28 @@ experimental_lambda.call
2120
2264
  #=> 3
2121
2265
  \end_layout
2122
2266
 
2123
- \begin_layout Subsection*
2267
+ \begin_layout Section*
2124
2268
  Return value arity
2125
2269
  \end_layout
2126
2270
 
2127
2271
  \begin_layout Standard
2128
- It is possible to return more than one value.
2272
+ It is possible to return more than one value
2273
+ \begin_inset Foot
2274
+ status open
2275
+
2276
+ \begin_layout Plain Layout
2277
+ Technically, methods and closures always return exactly 1 object – multiple
2278
+ values are returned via a single array object.
2279
+ But pragmatically, and especially with respect to
2280
+ \family typewriter
2281
+ YPetri
2282
+ \family default
2283
+ , the notion of return value arity is useful.
2284
+ \end_layout
2285
+
2286
+ \end_inset
2287
+
2288
+ .
2129
2289
  For example:
2130
2290
  \end_layout
2131
2291
 
@@ -2250,5 +2410,832 @@ z
2250
2410
  #=> 3
2251
2411
  \end_layout
2252
2412
 
2413
+ \begin_layout Part*
2414
+
2415
+ \family typewriter
2416
+ YSupport
2417
+ \family default
2418
+ library
2419
+ \end_layout
2420
+
2421
+ \begin_layout Standard
2422
+ Finally, having introduced the basic Ruby syntax, let us mention
2423
+ \family typewriter
2424
+ YSupport
2425
+ \family default
2426
+ gem (gem = published Ruby library), that collects the assets (modules,
2427
+ classes, methods...) of general concern in use by
2428
+ \family typewriter
2429
+ YPetri
2430
+ \family default
2431
+ /
2432
+ \family typewriter
2433
+ YNelson
2434
+ \family default
2435
+ .
2436
+ Of these, a particular mention goes to
2437
+ \family typewriter
2438
+ NameMagic
2439
+ \family default
2440
+ , widely used in
2441
+ \family typewriter
2442
+ YPetri
2443
+ \family default
2444
+ ,
2445
+ \family typewriter
2446
+ YNelson
2447
+ \family default
2448
+ and
2449
+ \family typewriter
2450
+ SY
2451
+ \family default
2452
+ (physical units) libraries.
2453
+ \end_layout
2454
+
2455
+ \begin_layout Section*
2456
+
2457
+ \family typewriter
2458
+ NameMagic
2459
+ \end_layout
2460
+
2461
+ \begin_layout Standard
2462
+ In software engineering,
2463
+ \emph on
2464
+ magic
2465
+ \emph default
2466
+ is a technical term for irregular side effects of language expressions.
2467
+ The problem that
2468
+ \family typewriter
2469
+ NameMagic
2470
+ \family default
2471
+ solves is, that objects (such as chemical species encoded in
2472
+ \family typewriter
2473
+ YNelson
2474
+ \family default
2475
+ ) are frequently named, and naming them is an annoying chore.
2476
+ Consider a simple case:
2477
+ \end_layout
2478
+
2479
+ \begin_layout LyX-Code
2480
+ class Student
2481
+ \end_layout
2482
+
2483
+ \begin_layout LyX-Code
2484
+ attr_accessor :name
2485
+ \end_layout
2486
+
2487
+ \begin_layout LyX-Code
2488
+ def initialize name: nil
2489
+ \end_layout
2490
+
2491
+ \begin_layout LyX-Code
2492
+ @name = name
2493
+ \end_layout
2494
+
2495
+ \begin_layout LyX-Code
2496
+ end
2497
+ \end_layout
2498
+
2499
+ \begin_layout LyX-Code
2500
+ end
2501
+ \end_layout
2502
+
2503
+ \begin_layout Standard
2504
+ Now, to create named
2505
+ \family typewriter
2506
+ Student
2507
+ \family default
2508
+ instances, one has to mention
2509
+ \family typewriter
2510
+ :name
2511
+ \family default
2512
+ named argument in the constructor, and frequently, the same name has to
2513
+ be mentioned twice, such as when assigning to constants or variables:
2514
+ \end_layout
2515
+
2516
+ \begin_layout LyX-Code
2517
+ richard = Student.new( name: "Richard" )
2518
+ \end_layout
2519
+
2520
+ \begin_layout LyX-Code
2521
+ richard.name
2522
+ \end_layout
2523
+
2524
+ \begin_layout LyX-Code
2525
+ #=> "Richard"
2526
+ \end_layout
2527
+
2528
+ \begin_layout Standard
2529
+ In Ruby, we can notice that some objects have built-in capability to be
2530
+ named simply by constant assignment:
2531
+ \end_layout
2532
+
2533
+ \begin_layout LyX-Code
2534
+ foo = Class.new
2535
+ \end_layout
2536
+
2537
+ \begin_layout LyX-Code
2538
+ foo.name
2539
+ \end_layout
2540
+
2541
+ \begin_layout LyX-Code
2542
+ #=> nil
2543
+ \end_layout
2544
+
2545
+ \begin_layout LyX-Code
2546
+ Car = foo
2547
+ \end_layout
2548
+
2549
+ \begin_layout LyX-Code
2550
+ foo.name
2551
+ \end_layout
2552
+
2553
+ \begin_layout LyX-Code
2554
+ #=> "Car"
2555
+ \end_layout
2556
+
2557
+ \begin_layout Standard
2558
+ Magically, upon assigning
2559
+ \family typewriter
2560
+ Car = foo
2561
+ \family default
2562
+ , the object referred to by the
2563
+ \family typewriter
2564
+ foo
2565
+ \family default
2566
+ variable received an attribute
2567
+ \family typewriter
2568
+ name
2569
+ \family default
2570
+ , with value set to "
2571
+ \family typewriter
2572
+ Car
2573
+ \family default
2574
+ ".
2575
+ This standard behavior is termed constant magic.
2576
+
2577
+ \family typewriter
2578
+ NameMagic
2579
+ \family default
2580
+ mixin (part of
2581
+ \family typewriter
2582
+ YSupport
2583
+ \family default
2584
+ ) extends this standard behavior to any chosen object, and also takes care
2585
+ of keeping the instance registry and doing general naming related chores
2586
+ for its includers:
2587
+ \end_layout
2588
+
2589
+ \begin_layout LyX-Code
2590
+ require 'y_support/name_magic'
2591
+ \end_layout
2592
+
2593
+ \begin_layout LyX-Code
2594
+
2595
+ \end_layout
2596
+
2597
+ \begin_layout LyX-Code
2598
+ class Chemical
2599
+ \end_layout
2600
+
2601
+ \begin_layout LyX-Code
2602
+ include NameMagic
2603
+ \end_layout
2604
+
2605
+ \begin_layout LyX-Code
2606
+ end
2607
+ \end_layout
2608
+
2609
+ \begin_layout LyX-Code
2610
+
2611
+ \end_layout
2612
+
2613
+ \begin_layout LyX-Code
2614
+ NaCl = Chemical.new
2615
+ \end_layout
2616
+
2617
+ \begin_layout LyX-Code
2618
+ NaCl.name
2619
+ \end_layout
2620
+
2621
+ \begin_layout LyX-Code
2622
+ #=> "NaCl"
2623
+ \end_layout
2624
+
2625
+ \begin_layout Standard
2626
+ It might seem like a small thing, but in a big file of complicated equation,
2627
+ it really starts to matter whether one writes on each line "
2628
+ \family typewriter
2629
+ NaCl = Chemical.new( name: NaCl )
2630
+ \family default
2631
+ ", or just "
2632
+ \family typewriter
2633
+ NaCl = Chemical.new
2634
+ \family default
2635
+ ".
2636
+
2637
+ \family typewriter
2638
+ NameMagic
2639
+ \family default
2640
+ is a part of
2641
+ \family typewriter
2642
+ YSupport
2643
+ \family default
2644
+ library accompanying
2645
+ \family typewriter
2646
+ YPetri
2647
+ \family default
2648
+ and
2649
+ \family typewriter
2650
+ YNelson
2651
+ \family default
2652
+ .
2653
+ You can install
2654
+ \family typewriter
2655
+ YSupport
2656
+ \family default
2657
+ from the command line by "
2658
+ \family typewriter
2659
+ gem install y_support
2660
+ \family default
2661
+ ".
2662
+ \end_layout
2663
+
2664
+ \begin_layout Part*
2665
+ Other essential concepts
2666
+ \end_layout
2667
+
2668
+ \begin_layout Standard
2669
+ There are a few more essential concepts of Ruby that
2670
+ \family typewriter
2671
+ YNelson
2672
+ \family default
2673
+ users should be familiar with, such as namespaces and parametrized subclassing.
2674
+ Code examples in this section are slightly more complicated, and also,
2675
+ they make use of
2676
+ \family typewriter
2677
+ YSupport
2678
+ \family default
2679
+ gem.
2680
+ Install
2681
+ \family typewriter
2682
+ YSupport
2683
+ \family default
2684
+ by typing
2685
+ \family typewriter
2686
+ gem install y_support
2687
+ \family default
2688
+ in your command line before studying code examples in this section.
2689
+ \end_layout
2690
+
2691
+ \begin_layout Section*
2692
+ Namespaces
2693
+ \end_layout
2694
+
2695
+ \begin_layout Standard
2696
+ In Ruby, namespaces are known as modules (objects of
2697
+ \family typewriter
2698
+ Module
2699
+ \family default
2700
+ class).
2701
+ These objects are containers for constants and method definitions.
2702
+ For example, let us imagine that we want to define constants, classes and
2703
+ methods related to the game of chess.
2704
+ We could simply define them in the command line, without any considerations,
2705
+ We could do it directly, but that way, all of them would be defined in
2706
+ the root of Ruby namespace – on
2707
+ \family typewriter
2708
+ Object
2709
+ \family default
2710
+ class.
2711
+ The reason why this is not a good idea is the same as the reason why it
2712
+ is not a good idea to put all your files in the root of your filesystem.
2713
+ Chess-related terms such as
2714
+ \family typewriter
2715
+ Field
2716
+ \family default
2717
+ or
2718
+ \family typewriter
2719
+ Piece
2720
+ \family default
2721
+ could collide with concepts from other domains not related to chess.
2722
+ For that reason, we will collect all the chess-related assets into a single
2723
+ namespace:
2724
+ \end_layout
2725
+
2726
+ \begin_layout LyX-Code
2727
+ module Chess
2728
+ \end_layout
2729
+
2730
+ \begin_layout LyX-Code
2731
+ class Board < Array
2732
+ \end_layout
2733
+
2734
+ \begin_layout LyX-Code
2735
+ SIZE = 8 # standard chessboard
2736
+ \end_layout
2737
+
2738
+ \begin_layout LyX-Code
2739
+
2740
+ \end_layout
2741
+
2742
+ \begin_layout LyX-Code
2743
+ class Field # chessboard field
2744
+ \end_layout
2745
+
2746
+ \begin_layout LyX-Code
2747
+ attr_accessor :contents
2748
+ \end_layout
2749
+
2750
+ \begin_layout LyX-Code
2751
+ end
2752
+ \end_layout
2753
+
2754
+ \begin_layout LyX-Code
2755
+
2756
+ \end_layout
2757
+
2758
+ \begin_layout LyX-Code
2759
+ def self.new # constructs 8 × 8 array of arrays
2760
+ \end_layout
2761
+
2762
+ \begin_layout LyX-Code
2763
+ super( SIZE, Array.new( SIZE ) { Field.new } )
2764
+ \end_layout
2765
+
2766
+ \begin_layout LyX-Code
2767
+ end
2768
+ \end_layout
2769
+
2770
+ \begin_layout LyX-Code
2771
+ # chessboard is defined here
2772
+ \end_layout
2773
+
2774
+ \begin_layout LyX-Code
2775
+ end
2776
+ \end_layout
2777
+
2778
+ \begin_layout LyX-Code
2779
+
2780
+ \end_layout
2781
+
2782
+ \begin_layout LyX-Code
2783
+ Piece = Class.new # chess piece
2784
+ \end_layout
2785
+
2786
+ \begin_layout LyX-Code
2787
+ Pawn = Class.new Piece # chess pawn
2788
+ \end_layout
2789
+
2790
+ \begin_layout LyX-Code
2791
+ Knight = Class.new Piece # chess knight
2792
+ \end_layout
2793
+
2794
+ \begin_layout LyX-Code
2795
+ Rook = Class.new Piece # chess rook
2796
+ \end_layout
2797
+
2798
+ \begin_layout LyX-Code
2799
+ # etc.
2800
+ \end_layout
2801
+
2802
+ \begin_layout LyX-Code
2803
+ end
2804
+ \end_layout
2805
+
2806
+ \begin_layout Standard
2807
+ We then access the contents of the namespace in the way similar to the way
2808
+ we address the files in the filesystem:
2809
+ \end_layout
2810
+
2811
+ \begin_layout LyX-Code
2812
+ Chess::Board # namespace Chess, constant Board
2813
+ \end_layout
2814
+
2815
+ \begin_layout LyX-Code
2816
+ Chess::Piece # namespace Chess, constant Piece
2817
+ \end_layout
2818
+
2819
+ \begin_layout LyX-Code
2820
+ Chess::Pawn # namespace Chess, constant Pawn
2821
+ \end_layout
2822
+
2823
+ \begin_layout LyX-Code
2824
+ Chess::Board::SIZE # namespace Chess::Board, constant SIZE
2825
+ \end_layout
2826
+
2827
+ \begin_layout LyX-Code
2828
+ Chess::Board::Field # namespace Chess::Board, constant Field
2829
+ \end_layout
2830
+
2831
+ \begin_layout LyX-Code
2832
+ # etc.
2833
+ \end_layout
2834
+
2835
+ \begin_layout Standard
2836
+ Let us note that in the above example,
2837
+ \family typewriter
2838
+ Board
2839
+ \family default
2840
+ ,
2841
+ \family typewriter
2842
+ Piece
2843
+ \family default
2844
+ ,
2845
+ \family typewriter
2846
+ Pawn
2847
+ \family default
2848
+ are merely constants of the namespace
2849
+ \family typewriter
2850
+ Chess
2851
+ \family default
2852
+ .
2853
+ Similarly, in
2854
+ \family typewriter
2855
+ YPetri
2856
+ \family default
2857
+ , when talking about
2858
+ \family typewriter
2859
+ YPetri::Place
2860
+ \family default
2861
+ ,
2862
+ \family typewriter
2863
+ YPetri::Transition
2864
+ \family default
2865
+ or
2866
+ \family typewriter
2867
+ YPetri::Net
2868
+ \family default
2869
+ , it means constants
2870
+ \family typewriter
2871
+ Place
2872
+ \family default
2873
+ ,
2874
+ \family typewriter
2875
+ Transition
2876
+ \family default
2877
+ and
2878
+ \family typewriter
2879
+ Net
2880
+ \family default
2881
+ belonging to the module
2882
+ \family typewriter
2883
+ YPetri
2884
+ \family default
2885
+ and containing the relevant class objects.
2886
+ But each of these classes is a namespace of its own, that can have constants
2887
+ defined on it.
2888
+ For example,
2889
+ \family typewriter
2890
+ YPetri::Simulation
2891
+ \family default
2892
+ has constants
2893
+ \family typewriter
2894
+ YPetri::Simulation::PlaceRepresentation
2895
+ \family default
2896
+ and
2897
+ \family typewriter
2898
+ YPetri::Simulation::TransitionRepresentation
2899
+ \family default
2900
+ , representing copies of the net's places and transitions when executed
2901
+ inside a
2902
+ \family typewriter
2903
+ Simulation
2904
+ \family default
2905
+ instance.
2906
+ \end_layout
2907
+
2908
+ \begin_layout Section*
2909
+ Parametrized subclassing
2910
+ \end_layout
2911
+
2912
+ \begin_layout Standard
2913
+ One of the core techniques used in
2914
+ \family typewriter
2915
+ YNelson
2916
+ \family default
2917
+ /
2918
+ \family typewriter
2919
+ YPetri
2920
+ \family default
2921
+ domain model is parametrized subclassing.
2922
+ Literature on the topic does exist
2923
+ \begin_inset CommandInset citation
2924
+ LatexCommand citep
2925
+ key "Roberts1996efp"
2926
+
2927
+ \end_inset
2928
+
2929
+ , but again, the concept is best explained on examples:
2930
+ \end_layout
2931
+
2932
+ \begin_layout LyX-Code
2933
+ require 'y_support/all'
2934
+ \end_layout
2935
+
2936
+ \begin_layout LyX-Code
2937
+
2938
+ \end_layout
2939
+
2940
+ \begin_layout LyX-Code
2941
+ class Human
2942
+ \end_layout
2943
+
2944
+ \begin_layout LyX-Code
2945
+ include NameMagic # allows humans to be named easily
2946
+ \end_layout
2947
+
2948
+ \begin_layout LyX-Code
2949
+ end
2950
+ \end_layout
2951
+
2952
+ \begin_layout Standard
2953
+ Humans generally live in settlements.
2954
+ Let us create class
2955
+ \family typewriter
2956
+ Village
2957
+ \family default
2958
+ representing settlements.
2959
+ \end_layout
2960
+
2961
+ \begin_layout LyX-Code
2962
+ class Village
2963
+ \end_layout
2964
+
2965
+ \begin_layout LyX-Code
2966
+ include NameMagic # allows villages to be named easily
2967
+ \end_layout
2968
+
2969
+ \begin_layout LyX-Code
2970
+ end
2971
+ \end_layout
2972
+
2973
+ \begin_layout Standard
2974
+ At this point, we are standing in front of the problem of making humans
2975
+ associated with their settlements.
2976
+ One way to do it is to make each
2977
+ \family typewriter
2978
+ Human
2979
+ \family default
2980
+ instance remember which settlement they belong to.
2981
+ This approach, which you can certainly imagine well even without demonstration,
2982
+ is in common use.
2983
+ But we have a more powerful approach at our disposal – subclassing.
2984
+ This is how we can define a subclass of humans living in London:
2985
+ \end_layout
2986
+
2987
+ \begin_layout LyX-Code
2988
+ London = Village.new
2989
+ \end_layout
2990
+
2991
+ \begin_layout LyX-Code
2992
+
2993
+ \end_layout
2994
+
2995
+ \begin_layout LyX-Code
2996
+ class Londoner
2997
+ \color red
2998
+ <
2999
+ \color inherit
3000
+ Human # using < sign
3001
+ \end_layout
3002
+
3003
+ \begin_layout LyX-Code
3004
+ def self.settlement; London end # let the class know its city
3005
+ \end_layout
3006
+
3007
+ \begin_layout LyX-Code
3008
+ end
3009
+ \end_layout
3010
+
3011
+ \begin_layout LyX-Code
3012
+
3013
+ \end_layout
3014
+
3015
+ \begin_layout LyX-Code
3016
+ John = Londoner.new
3017
+ \end_layout
3018
+
3019
+ \begin_layout LyX-Code
3020
+ John.class.settlement #=> London
3021
+ \end_layout
3022
+
3023
+ \begin_layout Standard
3024
+ Alternative syntax for subclassing is this:
3025
+ \end_layout
3026
+
3027
+ \begin_layout LyX-Code
3028
+ Dublin = Village.new
3029
+ \end_layout
3030
+
3031
+ \begin_layout LyX-Code
3032
+
3033
+ \end_layout
3034
+
3035
+ \begin_layout LyX-Code
3036
+ Dubliner = Class.new Human do # using argument to Class.new
3037
+ \end_layout
3038
+
3039
+ \begin_layout LyX-Code
3040
+ def self.settlement; Dublin end
3041
+ \end_layout
3042
+
3043
+ \begin_layout LyX-Code
3044
+ end
3045
+ \end_layout
3046
+
3047
+ \begin_layout LyX-Code
3048
+
3049
+ \end_layout
3050
+
3051
+ \begin_layout LyX-Code
3052
+ Finnegan = Dubliner.new
3053
+ \end_layout
3054
+
3055
+ \begin_layout LyX-Code
3056
+ Finnegan.class.settlement #=> Dublin
3057
+ \end_layout
3058
+
3059
+ \begin_layout LyX-Code
3060
+
3061
+ \end_layout
3062
+
3063
+ \begin_layout Standard
3064
+ Simply, each settlement has its own class of humans – its inhabitants.
3065
+ But since there are many settlements, it is inconvenient to manually define
3066
+ the inhabitant class for each of them.
3067
+ We therefore make each village automatically construct its own subclass
3068
+ of
3069
+ \family typewriter
3070
+ Human
3071
+ \family default
3072
+ and parametrize it with
3073
+ \family typewriter
3074
+ settlement
3075
+ \family default
3076
+ attribute.
3077
+
3078
+ \family typewriter
3079
+ YSupport
3080
+ \family default
3081
+ supports parametrized subclassing with method
3082
+ \family typewriter
3083
+ #param_class
3084
+ \family default
3085
+ , and makes it easy to construct a PS of
3086
+ \family typewriter
3087
+ Human
3088
+ \family default
3089
+ for each
3090
+ \family typewriter
3091
+ Village
3092
+ \family default
3093
+ istance.
3094
+ \end_layout
3095
+
3096
+ \begin_layout LyX-Code
3097
+ class Village # reopening the class defined earlier
3098
+ \end_layout
3099
+
3100
+ \begin_layout LyX-Code
3101
+ def initialize # defining a constructor
3102
+ \end_layout
3103
+
3104
+ \begin_layout LyX-Code
3105
+ param_class( { Human: Human }, with: { settlement: self } )
3106
+ \end_layout
3107
+
3108
+ \begin_layout LyX-Code
3109
+ end
3110
+ \end_layout
3111
+
3112
+ \begin_layout LyX-Code
3113
+ end
3114
+ \end_layout
3115
+
3116
+ \begin_layout Standard
3117
+ Each village has now its own PS of
3118
+ \family typewriter
3119
+ Human
3120
+ \family default
3121
+ .
3122
+ \end_layout
3123
+
3124
+ \begin_layout LyX-Code
3125
+ Stockholm, Riga, Canberra = 3.times.map { Village.new }
3126
+ \end_layout
3127
+
3128
+ \begin_layout LyX-Code
3129
+ Stockholm.Human # class of Stockholm citizens
3130
+ \end_layout
3131
+
3132
+ \begin_layout LyX-Code
3133
+ Riga.Human # class of Riga citizens
3134
+ \end_layout
3135
+
3136
+ \begin_layout LyX-Code
3137
+ Canberra.Human # class of Vilnius citizens
3138
+ \end_layout
3139
+
3140
+ \begin_layout LyX-Code
3141
+ Stockholm.Human == Riga.Human #=> false
3142
+ \end_layout
3143
+
3144
+ \begin_layout LyX-Code
3145
+
3146
+ \end_layout
3147
+
3148
+ \begin_layout LyX-Code
3149
+ Fred = Stockholm.Human.new # Stockholm citizen constructor
3150
+ \end_layout
3151
+
3152
+ \begin_layout LyX-Code
3153
+ Fred.class.settlement #=> Stockholm
3154
+ \end_layout
3155
+
3156
+ \begin_layout Standard
3157
+ We say that PS of
3158
+ \family typewriter
3159
+ Human
3160
+ \family default
3161
+ class
3162
+ \emph on
3163
+ depends
3164
+ \emph default
3165
+ on
3166
+ \family typewriter
3167
+ Village
3168
+ \family default
3169
+ .
3170
+ The advantage is that instances of the PS of
3171
+ \family typewriter
3172
+ Human
3173
+ \family default
3174
+ don't need to be explicitly told which village do they belong to, and have
3175
+ easy access to the assets of its owner
3176
+ \family typewriter
3177
+ Village
3178
+ \family default
3179
+ instance.
3180
+ The concept of parametrized subclassing is actually very simple.
3181
+ \end_layout
3182
+
3183
+ \begin_layout Section*
3184
+ Convenience methods
3185
+ \end_layout
3186
+
3187
+ \begin_layout Standard
3188
+ Convenience methods are methods in which the consistency of the behavior
3189
+ is traded for syntax sweetness.
3190
+ Convenience methods may do entirely different things for different argument
3191
+ sets.
3192
+ For example,
3193
+ \family typewriter
3194
+ Place#marking
3195
+ \family default
3196
+ without arguments simply returns the place's marking.
3197
+ But with arguments, it can be used to define a guard.
3198
+ \end_layout
3199
+
3200
+ \begin_layout LyX-Code
3201
+ A = Place.new marking: 42
3202
+ \end_layout
3203
+
3204
+ \begin_layout LyX-Code
3205
+ A.marking # Simply returns its marking
3206
+ \end_layout
3207
+
3208
+ \begin_layout LyX-Code
3209
+ # But with different arguments, same method can be used to
3210
+ \end_layout
3211
+
3212
+ \begin_layout LyX-Code
3213
+ # define a guard.
3214
+ \end_layout
3215
+
3216
+ \begin_layout LyX-Code
3217
+ A.marking "must never be negative" do |m| m >= 0 end
3218
+ \end_layout
3219
+
3220
+ \begin_layout Standard
3221
+ Depending on circumstances, use of convenience methods in reusable code
3222
+ may or may not be bad practice.
3223
+ \end_layout
3224
+
3225
+ \begin_layout LyX-Code
3226
+
3227
+ \end_layout
3228
+
3229
+ \begin_layout LyX-Code
3230
+ \begin_inset CommandInset bibtex
3231
+ LatexCommand bibtex
3232
+ bibfiles "/home/boris/b/5ced/ced"
3233
+ options "plainnat"
3234
+
3235
+ \end_inset
3236
+
3237
+
3238
+ \end_layout
3239
+
2253
3240
  \end_body
2254
3241
  \end_document