Рубрики
Лекции mail.ru Лекция 5

Лекция 5. Особенности использования языка Ruby

0:27 — введение в функциональное программирование
4:35 — блоки
9:04 — класс Proc и Lambda
18:09 — функциональный стиль
31:41 — отложенные вычисления (lazy-объект)
41:27 — цепочка вызовов методов
43:10 — метод map/collect
44:00 — метод select
45:09 — метод inject/reduce
46:55 — метод #tap
48:11 — метод #yield_self
49:37 — библиотека dry-rb
54:05 — примеры решения задач
58:18 — полезные особенности Ruby
59:16 — генерация методов с помощью define_method
1:01:10 — пример кода с неизвестными методами
1:04:00 — Domain Specific Language (DSL)
1:07:20 — область применения Ruby
1:08:52 — скрипты администрирования
1:10:28 — управление развертыванием приложений
1:13:33 — мониторинг сервисов в распределенной системе
1:14:17 — создание «настольных» приложений
1:14:53 — тестирование приложений
1:22:10 — научные вычисления
1:23:03 — прототипирование протоколов взаимодействия
1:23:51 — Ruby-подобные языки программирования
1:25:41 — полезные ссылки

name_lenght = ['bethoven', 'mike', 'mic', 'michel'].inject(0) do |accumulator, dog_name| 
  accumulator += dog_name.length
end
puts name_lenght

# 21Code language: Ruby (ruby)

Ruby не является истинным языком функционального программирования

Он является — объектным, императивным с функциональным стилем

Императивный стиль — написание отдельного действия, которое тут же выполняется. Императив — приказ

В функциональном программировании, принципиально другой подход. Хранится не состояние, а функция.

Функция в основе всего
● Функция может быть аргументом другой функции
● Хранится не состояние программы, а функции и аргументы
● Значения неизменны. Новое значение – новое имя
● Функции должны быть чистыми

Достоинства функционального программирования:

● Компактный код
● Упрощение модульного тестирования
● Отложенные вычисления
● Распараллеливание без участия программиста

Одно из требований к языкам функционального программирование — возможность выполнить операции над функцией до того как были выполнены операции над значениями.

Пример. x2 / x

В императивном стиле. Если у нас значение 0 то мы должны честно возвести в квадрат и разделить на 0

В функциональном стиле есть функции есть возводящие в квадрат переменную и функция деления на 0. Мы можем сделать преобразования в этих функциях которые уберут необходимость делить на 0. То есть позволяет устранить проблемы до того как мы приступили к обработке данных.
Мы можем передать функцию (с условиями которые нам нужны) в качестве параметра другой функции или с помощью yield

Блок по сути экземпляры класса proc

Proc — сохраненный код, который можно вызывать где то еще

Объект как код для выполнения

a = Proc.new { |name| puts "Hello, #{name}!" }
a.call 'world' # => Hello, world!Code language: Ruby (ruby)

Результат выполнения = результат последней
операции

b = Proc.new { |x| x * x }
c = b.call 4
puts c # 16Code language: Ruby (ruby)

Proc:lambda

Proc:lambda — Возможность записать функцию в компактной форме (Объект как функция)

# Компактная форма записи
p a = ->(x) { x * x }
p a.call 2 # получим 4

# Традиционная форма записи
p b = lambda { |x| x + x }
p b.call 3 # получим 6Code language: Ruby (ruby)

lambda vs Proc

# Proc – контейнер кода 
def proc_test
  Proc.new { puts 'proc'; return }.call
  puts 'proc_test end' # сюда не попадаем никогда!
end
proc_test # => proc

# Код внутри lambda изолирован 
def lambda_test
  ->{ puts 'lambda'; return }.call 
  puts 'lambda_test end'
end
lambda_test # => lambda
# lambda_test endCode language: Ruby (ruby)

Когда мы вставляем в метод объект proc. Это равносильно если бы просто написали этот код в методе. Например если мы напишем в методе return то мы выйдем из этой ф-и, если мы передадим с помощью proc, то результат будет такой же.
Lambda не влияет на работу функции в которую она вставлена. Если мы передадим return с помощью lambda, то это вернет значение но не остановит выполнение остальной части ф-и в которую мы вставили эту lamdba

some_func = ->(x) do 
  x + 3
end # lambda

def d(just_param, x)
  just_param.call(x) * just_param.call(x)
end

puts d(some_func, 7)
# 100Code language: Ruby (ruby)
a = -> (x) {x * 10}
# #<Proc:0x00007fc4fba55178@(pry)

[1,2,3,4,5].map(&a)
# [10, 20, 30, 40, 50]Code language: Ruby (ruby)

Lambda — выполняем эту функцию как отдельную, она не влияет на тот код который находиться вокруг

def g(x)
  (yield x) * (yield x)
end

# анонимная ф-ия
puts g(7) {|x|x+3} # передали block в параметре

# передача ф-ии как блока
f1 = ->(x) {x + 3} # Определили lambda
puts g(7, &f1) # передали lambda в параметре

# & - ampersand operator
# Позволяет передать блок в параметре

# Преобразование method -> lambda
def f2(x)
  x+3
end
puts (f2_l = method(:f2).to_proc).lambda? # true
puts g(7, &f2_l) # 100Code language: Ruby (ruby)

Пример короткой записи изменения элементов в массиве в функциональном стиле

dd = ['ad','bb'].map(&:upcase)

# ["AD", "BB"]Code language: PHP (php)
dogs = ['bethoven', 'mike', 'mic', 'michel'].select {|name| name if name.length <= 4}
puts dogs

# mike
# micCode language: PHP (php)

Пример кода с неизвестными методами

Перехват обращения к не существующему методу

Elements = {
  html: ->(var) { "<html>#{var}</html>\n" }, 
  head: ->(var) { "<head>#{var}</head>\n" }, 
  title: ->(var) { "<title>#{var}</title>\n" }, 
  body: ->(var) { "<body>#{var}</body>\n" }, 
  div: ->(var) { "<div>#{var}</div>\n" },
  green: -> (var) { "<span style='color: green'>#{var}</span>\n" },
  br: -> { "<br/>" }
}

def method_missing(meth, *args, &block) 
  if (func = Elements[meth])
    block ? func.call( block.call ) : func.call 
  else
    # если не знаем, что это, вызываем обработчик предка
    super.method_missing(meth, *args, &block)
  end
end

result = html do
  head { title { "Test page" } } + 
  body do
    div do 
      "Uncolored string" + br + "test string" 
      green do 
        "Hello"
      end 
    end
  end
end
  
puts resultCode language: Ruby (ruby)

DSL

Пример Rspec

Полезные особенности Ruby

● Динамическое объявление методов
● Расширенный синтаксис без скобок
● Большое количество встроенных функций
● Наличие большого количества сторонних библиотек

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *