无法在 Racket 中使用 let
Not able to use let in Racket
我正在尝试修改 http://home.adelphi.edu/~siegfried/cs270/270rl10.html 上的排序代码,其中我使用 let 作为插入函数:
(define (mysort alon )
(let insert ((n n) (alon alon))
(cond
[(empty? alon) (cons n empty)]
[else (cond
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert n (rest alon))])])
(cond
[(empty? alon) empty]
[(cons? alon) (insert (first alon)
(mysort (rest alon)))])))
(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
但是,它在 'let' 变量声明级别不起作用:
n: unbound identifier in module in: n
我在这里 (https://docs.racket-lang.org/reference/let.html) 看到 'let' 需要有变量的初始值。我们可以在不初始化变量的情况下使用 'let' 吗?如何更正以上代码?
编辑:我尝试使用 lambda 但它不起作用:
(define (mysort4 alon )
(let ([insert4
(lambda (n alon)
(cond
[(empty? alon) (cons n empty)]
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert4 n (rest alon) ))]))])
(cond
[(empty? alon) empty]
[(cons? alon) (insert4 (first alon)
(mysort4 (rest alon) ) )])))
(mysort4 (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
错误是:
insert4: unbound identifier in module in: insert4
当您需要内部辅助函数时,请使用内部定义而不是 let
。
通过最小的更改(使用 define
而不是 let
),您将获得:
#lang racket
(define (mysort alon )
(define (insert n alon)
(cond
[(empty? alon) (cons n empty)]
[else (cond
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert n (rest alon)))])]))
(cond
[(empty? alon) empty]
[(cons? alon) (insert (first alon)
(mysort (rest alon)))]))
(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
当您使用 let
创建内容时
(define test 10)
(let ((test (lambda (x)
(list x test))))
(test 'result))
; ==> (result 10)
显然 lambda 内部的 test
是全局的而不是 "itself",但为什么。 let
只是立即调用的匿名函数的语法糖,因此我们可以将其重写为:
(define test 10)
((lambda (test)
(test 'result))
(lambda (x)
(list x test)))
在这里您看到第一个 lambda 具有 test
作为绑定变量,因此始终是第一个操作数,但第二个 lambda 没有 test
除了全局绑定。
在递归过程中不能使用 let
,因为在创建闭包时绑定不在环境中(计算 lambda)。为了解决这个问题,我们使用 letrec
解决了这个问题:
(define test 10)
(letrec ((test (lambda (x)
(list x test))))
(test 'result))
; ==> (result #<procedure:test>)
要看为什么可以展开这个表格看看:
(let ((test 'undefined))
(let ((newtemp (lambda (x) (list x test))))
(set! test newtemp))
(test 'result))))
; ==> (result #<procedure:test>)
我不会在这里展开 let
形式,但请注意在创建 lambda 时 test
存在的事实。 lambda 成为值,但绑定是相同的。
不是顶层的 define
被重写*为 letrec
因此下面的代码完全相同:
(let () ; this is to make `define` local and not global
(define test (lambda (x)
(list x test))
(test 10))
; ==> (result #<procedure:test>)
在命名的 let
中,名称绑定在 letrec
中,但其他值不是。要修复第一个:
(define (mysort alon)
(cond
[(empty? alon) empty]
[(cons? alon)
(let insert ((n (first alon))
(alon (rest alon)))
(cond
[(empty? alon) (cons n empty)]
[(< n (first alon)) (cons n alon)]
[else (cons (first alon) (insert n (rest alon)))]))]))
请注意,我将嵌套的 cond
展平,因为 cond
的重点是不必嵌套它们。它等同于其他语言中的 if-elseif*-else
。该代码不起作用,因为它只放置了第一个元素。也许将所有元素插入一个以空列表开头的列表中是可行的。
第二个只需将 let
更改为 letrec
即可。该代码与相同的功能相同,它只根据其余部分插入第一个元素,但递归将适用于该元素。
如果您查看链接到的页面,您会发现您 insert
进入的列表已经排序。 IE。你在那里错过了一些东西..
insertion-sort
不是一种有效的算法。 #lang racket
对较小的列表使用合并排序和调整。试图在速度上击败它是徒劳的。
*
反之亦然。球拍使用letrec
(准确地说是letrec-values
)
我正在尝试修改 http://home.adelphi.edu/~siegfried/cs270/270rl10.html 上的排序代码,其中我使用 let 作为插入函数:
(define (mysort alon )
(let insert ((n n) (alon alon))
(cond
[(empty? alon) (cons n empty)]
[else (cond
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert n (rest alon))])])
(cond
[(empty? alon) empty]
[(cons? alon) (insert (first alon)
(mysort (rest alon)))])))
(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
但是,它在 'let' 变量声明级别不起作用:
n: unbound identifier in module in: n
我在这里 (https://docs.racket-lang.org/reference/let.html) 看到 'let' 需要有变量的初始值。我们可以在不初始化变量的情况下使用 'let' 吗?如何更正以上代码?
编辑:我尝试使用 lambda 但它不起作用:
(define (mysort4 alon )
(let ([insert4
(lambda (n alon)
(cond
[(empty? alon) (cons n empty)]
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert4 n (rest alon) ))]))])
(cond
[(empty? alon) empty]
[(cons? alon) (insert4 (first alon)
(mysort4 (rest alon) ) )])))
(mysort4 (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
错误是:
insert4: unbound identifier in module in: insert4
当您需要内部辅助函数时,请使用内部定义而不是 let
。
通过最小的更改(使用 define
而不是 let
),您将获得:
#lang racket
(define (mysort alon )
(define (insert n alon)
(cond
[(empty? alon) (cons n empty)]
[else (cond
[(< n (first alon)) (cons n alon)]
[else (cons (first alon)
(insert n (rest alon)))])]))
(cond
[(empty? alon) empty]
[(cons? alon) (insert (first alon)
(mysort (rest alon)))]))
(mysort (list 1 2 3 4 5 6 2 3 1 4 5 2 10))
当您使用 let
(define test 10)
(let ((test (lambda (x)
(list x test))))
(test 'result))
; ==> (result 10)
显然 lambda 内部的 test
是全局的而不是 "itself",但为什么。 let
只是立即调用的匿名函数的语法糖,因此我们可以将其重写为:
(define test 10)
((lambda (test)
(test 'result))
(lambda (x)
(list x test)))
在这里您看到第一个 lambda 具有 test
作为绑定变量,因此始终是第一个操作数,但第二个 lambda 没有 test
除了全局绑定。
在递归过程中不能使用 let
,因为在创建闭包时绑定不在环境中(计算 lambda)。为了解决这个问题,我们使用 letrec
解决了这个问题:
(define test 10)
(letrec ((test (lambda (x)
(list x test))))
(test 'result))
; ==> (result #<procedure:test>)
要看为什么可以展开这个表格看看:
(let ((test 'undefined))
(let ((newtemp (lambda (x) (list x test))))
(set! test newtemp))
(test 'result))))
; ==> (result #<procedure:test>)
我不会在这里展开 let
形式,但请注意在创建 lambda 时 test
存在的事实。 lambda 成为值,但绑定是相同的。
define
被重写*为 letrec
因此下面的代码完全相同:
(let () ; this is to make `define` local and not global
(define test (lambda (x)
(list x test))
(test 10))
; ==> (result #<procedure:test>)
在命名的 let
中,名称绑定在 letrec
中,但其他值不是。要修复第一个:
(define (mysort alon)
(cond
[(empty? alon) empty]
[(cons? alon)
(let insert ((n (first alon))
(alon (rest alon)))
(cond
[(empty? alon) (cons n empty)]
[(< n (first alon)) (cons n alon)]
[else (cons (first alon) (insert n (rest alon)))]))]))
请注意,我将嵌套的 cond
展平,因为 cond
的重点是不必嵌套它们。它等同于其他语言中的 if-elseif*-else
。该代码不起作用,因为它只放置了第一个元素。也许将所有元素插入一个以空列表开头的列表中是可行的。
第二个只需将 let
更改为 letrec
即可。该代码与相同的功能相同,它只根据其余部分插入第一个元素,但递归将适用于该元素。
如果您查看链接到的页面,您会发现您 insert
进入的列表已经排序。 IE。你在那里错过了一些东西..
insertion-sort
不是一种有效的算法。 #lang racket
对较小的列表使用合并排序和调整。试图在速度上击败它是徒劳的。
*
反之亦然。球拍使用letrec
(准确地说是letrec-values
)