Общие Рубин Фразеологизмы



одна вещь, которую я люблю в ruby, заключается в том, что в основном это очень читаемый язык (который отлично подходит для самодокументированного кода)



однако, вдохновленный этим вопросом: Ruby Code explained
и описание как ||= работает в ruby, я думал о Ruby идиомы я не использую, как честно говоря, я не полностью Грок их.



Итак, мой вопрос похож на пример из упомянутого вопроса, Какие общие, но не очевидные идиомы ruby мне нужно знать, чтобы быть действительно опытным программистом ruby?



кстати, из упомянутого вопроса



a ||= b 


эквивалентно



if a == nil || a == false
a = b
end


(спасибо Яну Терреллу за исправление)



Edit: оказывается, этот момент не совсем бесспорен. Правильное расширение на самом деле



(a || (a = (b))) 


видеть эти ссылки для почему:




спасибо Йоргу W Mittag за указание на это.

574   15  

15 ответов:

волшебное предложение if, которое позволяет одному и тому же файлу служить библиотекой или скриптом:

if __FILE__ == 
  # this library may be run as a standalone script
end

упаковка и распаковка массива:

# put the first two words in a and b and the rest in arr
a,b,*arr = *%w{a dog was following me, but then he decided to chase bob}
# this holds for method definitions to
def catall(first, *rest)
  rest.map { |word| first + word }
end
catall( 'franken', 'stein', 'berry', 'sense' ) #=> [ 'frankenstein', 'frankenberry', 'frankensense' ]

синтаксический сахар для хэшей в качестве аргументов метода

this(:is => :the, :same => :as)
this({:is => :the, :same => :as})

хэш-инициализаторов:

