Khác biệt giữa các bản “Ngôn ngữ lập trình”

n (Đã lùi lại sửa đổi của 113.172.140.110 (Thảo luận) quay về phiên bản cuối của Tuanminh01)
Thẻ: Lùi tất cả
<div id="STRONG">Các '''ngôn ngữ có kiểu mạnh''' không cho phép dùng các giá trị của kiểu này như là một kiểu khác. Chúng rất chặt chẽ trong việc phát hiện sự dùng sai kiểu. Việc phát hiện này sẽ xảy ra ở thời gian thi hành (''run-time'') đối với các ngôn ngữ có kiểu động và xảy ra ở thời gian dịch đối với các ngôn ngữ có kiểu tĩnh.<br />[[ADA]], [[Java (ngôn ngữ lập trình)|Java]], ML và [[Oberon]] là các ví dụ của ngôn ngữ có kiểu mạnh.</div>
<DIV id="WEAK">Ngược lại, '''ngôn ngữ có kiểu yếu''' không quá khắt khe trong các quy tắc về kiểu hoặc cho phép một cơ chế tường minh để xử lý các vi phạm. Thường nó cho phép hành xử các biểu hiện chưa được định nghĩa trước, các vi phạm về sự phân đoạn (''segmentation''), hay là các biểu hiện không an toàn khác khi mà các kiểu bị gán giá trị một cách không đúng.<br />[[C (ngôn ngữ lập trình)|C]], [[ASM]], [[C++]], Tcl và [[Lua]] là các ví dụ của ngôn ngữ có kiểu yếu.</div>
 
Lưu ý:
* Các khái niệm về kiểu ''mạnh'' hay ''yếu'' có tính tương đối. Java là ngôn ngữ có kiểu mạnh đối với C nhưng yếu đối với ML. Tùy theo cách nhìn mà các khái niệm đó được dùng, nó tương tự như việc xem ngôn ngữ ASM là ở cấp ''thấp'' hơn ngôn ngữ C; trong khi Java lại là ngôn ngữ ở mức ''cao'' hơn C.
* Hai khái niệm ''tĩnh'' và ''mạnh'' cũng không đối lập nhau. Java là ngôn ngữ có kiểu mạnh và tĩnh. C là ngôn ngữ có kiểu yếu và tĩnh. Trong khi đó, Python là ngôn ngữ có kiểu mạnh và động. Tcl lại là ngôn ngữ có kiểu yếu và động. ''Cũng nên biết trước rằng có nhiều người đã dùng sai các khái niệm trên và cho rằng kiểu mạnh là kiểu tĩnh cộng với mạnh. Lầm lẫn hơn, họ còn cho rằng ngôn ngữ C có kiểu mạnh mặc dù rằng C không hề bắt nhiều loại lỗi về việc dùng sai kiểu.''
 
=== Cấu trúc dữ liệu ===
Hầu hết các ngôn ngữ đều cung cấp các cách thức để lắp ráp các cấu trúc dữ liệu phức tạp từ các kiểu sẵn có và để liên kết các tên với các kiểu mới kết hợp (dùng các kiểu [[mảng (lập trình)|mảng]], [[danh sách (lập trình)|danh sách]], [[hàng đợi (lập trình)|hàng đợi]], [[ngăn xếp (lập trình)|ngăn xếp]] hay [[tập tin]]).
 
Các ngôn ngữ [[lập trình hướng đối tượng|hướng đối tượng]] cho phép [[lập trình viên]] định nghĩa các kiểu dữ liệu mới gọi là [[đối tượng]]. trong nội bộ các đối tượng đó có riêng các hàm và các biến (và thường được gọi theo thứ tự là các ''phương thức'' và các ''thuộc tính''). Một chương trình có định nghĩa các đối tượng sẽ cho phép các đối tượng đó thực thi như là các [[chương trình con]] độc lập nhưng lại tương tác nhau. Các tương tác này có thể được thiết kế trong lúc viết mã để mô hình hóa và mô phỏng theo đời sống thật của các đối tượng. Nói một cách đơn giản, các ngôn ngữ [[lập trình hướng đối tượng|hướng đối tượng]] đã được cho thêm ''sức sống'' để có riêng những tính năng hoạt động và tương tác với thế giới bên ngoài. Ngoài ra, các đối tượng còn có thêm các đặc tính như là thừa kế và đa hình. Điều này là một ưu thế trong việc dùng ngôn ngữ loại này để mô tả các đối tượng của thế giới thực.
 
