freenode/lisp - IRC Chatlog
Search
3:45:22
beach
I find the example/question of remexre impossible to follow because of all the oversimplifications. You can't change the class of a vector, nor of a bit or :mu.
3:59:33
loke
McCLIM from the 19'th of this month is fine, but the latest version throws an SBCL AVER when loading Clouseau
4:12:42
beach
remexre: If I understand what you are doing, it looks similar to what I do in Cluffer. Cluffer is a tree (representing a sequence) of editor lines stored in the leaves of the tree.
4:12:49
beach
At any point in time, one line is "open", so it is represented as a gap buffer for fast updates. Other lines are "closed", so they are represented as something more compact.
4:13:06
beach
When a closed line is about to be modified, the currently open line is first closed. Then I inspect the contents.
4:13:17
beach
If there are objects in it other than characters, I create a simple vector and move the contents of the gap buffer to it.
4:13:28
beach
If it contains only characters, but not only base characters, I create a simple string.
4:13:31
beach
And if it contains only base characters, I create a simple base string. Maybe I haven't implemented all these optimization yet, but that's the idea at least.
4:14:09
beach
remexre: But, since all these objects are instance of built-in classes, I can't reliably use change-class.
4:16:48
beach
I suppose you mean "standard classes". You can use change-class on one of those instances, but that won't change the representation of the wrapped object.
4:19:29
beach
Oh, since I mentioned Cluffer, the entire thing is defined as a bunch of CLOS protocols, allowing client code to customize how lines are represented, how they are opened, and how they are closed.
4:37:31
loke
beach: I don't know about his case specifically, but I think of “primitives” as being objects that fit in a single register. Such as fixnums, characters, etc.
4:46:24
loke
remexre: That would be any class which has STANDARD-CLASS (or a subclass of which) as its metaclass.
4:47:39
beach
loke: Both "classes" (meaning "standard classes") and "primitive classes" (probably meaning "built-in classes") were mentioned.
4:54:01
beach
remexre: And, yes, I use the same trick in Cluffer. I wrap the line contents in a standard object that can be an instance of either CLOSED-LINE or OPEN-LINE, and I use CHANGE-CLASS on that standard object so as to preserve the identity. But I still need to replace the line contents "manually" when the line is opened or closed.
6:01:02
beach
Question: When an attempt is made to transferred control to an exit point, it is possible that the exit point has been "abandoned", But is it also possible that an attempt can be made to execute the cleanup form of an UNWIND-PROTECT form even though the exit point corresponding to the UNWIND-PROTECT form has been "abandoned"? If so, I would like to see an example.
6:20:23
specbot
Transfer of Control to an Exit Point: http://www.lispworks.com/reference/HyperSpec/Body/05_b.htm
6:25:59
flip214
beach: reading that chapter and thinking through a few (invalid) examples I believe that "abandoned" is meant as
6:26:35
flip214
"code flow won't get back to that point", so the corresponding U-P isn't relevant any more either.
6:28:37
lieven
or for maximum fun, you have handed out #'(lambda () (go foo)) closures to downward functions. SERIES does that a lot and has brought forward bugs in implementations with it.
6:29:11
beach
flip214: No, it means that an attempt can be made to transfer to it, but that would be illegal.
6:30:42
beach
flip214: So the question is whether such an attempt is possible when it comes to an UNWIND-PROTECT as opposed to a GO or a RETURN-FROM.
6:32:13
beach
So I know that i need a VALID-P slot in an exit point that corresponds to a BLOCK or a TAGBODY, and I am trying to determine whether I need one in an exit point that corresponds to an UNWIND-PROTECT.
6:33:16
beach
I know SBCL does not check the validity of all its exit points, but that's not a bug, because the Common Lisp HyperSpec says it's undefined behavior.
6:40:23
beach
So the question becomes: Is there a concept of an exit point corresponding to UNWIND-PROTECT being "abandoned", and if so, what does it imply and when is it done?
6:41:33
beach
I am thinking that it is abandoned once the cleanup forms have been executed (as opposed to initially as suggested by point 1), and I think it implies that the cleanup forms can not be executed a second time.
6:42:53
beach
And if I am right, my first question still stands, i.e. is it possible that such an attempt can be made, so that I have to represent this fact explicitly, and if so, what is the situation that can make such an attempt possible?
6:44:05
beach
I think the problem with the terminology is the definition of "exit point". The glossary includes UNWIND-PROTECT, but 5.2 seems to exclude such points.
6:45:56
beach
Here is what I think. The cleanup forms of UNWIND-PROTECT are always executed starting with the most recently established ones.
6:48:04
beach
If an UNWIND-PROTECT does a non-local control transfer to an exit point that has not yet been abandoned, then only less recent UNWIND-PROTECT exit points are present in the dynamic environment. So they can't have already been executed. Hence they are not abandoned.
6:54:45
beach
So in conclusion, I don't think that UNWIND-PROTECT needs an explicit indication that it has been abandoned.
6:55:28
beach
I think what I will do is I will exclude UNWIND-PROTECT from the definition of "exit point" in my code. That way, 5.2 makes more sense.
7:07:48
beach
We really, really should create this document/website called "Common Lisp for language implementers".
7:08:36
scymtym
beach: was this discussion in #lisp? i only see CHANGE-CLASS and a clouseau regression so far
7:18:32
beach
I so wish we had an "annotatable" Common Lisp HyperSpec the way we do with the CLIM specification.
7:24:48
no-defun-allowed
beach: Is the situation you're asking for anything like this example in a scan of CLTL? It sounds similar to me but I'm not sure: https://i.redd.it/wf8yklonnph31.jpg
7:24:54
beach
Not sure I understand the question. I would like a document that explains the deep ideas of the standard where those are not clear from the existing document, and I would like a discussion about implementation strategies with pros and cons of each one, including the impact of every choice on the rest of the system.
7:25:32
scymtym
beach: reading 5.2, i had the same impression, that is UNWIND-PROTECT clauses don't seem to make sense as exit points in their own right. associating them with other exit points seems better. still thinking about the actual question
7:27:02
beach
no-defun-allowed: My question is specifically about exit points corresponding to UNWIND-PROTECT.
7:36:19
scymtym
i mean control is transferred to an exit point, not an UNWIND-PROTECT clause. but when transfer is transferred, there is a sequence of associated UNWIND-PROTECT clauses (not statically associated with the program point that established the exit point, of course). that's my understanding of 5.2
7:49:24
beach
Let's say the dynamic environment contains B1 B2 U1 U2 where B1 and B2 are BLOCK points and U1 and U2 are UNWIND-PROTECT points. and U2 is the most recent.
7:52:04
beach
But when we are done, we have to make sure that we do not return to the initial transfer, because we would then execute the cleanup forms of U1 again.
7:52:44
beach
So, it looks to me like there is at most one occurrence of 5.2 possible at any point in time. They do not nest.
7:53:11
scymtym
i was thinking about the same example: (block outer (block inner (unwind-protect (unwind-protect (return-from inner) (print 1) (return-from outer)) (print 2))))
7:54:30
beach
But we can't consider this situation illegal, so it makes no sense to mark U1 as abandoned and signal an error in the initial transfer.
7:57:11
beach
Or else, we have different concept of "abandoned" for UNWIND-PROTECT, meaning "don't execute the cleanup forms again".
7:57:17
scymtym
i was thinking about modeling the exit point/uwp stack more explicitly and turning 5.2 into an algorithm (or more than one, if there are multiple possible interpretations) to get a more formal grip
7:58:25
beach
Good idea. And that is basically what I am trying to do, because I am planning to implement this stuff for SICL. But you are right, an more formal algorithm is probably a good start.
8:00:38
beach
The other slight quirk is that, as a result of RETURN-FROM, the exit point is abandoned and cannot be used again. But as a result of GO, the exit point is still valid.
8:04:21
beach
More quirks: 5.2 says "Not that for go, the exit point is the form within the tagbody that is being executed at the time the go is performed;...."
8:05:50
beach
So if I have (tagbody (f) (g) out) and (f) happens to do a (go out), then the exit point is (f)?
8:07:47
scymtym
one could also argue the statement containing the GO form, but the GO form itself is strange
8:10:18
beach
So 5.2 says that exit points are forms, but the glossary says that they are points in a control form.
8:13:38
beach
It seems to me that a "point" is either before a particular form is about to be evaluated, or immediately after a particular form has been evaluated. Or something like that.
8:15:15
scymtym
the static aspect sounds like program points. but the ability to abandon exit points requires some kind of attached dynamic state
8:21:05
beach
It should be defined somewhere that the program point corresponding to the end of the evaluation of the last form in the body is one where special variable bindings established by the lambda list are undone before control returns to the caller.
8:23:08
scymtym
time to look into formal semantics for common lisp? i would be surprised if that hadn't been attempted before, though
8:24:23
beach
We had to make some of it formal in Cleavir (especially in version 2), where we have the concept of a "compilation context" that says how values are to be used, and what the successor forms are.
8:27:41
beach
Hmm, maybe if I just document what Cleavir2 does, while avoiding direct references to its data structures, it would be a good start.
8:28:11
scymtym
yeah, i said the above half-jokingly. some kind of middle ground in terms of formality may be best since formal semantics for all of common lisp seems daunting
8:31:05
beach
*sigh*, I think I just signed up for yet another huge task. But I can't put what I am doing on hold, so it shall have to wait, or I can do it in parallel with my current tasks.
9:08:53
beach
So at least I convinced myself that the previous example with B1 B2 U1 U2 is not a problem.
9:09:39
beach
The "unwinder", i.e. the procedure that executes the steps of section 5.2 is basically executed as a result of a function call.
9:11:13
beach
If U2 executes the unwinder again, that second invocation will end with a non-local jump to B1, and the first invocation of the unwinder will be automatically eliminated.
10:29:56
isBEKaml
How can I define optional arguments with default values in defuns? as an example: (defun factorial (n (acc 1)) ...) ?
10:32:22
White_Flame
acc = defaults NIL. (acc 1) = defaults 1. (acc 1 acc-p) = the acc-p boolean tells you if the caller actually included that parameter or not
10:32:40
White_Flame
the latter, because (factorial 3 1) is ambiguous as to whether the 1 was passed or defaulted
10:32:59
isBEKaml
White_Flame: yeah, I vaguely remembered seeing something like that in PG's ANSI CL book
10:33:34
White_Flame
also, there's #clschool for basic questions, a lot of responses will get advanced here
10:34:28
isBEKaml
thanks, I have worked around my failing memory with labels in that factorial function now
12:03:40
beach
To me, it is looking more and more like the authors of the standard had some very concrete implementation of the dynamic environment in mind, and that they tried to avoid such a concrete description in the standard, in favor of some more abstract language. The net result is a loss of precision, and also some contradicting terminology.
12:05:00
beach
I am currently trying to recover that concrete description. And then I will try to find a better way of turning it abstract so that no precision is lost. I am not sure that I will be able to do that though.
12:15:29
beach
It is interesting how one can think that one knows a language pretty well, but then when one tries to create an implementation of it, one discovers several holes in one's knowledge about it. And some holes in the specification of it as well.
12:37:15
ralt
a simple single-threaded event loop using only lisp and some small cffi wrappers is not too hard to do
13:46:41
Xach
i used it to do async dns and async http to have bounded response times for a web app.
13:52:17
ralt
Xach: yes, that's my point, a custom single threaded one is fairly straightforward once you have epoll
13:53:45
Xach
i cheated and didn't use the system resolver, just parsed resolv.conf and did direct networking myself. which does not work in all situations but did for me.
14:05:56
dlowe
I have no idea how this got called grovelling - maybe it's basically a form of giving up and begging other languages to do things