My guiding light is Kent Beck's rules of Simple Design (източник):
- The code must first be correct (as defined by tests);
- then it should be a clear statement of the design (what J.B.Rainsberger calls "no bad names");
- then it should contain no duplication (of text, of ideas, or of responsibility);
- and finally it must be the smallest code that meets all of the above.
It's time to stop refactoring when the code makes a reasonable stab at meeting those goals, and when any further changes would add no further benefit.
if/elsif/elsif/elsif/else
Кои от следните стойности ще се оценят до истина?
true
""
nil
[]
:baba
nil
.Какво ще изведе на екрана следната програма:
life_gives_you = 'lemons'
make = life_gives_you
make[5] = 'a'
make << 'de'
puts "When life gives you #{life_gives_you}"
puts "Make #{make}"
When life gives you lemonade
Make lemonade
По какво се различават имената в следните три реда:
variable = 1
Variable = 1
$variable = 1
if !foo
bar
elsif baz
qux
else
norf
end
bar if not foo
bar unless foo
def max(a, b)
a > b ? a : b
end
max(1, 5) # => 5
В Ruby всичко може да се разглежда като израз, който си има оценка (стойност).
42 # => 42
x = 'files' # => "files"
def foo() end # => :foo
В Ruby има четири оператора за равенство
one == two # сравнява по стойност
one === two # специален оператор, който се използва в case
one.eql? two # сравнява по стойност и тип
one.equal? two # връща true, само ако one и two са един и същ обект
Досега говорихме за:
String
)
Integer
) и с плаваща запетая (Float
)
TrueClass
, FalseClass
NilClass
Bignum
(core)
BigDecimal
(stdlib)
Rational
Complex
Това малко ще се промени в Ruby 2.4
Rational
Rational(a, b)
или с литерален синтаксис (само в 2.1+): 0.1r
И такъв вграден тип има, Complex
(документация):
Complex(1) # => (1+0i)
Complex(2, 3) # => (2+3i)
Complex('0.3-0.5i') # => (0.3-0.5i)
Complex('2/3+3/4i') # => ((2/3)+(3/4)*i)
3.to_c # => (3+0i)
0.3.to_c # => (0.3+0i)
'0.3-0.5i'.to_c # => (0.3-0.5i)
'2/3+3/4i'.to_c # => ((2/3)+(3/4)*i)
'1@2'.to_c # => (-0.4161468365471424+0.9092974268256817i)
Колко от вас са запознати със следните неща:
map
и filter
Минимално необходимо знание за всеки програмист. Поставете си го за цел.
Един обект се обръща до низ с #to_s
. Има и друг вариант, #inspect
,
който го обръща до текстов низ, изглеждащ като ruby код. Целта е инспектиране.
puts(something)
извежда something.to_s
p(something)
извежда something.inspect
#
е коментар
#puts
, Array#inject
"The answer: #{40 + 2}"
C#
Array
. Разбира се, има литерален синтаксис
[1, 2, 3, 4]
[18, :female, 'Burgas']
numbers = [:zero, :one, :two]
numbers[1] # => :one
numbers[10] # => nil
numbers[-1] # => :two
numbers[5] = :five
numbers[5] # => :five
numbers # => [:zero, :one, :two, nil, nil, :five]
Array#fetch
хвърля грешка или връща друга стойност при индексиране извън обема на масива:
numbers = [:zero, :one, :two]
numbers.fetch(1) # => :one
numbers.fetch(10) # => error: IndexError
numbers.fetch(10) { |n| puts "#{n} isn't in array" } # вместо IndexError, се изпълнява кодът между { }
numbers.fetch(10, :dunno) # => :dunno
numbers[10] or :dunno # като предното, ама не точно
Ползва се по-рядко, отколкото си мислите.
numbers = [3, 1, 2, 4]
numbers.length # => 4
numbers.size # => 4
numbers.sort # => [1, 2, 3, 4]
numbers.reverse # => [4, 2, 1, 3]
numbers[1..2] # => [1, 2]
sort
и reverse
връщат нов масив, без да променят numbers
.
#include?
ви казва дали масив съдържа даден елемент.
prime_digits = [2, 3, 5, 7]
prime_digits.include? 2 # => true
prime_digits.include? 4 # => false
Внимание: линейно търсене. Подходящо за малки списъци.
[:a, :b, :c] + [:d, :e] # => [:a, :b, :c, :d, :e]
[:a, :b, :c, :b, :a] - [:b, :c, :d] # => [:a, :a]
[:a, :b, :c] & [:b, :c, :d] # => [:b, :c]
[:a, :b, :c] | [:b, :c, :d] # => [:a, :b, :c, :d]
&
и |
конкатенират списъците и премахват повторенията.
В Ruby има множества, които са по-удачни в повечето случаи.
numbers = [1, 2, 3]
numbers << 4
p numbers # => [1, 2, 3, 4]
numbers.insert 0, :zero
p numbers # => [:zero, 1, 2, 3, 4]
result = numbers.delete_at(0)
p result # => :zero
p numbers # => [1, 2, 3, 4]
stack = [1, 2, 3]
stack.push 4
p stack # => [1, 2, 3, 4]
top = stack.pop
p stack # => [1, 2, 3]
p top # => 4
#shift
и #unshift
са аналогични, но работят с началото на масива.
[1, 2, 3].join("-") # => "1-2-3"
[1, 2, 3].permutation # сещате се какво връща
[1, 2].product([3, 4]) # => [[1, 3], [1, 4], [2, 3], [2, 4]]
[[1, 2], [3, 4]].transpose # => [[1, 3], [2, 4]]
[1, 2, 3, 4].shuffle # разбърква масива произволно
Има редица такива методи, които може да намерите в Ruby Doc.
Може да оставите запетая след последния елемент на масива. Така редовете се разместват по-лесно. Важи и за хешове.
songs = [
'My Favorite Things',
'Alabama',
'A Love Supreme',
]
Има специален синтаксис за масив от думи.
%w(chunky bacon) == ['chunky', 'bacon']
%w[a b c] == ['a', 'b', 'c']
%w{cool stuff} == ['cool', 'stuff']
%w<coffee tea water> == ['coffee', 'tea', 'water']
%w|foo bar| == ['foo', 'bar']
Може да използвате различни видове символи, които да ограждат думите от масива:
! @ # $ * - _
Този списък от символи е непълен.
slice
(документация)
[]
е всъщност метод на Array
, който е синоним на slice
[]=
от своя страна позволява и да променяте въпросните отрязъци от масиваnumbers = [1, 2, 3, 4, 5, 6]
numbers[0..2] # => [1, 2, 3]
numbers[-3..-1] # => [4, 5, 6]
numbers[1, 1] # => [2]
numbers[0..2] = [:wat]
numbers # => [:wat, 4, 5, 6]
Итерира се с #each
, както всичко останало в Ruby:
primes = [2, 3, 5, 7, 11]
primes.each { |n| puts n }
primes.each do |n|
puts n
end
for
#each
do
/end
се ползва, когато блокът е няколко редаHash
, но има и литерален синтаксис – {}
{1 => :one, 2 => :two}
numbers = {:one => :eins, :two => :zwei}
numbers[:one] # => :eins
numbers[:three] # => nil
numbers[:three] = :drei
numbers[:three] # => :drei
numbers.fetch(:four, :keine_ahnung) # => :keine_ahnung
numbers.fetch(:four) # => error: KeyError
numbers = {:one => :eins, :two => :zwei}
numbers.keys # => [:one, :two]
numbers.values # => [:eins, :zwei]
numbers.each { |pair| puts pair }
numbers.each { |key, value| puts key, value }
numbers = {1 => 2, 3 => 4}
numbers.key?(:three) # => false
numbers.size # => 2
numbers.invert # => {2=>1, 4=>3}
numbers.merge({5 => 6}) # => {1=>2, 3=>4, 5=>6}
numbers.to_a # => [[1, 2], [3, 4]]
Hash[1, 2, 3, 4] # => {1=>2, 3=>4}
Долните два реда произвеждат еднакви хешове. Второто е 1.9+ синтаксис и ще предпочитаме него по конвенция (когато може):
{:one => 1, :two => 2}
{one: 1, two: 2}
Има интересна врътка при извикването на методи, за която ще споменем малко по-натам.
Enumerable
)