=== Các mệnh lệnh và dòng điều khiển ===
Khi dữ liệu đã được định rõ, máy tính phải được chỉ thị làm thế nào để tiến hành các phép toán trên dữ liệu đó. Những mệnh đề cơ bản có thể được cấu trúc thông qua việc sử dụng các từ khóa (đã được định nghĩa bởi ngôn ngữ lập trình) hoặc là có thể tạo thành từ việc dùng và kết hợp các cấu trúc ngữ pháp hay cú pháp đã được định nghĩa. Những mệnh đề cơ bản này gọi là các [[câu lệnh]].
 
Tùy theo ngôn ngữ, các câu lệnh có thể được kết hợp với nhau theo trật tự nào đó. Điều này cho phép thiết lập được các chương trình thực hiện được nhiều chức năng. Xa hơn, ngoài các câu lệnh để thay đổi và điều chỉnh dữ liệu, còn có những kiểu câu lệnh dùng để điều khiển dòng xử lý của máy tính như là phân nhánh, định nghĩa bởi nhiều trường hợp, vòng lặp, hay kết hợp các chức năng. Đây là các thành tố không thể thiếu của một ngôn ngữ lập trình.
 
=== Các tên và các tham số ===
Muốn cho chương trình thi hành được thì phải có phương pháp xác định được các vùng trống của bộ nhớ để làm kho chứa dữ liệu. Phương pháp được biết nhiều nhất là thông qua tên của các biến. Tùy theo ngôn ngữ, các vùng trống gián tiếp có thể bao gồm các tham chiếu, mà thật ra, chúng là các con trỏ (''pointer'') chỉ đến những vùng chứa khác của bộ nhớ, được cài đặt trong các biến hay nhóm các biến. Phương pháp này gọi là ''đặt tên kho nhớ''.
Tương tự với phương pháp đặt tên kho nhớ, là phương pháp ''đặt tên những nhóm của các chỉ thị''. Trong hầu hết các ngôn ngữ lập trình, đều có cho phép gọi đến các [[macro (điện toán)|macro]] hay các [[chương trình con]] như là các câu lệnh để thi hành nội dung mô tả trong các [[macro (điện toán)|macro]] hay [[chương trình con]] này thông qua tên. Việc dùng tên như thế này cho phép các chương trình đạt tới một sự linh hoạt cao và có giá trị lớn trong việc tái sử dụng [[mã nguồn]] (vì người viết mã không cần phải lặp lại những đoạn mã giống nhau mà chỉ việc định nghĩa các [[macro (điện toán)|macro]] hay các [[chương trình con]].)
 
Các tham chiếu gián tiếp đến các chương trình khả dụng hay các bộ phận dữ liệu đã được xác định từ trước cho phép nhiều ngôn ngữ định hướng ứng dụng tích hợp được các thao tác khác nhau.
 
