2013-02-18 29 views
5

Vì vậy, tôi biết rằng trong Đề án xác định là dành cho Phạm vi năng động và để cho Phạm vi tĩnh, tuy nhiên điều sau confuses me:Scheme phạm trù (xác định và để cho)

Nếu tôi có

(let ((x 0)) 
    (define f (lambda() x)) 
    (display (f)) 
    (let ((x 1)) 
    (display (f)) 
    ) 
) 

Nó sẽ hiển thị 00. Cho đến nay rất tốt. Tuy nhiên, nếu tôi thêm xác định bổ sung cho x như vậy:

(let ((x 0)) 
    (define f (lambda() x)) 
    (display (f)) 
    (define x 4) 
    (let ((x 1)) 
    (display (f)) 
    ) 
) 

Nó sẽ hiển thị undefined4. Tại sao điều này? Tại sao xác định x sau khi đánh giá f ảnh hưởng đến giá trị trả lại của (f)? Và tại sao giá trị trả về "không xác định"?

Nó cũng đáng nói đến là ràng buộc f với letrec thay vì xác định cũng sẽ làm việc:

(let ((x 0)) 
    (letrec ((f (lambda() x))) 
    (display (f)) 
    (define x 4) 
    (let ((x 1)) 
    (display (f)) 
    ) 
) 
) 

Returns 00.

Lưu ý: Tôi đã sử dụng DrRacket với languge đặt trên "Pretty Big"

+2

Ý anh là gì bởi "xác định được cho Phạm vi năng động trong Đề án"? BTW, trừ khi bạn được yêu cầu sử dụng nó cho một khóa học, "Pretty Big" là một phương ngữ lỗi thời. – Rhangaun

+3

Đề án luôn sử dụng phạm vi tĩnh, không chính xác để nói rằng "xác định là động và để cho phạm vi tĩnh" –

+0

Tôi đồng ý với Oscar: tiền đề trong câu hỏi là sai hoặc đang sử dụng sai cụm từ. – dyoo

Trả lời

0

Trường hợp 1: phần thân của f liên kết với phần ngoài cùng cho phép trong cả hai lần gọi, dẫn đến 00 là phạm vi tĩnh yêu cầu.

Trường hợp 2: Tôi không chắc chắn về điều này, nhưng nội bộ (define x 4) đổ bóng tối đa bên ngoài x = 0 ràng buộc, và nằm trong phạm vi mặc dù nó là văn bản sau cuộc gọi đến f. Sau đó, một số thứ tự của đánh giá trickiness làm cho cuộc gọi đầu tiên xảy ra trước khi ràng buộc x mới được khởi tạo đầy đủ, do đó, nó "uninitialized". Cuộc gọi thứ hai ở bên trong cho phép xảy ra sau khi mọi thứ được khởi tạo, vì vậy 4.

Trường hợp 3: Bây giờ chúng ta đã đặt rõ ràng letrec và xác định trong phạm vi riêng biệt, f rõ ràng là tham chiếu đến ngoài cùng. Định nghĩa không có gì ở đây.

5

Vấn đề bạn gặp phải trong trường hợp thứ hai là (define x 42) làm cho x biến cho phạm vi toàn bộ số được xác định. Bây giờ, mặc dù biến số được xác định cho toàn bộ phạm vi, giá trị của nó không được xác định cho đến khi dòng (define x 42) thực tế.

(let() 
    ;; up here, `x` is defined but has an undefined value 
    ;; ... 
    (define x 42) 
    ;; down here `x` has the value 42 
    ;; ... 
) 

Nó đóng vai trò như thế này:

(let ([x 'undefined]) 
    ;; ... up here, `x` is 'undefined 
    (set! x 42) 
    ;; ... down here, `x` is 42 
) 
+0

Bun ở đâu đi 'let ((x 0))' ở trên cùng? – Necto

1

thứ hai và thứ ba đoạn mã của bạn không Scheme (không ai trong số R5RS, R6RS cũng không R7RS). Các <body> (của một let và những người khác) được định nghĩa là:

<body> -> <definition>* <sequence> 
<sequence> -> <command>* <expression> 
<command> -> <expression> 

và do đó một define (mà là một <definition>) không thể theo display (một <expression>). Bạn có khả năng nhận được kết quả khó hiểu vì trình biên dịch/thông dịch viên đang xử lý không chính xác việc mở rộng 'let'.

Đây là những gì một 'tốt' R6RS trình biên dịch hiện:

> (let ((x 0)) 
    (letrec ((f (lambda() x))) 
    (display (f)) 
    (define x 4) 
    (let ((x 1)) 
    (display (f)) 
    ) 
) 
) 
Unhandled exception 
Condition components: 
    1. &who: define 
    2. &message: "a definition was found where an expression was expected" 
    3. &syntax: 
     form: (define x 4) 
     subform: #f 
    4. &trace: #<syntax (define x 4)> 
> 
+0

Trình biên dịch nào bạn sử dụng? – Necto

+0

Ikarus (http://en.wikipedia.org/wiki/Ikarus_(Scheme_implementation)) – GoZoner