สำนวนคืออะไร?


19

ฉันเข้าใจ "สำนวน" เพื่อเป็นการดำเนินการทั่วไปหรือรูปแบบที่ในภาษาเฉพาะไม่ง่ายโดยไวยากรณ์ภาษาหลักเช่นการเพิ่มจำนวนเต็ม:

i = i + 1;

ใน C ++ สำนวนนี้จะทำให้ผู้ปฏิบัติงานง่ายขึ้น:

++i;

อย่างไรก็ตามเมื่อมีคนใช้คำว่า "สำนวน" ฉันไม่แน่ใจว่าจะเข้าใจมันอย่างไร อะไรทำให้ชิ้นส่วนของรหัส "สำนวน"?


สิ่งนี้มีมากในenglish.stackexchange.comเช่นเดียวกับที่นี่
S.Lott

@ perl.j: เข้าใจอย่างถ่องแท้ คุณได้ชี้แจงให้ชัดเจนว่าเหตุใดคำจำกัดความของ "Idiomatic" จึงไม่ได้อยู่ใน english.stackexchange.com มีประโยชน์มาก
S.Lott

คำตอบ:


24

วิธีการเขียนรหัสบางอย่างเป็นสำนวนคือเมื่อคุณเขียนในลักษณะที่เฉพาะเจาะจงมากเนื่องจากสำนวนเฉพาะภาษาที่ภาษาอื่นไม่มี

ตัวอย่างเช่นใน C ++ การหาประโยชน์จาก RAII idiom นำไปสู่วิธีการเขียนรหัส C ++ ที่ใช้ในการจัดการทรัพยากรที่เป็นสำนวน

อีกตัวอย่างหนึ่งคือการใช้ list comprehensions ใน Python เพื่อสร้าง list มันเป็นสำนวนเพราะคุณจะต้องใช้ list comprehension ใน idiomatic Python แต่คุณสามารถทำได้เหมือนกันโดยใช้ฟังก์ชันตัวสร้างในภาษาอื่นหรือแม้แต่ใน Python

บ่อยครั้งที่บางคนพยายามใช้ภาษาใหม่โดยไม่ใช้สำนวนเฉพาะภาษานี้จะไม่เขียนรหัสสำนวน


คำอธิบายที่ยอดเยี่ยม ดังนั้นใน C # ถ้าฉันสร้างวิธีการขยายที่เรียกว่าTryAdd()ในDictionaryคลาสทั่วไปเพื่อตรวจสอบก่อน!Contains()แล้วจึงเรียกAdd()มันจะเป็นสำนวน? ฉันใช้คุณสมบัติเฉพาะสำหรับ C # - วิธีการขยาย
void.pointer

1
ฉันไม่แน่ใจเหมือน coder c ++ ที่มีประสบการณ์มากที่สุดจะบอกให้คุณเขียนฟังก์ชั่นฟรีเพื่อขยายคลาสแทนการเพิ่มสมาชิกหากเป็นไปได้ มันไม่เหมือนกับวิธีการขยาย C # แต่ค่อนข้างใกล้เคียงกับภาษาใด ๆ ที่อนุญาตให้ใช้ฟังก์ชันฟรี สิ่งที่ฉันแน่ใจคือการเขียน "set / getters" ใน C # โดยใช้คุณสมบัติ IS เป็นสำนวน
Klaim

แต่นี่ไม่ใช่ C ++ ดังนั้นการใช้ "C ++ way" อาจไม่เป็น "สำนวน" มากพอ การใช้วิธีการขยายที่นี่มีเหตุผลและเหมือน C # มาก ไม่ว่าในกรณีใดมันเป็นตัวอย่าง แต่วิธีการขยายนั้นมีความหมายเฉพาะกับ C # มาก
void.pointer

