Ngôn ngữ loại động so với ngôn ngữ loại tĩnh


205

Những lợi thế và hạn chế của ngôn ngữ loại động so với ngôn ngữ loại tĩnh là gì?

Xem thêm : whats với tình yêu của ngôn ngữ động (một chủ đề tranh luận hơn nhiều ...)


10
Câu hỏi này quá chủ quan.
Jason Dagit

7
Tôi sẽ không gọi nó là chủ quan, nhưng mồi lửa. Nhưng có một số sự thật khách quan liên quan đến nó.
Vinko Vrsalovic

2
Đồng ý: quá chủ quan. Thật thú vị khi so sánh và đối chiếu hai cách tiếp cận, nhưng nó lại nguy hiểm trên bờ vực tận thế của diễn đàn.
Daniel Spiewak

17
Ngôn ngữ động rất tốt cho việc phát triển nhanh chóng các ứng dụng demo / vứt đi vì nếu bạn mắc lỗi đánh máy, trang web vẫn tải bạn có thể có một vài yếu tố dữ liệu sai ở đây hoặc ở đó. Tôi không thể tưởng tượng bất kỳ tình huống nào khác trong đó khả năng nhập sai các biến của bạn mà không gặp lỗi trình biên dịch được coi là một "lợi thế".
Alex R

4
Một lỗi như vậy thường sẽ khiến JavaScript dừng lại, mà tôi cho là một điều rất tốt. Ít nhất thì nó cũng sẽ ném những lỗi mà tôi cũng thấy có giá trị. Vì một số lý do, đó luôn là một chàng trai từ mô hình gõ tĩnh muốn chôn vùi các lỗi javascript của mình bằng các câu lệnh try / Catch trống. Đó là một cái gì đó của một hiện tượng trong kinh nghiệm của tôi. Đó là gì? Bất kể, nó không giống như chúng tôi không nhận được phản hồi khi chúng tôi chạy mã của chúng tôi.
Erik Reppen

Câu trả lời:


139

Khả năng trình thông dịch suy ra các chuyển đổi loại và loại làm cho thời gian phát triển nhanh hơn, nhưng nó cũng có thể gây ra lỗi trong thời gian chạy mà bạn không thể có được bằng ngôn ngữ gõ tĩnh nơi bạn bắt chúng vào thời gian biên dịch. Nhưng cái nào tốt hơn (hoặc thậm chí nếu điều đó luôn luôn đúng) được thảo luận sôi nổi trong cộng đồng những ngày này (và từ rất lâu).

Một vấn đề tốt là từ việc gõ tĩnh ở những nơi có thể, gõ động khi cần thiết: Sự kết thúc của cuộc chiến tranh lạnh giữa các ngôn ngữ lập trình của Erik Meijer và Peter Drayton tại Microsoft:

Những người ủng hộ việc gõ tĩnh cho rằng các ưu điểm của gõ tĩnh bao gồm phát hiện sớm các lỗi lập trình (ví dụ: ngăn thêm số nguyên vào boolean), tài liệu tốt hơn ở dạng chữ ký loại (ví dụ: kết hợp số và loại đối số khi giải quyết tên), hơn nữa cơ hội tối ưu hóa trình biên dịch (ví dụ: thay thế các cuộc gọi ảo bằng các cuộc gọi trực tiếp khi loại chính xác của máy thu được biết tĩnh), tăng hiệu quả thời gian chạy (ví dụ: không phải tất cả các giá trị cần mang theo kiểu động) và trải nghiệm nhà phát triển thời gian thiết kế tốt hơn (ví dụ: biết loại máy thu, IDE có thể trình bày menu thả xuống của tất cả các thành viên hiện hành). Những kẻ cuồng đánh máy tĩnh cố gắng làm cho chúng tôi tin rằng các chương trình được gõ tốt không thể sai. Trong khi điều này chắc chắn nghe có vẻ ấn tượng, đó là một tuyên bố khá trống rỗng. Kiểm tra kiểu tĩnh là sự trừu tượng hóa thời gian biên dịch của hành vi thời gian chạy của chương trình của bạn và do đó, nó nhất thiết chỉ là một phần âm thanh và không đầy đủ. Điều này có nghĩa là các chương trình vẫn có thể bị lỗi do các thuộc tính không được theo dõi bởi trình kiểm tra loại và có những chương trình trong khi chúng không thể bị lỗi thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. Kiểm tra kiểu tĩnh là sự trừu tượng hóa thời gian biên dịch của hành vi thời gian chạy của chương trình của bạn và do đó, nó nhất thiết chỉ là một phần âm thanh và không đầy đủ. Điều này có nghĩa là các chương trình vẫn có thể bị lỗi do các thuộc tính không được theo dõi bởi trình kiểm tra loại và có những chương trình trong khi chúng không thể bị lỗi thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. Kiểm tra kiểu tĩnh là sự trừu tượng hóa thời gian biên dịch của hành vi thời gian chạy của chương trình của bạn và do đó, nó nhất thiết chỉ là một phần âm thanh và không đầy đủ. Điều này có nghĩa là các chương trình vẫn có thể bị lỗi do các thuộc tính không được theo dõi bởi trình kiểm tra loại và có những chương trình trong khi chúng không thể bị lỗi thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. và do đó nó nhất thiết chỉ là một phần âm thanh và không đầy đủ. Điều này có nghĩa là các chương trình vẫn có thể bị lỗi do các thuộc tính không được theo dõi bởi trình kiểm tra loại và có những chương trình trong khi chúng không thể bị lỗi thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. và do đó nó nhất thiết chỉ là một phần âm thanh và không đầy đủ. Điều này có nghĩa là các chương trình vẫn có thể bị lỗi do các thuộc tính không được theo dõi bởi trình kiểm tra loại và có những chương trình trong khi chúng không thể bị lỗi thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. và có những chương trình mà trong khi chúng không thể sai thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên. và có những chương trình mà trong khi chúng không thể sai thì không thể kiểm tra kiểu. Sự thúc đẩy của việc gõ tĩnh ít một phần và hoàn chỉnh hơn khiến cho các hệ thống kiểu trở nên quá phức tạp và kỳ lạ như được chứng kiến ​​bởi các khái niệm như kiểu ảo phật giả [11] và kiểu wobbly kiểu [10]. Điều này giống như cố gắng chạy marathon với một quả bóng và dây xích buộc vào chân của bạn và hét lên một cách đắc thắng rằng bạn gần như đã làm được điều đó mặc dù bạn đã thoát ra sau dặm đầu tiên.

