我是计划新手,并试图了解创建过程时$('li[data-id=45][data-ud=322 ]');
的工作原理。更确切地说,以下两个声明之间的区别是:
define
有人可以提示(define name (procedure))
(define (name) (procedure))
如何在引擎盖下工作吗?我知道在第一种情况下define
创建一个指向过程的指针。第二个是没有参数define
的过程的修剪版本,但指针(define (name arg) (procedure))
和name
如何相互不同?
显然,(name)
的使用取决于它的定义方式。
name
谢谢!
答案 0 :(得分:3)
define
形式是'语法糖':它只是一种更方便的语法。表达式
(define (foo x)
(+ x 1))
根据定义等同于
(define foo
(lambda (x)
(+ x 1)))
也就是说,正如(define bar 1)
设置bar
等于值 1
,(define foo (lambda ...))
将foo
定义为等于值 (lambda (x) (+ x 1))
,这是一个过程(即函数),它在其单个参数中加1。
啊哈!这里的时刻意识到在Scheme(和其他Lisps)中,一个过程是一个值,其状态与1
或"hello"
相同,因此可以分配给符号等为foo
。
表达式(lambda ...)
计算为过程类型的值。
直截了当,语法(define (foo ...) ...)
应该是透明的。
(并没有想到'功能指针' - 这是一个C概念,只会混淆这里的事情。)
答案 1 :(得分:3)
这些都不是任何方式,形状或形式的指针。
define
将名称绑定到当前环境中的值,而在Scheme中,过程是第一类值。
(define name (procedure))
将name
定义为现在调用procedure
的结果的值。
(define (name) (procedure))
将name
定义为不带参数的过程,并在调用时返回不带参数调用procedure
的结果。
第二种形式相当于
(define name (lambda () (procedure)))
示例(来自球拍 - current-seconds
是自UTC时间1970年1月1日午夜起的秒数):
> (current-seconds)
1462879945
> (define name (current-seconds))
> name
1462879957
name
是一个数字,而不是一个程序。
> (define (nameproc) (current-seconds))
> nameproc
#<procedure:nameproc>
nameproc
是一个程序,而不是数字。
> (nameproc)
1462879980
> (nameproc)
1462879983
正如您所看到的,nameproc
每次被调用时都会返回不同的值...
> name
1462879957
> name
1462879957
...但name
是一个整数且不会改变。
答案 2 :(得分:2)
(define (proc) ...)
只是(define proc (lambda () ...))
的语法糖。
如果您熟悉命令式语言,define
实际上是一种分配:
> (define proc 2)
&LT; =&GT; (ISH)
proc = 2;
您可以分配给符号的一件事是功能,如下所示:
> (define proc (lambda (x y) (+ x y)))
> (proc 1 2)
3
&LT; =&GT; (ISH)
>>> proc = lambda x, y: x + y
>>> proc(1, 2)
3
现在没有什么可以阻止你定义不带参数的函数:
> (define proc (lambda () (+ 1 1)))
> (proc)
2
指定proc
函数不带参数,并返回(+ 1 1)
的值(即2)。这与<{1}}的不同,它直接将值分配给(define proc (+ 1 1))
(实际上完全等同于proc
)。
现在,可能让您感到困惑的是,由于编写(define proc 2)
的工作量太大,因此Scheme实现通常会提供函数定义的“简写”版本:
lambda
所以> (define (proc <args>) <body>)
<=>
> (define proc (lambda <args> <body>))
去了(define (proc) 2)
,而(define proc (lambda () 2))
只是将(define proc 2)
分配到2
。符号可能通过指针绑定到值的事实是一个实现细节,只涉及您的解释器,并且应该与推理无关。
proc
创建一个函数
(define (func) x)
将(define func x)
分配给x
答案 3 :(得分:0)
define
可能是Scheme中最模糊的特殊形式,因为它在不同的范围和不同的第一个参数中用于不同的目的。这是:
符号与列表第一个参数之间的差异
define
的基本用法是:
(define var <expression>)
它使用表达式var
的结果定义变量<expression>
。
由于Scheme是一个LISP1程序(在其他一些语言中也称为函数)是用一个评估的lambda形式创建的,例如。 (lambda argument-list . body)
您可以通过为define
(define add1 (lambda (n) (+ 1 n)))
对于命名程序,define
有一种特殊的语法,其中define
和lambda
表单被混合在一起。您可以将add1
写为:
(define (add1 n) (+ 1 n))
这意味着完全一样,有些书籍不会将这最后一个版本暴露给用户,因为有两种方法可以解决这个问题,特别是如果你想要一个过程来返回一个过程。
顶级或词汇范围
当顶级值分配给全局范围时。这意味着所有程序都可以访问它,除非在本地范围内重新定义变量,查看使用中的代码和最高级别的代码。
如果define
发生在程序的过程或语法糖中(let
,let*
,letrec
,rec
,{{1}然后,表单与过程顶部的lambda
相同,它只存在于该过程和嵌套过程中。第二个letrec中的代码完成运行绑定消失:
letrec
这与:
相同(define (test n)
(define v (* 2 n))
(define (add1 n) (+ 1 n))
(add1 v))
letrec只是一个花哨的(define test
(lambda (n)
(letrec ((v (* 2 n))
(add1 (lambda (n) (+ 1 n)))
(add1 v))))
let
当然(define test
(lambda (n)
(let ((v 'undefined) (add1 'undefined))
(let ((v1 (* 2 n))
(v2 (lambda (n) (+ 1 n))))
(set! v v1)
(set! add1 v2))
(add1 v))))
只是一个let
,会立即应用:
lambda
(define test
(lambda (n)
((lambda (v add1)
((lambda (v1 v2)
(set! v v1)
(set! add1 v2)) (* 2 n) (lambda (n) (+ 1 n)))
(add1 v) ; can access n, v, and add1 but not v1, and v2
'undefined 'undefined)))
仅在名称和值之间进行绑定,其中值通常表示对象的地址(也称为指针)。相同的名称可以在不同的范围内具有不同的绑定,因此相同的变量名称并不总是指向同一个对象。这是一个例子:
define
此处,顶级(define lst '(1 2 3 4 5))
(define (last x)
(define lst (cdr x))
(if (null? lst)
(car lst)
(last lst)))
(last lst) ; ==> 5
始终为lst
,而过程中的'(1 2 3 4 5)
始终是参数lst
的子列表之一。它们同时存在,但名称相同但都指向不同的值。在正文中,全局不可访问,因为它被具有相同名称的本地绑定所遮蔽。