ทำไม Lua ถึงไม่มีคำสั่ง“ ต่อ”?


144

ฉันติดต่อกับ Lua เป็นอย่างมากในช่วงไม่กี่เดือนที่ผ่านมาและฉันชอบคุณสมบัติส่วนใหญ่ แต่ฉันก็ยังขาดอะไรบางอย่างอยู่:

  • ทำไมถึงไม่มีcontinue?
  • มีวิธีแก้ปัญหาอะไรบ้าง

12
เนื่องจากมีการถามคำถามนี้ Lua จึงมีgotoคำสั่งที่สามารถนำไปใช้เพื่อดำเนินการต่อได้ ดูคำตอบด้านล่าง
lhf

คำตอบ:


71

ใน Lua 5.2 วิธีแก้ปัญหาที่ดีที่สุดคือใช้ goto:

-- prints odd numbers in [|1,10|]
for i=1,10 do
  if i % 2 == 0 then goto continue end
  print(i)
  ::continue::
end

สิ่งนี้ได้รับการสนับสนุนใน LuaJIT ตั้งแต่รุ่น 2.0.1


47
ฉันหวังว่าพวกเขาจะรวมของจริงcontinueหนึ่งวัน การgotoแทนที่ไม่ได้ดูดีมากและต้องการบรรทัดเพิ่มเติม และนั่นจะไม่สร้างปัญหาถ้าคุณมีวงวนมากกว่าหนึ่งอันที่ทำสิ่งนี้ในฟังก์ชั่นเดียวทั้งคู่ด้วย::continue::? การสร้างชื่อต่อวงไม่ได้ฟังดูเหมือนเป็นเรื่องที่ควรทำ
ET

66

วิธีการที่ภาษาจัดการขอบเขตคำศัพท์สร้างปัญหากับทั้งและgoto continueตัวอย่างเช่น,

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ภายในหน้ากากร่างกายห่วงตัวแปรนอกชื่อaและขอบเขตของท้องถิ่นที่ทอดตัวข้ามเงื่อนไขของคำสั่งเพื่อให้อยู่ในสภาพที่มีการทดสอบด้านในสุดuntila

หากcontinueมีอยู่มันจะต้องถูก จำกัด ความหมายเพื่อให้ใช้ได้เฉพาะหลังจากตัวแปรทั้งหมดที่ใช้ในเงื่อนไขนั้นเข้ามาในขอบเขต นี่เป็นเงื่อนไขที่ยากในการจัดทำเอกสารให้กับผู้ใช้และบังคับใช้ในคอมไพเลอร์ มีการหารือข้อเสนอต่าง ๆ เกี่ยวกับปัญหานี้รวมถึงคำตอบง่ายๆที่ไม่อนุญาตให้continueใช้ในrepeat ... untilรูปแบบของการวนซ้ำ จนถึงขณะนี้ยังไม่มีกรณีการใช้ที่น่าสนใจเพียงพอที่จะรวมไว้ในภาษา

โดยทั่วไปแล้วการหลีกcontinueเลี่ยงเงื่อนไขที่จะทำให้ a ถูกดำเนินการและรวบรวมส่วนที่เหลือของลูปบอดี้ภายใต้เงื่อนไขนั้น ดังนั้นการวนซ้ำต่อไปนี้

-- 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

สามารถเขียนได้

-- 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

มีความชัดเจนเพียงพอและมักจะไม่เป็นภาระเว้นแต่คุณจะมีชุดของเครื่องมือที่ซับซ้อนซึ่งควบคุมการทำงานของลูป


5
มาจากพื้นหลังของไพ ธ อนนี่เป็นคำตอบที่สับสนเพราะทุกขอบเขตในนั้นรู้ว่าอะไรคือตัวแปรท้องถิ่นก่อนที่จะทำงาน until...คือผมคาดว่าจะมีข้อผิดพลาดที่ไม่ถูกผูกตัวแปรท้องถิ่นในกรณีของการเข้าถึง
ubershmekel

2
มีการถกเถียงกันอย่างนี้ในชุมชนลัวะก่อนที่จะนำgotoเข้าสู่ Lua 5.2 ธรรมชาติgotoมีปัญหาเดียวกัน ในที่สุดพวกเขาตัดสินใจว่าสิ่งที่รันไทม์และ / หรือค่าใช้จ่ายในการสร้างรหัสเพื่อป้องกันมันมีมูลค่าประโยชน์ของการมีความยืดหยุ่นgotoที่สามารถนำมาใช้เพื่อเลียนแบบทั้งสองและหลายระดับcontinue breakคุณจะต้องค้นหารายการใน Lua เพื่อดูรายการที่เกี่ยวข้องเพื่อรับรายละเอียด เนื่องจากพวกเขาแนะนำตัวgotoมันจึงไม่สามารถเอาชนะได้อย่างแน่นอน
RBerteig

72
ไม่มีอะไร "ชัดเจนเพียงพอ" เกี่ยวกับการเขียนโค้ดโดยไม่ต้องดำเนินการต่อ เป็นความผิดพลาดในการวางโค้ดในเงื่อนไขที่ควรใช้การดำเนินการต่อและความต้องการเขียนโค้ดที่น่าเกลียดอย่างที่ไม่ควรได้รับความเห็นอกเห็นใจ ไม่มีข้อแก้ตัวอย่างแน่นอน
Glenn Maynard

4
คำอธิบายนี้ไม่สมเหตุสมผล localคอมไพเลอร์เป็นเพียงคำสั่งเท่านั้น - ไม่สำคัญว่าการทำลายรันไทม์ระหว่างlocalและการใช้ตัวแปรคืออะไรคุณไม่จำเป็นต้องเปลี่ยนแปลงอะไรในคอมไพเลอร์เพื่อรักษาพฤติกรรมการกำหนดขอบเขตเดียวกัน ใช่สิ่งนี้อาจไม่ชัดเจนและต้องการเอกสารเพิ่มเติมบางส่วน แต่หากต้องการย้ำอีกครั้งจำเป็นต้องมีการเปลี่ยนแปลงค่าศูนย์ในคอมไพเลอร์ repeat do break end until trueตัวอย่างเช่นในคำตอบของฉันแล้วสร้างตรง bytecode เดียวกันกับที่คอมไพเลอร์จะมีการดำเนินการต่อความแตกต่างเพียงอย่างเดียวคือว่าcontinueคุณจะไม่จำเป็นต้องไวยากรณ์พิเศษที่น่าเกลียดที่จะใช้มัน
Oleg V. Volkov

7
ที่คุณสามารถทดสอบตัวแปรภายในพูดเกี่ยวกับการออกแบบที่มีข้อบกพร่อง เงื่อนไขอยู่นอกขอบเขตภายในและไม่ควรมีการเข้าถึงตัวแปรภายใน พิจารณาสิ่งที่เทียบเท่าใน C: do{int i=0;}while (i == 0);ล้มเหลวหรือใน C ++: do int i=0;while (i==0);ยังล้มเหลว ("ไม่ได้ประกาศในขอบเขตนี้") สายเกินไปที่จะเปลี่ยนว่าตอนนี้ใน Lua น่าเสียดาย
Pedro Gimeno

47

คุณสามารถล้อมร่างกายห่วงเพิ่มเติมrepeat until trueแล้วใช้do break endภายในเพื่อผลของการดำเนินการต่อ โดยปกติคุณจะต้องตั้งค่าสถานะเพิ่มเติมหากคุณตั้งใจจะbreakวนซ้ำเช่นกัน

ซึ่งจะวนซ้ำ 5 ครั้งพิมพ์ 1, 2 และ 3 ในแต่ละครั้ง

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