Những người ủng hộ các ngôn ngữ gõ động cho rằng gõ tĩnh quá cứng và tính mềm của ngôn ngữ động khiến chúng phù hợp lý tưởng cho các hệ thống tạo mẫu với các yêu cầu thay đổi hoặc không xác định hoặc tương tác với các hệ thống khác thay đổi không thể đoán trước (tích hợp dữ liệu và ứng dụng). Tất nhiên, các ngôn ngữ được gõ động là không thể thiếu để xử lý các hành vi chương trình thực sự năng động như chặn phương thức, tải động, mã di động, phản ánh thời gian chạy, v.v. Trong mẹ của tất cả các bài viết về kịch bản [16], John Ousterhout lập luận rằng các hệ thống gõ tĩnh ngôn ngữ lập trình làm cho mã ít sử dụng lại, dài dòng hơn, không an toàn hơn và ít biểu cảm hơn các ngôn ngữ kịch bản được gõ động. Lập luận này được đưa ra theo nghĩa đen bởi nhiều người đề xướng các ngôn ngữ kịch bản được gõ động. Chúng tôi lập luận rằng đây là một lời ngụy biện và rơi vào cùng loại với lập luận rằng bản chất của lập trình khai báo là loại bỏ sự phân công. Hay như John Hughes nói [8], việc không thể tạo ra một ngôn ngữ mạnh mẽ hơn bằng cách bỏ qua các tính năng là một điều không thể. Bảo vệ thực tế rằng trì hoãn tất cả các loại kiểm tra thời gian chạy là một điều tốt, đang chơi các chiến thuật đà điểu với thực tế là các lỗi nên được bắt càng sớm trong quá trình phát triển càng tốt. đó là một sự bất khả thi logic để làm cho một ngôn ngữ mạnh mẽ hơn bằng cách bỏ qua các tính năng. Bảo vệ thực tế rằng trì hoãn tất cả các loại kiểm tra thời gian chạy là một điều tốt, đang chơi các chiến thuật đà điểu với thực tế là các lỗi nên được bắt càng sớm trong quá trình phát triển càng tốt. đó là một sự bất khả thi logic để làm cho một ngôn ngữ mạnh mẽ hơn bằng cách bỏ qua các tính năng. Bảo vệ thực tế rằng trì hoãn tất cả các loại kiểm tra thời gian chạy là một điều tốt, đang chơi các chiến thuật đà điểu với thực tế là các lỗi nên được bắt càng sớm trong quá trình phát triển càng tốt.


37
"Chặn phương thức, tải động, mã di động, phản ánh thời gian chạy" đều có thể được thực hiện trong Java, chỉ dành cho bản ghi.
Will Hartung

13
Các loại Phantom không "quá phức tạp".
Jon Harrop

12
Liên kết đến tờ Meijer bị hỏng kể từ ngày 16/5/2010.
jchadhowell

5
@jchadhowell, bạn có thể thấy rằng đây research.microsoft.com/en-us/um/people/emeijer/Papers/...
Srinivas Reddy Thatiparthy

4
@VinkoVrsalovic Các ngôn ngữ tĩnh với kiểu suy luận và đa hình là khá tốt để tạo mẫu nhanh. Họ cung cấp sự thoải mái giống như ngôn ngữ động và sự an toàn của ngôn ngữ tĩnh.
Edgar Klerks

119

