Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Khám phá 9 cải tiến quan trọng trong Ruby 2.4 – Những gì lập trình viên cần biết

Đã trở thành truyền thống phát hành các phiên bản Ruby mới vào dịp Giáng sinh.

Và trong bài viết này, tôi muốn đề cập đến một số thay đổi thú vị nhất trong Ruby 2.4 để bạn có thể cập nhật tin tức 🙂

Float#round với từ khóa

Nếu bạn đang sử dụng float trong ứng dụng, tôi hy vọng bạn dùng floor hoặc ceil để làm tròn, vì phương thức Float#round đang thay đổi hành vi mặc định trong Ruby 2.4.

Ví dụ:

# Ruby 2.3
(2.5).round # 3
# Ruby 2.4
(2.5).round # 2

Hành vi mặc định giờ là "làm tròn đến số chẵn gần nhất" (round-to-nearest-even).

CẬP NHẬT: Hành vi mặc định cho Float#round đã quay lại "làm tròn lên" trong phiên bản cuối cùng của Ruby 2.4. Đây là quyết định của Matz sau khi bài viết này được xuất bản ban đầu.

Ngoài ra, Float#round giờ chấp nhận một đối số cho phép bạn định nghĩa loại làm tròn bạn muốn.

Các tùy chọn là:

  • :even
  • :up
  • :down

Ví dụ:

(4.5).round(half: :up) # 5

Cũng Float#floor, Float#ceil và Float#truncate giờ nhận một đối số tùy chọn cho phép bạn thiết lập độ chính xác.

Cờ chomp cho các phương thức IO

Nếu bạn từng dùng phương thức như gets hoặc each_line, tôi chắc chắn bạn nhớ việc phải đối phó với những ký tự xuống dòng phiền toái kia.

Những ký tự trông như thế này: \n.

Đây là thứ người mới bắt đầu luôn gặp khó khăn, nhưng tính năng mới này có thể giúp đỡ!

Dưới đây là ví dụ:

input = gets.chomp # "abc\n"

Giờ trong Ruby 2.4, bạn có thể thiết lập đối số từ khóa chomp và gets sẽ tự động loại bỏ ký tự xuống dòng cho bạn.

Ví dụ:

input = gets(chomp: true) # "abc"

Điều này sẽ hoạt động với bất kỳ giá trị nào không phải false hoặc nil (hai giá trị "falsy" duy nhất trong Ruby).

Vì vậy, điều này cũng hoạt động (nhưng không khuyến khích vì có thể gây nhầm lẫn):

input = gets(chomp: 1234) # "abc"

Đây không phải là vấn đề quá lớn, nhưng nó có thể giúp bạn tiết kiệm một lời gọi phương thức 🙂

Pathname#empty?

Ruby 2.4 triển khai Dir#empty? và File#empty?, các phương thức này cho phép bạn kiểm tra xem một thư mục hoặc tệp có rỗng không (điều đó khá rõ ràng, đúng không?).

Nhưng Pathname#empty? cũng vừa được thêm vào gần đây.

Nếu bạn chưa quen với Pathname, đây là một lớp gộp chức năng từ cả lớp Dir và File.

Ngoài ra, nó cũng "OO" (Hướng đối tượng) hơn trong việc trả về đối tượng Pathname thay vì chuỗi.

Ví dụ:

Pathname.empty?("file or directory name")

Commit: https://github.com/ruby/ruby/commit/9373c5efb993dd8cae0526118805449b19af2c22

Set compare_by_identity

Set là một cấu trúc dữ liệu có sẵn như một phần của thư viện chuẩn. Nó giúp bạn giữ một tập hợp các mục duy nhất.

Mặc định, các đối tượng được so sánh dựa trên giá trị của chúng (hoặc chính xác hơn, dựa trên giá trị hash của chúng).

Nhưng trong Ruby 2.4, có thể có một set các đối tượng duy nhất dựa trên object_id của chúng.

Ví dụ:

require 'set'
# Set bình thường
set = Set.new
set << 123 << 123 << "abc" << "abc"
# [123, "abc"]
# Set theo identity
set = Set.new().compare_by_identity
set << 123 << 123 << "abc" << "abc"
# [123, "abc", "abc"]

Nếu ai biết trường hợp sử dụng thú vị cho tính năng này, hãy để lại bình luận 🙂

