Yanıtlar:
Lua 5.2'de en iyi çözüm goto kullanmaktır:
-- prints odd numbers in [|1,10|]
for i=1,10 do
if i % 2 == 0 then goto continue end
print(i)
::continue::
end
Bu sürüm 2.0.1'den beri LuaJIT'de desteklenmektedir
continue
bir gün içerirler . goto
Yedek çok güzel bakmak ve daha hatları ihtiyacı yoktur. Ayrıca, bunu bir işlevde birden fazla döngü yapsaydı sorun yaratmaz ::continue::
mıydı? Her döngü için bir ad oluşturmak iyi bir şey gibi gelmiyor.
Dilin sözcüksel kapsamı yönetme biçimi hem goto
ve ile ilgili sorunlar oluşturur continue
. Örneğin,
local a=0
repeat
if f() then
a=1 --change outer a
end
local a=f() -- inner a
until a==0 -- test inner a
local a
Döngü gövdesinin içindeki bildirimi adlı dış değişkeni maskeler ve a
bu yerelin kapsamı until
ifadenin koşulu boyunca uzanır, böylece koşul en içteki testi yapar a
.
Varsa continue
, semantik olarak ancak koşulda kullanılan tüm değişkenler kapsama girdikten sonra geçerli olması için kısıtlanması gerekir. Bu, kullanıcıyı belgelemek ve derleyicide uygulamak zor bir durumdur. Bu soruna geçici muhtelif öneriler izin vermeme basit cevabı dahil tartışılmıştır continue
ile repeat ... until
döngü tarzında. Şimdiye kadar hiçbirinin dilde yer almasını sağlamak için yeterince zorlayıcı bir kullanım durumu olmadı.
Geçici çözüm genellikle a'nın continue
yürütülmesine neden olacak koşulu tersine çevirmek ve bu durumda döngü gövdesinin geri kalanını toplamaktır. Yani, aşağıdaki döngü
-- not valid Lua 5.1 (or 5.2)
for k,v in pairs(t) do
if isstring(k) then continue end
-- do something to t[k] when k is not a string
end
yazılabilir
-- valid Lua 5.1 (or 5.2)
for k,v in pairs(t) do
if not isstring(k) then
-- do something to t[k] when k is not a string
end
end
Döngü işlemini kontrol eden bir dizi ayrıntılı cull'ınız yoksa, yeterince açıktır ve genellikle bir yük değildir.
until...
.
goto
. Doğal olarak, goto
aynı meseleye sahiptir. Sonunda, çalışma zamanı ve / veya kod oluşturma maliyetleri ne olursa olsun, ona karşı koruma sağlamak için her ne olursa olsun, goto
hem continue
çok seviyeli hem de taklit etmek için kullanılabilecek bir esnekliğe sahip olmanın faydalarına değdiğine karar verdiler break
. Ayrıntıları almak için Lua liste arşivlerinde ilgili dizileri aramanız gerekir . Onlar tanıttıklarından beri goto
aşılmaz bir şey değildi.
local
yalnızca derleyici direktifidir - hangi çalışma zamanı insructions local
ve değişken kullanım arasında olduğu önemli değildir - aynı kapsam belirleme davranışını sürdürmek için derleyicide hiçbir şeyi değiştirmeniz gerekmez. Evet, bu çok açık olmayabilir ve bazı ek belgelere ihtiyaç duyabilir, ancak tekrarlamak için derleyicide SIFIR değişiklikleri gerektirir. repeat do break end until true
cevabım örnek zaten üretir tam derleyici ile devam edeceğini aynı bayt kodu, tek fark ile ki continue
çirkin ekstra sözdizimi gerek olmazdı kullanmak.
do{int i=0;}while (i == 0);
başarısız veya C ++: eşdeğer de başarısız olduğunu düşünün do int i=0;while (i==0);
("bu kapsamda bildirilmedi"). Maalesef şimdi Lua'da bunu değiştirmek için çok geç.
Döngü gövdesini ek olarak sarın repeat until true
ve sonra do break end
devam etmenin etkisi için içeride kullanabilirsiniz . Doğal olarak, gerçekten break
de döngüden çıkmayı düşünüyorsanız ek bayraklar ayarlamanız gerekir .
Bu, her seferinde 1, 2 ve 3 yazdırarak 5 kez dönecektir.
for idx = 1, 5 do
repeat
print(1)
print(2)
print(3)
do break end -- goes to next iteration of for
print(4)
print(5)
until true
end
Bu yapı JMP
, Lua bayt kodundaki gerçek bir opcode bile anlamına geliyor !
$ luac -l continue.lua
main <continue.lua:0,0> (22 instructions, 88 bytes at 0x23c9530)
0+ params, 6 slots, 0 upvalues, 4 locals, 6 constants, 0 functions
1 [1] LOADK 0 -1 ; 1
2 [1] LOADK 1 -2 ; 3
3 [1] LOADK 2 -1 ; 1
4 [1] FORPREP 0 16 ; to 21
5 [3] GETGLOBAL 4 -3 ; print
6 [3] LOADK 5 -1 ; 1
7 [3] CALL 4 2 1
8 [4] GETGLOBAL 4 -3 ; print
9 [4] LOADK 5 -4 ; 2
10 [4] CALL 4 2 1
11 [5] GETGLOBAL 4 -3 ; print
12 [5] LOADK 5 -2 ; 3
13 [5] CALL 4 2 1
14 [6] JMP 6 ; to 21 -- Here it is! If you remove do break end from code, result will only differ by this single line.
15 [7] GETGLOBAL 4 -3 ; print
16 [7] LOADK 5 -5 ; 4
17 [7] CALL 4 2 1
18 [8] GETGLOBAL 4 -3 ; print
19 [8] LOADK 5 -6 ; 5
20 [8] CALL 4 2 1
21 [1] FORLOOP 0 -17 ; to 5
22 [10] RETURN 0 1
luac
çıktı sağladığını görmek güzel ! Have a well desved upvote :)
Doğrudan Lua'nın tasarımcısından :
"Devam" ile ilgili temel kaygımız, (bizim görüşümüze göre) "devam" kadar az ya da çok önemli olan ve hatta yerini alabilecek başka kontrol yapıları olmasıdır. (Örneğin, [Java'da olduğu gibi] etiketleriyle kırın veya daha genel bir goto.) "Devam", daha fazla dilde mevcut olması dışında, diğer kontrol yapısı mekanizmalarından daha özel görünmemektedir. (Perl aslında iki "devam" ifadesine sahiptir, "sonraki" ve "yinele". Her ikisi de yararlıdır.)
continue
Lua'ya koymayı unuttum , üzgünüm " den daha mantıklı gelmedi .
İlk bölüm SSS'de öldürüldüğü gibi cevaplanmıştır .
Geçici bir çözüme gelince, döngünün gövdesini bir işlevde ve bundan return
erken, örneğin ör.
-- Print the odd numbers from 1 to 99
for a = 1, 99 do
(function()
if a % 2 == 0 then
return
end
print(a)
end)()
end
Veya her ikisini de break
ve continue
işlevsellik istiyorsanız , yerel işlevin testi gerçekleştirmesini sağlayın, örn.
local a = 1
while (function()
if a > 99 then
return false; -- break
end
if a % 2 == 0 then
return true; -- continue
end
print(a)
return true; -- continue
end)() do
a = a + 1
end
collectgarbage("count")
basit 100 denemenizden sonra bile kontrol edin, sonra konuşacağız. Bu tür "erken" optimizasyon, bir yüksek yük projesini geçen hafta her dakika yeniden başlatmaktan kurtardı.
Lua'yı daha önce hiç kullanmadım, ama Googled ve bununla geldim:
Soru 1.26'yı kontrol edin .
Bu yaygın bir şikayettir. Lua yazarları, devam etmenin olası yeni kontrol akış mekanizmalarından sadece biri olduğunu hissettiler (tekrar / kapsam kurallarıyla çalışamaması ikincil bir faktördü.)
Lua 5.2'de, aynı işi yapmak için kolayca kullanılabilecek bir goto ifadesi vardır.
Bu senaryo ile birçok kez karşılaştık ve devam etmeyi simüle etmek için bir bayrak kullanıyoruz. Goto ifadelerinin kullanımından da kaçınmaya çalışıyoruz.
Örnek: Kod, i = 3 dışında i = 1'den i = 10'a kadar olan ifadeleri yazdırmayı amaçlamaktadır. Ayrıca, kodunuzda bulunan diğer iç içe ifadeleri simüle etmek için "loop start", loop end "," start "ve" if end "de yazdırır.
size = 10
for i=1, size do
print("loop start")
if whatever then
print("if start")
if (i == 3) then
print("i is 3")
--continue
end
print(j)
print("if end")
end
print("loop end")
end
geri kalan tüm ifadelerin bir test bayrağıyla döngünün sonuna kadar eklenmesiyle elde edilir.
size = 10
for i=1, size do
print("loop start")
local continue = false; -- initialize flag at the start of the loop
if whatever then
print("if start")
if (i == 3) then
print("i is 3")
continue = true
end
if continue==false then -- test flag
print(j)
print("if end")
end
end
if (continue==false) then -- test flag
print("loop end")
end
end
Bunun en iyi yaklaşım olduğunu söylemiyorum ama bizim için mükemmel çalışıyor.
Lua, olabildiğince küçülmek isteyen hafif bir betik dilidir. Örneğin, öncesi / sonrası artış gibi birçok tekli işlem kullanılamaz
Devam etmek yerine,
arr = {1,2,3,45,6,7,8}
for key,val in ipairs(arr) do
if val > 6 then
goto skip_to_next
end
# perform some calculation
::skip_to_next::
end
Yine ters çevirme ile aşağıdaki kodu kullanabilirsiniz:
for k,v in pairs(t) do
if not isstring(k) then
-- do something to t[k] when k is not a string
end
Çünkü gereksiz¹. Bir geliştiricinin buna ihtiyaç duyacağı çok az durum vardır.
A) Çok basit bir döngüye sahip olduğunuzda, 1 ya da 2 astarlı, döngü döngüsünü döndürebilirsiniz ve yine de okunabilir.
B) Basit yordamsal kod yazarken (yani geçen yüzyılda nasıl kod yazdığımız), ayrıca yapılandırılmış programlama (yani geçen yüzyılda nasıl daha iyi kod yazdığımız) uygulamalısınız.
C) Nesneye yönelik kod yazıyorsanız, döngü gövdesiniz, bir veya iki satırda ifade edilemediği sürece, en fazla bir veya iki yöntem çağrısından oluşmamalıdır (bu durumda, bkz. A).
D) İşlevsel kod yazıyorsanız, sonraki yineleme için basit bir kuyruk çağrısı döndürmeniz yeterlidir.
Bir continue
anahtar kelime kullanmak istediğinizde, Lua'yı python gibi kodlamak istiyorsanız, ki bu sadece değildir.
A) uygulanmadığı sürece, bu durumda herhangi bir geçici çözüme gerek yoktur, Yapısal, Nesneye Dayalı veya Fonksiyonel programlama yapmanız gerekir. Bunlar Lua'nın inşa edildiği paradigmalar, bu yüzden kalıplarından kaçınmak için yolunuzdan çıkarsanız dile karşı savaşıyorsunuz.
Bazı açıklamalar:
Ua Lua çok minimalist bir dildir. Kaçabileceği kadar az özelliğe sahip olmaya çalışır ve bir continue
ifade bu anlamda önemli bir özellik değildir.
Bu minimalizm felsefesinin bu 2019 röportajında Roberto Ierusalimschy tarafından iyi yakalandığını düşünüyorum :
bunu ve bunu ekleyin ve bunu ortaya koyun ve sonunda nihai sonucun çoğu insanı tatmin etmeyeceğini anlıyoruz ve herkesin istediği tüm seçenekleri koymayacağız, bu yüzden hiçbir şey koymuyoruz. Sonunda, katı mod makul bir uzlaşmadır.
² Diğer dillerden Lua'ya gelen büyük miktarda programcı var gibi görünüyor çünkü komut dosyası oluşturmaya çalıştıkları program ne olursa olsun bunu kullanıyor ve birçoğu kendi dillerinden başka bir şey yazmak istemiyor gibi görünüyor "Lua'da neden X özelliği yok?"
Matz , yakın tarihli bir röportajda Ruby ile benzer bir durumu şöyle anlattı :
En popüler soru şudur: "X dil toplumundanım; X dilinden Ruby diline bir özellik tanıtamaz mısınız?" Veya bunun gibi bir şey. Ve bu isteklere her zamanki cevabım… “hayır, bunu yapmam” çünkü farklı dil tasarımı ve farklı dil geliştirme politikalarımız var.
³ Bu konuda yolunuzu kesmenin birkaç yolu vardır; bazı kullanıcılar, goto
çoğu durumda yeterince iyi bir yaklaşım olan, ancak çok çirkinleşir ve iç içe döngülerle tamamen kırılır. S kullanmanız goto
, kodunuzu başkalarına her gösterdiğinizde SICP'nin bir kopyasının size atılma tehlikesini de beraberinde getirir.
continue
uygun bir özellik olabilir, ama bu yapmaz gerekli . Birçok insan Lua'yı onsuz iyi kullanır, bu nedenle herhangi bir programlama Dili için gerekli olmayan düzgün bir özellikten başka bir şey olması gerçekten hiçbir durum yoktur.
goto
devam etmek için kullanılabilecek bir açıklama aldı . Aşağıdaki cevaplara bakın.