Các hệ thống loại tĩnh tìm cách loại bỏ một số lỗi tĩnh, kiểm tra chương trình mà không chạy nó và cố gắng chứng minh tính đúng đắn ở một số khía cạnh nhất định. Một số hệ thống loại có thể bắt lỗi nhiều hơn những hệ thống khác. Ví dụ, C # có thể loại bỏ các ngoại lệ con trỏ null khi được sử dụng đúng cách, trong khi Java không có sức mạnh như vậy. Twelf có một hệ thống loại thực sự đảm bảo rằng bằng chứng sẽ chấm dứt , "giải quyết" vấn đề tạm dừng .

Tuy nhiên, không có hệ thống loại nào là hoàn hảo. Để loại bỏ một loại lỗi cụ thể, họ cũng phải từ chối một số chương trình hoàn toàn hợp lệ vi phạm các quy tắc. Đây là lý do tại sao Twelf không thực sự giải quyết vấn đề tạm dừng, họ chỉ tránh nó bằng cách đưa ra một số lượng lớn bằng chứng hoàn toàn hợp lệ xảy ra để chấm dứt theo những cách kỳ lạ. Tương tự, hệ thống kiểu của Java từ chối PersistentVectortriển khai Clojure do sử dụng các mảng không đồng nhất. Nó hoạt động trong thời gian chạy, nhưng hệ thống loại không thể xác minh nó.

Vì lý do đó, hầu hết các hệ thống loại cung cấp "thoát", các cách để ghi đè trình kiểm tra tĩnh. Đối với hầu hết các ngôn ngữ, những ngôn ngữ này có hình thức truyền, mặc dù một số ngôn ngữ (như C # và Haskell) có toàn bộ chế độ được đánh dấu là "không an toàn".

Chủ quan, tôi thích gõ tĩnh. Được triển khai đúng cách (gợi ý: không phải Java), một hệ thống kiểu tĩnh có thể giúp ích rất nhiều trong việc loại bỏ các lỗi trước khi chúng làm sập hệ thống sản xuất. Các ngôn ngữ được gõ động có xu hướng yêu cầu kiểm tra đơn vị nhiều hơn, điều này rất tẻ nhạt vào thời điểm tốt nhất. Ngoài ra, các ngôn ngữ được nhập tĩnh có thể có một số tính năng nhất định không thể hoặc không an toàn trong các hệ thống loại động ( chuyển đổi ngầm định xuất hiện trong tâm trí). Đó là tất cả một câu hỏi về yêu cầu và hương vị chủ quan. Tôi sẽ không xây dựng Eclipse tiếp theo trong Ruby hơn là tôi sẽ cố gắng viết một tập lệnh sao lưu trong hội hoặc vá một kernel bằng Java.

Ồ, và những người nói rằng " x gõ có năng suất gấp 10 lần so vớiy " chỉ đơn giản là thổi khói. Gõ động có thể "cảm thấy" nhanh hơn trong nhiều trường hợp, nhưng nó sẽ mất đi một khi bạn thực sự cố gắng làm cho ứng dụng ưa thích của mình chạy . Tương tự như vậy, gõ tĩnh có vẻ như là mạng an toàn hoàn hảo, nhưng người ta nhìn vào một số định nghĩa kiểu chung phức tạp hơn trong Java sẽ khiến hầu hết các nhà phát triển bàn tán xôn xao vì bịt mắt. Ngay cả với hệ thống loại và năng suất, không có viên đạn bạc.

Lưu ý cuối cùng: đừng lo lắng về hiệu suất khi so sánh tĩnh với gõ động. Các JIT hiện đại như V8 và TraceMonkey đang đến gần nguy hiểm với hiệu suất ngôn ngữ tĩnh. Ngoài ra, việc Java thực sự biên dịch thành ngôn ngữ trung gian động vốn có nên là một gợi ý rằng trong hầu hết các trường hợp, gõ động không phải là kẻ giết người hiệu năng lớn mà một số người nghĩ ra.


5
Về hiệu suất. Trong các trường hợp phổ biến, nó sẽ không tạo ra nhiều sự khác biệt, nhưng trong các bài toán căng thẳng cao và như vậy, có một sự khác biệt thực sự. Test's đã chứng minh một cuộc gọi của một chức năng, trong trường hợp ipy vs C #, khác với một ngàn chu kỳ. Chỉ vì trước đây phải chắc chắn một phương thức tồn tại.
Dykam

29
Bạn có thể giải thích rõ hơn về vấn đề "C # có thể loại bỏ các ngoại lệ con trỏ null khi được sử dụng đúng cách, trong khi Java không có sức mạnh như vậy." ? Một ví dụ hoặc trích dẫn sẽ được đánh giá cao.
Srinivas Reddy Thatiparthy

13
"Một số định nghĩa kiểu chung phức tạp hơn trong Java gửi hầu hết các nhà phát triển đang tìm kiếm mù mắt" - nếu đây là ví dụ tồi tệ nhất của bạn, rõ ràng bạn đã không sử dụng C ++ ;-)
bacar

