Would love to see something on set/setq/setf, when to use each and maybe when to use those vs when to use what you covered in this video! Forever grateful for your helpful videos. If I ever learn enough, I'll pass the torch however I can.
One interesting use case for dynamic variables is this: Locally overwriting dynamic variables provides some amount of control over how (e.g. builtin) functions that use those variables work. For example one could lexically overwrite /*print-base*/ and thus change how print works (see the spec on /*print-base*/ for examples). This is actually feels a bit like creational OOP patterns (like factory method): To change a system, change a specific component of the system.
one could argue that the earmuffs convention was created because Lisp is case insensitive. differentiating between FOO, Foo, and foo becomes impossible but +foo+, *foo*, and foo are now distinct
Nice explanation about the subject. I would just like to add that if you could show some more realistic use cases for a feature you are teaching, it would be even more interesting. That said, I know it is not always easy (or even possible) to be didactic and still show "real" case examples for everything. Keep up the superb work!
Spot on comment. I'm not sure how to do that with adding addition knowledge dependencies though. Currently this video requires 'evaluation basics' & 'equality' and really because of in-package it should have one on packages but I haven't made that video yet. Ideally I'd like for some lovely person to make a site which has a big ol' graph that showing the interconnections so folks can take their own path whilst also understanding how things relate... thats all long term stuff though. Thanks for commenting it's always cool to hear good ideas in this space
Jump to function definition is 'M-.' jump back is 'M-,' . Also you might want to try 'C-h m' as that will show the keybindings for all the modes active in the current buffer (super handy)
Thanks for sharing!! I have a problem about dynamic variables: (defvar *a* 20) (defun test () (let ((*a* 1)) (lambda () (print *a*)))) (funcall (test)) In this case, funcall of test will print "20", the variable *a* is dynamic, but in the lambda function returned by test, it is a so called "closure", so *a* supposed to be bound to 1 everywhere. so where am i wrong? I am a little confused by these things. Appreciated very much
From clhs.lisp.se/Body/03_ad.htm we see that 'A lexical closure is a function that can refer to and alter the values of lexical bindings established by binding forms that textually include the function definition.' The key point there is that it is about lexical bindings and not dynamic ones so in: ``` (defvar *a* 20) (defun test () (let ((*a* 1) (b 2)) (lambda () (print (+ b *a*))))) (funcall (test)) ``` b will be captured by the lambda, and *a* will not
Thanks for your responding. So the key point is the type of variable? Variable "*a*" is dynamic while Variable "b" is lexical? If so, when set a variable directly in the REPL(it outputs some warning), what's the type of this variable? Meanwhile, when I make some test of these, I find a strange situation(although would not happen in real case): ``` ;; First set a1 CL-USER> (setf a1 20) ; in: SETF A1 ; (SETF A1 20) ; ==> ; (SETQ A1 20) ; ; caught WARNING: ; undefined variable: A1 ; ; compilation unit finished ; Undefined variable: ; A1 ; caught 1 WARNING condition 20 ;; Then define a test function CL-USER> (defun test-1 () (let ((a1 1)) (lambda () (list a1)))) TEST-1 ;; Call the result of the test func, output 1, as this is lexical binding CL-USER> (funcall (test-1)) (1) ;; Redefine again with "defvar", seems no effect to former test-1 CL-USER> (defvar a1 40) A1 CL-USER> (funcall (test-1)) (1) ;; Let's redefine the test func CL-USER> (defun test-1 () (let ((a1 1)) (lambda () (list a1)))) WARNING: redefining COMMON-LISP-USER::TEST-1 in DEFUN TEST-1 ;; Werid Happens!! seems variable "a1" changes to dynamic, but the value is not 40(from defvar), it is 20 (from setf)! CL-USER> (funcall (test-1)) (20) ``` I don't know it's the desired behavior or it is just a implementation issue(I test in sbcl). It's a long comment, Appreciated very much ! :)
Would love to see something on set/setq/setf, when to use each and maybe when to use those vs when to use what you covered in this video!
Forever grateful for your helpful videos. If I ever learn enough, I'll pass the torch however I can.
One interesting use case for dynamic variables is this: Locally overwriting dynamic variables provides some amount of control over how (e.g. builtin) functions that use those variables work. For example one could lexically overwrite /*print-base*/ and thus change how print works (see the spec on /*print-base*/ for examples).
This is actually feels a bit like creational OOP patterns (like factory method): To change a system, change a specific component of the system.
one could argue that the earmuffs convention was created because Lisp is case insensitive.
differentiating between FOO, Foo, and foo becomes impossible but +foo+, *foo*, and foo are now distinct
Nice explanation about the subject. I would just like to add that if you could show some more realistic use cases for a feature you are teaching, it would be even more interesting. That said, I know it is not always easy (or even possible) to be didactic and still show "real" case examples for everything.
Keep up the superb work!
Spot on comment. I'm not sure how to do that with adding addition knowledge dependencies though. Currently this video requires 'evaluation basics' & 'equality' and really because of in-package it should have one on packages but I haven't made that video yet. Ideally I'd like for some lovely person to make a site which has a big ol' graph that showing the interconnections so folks can take their own path whilst also understanding how things relate... thats all long term stuff though. Thanks for commenting it's always cool to hear good ideas in this space
How do you link your emacs to Common Lisp HyperSpec and call on function definitions with an emacs keybinding?
'C-c C-d h' So that's: hold down control, tap c, tap d, release control tap h
Jump to function definition is 'M-.' jump back is 'M-,' . Also you might want to try 'C-h m' as that will show the keybindings for all the modes active in the current buffer (super handy)
Thanks for sharing!!
I have a problem about dynamic variables:
(defvar *a* 20)
(defun test ()
(let ((*a* 1))
(lambda () (print *a*))))
(funcall (test))
In this case, funcall of test will print "20", the variable *a* is dynamic, but in the lambda function returned by test, it is a so called "closure", so *a* supposed to be bound to 1 everywhere.
so where am i wrong? I am a little confused by these things.
Appreciated very much
+Sen Ni that is a great question! I am on my mobile right now but I'll definitely get to this. This will have to be a video too
From clhs.lisp.se/Body/03_ad.htm we see that 'A lexical closure is a function that can refer to and alter the values of lexical bindings established by binding forms that textually include the function definition.' The key point there is that it is about lexical bindings and not dynamic ones so in:
```
(defvar *a* 20)
(defun test ()
(let ((*a* 1)
(b 2))
(lambda () (print (+ b *a*)))))
(funcall (test))
```
b will be captured by the lambda, and *a* will not
Thanks for your responding.
So the key point is the type of variable? Variable "*a*" is dynamic while Variable "b" is lexical?
If so, when set a variable directly in the REPL(it outputs some warning), what's the type of this variable?
Meanwhile, when I make some test of these, I find a strange situation(although would not happen in real case):
```
;; First set a1
CL-USER> (setf a1 20)
; in: SETF A1
; (SETF A1 20)
; ==>
; (SETQ A1 20)
;
; caught WARNING:
; undefined variable: A1
;
; compilation unit finished
; Undefined variable:
; A1
; caught 1 WARNING condition
20
;; Then define a test function
CL-USER> (defun test-1 ()
(let ((a1 1))
(lambda () (list a1))))
TEST-1
;; Call the result of the test func, output 1, as this is lexical binding
CL-USER> (funcall (test-1))
(1)
;; Redefine again with "defvar", seems no effect to former test-1
CL-USER> (defvar a1 40)
A1
CL-USER> (funcall (test-1))
(1)
;; Let's redefine the test func
CL-USER> (defun test-1 ()
(let ((a1 1))
(lambda () (list a1))))
WARNING: redefining COMMON-LISP-USER::TEST-1 in DEFUN
TEST-1
;; Werid Happens!! seems variable "a1" changes to dynamic, but the value is not 40(from defvar), it is 20 (from setf)!
CL-USER> (funcall (test-1))
(20)
```
I don't know it's the desired behavior or it is just a implementation issue(I test in sbcl).
It's a long comment, Appreciated very much ! :)
@@senni1083 the same happens in CCL
defvar doesn't change symbol's value
@@senni1083 stackoverflow.com/questions/28328187/in-common-lisp-how-to-test-if-variable-is-special