有人可以解释以下两种情况之间的区别(特别是对于我来说,如果我无法理解的话,这些评论是来自function的CLHS:
;; This function assumes its callers have checked the types of the
;; arguments, and authorizes the compiler to build in that assumption.
(defun discriminant (a b c)
(declare (number a b c))
"Compute the discriminant for a quadratic equation."
(- (* b b) (* 4 a c))) => DISCRIMINANT
(discriminant 1 2/3 -2) => 76/9
;; This function assumes its callers have not checked the types of the
;; arguments, and performs explicit type checks before making any assumptions.
(defun careful-discriminant (a b c)
"Compute the discriminant for a quadratic equation."
(check-type a number)
(check-type b number)
(check-type c number)
(locally (declare (number a b c))
(- (* b b) (* 4 a c)))) => CAREFUL-DISCRIMINANT
(careful-discriminant 1 2/3 -2) => 76/9
宏之间的区别check-type
并输入check-type
是前者不能被编译器忽略(并且,如果检查失败,可以互动地纠正输入),而后者只是提示编译器(更重要的是,对代码读者而言)编译器会忽略哪个may。
我正在尝试自己学习一些CL,所以我会提供最佳答案。与静态语言相比,Common Lisp是一种declarations。对于静态语言,请检查Haskell-它会进行大量编译时检查,以确保类型与所有函数匹配,并让您知道它是否失败。但是,在Common Lisp中,dynamic language。
但是,在Common Lisp中,变量的输入方式不是Java或C ++等语言。也就是说,您无需声明每个变量可以容纳的对象类型。相反,变量可以保留任何类型的值,并且这些值携带可以用于在运行时检查类型。因此,Common Lisp是动态的键入-类型错误是动态检测到的。例如,如果您通过除了+功能以外的数字,Common Lisp会表示类型错误。另一方面,Common Lisp是一个强大的从所有类型错误都会检测到-无法将对象视为类的实例并非如此。
因此,我们声明为函数自变量的变量默认没有类型。这对您可能是一个好读物:things are a little different。在第一段中,内容如下:
需要特别注意的是,在Lisp中,类型,而不是变量。任何变量都可以具有任何Lisp对象作为其变量值。 (可以明确声明变量实际上将仅采用一组有限的值之一。然而,这样的声明可能总是会被省略,程序仍然会正确运行。此类声明仅构成对提高效率可能有用的用户。参见声明。)
因此,每当您创建函数时,这些变量都可以使用任何Lisp对象作为其值。
如果我们在https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node15.html冒险,则会看到以下内容:
声明有两种不同的用法,一种是声明Lisp变量为“特殊”(这会影响适当的语义变量的绑定),另一种是提供建议以帮助Common Lisp系统(实际上是编译器)运行您的Lisp代码更快,或具有更复杂的调试选项。
在这种情况下,我们向Common Lisp系统提供有关类型和类型检查的建议。让我们看看您提供的两个示例函数。
首先,“判别式”函数使用声明函数来断言参数确实是数字,并且编译器不需要检查它们。小心区分函数使用声明来确保每个变量确实是一个数字,然后执行该操作。
您可能会问“我为什么要麻烦它?”,答案是提供更优化的功能(判别式)或提供更好的调试功能以及更多有关错误的信息(谨慎判别)。为了显示差异,我启动了SBCL并定义了两个函数。然后,我使用反汇编来显示每个的机器代码。注意区别对待比区别对待执行更多的检查,从而导致更多的机器代码!
(反汇编#'判别式)
declare
(反汇编#'care-discriminant)
; disassembly for DISCRIMINANT
; Size: 83 bytes. Origin: #x10023700D7 ; DISCRIMINANT
; 0D7: 498B5D10 MOV RBX, [R13+16] ; thread.binding-stack-pointer
; 0DB: 48895DF8 MOV [RBP-8], RBX
; 0DF: 840425F8FF1020 TEST AL, [#x2010FFF8] ; safepoint
; 0E6: 488B55E8 MOV RDX, [RBP-24]
; 0EA: 488B7DE8 MOV RDI, [RBP-24]
; 0EE: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 0F5: 488955D8 MOV [RBP-40], RDX
; 0F9: 488B55F0 MOV RDX, [RBP-16]
; 0FD: BF08000000 MOV EDI, 8
; 102: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 109: 488B7DE0 MOV RDI, [RBP-32]
; 10D: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 114: 488BFA MOV RDI, RDX
; 117: 488B55D8 MOV RDX, [RBP-40]
; 11B: FF1425B8000020 CALL QWORD PTR [#x200000B8] ; GENERIC--
; 122: 488BE5 MOV RSP, RBP
; 125: F8 CLC
; 126: 5D POP RBP
; 127: C3 RET
; 128: CC10 INT3 16 ; Invalid argument count trap
NIL
如此处所示,Common Lisp也可以被编译,这使某些人感到困惑。最好在这里回答:; disassembly for CAREFUL-DISCRIMINANT
; Size: 422 bytes. Origin: #x10023701E3 ; CAREFUL-DISCRIMINANT
; 1E3: 4D8B4510 MOV R8, [R13+16] ; thread.binding-stack-pointer
; 1E7: 4C8945F8 MOV [RBP-8], R8
; 1EB: 840425F8FF1020 TEST AL, [#x2010FFF8] ; safepoint
; 1F2: EB44 JMP L1
; 1F4: 660F1F840000000000 NOP
; 1FD: 0F1F00 NOP
; 200: L0: 488B7DF0 MOV RDI, [RBP-16]
; 204: 4883EC10 SUB RSP, 16
; 208: 488B1571FFFFFF MOV RDX, [RIP-143] ; 'A
; 20F: 488B3572FFFFFF MOV RSI, [RIP-142] ; 'NUMBER
; 216: 4C894DD8 MOV [RBP-40], R9
; 21A: 488B056FFFFFFF MOV RAX, [RIP-145] ; #<SB-KERNEL:FDEFN SB-KERNEL:CHECK-TYPE-ERROR>
; 221: B906000000 MOV ECX, 6
; 226: 48892C24 MOV [RSP], RBP
; 22A: 488BEC MOV RBP, RSP
; 22D: FF5009 CALL QWORD PTR [RAX+9]
; 230: 4C8B4DD8 MOV R9, [RBP-40]
; 234: 488955F0 MOV [RBP-16], RDX
; 238: L1: 840425F8FF1020 TEST AL, [#x2010FFF8] ; safepoint
; 23F: 488B45F0 MOV RAX, [RBP-16]
; 243: 448D40F1 LEA R8D, [RAX-15]
; 247: 41F6C001 TEST R8B, 1
; 24B: 7512 JNE L2
; 24D: 4180F80A CMP R8B, 10
; 251: 740C JEQ L2
; 253: 41F6C00F TEST R8B, 15
; 257: 75A7 JNE L0
; 259: 8078F129 CMP BYTE PTR [RAX-15], 41
; 25D: 77A1 JNBE L0
; 25F: L2: EB47 JMP L4
; 261: 660F1F840000000000 NOP
; 26A: 660F1F440000 NOP
; 270: L3: 488B7DE8 MOV RDI, [RBP-24]
; 274: 4883EC10 SUB RSP, 16
; 278: 488B1519FFFFFF MOV RDX, [RIP-231] ; 'B
; 27F: 488B3502FFFFFF MOV RSI, [RIP-254] ; 'NUMBER
; 286: 4C894DD8 MOV [RBP-40], R9
; 28A: 488B05FFFEFFFF MOV RAX, [RIP-257] ; #<SB-KERNEL:FDEFN SB-KERNEL:CHECK-TYPE-ERROR>
; 291: B906000000 MOV ECX, 6
; 296: 48892C24 MOV [RSP], RBP
; 29A: 488BEC MOV RBP, RSP
; 29D: FF5009 CALL QWORD PTR [RAX+9]
; 2A0: 4C8B4DD8 MOV R9, [RBP-40]
; 2A4: 488955E8 MOV [RBP-24], RDX
; 2A8: L4: 840425F8FF1020 TEST AL, [#x2010FFF8] ; safepoint
; 2AF: 488B45E8 MOV RAX, [RBP-24]
; 2B3: 448D40F1 LEA R8D, [RAX-15]
; 2B7: 41F6C001 TEST R8B, 1
; 2BB: 7512 JNE L5
; 2BD: 4180F80A CMP R8B, 10
; 2C1: 740C JEQ L5
; 2C3: 41F6C00F TEST R8B, 15
; 2C7: 75A7 JNE L3
; 2C9: 8078F129 CMP BYTE PTR [RAX-15], 41
; 2CD: 77A1 JNBE L3
; 2CF: L5: EB3D JMP L7
; 2D1: 660F1F840000000000 NOP
; 2DA: 660F1F440000 NOP
; 2E0: L6: 498BF9 MOV RDI, R9
; 2E3: 4883EC10 SUB RSP, 16
; 2E7: 488B15B2FEFFFF MOV RDX, [RIP-334] ; 'C
; 2EE: 488B3593FEFFFF MOV RSI, [RIP-365] ; 'NUMBER
; 2F5: 488B0594FEFFFF MOV RAX, [RIP-364] ; #<SB-KERNEL:FDEFN SB-KERNEL:CHECK-TYPE-ERROR>
; 2FC: B906000000 MOV ECX, 6
; 301: 48892C24 MOV [RSP], RBP
; 305: 488BEC MOV RBP, RSP
; 308: FF5009 CALL QWORD PTR [RAX+9]
; 30B: 4C8BCA MOV R9, RDX
; 30E: L7: 840425F8FF1020 TEST AL, [#x2010FFF8] ; safepoint
; 315: 458D41F1 LEA R8D, [R9-15]
; 319: 41F6C001 TEST R8B, 1
; 31D: 7513 JNE L8
; 31F: 4180F80A CMP R8B, 10
; 323: 740D JEQ L8
; 325: 41F6C00F TEST R8B, 15
; 329: 75B5 JNE L6
; 32B: 418079F129 CMP BYTE PTR [R9-15], 41
; 330: 77AE JNBE L6
; 332: L8: 4C894DD8 MOV [RBP-40], R9
; 336: 488B55E8 MOV RDX, [RBP-24]
; 33A: 488B7DE8 MOV RDI, [RBP-24]
; 33E: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 345: 488955E0 MOV [RBP-32], RDX
; 349: 4C8B4DD8 MOV R9, [RBP-40]
; 34D: 488B55F0 MOV RDX, [RBP-16]
; 351: BF08000000 MOV EDI, 8
; 356: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 35D: 4C8B4DD8 MOV R9, [RBP-40]
; 361: 498BF9 MOV RDI, R9
; 364: FF1425C0000020 CALL QWORD PTR [#x200000C0] ; GENERIC-*
; 36B: 488BFA MOV RDI, RDX
; 36E: 4C8B4DD8 MOV R9, [RBP-40]
; 372: 488B55E0 MOV RDX, [RBP-32]
; 376: FF1425B8000020 CALL QWORD PTR [#x200000B8] ; GENERIC--
; 37D: 4C8B4DD8 MOV R9, [RBP-40]
; 381: 488BE5 MOV RSP, RBP
; 384: F8 CLC
; 385: 5D POP RBP
; 386: C3 RET
; 387: CC10 INT3 16 ; Invalid argument count trap
NIL
。