3
"Ngoài ra, việc Java thực sự biên dịch thành ngôn ngữ trung gian động vốn có nên là một gợi ý rằng đối với hầu hết các trường hợp, gõ động không phải là kẻ giết người hiệu năng lớn mà một số người nghĩ ra." - khi ví dụ về ngôn ngữ của bạn có "hiệu suất tốt" là Java, bạn có thể muốn xem xét lại.
Yakk - Adam Nevraumont

" Java biên dịch thành một trung gian động vốn có " - điều đó không đúng. Các kiểm tra tĩnh đã được thực hiện trước và do đó không có kiểm tra thời gian chạy bổ sung nào được yêu cầu vì trình biên dịch chọn các hướng dẫn như daddbởi vì anh ta biết trước rằng các toán hạng là doubles.
Bia Michael

45

Vâng, cả hai đều rất, rất rất rất hiểu lầm và cũng là hai điều hoàn toàn khác nhau. không loại trừ lẫn nhau .

Các loại tĩnh là một hạn chế về ngữ pháp của ngôn ngữ. Langauges gõ tĩnh có thể nói là không có ngữ cảnh. Sự thật đơn giản là nó trở nên bất tiện khi diễn đạt một ngôn ngữ hoàn toàn trong ngữ pháp không ngữ cảnh không xử lý tất cả dữ liệu của nó đơn giản như các vectơ bit. Các hệ thống kiểu tĩnh là một phần của ngữ pháp của ngôn ngữ nếu có, chúng chỉ đơn giản hạn chế nó hơn một ngữ pháp tự do ngữ cảnh có thể, do đó kiểm tra ngữ pháp xảy ra trong hai lần đi qua nguồn thực sự. Các loại tĩnh tương ứng với khái niệm toán học của lý thuyết loại, lý thuyết loại trong toán học chỉ đơn giản là hạn chế tính hợp pháp của một số biểu thức. Giống như, tôi không thể nói 3 + [4,7]trong toán học, điều này là do lý thuyết loại của nó.

Do đó, các loại tĩnh không phải là một cách để 'ngăn ngừa lỗi' từ góc độ lý thuyết, chúng là một hạn chế của ngữ pháp. Thật vậy, với điều kiện là +, 3 và các khoảng có các định nghĩa lý thuyết tập hợp thông thường, nếu chúng ta loại bỏ hệ thống loại 3 + [4,7]có kết quả được xác định khá rõ đó là một tập hợp. "Lỗi về kiểu thời gian chạy" về mặt lý thuyết không tồn tại, sử dụng thực tế của hệ thống loại này là để ngăn chặn các hoạt động mà con người không có ý nghĩa. Tất nhiên, hoạt động vẫn chỉ là sự dịch chuyển và thao tác của các bit.

Điều đáng chú ý ở đây là một hệ thống loại không thể quyết định liệu các hoạt động đó có xảy ra hay không nếu nó được phép chạy. Như trong, phân vùng chính xác tập hợp tất cả các chương trình có thể có trong những chương trình sẽ có 'lỗi loại' và những chương trình không có. Nó chỉ có thể làm hai điều:

1: chứng minh rằng lỗi loại sẽ xảy ra trong chương trình
2: chứng minh rằng chúng sẽ không xảy ra trong chương trình

Điều này có vẻ như tôi đang mâu thuẫn với chính mình. Nhưng những gì trình kiểm tra loại C hoặc Java thực hiện là nó từ chối một chương trình là 'không theo quy tắc' hoặc vì nó gọi đó là 'lỗi loại' nếu nó không thể thành công ở mức 2. Nó không thể chứng minh rằng chúng sẽ không xảy ra, điều đó không có nghĩa là chúng sẽ không xảy ra, nó chỉ có nghĩa là nó không thể chứng minh điều đó. Rất có thể là một chương trình sẽ không có lỗi loại bị từ chối đơn giản vì nó không thể được trình biên dịch chứng minh. Một ví dụ đơn giản làif(1) a = 3; else a = "string";, chắc chắn vì nó luôn luôn đúng, nhánh khác sẽ không bao giờ được thực thi trong chương trình và không xảy ra lỗi loại nào. Nhưng nó không thể chứng minh những trường hợp này một cách chung chung, vì vậy nó đã bị từ chối. Đây là điểm yếu lớn của rất nhiều ngôn ngữ được nhập tĩnh, trong việc bảo vệ bạn chống lại chính mình, bạn nhất thiết cũng được bảo vệ trong trường hợp bạn không cần đến nó.

Nhưng, trái với niềm tin phổ biến, cũng có những ngôn ngữ được gõ tĩnh hoạt động theo nguyên tắc 1. Họ chỉ từ chối tất cả các chương trình mà họ có thể chứng minh rằng nó sẽ gây ra lỗi loại và vượt qua tất cả các chương trình mà họ không thể. Vì vậy, có thể họ cho phép các chương trình có lỗi loại, một ví dụ điển hình là Gõ vợt, đó là sự kết hợp giữa gõ động và gõ tĩnh. Và một số người sẽ tranh luận rằng bạn có được điều tốt nhất của cả hai thế giới trong hệ thống này.

