2014-04-06 21 views
5

Tôi đang cố gắng kết hợp các chức năng với các sàng lọc theo cách chung chung để chúng có thể được gọi mà không cần sàng lọc. Ví dụ, thay vì ARRAY-INITIAL size valueARRAY/INITIAL size valueLàm thế nào để bọc một chức năng với một sàng lọc để tinh lọc là không cần thiết?

wrap: function [refined [path!] args [block!]] [ 
    function args compose [ 
     (refined) (args) 
    ] 
] 

array-initial wrap 'array/initial [size value] 

Không quá lạ mắt. Dường như làm việc nói chung, nhưng điều này có cái gì lạ nếu bạn gọi nó là sử dụng một chức năng:

>> n: 0 array/initial 4 does [++ n] 
== [10 11 12 13] 

>> n: 10 array-initial 4 does [++ n] 
== [10 10 10 10] 

Khi tôi source nó tôi có được điều này:

>> source array-initial 
array-initial: make function! [[size value][array/initial size value]] 

Được rồi, vì vậy những gì đang xảy ra là chức năng đang được gọi là được gọi trong trình bao bọc và kết quả của cuộc gọi được thông qua ... không phải là chức năng. Một giải pháp khác là sử dụng một từ để tránh đánh giá:

>> array-initial-2: function [size value] [array/initial size :value] 

>> array-initial-2: 10 array-initial-2 4 does [++ n] 
[10 11 12 13] 

Nhưng tôi đang tìm cách tiếp cận chung. Cách tốt nhất để proxy các thông số mà không có điều này xảy ra là gì?

+0

