词法作用域是否可以实现硬实时?
我正在读这篇论文是关于 funarg 问题的,这实际上是维护词法闭包环境的问题。这是一篇旧论文,我不确定作者的结论是否仍然成立,但他强烈暗示,为了拥有词法作用域而不是动态作用域,你必须放弃传统的 C 风格堆栈,而采用树结构环境,从堆分配。
这是否使得在任何硬实时系统中都不可能拥有词法范围的闭包?在实时嵌入式系统中,延迟以微秒为单位进行测量,通常会禁止堆分配,因为它会引入不确定的延迟。
这一直是我的一种无聊的好奇心,因为我主要是作为一名固件开发人员来制作面包的,其中 C 是事实上的语言,有一段时间,我似乎一直在利用我的脑力来弄清楚如何迫使 C让我用更复杂的语言免费做一些事情。因此,我开始想知道是否可以专门为基于微控制器的硬实时嵌入式系统实现一个 micro-lisp 编译器。
顺便说一句:我最近对诸如闭包和对象如何等价等深层主题有了深刻的见解,这让我对像 Stallman 和 Rich Hickey 以及 Paul Graham 这样的人更加敬畏。对我来说,从头开始实现 Lisp 似乎是一项艰巨的任务。很难知道从哪里开始。 (也许是 PG 对 McCarthy 的原始 eval 函数的实现,IDK)。无论如何,我离题了。
I was reading this paper about the funarg problem, which is really the problem of maintaining the environments of lexical closures. It's an old paper and I'm not sure if the author's conclusions still hold, but he strongly implies that, in order to have lexical rather than dynamic scope, you have to abandon the traditional C-style stack, and instead have a tree structure of environments, allocated from the heap.
Does this make it impossible to have lexically scoped closures in any hard-real-time system? in real-time embedded systems, where latencies are measured in microseconds, heap allocation is typically forbidden because of the non-deterministic latency it introduces.
This has been an idle curiosity of mine, because I make my bread mostly as a firmware developer where C is the de facto language, and for a while now it seems I've been using my brain power to figure out how to force C to let me do things that come for free in more sophisticated languages. Consequently, I've begun to wonder whether you could implement a micro-lisp compiler specifically for hard-real-time embedded microcontroller-based systems.
As a side note: I've lately gained great insights into deep topics like how closures and objects are equivalent and so forth, and it gives me greater awe of guys like Stallman and Rich Hickey, and Paul Graham. Implementing Lisp from the ground up seems like a daunting task to me. It's hard to know where to start. (Maybe with PG's implementation of McCarthy's original eval function, IDK). Anyway, I digress.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
词法作用域显然可以通过“硬实时”实现——毕竟,您说您正在将 C 用于实时应用程序,而 C 是一种词法作用域语言。我的猜测是,您实际上关心的是一流函数,而不是词法范围。假设,有一大堆已知的编译技术可以有效地处理一流函数。
首先,您在教科书等中看到的几乎总是在执行通常的树形环境,但在实践中,如果不将函数用作值,则根本不需要这样做。实际上,每个像样的函数式语言编译器都会识别此类代码,并使用堆栈来代替,因此分配的开销为零。 (请注意,此时这意味着,如果您将自己限制为用 C 编写的内容,则不需要分配。)然后,有很多其他方法可以减少分配 - 例如,考虑类似 < code>(lambda (x) (* x 9))——这个函数并没有真正关闭任何自由标识符,因此编译器将将其提升到顶部,这样就只有该函数的单个副本,并且再次没有分配。 (相关说明:通过这种优化,你已经得到了比 C 给你的更多的东西,但仍然没有分配。)
有一大堆 额外的优化可以避免分配,但是当然在某些情况下您确实需要分配新的闭包。但这些地方是静态可识别的,如果您真的关心此类分配,那么破解一个警告您此类分配的编译器应该不难。有很多这样的语言,例如GOAL,非常低级别的预方案。但是大多数人很快就掌握了 IME 的窍门,并且分配发生的位置变得越来越明显 - 因此您可以获得高级语言的好处,并且当它到达您想要优化的某些代码时,很容易看到分配发生的位置,并且通过通常的方式很容易避免它。 (当然,所有这些都与优化分配无关。)
Lexical scope is obviously possible with "hard real-time" -- after all, you say that you're using C for real-time applications, and C is a lexically scoped language. My guess is that you're actually concerned about first-class functions, not lexical scope. Assuming that, there's a whole bunch of known compilation techniques for dealing with first-class functions efficiently.
First of all, what you'll see in textbooks etc is almost always doing the usual tree-shaped environment, but in practice that's not needed at all if functions are not used as values. Practically every decent functional language compiler will identify such code and will use the stack instead, so there's zero overhead for allocation. (Note that at this point this means that if you limit yourself to the kind of things that you write in C then no allocation is needed.) Then, there's a bunch of additional ways to reduce allocations -- for example, consider something like
(lambda (x) (* x 9))
-- this function doesn't really close over any free identifiers, and therefore compilers will lift it to the top so there's a single copy of the function and, again, no allocation. (Related note: with this optimization you already get more than what C gives you and still no allocation.)There's a whole bunch of additional optimizations that avoid allocation, but of course there are cases where you really need to allocate a new closure. But these places are statically identifiable, and if you really care about such allocations then it shouldn't be difficult to hack up a compiler that warns you about such allocations. There have been a number of such languages, see for example GOAL, the very low level prescheme. But IME most people quickly get the hang of things and it's getting obvious where allocations happen -- so you get the benefit of a high level language, and when it gets to some code that you want to optimize, it's easy to see where allocation happens, and it's easy to avoid it in the usual ways. (And of course, all of this is unrelated to optimizing allocations.)
我发现了一些实时分配器,所以我想说。实时词法范围是可能的:
http://rtportal.upv.es/rtmalloc/
< a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.441&rep=rep1&type=pdf" rel="nofollow">http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.441&rep=rep1&type=pdf
在编写我自己的文章之前添加到您的摘要中micro-lisp,我会尝试为有问题的嵌入式系统查找或移植 lua 。它非常小,但提供了 LISP 的大部分功能:一流的函数、闭包、没有延续但有协程。
I found some real-time allocators so I'd say. lexical scope in real-time is possible:
http://rtportal.upv.es/rtmalloc/
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.106.441&rep=rep1&type=pdf
Adding to your digession, before writing my own micro-lisp, I would try to find or port lua for the embedded system in question. It is very small and offers much of LISP: first-class functions, closures, no continuations but co-routines.