Một ưu điểm khác của gõ tĩnh là các kiểu được biết tại thời gian biên dịch, và do đó trình biên dịch có thể sử dụng điều này. Nếu chúng ta trong Java làm "string" + "string"hoặc 3 + 3, cả hai +mã thông báo trong văn bản cuối cùng đại diện cho một hoạt động và mốc thời gian hoàn toàn khác nhau, trình biên dịch sẽ biết nên chọn loại nào trong số các loại một mình.

Bây giờ, tôi sẽ đưa ra một tuyên bố rất gây tranh cãi ở đây nhưng hãy đồng ý với tôi: 'kiểu gõ động' không tồn tại .

Nghe có vẻ rất gây tranh cãi, nhưng đó là sự thật, các ngôn ngữ được gõ động từ góc độ lý thuyết được tháo gỡ . Chúng chỉ là các ngôn ngữ gõ tĩnh chỉ với một loại. Hay nói một cách đơn giản, chúng là những ngôn ngữ thực sự được tạo ra bởi ngữ pháp bởi một ngữ pháp tự do ngữ cảnh trong thực tế.

Tại sao họ không có loại? Bởi vì mọi hoạt động được xác định và cho phép trên mọi toán tử, "lỗi loại thời gian chạy" chính xác là gì? Đó là từ một ví dụ lý thuyết hoàn toàn là một tác dụng phụ . Nếu thực hiện print("string")in chuỗi là một thao tác, thì cái length(3)trước có tác dụng phụ là ghi stringvào đầu ra tiêu chuẩn, đơn giản là cái sau error: function 'length' expects array as argument., đó là cái đó. Từ góc độ lý thuyết, không có thứ gọi là ngôn ngữ gõ động. Họ được tháo gỡ

Được rồi, lợi thế rõ ràng của ngôn ngữ 'gõ động' là sức mạnh biểu cảm, một hệ thống loại không có gì ngoài giới hạn của sức mạnh biểu cảm. Và nói chung, các ngôn ngữ có hệ thống loại thực sự sẽ có kết quả xác định cho tất cả các hoạt động không được phép nếu hệ thống loại chỉ bị bỏ qua, kết quả sẽ không có ý nghĩa với con người. Nhiều ngôn ngữ mất tính hoàn chỉnh Turing sau khi áp dụng một hệ thống loại.

Nhược điểm rõ ràng là thực tế là các hoạt động có thể xảy ra sẽ tạo ra kết quả vô nghĩa với con người. Để bảo vệ chống lại điều này, các ngôn ngữ được gõ động thường xác định lại các hoạt động đó, thay vì tạo ra kết quả vô nghĩa đó, chúng xác định lại nó có tác dụng phụ là viết ra một lỗi và có thể tạm dừng chương trình. Trên thực tế, đây không phải là một "lỗi", đặc điểm kỹ thuật ngôn ngữ thường bao hàm điều này, đây là hành vi của ngôn ngữ nhiều như in một chuỗi từ góc độ lý thuyết. Loại hệ thống do đó buộc người lập trình phải suy luận về dòng mã để đảm bảo rằng điều này không xảy ra. Hoặc thực sự, lý do để nó làmxảy ra cũng có thể có ích trong một số điểm để gỡ lỗi, cho thấy rằng đó hoàn toàn không phải là "lỗi" mà là một thuộc tính được xác định rõ của ngôn ngữ. Trên thực tế, phần còn lại của 'kiểu gõ động' mà hầu hết các ngôn ngữ có đang bảo vệ chống lại sự phân chia bằng 0. Đây là kiểu gõ động, không có kiểu nào, không có nhiều kiểu hơn số 0 là một kiểu khác với tất cả các số khác. Cái mà mọi người gọi là 'loại' chỉ là một thuộc tính khác của mốc thời gian, như độ dài của một mảng hoặc ký tự đầu tiên của chuỗi. Và nhiều ngôn ngữ được gõ động cũng cho phép bạn viết ra những thứ như thế "error: the first character of this string should be a 'z'".

Một điều nữa là các ngôn ngữ được gõ động có loại có sẵn trong thời gian chạy và thường có thể kiểm tra nó và xử lý nó và quyết định từ đó. Tất nhiên, về mặt lý thuyết, nó không khác gì việc truy cập char đầu tiên của một mảng và xem nó là gì. Trong thực tế, bạn có thể tạo C động của riêng mình, chỉ cần sử dụng một loại như int dài dài và sử dụng 8 bit đầu tiên của nó để lưu trữ 'loại' của bạn và viết các hàm phù hợp để kiểm tra nó và thực hiện phép cộng hoặc số nguyên. Bạn có một ngôn ngữ gõ tĩnh với một loại hoặc ngôn ngữ động.

