|
> you need to box the variables (carry type information in addition to the value). Dealing with boxing/unboxing and trying to minimize boxing operations in computations is regularly done in Lisp compilers. > It is possible to introduce new variables in the global scope from a local scope just like in Lisp. Generally Javascript and Lisp have a lot in common. Scoping rules are different though and Lisp is not object-oriented at the core - but provides closures or adds object-oriented extensions like CLOS which are semi-optional. * (defun f ()
(setf a 5))
; in: DEFUN F
; (SETF A 5)
; ==>
; (SETQ A 5)
;
; caught WARNING:
; undefined variable: COMMON-LISP-USER::A
;
; compilation unit finished
; Undefined variable:
; A
; caught 1 WARNING condition
F
* (defun g ()
(print a))
; in: DEFUN G
; (PRINT A)
;
; caught WARNING:
; undefined variable: COMMON-LISP-USER::A
;
; compilation unit finished
; Undefined variable:
; A
; caught 1 WARNING condition
As you can see the compiler warns about undefined variables, but deals with it. * (if (> (random 1.0) 0.5) (f))
5
* (g)
5
5
If we remove the binding of A, then we get a runtime error. * (makunbound 'a)
A
* (g)
debugger invoked on a UNBOUND-VARIABLE in thread
#<THREAD "main thread" RUNNING {10005205B3}>:
The variable A is unbound.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE ] Retry using A.
1: [USE-VALUE ] Use specified value.
2: [STORE-VALUE] Set specified value and use it.
3: [ABORT ] Exit debugger, returning to top level.
(G)
source: (PRINT A)
0]
As one can see, both F and G are actually compiled machine code functions. Both functions we directly AOT compiled to machine code when I entered them at the prompt. * (disassemble #'f)
; disassembly for F
; Size: 38 bytes. Origin: #x226D3C9C
; 9C: 498B4540 MOV RAX, [R13+64] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; A0: 488945F8 MOV [RBP-8], RAX
; A4: 488B15A5FFFFFF MOV RDX, [RIP-91] ; 'A
; AB: BF0A000000 MOV EDI, 10
; B0: B904000000 MOV ECX, 4
; B5: FF7508 PUSH QWORD PTR [RBP+8]
; B8: B898914F22 MOV EAX, #x224F9198 ; #<FDEFN SET>
; BD: FFE0 JMP RAX
; BF: 0F0B0F BREAK 15 ; Invalid argument count trap
NIL
* (disassemble #'g)
; disassembly for G
; Size: 57 bytes. Origin: #x226D3D3C
; 3C: 498B4540 MOV RAX, [R13+64] ; no-arg-parsing entry point
; thread.binding-stack-pointer
; 40: 488945F8 MOV [RBP-8], RAX
; 44: 488B05A5FFFFFF MOV RAX, [RIP-91] ; 'A
; 4B: 8B50F5 MOV EDX, [RAX-11]
; 4E: 4A8B142A MOV RDX, [RDX+R13]
; 52: 83FA61 CMP EDX, 97
; 55: 480F4450F9 CMOVEQ RDX, [RAX-7]
; 5A: 83FA51 CMP EDX, 81
; 5D: 7412 JEQ L0
; 5F: B902000000 MOV ECX, 2
; 64: FF7508 PUSH QWORD PTR [RBP+8]
; 67: B838555422 MOV EAX, #x22545538 ; #<FDEFN PRINT>
; 6C: FFE0 JMP RAX
; 6E: 0F0B0F BREAK 15 ; Invalid argument count trap
; 71: L0: 0F0B17 BREAK 23 ; UNBOUND-SYMBOL-ERROR
; 74: 00 BYTE #X00 ; RAX
NIL
|