문제
루비에 대해 내가 좋아하는 한 가지는 대부분 읽기 쉬운 언어라는 것입니다 (자체 문서화 코드에 적합합니다).
그러나이 질문에서 영감을 얻었습니다. 루비 코드가 설명되었습니다그리고 방법에 대한 설명 ||=
루비에서 일하는데, 나는 내가 사용하지 않는 루비 관용구에 대해 생각하고있었습니다. 솔직히 말해서 나는 그들을 완전히 사로 잡지 않았습니다.
그래서 제 질문은 참조 된 질문의 예와 비슷하지만, 진정으로 능숙한 루비 프로그래머가 되려면 공통적이지만 명백하지 않은 루비 관용구는 무엇입니까?
그건 그렇고, 참조 된 질문에서
a ||= b
동일합니다
if a == nil || a == false
a = b
end
(교정에 대한 Ian Terrell에게 감사합니다)
편집하다: 이 점은 완전히 논란의 여지가없는 것이 밝혀졌습니다. 올바른 확장은 사실입니다
(a || (a = (b)))
이유는 다음과 같은 링크를 참조하십시오.
- http://dablog.rubypal.com/2008/3/25/a-short-circuit-edge-case/
- http://dablog.rubypal.com/2008/3/26/short-circuit-post-correction/
- http://procnew.com/ruby-short-circuit-edge-case-response.html
이것을 지적한 Jörg W Mittag에게 감사합니다.
해결책
동일한 파일이 라이브러리 또는 스크립트 역할을하는 마법의 조항 :
if __FILE__ == $0
# 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"
블록, Procs 및 Lambdas. 살고 숨을 쉬십시오.
# 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' ]
다른 팁
이것 슬라이드 쇼 다음과 같이 메인 루비 관용구에 대해 매우 완전합니다.
두 값을 바꾸십시오 :
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 }
사례 진술에서 비교를 입력하십시오
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 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| ... }
루비 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
다음은 다양한 출처에서 나온 몇 가지가 있습니다.
"그렇지 않은 경우"와 "그렇지 않은"대신 "이 아닌"과 "때까지"를 사용하십시오. 그러나 "다른"조건이 존재하는 경우를 사용하지 않는 한 "사용하지 마십시오.
한 번에 여러 변수를 할당 할 수 있습니다.
a,b,c = 1,2,3
그리고 온도없이 변수를 교환합니다.
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
그것은 미묘하게 틀렸으며 신규 이민자의 루비 응용 프로그램에서 버그의 원천입니다.
둘 다 (그리고 만) 이후 nil
그리고 false
부울 거짓으로 평가하고 a ||= b
실제로 (거의*)와 같습니다.
if a == nil || a == false
a = b
end
또는 다른 루비 관용구로 다시 작성하려면 :
a = b unless a
(*모든 진술은 가치가 있으므로 기술적으로는 기술적으로 동등하지 않습니다. a ||= b
. 그러나 진술의 가치에 의존하지 않으면 차이가 보이지 않습니다.)
루비 관용구와 서식을 다루는 위키 페이지를 유지합니다.
나는 항상 다른 문장의 정확한 구문 (그리고 운영자의 이름을 댓글을 달 때?)이 속기의 정확한 구문을 항상 잊어 버린다.
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
업데이트
Ternary 운영자라고합니다.
Myvar를 반환 하시겠습니까? myvar.size : 0
당신은 쉽게 마샬링 물체로 심해 할 수 있습니다. - 루비 프로그래밍 언어에서 가져 왔습니다
def deepcopy(o)
Marshal.load(Marshal.dump(o))
end
방법 및 바인딩 객체뿐만 아니라 파일 및 I/O 스트림도 마샬링하기에는 너무 역동적입니다. 그들의 상태를 복원하는 신뢰할 수있는 방법은 없을 것입니다.
a = (b && b.attribute) || "default"
대략 :
if ( ! b.nil? && ! b == false) && ( ! b.attribute.nil? && ! b.attribute.false) a = b
else a = "default"
B가 발견되었거나 발견되지 않은 레코드 일 때 이것을 사용하며, 그 속성 중 하나를 가져와야합니다.
나는 값을 반환하기 때문에 if-then-elses 또는 case가 단축 될 수있는 방법을 좋아합니다.
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
케이스시기에도 동일하게 적용될 수 있습니다.
result = case test
when test>0 ; "positive"
when test==0 ; "zero"
else "negative"
end
이진 파일 작업을위한 array.pack 및 string.unpack :
# extracts four binary sint32s to four Integers in an Array
data.unpack("iiii")
메소드 누락 magick
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 Interperter는 정의 된 경우 'Method_missing'이라는 메소드를 호출합니다. 이름
좋은 질문!
코드가 더 직관적이고 빠를수록 우리가 구축하는 더 나은 소프트웨어라고 생각합니다. 작은 코드 스 니펫으로 루비를 사용하여 내 생각을 어떻게 표현하는지 보여 드리겠습니다. 여기에서 자세히 알아보십시오
지도
다양한 방식으로 맵 방법을 사용할 수 있습니다.
user_ids = users.map { |user| user.id }
또는:
user_ids = users.map(&:id)
견본
RAND 방법을 사용할 수 있습니다.
[1, 2, 3][rand(3)]
혼합:
[1, 2, 3].shuffle.first
그리고 관용적이고 단순하고 가장 쉬운 방법 ... 샘플!
[1, 2, 3].sample
이중 파이프와 동등 / 메모 화
설명에서 말했듯이 회고록을 사용할 수 있습니다.
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
관용적 루비 코드를 작성하려는 자세한 정보는 읽으십시오. 여기