08. Паралелно присвояване, case, интроспекция, require и още

08. Паралелно присвояване, case, интроспекция, require и още

08. Паралелно присвояване, case, интроспекция, require и още

5 ноември 2012

Днес

case

В Ruby има "switch". Казва се case.

def quote(name)
  case name
    when 'Yoda'
      puts 'Do or do not. There is no try.'
    when 'Darth Vader'
      puts 'The Force is strong with this one.'
    when 'R2-D2'
      puts 'Beep. Beep. Beep.'
    else
      puts 'Dunno what to say'
  end
end

case

особености

case

алтернативен синтаксис

case operation
  when :& then puts 'And?'
  when :| then puts 'Or...'
  when :! then puts 'Not!'
end

case

връщана стойност

На какво ще се оцени следният код?

case 'Wat?'
  when 'watnot' then puts "I'm on a horse."
end

Ако няма else и никой when не match-не, се връща nil.

case

стойности

case не сравнява с ==. Може да напишете следното.

def qualify(age)
  case age
    when 0..12
      'still very young'
    when 13..19
      'a teenager! oh no!'
    when 33
      'the age of jesus'
    when 90..200
      'wow. that is old!'
    else
      'not very interesting'
    end
end

case

Object#===

case сравнява с ===. Няколко класа го имплементират:

case

Class#===

def qualify(thing)
  case thing
    when Integer then 'this is a number'
    when String then 'it is a string'
    when Array then thing.map { |item| qualify item }
    else 'huh?'
  end
end

case

Range#===

case hours_of_sleep
  when 8..10 then 'I feel fine.'
  when 6...8 then 'I am a little sleepy.'
  when 1..3  then 'OUT OF MY WAY! I HAVE PLACES TO BE AND PEOPLE TO SEE!'
end

case

Regexp#===

def parse_date(date_string)
  case date_string
    when /(\d{4})-(\d\d)-(\d\d)/
      Date.new $1.to_i, $2.to_i, $3.to_i
    when /(\d\d)\/(\d\d)/(\d{4})/
      Date.new $3.to_i, $1.to_i, $2.to_i
  end
end

case

с обикновени условия

thing = 42
case
  when thing == 1 then 1
  else 'no_idea'
end

Въпроси по case

Сега е моментът.

Присвояване в Ruby

Паралелно присвояване

прост пример

a, b = 1, 2
a              # 1
b              # 2

a, b = b, a
a              # 2
b              # 1

Има няколко различни случая, които ще разгледаме.

Паралелно присвояване

присвояване на една променлива

a = 1, 2, 3
a # [1, 2, 3]

Практически същото като a = [1, 2, 3]

Паралелно присвояване

разпакетиране на дясната страна

a, b = [1, 2, 3]
a # 1
b # 2

a, b = 1, 2, 3
a # 1
b # 2

Паралелно присвояване

със splat аргументи

head, *tail = [1, 2, 3]
head   # 1
tail   # [2, 3]

first, *middle, last = 1, 2, 3, 4
first  # 1
middle # [2, 3]
last   # 4

Паралелно присвояване

splat аргументи отдясно

first, *middle, last = 1, [2, 3, 4]
first  # 1
middle # []
last   # [2, 3, 4]

first, *middle, last = 1, *[2, 3, 4]
first  # 1
middle # [2, 3]
last   # 4

Вложено присвояване

head, (title, body) = [1, [2, 3]]
head   # 1
title  # 2
body   # 3

Вложено присвояване и splat-ове

head, (title, *sentences) = 1, [2, 3, 4, 5, 6]
head      # 1
title     # 2
sentences # [3, 4, 5, 6]

Ред на оценка

Бележка за реда на оценка при присвояване — първо отдясно, след това отляво:

x = 0
a, b, c = x, (x += 1), (x += 1)
x # 2
a # 0
b # 1
c # 2

Променливата _

Променливата _

Може да ползвате едно име само един път, когато то се среща в списък с параметри на метод, блок и прочее.

Proc.new { |a, b, a| } # SyntaxError: duplicated argument name
Proc.new { |_, b, _| } # => #<Proc:0x007f818af68de0@(irb):23>

Горното важи не само за блокове, но и за методи.

Присвояване в Ruby

Къде важат тези правила?

[[1, [2, 3]], [4, [5, 6]], [7, [8, 9]]].each do |a, (b, c)|
  puts "#{a}, #{b}, #{c}"
end
# 1, 2, 3
# 4, 5, 6
# 7, 8, 9

Присвояване в Ruby

Имате ли въпроси по тази тема?

Импортиране на файлове

В Ruby, код от други файлове се импортира с require.

Например:

require 'bigdecimal'
require 'bigdecimal/util'

Какво търси require?

Зареждане на файлове от текущата директория

Зареждане на файлове от текущата директория

require_relative

Load path

където Ruby търси файлове за require

Как работи require?

Типичната структура на един gem

skeptic опростен

.
├── README.rdoc
├── Rakefile
├── bin
│   └── skeptic
├── features
├── lib
│   ├── skeptic
│   │   ├── rules.rb
│   │   └── scope.rb
│   └── skeptic.rb
├── skeptic.gemspec
└── spec 

Особеностите

Останалите неща

Kernel#load

Замразяване на обекти в Ruby

Замразяване на обекти

module Entities
  ENTITIES = {
    '&' => '&amp;',
    '"' => '&quot;',
    '<' => '&lt;',
    '>' => '&gt;',
  }.freeze

  ENTITY_PATTERN = /#{ENTITIES.keys.join('|')}/.freeze

  def escape(text)
    text.gsub ENTITY_PATTERN, ENTITIES
  end
end

Въпроси