سؤال
شيء واحد أنا أحب حول روبي هو أن الغالب هو للقراءة اللغة (وهو أمر عظيم بالنسبة الذاتي توثيق رمز)
ومع ذلك ، مستوحاة من هذا السؤال: روبي البرمجية شرح
ووصف كيف ||=
يعمل في روبي ، كنت أفكر روبي التعابير لا تستخدم ، بصراحة أنا لا تماما جروك لهم.
لذلك سؤالي هو تشبه المثال من الرجوع إليها السؤال ، ما شيوعا ، ولكن ليس واضحا ، روبي التعابير هل أنا بحاجة إلى أن يكون على بينة من أن يكون حقا يتقن روبي مبرمج ؟
بالمناسبة من الإشارة السؤال
a ||= b
ما يعادل
if a == nil || a == false
a = b
end
(شكرا إلى إيان تيريل للتصحيح)
تحرير: اتضح أن هذه النقطة ليست تماما جدال.الصحيح التوسع في الواقع
(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
بفضل يورغ W Mittag عن الإشارة إلى هذا.
المحلول
جملة if السحرية التي تتيح لنفس الملف العمل كمكتبة أو برنامج نصي:
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]}
بناء جملة metaclass
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| ... }
في الإصدار Ruby 1.9+، أو Rails، أو عن طريق تصحيح طريقة الرمز #to_proc، هذا أصبح مصطلحًا شائعًا بشكل متزايد:
strings.map(&:upcase)
الطريقة الشرطية/التعريف الثابت
SOME_CONSTANT = "value" unless defined?(SOME_CONSTANT)
أساليب الاستعلام والأساليب التدميرية (الانفجار).
def is_awesome?
# Return some state of the object, usually a boolean
end
def make_awesome!
# Modify the state of the object
end
المعلمات الضجة الضمنية
[[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
.ولكن إذا كنت لا تعتمد على قيمة البيان بأنك لن ترى فرقا.)
أحتفظ بصفحة ويكي تغطي بعض مصطلحات وتنسيقات روبي:
أنسى دائمًا بناء الجملة الدقيق لهذا الاختصار إذا كان عبارة else (واسم عامل التشغيل.تعليقات أي شخص؟) أعتقد أنه يستخدم على نطاق واسع خارج روبي، ولكن في حالة أراد شخص آخر بناء الجملة هنا فهو:
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 :0
يمكنك deepcopy مع تنظيم كائن بسهولة.- مأخوذة من لغة البرمجة روبي
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-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
ويمكن تطبيق الشيء نفسه على الحالة عندما:
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")
طريقة السحر المفقود
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]"
إذا قمت باستدعاء أساليب غير موجودة في كائنات روبي، فسوف يستدعي مترجم روبي الأسلوب المسمى "method_missing" إذا تم تعريفه، فيمكنك استخدامه لبعض الحيل، مثل كتابة أغلفة API، أو DSL، حيث لا تعرف جميع الأساليب والمعلمات أسماء
سؤال جيد!
أعتقد أنه كلما كان الكود أكثر سهولة وسرعة، كلما كان البرنامج الذي نبنيه أفضل.سأوضح لك كيف أعبر عن أفكاري باستخدام روبي في مقتطفات صغيرة من التعليمات البرمجية. اقرأ المزيد هنا
خريطة
يمكننا استخدام طريقة الخريطة بطرق مختلفة:
user_ids = users.map { |user| user.id }
أو:
user_ids = users.map(&:id)
عينة
يمكننا استخدام طريقة راند:
[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
لمزيد من المعلومات حول كيفية كتابة رمز روبي الاصطلاحي، اقرأ هنا