Thành ngữ là gì?


19

Tôi hiểu một "thành ngữ" là một hoạt động hoặc mẫu chung mà trong một ngôn ngữ cụ thể không được đơn giản hóa bằng cú pháp ngôn ngữ cốt lõi, chẳng hạn như gia số nguyên:

i = i + 1;

Trong C ++, thành ngữ này được đơn giản hóa bởi một toán tử:

++i;

Tuy nhiên, khi ai đó sử dụng thuật ngữ "thành ngữ", tôi không chắc làm thế nào để hiểu nó. Điều gì làm cho một đoạn mã "thành ngữ"?


Điều này thuộc về tiếng Anh.stackexchange.com cũng như ở đây.
S.Lott

@ perl.j: Sâu sắc. Bạn đã thực sự làm rõ lý do tại sao định nghĩa của "Thành ngữ" không thuộc về english.stackexchange.com. Rất hữu ích.
S.Lott

Câu trả lời:


24

Một cách viết thành ngữ của một số mã là khi bạn viết nó theo một cách rất cụ thể vì các thành ngữ dành riêng cho ngôn ngữ mà các ngôn ngữ khác không có.

Ví dụ, trong C ++, việc khai thác thành ngữ RAII dẫn đến cách viết mã C ++ quản lý tài nguyên là thành ngữ.

Một ví dụ khác là sử dụng khả năng hiểu danh sách trong Python để tạo danh sách. Nó là thành ngữ bởi vì bạn sẽ sử dụng khả năng hiểu danh sách trong Python thành ngữ nhưng bạn có thể đã làm tương tự bằng cách sử dụng hàm tạo trong bất kỳ ngôn ngữ nào khác hoặc thậm chí trong Python.

Thông thường, ai đó đang thử một ngôn ngữ mới mà không sử dụng các thành ngữ dành riêng cho ngôn ngữ này sẽ không viết mã thành ngữ.


Mô tả tuyệt vời. Vậy trong C #, nếu tôi tạo một phương thức mở rộng được gọi TryAdd()trên Dictionarylớp Chung để kiểm tra trước !Contains()rồi gọi Add(), thì đây có phải là thành ngữ không? Tôi đang sử dụng một tính năng dành riêng cho C # - phương thức mở rộng.
void.pulum

1
Tôi không chắc chắn chính xác như hầu hết các lập trình viên C ++ có kinh nghiệm sẽ bảo bạn viết các hàm miễn phí để mở rộng các lớp thay vì thêm thành viên, nếu có thể. Nó không giống như các phương thức mở rộng C # nhưng nó khá gần gũi và có sẵn cho bất kỳ ngôn ngữ nào cho phép các chức năng miễn phí. Điều tôi chắc chắn là việc viết "set / getters" trong C # bằng cách sử dụng các thuộc tính IS là thành ngữ.
Klaim

Nhưng đây không phải là C ++, vì vậy sử dụng "cách C ++" có thể không đủ "thành ngữ". Sử dụng một phương pháp mở rộng ở đây là hợp lý và rất giống C #. Trong mọi trường hợp, đó là một ví dụ nhưng các phương thức mở rộng rất thành ngữ đối với C #.
void.pulum

