y_nelson 2.3.7 → 2.3.8

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