Commit: https://github.com/ruby/ruby/commit/76977611dd68e384fdce8c546efda5e1931e67a6

Refinements với Kernel#send, BasicObject#send, Symbol#to_proc

Tôi không sẽ đề cập chi tiết về refinements ở đây, nhưng ý tưởng cơ bản là có thể thêm phương thức vào một lớp như String, trong khi giữ thay đổi này "cục bộ" trong một tệp hoặc lớp.

Kể từ Ruby 2.4, các phương thức được định nghĩa qua refinements sẽ có sẵn khi được gọi qua các phương thức như Kernel#send và Symbol#to_proc.

Ví dụ:

module TenTimes
  refine String do
    def ten_times
      puts self * 10
    end
  end
end
class Thing
  using TenTimes
  "abc".send(:ten_times)
end

Nếu bạn thử điều này trong 2.3 hoặc thấp hơn, bạn sẽ gặp lỗi 'undefined method'.

Commit: https://github.com/ruby/ruby/commit/35a29390197750abf97ef16fa0740e377764daef

Hash#transform_values

Đây là một phương thức khác được trích xuất từ Rails và đưa thẳng vào Ruby. Tôi đang nói về Hash#transform_values, hoạt động tương tự như Array#map.

Ví dụ:

h = {a: 1, b: 2, c: 3}
h.transform_values { |v| v * 10 } # {a: 10, b: 20, c: 30}

Cũng có Hash#transform_values! nếu bạn cần thay đổi tại chỗ (in-place mutation).

Kernel#clone giờ nhận đối số từ khóa tùy chọn

Như bạn có thể biết, có thể tạo bản sao của một đối tượng Ruby. Điều này hữu ích vì hầu hết các đối tượng Ruby đều có thể thay đổi (mutable) và bạn có thể muốn tránh làm thay đổi đối tượng gốc.

Chúng ta có hai phương thức để tạo bản sao đối tượng:

  • clone
  • dup

Có một vài khác biệt nhỏ giữa clone và dup, nhưng cho bài viết này hãy chỉ nói rằng clone giữ trạng thái "frozen" của đối tượng gốc trong khi dup thì không.

Mới trong 2.4 là khả năng gọi clone với cờ "freeze".

Ví dụ:

foo = "test".freeze
boo = foo.clone(freeze: false)
boo.frozen? # false

Tôi không chắc tính năng này hữu ích đến mức nào, nhưng ai không muốn nhiều tùy chọn hơn 🙂

Commit: https://github.com/ruby/ruby/commit/320ae01c5fb091eab0926c186f304a9caeda1ace

Thread.report_on_exception

Một tính năng khác đi kèm 2.4 là Thread.report_on_exception. Điều này được đề xuất vì ngoại lệ Thread mặc định là im lặng, và điều này có thể che giấu các vấn đề với mã của bạn.

Giá trị mặc định là false, nhưng nếu ứng dụng của bạn sử dụng Thread, bạn nên thử bật tùy chọn này khi nâng cấp lên Ruby 2.4.

Ví dụ:

Thread.report_on_exception = true
t1 = Thread.new do
  puts "In new thread"
  raise "Exception from thread"
end
sleep(1)
puts "In the main thread"

Điều này sẽ hiển thị ngoại lệ, nhưng sẽ không làm sập chương trình của bạn. Phương án thay thế là Thread.abort_on_exception, luôn có sẵn từ trước.

Chú ý rằng cũng có phiên bản instance của phương thức này, nên bạn có thể thiết lập tùy chọn này cho từng thread thay vì tất cả các thread.

Binding#irb

Bạn có phải fan của việc dùng binding.pry để gỡ lỗi? Giờ chúng ta cũng có binding.irb hoạt động theo cách tương tự.

Nhưng vì là irb, bạn vẫn không có tất cả những thứ tuyệt vời mà pry cung cấp, như tô màu cú pháp.

Tốt hơn không nếu vì lý do nào đó bạn không có quyền truy cập pry 🙂

Commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a

Kết luận

Phiên bản Ruby mới này mang lại nhiều tính năng thú vị, vì vậy hãy chắc chắn kiểm tra nó khi có sẵn.

Đừng quên chia sẻ bài viết này để nhiều người hơn có thể học hỏi về các tính năng mới trong Ruby 2.4!