रूबी की छिपी विशेषताएं


160

"हिडन फीचर्स ऑफ ..." मेम को जारी रखते हुए, आइए रूबी प्रोग्रामिंग भाषा की कम-ज्ञात लेकिन उपयोगी विशेषताओं को साझा करें।

इस चर्चा को मूल रूबी के साथ सीमित करने की कोशिश करें, बिना किसी रूबी के सामान पर।

यह सभी देखें:

(कृपया, प्रति उत्तर केवल एक छिपी हुई सुविधा।)

धन्यवाद


जवाबों:


80

रूबी से 1.9 प्रोक # === प्रोक # कॉल का एक उपनाम है, जिसका अर्थ है कि प्रोक ऑब्जेक्ट का उपयोग इस तरह किया जा सकता है:

def multiple_of(factor)
  Proc.new{|product| product.modulo(factor).zero?}
end

case number
  when multiple_of(3)
    puts "Multiple of 3"
  when multiple_of(7)
    puts "Multiple of 7"
end

1
मैंने वास्तव में ऐसा करने के लिए एक बिंदु पर एक रत्न लिखा था, लेकिन मेरा कोड (ए) गड़बड़ था, और (बी) धीमा था। मुझे बहुत खुशी है कि कार्यक्षमता ने इसे कोर में बना दिया है।
जेम्स ए। रोसेन

76

पीटर कूपर के पास रूबी ट्रिक्स की एक अच्छी सूची है। शायद मेरा पसंदीदा उसका एकल आइटम और संग्रह दोनों की गणना करने की अनुमति है। (यह है, एक गैर-संग्रह वस्तु को एक संग्रह के रूप में समझो, जिसमें वह वस्तु हो।) यह इस तरह दिखता है:

[*items].each do |item|
  # ...
end

38
इसका एक और अधिक स्पष्ट (और इस प्रकार अच्छा) रूप एरे (आइटम) है। नीच
मिथिला

यदि itemsएक स्ट्रिंग है तो आपको इसे [*…] के साथ जोड़ना नहीं है। String.each पात्रों पर पुनरावृति नहीं करता है क्योंकि कुछ उम्मीद कर सकते हैं। यह केवल ब्लॉक में ही लौटता है।
mxcl

इससे क्या फायदा होगा? बस उत्सुक।
एड एस।

1
@ ईडी: यदि आप एक विधि लिख रहे हैं तो यह अच्छा है और विधि के उपयोगकर्ता को या तो वैराग्य सूची या एरे को पास करने की अनुमति देना चाहते हैं।
जेम्स ए। रोसेन

64

यह कैसे छिपा है पता नहीं है, लेकिन मैं इसे उपयोगी पाया है जब एक एक आयामी सरणी से बाहर हैश बनाने की जरूरत है:

fruit = ["apple","red","banana","yellow"]
=> ["apple", "red", "banana", "yellow"]

Hash[*fruit]    
=> {"apple"=>"red", "banana"=>"yellow"}