Trong thực tế tất cả các chương trình này, các ngôn ngữ gõ tĩnh thường được sử dụng trong bối cảnh viết phần mềm thương mại, trong khi các ngôn ngữ gõ động có xu hướng được sử dụng trong bối cảnh giải quyết một số vấn đề và tự động hóa một số tác vụ. Viết mã bằng các ngôn ngữ được nhập tĩnh đơn giản chỉ mất nhiều thời gian và cồng kềnh vì bạn không thể làm những việc mà bạn biết sẽ không ổn nhưng hệ thống loại vẫn bảo vệ bạn trước những lỗi bạn không mắc phải. Nhiều lập trình viên thậm chí không nhận ra rằng họ làm điều này bởi vì nó nằm trong hệ thống của họ nhưng khi bạn viết mã bằng các ngôn ngữ tĩnh, bạn thường làm việc xung quanh thực tế là hệ thống loại sẽ không cho phép bạn làm những điều không thể sai, bởi vì nó không thể chứng minh rằng nó sẽ không đi sai.

Như tôi đã lưu ý, 'gõ tĩnh' nói chung có nghĩa là trường hợp 2, có tội cho đến khi được chứng minh vô tội. Nhưng một số ngôn ngữ, không xuất phát từ hệ thống loại của chúng từ lý thuyết loại tất cả đều sử dụng quy tắc 1: Vô tội cho đến khi được chứng minh là có tội, có thể là sự lai ghép lý tưởng. Vì vậy, có lẽ Typed Vợt là dành cho bạn.

Ngoài ra, đối với một ví dụ vô lý và cực đoan hơn, tôi hiện đang triển khai một ngôn ngữ trong đó 'loại' thực sự là ký tự đầu tiên của mảng, chúng là dữ liệu, dữ liệu của 'loại', 'loại', chính là một loại và mốc thời gian, mốc dữ liệu duy nhất có chính nó là một loại. Các loại không hữu hạn hoặc giới hạn tĩnh nhưng các loại mới có thể được tạo dựa trên thông tin thời gian chạy.


1
"Nhiều ngôn ngữ mất tính hoàn chỉnh Turing sau khi áp dụng một hệ thống loại." không áp dụng cho các ngôn ngữ lập trình thông thường, phải không? từ những gì tôi đọc được, các ngôn ngữ thông thường không hoàn chỉnh
Răzvan Flavius ​​Panda

1
@ RăzvanPanda: Lajla có lẽ đã đề cập đến các biến thể của phép tính lambda Typed hoặc một số ngôn ngữ lập trình mà họ sử dụng trên các trình duyệt định lý. Nhiều người trong số họ chỉ có thể thể hiện các chương trình được bảo đảm tạm dừng và do đó không hoàn thành Turing. Các ngôn ngữ lập trình chức năng thực tế dựa trên các hệ thống loại này đi xung quanh giới hạn này bằng cách mở rộng phép tính cốt lõi với các kiểu đệ quy.
hugomg

1
"Nghe có vẻ rất gây tranh cãi, nhưng đó là sự thật, các ngôn ngữ được gõ động từ góc độ lý thuyết được tháo gỡ." - ... và ngay lập tức, tôi biết bạn không biết bạn đang nói về cái gì. Gõ động chỉ có nghĩa là các loại thuộc về các giá trị, không phải là định danh. Nó làm cho các chương trình khó chứng minh hơn, nhưng không nhất thiết là không thể. Đa hình nội tuyến và đa hình tham số đã dẫn đến sự phát triển của tối ưu hóa thời gian liên kết; giải quyết cùng loại vấn đề biên dịch các ngôn ngữ được gõ động tối ưu có: đó là biết tất cả các đầu vào và đầu ra có thể.
Khéo léo xử lý

25

Có lẽ "lợi ích" lớn nhất của việc gõ động là đường cong học tập nông hơn. Không có hệ thống loại để tìm hiểu và không có cú pháp không tầm thường cho các trường hợp góc như ràng buộc kiểu. Điều đó làm cho việc gõ động có thể tiếp cận được với nhiều người hơn và khả thi đối với nhiều người mà các hệ thống kiểu tĩnh tinh vi nằm ngoài tầm với. Do đó, việc gõ động đã bắt kịp trong bối cảnh giáo dục (ví dụ Scheme / Python tại MIT) và các ngôn ngữ dành riêng cho tên miền dành cho những người không lập trình (ví dụ Mathicala ). Các ngôn ngữ động cũng đã bị cuốn vào những ngóc ngách nơi chúng có ít hoặc không có cạnh tranh (ví dụ Javascript).

Các ngôn ngữ được gõ động ngắn gọn nhất (ví dụ: Perl, APL, J, K, Mathicala ) là các miền cụ thể và có thể ngắn gọn hơn đáng kể so với các ngôn ngữ được nhập tĩnh có mục đích chung ngắn gọn nhất (ví dụ OCaml ) trong các hốc mà chúng được thiết kế cho .