=== Cơ chế tham khảo và việc tái sử dụng mã nguồn ===
Mỗi ngôn ngữ lập trình đều có một bộ các cú pháp quy định việc lập trình sao cho [[mã nguồn]] được thực thi. Theo đó, mỗi nhà sản xuất ngôn ngữ lập trình sẽ cung cấp một bộ các cấu trúc ngữ pháp cho các câu lệnh, một khối lượng lớn các từ vựng quy ước được định nghĩa từ trước, và một số lượng các thủ tục hay hàm cơ bản. Ngoài ra, để giúp lập trình viên dễ dàng sử dụng, nhà sản xuất còn phải cung cấp các tài liệu tra cứu về đặc tính của ngôn ngữ mà họ phát hành. Những tài liệu tra cứu này bao gồm hầu hết các đặc tả, tính chất, các tên (hay từ khoá) mặc định, phương pháp sử dụng, và nhiều khi là các [[mã nguồn]] để làm ví dụ. Do sự không thống nhất trong các ý kiến về việc thiết kế và sử dụng từng ngôn ngữ nên có thể xảy ra trường hợp [[mã nguồn]] của cùng một ngôn ngữ chạy được cho phần mềm dịch này nhưng không tương thích được với phần mềm dịch khác. Ví dụ là các [[mã nguồn]] C viết cho Microsoft C (phiên bản 6.0) có thể không chạy được khi dùng trình dịch Borland (phiên bản 4.5) nếu không biết cách thức điều chỉnh. Đây cũng là nguyên do của các kỳ hội nghị chuẩn hóa ngôn ngữ lập trình. Ngoài công việc chính là phát triển ngôn ngữ đặc thù, hội nghị còn tìm cách thống nhất hóa ngôn ngữ bằng cách đưa ra các tiêu chuẩn, các khuyến cáo thay đổi về ngôn ngữ trong tương lai hay các đổi mới về cú pháp của ngôn ngữ.
 
Những đổi mới về tiêu chuẩn của một ngôn ngữ mặt khác lại có thể gây ra các hiệu ứng phụ. Đó là việc [[mã nguồn]] của một ngôn ngữ dùng trong phiên bản cũ không tương thích được với phần mềm dịch dùng tiêu chuẩn mới hơn. Đây cũng là một việc cần lưu tâm cho những người lập trình. Trường hợp điển hình nhất là việc thay đổi phiên bản về ngôn ngữ [[Visual Basic]] của [[Microsoft]]. Các [[mã nguồn]] của phiên bản 6.0 có thể sẽ không dịch được nếu dùng phiên bản mới hơn. Lý do là nhà thiết kế đã thay đổi kiến trúc của VisualBasic để nâng cao và cung cấp thêm các chức năng mới về lập trình theo định hướng đối tượng cho ngôn ngữ này.
 
Thay vào việc tái sử dụng [[mã nguồn]] thì cũng có các hướng phát triển khác nhằm tiết kiệm công sức cho người lập trình mà hai hướng chính là:
* Việc ra đời của các [[bytecode]] mà điển hình là ngôn ngữ Java. Với Java thì [[mã nguồn]] sẽ được dịch thành một ngôn ngữ trung gian khác gọi là bytecode. Mã của bytecode một lần nữa sẽ được phần mềm thông dịch thực thi, phần mềm này gọi là máy ảo. Các máy ảo được cài đặt sẵn trên các máy tính và được cung cấp miễn phí. Tùy theo [[hệ điều hành]] mà có thể cài đặt máy ảo thích hợp. Do đó, cùng một nguồn Java bytecode có thể chạy trong bất cứ hệ điều hành nào miễn là hệ điều hành đó có cài đặt sẵn máy ảo Java. Việc này tiết kiệm rất nhiều công sức cho lập trình viên vì họ không phải viết mã Java khác nhau cho mỗi hệ điều hành.
* Tận dụng tính chất thừa kế của các lớp (''class'') trong các ngôn ngữ [[lập trình hướng đối tượng|hướng đối tượng]]. Theo kiểu thiết kế này, một đối tượng có thể thụ hưởng các đặc tính mà các thế hệ trước của chúng đã có. Do đó, khi phát triển phần mềm mới theo cấu trúc của các lớp, người ta chỉ cần tạo thêm các lớp con (''subclass'') có nhiều tính năng mới hơn. Điều này giúp giảm bớt công sức vì không phải phát triển lại từ đầu. (Lưu ý: Java cũng là một loại ngôn ngữ hướng đối tượng nên nó có luôn ưu thế này.)
 