สิ่งปลูกสร้างนี้แปลเป็น opcode JMPใน Lua bytecode อย่างแท้จริง!

$ 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

4
คำตอบนี้ดี แต่ก็ยังต้องการ 3 บรรทัดแทนที่จะเป็นเพียงหนึ่งบรรทัด (หากรองรับ "ดำเนินการต่อ" อย่างเหมาะสม) มันค่อนข้างดีกว่าและปลอดภัยกว่าป้ายกำกับของ goto เนื่องจากสำหรับการปะทะกันของชื่อนั้นอาจต้องหลีกเลี่ยงการวนซ้ำซ้อนกัน
ET

3
อย่างไรก็ตามจะหลีกเลี่ยงปัญหา "ของจริง" กับ goto โดยที่คุณไม่จำเป็นต้องสร้างตัวระบุ / ป้ายกำกับใหม่สำหรับแต่ละ psuedo-continue และมีข้อผิดพลาดน้อยลงเนื่องจากรหัสถูกปรับเปลี่ยนตามเวลา ฉันเห็นด้วยว่าการดำเนินการต่อจะมีประโยชน์แต่ IMO นี้เป็นสิ่งที่ดีที่สุดถัดไป (และต้องมีสองบรรทัดสำหรับการทำซ้ำ / จนกระทั่งกับ "การดำเนินการต่อ" ที่เป็นทางการมากกว่านี้ .. .. และแม้กระทั่งถ้าคุณเกี่ยวข้องกับสาย นับคุณสามารถเขียน "ทำซ้ำ" และ "จนถึงจุดสิ้นสุดที่แท้จริง" ได้ตลอดเวลาตัวอย่างเช่น: gist.github.com/wilson0x4d/f8410719033d1e0ef771 )
Shaun Wilson

1
ดีที่จะเห็นคนจริงพิจารณาประสิทธิภาพการทำงานและได้ให้luacการส่งออกในดังนั้น!
โหวตขึ้นโหวตได้

17

ส่งตรงจากดีไซเนอร์ Lua :

ความกังวลหลักของเรากับ "ดำเนินการต่อ" คือมีโครงสร้างการควบคุมอื่น ๆ หลายอย่างที่ (ในมุมมองของเรา) มีความสำคัญไม่มากไปกว่า "ดำเนินการต่อ" และอาจแทนที่ได้ (เช่นแตกกับเลเบล [ใน Java] หรือแม้แต่ goto ทั่วไป) "ดำเนินการต่อ" ดูเหมือนจะไม่พิเศษกว่ากลไกโครงสร้างการควบคุมอื่น ๆ ยกเว้นว่ามีอยู่ในภาษาอื่น ๆ (Perl จริง ๆ มีสองข้อความ "ดำเนินการต่อ", "ถัดไป" และ "ทำซ้ำ" ทั้งสองมีประโยชน์)


5
ฉันรักการอนุญาติ: "ทั้งสองมีประโยชน์" ทันทีหลังจากคำอธิบายของ "เราจะไม่ไปทำมัน"
David Ljung Madison Stellar

2
มันเป็นที่จะต้องทราบขอบเขตที่ว่าพวกเขาถูกมองไปยังที่อยู่เมื่อพวกเขาได้ทำมันโดยการเพิ่ม "โกโตะ" สร้างใน 5.2 (ซึ่งไม่ได้รับการปล่อยออกมาเมื่อคำตอบนี้ถูกเขียน) ดูคำตอบนี้จาก 2012หลังจากปล่อย 5.2.0
Stuart P. Bentley

3
ถูกต้อง - เนื่องจาก 'goto' เป็นที่รู้จักกันดีว่าเป็นโครงสร้างการเขียนโปรแกรมที่ดี (ถากถางสุดท้าย) อืมม
David Ljung Madison Stellar

2
แต่มันก็ฟังดูไม่สมเหตุสมผลกว่า "ฉันลืมใส่continueLua ขอโทษ"
neoedmund

