Ruby sinh năm bao nhiêu?
Ruby là một ngôn ngữ lập trình hướng đối tượng, có khả năng phản ứng. Theo tác giả, Ruby chịu ảnh hưởng bởi Perl, Smalltalk, Eiffel, Ada và Lisp. Ruby cung cấp nhiều mẫu hình lập trình, bao gồm lập trình hàm, hướng đối tượng, mệnh lệnh, phản xạ. Nó sử dụng hệ thống kiểu biến động và tự động quản lý bộ nhớ tự động. Ruby được tạo ra từ 24 tháng 2 năm 1993, bởi lập trình viên người Nhật Bản tên là Matsumoto Yukihiro (松本 行弘), biệt danh Matz. Phiên bản chính thức 0.95 (Đây là phiên bản công khai đầu tiên của Ruby được công bố tại Nhật Bản) vào ngày 21 tháng 12 năm 1995. Ở phiên bản Ruby 0.95, nó đã có nhiều tính năng quen thuộc trong các phiên bản sau của Ruby, bao gồm thiết kế hướng đối tượng, các lớp với kế thừa, mixin, vòng lặp, xử lý ngoại lệ và thu gom rác. Sau khi phát hành Ruby 0.95 vào năm 1995, một số phiên bản ổn định của Ruby đã được phát hành trong những năm tiếp theo:
Tháng 9 năm 2005, phiên bản ổn định mới nhất là 1.8.3. Ruby 1.9 (với một số thay đổi) cũng đang trong quá trình phát triển. Ruby 1.9 được phát hành vào ngày Giáng sinh năm 2007. Hiệu quả với Ruby 1.9.3, phát hành ngày 31 tháng 10 năm 2011, Ruby chuyển từ việc được cấp phép kép theo Giấy phép Ruby và GPL để được cấp phép kép theo Giấy phép Ruby và giấy phép BSD hai điều khoản. Việc chuyển đổi sang phiên bản 1.9 từ 1.8 đã bị chậm lại do nhiều gems phổ biến cần được viết lại. Ruby 1.9 giới thiệu nhiều thay đổi đáng kể so với các phiên bản 1.8. Ví dụ:
Ruby 1.9 đã lỗi thời kể từ ngày 23 tháng 2 năm 2015, [32] và nó sẽ không còn nhận được bản sửa lỗi và bảo mật nữa. Người dùng nên nâng cấp lên phiên bản mới hơn. Phiên bảnPhiên bản nâng cấpNgày phát hànhKết thúc giai đoạn hỗ trợKết thúc giai đoạn bảo trì bảo mật1.0Chưa rõ25/12/1996Chưa rõChưa rõ1.81,8,7-p37504/08/200306/201201/07/20141.91.9.3-p55125/12/200723/02/201423/02/20152.02.0.0-p64824/02/201324/02/201524/02/20162.12.1.1025/12/201330/03/201631/01/20172.22.2.1025/12/201428/03/201731/03/20182.32.3.825/12/201520/06/201831/03/20192.42.4.825/12/201601/04/201901/04/20202.52.5.725/12/2017Chưa được công bốChưa được công bố2.62.6.525/12/2018Chưa được công bốChưa được công bố2.72.7.025/12/2019Chưa được công bốChưa được công bố3.03.0.???/??/2020Chưa được công bốChưa được công bốChú thích:
Nguồn gốc của cái tên "Ruby" là từ một phiên chat online giữa Matsumoto và Ishitsuka Keiji vào ngày 24 tháng 2 năm 1993, trước khi bất kỳ đoạn mã nào được viết cho ngôn ngữ này. Ban đầu, "Coral" và "Ruby" là hai cái tên được đề xuất. Matsumoto chọn tên sau trong email gửi đến Ishitsuka. Sau này Matz cũng bất ngờ khi phát hiện ra Pearl là viên đá quý tượng trưng cho những người sinh tháng 6, còn Ruby thì tượng trưng cho những người sinh tháng 7. Anh cho rằng cái tên Ruby như thế là phù hợp vì Ruby kế thừa và phát triển nhiều đặc tính từ Perl . Quan điểm chính trong việc thiết kế của Matz là nhằm giảm thiểu các công việc nhàm chán mà họ, các nhà lập trình, buộc phải làm; tiếp đến là nguyên tắc thiết kế giao diện người dùng (user interface) hiệu quả. Ông nhấn mạnh rằng việc thiết kế hệ thống cần phải tập trung vào con người, hơn là vào máy tính : Often people, especially computer engineers, focus on the machines. They think, "By doing this, the machine will run faster. By doing this, the machine will run more effectively. By doing this, the machine will something something something." They are focusing on machines. But in fact we need to focus on humans, on how humans care about doing programming or operating the application of the machines. We are the masters. They are the slaves.Ngôn ngữ Ruby được thiết kế nhằm theo nguyên tắc ít gây ngạc nhiên nhất (principle of least surprise-POLS), nghĩa là ngôn ngữ hoạt động theo một cách trực quan hay ít nhất đó cũng là nhận xét mà các nhà lập trình đưa ra. Nguyên tắc này không xuất phát từ Matz và, nói chung, Ruby gần với suy nghĩ ít ngạc nhiên nhất của 'Matz' hơn. Ruby là một ngôn ngữ hướng đối tượng: mỗi giá trị đều là một đối tượng (object), bao gồm các kiểu dữ liệu mà đối với các ngôn ngữ khác, chúng là kiểu cơ bản (primitive) như integer. Mỗi hàm (function) là một phương thức (method). Tên biến (variables) chính là tham chiếu (references) đến các đối tượng, bản thân nó không phải là đối tượng. Ruby hỗ trợ kế thừa (inheritance) với dynamic dispatch, mixin và singleton method (thuộc về, và để định nghĩa cho, một instance đơn hơn là định nghĩa dành cho lớp). Mặc dù Ruby không hỗ trợ đa kế thừa, các lớp vẫn có thể được đưa vào các module dưới dạng các mixins. Cú pháp dạng thủ tục (procedural syntax) vẫn còn được hỗ trợ, có vẻ như là ngoài tầm vực của mọi đối tượng, nhưng thực sự là thuộc một thể hiện của class Object tên là 'main'. Vì class này là cha của mọi class khác, nó trở trên ẩn đối với mọi lớp và đối tượng. Ruby được xem là một ngôn ngữ lập trình đa mẫu hình (multi-paradigm programming language): nó cho phép bạn lập trình dạng thủ tục (tạo ra các hàm/biến nằm ngoài phạm vi của các lớp và biến chúng thành một phần của đối tượng gốc, 'self' Object), với khả năng hướng đối tượng (mọi thứ đều là đối tượng) hay hàm (nó có các hàm không có tên (anonymous functions), closures, và continuations; mọi câu lệnh đều có giá trị trả về, và các hàm đều trả về kết quả ước lượng cuối cùng). Nó hỗ trợ mạnh cho tự định kiểu (type introspection), reflection và meta-programming. Theo Ruby FAQ, "Nếu bạn thích Perl, bạn sẽ thích Ruby và sẽ thấy thoải mái với cú pháp của nó. Nếu bạn thích Smalltalk, bạn sẽ thích Ruby và sẽ thấy thoải mái với ngữ nghĩa của nó (semantics). Nếu bạn thích Python, bạn có thể hoặc không thể dừng lại bởi sự khác biệt lớn trong triết lý hiện thực giữa Python và Ruby/Perl." Ruby có hai bản thông dịch chính: bộ thông dịch Ruby ban đầu (viết tắt là MRI), bản được dùng phổ biến nhất, và JRuby, bộ thông dịch dựa trên ngôn ngữ Java. Bộ thông dịch Ruby đã được cài đặt trên nhiều nền tảng khác nhau, bao gồm Unix, Microsoft Windows, DOS, Mac OS X, OS/2, Amiga và một số nền tảng khác. Bản chính thức của Ruby có kèm theo "IRB", là bộ thông dịch dạng dòng lệnh trực tiếp (interactive command-line interpreter) giúp cho việc kiểm tra code nhanh chóng. Ruby được phân phối tự do theo đăng ký tự do và mã nguồn mở GPL và Ruby License [1] Lưu trữ 2011-08-26 tại Wayback Machine. Ruby hiện tại vẫn chưa hỗ trợ Unicode, dù chỉ mới hỗ trợ tạm thời cho UTF-8. Mặc dù việc thiết kế Ruby tuân theo nguyên tắc ít gây ngạc nhiên nhất, nhưng một số tính năng khác với các ngôn ngữ khác như C hay Perl:
Một danh sách các lỗi thường gặp ("gotchas") có thể tra trong cuốn sách của Hal Fulton The Ruby Way, trang 48–64. Tuy nhiên, vì danh sách trong cuốn sách là dựa trên phiên bản cũ của Ruby (version 1.6), một số mục đã được sửa đổi sau khi cuốn sách ấn hành. Ví dụ, puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'4 bây giờ làm việc được với puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'5, puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'6 và puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'7, cũng như với iterators. Lưu ý: Các ví dụ sử dụng chuỗi ký tự Unicode để chạy được cần đặt một biến môi trường là $KCODE="u". Hay là chạy #ruby với tùy chọn là -K u vẫn được. Xem thêm những hạn chế của phiên bản Ruby hiện tại với Unicode tại ruby và unicode Lưu trữ 2005-12-18 tại Wayback Machine # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty" print 'Làm ơn gõ tên >' name = gets.chomp puts "Chào #{name}." puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.' Khởi tạo và sử dụng một mảng: a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5] Khởi tạo và xây dựng một mảng kết hợp (Ruby gọi là hash): hash = Hash.new # Tương đương với hash = {} hash = {:water => 'wet',:fire => 'hot'} # Đoạn mã đầu trở nên dư thừa khi # đưa cho hash một đối tượng hash riêng biệt mới puts hash[:fire] # Xuất ra "hot" hash.each_pair do |key, value| # Hoặc: hash.each do |key, value| puts "#{key} is #{value}" end # Trả về {:water => 'wet',:fire => 'hot'} và xuất ra: # water is wet # fire is hot hash.delete:water # Hủy cặp giá trị:water => 'wet' và trả về "wet" hash.delete_if {|key, value| value == 'hot'} # Hủy cặp giá trị:fire => 'hot' và trả về {} Mệnh đề If: # Tạo ra một số ngẫu nhiên và in ra số đó là chẵn hay lẻ. if rand(100) % 2 == 0 puts "Là số chẵn" else puts "Là số lẻ" end 2 cách để tạo một đoạn block: { puts 'Xin chào, thế giới!' } # lưu ý dấu ngoặc # hoặc: do puts 'Xin chào, thế giới!' end Một block có thể được truyền đến một hàm (method) như một tham số tùy chọn. Nhiều hàm được cài sẵn có tham số như vậy: File.open('file.txt', 'w') do |file| # 'w' biểu thị "chế độ ghi chép" file.puts 'Viết gì đó' end # Tập tin sẽ tự động đóng ở đây File.readlines('file.txt').each do |line| puts line end # => 'Viết gì đó' Thông số đi qua block để trở thành closure (ví dụ): # Trong một biến thể hiện đối tượng (biểu thị bằng '@'), hãy lưu block này. def remember(&p) @block = p end # Dùng hàm trên, cho block đó một cái tên. remember {|ten| puts "Xin chào, #{ten}!"} # Dùng closure (lưu ý rằng điều này không có áp dụng tự do cho các biến khác):! @block.call("Tèo") # Xuất ra "Xin chào, Tèo!" Tạo ra một hàm ẩn danh: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"0 Trả về closure từ một hàm: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"1 Trong một hàm, có thể thay đổi block vào lúc gọi hàm: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"2 Duyệt lần lượt trên enumation và mảng bằng cách dùng block: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"3 Block cũng có thể dùng với các hàm dựng sẵn: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"4 Hay: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"5 Sử dụng enumeration và block để xuất ra lũy thừa 2 của các số từ 1 đến 10: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"6 Đoạn mã sau định nghĩa một lớp tên là puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'8. Bên cạnh phương thức khởi tạo puts 'Cho tôi con số của bạn' number = gets.chomp puts number.to_i output_number = number.to_i + 1 puts output_number.to_s + ' là một con số lớn hơn.'9, là phương thức được gọi đến khi cần tạo đối tượng mới, lớp này còn có 2 phương thức khác: một là ghi đè lên toán tử so sánh <=> (vì thế a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]0 có thể sắp xếp theo tuổi) và hai là là ghi đè lên phương thức a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]1 (vì thế a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]2 có thể định dạng đầu ra của nó). Ở đây, a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]3 là một ví dụ của meta-programming trong Ruby: nó định nghĩa các phương thức dạng getter và setter của biến thực thể, trong khi a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]4 các phương thức dạng 'getter'. Và, câu lệnh cuối cùng trong một phương thức là giá trị trả về của nó, điều này cho phép bỏ qua lệnh a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]5. # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"7 Đoạn mã trên in ra ba tên theo tuổi giảm dần: Một trường hợp ngoại lệ được đưa ra với lệnh a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]6: Có thể thêm một thông báo tùy chọn: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"8 Ngoại lệ cũng có thể xác định bởi các lập trình viên: # Mọi thứ, kể cả tầm thường nhất, là một đối tượng. Vì thế những ví dụ dưới đều chạy được: -199.abs # => 199, abs: giá trị tuyệt đối "ruby is cool".length # => 12 "Rick".index("c") # => 2 "Nice Day Isn't It?".split(//).uniq.sort.join # => " '?DINaceinsty"9 Ngoài ra, một thực thể của lớp Ngoại lệ có thể tạo ra được với biến a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]6 như sau: print 'Làm ơn gõ tên >' name = gets.chomp puts "Chào #{name}."0 Có thể tìm thấy các code mẫu của Ruby dưới dạng các thuật toán tại: Ruby có thể chạy trên các hệ điều hành sau: Có thể còn thêm một số platform khác. viết dòng này vào file hello.rb và chạy thử Cú pháp trong Ruby tương tự như Perl and Python. Lớp và phương thức được định nghĩa thông qua các từ khóa, ngoài ra khối (block) còn có thể được định nghĩa bằng cặp dấu ngoặc nhọn a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]8. Khác với Perl, biến số (variable) không nhất thiết phải bắt đầu bằng dấu a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]9, và nếu sử dụng sẽ thay đổi phạm vi của biến số. Các kí tự xuống dòng (line breaks) cũng như dấu chấm phẩy hash = Hash.new # Tương đương với hash = {} hash = {:water => 'wet',:fire => 'hot'} # Đoạn mã đầu trở nên dư thừa khi # đưa cho hash một đối tượng hash riêng biệt mới puts hash[:fire] # Xuất ra "hot" hash.each_pair do |key, value| # Hoặc: hash.each do |key, value| puts "#{key} is #{value}" end # Trả về {:water => 'wet',:fire => 'hot'} và xuất ra: # water is wet # fire is hot hash.delete:water # Hủy cặp giá trị:water => 'wet' và trả về "wet" hash.delete_if {|key, value| value == 'hot'} # Hủy cặp giá trị:fire => 'hot' và trả về {}0 phân chia các mệnh đề (statement) với nhau. Một trong những điểm khác biệt lớn nhất so với Perl và Python là Ruby ẩn hoàn toàn các biến của thực thể (instance) và chỉ có thể truy cập và chỉnh sửa chúng thông qua các phương thức (như hash = Hash.new # Tương đương với hash = {} hash = {:water => 'wet',:fire => 'hot'} # Đoạn mã đầu trở nên dư thừa khi # đưa cho hash một đối tượng hash riêng biệt mới puts hash[:fire] # Xuất ra "hot" hash.each_pair do |key, value| # Hoặc: hash.each do |key, value| puts "#{key} is #{value}" end # Trả về {:water => 'wet',:fire => 'hot'} và xuất ra: # water is wet # fire is hot hash.delete:water # Hủy cặp giá trị:water => 'wet' và trả về "wet" hash.delete_if {|key, value| value == 'hot'} # Hủy cặp giá trị:fire => 'hot' và trả về {}1, a = [1, 'chào', 3.14, 1, 2, [4, 5]] a[2] # => 3.14 a.reverse # => [[4, 5], 2, 1, 3.14, 'chào', 1] a.flatten.uniq # => [1, 'chào', 3.14, 2, 4, 5]4). Ruby Application Archive đóng vai trò là một kho lưu trữ đủ loại ứng dụng và các thư viện viết bằng Ruby, với hàng ngàn mục. Mặc dù số lượng ứng dụng sẵn có không lớn bằng với cộng đồng của Perl hay Python, vẫn có đủ loại công cụ và tiện ích nhằm hỗ trợ cho việc phát triển ngôn ngữ trong tương lai. |