Vâng, đó là lý do tại sao tôi nói "Tôi không chắc chắn", nó có cảm giác thành ngữ nhưng nó rất gần với các tính năng cơ bản khác của các ngôn ngữ khác mà tôi không chắc chắn (vì tôi không phải là nhà phát triển C #). Tôi có một ví dụ khác: việc lặp được thực hiện bằng cách đệ quy trong tất cả các ngôn ngữ chức năng. Bạn có thể làm điều đó bằng các ngôn ngữ khác, nhưng rõ ràng nó là thành ngữ của các ngôn ngữ chức năng. Không chắc chắn nếu nó giúp.
Klaim

1
Tất nhiên python tiến thêm một bước bằng cách có một cách thành ngữ để chỉ mã thành ngữ, tức là pythonic. * 8 ')
Đánh dấu gian hàng

12

Định nghĩa bình thường

Sử dụng, chứa hoặc biểu thị các biểu thức tự nhiên đối với người bản ngữ

Định nghĩa lập trình

Sử dụng, chứa hoặc biểu thị các biểu thức tự nhiên cho lập trình viên [Chèn ngôn ngữ]


1
Nếu tôi nghĩ định nghĩa "google" cho thuật ngữ này là hữu ích thì tôi đã không đăng ở đây. Tôi muốn một mô tả tốt hơn (giống như hướng dẫn) với các ví dụ.
void.pulum

3
@Robert - Tôi đoán tôi không hiểu tại sao bạn không hiểu.
ChaosPandion

2
Tôi đọc câu trả lời của bạn trước, nó không rõ ràng lắm. Sau khi đọc câu trả lời được đánh dấu là câu trả lời của tôi, nó trở nên rất rõ ràng "thành ngữ" nghĩa là gì và bây giờ tôi đã hiểu nó. Bây giờ tôi đọc câu trả lời của bạn nó có ý nghĩa. Tuy nhiên, bạn đã không đưa tôi qua các ví dụ và các tình huống khác nhau, đó là lý do tại sao tôi nghĩ rằng câu trả lời của bạn không hữu ích. Bạn đã đưa ra phản hồi "webster" đúng về mặt kỹ thuật nhưng không hữu ích cho đến khi giúp tôi hiểu. Tôi đánh giá cao sự giúp đỡ của bạn mặc dù.
void.pulum

7

Thành ngữ trong ngữ cảnh lập trình thường có thể được định nghĩa là "cách tự nhiên nhất để diễn đạt một cái gì đó bằng ngôn ngữ"

Tôi thấy từ thành ngữ xuất hiện đặc biệt rất nhiều trong Ruby. Trong Ruby, có các khả năng lập trình meta lớn và để viết mã Ruby thành ngữ, bạn thường phải sử dụng các mã này.

Lưu ý rằng chỉ vì một đoạn mã là thành ngữ, không có nghĩa là nó sạch hoặc thậm chí ngắn gọn. Nhiều khi bạn phải thỏa hiệp.

Vì vậy, về cơ bản, thành ngữ phổ biến nhất đề cập đến cách phổ biến nhất để viết một cái gì đó bằng ngôn ngữ, thường là bao gồm cả "tiếng lóng" (thành ngữ). Nếu một đoạn mã không phải là thành ngữ, nó có thể hoàn toàn dễ đọc, súc tích, rõ ràng và chính xác, nhưng nó có thể cảm thấy / trông lúng túng trong ngôn ngữ được sử dụng. Sở thích của việc viết lại một đoạn mã như vậy có thực sự là một điều tốt hay không và phải được đánh giá theo từng trường hợp

Ví dụ tiếng Anh có thể phụ thuộc vào khu vực. Sử dụng từ bumnày có lẽ là cần thiết cho tiếng Anh Anh thành ngữ, trong khi buttphù hợp hơn với tiếng Anh Mỹ. (Tôi không biết nhiều tiếng Anh Anh buồn bã: /)


Cảm ơn (upvote), tôi nghĩ rằng định nghĩa của bạn đánh nó ngay tại chỗ cho tôi!
Ashaman Kingpin

3

Ví dụ tốt nhất tôi có thể nghĩ ra, trên đỉnh đầu, vì một thứ gì đó thành ngữ, đến từ Ruby.

Trong vô số ngôn ngữ, bạn có thể lặp lại với:

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

Hoặc một cái gì đó rất giống nhau. Nhiều ngôn ngữ cũng có foreach(x in SetOfXes)cấu trúc. Nhưng phép lặp đó là thành ngữ đối với Ruby bao gồm những thứ như:

collection.each do |current|
  current.do_stuff
end

và ngay cả

10.times do |x|
  puts x
end

Tôi thấy những điều này là thành ngữ bởi vì chúng đại diện cho một cách làm một cái gì đó ít phổ biến hơn, và nó đại diện cho một cái gì đó cốt lõi của triết lý của miền của nó. Ruby có một triết lý về sự tương tác với các đối tượng, trong khi không phải là duy nhất, không phổ biến.

Trên một ghi chú ngữ nghĩa, bất cứ khi nào tôi nghe thấy từ thành ngữ, bộ não của tôi sẽ tự động hoàn thành ý nghĩ là "thành ngữ ..." - tôi chỉ phản xạ phân tích nó theo liên quan đến một chủ đề cụ thể.


Làm thế nào collection.each do |current|khác với foreach(current in collection)? Cả hai đều là các cấu trúc vòng lặp được đặt currentcho từng phần tử của collection.
MSalters

2

Thành ngữ thường là cách tốt nhất có thể để diễn đạt một tình huống phổ biến, tương đối phức tạp trong một ngôn ngữ. Gia tăng không phải là một thành ngữ hay bất cứ thứ gì thuộc loại này. Sử dụng gia tăng tiền tố thay vì hậu tố, bạn có thể lập luận là một thành ngữ C ++.

Thành ngữ là cách tốt nhất để sử dụng ngôn ngữ, được xác định bởi người dùng chuyên gia. Một thành ngữ C ++ thực sự sẽ là các đối tượng hàm. Một thành ngữ khác sẽ là RAII. Không có gì trong ngôn ngữ nói với bạn rằng bạn phải giải phóng tài nguyên trong hàm hủy. Nhưng đó là thành ngữ để làm như vậy. Một ví dụ khác là các mẫu - thật đơn giản khi sử dụng các mẫu cho mọi thứ bạn có thể, nhưng không có gì ngăn cản bạn sử dụng thừa kế.


Wikipedia đã sử dụng tăng dần làm ví dụ, vì vậy đó là lý do tại sao tôi đề cập đến nó trong câu hỏi của mình. Tại sao thành ngữ bắt buộc phải phức tạp? Điều này dường như không phải là một phần của định nghĩa dựa trên các câu trả lời khác.
void.pulum

4
@Robert Tweetsey: Làm thế nào có thể tăng có thể là một thành ngữ? Đó là một phần của ngôn ngữ . Thành ngữ được tạo bởi người dùng ngôn ngữ, chúng thay đổi theo thời gian. Tăng không phải là một thành ngữ, nó là một chức năng cơ bản của ngôn ngữ. Theo logic đó, tôi có thể nói rằng bất kỳ chức năng ngôn ngữ cơ bản nào khác là một thành ngữ, và do đó mọi chương trình đều là thành ngữ, điều này không phải.
DeadMG

2

Định nghĩa của bạn không đánh tôi là chính xác. Một thành ngữ là một cách viết một cái gì đó có thể hoặc không thể có trong các ngôn ngữ khác, nhưng đó là điều phổ biến trong ngôn ngữ này. Thông thường, nó ngắn hơn giải pháp thay thế, nhưng đó không thực sự là một yêu cầu.

Có thể dễ dàng hơn để giải thích nó bằng cách nói về những gì không phải là thành ngữ. Trong C ++, nó khá thành ngữ để viết:

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

Nó thậm chí còn thành ngữ hơn để viết:

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

Mã này thực hiện chính xác điều tương tự - một số người mới sử dụng C ++ có thể đọc nó dưới dạng thử nghiệm để xem liệu p có bằng với những gì hàm trả về không, nhưng đó không phải là những gì nó làm.

So sánh với những gì ai đó có thể viết, rất phi thành ngữ, người đến từ ngôn ngữ khác:

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

Bạn cũng sẽ thấy nội dung này bị loại là không thành ngữ:

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

Bởi vì cách tiếp cận thành ngữ là

return (x>0);

Các cách không thành ngữ không sai, nhưng chúng thường mất nhiều thời gian hơn để gõ và chúng luôn mất nhiều thời gian hơn để đọc, cho những người biết thành ngữ này. Nếu tôi gọi bạn là "cậu bé khóc sói" và bạn biết câu chuyện, nó sẽ nhanh hơn nếu tôi giải thích về việc báo động sai khiến mọi người bỏ qua bạn như thế nào. Tất nhiên, vấn đề là nếu bạn không biết câu chuyện và không biết những con sói phải làm gì với những gì chúng ta đang nói. Tương tự, nó có thể là một vấn đề nếu bạn chưa từng thấy return x<y;trước đây và thực sự không biết nó làm gì.


1
Cách tiếp cận thành ngữ chắc chắn sẽ là khai báo con trỏ trong điều kiện if, để nó không bao giờ có thể được truy cập nếu nó không phải là NULL. if(Foo* p = SomeThingThatReturnsAFooPointer(arg, param, x, y))
DeadMG

mm, có lẽ. Hoặc một ngàn dòng trước đó vì nó được sử dụng trong toàn bộ khối này. Hoặc trong tệp tiêu đề vì đó là biến thành viên. Tôi chỉ tuyên bố nó để độc giả biết đó là Foo *, bạn nói đúng là trong đời thực, nó sẽ không được khai báo ở đó.
Kate Gregory

1

Khi có nhiều cách để thể hiện một cái gì đó, cách phổ biến nhất hoặc thường được chấp nhận. Chẳng hạn, sử dụng câu lệnh có cấu trúc trong C thay vì tương đương chính xác bằng cách sử dụng câu lệnh goto.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.