17

ส่วนแรกจะได้รับการตอบในคำถามที่พบบ่อยตามที่สังหารชี้ให้เห็น

สำหรับวิธีแก้ปัญหาคุณสามารถพันร่างของลูปในฟังก์ชันและreturnก่อนหน้านั้นได้เช่น

-- 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

หรือถ้าคุณต้องการทั้งฟังก์ชั่นbreakและcontinueฟังก์ชั่นให้ฟังก์ชั่นท้องถิ่นทำการทดสอบเช่น

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

16
โปรดอย่า คุณสร้างสภาพแวดล้อมการปิดในแต่ละการวนซ้ำและนี่เป็นความทรงจำมากมายและรอบ GC
Oleg V. Volkov

4
ไปตรวจสอบcollectgarbage("count")แม้หลังจากพยายาม 100 ครั้งง่ายๆแล้วเราจะคุยกัน การเพิ่มประสิทธิภาพ "ก่อนกำหนด" ดังกล่าวช่วยให้โครงการไฮโหลดหนึ่งโครงการไม่สามารถรีบูตได้ทุกนาทีในสัปดาห์ที่แล้ว
Oleg V. Volkov

4
@ OlegV.Volkov ในขณะที่ตัวอย่างนี้ทำให้โหลดค่อนข้างสูงใน GC มันจะไม่รั่วไหล - การปิดชั่วคราวทั้งหมดจะถูกเก็บรวบรวม ฉันไม่รู้เกี่ยวกับโครงการของคุณ แต่ IME การรีบูตซ้ำส่วนใหญ่เกิดจากการรั่วไหล
finnw

10

ฉันไม่เคยใช้ Lua มาก่อน แต่ฉัน Googled และมากับสิ่งนี้:

http://www.luafaq.org/

ตรวจสอบคำถาม 1.26

นี่คือการร้องเรียนทั่วไป ผู้เขียน Lua รู้สึกว่าการดำเนินการต่อเป็นเพียงหนึ่งในกลไกการควบคุมการไหลที่เป็นไปได้ใหม่จำนวนหนึ่ง (ความจริงที่ว่ามันไม่สามารถทำงานกับกฎขอบเขตการทำซ้ำ / จนกระทั่งเป็นปัจจัยรอง)

ใน Lua 5.2 มีคำสั่ง goto ซึ่งสามารถใช้ในการทำงานเดียวกันได้อย่างง่ายดาย


8

เราสามารถทำได้ดังนี้ด้านล่างมันจะข้ามตัวเลข

local len = 5
for i = 1, len do
    repeat 
        if i%2 == 0 then break end
        print(" i = "..i)
        break
    until true
end

O / P:

i = 1
i = 3
i = 5

6

เราพบสถานการณ์นี้หลายครั้งและเราก็ใช้การตั้งค่าสถานะเพื่อจำลองการดำเนินการต่อ เราพยายามหลีกเลี่ยงการใช้คำสั่ง goto เช่นกัน

ตัวอย่าง: รหัสตั้งใจพิมพ์คำสั่งจาก i = 1 ถึง i = 10 ยกเว้น i = 3 นอกจากนี้ยังพิมพ์ "loop start", loop end "," if start "และ" if end "เพื่อจำลองคำสั่งที่ซ้อนกันอื่น ๆ ที่มีอยู่ในรหัสของคุณ

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

ทำได้โดยการแนบคำแถลงที่เหลือทั้งหมดจนกระทั่งขอบเขตสิ้นสุดของลูปด้วยแฟล็กทดสอบ

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

ฉันไม่ได้บอกว่านี่เป็นวิธีการที่ดีที่สุด แต่ใช้ได้ดีกับเรา


5

Lua เป็นภาษาสคริปต์ที่มีน้ำหนักเบาซึ่งต้องการเล็กลงที่สุด ตัวอย่างเช่นการดำเนินการ unary จำนวนมากเช่นการเพิ่มก่อน / หลังไม่พร้อมใช้งาน