=== Triết lý của các thiết kế ===
Tùy theo mục đích của ngôn ngữ mà chúng được thiết kế để tạo điều kiện giải quyết những vấn đề mà ngôn ngữ đó hướng tới. Những chức năng này làm cho một ngôn ngữ có thể tiện lợi để dùng phát triển loại phần mềm này nhưng có thể khó để phát triển loại phần mềm khác.
 
Hầu hết các ngôn ngữ đòi hỏi sự chính xác cao về mặt cú pháp. Các ngôn ngữ không cho phép có lỗi. Mặc dù vậy, một số ít ngôn ngữ cũng cho phép tự điều chỉnh trong một mức độ khá cao, khi đó chương trình tự viết lại để xử lý những trường hợp mới. Các ngôn ngữ như Prolog, PostScript và các thành viên trong họ ngôn ngữ Lisp có khả năng này. Trong ngôn ngữ MUMPS, kỹ thuật này gọi là tái biên dịch động. Các phần mềm mô phỏng và nhiều máy ảo (''virtual machine'') khai thác kỹ thuật này để có hiệu suất cao.
 
Một yếu tố liên quan đến triết lý thiết kế là có một số ngôn ngữ vì muốn tạo sự dễ dàng cho người mới dùng, đã không phân biệt việc viết chữ hoa hay không. Pascal và Basic là hai ngôn ngữ không phân biệt việc một ký tự có viết hoa hay không, trái lại trong C/C++, Java, PHP, Perl, BASH đều bắt buộc phải bảo đảm việc viết đúng y hệt như lúc khai báo cho các tên.
 
== Các thành tố căn bản của một ngôn ngữ ==
=== Các dạng câu lệnh ===
Câu lệnh là một thành tố quan trọng nhất của mọi ngôn ngữ lập trình. Tùy theo ngôn ngữ các câu lệnh đều phải tuân theo các trật tự sắp xếp của các [[từ khóa]], [[tham số]], [[biến số|biến]] và các định danh khác như các [[macro (điện toán)|macro]], hàm, thủ tục cũng như các quy ước khác. Tập hợp trật tự và quy tắc đó tạo thành [[cú pháp học|cú pháp]] của ngôn ngữ lập trình. Các dạng câu lệnh bao gồm
* <div id="DEF">'''Định nghĩa''': Dạng câu lệnh này cho phép xác định một kiểu dữ liệu mới hay một [[#CONST|hằng]]. Lưu ý là trong các ngôn ngữ [[lập trình hướng đối tượng|lập trình định hướng đối tượng]] thì mỗi lớp đều có thể là một kiểu dữ liệu mới do đó việc tạo ra một lớp mới tức là đã dùng câu lệnh kiểu định nghĩa.
:Ví dụ: Trong C hay C++, câu lệnh <code>#define PI 3.1415927</code> sẽ cho phép định nghĩa tên ([[macro (điện toán)|macro]]) PI với giá trị không đổi là 3,1415927.
 
* <div id="DECLARE">'''Khai báo''': Cũng gần giống như dạng định nghĩa, dạng khai báo cho phép người lập trình chính thức thông báo về sự ra đời của một biến, hay một tên (tên hàm chẳng hạn). Thông thường, đối với ngôn ngữ tĩnh, tên hàm hay biến mới đều phải có phần cho biết kiểu dữ liệu của biến hay hàm. Tuy nhiên, điều này không bắt buộc với ngôn ngữ động. Ngoài ra, các khai báo đôi khi còn cho phép các biến gán một giá trị ban đầu nhưng thường thì việc này cũng không bắt buộc. (Xem thêm loại câu lệnh gán giá trị). Đối với nhiều ngôn ngữ thì việc khai báo có thể cho phép chương trình đó được cấp thêm một phần bộ nhớ dự trữ riêng cho các biến (hay các đối tượng) đăng ký tên trong câu lệnh khai báo.</div>
Người dùng vô danh