ध्यान दें कि Hash[ [["apple","red"], ["banana","yellow"] ]वही परिणाम उत्पन्न करता है।
मार्क-आंद्रे लाफ्यून ने

54

एक चाल मुझे पसंद है कि एरेट्स के *अलावा अन्य वस्तुओं पर स्पैट ( ) विस्तारक का उपयोग करना है । यहाँ एक नियमित अभिव्यक्ति मैच पर एक उदाहरण दिया गया है:

match, text, number = *"Something 981".match(/([A-z]*) ([0-9]*)/)

अन्य उदाहरणों में शामिल हैं:

a, b, c = *('A'..'Z')

Job = Struct.new(:name, :occupation)
tom = Job.new("Tom", "Developer")
name, occupation = *tom

13
संयोग से, जिज्ञासु के लिए, यह स्पष्ट रूप से फुलाए के लक्ष्य पर to_a कॉल करके काम करता है।
बॉब अमन

1
यदि आप मैच में रुचि नहीं रखते हैं, तो आप कर सकते हैं text, number = *"text 555".match(/regexp/)[1..-1]
एंड्रयू ग्रिम

text, number = "Something 981".scan(/([A-z]*) ([0-9]*)/).flatten.map{|m| Integer(m) rescue m}
जोनास एल्फ्रॉस्टेम

7
दोनों अच्छी चाल है, लेकिन वहाँ एक बिंदु है जहाँ यह बहुत जादू है, है ना ?!
टमाटर का जनाब

1
@ और, क्या आपने माना, कि मैच शून्य वापसी कर सकता है? nil में विधि नहीं है []
एलेक्सी

52

वाह, किसी ने फ्लिप फ्लॉप ऑपरेटर का उल्लेख नहीं किया:

1.upto(100) do |i|
  puts i if (i == 3)..(i == 15)
end

11
ठीक है ... किसी को यह एक मुझे समझाने के लिए जा रहा है। यह काम करता है, लेकिन मैं यह पता नहीं लगा सकता कि क्यों।
बॉब अमन

12
फ्लिप फ्लॉप ऑपरेटर एक स्टेटफुल है अगर। इसका राज्य जैसे ही सच पर स्विच करता है i == 3और झूठे पर स्विच करता है के बाद i != 3 और i == 15। फ्लिप-फ्लॉप के समान: en.wikipedia.org/wiki/Flip-flop_%28electronics%29
Konstantin Haase

1
मैं वास्तव में इसे एक छिपी हुई विशेषता नहीं कहूंगा, इसलिए बहुत गुस्सा आता है। मुझे याद है कि पहली बार मुझे Freenode पर #Ruby में सालों पहले पेश किया गया था; मैंने मूल रूप से रूबी की हर एक विशेषता को किसी एक बिंदु पर इस्तेमाल किया है, सिवाय इसके
ELLIOTTCABLE

1
मैं इसे झुंझलाहट नहीं कहूंगा, यह सिर्फ कुछ है जो आपने उपयोग नहीं किया है। मैं इसका उपयोग करता हूं और यह कोड को अच्छी तरह से कम कर सकता है, खासकर जब मैं कुछ मानदंडों के आधार पर फाइलों से लाइनों के ब्लॉकों को पकड़ रहा हूं।
द टिन मैन

49

माणिक के बारे में ठंडी चीजों में से एक यह है कि आप तरीकों को कॉल कर सकते हैं और उन स्थानों पर कोड चला सकते हैं, जहां अन्य भाषाएं विधि या वर्ग परिभाषाओं में मौजूद हैं।

उदाहरण के लिए, एक वर्ग बनाने के लिए जिसमें एक अज्ञात सुपरक्लास होता है जब तक कि रन टाइम नहीं होता है, यानी रैंडम, आप निम्न कार्य कर सकते हैं:

class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample

end

RandomSubclass.superclass # could output one of 6 different classes.

यह 1.9 का उपयोग करता है Array#sample विधि (1.8.7-केवल, देखें Array#choice) , और उदाहरण बहुत ही विपरीत है, लेकिन आप यहां शक्ति देख सकते हैं।

एक और अच्छा उदाहरण डिफ़ॉल्ट पैरामीटर मान रखने की क्षमता है जो गैर निश्चित हैं (जैसे अन्य भाषाएं अक्सर मांग करती हैं):

def do_something_at(something, at = Time.now)
   # ...
end

बेशक पहले उदाहरण के साथ समस्या यह है कि इसका मूल्यांकन परिभाषा के समय पर किया जाता है, समय पर नहीं। इसलिए, एक बार एक सुपरक्लास चुने जाने के बाद, यह उस सुपरक्लास के शेष कार्यक्रम के लिए रहता है।

हालांकि, दूसरे उदाहरण में, हर बार जब आप कॉल करते हैं do_something_at, तो atचर वह समय होगा जब विधि को बुलाया गया था (ठीक है, इसके बहुत करीब)


2
नोट: Array # rand ActiveSupport द्वारा प्रदान किया जाता है जिसे आप रेल के बाहर आसानी से उपयोग कर सकते हैंrequire 'activesupport'
rfunduk

Array # पसंद 1.8.7
जोश ली

24
Array # पसंद केवल 1.8.7 है ! इसका उपयोग न करें, यह 1.9 में चला गया है और 1.8.8 में चला जाएगा। #Sample
मार्क-आंद्रे लफ़्यून डे

अजगर: वर्ग डिक्लिस्ट ([तानाशाह, सूची] [यादृच्छिक। वृंद (0,1)]): पास
अनुराग उनियाल

def do_something_at (कुछ, at = lambda {Time.now}) at.call #now dynamically time end
Jack Kinsella

47

एक और छोटी विशेषता - Fixnumकिसी भी आधार को 36 में बदलना :

>> 1234567890.to_s(2)
=> "1001001100101100000001011010010"

>> 1234567890.to_s(8)
=> "11145401322"

>> 1234567890.to_s(16)
=> "499602d2"

>> 1234567890.to_s(24)
=> "6b1230i"

>> 1234567890.to_s(36)
=> "kf12oi"

और जैसा कि ह्यू वाल्टर्स ने टिप्पणी की है, दूसरे तरीके को परिवर्तित करना उतना ही सरल है:

>> "kf12oi".to_i(36)
=> 1234567890

1
और पूर्णता के लिए, String#to_s(base)एक पूर्णांक में वापस बदलने के लिए इस्तेमाल किया जा सकता है; "1001001100101100000001011010010".to_i(2), "499602d2".to_i(16)आदि सभी मूल वापस करते हैं Fixnum
हुव वाल्टर

40

डिफ़ॉल्ट मूल्यों के साथ हैश! इस मामले में एक सरणी।

parties = Hash.new {|hash, key| hash[key] = [] }
parties["Summer party"]
# => []

parties["Summer party"] << "Joe"
parties["Other party"] << "Jane"

मेटाप्रोग्रामिंग में बहुत उपयोगी है।


1
हाँ सच है। रूबी हैश '<<' ऑपरेटर को स्वीकार कर सकता है अगर वहाँ पहले से ही '=' के साथ डिफ़ॉल्ट मान असाइन किया गया है (परवाह नहीं है, भले ही यह खाली असाइनमेंट हो) अन्यथा हैश 'स्वीकार' नहीं करेगा। CMIIW
MHD

39

रूबी 1.9 स्रोत डाउनलोड करें, और जारी करें make golf, फिर आप इस तरह की चीजें कर सकते हैं:

make golf

./goruby -e 'h'
# => Hello, world!

./goruby -e 'p St'
# => StandardError

./goruby -e 'p 1.tf'
# => 1.0

./goruby19 -e 'p Fil.exp(".")'
"/home/manveru/pkgbuilds/ruby-svn/src/trunk"

golf_prelude.cदूर छुपाने वाली अधिक साफ-सुथरी चीजों के लिए पढ़ें ।


38

1.9 प्रोक कार्यक्षमता में एक और मजेदार इसके अलावा प्रोक # करी है जो आपको एन -1 को स्वीकार करने वाले प्रो में एन तर्कों को स्वीकार करने की अनुमति देता है। यहाँ यह प्रोक # === टिप के साथ संयुक्त है जिसका मैंने ऊपर उल्लेख किया है:

it_is_day_of_week = lambda{ |day_of_week, date| date.wday == day_of_week }
it_is_saturday = it_is_day_of_week.curry[6]
it_is_sunday = it_is_day_of_week.curry[0]

case Time.now
when it_is_saturday
  puts "Saturday!"
when it_is_sunday
  puts "Sunday!"
else
  puts "Not the weekend"
end

35

गैर बूलियन मूल्यों पर बूलियन ऑपरेटरों।

&& तथा ||

दोनों मूल्यांकन किए गए अंतिम अभिव्यक्ति का मूल्य लौटाते हैं।

जिसके कारण ऐसा है ||= यदि चर अपरिभाषित है, तो चर दाईं ओर दिए गए मान के साथ चर को अद्यतन करेगा। यह स्पष्ट रूप से प्रलेखित नहीं है, लेकिन सामान्य ज्ञान है।

हालाँकि इस &&=बारे में बहुत व्यापक रूप से जानकारी नहीं है।

string &&= string + "suffix"

के बराबर है

if string
  string = string + "suffix"
end

यह विनाशकारी संचालन के लिए बहुत आसान है जो चर अपरिभाषित होने पर आगे नहीं बढ़ना चाहिए।


2
अधिक सटीक, string &&= string + "suffix" के बराबर है string = string && string + "suffix"। वह &&और ||उनके दूसरे तर्क को पिकअक्स, पी में चर्चा की गई है। 154 (भाग I - रूबी, अभिव्यक्ति, सशर्त निष्पादन के पहलू)।
रिचर्ड माइकल

29

रेल # प्रतीक to_proc कि रेल प्रदान करता है वास्तव में अच्छा है।

के बजाय

Employee.collect { |emp| emp.name }

तुम लिख सकते हो:

Employee.collect(&:name)

यह, जाहिरा तौर पर, एक ब्लॉक का उपयोग करने की तुलना में "परिमाण धीमा" का क्रम है। igvita.com/2008/07/08/6-optimization-tips-for-ruby-mri
चार्ल्स रॉपर

मैंने अभी इसकी कोशिश की, और पाया कि दोनों के बीच कोई महत्वपूर्ण अंतर नहीं है। मुझे यकीन नहीं है कि यह "परिमाण का क्रम" सामान कहां से आया है। (रूबी 1.8.7 का उपयोग करते हुए)
मैट ग्रांडे

1
रेल के बाहर ऐसा करना आसान भी है और इसके साथ ही ऐसा किया जा सकता है require 'activesupport'क्योंकि वास्तव में इनमें से अधिकांश मददगार हैं।
rfunduk

8
यह सक्रिय_ असमर्थता के लागू होने के कारण धीमी गति से हुआ करता था, अर्थात इसने कई तर्क स्वीकार किए हैं ताकि आप (1..10) जैसे शांत बकवास कर सकें। संग्रह जैसे% w (त्वरित ब्राउन लोमड़ी) .map और: ऊपर चढ़ना। 1.8.7 के रूप में यह मुख्य रूबी है और प्रदर्शन उचित है।
स्टीव ग्राहम

4
@thenduks: और यह रूबी 1.8.7 और 1.9 में एक्टिवास्पोर्ट की मदद के बिना किया जा सकता है।
एंड्रयू ग्रिम

28

एक अंतिम एक - रूबी में आप किसी भी चरित्र का उपयोग कर सकते हैं जिसे आप तारों को सीमांकित करना चाहते हैं। निम्नलिखित कोड लें:

message = "My message"
contrived_example = "<div id=\"contrived\">#{message}</div>"

यदि आप स्ट्रिंग के भीतर दोहरे-उद्धरणों से बचना नहीं चाहते हैं, तो आप बस एक अलग सीमांकक का उपयोग कर सकते हैं:

contrived_example = %{<div id="contrived-example">#{message}</div>}
contrived_example = %[<div id="contrived-example">#{message}</div>]

साथ ही सीमांकक से बचने के लिए, आप इन सीमांकक का उपयोग अच्छे बहुपरत के तार के लिए कर सकते हैं:

sql = %{
    SELECT strings 
    FROM complicated_table
    WHERE complicated_condition = '1'
}

19
कोई भी चरित्र नहीं है , लेकिन यह अभी भी बहुत अच्छा है। यह अन्य शाब्दिक शब्दों के साथ भी काम करता है:% () /% {} /% [] /% <> /% || % r () /% r {} /% r [] /% r <> /% r || % w () /% w {} /% w [] /% w <> /% w ||
बो जीन्स

वहाँ भी हेरोइन डॉक्टर वाक्यविन्यास है: << ब्लॉक ... ब्लॉक, जो मैं बहुस्तरीय एसक्यूएल बयान आदि जैसी चीजों के लिए उपयोग करना पसंद करता हूं
मार्टिन टी।

26

मैं डिफाइन_मिथोड कमांड का उपयोग गतिशील रूप से उत्पन्न करने के तरीकों को खोजने के लिए करता हूं जो कि काफी दिलचस्प और अच्छी तरह से ज्ञात नहीं हैं। उदाहरण के लिए:

((0..9).each do |n|
    define_method "press_#{n}" do
      @number = @number.to_i * 10 + n
    end
  end

उपरोक्त कोड गतिशील रूप से "प्रेस 1" के माध्यम से "प्रेस 1" बनाने के लिए 'डिफाइन_मिथोड' कमांड का उपयोग करता है। बल्कि तब सभी 10 विधियों को टाइप करना, जिसमें निबंध में समान कोड होते हैं, परिभाषित विधि कमांड का उपयोग मक्खी पर इन तरीकों को उत्पन्न करने के लिए किया जाता है।


4
Def_method के साथ एकमात्र समस्या यह है कि यह रूबी 1.8 में पैरामीटर के रूप में ब्लॉकों को पारित करने की अनुमति नहीं देता है। इस ब्लॉग पोस्ट को वर्कअराउंड के लिए देखें ।
एंड्रयू ग्रिम

26

एक असीम आलसी सूची के रूप में एक रेंज ऑब्जेक्ट का उपयोग करें:

Inf = 1.0 / 0

(1..Inf).take(5) #=> [1, 2, 3, 4, 5]

अधिक जानकारी यहाँ: http://banisterfiend.wordpress.com/2009/10/02/wtf-infinite-ranges-in-ruby/


लिंक किए गए लेख में lazy_select बहुत साफ है।
जोसेफ वीसमैन

यह वाकई कमाल है। मुझे पसंद है कि इन्फिनिटी कैसे एक फ्लोट है, इस तरह जब मैंने यह कोशिश की: (-Inf..Inf) .take (4) यह एक उठाया (तार्किक रूप से सुसंगत) फ्लोट त्रुटि से पुनरावृति नहीं कर सकता। : D
zachaysan

23

module_function

मॉड्यूल तरीके जिन्हें मॉड्यूल_फंक्शन के रूप में घोषित किया जाता है , खुद को उस वर्ग में निजी उदाहरण विधियों के रूप में कॉपी करेंगे , जिसमें मॉड्यूल शामिल हैं:

module M
  def not!
    'not!'
  end
  module_function :not!
end

class C
  include M

  def fun
    not!
  end
end

M.not!     # => 'not!
C.new.fun  # => 'not!'
C.new.not! # => NoMethodError: private method `not!' called for #<C:0x1261a00>

यदि आप किसी भी तर्क के बिना मॉड्यूल_फंक्शन का उपयोग करते हैं , तो मॉड्यूल_फंक्शन स्टेटमेंट के बाद आने वाले किसी भी मॉड्यूल तरीके स्वतः ही मॉड्यूल_फंक्शन बन जाएंगे।

module M
  module_function

  def not!
    'not!'
  end

  def yea!
    'yea!'
  end
end


class C
  include M

  def fun
    not! + ' ' + yea!
  end
end
M.not!     # => 'not!'
M.yea!     # => 'yea!'
C.new.fun  # => 'not! yea!'

4
यदि आप केवल मॉड्यूल में निजी तरीकों की घोषणा करना चाहते हैं, तो बस निजी कीवर्ड का उपयोग करें। मॉड्यूल को शामिल करने वाली कक्षाओं में विधि को निजी बनाने के अलावा, मॉड्यूल_फंक्शन मॉड्यूल उदाहरण की विधि की प्रतिलिपि बनाता है। ज्यादातर मामलों में यह वह नहीं है जो आप चाहते हैं।
टमाटर का

मुझे पता है कि आप सिर्फ निजी इस्तेमाल कर सकते हैं। लेकिन यह रूबी की छिपी हुई विशेषताओं पर एक सवाल है। और, मुझे लगता है कि ज्यादातर लोगों ने मॉड्यूल_फंक्शन (खुद शामिल) के बारे में कभी नहीं सुना है जब तक कि वे इसे डॉक्टर में नहीं देखते हैं और इसके चारों ओर खेलना शुरू करते हैं।
न्यूटनप्पल

उपयोग करने का एक विकल्प module_function(दूसरा तरीका) सिर्फ उपयोग करना है extend self(जो बहुत अच्छा लग रहा है: D)
J -_- L

23

लघु इंजेक्शन, जैसे:

सीमा का योग:

(1..10).inject(:+)
=> 55

2
वर्थ नोटिंग आपको रूबी 1.9 या रूबी की जरूरत है रूबी 1.8 के साथ काम करने के लिए।
mxcl

1
@ मैक्स हॉवेल: या require 'backports':-)
मार्क-एंड्रे लाफ्यून

1
क्या यह होहॉय के उत्तर की नकल नहीं है?
एंड्रयू ग्रिम

21

चेतावनी: इस आइटम को 2008 की # 1 सबसे डरावनी हैक के रूप में वोट दिया गया था , इसलिए देखभाल के साथ उपयोग करें। दरअसल, प्लेग की तरह इससे बचें, लेकिन यह निश्चित रूप से हिडन रूबी है।

रूबी में सुपर ऑपरेटर्स नए ऑपरेटर जोड़ें

कभी अपने कोड में कुछ अनूठे ऑपरेशन के लिए एक सुपर-गुप्त हैंडशेक ऑपरेटर चाहते हैं? कोड गोल्फ खेलना पसंद है? जैसे - ~ + ~ - या <--- जैसे ऑपरेटरों का प्रयास करें कि किसी आइटम के क्रम को उलटने के लिए उदाहरणों में अंतिम उपयोग किया जाता है।

सुपरवाइज़र प्रोजेक्ट के साथ मेरा कोई लेना-देना नहीं है।


19

मुझे पार्टी के लिए देर हो रही है, लेकिन:

आप आसानी से दो समान लंबाई के एरेज़ ले सकते हैं और उन्हें हैश में बदल सकते हैं, जिसमें एक एरे होगा जिसमें कीज़ और दूसरे वैल्यूज़ की आपूर्ति होगी:

a = [:x, :y, :z]
b = [123, 456, 789]

Hash[a.zip(b)]
# => { :x => 123, :y => 456, :z => 789 }

(यह काम करता है क्योंकि Array # ज़िप "zips" दो सरणियों से मूल्यों को:

a.zip(b)  # => [[:x, 123], [:y, 456], [:z, 789]]

और हैश [] सिर्फ इस तरह की एक सरणी ले सकता है। मैंने देखा है कि लोग ऐसा करते हैं:

Hash[*a.zip(b).flatten]  # unnecessary!

जो एक ही परिणाम देता है, लेकिन चपटा और चपटा पूरी तरह से अनावश्यक है - शायद वे अतीत में नहीं थे?)


3
यह वास्तव में एक लंबे समय के लिए अनिर्दिष्ट था (देखें redmine.ruby-lang.org/issues/show/139 )। ध्यान दें कि यह नया रूप रूबी 1.8.7 के लिए नया है
मार्क-आंद्रे लाफ्यून डे

19

रूबी में ऑटो-वाइजिंग हैश

def cnh # silly name "create nested hash"
  Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}
end
my_hash = cnh
my_hash[1][2][3] = 4
my_hash # => { 1 => { 2 => { 3 =>4 } } }

यह सिर्फ लानत हो सकती है।


1
मैं इसे देशी हैश module InfHash; def self.new; Hash.new {|h,k| h[k] = Hash.new(&h.default_proc)}; end; end
इनिट की

16

एक एरेक्ट को नष्ट करना

(a, b), c, d = [ [:a, :b ], :c, [:d1, :d2] ]

कहाँ पे:

a #=> :a
b #=> :b
c #=> :c
d #=> [:d1, :d2]

इस तकनीक का उपयोग करके हम किसी भी गहराई के नेस्टेड सरणी से बाहर सटीक मान प्राप्त करने के लिए सरल असाइनमेंट का उपयोग कर सकते हैं।


15

Class.new()

रन टाइम पर एक नई क्लास बनाएं। तर्क को व्युत्पन्न करने के लिए एक वर्ग हो सकता है, और ब्लॉक वर्ग निकाय है। आप const_set/const_get/const_defined?अपनी नई कक्षा को ठीक से पंजीकृत करवाने के लिए भी देखना चाहते हैं , ताकिinspect एक नंबर के बजाय एक नाम प्रिंट हो ।

ऐसा कुछ नहीं जिसकी आपको हर दिन जरूरत हो, लेकिन जब आप करें तो काफी आसान हो।


1
MyClass = Class.new Array do; def hi; 'hi'; end; endके बराबर लगता है class MyClass < Array; def hi; 'hi'; end; end
3

1
शायद मेरे बारे में जितना सोचा था उससे ज्यादा सच। यह भी प्रतीत होता है कि आप केवल एक स्थिर के बजाय एक चर से विरासत में प्राप्त कर सकते हैं। हालाँकि, यदि आप रन समय पर वर्ग नाम का निर्माण करने की आवश्यकता है, तो शर्करायुक्त संस्करण (दूसरा) काम नहीं करता है। (बारिंग eval, ज़ाहिर है।)
जस्टिन लव

इस तकनीक को Metaprogramming Ruby नामक पुस्तक में बहुत अच्छी तरह से वर्णित किया गया है ।
पॉल प्लाडीज

13

लगातार संख्याओं की एक सरणी बनाएं:

x = [*0..5]

सेट करने के लिए x [0, 1, 2, 3, 4, 5]


हां, लेकिन यह उतना छोटा और मीठा नहीं है;)
घोड़े का बच्चा

2
terseness उद्देश्य है, पठनीयता स्वाद और अनुभव की बात है
एलेक्सी

स्पैट ( *) ऑपरेटर मूल रूप से to_aवैसे भी कॉल करता है।
मैथ्यूस मोरेरा

13

रूबीलैंड में आपके द्वारा देखे गए बहुत सारे जादू मेटाप्रोग्रामिंग के साथ करना है, जो बस कोड लिख रहा है जो आपके लिए कोड लिखता है। रूबी के attr_accessor, attr_reader, और attr_writer, सभी सरल metaprogramming हैं कि वे एक पंक्ति में दो तरीकों, एक मानक पद्धति के अनुसार तैयार करते। रेल अपने संबंध-प्रबंधन के तरीकों की तरह पूरी तरह से मेटाप्रोग्रामिंग करती हैhas_one औरbelongs_to

लेकिन class_evalगतिशील रूप से लिखे गए कोड को निष्पादित करने के लिए अपने स्वयं के मेटाप्रोग्रामिंग ट्रिक्स बनाना बहुत सरल है ।

निम्न उदाहरण एक आवरण वस्तु को एक आंतरिक वस्तु के साथ-साथ कुछ विधियों को आगे बढ़ाने की अनुमति देता है:

class Wrapper
  attr_accessor :internal

  def self.forwards(*methods)
    methods.each do |method|
      define_method method do |*arguments, &block|
        internal.send method, *arguments, &block
      end
    end
  end

  forwards :to_i, :length, :split
end

w = Wrapper.new
w.internal = "12 13 14"
w.to_i        # => 12
w.length      # => 8
w.split('1')  # => ["", "2 ", "3 ", "4"]

विधि Wrapper.forwardsविधियों के नामों के लिए प्रतीक लेती है और उन्हें methodsसरणी में संग्रहीत करती है । फिर, उनमें से प्रत्येक के लिए, हम उपयोग करते हैंdefine_method एक नया तरीका बनाने के लिए करते हैं जिसका काम सभी तर्कों और ब्लॉकों सहित संदेश भेजना है।

मेटाप्रोग्रामिंग मुद्दों के लिए एक महान संसाधन यही कारण है कि लकी स्टिफ़ की "मेटाप्रोग्रामिंग को स्पष्ट रूप से देखना"


मैं रूबी में पहले मेटाप्रोग्रामिंग में सिर डुबाना चाहता हूं। क्या आप इसके साथ आरंभ करने के लिए कुछ संदर्भ प्रदान कर सकते हैं (दिए गए लिंक के अलावा)? किताबें भी करेंगे। धन्यवाद।
चिरंतन

PragProg के videocasting सेरी "रूबी ऑब्जेक्ट मॉडल और Metaprogramming" गहरे लाल रंग का उपयोग करते हुए मेटा प्रोग्रामिंग करने के लिए अपने एक अच्छा परिचय: pragprog.com/screencasts/v-dtrubyom/...
caffo

@Chirantan, पर एक नजर है Metaprogramming रूबी
पॉल प्लेजिज 19

12

===(obj)मामले की तुलना के लिए प्रतिक्रिया करने वाली किसी भी चीज़ का उपयोग करें :

case foo
when /baz/
  do_something_with_the_string_matching_baz
when 12..15
  do_something_with_the_integer_between_12_and_15
when lambda { |x| x % 5 == 0 }
  # only works in Ruby 1.9 or if you alias Proc#call as Proc#===
  do_something_with_the_integer_that_is_a_multiple_of_5
when Bar
  do_something_with_the_instance_of_Bar
when some_object
  do_something_with_the_thing_that_matches_some_object
end

Module(और इस प्रकार Class), Regexp, Date, और कई अन्य वर्गों एक उदाहरण विधि को परिभाषित: === (अन्य), और सभी के लिए इस्तेमाल किया जा सकता है।

रूबी 1.9 के रूप में अलियास होने की याद दिलाने के लिए फरल का धन्यवाद ।Proc#callProc#===


11

"रूबी" बाइनरी (कम से कम एमआरआई के) बहुत सारे स्विच का समर्थन करता है जो कि पर्ल वन-लाइनर्स को काफी लोकप्रिय बनाते हैं।

महत्वपूर्ण:

  • -n बस "हो जाता है" के साथ एक बाहरी लूप सेट करता है - जो जादुई रूप से दिए गए फ़ाइल नाम या STDIN के साथ काम करता है, प्रत्येक पठन लाइन को $ _ में सेट करता है।
  • -p समान -n लेकिन एक स्वचालित के साथ put प्रत्येक लूप पुनरावृत्ति के अंत में एस के
  • $ F में संग्रहीत प्रत्येक इनपुट लाइन पर -split को -a स्वचालित कॉल
  • -आई इन-प्लेस एडिट इनपुट फाइल्स
  • -l स्वचालित कॉल .chomp इनपुट पर
  • -ई कोड का एक टुकड़ा निष्पादित करें
  • -सी चेक सोर्स कोड
  • चेतावनी के साथ

कुछ उदाहरण:

# Print each line with its number:
ruby -ne 'print($., ": ", $_)' < /etc/irbrc

# Print each line reversed:
ruby -lne 'puts $_.reverse' < /etc/irbrc

# Print the second column from an input CSV (dumb - no balanced quote support etc):
ruby -F, -ane 'puts $F[1]' < /etc/irbrc

# Print lines that contain "eat"
ruby -ne 'puts $_ if /eat/i' < /etc/irbrc

# Same as above:
ruby -pe 'next unless /eat/i' < /etc/irbrc

# Pass-through (like cat, but with possible line-end munging):
ruby -p -e '' < /etc/irbrc

# Uppercase all input:
ruby -p -e '$_.upcase!' < /etc/irbrc

# Same as above, but actually write to the input file, and make a backup first with extension .bak - Notice that inplace edit REQUIRES input files, not an input STDIN:
ruby -i.bak -p -e '$_.upcase!' /etc/irbrc

Google को "रूबी वन-लाइनर्स" और "पर्ल वन-लाइनर्स" के लिए बेझिझक और अधिक व्यावहारिक और व्यावहारिक उदाहरणों के लिए स्वतंत्र महसूस करें। यह अनिवार्य रूप से आपको रूबी को जाग और sed के लिए एक शक्तिशाली शक्तिशाली प्रतिस्थापन के रूप में उपयोग करने की अनुमति देता है।


10

भेजने () विधि एक सामान्य उद्देश्य विधि है कि रूबी में किसी भी वर्ग या वस्तु पर इस्तेमाल किया जा सकता है। यदि ओवरराइड नहीं किया गया है, तो भेजें () एक स्ट्रिंग को स्वीकार करता है और उस विधि का नाम पुकारता है जिसके तार को पास किया जाता है। उदाहरण के लिए, यदि उपयोगकर्ता "Clr" बटन पर क्लिक करता है, तो 'press_clear' स्ट्रिंग भेज दिया जाएगा () विधि और 'press_clear' विधि कहा जाएगा। रूबी में कार्यों को कॉल करने के लिए मज़ेदार और गतिशील तरीके से भेजने () विधि की अनुमति मिलती है।

 %w(7 8 9 / 4 5 6 * 1 2 3 - 0 Clr = +).each do |btn|
    button btn, :width => 46, :height => 46 do
      method = case btn
        when /[0-9]/: 'press_'+btn
        when 'Clr': 'press_clear'
        when '=': 'press_equals'
        when '+': 'press_add'
        when '-': 'press_sub'
        when '*': 'press_times'
        when '/': 'press_div'
      end

      number.send(method)
      number_field.replace strong(number)
    end
  end

मैं ब्लॉगिंग शूज़ में इस सुविधा के बारे में अधिक बात करता हूं : द सिंपल-कैल्क एप्लिकेशन


एक सुरक्षा छेद खोलने के लिए एक शानदार तरीके की तरह लगता है।
एम.पी.

4
जहाँ भी संभव हो मैं प्रतीकों का उपयोग करूँगा।
रीटो

9

मूर्ख कुछ वर्ग या मॉड्यूल यह बता रहा है कि यह वास्तव में आवश्यक नहीं है कुछ की आवश्यकता है:

$" << "something"

यह उदाहरण के लिए उपयोगी है जब ए की आवश्यकता होती है कि बारी में बी की आवश्यकता होती है लेकिन हमें अपने कोड में बी की आवश्यकता नहीं है (और ए इस कोड के माध्यम से इसका उपयोग नहीं करेगा):

उदाहरण के लिए, बैकग्राउंड bdrb_test_helper requires 'test/spec', लेकिन आप इसका उपयोग बिलकुल नहीं करते हैं, इसलिए आपके कोड में:

$" << "test/spec"
require File.join(File.dirname(__FILE__) + "/../bdrb_test_helper")

क्या यह समस्याओं को ठीक करता है जहां रत्न A को foo-1.0.0 की आवश्यकता होती है, और gem B को foo-1.0.1 की आवश्यकता होती है?
एंड्रयू ग्रिम

नहीं क्योंकि "कुछ" कोड उपलब्ध नहीं होगा: यह केवल यह अनुकरण करता है कि "कुछ" आवश्यक है, लेकिन यह वास्तव में इसकी आवश्यकता नहीं है। $ "एक सरणी है जिसमें आवश्यकता से अधिक मॉड्यूल के नाम होते हैं (इसका उपयोग दो बार लोडिंग मॉड्यूल को रोकने के लिए आवश्यक होता है)। इसलिए, यदि आप इसका उपयोग रत्नों को मूर्ख बनाने के लिए करते हैं, तो जब रत्न वास्तविक" कुछ "का उपयोग करने का प्रयास करते हैं तो एक दुर्घटना उत्पन्न होगी। कोड, क्योंकि यह मौजूद नहीं होगा। आप इसके बजाय एक नवीनतम के बजाय एक मणि के ठोस संस्करण (जैसे foo-1.0.0) के लिए मजबूर कर सकते हैं: docs.rubygems.org/read/chapter/4#page71
olegueret

9

Fixnum#to_s(base)वास्तव में कुछ मामलों में उपयोगी हो सकता है। ऐसा ही एक मामला 36 के आधार का उपयोग करके यादृच्छिक संख्या को स्ट्रिंग में परिवर्तित करके यादृच्छिक (छद्म) अद्वितीय टोकन उत्पन्न कर रहा है।

लंबाई 8 का टोकन:

rand(36**8).to_s(36) => "fmhpjfao"
rand(36**8).to_s(36) => "gcer9ecu"
rand(36**8).to_s(36) => "krpm0h9r"

लंबाई 6 का टोकन:

rand(36**6).to_s(36) => "bvhl8d"
rand(36**6).to_s(36) => "lb7tis"
rand(36**6).to_s(36) => "ibwgeh"

9

एक विधि को परिभाषित करना जो किसी भी संख्या में मापदंडों को स्वीकार करता है और बस उन सभी को त्याग देता है

def hello(*)
    super
    puts "hello!"
end

उपरोक्त helloविधि को केवल puts "hello"स्क्रीन पर कॉल करने और कॉल करने की आवश्यकता है super- लेकिन जब से सुपरक्लास helloमापदंडों को परिभाषित करता है, तब तक इसे अच्छी तरह से करना पड़ता है - हालांकि, क्योंकि इसे वास्तव में स्वयं मापदंडों का उपयोग करने की आवश्यकता नहीं है - यह उन्हें एक नाम देने की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.