#LyX 2.0 created this file. For more info see http://www.lyx.org/ \lyxformat 413 \begin_document \begin_header \textclass article \use_default_options false \maintain_unincluded_children false \language english \language_package default \inputencoding auto \fontencoding global \font_roman default \font_sans default \font_typewriter default \font_default_family default \use_non_tex_fonts false \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \default_output_format default \output_sync 0 \bibtex_command default \index_command default \paperfontsize default \spacing single \use_hyperref false \papersize default \use_geometry true \use_amsmath 1 \use_esint 1 \use_mhchem 1 \use_mathdots 1 \cite_engine natbib_authoryear \use_bibtopic false \use_indices false \paperorientation portrait \suppress_date false \use_refstyle 0 \index Index \shortcut idx \color #008000 \end_index \leftmargin 2.2cm \topmargin 3cm \rightmargin 2.2cm \bottommargin 3cm \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \paragraph_indentation default \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false \html_math_output 0 \html_css_as_file 0 \html_be_strict false \end_header \begin_body \begin_layout Title Ruby for YNelson Users in 20 minutes \end_layout \begin_layout Standard For \family typewriter YNelson \family default users, basic Ruby syntax is necessary. This document provides the Ruby syntax primer for \family typewriter YNelson \family default users. \series bold This document is better done in one session, as the provided code samples rely on each other. \series default If you are familiar with Ruby, you do not need to read this document at all. Those who want more thorough introduction to the language, I recommend http://www.rubyist.net/~slagell/ruby/index.html, or any of the many Ruby textbooks. \end_layout \begin_layout Subsection* Variables and Constants \end_layout \begin_layout Standard In Ruby, everything is an \emph on \color red object \emph default \color inherit . Objects can be assigned to \emph on \color red variables \emph default \color inherit or \emph on \color red constants \emph default \color inherit . Ruby constants \color red must always start with capital letter \color inherit . Variables starting with small letter are \emph on \color red local variables \emph default \color inherit . (Other types of variables are \emph on \color red instance variables \emph default \color inherit , \emph on \color red class variables \emph default \color inherit and \emph on \color red global constants \emph default \color inherit ; this is not important at the moment.) \end_layout \begin_layout LyX-Code alpha = 1 \end_layout \begin_layout LyX-Code #=> 1 \end_layout \begin_layout LyX-Code beta = [1, 2] \end_layout \begin_layout LyX-Code #=> [1, 2] \end_layout \begin_layout LyX-Code Gamma = { x: 1, y: 2, z: 3 } \end_layout \begin_layout LyX-Code #=> {:x=>1, :y=>2, :z=>3} \end_layout \begin_layout Standard You can check this using \family typewriter \color red defined? \family default \color inherit operator: \end_layout \begin_layout LyX-Code defined? alpha \end_layout \begin_layout LyX-Code #=> "local-variable" \end_layout \begin_layout LyX-Code defined? Gamma \end_layout \begin_layout LyX-Code #=> "constant" \end_layout \begin_layout Subsection* Methods \end_layout \begin_layout Standard Different classes respond to different \emph on \color red methods \emph default \color inherit , and respond to them differently: \end_layout \begin_layout LyX-Code beta. \color red size \end_layout \begin_layout LyX-Code #=> 2 \end_layout \begin_layout LyX-Code Gamma.size \end_layout \begin_layout LyX-Code #=> 3 \end_layout \begin_layout LyX-Code Gamma. \color red keys \end_layout \begin_layout LyX-Code #=> [:x, :y, :z] \end_layout \begin_layout LyX-Code Gamma. \color red values \end_layout \begin_layout LyX-Code #=> [1, 2, 3] \end_layout \begin_layout LyX-Code beta.keys \end_layout \begin_layout LyX-Code #=> NoMethodError: undefined method `keys' for [1, 2]:Array \end_layout \begin_layout Standard Methods can be defined by \family typewriter \color red def \family default \color inherit keyword: \end_layout \begin_layout LyX-Code \color red def \color inherit average( a, b ) \end_layout \begin_layout LyX-Code ( a + b ). \color red to_f \color inherit / 2 \end_layout \begin_layout LyX-Code \color red end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code average( 2, 3 ) \end_layout \begin_layout LyX-Code #=> 2.5 \end_layout \begin_layout Standard In the code example above, ' \family typewriter to_f \family default ' method performs conversion of an integer into a floating point number, which is not important. \end_layout \begin_layout Subsection* Classes \end_layout \begin_layout Standard Every object belongs to some \emph on \color red class \emph default \color inherit (object type): \end_layout \begin_layout LyX-Code alpha. \color red class \end_layout \begin_layout LyX-Code #=> \color red Fixnum \end_layout \begin_layout LyX-Code beta.class \end_layout \begin_layout LyX-Code #=> \color red Array \end_layout \begin_layout LyX-Code Gamma.class \end_layout \begin_layout LyX-Code #=> \color red Hash \end_layout \begin_layout Standard New classes can be defined with \family typewriter \color red class \family default \color inherit keyword. The methods defined inside the class will become the \emph on \color red instance methods \emph default \color inherit of that class: \end_layout \begin_layout LyX-Code class Dog \end_layout \begin_layout LyX-Code def speak! \end_layout \begin_layout LyX-Code \color red puts \color inherit "Bow wow!" \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code Pochi = Dog. \color red new \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code Pochi.speak! \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout LyX-Code class Cat \end_layout \begin_layout LyX-Code def speak! \end_layout \begin_layout LyX-Code puts "Meow" \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code Tama = Cat.new \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code Tama.speak! \end_layout \begin_layout LyX-Code #=> Meow \end_layout \begin_layout Standard These two classes now represent respectively dogs and cats in your irb session. In the code above, you could notice ' \family typewriter new \family default ' method, used to create instances from the defined classes, and ' \family typewriter puts \family default ' method, used to simply print characters on the screen. \end_layout \begin_layout Subsection* Strings, Symbols, Arrays and Hashes \end_layout \begin_layout Standard For \family typewriter YPetri \family default users, it will be especially necessary to learn more about \emph on \color red strings \emph default \color inherit , \emph on \color red symbols \emph default \color inherit , \emph on \color red arrays \emph default \color inherit , \emph on \color red hashes \emph default \color inherit , and how to define and read \emph on \color red closures \emph default \color inherit (aka. \emph on anonymous functions \emph default ). Strings and symbols are among the most basic Ruby objects, while arrays and hashes are important in understanding \emph on \color red argument passing \emph default \color inherit to methods and closures. \series bold \color blue Understanding argument passing and closure writing is essential in using YPetri DSL. \end_layout \begin_layout Subsubsection* Strings \end_layout \begin_layout Standard A string is simply a sequence of characters, which can be defined using single or double quotes ( \family typewriter \color red ' \family default \color inherit or \family typewriter \color red " \family default \color inherit ): \end_layout \begin_layout LyX-Code my_string = 'Hello world!' \end_layout \begin_layout LyX-Code #=> "Hello world!" \end_layout \begin_layout LyX-Code my_string.class \end_layout \begin_layout LyX-Code #=> \color red String \end_layout \begin_layout Standard Strings are mutable (can be changed): \end_layout \begin_layout LyX-Code my_string. \color red object_id \end_layout \begin_layout LyX-Code #=> 81571950 \end_layout \begin_layout LyX-Code 7. \color red times \color inherit \color red do \color inherit my_string. \color red chop! \color inherit \color red end \end_layout \begin_layout LyX-Code #=> 7 \end_layout \begin_layout LyX-Code my_string \end_layout \begin_layout LyX-Code #=> "Hello" \end_layout \begin_layout LyX-Code my_string.object_id \end_layout \begin_layout LyX-Code #=> 81571950 \end_layout \begin_layout Standard Above, you can newly notice \family typewriter times \family default method, \family typewriter do ... end \family default block, and \family typewriter chop! \family default method that removes the last character from \family typewriter my_string \family default 7 times, until only \family typewriter "Hello" \family default remains. But the important thing is that as \family typewriter object_id \family default method shows, \family typewriter my_string \family default is still the same object (same \emph on \color red object id \emph default \color inherit ), although the contents is changed. \end_layout \begin_layout LyX-Code my_string \color red << \color inherit "Pochi!" \end_layout \begin_layout LyX-Code #=> "Hello Pochi!" \end_layout \begin_layout LyX-Code my_string.object_id \end_layout \begin_layout LyX-Code #=> 81571950 \end_layout \begin_layout Standard Again, \family typewriter << \family default operator changed the contents, but the object id remained the same. \end_layout \begin_layout Subsubsection* Symbols \end_layout \begin_layout Standard Unlike strings, symbols are immutable – they never change. They are written with colon ( \family typewriter \color red : \family default \color inherit ): \end_layout \begin_layout LyX-Code :Pochi.class \end_layout \begin_layout LyX-Code #=> \color red Symbol \end_layout \begin_layout Subsubsection* Arrays \end_layout \begin_layout Standard As seen earlier, they can be defined with square brackets \family typewriter [] \family default . Square brackets are also used to address the array elements, counting from 0. \end_layout \begin_layout LyX-Code my_array = [ Pochi, Tama ] \end_layout \begin_layout LyX-Code #=> [#, #] \end_layout \begin_layout LyX-Code my_array[0] \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout Standard Negative numbers can be used to address the elements from the end of the array: \end_layout \begin_layout LyX-Code my_array[-1] \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code my_array[-2] \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout Subsubsection* Hashes \end_layout \begin_layout Standard As for hashes, there are two ways of defining them. The first way uses \emph on \color red Ruby rocket \emph default \color inherit ( \family typewriter \color red => \family default \color inherit ): \end_layout \begin_layout LyX-Code h1 = { Pochi => "dog", Tama => "cat" } \end_layout \begin_layout LyX-Code #=> {#=>"dog", #=>"cat"} \end_layout \begin_layout LyX-Code h1[ Tama ] \end_layout \begin_layout LyX-Code #=> "cat" \end_layout \begin_layout LyX-Code h1[ Pochi ] \end_layout \begin_layout LyX-Code #=> "dog" \end_layout \begin_layout Standard The second way is possible only when the keys are symbols. It is done by shifting the colon to the right side of the symbol: \end_layout \begin_layout LyX-Code h2 = { dog: Pochi, cat: Tama } \end_layout \begin_layout LyX-Code #=> {:dog=>#, :cat=>#} \end_layout \begin_layout LyX-Code h2[:dog] \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout Subsection* Code blocks and Closures \end_layout \begin_layout Standard \emph on \color red Code blocks \emph default \color inherit , or simply \emph on \color red blocks \emph default \color inherit , are pieces of code enclosed by \family typewriter \color red do \family default \color inherit / \family typewriter \color red end \family default \color inherit pair, or by curly brackets \family typewriter \color red {} \family default \color inherit . Code blocks can be passed to methods: \end_layout \begin_layout LyX-Code [1, 2, 3, 4].map \color red { | \color inherit n \color red | \color inherit n + 3 \color red } \end_layout \begin_layout LyX-Code #=> [4, 5, 6, 7] \end_layout \begin_layout LyX-Code my_array. \color red each \color inherit do \color red | \color inherit member \color red | \color inherit member.speak! end \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout LyX-Code Meow \end_layout \begin_layout Standard In the first case, ' \family typewriter map \family default ' method was passed a block specifying addition of 3. In the second case, ' \family typewriter each \family default ' method was passed a block calling \family typewriter speak! \family default method on the array elements. Please note the pipe, or vertical line charecters ( \color red | \color inherit ), that delimit the block arguments (both blocks above happen to have only one argument). Code blocks can be understood as anonymous functions – a way of specifying an operation, when one does not want to write a method for it. Their semantics corresponds to \emph on lambda calculus \emph default . \end_layout \begin_layout Subsubsection* Return values \end_layout \begin_layout Standard Code blocks (and actually, all Ruby statements) have return value. With code blocks, the return value will typically be the last statement: \end_layout \begin_layout LyX-Code [1, 2, 3, 4].map { |v| \end_layout \begin_layout LyX-Code v + 3 # this value will be ignored \end_layout \begin_layout LyX-Code v - 1 # last value of the block will be returned \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code #=> [0, 1, 2, 3] \end_layout \begin_layout Subsubsection* Closures \end_layout \begin_layout Standard A block packaged for future use is called a \emph on \color red closure \emph default \color inherit . Ruby closures come in two flavors: \family typewriter \color red proc \family default \color inherit and \family typewriter \color red lambda \family default \color inherit . They are created by passing a block to the \family typewriter proc \family default / \family typewriter lambda \family default keyword: \end_layout \begin_layout LyX-Code my_proc = \color red proc \color inherit do |organism| organism.speak! end \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code my_lambda = \color red lambda \color inherit do |organism| organism.speak! end \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout Standard Once defined, they can be reused in code. Notice the ampersand ( \family typewriter \color red & \family default \color inherit ) indicating block reuse: \end_layout \begin_layout LyX-Code my_array.each \color red & \color inherit my_proc \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout LyX-Code Meow \end_layout \begin_layout LyX-Code my_array.each &my_lambda \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout LyX-Code Meow \end_layout \begin_layout Standard Closures can also be called alone, a little bit like methods: \end_layout \begin_layout LyX-Code my_proc. \color red call \color inherit ( Pochi ) \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout LyX-Code my_lambda.call( Tama ) \end_layout \begin_layout LyX-Code #=> Meow \end_layout \begin_layout Standard Instead of \family typewriter call \family default keyword, you can just use dot before the parenthesis to call closures: \end_layout \begin_layout LyX-Code my_proc \color red . \color inherit ( Tama ) \end_layout \begin_layout LyX-Code #=> Meow \end_layout \begin_layout LyX-Code my_lambda.( Pochi ) \end_layout \begin_layout LyX-Code #=> Bow wow! \end_layout \begin_layout Standard Differences between \family typewriter proc \family default and \family typewriter lambda \family default closures are minor. For \family typewriter YNelson \family default users, the most noticeable difference will be, that \family typewriter proc \family default less finicky about its arguments than \family typewriter lambda \family default : \end_layout \begin_layout LyX-Code my_proc.( Tama, "garbage" ) \end_layout \begin_layout LyX-Code #=> Meow \end_layout \begin_layout LyX-Code my_lambda.( Tama, "garbage" ) \end_layout \begin_layout LyX-Code #=> ArgumentError: wrong number of arguments (2 for 1) \end_layout \begin_layout Subsection* Passing arguments \end_layout \begin_layout Standard Earlier, we have defined method \family typewriter average \family default , expecting two arguments. If wrong number of arguments is supplied, \family typewriter ArgumentError \family default will ensue: \end_layout \begin_layout LyX-Code average( 3, 5 ) \end_layout \begin_layout LyX-Code #=> 4 \end_layout \begin_layout LyX-Code average( 3, 5, 8 ) \end_layout \begin_layout LyX-Code #=> ArgumentError: wrong number of arguments (3 for 2) \end_layout \begin_layout Standard Obviously, this is not a very nice behavior when it comes to averages. It is a general situation, that when calling more advanced methods, we need to modify their behavior, or pass more complicated structures to them. This is seen eg. with \family typewriter YNelson::Transition \family default constructors, and will be further encountered in \family typewriter YCell \family default and \family typewriter YChem \family default DSLs. Furthermore, \family typewriter YNelson \family default users have to be able to write their own closures, because that is how \emph on functions \emph default of \emph on functional transitions \emph default are specified. In other words, \family typewriter \series bold YNelson \family default users have to master argument passing from both user and programmer side \series default . There is no way around this. With functional Petri nets, one cannot avoid writing functions. It is possible to avoid using \family typewriter YNelson \family default , but it is not possible to avoid learning to write functions. Every simulator of functional Petri nets brings with itself some sort of function language, which one has to learn. With \family typewriter YNelson \family default , this is the language of Ruby closures. \end_layout \begin_layout Subsubsection* Optional arguments \end_layout \begin_layout Standard Arguments with prescribed default value are optional. Let us write an improved \family typewriter average \family default method that can accept either 2 or 3 arguments: \end_layout \begin_layout LyX-Code def average( a, b, c \color red = \color inherit :pochi ) \end_layout \begin_layout LyX-Code \color red # \color inherit If c argument was not given, :pochi symbol will be assigned \end_layout \begin_layout LyX-Code # to c by default. \end_layout \begin_layout LyX-Code \color red if \color inherit c \color red == \color inherit :pochi \color red then \color inherit # only 2 arguments were supplied \end_layout \begin_layout LyX-Code ( a + b ).to_f / 2 \end_layout \begin_layout LyX-Code \color red else \color inherit # 3 arguments were supplied \end_layout \begin_layout LyX-Code ( a + b + c ).to_f / 3 \end_layout \begin_layout LyX-Code \color red end \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code average( 3, 5 ) \end_layout \begin_layout LyX-Code #=> 4 \end_layout \begin_layout LyX-Code average( 3, 5, 8 ) \end_layout \begin_layout LyX-Code #=> 5.333333333333333 \end_layout \begin_layout LyX-Code average( 1, 2, 3, 4 ) \end_layout \begin_layout LyX-Code #=> ArgumentError: wrong number of arguments (4 for 3) \end_layout \begin_layout Standard The default value for \family typewriter c \family default argument is prescribed using single equals sign ( \family typewriter \color red = \family default \color inherit ). Apart from that, you can notice \family typewriter \color red if \family default \color inherit ... \family typewriter \color red then \family default \color inherit ... \family typewriter \color red else \family default \color inherit ... \family typewriter \color red end \family default \color inherit statement, which needs no explanation, equality test (double equals sign, \family typewriter \color red == \family default \color inherit ), used to test whether \family typewriter c \family default contains \family typewriter :pochi \family default symbol (indicating missing value), and comment character (octothorpe aka. sharp, \family typewriter \color red # \family default \color inherit ). Comment character \family typewriter \color red # \family default \color inherit causes all characters until the end of the line to be ignored by Ruby. All code lines, exception the obvious ones, should have comments. \end_layout \begin_layout Subsubsection* Variable-length argument lists \end_layout \begin_layout Standard We will now improve our \family typewriter average \family default method, so that it can calculate averages of any number of arguments. For this, we will use asterisk ( \family typewriter \color red * \family default \color inherit ) syntactic modifier, also known as \emph on splash \emph default . The asterisk will cause a method to collect the arguments into an array. Let's try it out first: \end_layout \begin_layout LyX-Code def examine_arguments( x, \color red * \color inherit aa ) \end_layout \begin_layout LyX-Code puts "x is a \color red #{ \color inherit x.class \color red } \color inherit ." \end_layout \begin_layout LyX-Code puts "aa is #{aa.class} of #{aa.size} elements." \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout Standard Method examine arguments takes one normal argument ( \family typewriter x \family default ), and collects the rest of the arguments into an array ( \family typewriter aa \family default ), thanks to the splash modifier. (Apart from that, you can notice string interpolation using \family typewriter #{ ... } \family default notation in the above code.) Then it prints the class of \family typewriter x \family default , class of \family typewriter aa \family default (which should be an array), and the number of elements after \family typewriter x \family default . \end_layout \begin_layout LyX-Code examine_arguments( 1 ) \end_layout \begin_layout LyX-Code #=> x is a Fixnum. \end_layout \begin_layout LyX-Code aa is Array of 0 elements. \end_layout \begin_layout LyX-Code nil \end_layout \begin_layout LyX-Code examine_arguments( :hello, :pochi, 3, 5, "garbage" ) \end_layout \begin_layout LyX-Code #=> x is a Symbol. \end_layout \begin_layout LyX-Code aa is Array of 4 elements. \end_layout \begin_layout LyX-Code nil \end_layout \begin_layout Standard With this, we can go on to define our improved average method: \end_layout \begin_layout LyX-Code def average( *aa ) \end_layout \begin_layout LyX-Code aa. \color red reduce( :+ ) \color inherit .to_f / aa.size \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code average 3, 5, 7, 11 \end_layout \begin_layout LyX-Code #=> 6.5 \end_layout \begin_layout Standard You can also newly notice \family typewriter reduce( :+ ) \family default method, used to calculate the sum of the \family typewriter aa \family default array. To also practice closures, let us define a lambda doing the same as the \family typewriter average \family default method above: \end_layout \begin_layout LyX-Code avg = lambda { |*aa| aa.reduce( :+ ).to_f / aa.size } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code avg.( 11, 7, 5, 3 ) \end_layout \begin_layout LyX-Code #=> 6.5 \end_layout \begin_layout Subsubsection* Named arguments \end_layout \begin_layout Standard The main purpose of named arguments is to make the interface (or DSL) easier to remember, and the code easier to read. Easy-to-read code is a crucial requirement for scalable development. In Ruby methods, named arguments can be specified \color red as hash pairs in the method call \color inherit : \end_layout \begin_layout LyX-Code def density( length: 1, width: 1, height: 1, weight: 1 ) \end_layout \begin_layout LyX-Code weight.to_f / ( length * width * height ) \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code #=> nil \end_layout \begin_layout LyX-Code density( length: 2, width: 2, height: 2, weight: 10 ) \end_layout \begin_layout LyX-Code #=> 1.25 \end_layout \begin_layout Standard The above method calculates mean density of boxes of certain height, width, length and weight. Double splash ( \family typewriter \color red ** \family default \color inherit ) can be used to collect all the options in a hash. Let's use it to define a closure that does exactly the same thing as the method \family typewriter density \family default we have just defined, in a slightly different way: \end_layout \begin_layout LyX-Code dens_closure = \color red -> \color inherit **nn do \end_layout \begin_layout LyX-Code nn[:weight].to_f / ( nn[:length] * nn[:width] * nn[:height] ) end \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code dens_closure.( length: 2, width: 2, height: 2, weight: 10 ) \end_layout \begin_layout LyX-Code #=> 1.25 \end_layout \begin_layout Standard Above, note the alternative syntax for lambdas: \family typewriter -> arg do ... end \family default is the same as \family typewriter lambda do |arg| ... end \family default . Having hereby introduced the named arguments, let us notice hash-collecting behavior for square bracket ( \family typewriter [] \family default ) array constructor syntax. \end_layout \begin_layout Subsubsection* Hash-collecting behavior of square brackets \end_layout \begin_layout Standard In more complicated method argument structures, it can be advantageous to take use of the hash-collecting by square brackets. It is normal for curly braces to create hashes: \end_layout \begin_layout LyX-Code h = { length: 2, width: 3, height: 4 } \end_layout \begin_layout LyX-Code #=> {:length=>2, :width=>3, :height=>4} \end_layout \begin_layout LyX-Code h.class \end_layout \begin_layout LyX-Code #=> Hash \end_layout \begin_layout Standard However, square brackets, that generally create arrays, are also \color red able to collect hashes just like the argument fields with named arguments \color inherit : \end_layout \begin_layout LyX-Code a0 = [ 1, 2, 3 ] \end_layout \begin_layout LyX-Code #=> [1, 2, 3] \end_layout \begin_layout LyX-Code a0.class \end_layout \begin_layout LyX-Code #=> Array \end_layout \begin_layout LyX-Code a1 = [ 1, 2, 3, length: 2, width: 3, height: 4 ] \end_layout \begin_layout LyX-Code #=> [1, 2, 3, {:length=>2, :width=>3, :height=>4}] \end_layout \begin_layout LyX-Code a1.class \end_layout \begin_layout LyX-Code #=> Array \end_layout \begin_layout LyX-Code a1.map &:class \end_layout \begin_layout LyX-Code #=> [Fixnum, Fixnum, Fixnum, Hash] \end_layout \begin_layout LyX-Code a1[-1] \end_layout \begin_layout LyX-Code #=> {:length=>2, :width=>3, :height=>4} \end_layout \begin_layout Standard In other words, if there are any trailing \family typewriter key / value \family default pairs inside square brackets, they will be collected into a hash, which will become the last element of the array. This possibility to mix ordered elements with \family typewriter key / value \family default pairs is used eg. in \family typewriter YCell \family default \family typewriter enzyme \family default constructor method. \end_layout \begin_layout Subsection* Arity \end_layout \begin_layout Standard Every closure and every method has arity, which is basically the number of input arguments. (Closures with 0 arguments are null \emph on ary \emph default , with 1 argument un \emph on ary \emph default , with 2 arguments bin \emph on ary \emph default , with 3 arguments tern \emph on ary \emph default etc. – therefrom \emph on arity \emph default .) \end_layout \begin_layout LyX-Code doubler = lambda { |a| a * 2 } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code doubler.call( 3 ) \end_layout \begin_layout LyX-Code #=> 6 \end_layout \begin_layout LyX-Code doubler.arity \end_layout \begin_layout LyX-Code #=> 1 \end_layout \begin_layout LyX-Code adder = lambda { |p, q| p + q } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code adder.call( 5, 6 ) \end_layout \begin_layout LyX-Code #=> 11 \end_layout \begin_layout LyX-Code adder.arity \end_layout \begin_layout LyX-Code #=> 2 \end_layout \begin_layout LyX-Code scaler = lambda { |number, p, q| number * (q / p) } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code scaler.call( 10, 2, 3 ) \end_layout \begin_layout LyX-Code #=> 15 \end_layout \begin_layout LyX-Code scaler.arity \end_layout \begin_layout LyX-Code #=> 3 \end_layout \begin_layout LyX-Code constant_function = lambda { 42 } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code constant_function.call \end_layout \begin_layout LyX-Code #=> 42 \end_layout \begin_layout LyX-Code constant_function.arity \end_layout \begin_layout LyX-Code #=> 0 \end_layout \begin_layout Standard Closures / methods with variable length arguments indicate this by reporting negative arity: \end_layout \begin_layout LyX-Code summation = lambda { |*array| array.reduce( :+ ) } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code summation.call( 1, 2, 3, 4 ) \end_layout \begin_layout LyX-Code #=> 10 \end_layout \begin_layout LyX-Code summation.arity \end_layout \begin_layout LyX-Code #=> -1 \end_layout \begin_layout LyX-Code array_scale = lambda { |*a, coeff| a.map { |e| e * coeff } } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code array_scale.call( 1, 2, 3, 4, 7 ) \end_layout \begin_layout LyX-Code #=> [7, 14, 21, 28] \end_layout \begin_layout LyX-Code array_scale.arity \end_layout \begin_layout LyX-Code #=> -2 \end_layout \begin_layout Subsection* Return value \end_layout \begin_layout Standard The last statement in a closure / method becomes the return value. In methods and lambda-type closures, return statement can also be used explicitly: \end_layout \begin_layout LyX-Code divider = lambda { |u, v| \end_layout \begin_layout LyX-Code if v == 0 then \end_layout \begin_layout LyX-Code return :division_by_zero # explicit return statement \end_layout \begin_layout LyX-Code end \end_layout \begin_layout LyX-Code u / v # implicit return value - last statement of the closure \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code divider.call( 15, 3 ) \end_layout \begin_layout LyX-Code #=> 5 \end_layout \begin_layout LyX-Code divider.call( 15, 0 ) \end_layout \begin_layout LyX-Code #=> :division_by_zero \end_layout \begin_layout LyX-Code experimental_closure = proc { \end_layout \begin_layout LyX-Code 1 # this value will be ignored \end_layout \begin_layout LyX-Code 3 # this value will be ignored, too \end_layout \begin_layout LyX-Code 42 # this value will be discarded as well \end_layout \begin_layout LyX-Code 41 } # this value will be returned \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code experimental_closure.call \end_layout \begin_layout LyX-Code #=> 41 \end_layout \begin_layout LyX-Code experimental_lambda = lambda { \end_layout \begin_layout LyX-Code 1 # this value will be ignored \end_layout \begin_layout LyX-Code return 3 # this value will be returned \end_layout \begin_layout LyX-Code 7 # execution will never get here at all \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code experimental_lambda.call \end_layout \begin_layout LyX-Code #=> 3 \end_layout \begin_layout Subsection* Return value arity \end_layout \begin_layout Standard It is possible to return more than one value. For example: \end_layout \begin_layout LyX-Code multiplication_table = lambda { |number| \end_layout \begin_layout LyX-Code [1, 2, 3, 4, 5] \end_layout \begin_layout LyX-Code .map { |element| element * number } \end_layout \begin_layout LyX-Code } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout Standard This method returns 5 values. We can receive them by using a simultaneous assignment statement: \end_layout \begin_layout LyX-Code by_one, by_two, by_three, by_four, by_five = multiplication_table.call( 7 ) \end_layout \begin_layout LyX-Code #=> [7, 14, 21, 28, 35] \end_layout \begin_layout LyX-Code by_one \end_layout \begin_layout LyX-Code #=> 7 \end_layout \begin_layout LyX-Code by_two \end_layout \begin_layout LyX-Code #=> 14 \end_layout \begin_layout LyX-Code by_five \end_layout \begin_layout LyX-Code #=> 35 \end_layout \begin_layout Standard Or we can simply collect them in an array: \end_layout \begin_layout LyX-Code collection = multiplication_table.( 3 ) \end_layout \begin_layout LyX-Code #=> [3, 6, 9, 12, 15] \end_layout \begin_layout Standard In \family typewriter YNelson \family default , it sometimes becomes necessary to write closures with higher return arity (returning more than one value). This is normally done by returning an array. Also, lambda return statement can be used to return multiple values: \end_layout \begin_layout LyX-Code constant_vector = lambda { return 1, 2, 3 } \end_layout \begin_layout LyX-Code #=> # \end_layout \begin_layout LyX-Code x, y, z = constant_vector.call \end_layout \begin_layout LyX-Code #=> [1, 2, 3] \end_layout \begin_layout LyX-Code x \end_layout \begin_layout LyX-Code #=> 1 \end_layout \begin_layout LyX-Code y \end_layout \begin_layout LyX-Code #=> 2 \end_layout \begin_layout LyX-Code z \end_layout \begin_layout LyX-Code #=> 3 \end_layout \end_body \end_document