แทนที่จะดำเนินการต่อคุณสามารถใช้ข้ามเช่น

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

4

คุณสามารถใช้รหัสต่อไปนี้อีกครั้งด้วยการสลับกลับ:

for k,v in pairs(t) do
  if not isstring(k) then 
    -- do something to t[k] when k is not a string
end

ปัญหาเกี่ยวกับการผกผันคือบ่อยครั้งกว่าไม่มีหลายเงื่อนไขในซีรีส์ (เช่นเพื่อตรวจสอบการป้อนข้อมูลผู้ใช้) และเนื่องจากอาจจำเป็นต้องมีไฟฟ้าลัดวงจรในทุกจุดตลอดทางการผกผันหมายถึงการวางเงื่อนไขไว้อย่างต่อเนื่อง (แทนที่จะเป็น "เลวร้ายนี้หรือไม่แล้วหลบหนี; อื่นเลวนี้แล้วหนี" ซึ่งตรงไปตรง คุณท้ายด้วยรหัสเช่น "ไม่เป็นไรแล้วนี้ไม่เป็นไรแล้วเป็นไรได้หรือไม่แล้วทำเช่นนี้" ซึ่งมากเกินไป
Leslie Krause

-2

ทำไมไม่มีการดำเนินการต่อ?

เพราะมันไม่จำเป็น¹ มีสถานการณ์น้อยมากที่ผู้พัฒนาต้องการมัน

A) เมื่อคุณมีวงวนที่ง่ายมากให้พูด 1 หรือ 2 ซับจากนั้นคุณก็สามารถหมุนสภาพลูปไปรอบ ๆ และมันยังคงอ่านได้มากมาย

B) เมื่อคุณกำลังเขียนโค้ดขั้นตอนง่าย ๆ (aka วิธีที่เราเขียนโค้ดในศตวรรษที่ผ่านมา) คุณควรใช้การเขียนโปรแกรมแบบมีโครงสร้าง (aka. วิธีที่เราเขียนโค้ดที่ดีกว่าในศตวรรษที่ผ่านมา)

C) ถ้าคุณกำลังเขียนโค้ดเชิงวัตถุร่างกายลูปของคุณควรประกอบด้วยการเรียกใช้วิธีไม่เกินหนึ่งหรือสองวิธีเว้นแต่ว่ามันจะสามารถแสดงในหนึ่งหรือสองซับ (ในกรณีนี้ดู A)

D) หากคุณกำลังเขียนโค้ดที่ใช้งานได้ให้ส่งค่าโทรกลับแบบธรรมดาสำหรับการทำซ้ำครั้งถัดไป

กรณีเดียวเมื่อคุณต้องการใช้continueคำหลักคือถ้าคุณต้องการให้รหัส Lua เหมือนกับเป็นงูหลามซึ่งเป็นเพียงไม่ได้²

มีวิธีแก้ปัญหาอะไรบ้าง

ยกเว้น A) ใช้ซึ่งในกรณีนี้ไม่จำเป็นต้องแก้ไขปัญหาใด ๆ คุณควรทำการเขียนโปรแกรมแบบโครงสร้างเชิงวัตถุหรือเชิงฟังก์ชัน นี่คือกระบวนทัศน์ที่ Lua สร้างขึ้นดังนั้นคุณจะต้องต่อสู้กับภาษาถ้าคุณพยายามหลีกเลี่ยงรูปแบบของพวกเขา”


ชี้แจงบางส่วน:

¹ Lua เป็นภาษาที่เรียบง่ายมาก มันพยายามที่จะมีคุณสมบัติน้อยที่สุดเท่าที่จะทำได้และcontinueแถลงการณ์ไม่ใช่คุณสมบัติที่สำคัญในแง่นั้น