Những nhược điểm chính của gõ động là:

  • Lỗi loại thời gian chạy.

  • Có thể rất khó hoặc thậm chí thực tế không thể đạt được cùng một mức độ chính xác và đòi hỏi phải thử nghiệm nhiều hơn nữa.

  • Không có tài liệu xác minh trình biên dịch.

  • Hiệu suất kém (thường là vào thời gian chạy nhưng đôi khi vào thời gian biên dịch thay vào đó, ví dụ Steme Scheme) và hiệu suất không thể đoán trước do phụ thuộc vào tối ưu hóa tinh vi.

Cá nhân, tôi lớn lên trên các ngôn ngữ động nhưng sẽ không chạm vào chúng với cực 40 'như một chuyên gia trừ khi không có lựa chọn khả thi nào khác.


2
Tôi sẽ nói rào cản thấp hơn để nhập cảnh nhưng làm chủ không kém gì đường cong học tập.
Erik Reppen

Không phải là đường cong học tập ít hơn bởi vì bạn không có một hệ thống loại để học?
Jon Harrop

Vẫn còn một hệ thống loại. Bạn có thể đoán hợp lý về những gì xảy ra khi bạn thêm một bool và một chuỗi nhưng nó thường giúp rất nhiều để biết một số chi tiết thực tế về cách các loại được ép buộc trong một ngôn ngữ được gõ động. Đó là điều mà rất nhiều người nghiêm khắc chỉ không có được. Chúng tôi thực sự học những thứ này.
Erik Reppen

@ErikReppen: Chúng tôi đang sử dụng các định nghĩa khác nhau về "hệ thống loại". Tôi đã đề cập đến việc không phải học một hệ thống kiểu tĩnh, ví dụ như các kiểu dữ liệu đại số, tổng quát. Các "loại" mà bạn đang đề cập chỉ là dữ liệu. Thực tế là một số chức năng từ chối một số dữ liệu trong thời gian chạy là phổ biến.
Jon Harrop

12

Từ đánh máy của Artima : Bài viết mạnh so với yếu, tĩnh so với động :

gõ mạnh ngăn chặn các hoạt động trộn giữa các loại không khớp. Để trộn các loại, bạn phải sử dụng một chuyển đổi rõ ràng

gõ yếu có nghĩa là bạn có thể trộn các loại mà không cần chuyển đổi rõ ràng

Trong bài báo của Pascal Costanza, Đánh máy động so với gõ tĩnh - Phân tích dựa trên mẫu (PDF), ông tuyên bố rằng trong một số trường hợp, gõ tĩnh dễ bị lỗi hơn so với gõ động. Một số ngôn ngữ được nhập tĩnh buộc bạn phải mô phỏng thủ công gõ động để thực hiện "Điều đúng". Nó được thảo luận tại Lambda the Ultimate .


1
"Gõ tĩnh dễ bị lỗi hơn gõ động" - Vâng, vâng, và NHÂN ĐÔI có! Tôi đã có nhiều kinh nghiệm trong cả hai loại ngôn ngữ và trong mọi trường hợp, ngôn ngữ động "chỉ hoạt động" trong khi tĩnh yêu cầu gấp đôi thời gian gỡ lỗi (Xem C ++ và Delphi). Điều này thường xảy ra do các vấn đề về kiểu, đặc biệt là truyền dữ liệu giữa các mô-đun và hàm với các kiểu điên. Mặc dù có tất cả các loại lỗi lý thuyết mà ngôn ngữ động có thể gây ra, nhưng trên thực tế, RẤT hiếm khi tôi gặp phải lỗi do ép buộc kiểu trừ khi bạn là một lập trình viên kém lạm dụng các loại động.
dallin

7
Tôi đã đọc một bản thảo giấy Costanza vài năm trước. Ở mọi nơi anh ta đã viết "tĩnh", anh ta thực sự có nghĩa là "Java". Tôi đã đưa cho anh ấy hàng tá ví dụ phản biện bằng các ngôn ngữ như OCaml đã từ chối yêu cầu của anh ấy nhưng anh ấy vẫn tiếp tục và xuất bản nó. Nhìn vẻ ngoài của tờ giấy đó, anh ta vẫn xuất bản cùng một thứ vô nghĩa cũ. Ví dụ, trong bài báo đó, ông tuyên bố "C # nói chung là một bản sao xấu của Java". Điều đó không có chỗ trong một bài báo khoa học ...
Jon Harrop

@dallin Trải nghiệm của tôi hoàn toàn ngược lại: phải lập trình rất nhiều về C, C ++, Java, Python, Perl và những thứ tương tự, tôi sẽ không bao giờ bắt đầu bất cứ điều gì lớn hơn một chương trình điều chỉnh nhỏ bằng ngôn ngữ được gõ động trừ khi bị ép buộc. Trong Python, tôi vẫn rùng mình khi nghĩ về một dự án WSGI: các cuộc gọi lại mà tôi phải ghi đè được chuyển qua các tham chiếu của các đối tượng và mã dường như hoạt động tốt, khi nó bị lỗi vì đôi khi nó không phải là đối tượng mà là một số loại nguyên tố Được thông qua. Một ngôn ngữ giúp dễ dàng tạo ra những thứ lỗi như thế thật nguy hiểm.
Bia Michael

