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 not 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
)
Fixnum
) и с плаваща запетая (Float
)
TrueClass
, FalseClass
NilClass
Bignum
(core)
BigDecimal
(stdlib)
Rational
Complex
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
)