ใช่นั่นคือเหตุผลที่ฉันพูดว่า "ฉันไม่แน่ใจ" มันให้ความรู้สึกแปลก ๆ แต่ใกล้เคียงกับคุณสมบัติพื้นฐานอื่น ๆ ของภาษาอื่น ๆ ที่ฉันไม่แน่ใจ (เพราะฉันไม่ใช่ C # dev) ฉันมีตัวอย่างอื่น: การวนซ้ำทำได้โดยการเรียกซ้ำในภาษาที่ใช้งานได้ทั้งหมด คุณสามารถทำได้ในภาษาอื่น แต่เห็นได้ชัดว่ามันเป็นสำนวนภาษาที่ใช้งานได้ ไม่แน่ใจว่ามันช่วยได้หรือไม่
Klaim

1
แน่นอนว่าไพ ธ อนนั้นก้าวไปอีกขั้นหนึ่งโดยการใช้วิธีการอ้างอิงถึงรหัสสำนวนเช่นไพทอน * 8 ')
Mark Booth

12

คำจำกัดความปกติ

การใช้ที่มีหรือแสดงถึงการแสดงออกที่เป็นธรรมชาติของเจ้าของภาษา

นิยามการเขียนโปรแกรม

การใช้มีหรือแสดงถึงนิพจน์ที่เป็นธรรมชาติสำหรับโปรแกรมเมอร์[แทรกภาษา]


1
ถ้าฉันคิดว่าคำนิยาม "google" สำหรับคำนี้มีประโยชน์ฉันจะไม่โพสต์ที่นี่ ฉันต้องการคำอธิบายที่ดีกว่า (เหมือนกวดวิชา) พร้อมตัวอย่าง
void.pointer

3
@ Robert - ฉันเดาว่าฉันไม่เข้าใจว่าทำไมคุณไม่เข้าใจ
ChaosPandion

2
ฉันอ่านคำตอบของคุณก่อนมันไม่ชัดเจน หลังจากอ่านคำตอบที่ถูกทำเครื่องหมายว่าเป็นคำตอบของฉันแล้วมันชัดเจนมากว่า "สำนวน" หมายถึงอะไรและตอนนี้ฉันเข้าใจแล้ว ตอนนี้ฉันอ่านคำตอบของคุณมันสมเหตุสมผลแล้ว อย่างไรก็ตามคุณไม่ได้พาฉันไปดูตัวอย่างและสถานการณ์ที่แตกต่างกันซึ่งเป็นเหตุผลที่ฉันคิดว่าคำตอบของคุณไม่เป็นประโยชน์ คุณให้คำตอบ "เว็บสเตอร์" ซึ่งถูกต้องทางเทคนิค แต่ไม่เป็นประโยชน์เท่าที่ช่วยฉันเข้าใจ ฉันขอขอบคุณสำหรับความช่วยเหลือของคุณ
void.pointer

7

สำนวนในบริบทของการเขียนโปรแกรมมักจะถูกกำหนดให้เป็น "วิธีธรรมชาติที่สุดในการแสดงบางสิ่งบางอย่างในภาษา"

ฉันเห็นคำว่าสำนวนขึ้นมาโดยเฉพาะอย่างยิ่งในทับทิม ใน Ruby มีความสามารถในการเขียนโปรแกรมเมตาขนาดใหญ่และในการเขียนโค้ด Ruby แบบสำนวนคุณต้องใช้รหัสเหล่านี้

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

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

ตัวอย่างภาษาอังกฤษเป็นสำนวนสามารถขึ้นอยู่กับภูมิภาค การใช้คำbumอาจเป็นสิ่งจำเป็นสำหรับภาษาอังกฤษแบบสหราชอาณาจักรในขณะbuttที่เหมาะสมสำหรับภาษาอังกฤษแบบสหรัฐอเมริกา (ฉันไม่รู้ภาษาอังกฤษสหราชอาณาจักรเท่าไรเศร้า: /)


ขอบคุณ (upvoted) ฉันคิดว่าคำนิยามของคุณถูกต้องตรงประเด็นสำหรับฉัน!
Ashaman Kingpin

3

ตัวอย่างที่ดีที่สุดที่ฉันสามารถประดิษฐ์ออกจากหัวของฉันสำหรับสิ่งที่เป็นสำนวนมาจากทับทิม

ในภาษาที่หลากหลายคุณสามารถทำซ้ำได้ด้วย:

for( start; end; increment){
    code;
}

หรือสิ่งที่คล้ายกันมาก หลายภาษามีforeach(x in SetOfXes)โครงสร้าง แต่การทำซ้ำที่เป็นสำนวนถึงทับทิมรวมถึงสิ่งที่ชอบ:

collection.each do |current|
  current.do_stuff
end

และแม้กระทั่ง

10.times do |x|
  puts x
end

ฉันเห็นสิ่งเหล่านี้เป็นสำนวนเพราะพวกเขาเป็นตัวแทนของวิธีการทำบางสิ่งบางอย่างที่ไม่ธรรมดา Ruby มีปรัชญาเกี่ยวกับการโต้ตอบกับวัตถุต่าง ๆ ที่ไม่ซ้ำกัน

ในบันทึกความหมายเมื่อใดก็ตามที่ฉันได้ยินคำว่าสำนวนสมองของฉันจะคิดว่า "สำนวนถึง ... " โดยอัตโนมัติ - ฉันแค่แยกวิเคราะห์มันเกี่ยวกับเรื่องเฉพาะ


เป็นวิธีการที่collection.each do |current|แตกต่างจากforeach(current in collection)? ทั้งสองมีโครงสร้างห่วงว่าชุดองค์ประกอบของแต่ละcurrent collection
MSalters

2

สำนวนมักเป็นวิธีที่ดีที่สุดในการแสดงสถานการณ์ทั่วไปที่ค่อนข้างซับซ้อนในภาษา การเพิ่มขึ้นไม่ใช่สำนวนหรือสิ่งใด ๆ ใช้การเพิ่มคำนำหน้าแทน postfix คุณสามารถยืนยันว่าเป็นสำนวน C ++

สำนวนเป็นวิธีที่ดีที่สุดในการใช้ภาษาตามที่กำหนดโดยผู้ใช้ที่เชี่ยวชาญ สำนวน C ++ จริงจะเป็นวัตถุฟังก์ชั่น สำนวนอื่นจะเป็น RAII ไม่มีสิ่งใดในภาษาที่บอกคุณว่าคุณต้องเพิ่มทรัพยากรใน destructor แต่มันเป็นสำนวนที่จะทำเช่นนั้น อีกตัวอย่างหนึ่งคือเทมเพลต - มันเป็นเรื่องธรรมดาที่จะใช้เทมเพลตสำหรับทุกอย่างที่คุณทำได้ แต่ไม่มีอะไรหยุดยั้งคุณได้มากกว่าการใช้มรดก


Wikipedia ใช้การเพิ่มค่าเป็นตัวอย่างดังนั้นฉันจึงพูดถึงสิ่งนี้ในคำถามของฉัน ทำไมสำนวนต้องมีความซับซ้อน? ดูเหมือนจะไม่ได้เป็นส่วนหนึ่งของคำนิยามตามคำตอบอื่น ๆ
void.pointer

4
@ Robert Dailey: การเพิ่มขึ้นอาจเป็นสำนวนได้อย่างไร? มันเป็นส่วนหนึ่งของภาษา สำนวนถูกสร้างขึ้นโดยผู้ใช้ภาษาพวกเขาเปลี่ยนแปลงตลอดเวลา การเพิ่มไม่ได้เป็นสำนวน แต่เป็นฟังก์ชั่นพื้นฐานของภาษา จากการใช้ตรรกะนั้นฉันสามารถพูดได้ว่าฟังก์ชั่นภาษาพื้นฐานอื่น ๆ นั้นเป็นสำนวนและดังนั้นทุกโปรแกรมจึงเป็นสำนวนซึ่งไม่ใช่
DeadMG

2

คำจำกัดความของคุณไม่ได้โจมตีฉันอย่างถูกต้อง สำนวนเป็นวิธีการเขียนสิ่งที่อาจหรือไม่อาจเป็นไปได้ในภาษาอื่น ๆ แต่นั่นเป็นเรื่องธรรมดาในภาษานี้ โดยปกติแล้วจะสั้นกว่าตัวเลือกอื่น แต่นั่นไม่ใช่ข้อกำหนด

อาจอธิบายได้ง่ายขึ้นโดยพูดถึงสิ่งที่ไม่ใช่สำนวน ใน C ++ มันเป็นเรื่องง่ายที่จะเขียน:

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p)
{
 // whatever
}