@MichaelBeer Bạn cũng có thể nói một ngôn ngữ như C / C ++ cho phép bạn trực tiếp quản lý bộ nhớ là điều nguy hiểm! Tôi chắc chắn đã vật lộn với lỗi bộ nhớ trong nhiều giờ. Các dự án Java lớn cũng không có dã ngoại. Trong bất kỳ ngôn ngữ nào, bạn phải hiểu được sự nguy hiểm của ngôn ngữ và các thực hành tốt. Các dự án tồi tệ nhất tuyệt đối tôi từng làm là các dự án PHP với cấu trúc nhỏ, nhưng tôi cũng đã làm việc với các dự án có ngôn ngữ động là mơ ước khi chúng sử dụng một khung công tác tốt và thực hành lập trình tốt.
dallin

@dallin Đồng ý, mọi ngôn ngữ đều có những cạm bẫy của nó. Nhưng những sai sót mà tôi đã đề cập là vốn có của bất kỳ ngôn ngữ gõ động nào, khả năng thao tác trực tiếp bộ nhớ không phải là thuộc tính vốn có của các ngôn ngữ được nhập tĩnh. Bạn có thể tưởng tượng các ngôn ngữ được gõ động cho phép bạn thao tác trực tiếp với mem. Tôi đồng ý rằng C ++ là một người tuyệt vọng, với chính người phát minh ra ngôn ngữ này tin rằng không một người nào trên hành tinh này có thể biết tất cả các phần của ngôn ngữ. Tuy nhiên, điều này không thể đổ lỗi cho việc C ++ bị đánh máy tĩnh, nhưng một con quái vật đã phát triển từ 30 năm nay ...
Michael Bia

3

Nó phụ thuộc vào bối cảnh. Có rất nhiều lợi ích phù hợp với hệ thống gõ động cũng như cho kiểu gõ mạnh. Tôi cho rằng dòng ngôn ngữ kiểu động nhanh hơn. Các ngôn ngữ động không bị hạn chế với các thuộc tính lớp và trình biên dịch nghĩ về những gì đang diễn ra trong mã. Bạn có một chút tự do. Hơn nữa, ngôn ngữ động thường biểu cảm hơn và dẫn đến ít mã hơn là tốt. Mặc dù vậy, nó dễ bị lỗi hơn và cũng đáng nghi ngờ và phụ thuộc nhiều hơn vào độ bao phủ của bài kiểm tra đơn vị. Đó là nguyên mẫu dễ dàng với lang động nhưng bảo trì có thể trở thành ác mộng.

Lợi ích chính của hệ thống gõ tĩnh là hỗ trợ IDE và phân tích mã chắc chắn. Bạn trở nên tự tin hơn về mã sau mỗi thay đổi mã. Việc bảo trì là hòa bình của bánh với các công cụ như vậy.


0

Có rất nhiều điều khác nhau về ngôn ngữ tĩnh và động. Đối với tôi, sự khác biệt chính là trong các ngôn ngữ động, các biến không có kiểu cố định; thay vào đó, các loại được gắn với các giá trị. Bởi vì điều này, mã chính xác được thực thi là không xác định cho đến khi thời gian chạy.

Trong các triển khai sớm hoặc ngây thơ, đây là một lực cản hiệu suất rất lớn, nhưng các JIT hiện đại đã tiến gần đến mức tốt nhất bạn có thể có được với việc tối ưu hóa các trình biên dịch tĩnh. (trong một số trường hợp rìa, thậm chí tốt hơn thế).


0

Đó là tất cả về công cụ phù hợp cho công việc. Không phải là tốt hơn 100% thời gian. Cả hai hệ thống được tạo ra bởi con người và có sai sót. Xin lỗi, nhưng chúng tôi hút và làm cho công cụ hoàn hảo.

Tôi thích gõ động vì nó không theo cách của tôi, nhưng có lỗi thời gian chạy có thể xuất hiện mà tôi không có kế hoạch. Khi gõ tĩnh có thể sửa các lỗi đã nói ở trên, nhưng điều khiển một lập trình viên mới (bằng ngôn ngữ đã gõ) đang cố gắng tạo ra một chuỗi char và chuỗi không đổi.


-3

Nhập tĩnh: Các ngôn ngữ như Java và Scala được gõ tĩnh.

Các biến phải được xác định và khởi tạo trước khi chúng được sử dụng trong mã.

cho người cũ int x; x = 10;

System.out.println (x);

Gõ động: Perl là một ngôn ngữ gõ động.

Các biến không cần phải được khởi tạo trước khi chúng được sử dụng trong mã.

y = 10; sử dụng biến này trong phần sau của mã


5
Điều này không có gì để làm với hệ thống loại.
Thiago Negri
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.