ฉันคิดว่าปรัชญาของความเรียบง่ายนี้ถูกจับได้เป็นอย่างดีโดยRoberto Ierusalimschyในการสัมภาษณ์ปี 2019นี้:

เพิ่มนั้นและนั่นและที่นำออกและในท้ายที่สุดเราเข้าใจข้อสรุปสุดท้ายจะไม่ตอบสนองคนส่วนใหญ่และเราจะไม่ใส่ตัวเลือกทั้งหมดที่ทุกคนต้องการดังนั้นเราจึงไม่ใส่อะไรเลย ในที่สุดโหมดที่เข้มงวดคือการประนีประนอมที่เหมาะสม

²ดูเหมือนว่ามีโปรแกรมเมอร์จำนวนมากที่มาที่ Lua จากภาษาอื่น ๆ เพราะโปรแกรมใดก็ตามที่พวกเขากำลังพยายามที่จะเขียนสคริปต์เพื่อใช้งานและหลายคนต้องการดูเหมือนจะไม่ต้องการเขียนอะไรนอกจากภาษาของพวกเขา ตัวเลือกซึ่งนำไปสู่คำถามมากมายเช่น "ทำไม Lua จึงไม่มีฟีเจอร์ X"

Matzอธิบายสถานการณ์ที่คล้ายกันกับ Ruby ในการสัมภาษณ์เมื่อเร็ว ๆ นี้ :

คำถามที่ได้รับความนิยมมากที่สุดคือ: "ฉันมาจากชุมชนภาษา X คุณไม่สามารถแนะนำคุณสมบัติจากภาษา X ถึง Ruby ได้หรือไม่" หรืออะไรทำนองนั้น และคำตอบปกติของฉันสำหรับคำขอเหล่านี้คือ ... "ไม่ฉันจะไม่ทำอย่างนั้น" เพราะเรามีการออกแบบภาษาที่แตกต่างกันและนโยบายการพัฒนาภาษาที่แตกต่างกัน

³มีหลายวิธีในการแฮ็กข้อมูลของคุณ ผู้ใช้บางคนแนะนำให้ใช้gotoซึ่งเป็นสิ่งที่ดีพอในกรณีส่วนใหญ่ แต่ก็น่าเกลียดมากอย่างรวดเร็วและแยกออกเป็นสองกลุ่มด้วยลูปซ้อนกัน การใช้gotos ยังทำให้คุณตกอยู่ในอันตรายจากการมีสำเนาของ SICP ที่ส่งถึงคุณเมื่อใดก็ตามที่คุณแสดงรหัสของคุณให้กับบุคคลอื่น


1
ฉันลงคะแนนเพราะประโยคแรกเป็นเท็จอย่างเห็นได้ชัดและคำตอบที่เหลือก็ไม่ช่วยเหลือ
bfontaine

ช่วยเหลือ? อาจจะ; มันเป็นคำตอบที่ค่อนข้างใช้ความเห็น เห็นได้ชัดว่าประโยคแรกนั้นจริง continueอาจจะเป็นคุณลักษณะที่สะดวก แต่นั่นก็ไม่ได้ทำให้มันจำเป็น ผู้คนจำนวนมากใช้ Lua ไม่เป็นไรดังนั้นจึงไม่มีกรณีใดที่จะเป็นสิ่งอื่นนอกเหนือจากคุณสมบัติที่เป็นระเบียบซึ่งไม่จำเป็นสำหรับการเขียนโปรแกรมภาษาใด ๆ
DarkWiiPlayer

นั่นไม่ใช่การโต้แย้ง: คุณไม่สามารถโต้แย้งได้ว่าผู้คน "ดีถ้าไม่มี" เมื่อพวกเขาไม่มีทางเลือก
bfontaine

ฉันคิดว่าเรามีคำจำกัดความที่แตกต่างกันของ "จำเป็น" แล้ว
DarkWiiPlayer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.