序列“基元”的最小集合是什么? 任何序列计算都需要吗?

发布于 2024-07-19 03:36:25 字数 559 浏览 2 评论 0原文

我正在用解释器编写类似计划的内容。 类似Scheme 的解释器应该能够很好地与任何实现 IEnumerable 的对象一起工作,这似乎很自然。

解释器不允许突变 - 不会暴露有副作用的函数。

由于 IEnumerable 不可克隆(请参阅此处),我无法实现迭代该列表有效地使用 car 和 cdr。

为了让任何“高阶”内容变得高效,我必须将一些原语实现为解释器的 C# 内置函数。

到目前为止,我已经将以下“原语”实现为 C# 内置函数:

  1. 过滤
  2. 器映射(完整的映射,而不仅仅是 mapcar)
  3. foldr

但我怀疑,例如,我可能可以使用映射和折叠的组合来实现“过滤器”。

我需要公开为“内置函数”的最小原语集是什么,以便我可以通过 IEnumerable 实例实现任何其他功能,而无需过多的运行时或空间成本,并且不必引入突变?

I am writing a Scheme-like in interpreter. It seems natural that the Scheme-like interpreter ought to work well with any object that implements IEnumerable.

The interpreter does not allow for mutation - no functions with side effects are exposed.

Because IEnumerable is not cloneable, (see here ), I can't implement iteration over the list efficiently using car and cdr.

In order to allow any "higher order" stuff to be efficient then, I've had to implement some primitives as C# builtins for the interpreter.

So far I have implemented the following "primitives" as C# builtin functions:

  1. filter
  2. map (the full map, not just mapcar)
  3. foldr

But I suspect, for example, that I could probably implement "filter" using a combination of map and foldr.

What is the minimal set of primitives I would need to expose as "builtins" such that I can implement any other functionality over IEnumerable instances without excess runtime or space costs, and without having to introduce mutation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花开浅夏 2024-07-26 03:36:25

所有函数都已在 System.Linq 命名空间中为您提供。

  1. 过滤=其中
  2. 地图=选择
  3. 折叠/减少=聚合(foldr=反转然后聚合)

您会发现更多。 例如

SelectMany = 地图 + 地图 + 展平
GroupBy = 分区

remq 和朋友可以用过滤器来完成。

更新

这些显然只需要 1 个列表参数,与正常的方案定义不同。

All the functions are already there for you in the System.Linq namespace.

  1. filter = Where
  2. map = Select
  3. fold/reduce = Aggregate (foldr = Reverse then Aggregate)

You will find many more. Eg

SelectMany = map + map + flatten
GroupBy = partition

remq and friends can be done in terms of filter.

Update

These obviously only take 1 single list argument, unlike the normal Scheme definitions.

半窗疏影 2024-07-26 03:36:25

您并不严格要求 map 是一个原语,因为您可以根据 foldr 来定义它。

示例(在 Haskell 中):

map f = foldr (\a b->f a:b) []

这实际上是 mapcar 而不是 map,但完整的 map 在 Haskell 中很难表达为 apply 不可用。

更完整的例子(在Scheme中):

(define (mapcar f l)
  (foldr (lambda (x t) (cons (f x) t)) ‛() l))

(define (heads ls) (mapcar car ls))

(define (tails ls) (mapcar cdr ls))

(define (any-null? ls) (foldr or? ﹟f (mapcar null? ls)))

(define (map f . ls)
  (if (any-null? ls)
      ‛()
      (cons (apply f (heads ls)) (apply map f (tails ls)))))

如果你没有carcdr,还有其他方法来定义它们,例如,如果你有闭包& 您的语言中的变量:

(define (car a) (foldr (lambda (x y) x) ﹟f a))

(define (cdr a)
  (let ((prev ‛())
        (tmp #f))
    (foldr (lambda (h t) (set! tmp (cons h t)) (set! prev t) tmp)
           ‛()
           a)
    prev))

You don't strictly need map to be a primitive as you can define it in terms of foldr.

Example (in Haskell):

map f = foldr (\a b->f a:b) []

This is really mapcar not map, but full map is difficult to express in Haskell as apply is not available.

More complete example (in Scheme):

(define (mapcar f l)
  (foldr (lambda (x t) (cons (f x) t)) ‛() l))

(define (heads ls) (mapcar car ls))

(define (tails ls) (mapcar cdr ls))

(define (any-null? ls) (foldr or? ﹟f (mapcar null? ls)))

(define (map f . ls)
  (if (any-null? ls)
      ‛()
      (cons (apply f (heads ls)) (apply map f (tails ls)))))

And if you don't have car and cdr there are other ways to define them, e.g. if you have closures & variables in your language:

(define (car a) (foldr (lambda (x y) x) ﹟f a))

(define (cdr a)
  (let ((prev ‛())
        (tmp #f))
    (foldr (lambda (h t) (set! tmp (cons h t)) (set! prev t) tmp)
           ‛()
           a)
    prev))
不乱于心 2024-07-26 03:36:25

我不太确定您的序列计算的目标是什么功能,但连接操作(即展平嵌套序列)可能也非常有用。 看一下 Haskell 的列表推导式是如何脱糖的以了解原因。

I'm not quite sure what functionality you are aiming for with your sequence computations, but a concat operation (i.e. flatten nested sequences) might be very useful too. Take a look at how Haskell's list comprehensions are desugared to see why.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文