มันยิ่งสำนวนที่จะเขียน:

Foo* p; 
if(p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
{
 // whatever
}

รหัสนี้ทำในสิ่งเดียวกัน - บางคนที่ยังใหม่กับ C ++ อาจอ่านว่าเป็นการทดสอบเพื่อดูว่า p เท่ากับฟังก์ชันที่ส่งคืนหรือไม่ แต่นั่นไม่ใช่สิ่งที่มันทำ

เปรียบเทียบกับสิ่งที่บางคนอาจเขียนไม่ใช่คนที่มาจากภาษาอื่น:

Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y);
if(p !=NULL)
{
 // whatever
}

นอกจากนี้คุณยังจะเห็นสิ่งนี้ที่ล้มเหลวโดยไม่ใช้คำว่า:

if (x>0)
  return true;
else
 return false;

เพราะวิธีการใช้สำนวนนั้น

return (x>0);

วิธีที่ไม่ใช้สำนวนไม่ผิด แต่มักใช้เวลานานกว่าในการพิมพ์และใช้เวลาในการอ่านนานกว่าสำหรับผู้ที่รู้จักสำนวน ถ้าฉันเรียกคุณว่า "เด็กชายผู้ร้องไห้หมาป่า" และคุณรู้เรื่องนี้มันเร็วกว่าถ้าฉันอธิบายเกี่ยวกับการเตือนที่ผิดพลาดที่ทำให้ผู้คนไม่สนใจคุณ แน่นอนปัญหาคือถ้าคุณไม่รู้เรื่องราวและไม่รู้ว่าหมาป่าทำอะไรกับสิ่งที่เรากำลังพูดถึง ในทำนองเดียวกันอาจเป็นปัญหาหากคุณไม่เคยเห็นreturn x<y;มาก่อนและไม่รู้จริงๆว่าทำอะไร


1
วิธีการใช้สำนวนจะเป็นการประกาศตัวชี้ในเงื่อนไข if เพื่อที่จะไม่สามารถเข้าถึงได้หากไม่ใช่ NULL if(Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
DeadMG

อาจจะ หรือหนึ่งพันบรรทัดก่อนหน้าเพราะมันถูกใช้ทั่วทั้งบล็อก หรือในไฟล์ส่วนหัวเพราะมันเป็นตัวแปรสมาชิก ฉันแค่ประกาศเพื่อผู้อ่านจะได้รู้ว่ามันเป็น Foo * คุณพูดถูกในชีวิตจริงที่ไม่ได้ประกาศไว้ที่นั่น
Kate Gregory

1

เมื่อมีหลายวิธีในการแสดงบางสิ่งซึ่งเป็นวิธีที่ใช้กันทั่วไปหรือยอมรับกันโดยทั่วไป ตัวอย่างเช่นการใช้คำสั่งที่มีโครงสร้างใน C แทนการเทียบเท่าที่แน่นอนโดยใช้คำสั่ง goto

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