1 Câu hỏi: Làm thế nào để tuyên bố thử lại hoạt động trong Ruby?

câu hỏi được tạo ra tại Wed, May 8, 2019 12:00 AM

Tôi mới bắt đầu sử dụng Ruby, nhưng hướng dẫn sử dụng mà tôi đang theo dõi dường như đã lỗi thời. Tôi đã thực hiện một số nghiên cứu nhưng tôi không thể tìm thấy câu trả lời rõ ràng.

Hướng dẫn sử dụng từ khóa 'thử lại' bên trong phương thức hoạt động như một vòng lặp, nhưng nó được sử dụng mà không có khối bắt đầu /giải cứu và hành vi có vẻ khá khác biệt khi bạn buộc từ khóa 'thử lại' ở bên trong của một khối bắt đầu /giải cứu.

Tôi đã thử nhiều thứ: -Đầu tiên đầu tiên là sử dụng từ khóa "bắt đầu" khi bắt đầu phương thức và 'nâng cao' tại điểm thử lại, sau đó là 'giải cứu tương ứng; thử lại; kết thúc;'. -Bạn cuối cùng đã sử dụng khối 'bắt đầu /giải cứu' bên ngoài, kết thúc cuộc gọi của phương thức.

Theo logic trong hướng dẫn sử dụng, chỉ có cái cuối cùng hoạt động như bình thường.

Có một số ví dụ:

Mã trong hướng dẫn sử dụng như sau:

def WHILE(cond)
  return if not cond
  yield
  retry
end
i=0; WHILE(i<3) {print i; i+=1}
kết quả

: 012

Tôi đã thử các cách sau:

def WHILE(cond)
  begin
    return if not cond
    yield
    raise
  rescue
    retry
  end
end
i=0; WHILE(i<3) {print i; i+=1}
kết quả

: số vô hạn

def WHILE(cond)
  return if not cond
  yield
end
i=0; begin; WHILE(i<3) {print i; i+=1}; raise; rescue; retry; end
kết quả

: 012 (cộng với in vòng lặp vô hạn rõ ràng không có gì)

Tôi hy vọng bạn đưa tôi ra khỏi sự nghi ngờ hiện hữu này, nhưng đây là kết luận của tôi.

Trước khi sử dụng bắt buộc khối bắt đầu /giải cứu cho từ khóa 'thử lại', nó có thể được sử dụng theo cách không thể thực hiện được nữa, lặp lại cuộc gọi của một phương thức bất chấp nằm trong phương thức đó .

Bây giờ, nó chỉ nhảy đến câu lệnh 'bắt đầu'.

Nhưng tôi không chắc về điều này và tôi cần xác nhận. Và nếu vậy, có bất kỳ hình thức nào để phục hồi loại sử dụng đó không?

Cảm ơn.

    
1
  1. "có bất kỳ hình thức nào để phục hồi loại sử dụng đó" Xin lỗi, không rõ: bạn muốn retry để làm gì?
    2019-05-08 16: 30: 26Z
  2. Xin lỗi, tôi chỉ tự hỏi liệu nó có thể được sử dụng để có được kết quả giống như trong ví dụ đầu tiên hay không, trước khi bị buộc phải ở trong "bắt đầu /giải cứu" khối. Đối với tôi, dường như có thể nhớ lại phương thức với một tham số được cập nhật.
    2019-05-08 16: 35: 10Z
  3. Ví dụ đầu tiên không hoạt động trong Ruby 2.6. Bạn gặp lỗi trên dòng 4: Thử lại không hợp lệ (SyntaxError)
    2019-05-08 16: 36: 11Z
  4. @ tadman Tôi biết, tôi thấy rằng nó đã bị buộc phải ở trong một khối cứu hộ trong Ruby 2.3.1 (trước đó, nó đã hoạt động)
    2019-05-08 16: 42: 25Z
1 Câu trả lời                              1                         

WHILE của bạn không hoạt động như while thông thường vì trong trường hợp của bạn, i<3 được đánh giá tại thời điểm cuộc gọi một lần . Câu lệnh while đánh giá nó mỗi lần.

Nếu bạn muốn viết một số tương đương while, điều quan trọng là điều kiện của bạn phải là thứ mà có thể được đánh giá, không phải là thứ được đã đánh giá.

Bạn có thể khắc phục điều đó bằng cách chấp nhận Proc như một điều kiện:

def so_long_as(cond)
  loop do
    return unless cond.call

    yield
  end
end

Sau đó, bạn gọi nó như thế này:

i = 0
so_long_as(-> { i < 3 }) do
  print i
  i += 1
end

Trường hợp hiện in 012 và chấm dứt hợp lệ.

Điều quan trọng cần lưu ý là retry chỉ hoạt động trong bối cảnh begin/end, không phải là một phương pháp thông thường, mà bây giờ bạn phải sử dụng redo thay thế:

i = 0
redone = false
so_long_as(-> { i < 3 }) do
  print i
  unless (redone)
    redone = true
    redo
  end
  i += 1
end

Nơi in 0012 ngay bây giờ.

Đã có một số thay đổi quan trọng đối với cách thức hoạt động của redoretry đáng để đọc lên.

    
3
2019-05-08 16: 41: 15Z
  1. Cảm ơn! Nó thực sự là giải thích. Vì vậy tôi có thể làmđại loại như thế này: def WHILE(cond) begin return if not cond.call yield raise rescue retry end end i=0; WHILE(-> {i<3}) {print i; i+=1} Tôi biết rằng điều này khá xấu và tốt hơn là sử dụng một vòng lặp thông thường, nhưng bây giờ tôi chắc chắn rằng mặc dù của tôi đã đi đúng hướng.
    2019-05-10 13: 23: 41Z
  2. Vì vậy, tham số của phương thức chỉ cần được "cập nhật" (hoặc đánh giá lại) để đánh giá tại câu lệnh return. Và từ khóa thử lại dường như làm điều đó trước 2.3.1.
    2019-05-10 13: 34: 51Z
  3. Bạn cần cái được gọi một cách lỏng lẻo là giá trị "động", một giá trị có thể được đánh giá nhiều lần để kiểm tra chống lại các điều kiện thay đổi. Một đóng cửa lambda (Proc) thực hiện công việc này độc đáo, do đó, đối số đầu tiên. Họ đã thay đổi cách retry hoạt động trong Ruby khá đột ngột. Tôi nghĩ rằng để tránh nó làm hai việc khác nhau và hơi mâu thuẫn tùy thuộc vào ngữ cảnh.
    2019-05-10 16: 34: 25Z
nguồn đặt đây