libera/#commonlisp - IRC Chatlog
Search
5:46:00
susam
Most of the time I realize that my erroneous code is running in an infinite loop only when the computer's fan goes berserk. I don't realize it in SLIME REPL because the REPL prompt always returns successfully without any output. Do you have another way to realize that your code is running in an infinite loop?
5:46:33
susam
It takes a while to realize that no output + fan noise => infinite loop. It feels disorienting until that realization.
5:47:54
beach
You must be running the code in a separate thread if you get the prompt back. The solution, then, is to run it in the same thread as the REPL.
5:47:56
mfiano
I have stats for cpu and memory utilization visible at all times (on the bottom of my screen, and I'm trained to keep a constant eye on them)
5:50:33
susam
beach: I am not doing threads. For example, here is a simple test case to reproduce what I see. Type (loop) in a code buffer. Then C-c C-c to compile it. SLIME-REPL shows "; processing (LOOP)" with the "CL-USER>" prompt below it.
5:51:10
susam
Now it isn't a new "CL-USER>" prompt. It is the old prompt itself pushed below the "; processing (LOOP)" line.
5:53:31
susam
So the visual feedback for infinite loop is indistinguishable from that due to correct code.
5:54:10
susam
mfiano: Okay. Thanks for the tip. I will set up my environment to show CPU and memory usage too.
5:55:31
mfiano
When you C-c C-c, it is compiled on a background thread with results sent to the repl thread.
5:57:04
susam
pillton: It happens with your loop too but the "here" output gives a visual feedback that I am in an infinite loop, so no disorientation there. This is what the REPL looks like then: https://plaster.tymoon.eu/view/2543
5:57:33
susam
mfiano: Thanks. That makes sense. So that is consistent with what beach said too. The code is compiled in a background thread.
5:57:33
mfiano
This is important to realize, because if you have a continuous render/event loop or some such, you will need a thread-safe queue to process class redefinitions.
5:58:09
pillton
susam: I don't understand. C-c C-c compiles the "current toplevel form". It doesn't evaluate it.
6:01:29
susam
pillton: What happens if you C-c C-c this in your Lisp buffer: (dotimes (n 10) (print n)). Does it not end up printing 0 1 2 ... 10 in your REPL?
6:04:05
susam
pillton: Yes, that was a disconcerting for me too when I began learning CL with SLIME. But gradually got used to it. For example, C-c C-c is mapped to slime-compile-defun but it can compile any top-level form.
6:04:21
susam
To be fair to the doc, it does spell it out clearly. "The code for the region is executed after compilation. In principle, the command writes the region to a file, compiles that file, and loads the resulting code."
6:05:41
susam
I now realize I should ask more of these questions in this channel. Lot to learn. I have been coding like a caveman for so long.
6:07:31
susam
Interesting, it indeed does not. It probably should, otherwise the behaviour can be confusing. I quoted the documentation from here: https://common-lisp.net/project/slime/doc/html/Compilation.html
7:46:01
sm2n
mfiano, do you have any examples of that (event loop class redefinitions with a threadsafe queue)?
7:47:14
mfiano
That is pretty domain-specific code...I have a few private examples, but spread out across a large project, so not worth sharing
7:49:39
sm2n
could you at least outline how it should work? I didn't know you could queue class redefinitions up
7:53:07
mfiano
Well the issue is, that there is a bit of implementation-specific behavior regarding when and how the generic accessors of a defclass should be recompiled, and since SLIME compiles on a dedicated compilation thread and not your application thread, there could be a slight instance in which the slots are non-existant, or no applicable methods exist. If you require live-redefining classes (or your
7:53:09
mfiano
users do), a solution would be to write a macro that expands into a thunk which calls defclass, and call that function in your main thread as you pop items off of your locking queue.
7:53:44
mfiano
I do this in my game engine. At worst though, if you don't do any of this, you'll just be presented with the debugger for a single frame, in which you can hit the continue restart.
7:54:40
sm2n
"When the class C is redefined, changes are propagated to its instances and to instances of any of its subclasses. Updating such an instance occurs at an implementation-dependent time, but no later than the next time a slot of that instance is read or written. "
7:55:53
mfiano
I think the underlying problem is that when you recompile a defclass, the methods for the generic function accessors are removed, and then re-added.
8:01:04
mfiano
It's a rare bug to encounter, you'd have to be calling a slot accessor fast enough, or lucky enough to hit it at the exact moment during the redefinition between method removal and addition.
8:01:22
mfiano
and when you do encounter it, it's non-fatal, as you can just issue the continue restart.
8:26:32
phadthai
multithreaded lisp largely chose what is protected by locks or not and it's also a performance tradeoff, I suspect the above is related and needs an explicit lock
8:28:52
phadthai
and concurrency was not part of the standard; I think that the only fairly agreed thing is that dynamically scoped variables can be used as thread-specific contexts
12:55:22
jmercouris
is there a way to actually obtain `(lambda () (print "tomatoes are great"))` from xyz?
13:01:29
Bike
in general the source of a function still isn't going to be enough to serialize it, e.g. for closures
13:13:45
polygon-op
being able to see the source code of the commercial system doesn't mean that it could be copied (that would depend on the license)
13:25:46
jmercouris
is there a way to see who has a reference to something preventing it from being GC'd?
13:28:19
beach
If you track everything, you are pretty much preventing it from being garbage collected, unless you use weak references.
13:30:57
Bike
what the thing i'm recalling does is give you a path from roots to a given object. since the object you're looking for is already alive for some reason, you're not making it any more impossible to collect
13:39:52
_death
(setf (gethash path *data-paths*) path) <- the hash table is weak only on keys.. if the value is path, then it defeats the purpose