# this
animals = Hash.new { [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {}
# is not the same as this
animals = Hash.new { |_animals, type| _animals[type] = [] }
animals[:dogs] << :Scooby
animals[:dogs] << :Scrappy
animals[:dogs] << :DynoMutt
animals[:squirrels] << :Rocket
animals[:squirrels] << :Secret
animals #=> {:squirrels=>[:Rocket, :Secret], :dogs=>[:Scooby, :Scrappy, :DynoMutt]}

синтаксис метакласс

x = Array.new
y = Array.new
class << x
  # this acts like a class definition, but only applies to x
  def custom_method
     :pow
  end
end
x.custom_method #=> :pow
y.custom_method # raises NoMethodError

переменные экземпляра класса

class Ticket
  @remaining = 3
  def self.new
    if @remaining > 0
      @remaining -= 1
      super
    else
      "IOU"
    end
  end
end
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> Ticket
Ticket.new #=> "IOU"

блоки, проки и лямбды. Живите и дышите ими.

 # know how to pack them into an object
 block = lambda { |e| puts e }
 # unpack them for a method
 %w{ and then what? }.each(&block)
 # create them as needed
 %w{ I saw a ghost! }.each { |w| puts w.upcase }
 # and from the method side, how to call them
 def ok
   yield :ok
 end
 # or pack them into a block to give to someone else
 def ok_dokey_ok(&block)
    ok(&block)
    block[:dokey] # same as block.call(:dokey)
    ok(&block)
 end
 # know where the parentheses go when a method takes arguments and a block.
 %w{ a bunch of words }.inject(0) { |size,w| size + 1 } #=> 4
 pusher = lambda { |array, word| array.unshift(word) }
 %w{ eat more fish }.inject([], &pusher) #=> ['fish', 'more', 'eat' ]

этой слайдшоу довольно полно на основных идиомах Ruby, как в:

  • поменять местами два значения:

    x, y = y, x

  • параметры, которые, если не указано, принимают значение по умолчанию

    def somemethod(x, y=nil)

  • Пакетирует посторонние параметры в массив

    def substitute(re, str, *rest)

и так далее...

еще несколько идиом:

использование %w,%r и %( разделители

%w{ An array of strings %}
%r{ ^http:// }
%{ I don't care if the string has 'single' or "double" strings }

сравнение типов в операторах case

def something(x)
  case x
    when Array
      # Do something with array
    when String
      # Do something with string
    else
      # You should really teach your objects how to 'quack', don't you?
  end
end

... и в целом злоупотребление === метод в операторах case

case x
  when 'something concrete' then ...
  when SomeClass then ...
  when /matches this/ then ...
  when (10...20) then ...
  when some_condition >= some_value then ...
  else ...
end

что-то, что должно выглядеть естественно для рубистов, но, возможно, не так для людей, происходящих из других языков: использование each в пользу for .. in

some_iterable_object.each{|item| ... }

в Ruby 1.9+, рельсы, или исправление символа#to_proc метод,этой становится все более популярной идиомой:

strings.map(&:upcase)

условный метод/определение константы

SOME_CONSTANT = "value" unless defined?(SOME_CONSTANT)

методы запроса и деструктивные (bang) методы

def is_awesome?
  # Return some state of the object, usually a boolean
end

def make_awesome!
  # Modify the state of the object
end

неявные параметры splat

[[1, 2], [3, 4], [5, 6]].each{ |first, second| puts "(#{first}, #{second})" }

Я такой:

str = "Something evil this way comes!"
regexp = /(\w[aeiou])/

str[regexp, 1] # <- This

что (примерно) эквивалентно:

str_match = str.match(regexp)
str_match[1] unless str_match.nil?

или по крайней мере, это то, что я использовал на замену таких блоков.

Я бы предложил прочитать код популярных и хорошо разработанных плагинов или драгоценных камней от людей, которыми вы восхищаетесь и уважаете.

некоторые примеры, с которыми я столкнулся:

if params[:controller] == 'discussions' or params[:controller] == 'account'
  # do something here
end

соответствующую

if ['account', 'discussions'].include? params[:controller]
  # do something here
end

, который позже будет переработан в

if ALLOWED_CONTROLLERS.include? params[:controller]
  # do something here
end

вот несколько, отобранных из различных источников:

используйте "если " и" пока "вместо" Если нет "и"пока нет". Однако старайтесь не использовать "если", когда существует условие "else".

помните, что вы можете назначить несколько переменных сразу:

a,b,c = 1,2,3

и даже поменять переменную без temp:

a,b = b,a

при необходимости используйте конечные условные обозначения, например

do_something_interesting unless want_to_be_bored?

имейте в виду, что обычно используется, но не сразу очевидно (для меня по крайней мере) способ определения методов класса:

class Animal
  class<<self
    def class_method
      puts "call me using Animal.class_method"
    end
  end
end

ссылки:

кстати, из ссылки вопрос

a ||= b 

эквивалентно

if a == nil   
  a = b 
end

это тонко неверно, и является источником ошибок в приложениях Ruby новичков.

так как оба (и только) nil и false вычислить логическое значение false,a ||= b фактически (почти*) эквивалентно:

if a == nil || a == false
  a = b
end

или, чтобы переписать его с другой идиомой Ruby:

a = b unless a

(*так как каждое утверждение имеет значение, они технически не эквивалентны a ||= b. Но если вы не полагаетесь на значение утверждения, вы не увидите разницы.)

Я поддерживаю вики-страницу, которая охватывает некоторые идиомы Ruby и форматирование:

https://github.com/tokland/tokland/wiki/RubyIdioms

вы можете deepcopy с маршалинг объекта легко. - взято из языка программирования Ruby

def deepcopy(o)
  Marshal.load(Marshal.dump(o))
end

обратите внимание, что файлы и потоки ввода-вывода, Как а также способ и объекты привязки, слишком динамичны для маршалинга; там не было бы надежного способа восстановить свое государство.

a = (b && b.attribute) || "default"

грубо:

if ( ! b.nil? && ! b == false) && ( ! b.attribute.nil? && ! b.attribute.false) a = b
else a = "default"

Я использую это, когда b-это запись, которая может быть или не быть найдена, и мне нужно получить один из ее атрибутов.

Я всегда забываю точный синтаксис этого сокращенного оператора if else (и имя оператора. комментарии кто?) Я думаю, что он широко используется за пределами ruby, но в случае, если кто-то еще хочет синтаксис здесь:

refactor < 3 ? puts("No need to refactor YET") : puts("You need to refactor this into a  method")

увеличивается до

if refactor < 3
  puts("No need to refactor YET")
else
  puts("You need to refactor this into a  method")
end

обновление

вызывается тернарный оператор:

вернуть myvar ? аргумент myVar.размер : 0

мне нравится, как If-then-elses или case-when могут быть сокращены, потому что они возвращают значение:

if test>0
  result = "positive"
elsif test==0
  result = "zero"
else
  result = "negative"
end

можно переписать

result = if test>0
  "positive"
elsif test==0
  "zero"
else
  "negative"
end

то же самое может быть применено к case-when:

result = case test
when test>0 ; "positive"
when test==0 ; "zero"
else "negative"
end

массив.пакет и веревка.распаковать для работы с двоичными файлами:

# extracts four binary sint32s to four Integers in an Array
data.unpack("iiii") 

метод отсутствует магия

class Dummy  
  def method_missing(m, *args, &block)  
    "You just called method with name #{m} and arguments- #{args}"  
  end  
end

Dummy.new.anything(10, 20)
=> "You just called method with name anything and arguments- [10, 20]"

Если вы вызываете методы, которые не существуют в объектах ruby, интерпретатор ruby вызовет метод с именем "method_missing", если он определен, вы можете использовать это для некоторых трюков, таких как написание оболочек api или dsl, где вы не знаете всех методов и имен параметров

хороший вопрос!

как я думаю, чем более интуитивным и быстрым является код, тем лучше программное обеспечение, которое мы создаем. Я покажу вам, как я выражаю свои мысли с помощью Ruby в маленьких фрагментах кода. подробнее здесь

карта

мы можем использовать метод map по-разному:

user_ids = users.map { |user| user.id }

или:

user_ids = users.map(&:id)

пример

мы можем использовать функцию слчис метод:

[1, 2, 3][rand(3)]

Shuffle:

[1, 2, 3].shuffle.first

и идиоматический, простой и легкий способ... образец!

[1, 2, 3].sample

Двойная Труба Равна / Memoization

как вы сказали в описании, мы можем использовать мемоизацию:

some_variable ||= 10
puts some_variable # => 10

some_variable ||= 99
puts some_variable # => 10

Статический Метод / Метод Класса

мне нравится использовать методы класса, я чувствую, что это действительно идиоматический способ создания и использования классов:

GetSearchResult.call(params)

простой. Красивый. Интуитивный. Что происходит на заднем плане?

class GetSearchResult
  def self.call(params)
    new(params).call
  end

  def initialize(params)
    @params = params
  end

  def call
    # ... your code here ...
  end
end

для получения дополнительной информации, чтобы написать идиоматический код Ruby, прочитайте здесь

Comments

    Ничего не найдено.