@ endo64 Bạn [thêm một bản sao] (http://stackoverflow.com/revisions/22892499/3) ... đó là chức năng Rebol2. Trong Rebol3 quyết định đã được thực hiện để loại bỏ hình thức FUNCTION ... nó bây giờ những gì đã từng được gọi là FUNCT. Thân thiện với người dùng hơn theo cách đó (và tương thích với Red). Đề nghị của tôi là về cơ bản chúng tôi chỉ cố gắng rìu tất cả các FUNCTION sử dụng trong các mẫu mã Rebol2 và sau đó chuyển đổi tất cả FUNCT thành FUNCTION trong Rebol3. – HostileFork

+0

Ồ đúng, tôi quên điều đó. – endo64

Trả lời

1

Đây là một bài tập hấp dẫn, phải yêu SO.

Hóa ra bạn thực sự cần một "làm giảm" quấn chức năng với các đối số get-word ...

R3 chỉ vào lúc này:

unrefine: func [ 
    "Return an equivalent function with the given refinements wired in." 
    refined [any-path! block!] "The function, with the refinements to include." 
    /local ospec spec body found p s w b r 
] [ 
    ospec: spec-of get first refined: to lit-path! :refined 
    body: append copy spec: make block! length? ospec copy/deep [do reduce []] 
    append/only body/3 :refined 
    parse ospec [ 
    set s 0 1 string! (all [s append spec s]) 
    any [ 
     set w [word! | get-word! | lit-word!] (
     append spec :w 
     append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w]) 
     set b 0 1 block! (
     all [b append/only spec copy b]) 
     set s 0 1 string! (
     all [s append spec copy s]) 
    | 
     /local to end 
    | 
     set r refinement! (
     p: any [p tail spec] 
     if not found: find next refined r [append spec r]) 
     set s 0 1 string! (all [not found s append spec copy s]) 
     any [ 
     set w [word! | get-word! | lit-word!] (
      either found [p: insert p :w][append spec :w] 
      append body/3 either word! = type? :w [reduce ['quote to get-word! w]][w]) 
     set b 0 1 block! (
      all [b either found [p: insert/only p copy b][append/only spec copy b]]) 
     set s 0 1 string! (
      all [s either found [p: insert p copy s][append spec copy s]]) 
     ] 
    ] 
    ] 
    func spec body 
] 
+0

Đó là một ngụm! Nhưng chúng tôi sẽ đi với điều này như là câu trả lời cho bây giờ, trong mọi trường hợp. – HostileFork

1

Tôi tin rằng cách tiếp cận chung là bạn phải tính toán cách các từ được sử dụng trong các đối số hàm và được chuyển đến hàm.

wrap: func [ 
    'refined [path!] 
    args [block!] 
][ 
    func map-each arg args [ 
     either get-word? :arg [to word! arg] [:arg] 
    ] compose [ 
     (refined) (
      map-each arg args [ 
       either lit-word? :arg [to get-word! arg] [:arg] 
      ] 
     ) 
    ] 
] 

Có hai vấn đề ở đây — các từ xác định hàm và các từ được chuyển đến hàm. Bản cũ có hai dạng chính: từ! cho đối số bình thường và thắp sáng từ! cho các đối số theo nghĩa đen. Trong thông số kỹ thuật của chúng tôi, nếu chúng tôi có get-word! đối số, chúng tôi muốn chúng trở thành đối số bình thường và chuyển đổi thành từ!. Khi nói đến việc vượt qua các đối số, một lần nữa chúng tôi có hai hình thức: từ! để đánh giá đối số và get-word! để chuyển giá trị mà từ đó trỏ tới. Nếu thông số kỹ thuật của chúng tôi xử lý một từ thắp sáng!, chúng tôi cần chuyển một số từ get-word! dưới dạng từ! sẽ được chuyển theo nghĩa đen.

Hy vọng rằng tất cả đều có ý nghĩa!

Dù sao, làm thế nào điều này diễn ra là:

wrapped-foobar: wrap foo/bar ['literal evaluated :referred] 

Chúng tôi có ba loại của chúng ta, là người đầu tiên cho phép bạn để vượt qua những giá trị thông qua theo nghĩa đen-như lời mà không sử dụng thắp sáng-chữ; thứ hai đánh giá đối số trước khi đi qua; và thứ ba sẽ chuyển giá trị được giới thiệu — biểu mẫu này cho phép bạn chuyển qua các hàm. Bạn kết thúc với:

make function! [ 
    ['literal evaluated referred] [ 
     foo/bar :literal evaluated :referred 
    ] 
] 

Bây giờ thích của mảng/ban đầu là:

array-initial: wrap array/initial [size :value] 
n: 1 
array-initial 4 does [++ n] 
+0

Được rồi, tuyệt vời. Điều đó khắc phục lỗi mà ai đó hỏi tôi về GitHub. :-) Tôi cảm thấy đó là một mong muốn đủ phổ biến mà nó sẽ là tốt đẹp nếu phương ngữ đặc tả chức năng có thể cho phép bạn làm một số loại chuyên môn dễ dàng hơn. Tôi muốn làm điều này với sự phản chiếu nhưng có lẽ ai đó có thể thêm một câu trả lời khác để điều chỉnh nếu họ chán ... – HostileFork

+0

Người dùng GitHub, eh? – rgchris

+0

Hm ... một vấn đề ở đây là nguyên mẫu không khớp với chức năng được bao bọc. Vì vậy, ví dụ, wrapper có thể kết thúc với một arg trích dẫn khi bản gốc không có nó * (nó không phải '/ giá trị ban đầu' ... nhưng mảng-ban đầu được lấy' 'value') *. Có cách nào để làm cho dòng nguyên mẫu được bọc với bản gốc? – HostileFork

0

một cách đơn giản, bạn (aka tôi) không thể thực hiện điều này mà không phản ánh khối chức năng lập luận mà bạn đang gói. Không có cách nào khác.

Nếu một hàm sử dụng biểu mẫu từ ngữ hoặc dạng nhận từ của đối số, sự khác biệt đó phải được nhân đôi trong trình bao bọc của bạn. Xem câu trả lời này để giải thích về những gì là sự khác biệt giữa các hình thức :foo'foo của tham số:

Why doesn't Rebol 3 honor quoted function parameters that are parenthesized?

mỗi comment @ rgchris của, những gì bạn (còn gọi là I) cần phải làm là parse the argument block. Một câu trả lời đúng sẽ chứa mã thực hiện điều này, vì vậy mọi người nên cảm thấy tự do để thêm vào đó.

Các vấn đề liên quan