Песочница 3
Материал из Wiki.crossplatform.ru
BEGIN END __ENCODING__ __END__ __FILE__ __LINE__ alias and begin break case class def defined? do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield
BEGIN
puts "This is main Ruby Program" BEGIN { puts "Initializing Ruby Program" }
Initializing Ruby Program. This is main Ruby Program
Иногда используется для имитации предварительных ссылок на методы.
puts times_3(gets.to_i) BEGIN { def times_3(n) n * 3 end }
END { puts "Bye!" }
DATA.each do |line| first, last, phone, email = line.split('|') puts <<-EOM First name: #{first} Last name: #{last} Phone: #{phone} Email: #{email} EOM end __END__ David|Black|123-456-7890|dblack@... Someone|Else|321-888-8888|someone@else
Вывод:
First name: David Last name: Black Phone: 123-456-7890 Email: dblack@... First name: Someone Last name: Else Phone: 321-888-8888 Email: someone@else
class Person def name=(name) puts "Naming your person #{name}!" @name = name end alias full_name= name= end p = Person.new p.name = "David" # Naming your person David! class Person def name=(name) puts "Please use full_name=" end end p.full_name = "David" # Please use fullname=
puts "Hello" and "Goodbye"
the subexpression puts "Hello" is executed first, and returns nil. The whole expression thus reduces to:
nil and "Goodbye"
which reduces to nil. In this example, however:
puts "Hello" && "Goodbye"
begin i += 1 puts i end until i == 10
result = File.open("lines.txt") do |fh| fh.each do |line| break line if my_regex.match(line) end nil end
A case statement can end with an else clause. Each when statement can have multiple candidate values, separated by commas.
case x when 1,2,3 puts "1, 2, or 3" when 10 puts "10" else puts "Some other number" end
Case equality (success by a when candidate) is determined by the case-equality or "threequal" operator, ===. The above example is equivalent to:
if 1 === x or 2 === x or 3 === x puts "1, 2, or 3" elsif 10 === x puts "10" else puts "Some other number" end
Classes may be opened more than once, and methods and constants added during those subsequent openings. class blocks have their own local scope; local variables in scope already are not visible inside the block, and variables created inside the block do not survive the block.
class Person def name=(name) @name = name end end david = Person.new class << david def name=(name) if name == "David" @name = name else puts "Please don't name me other than David!" end end end david.name = "Joe" # Please don't name me other than David!" joe = Person.new joe.name = "Joe"
Inside a class block, self is set to the class object whose block it is. Thus it‘s possible to write class methods (i.e., singleton methods on class objects) by referring to self:
class Person def self.species "Homo sapiens" end end
def can be used either with or without a specific object:
- def method_name
- def object.singleton_method_name
Note that the expression is not executed.
p defined?(def x; end) # "expression" x # error: undefined method or variable p defined?(@x=1) # "assignment" p @x # nil
Assignment to a local variable will, however, have the usually result of initializing the variable to nil by virtue of the assignment expression itself:
p defined?(x=1) # assignment p x # nil
In most cases, the argument to defined? will be a single identifier:
def x; end p defined?(x) # "method"
array.each do |element| puts element * 10 end
In this context, do/end is equivalent to curly braces, except that curly braces have higher precedence. In this example:
puts [1,2,3].map {|x| x * 10 }
the code block binds to map; thus the output is:
10 20 30
In this version, however:
puts [1,2,3].map do |x| x * 10 end
begin 1/0 rescue ZeroDivisionError puts "Can't do that!" ensure puts "That was fun!" end
Output:
Can't do that! That was fun!
If the statement 1/0 is changed to something harmless, like 1/1, the rescue clause will not be executed but the ensure clause still will. false
false denotes a special object, the sole instance of FalseClass. false and nil are the only objects that evaluate to Boolean falsehood in Ruby (informally, that cause an if condition to fail.)
for a in [1,2,3,4,5] do puts a * 10 end
for is generally considered less idiomatic than each; indeed, for calls each, and is thus essentially a wrapper around it.
obj = Object.new def obj.each yield 1; yield 2 end for a in obj puts a end
prints:
1 2
The do keyword may optionally appear at the end of the for expression:
for a in array do # etc.
if m.score > n.score puts "m wins!" elsif n.score > m.score puts "n wins!" else puts "Tie!" end
An if statement can have more than one elsif clause (or none), but can only have one else clause (or none). The else clause must come at the end of the entire statement.
if can also be used in modifier position:
puts "You lose" if y.score < 10
then may optionally follow an if condition:
if y.score.nil? then puts "Have you even played the game?" end
[0,1,2,3,4].each do |n| next unless n > 2 puts "Big number: #{n}" end
Output:
Big number: 3 Big number: 4
next is typically used in cases like iterating through a list of files and taking action (or not) depending on the filename.
next can take a value, which will be the value returned for the current iteration of the block.
sizes = [0,1,2,3,4].map do |n| next("big") if n > 2 puts "Small number detected!" "small" end p sizes
Output:
Small number detected! Small number detected! Small number detected!["small", "small", "small", "big", "big"]
not true # false not 10 # false not false # true
Similar in effect to the negating bang (!), but has lower precedence:
not 3 == 4 # true; interpreted as not (3 == 4) !3 == 4 # false; interpreted as (!3) == 4, i.e., false == 4
By default, rescue only intercepts StandardError and its descendants, but you can specify which exceptions you want handled, as arguments. (This technique does not work when rescue is in statement-modifier position.) Moreover, you can have more than one rescue clause, allowing for fine-grained handling of different exceptions.
In a method (note that raise with no argument, in a rescue clause, re-raises the exception that‘s being handled):
def file_reverser(file) File.open(file) {|fh| puts fh.readlines.reverse } rescue Errno::ENOENT log "Tried to open non-existent file #{file}" raise end
In a begin/end block:
begin 1/0 rescue ZeroDivisionError puts "No way" end
In statement-modifier position:
while true 1/0 end rescue nil david = Person.find(n) rescue Person.new
rescue (except in statement-modifier position) also takes a special argument in the following form:
rescue => e
a = 0 begin 1/a rescue ZeroDivisionError => e puts e.message puts "Let's try that again..." a = 1 retry end puts "That's better!"
def three return 3 ensure puts "Enjoy the 3!" end a = three # Enjoy the 3! puts a # 3
Inside a code block, the behavior of return depends on whether or not the block constitutes the body of a regular Proc object or a lambda-style Proc object. In the case of a lambda, return causes execution of the block to terminate. In the case of a regular Proc, return attempts to return from the enclosing method. If there is no enclosing method, it‘s an error.
ruby -e 'Proc.new {return}.call' => -e:1:in `block in <main>': unexpected return (LocalJumpError)
ruby19 -e 'p lambda {return 3}.call' => 3
- In a method, the object on which the method was called is self
- In a class or module definition (but outside of any method definition contained therein), self is the class or module object being defined.
- In a code block associated with a call to class_eval (aka module_eval), self is the class (or module) on which the method was called.
- In a block associated with a call to instance_eval or instance_exec, self is the object on which the method was called.
self automatically receives message that don‘t have an explicit receiver:
class String def upcase_and_reverse upcase.reverse end end
module Vehicular def move_forward(n) @position += n end end class Vehicle include Vehicular # Adds Vehicular to the lookup path end class Car < Vehicle def move_forward(n) puts "Vrooom!" super # Calls Vehicular#move_forward end end
Called with no arguments and no empty argument list, super calls the appropriate method with the same arguments, and the same code block, as those used to call the current method. Called with an argument list or arguments, it calls the appropriate methods with exactly the specified arguments (including none, in the case of an empty argument list indicated by empty parentheses).
then
Optional component of conditional statements (if, unless, when). Never mandatory, but allows for one-line conditionals without semi-colons. The following two statements are equivalent:
if a > b; puts "a wins!" end if a > b then puts "a wins!" end
class C def m "Hi" end end class D < C end class E < D end class D undef m end C.new.m # Hi D.new.m # error E.new.m # error
unless y.score > 10 puts "Sorry; you needed 10 points to win." end
when
See case.
i = 0 while i < 10 i += 1 end
The value of the whole while statement is the value of the last expression evaluated the last time through the code. If the code is not executed (because the condition is false at the beginning of the operation), the while statement evaluates to nil.
while can also appear in modifier position, either in a single-line statement or in a multi-line statement using a begin/end block. In the one-line case:
i = 0 i += 1 while i < 10
the leading code is not executed at all if the condition is false at the start. However, in the "begin"-block case:
i = 0 begin i += 1 puts i end while i < 10
__NOTOC__