Thay thế chuỗi bằng .subst trong một vòng lặp for


8

Tôi muốn thực hiện thay thế chuỗi trong một forkhối bằng cách sử dụng một bản chụp có tên. Tôi đã dự kiến ​​sẽ lấy các số 1,2,3 làm đầu ra. Nhưng nó là Nilcho lần chạy đầu tiên, và sau đó là 1 và 2 cho lần chạy thứ 2 và thứ 3. Làm thế nào để tôi sử dụng .substchính xác trong cấu trúc vòng lặp? Tôi thấy hành vi tương tự khi sử dụng một mapcấu trúc thay vì forvòng lặp. Nó hoạt động như mong đợi, nếu tôi thay thế bằng một giá trị chuỗi cố định.

for <a1 b2 c3> -> $var {
    say $var;
    say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK      
}

#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11   
Output:

a1
Use of Nil in string context
  in block  at test3.pl6 line 3

b2
1
c3
2
]

Tôi tò mò. $ <Nr> là gì? (Tôi không thể tìm thấy nó trong tài liệu raku.)
p6steve


docs.raku.org/lingu/ từ - cảm ơn @valle - đã tìm thấy nó ngay bây giờ!
p6steve

Có lẽ nên cân nhắc sử dụng S///đôi khi. Trong trường hợp này bạn có thể làmS[.$<nr>=(\d)] = $<nr> given $var
Jo King

@JoKing Đẹp. Tôi đã nâng cao nhận xét của bạn, sau đó hủy bỏ upvote vì tôi nhận ra rằng tôi muốn kiểm tra một cái gì đó (hóa ra không quan trọng), và bây giờ SO sẽ không cho phép tôi phục hồi upvote của mình. Vì vậy, tôi đang viết điều này để thủ công +1 đề xuất tốt đẹp của bạn. Tôi cũng đã tích hợp nó vào câu trả lời của mình.
raiph

Câu trả lời:


9

Đánh giá TL; DR Defer $<nr>cho đến sau khi đánh giá regex. @ JoKing ++ gợi ý một cách . Một cách khác là chỉ bọc thay thế bằng niềng răng ( {$<nr>}).

Điều gì xảy ra khi mã gốc của bạn gọi subst

Trước khi Raku cố gắng gọi substthói quen, nó tập hợp một danh sách các đối số để truyền cho nó.

Có hai giá trị. Đầu tiên là một regex. không chạy . Giá trị thứ hai là $<nr>. Nó ước tính Nilbởi vì, khi bắt đầu một chương trình, biến đối tượng khớp hiện tại bị ràng buộc với thứ gì đó tuyên bố giá trị của nó Nilvà mọi nỗ lực truy cập giá trị của khóa trong nó - $<nr>- cũng trả về Nil. Vì vậy, mọi thứ đã đi sai vào thời điểm này, trước khi substchạy.

Khi Raku đã tập hợp danh sách các đối số này, nó sẽ cố gắng gọi subst. Nó thành công, và substchạy.

Để có được trận đấu tiếp theo, hãy substchạy regex. Điều này cập nhật biến đối tượng phù hợp hiện tại $/. Nhưng đã quá muộn để tạo ra bất kỳ sự khác biệt nào đối với giá trị thay thế đã được chuyển qua subst.

Với trận đấu trong tay, substtiếp theo xem xét đối số thay thế. Nó tìm thấy nó Nilvà hành động phù hợp.

Đối với cuộc gọi thứ hai của subst, $<nr>đã lấy giá trị từ cuộc gọi đầu tiên của subst. Và như thế.

Hai cách để trì hoãn đánh giá $<nr>

@JoKing đề nghị xem xét sử dụng S///. Cấu trúc này đánh giá regex (giữa cặp /s đầu tiên) trước, sau đó thay thế (giữa cặp /s cuối cùng ). (Nguyên tắc tương tự được áp dụng nếu bạn sử dụng các Scú pháp hợp lệ khác như S[...] = ....)

Nếu bạn sử dụng subst, như đã giải thích trong phần trước, Raku sẽ tập hợp danh sách đối số cho nó trước khi gọi nó. Nó tìm thấy một regex (cái mà nó không chạy) và một cái đóng (cái mà nó cũng không chạy). Sau đó, nó cố gắng gọi substvới những đối số đó và thành công trong việc làm như vậy.

Tiếp theo, substbắt đầu chạy. Nó đã nhận được mã cho cả trận đấu (regex) và thay thế (đóng cửa).

Nó chạy regex như hoạt động phù hợp. Nếu regex trả về một kết quả khớp thì substchạy bao đóng và sử dụng giá trị mà nó trả về làm thay thế.

Do đó, vì chúng tôi đã chuyển từ chuyển $<nr>thành giá trị trần, có nghĩa là nó bị đóng băng Nil, chuyển sang đóng gói, trong đó hoãn lại đánh giá của nó cho đến khi $/được đặt thành khớp với <nr>mục nhập dân cư , chúng tôi đã giải quyết vấn đề.

Lưu ý rằng điều này chỉ hoạt động bởi vì bất kỳ ai được thiết kế / triển khai substđều thông minh / đủ tốt để cho phép cả đối số đối sánh đối số là dạng Code(một biểu thức chính thức cho kết quả khớp và đóng thông thường để thay thế) nếu người dùng muốn điều đó. Sau đó, nó chạy trận đấu trước và chỉ sau đó chạy kết thúc thay thế nếu nó được thông qua, sử dụng kết quả của cuộc gọi sau đó làm thay thế cuối cùng. Tương tự, S///hoạt động vì điều đó đã được thiết kế để chỉ đánh giá sự thay thế sau lần đầu tiên nó đánh giá sự thay thế.

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.