声明检查类型之间的通用Lisp差异

问题描述 投票:0回答:2

有人可以解释以下两种情况之间的区别(特别是对于我来说,如果我无法理解的话,这些评论是来自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
common-lisp declare
2个回答
1
投票

宏之间的区别check-type并输入check-type是前者不能被编译器忽略(并且,如果检查失败,可以互动地纠正输入),而后者只是提示编译器(更重要的是,对代码读者而言)编译器会忽略哪个may


0
投票

我正在尝试自己学习一些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

© www.soinside.com 2019 - 2024. All rights reserved.