عوائد لا حصر له من مكرر
سؤال
وأنا أحاول تعلم بعض روبي. تخيل أنا حلقات والقيام بعملية مستمرة منذ فترة طويلة، وفي هذه العملية I ترغب في الحصول على الدوار لطالما كان ذلك ضروريا.
وهكذا يمكن أن أفعله:
a=['|','/','-','\\']
aNow=0
# ... skip setup a big loop
print a[aNow]
aNow += 1
aNow = 0 if aNow == a.length
# ... do next step of process
print "\b"
ولكن اعتقد انها تريد ان تكون أنظف القيام به:
def spinChar
a=['|','/','-','\\']
a.cycle{|x| yield x}
end
# ... skip setup a big loop
print spinChar
# ... do next step of process
print "\b"
وبالطبع الدعوة spinChar تريد كتلة. إذا أعطيها كتلة انها سوف يتعطل أجل غير مسمى.
وكيف يمكنني الحصول على مجرد yeild القادم من هذه الكتلة؟
المحلول
ولا يعمل روبي yield
في الطريق ومثال الخاص شابه ذلك. ولكن هذا قد يكون مكانا جيدا ل إغلاق :
def spinner()
state = ['|','/','-','\\']
return proc { state.push(state.shift)[0] }
end
spin = spinner
# start working
print spin.call
# more work
print spin.call
# etc...
في ممارسة وأعتقد أن هذا الحل قد يكون أيضا "ذكية" لمصلحتها، ولكن فهم فكرة <لأ href = "http://www.rubycentral.com/pickaxe/ref_c_proc.html" يختلط = "نوفولو noreferrer "> Proc
الصورة يمكن أن تكون مفيدة على أية حال.
نصائح أخرى
وأنا أحب جميع هذه الاقتراحات، ولكن وجدت مولد في المكتبة القياسية، وأعتقد أنها أكثر على غرار ما أردت القيام به:
spinChar=Generator.new{ |g|
['|','/','-','\\'].cycle{ |x|
g.yield x
}
}
#then
spinChar.next
#will indefinitly output the next character.
والزيادات array index
عادي مع معامل على مجموعة المجمدة ويبدو أن أسرع.
وموضوع فلاد هو أنيق ولكن ليس بالضبط ما أردت. وفي spinner class
أن الزيادة من سطر واحد يكون أجمل إذا كان معتمدا روبي i++
مثل GLYPHS[@i++%GLYPHS.length]
وspinner closure
ماكس مع التحول دفع يبدو مكثفة قليلا بالنسبة لي، ولكن بناء الجملة الناتج هو بالضبط تقريبا مثل هذه المولدات. على الأقل أنا أعتقد أن هذا الإغلاق مع بروك في هناك.
وwith_spinner
تشاك هو في الواقع قريبة جدا إلى ما أردت، ولكن لماذا كسر إذا لم يكن لديك لمع مولد النحو الوارد أعلاه.
وفاديم، وذلك بفضل لافتا الى generator
سيكون بطيئا.
"Here's a test of 50,000 spins:"
user system total real
"array index" 0.050000 0.000000 0.050000 ( 0.055520)
"spinner class" 0.100000 0.010000 0.110000 ( 0.105594)
"spinner closure" 0.080000 0.030000 0.110000 ( 0.116068)
"with_spinner" 0.070000 0.030000 0.100000 ( 0.095915)
"generator" 6.710000 0.320000 7.030000 ( 7.304569)
وأعتقد أنك تسير في مسارها الصحيح مع cycle
. ماذا عن شيء مثل هذا:
1.8.7 :001 > spinner = ['|','/','-','\\'].cycle
=> #<Enumerable::Enumerator:0x7f111c165790>
1.8.7 :002 > spinner.next
=> "|"
1.8.7 :003 > spinner.next
=> "/"
1.8.7 :004 > spinner.next
=> "-"
1.8.7 :005 > spinner.next
=> "\\"
1.8.7 :006 > spinner.next
=> "|"
وأنا لا أعتقد أنك تفهم تماما ما يفعل yield
في روبي. فإنه لا يرجع قيمة من كتلة - يمر قيمة <م> إلى م> كتلة قمت تمريرها إلى الأسلوب إرفاق
وأعتقد أنك تريد شيئا أكثر من هذا القبيل:
def with_spinner
a=['|','/','-','\\']
a.cycle do |x|
print x
$stdout.flush # needed because standard out is usually buffered
yield # this will call the do-block you pass to with_spinner
end
end
with_spinner do
#process here
#break when done
end
وذات مرة، كتبت مجموعة. ولكنها ليست مجرد مجموعة، انها مجموعة لديها مؤشر، حتى تتمكن من الاتصال foreverrr القادم! http://gist.github.com/55955
وزوج هذه الفئة مع مكرر بسيطة أو حلقة وأنت الذهبي.
a = Collection.new(:a, :b, :c)
1000.times do |i|
puts a.current
a.next
end
والتعليمات البرمجية الخاصة بك قليلا من الداخل إلى الخارج، إذا كان عليك عفوا قول ذلك. :)
لماذا لا:
class Spinner
GLYPHS=['|','/','-','\\']
def budge
print "#{GLYPHS[@idx = ((@idx || 0) + 1) % GLYPHS.length]}\b"
end
end
spinner = Spinner.new
spinner.budge
# do something
spinner.budge
spinner.budge
# do something else
spinner.budge
على الآن ، أو إذا كنت تريد شيئا مثل:
with_spinner do
# do my big task here
end
... ثم عليك أن على استخدام متعدد خيوط : ل
def with_spinner
t = Thread.new do
['|','/','-','\\'].cycle { |c| print "#{c}\b" ; sleep(1) }
end
yield
Thread.kill(t) # nasty but effective
end
والكالينجيون، والجواب أعلاه الألغام هو كل القذرة.
a=['|','/','-','\\']
a << a
a.each {|item| puts item}