libera/commonlisp - IRC Chatlog
Search
13:10:12
Bike
usually you write your project with a system definition .asd which includes external dependencies. if you then use quicklisp to load your project, it will take care of downloading anything you don't have downloaded. which is to say yes, but you probably don't want your project to actually use quicklisp itself unless it's a script kind of deal.
13:32:32
mfiano
Reminder: To anyone looking to have some fun this weekend (and all of next week in their spare time), the Lisp Game Jam friendly competition is kicking off tonight/tomorrow at midnight EDT: https://itch.io/jam/autumn-lisp-game-jam-2021
14:31:36
semz
There's also afaik still the problem that quicklisp doesn't verify downloads (has there been movement on that front?)
14:32:09
semz
it's one thing to do that on your own machine, but if you ship something that uses quicklisp in normal operation, your users will probably not appreciate that
15:00:23
JeromeLon
In a unit test, I want to check that a hook is called with the right argument. So I setup a special lexical witness variable, and update it from a lambda in the hook. But SBCL gives a warning, because there is no dynamic variable, even though everything is working fine. Any idea how I can improve this?
15:03:56
mfiano
JeromeLon: You are experiencing undefined behavior. Referencing a variable before defining it is not allowed by the standard.
15:07:10
White_Flame
but yeah, as far as this code goes, the specialness of *witness* only exists in that LET scope
15:07:50
White_Flame
if the INCF or access to *WITNESS* also exists outside that LET, then it would be handy
15:08:29
JeromeLon
beach: it's a setting that was extracted from a setting repository, and passed as an argument. There are many parts in the setting, the hook is the only one that can be EVALed
15:09:29
JeromeLon
White_Flame: right, but if all unit tests start to rely on defvars nothing is contained anymore
15:10:02
White_Flame
the defvar as well as the test function that uses it are all local to the testing package
15:10:45
JeromeLon
okok, so my solution only works by chance, and I should rely on a proper dynamic variable
15:36:51
JeromeLon
For reference, I tried on sbcl, clisp and ecl. In all cases, declaring the lexical variable special works: it's not BOUNDP, but the EVALed sexp has access to it. My test is (defun f1 () (let ((w 0)) (declare (special w)) (eval '(incf w)) w))
15:53:01
JeromeLon
beach: ok, how would you call it? "Dynamic variable that is only bound for the scope of the form that introduced it" is incorrect (BOUNDP is false).
15:58:33
beach
In your case (let (<stuff>)...) is the same as (let ((<stuff> nil))...) so your variable is bound in the scope of the LET.
15:59:39
JeromeLon
beach: I agree it is bound. I was mentioning BOUNDP because BOUNDP only returns true for dynamic variables, not lexically bound variables.
16:03:15
beach
Lexical variables are always bound, but there is no way to pass a lexical variable to BOUNDP.
16:11:49
JeromeLon
_death: nice, this fixes all my issues! No need for defvar, no warning, no global cluttering
16:15:14
_death
right.. still, I'd usually prefer defvar.. btw we've discussed all this last month I think, but september has been known at last..
16:16:01
Alfr
JeromeLon, does (boundp 'w) really tell you that w is unbound within the scope of that let? That's strange. (Precluding the case that you've makunbound it.)
16:20:17
beach
And it's not bound only within the scope of the let, but within the extent of the body of the let.
16:21:04
JeromeLon
Alfr: It's from my lambda than BOUNDP is false, even though it can access the variable (in https://pastebin.com/JzUqcTSG)
16:21:37
beach
So it is bound inside DECODE-SCALAR too, even though the body of the function DECODE-SCALAR is not in the scope of the LET.
16:21:43
_death
if you don't declare special at point of use, it's a lexical variable, e.g. check (funcall (let ((w 123)) (declare (special w)) (eval `(let ((w 42)) (lambda () w))))).. if the variable is free, some implementations take a lenient approach and look it up dynamic environment..
16:23:01
_death
"dynamic scope" is a colloquial term that means "indefinite scope and dynamic extent"
16:24:08
Alfr
beach, I thought that was clear from the context, as it's about that dynamic binding of W. Mea culpa.
16:25:59
_death
(you can also move the funcall inside the outer LET in the form I gave, with the same result)
16:31:21
JeromeLon
_death: "implementations take a lenient approach and look it up dynamic environment" this sentence explains everything. In particular, it explains why boundp is inconsistent with variable usage, I was finding this very confusing.
16:34:14
beach
JeromeLon: I suspect you are under the impression that the *...* inside your quoted expression refers to the binding in the LET.
16:39:02
JeromeLon
_death: no, I can't find the boundp returning false case again. I wish I had a better history of all my tests.
16:43:35
JeromeLon
anyway, when the code is consistent (using declare special both in the let and the eval), the behavior is consistent and clearly explained. And the initial weird case (eval having access to the special variable, even though nothing hints at it in its environment, but with a warning) has a reasonable explanation (lenient approach from the implementation)
16:46:47
_death
yeah.. SBCL warns you because generating that look-up code is not portable and perhaps not what you intended
17:27:32
lisp123
From the earlier discussion on Eval --> If I have (eval `(something ,other-thing)) , other-thing can still access the lexical environment in which the eval statement is placed into?
17:35:35
_death
your question is unclear.. other-thing presumably is a variable, and its value is used when creating the list that is passed to eval
17:45:57
lisp123
Similarly, (eval `(something ,(other-thing 'mysterious-symbol))) would evaluate other-thing within the lexical environment and pass the resultant list to eval?
17:48:11
lisp123
Yes. I was just curious on the earlier comment saying SBCL was being lenient, but perhaps its related to something else.
17:48:35
_death
the only thing is that the form it evaluates has no access to the lexical environment active when EVAL is called
18:22:19
pjb
JeromeLon: if you don't want to declare it special globaly, you will just have to wrap a local declaration around each use: (locally (declare (special ext::*witness*)) (incf ext::*witness*))
18:27:16
JeromeLon
pjb: yes, this was suggested by _death, and it's perfect for me, it's what I am using now in that code.