为什么重复循环变量不起作用

Why does loop variable in repeat not work

repeat 的循环变量可以在其块中使用,如下所示:

>> b: func [x] [x + i]
== func [x][x + i]
>> repeat i 2 [print reduce append copy [b] [3]]
4
5

可以看到函数“b”使用了变量“i”。

然而,在下面的例子中,函数没有看到循环变量“idx”。给出错误信息:

*** Script Error: idx has no value


Red []
map: function [a-func a-block][
result: [] args: [] clear result
either parse a-block [some block!][
  repeat idx length? a-block/1 [
    clear args
    foreach x a-block [append args to-block x/:idx]
    append result reduce append copy [a-func] args
    ]
   return result 
  ]
  [
   repeat idx length? a-block [
     append result to-block a-func a-block/:idx
     ]
   ]
]

map func [x y] [x + y - idx] [[1 2] [3 4]]

为什么第二个密码错了?以及如何让它发挥作用?

Loop variable of repeat can be used in its block like this

不幸的是,这在概念上是错误的。 块中没有使用循环“变量”,它对函数的主体块和repeat.

都是“全局可见的”
>> repeat index 5 []
>> index
== 5

从图表上看,那是 lambda → <idx in global context> ← repeat,而不是您可能认为的 lambda → repeat → <idx in repeat's "scope">

However,in the following example, the loop variable "idx" is not seen by the function.

这是因为您正在使用 function 构造函数,这使得 idx 单词在其上下文中是局部的,如下所示:

>> function [][repeat index 3 []]
== func [/local index][repeat index 3 []]

相比之下,func(在您的第一个示例中使用)不会这样做。

>> func [][repeat index 3 []]
== func [][repeat index 3 []]

也就是这段代码中:

map func [x y] [x + y - idx] [[1 2] [3 4]]

idx 在你映射到块上的匿名函数中和 idxmap 实现中是两个完全不同的“变量”,绑定到不同的上下文:一个到全局(其中它没有值,因此是错误消息),另一个是本地的(默认设置为 none)。

Red 的“作用域”模型(或者更确切地说完全没有)的机制是一个高级主题,但如果需要我可以详细说明。

可以说它不依赖于传统的词法范围(就像在大多数 Lisp 方言中一样),也没有严格意义上的变量。相反,它依赖于符号值(又名单词),这些符号值带有与名称空间(又名上下文)的绑定,可以在运行时随意更改(参见下面示例中的 bind)——有点像 f -Kernel 和更早的 Lisp 中的表达式,或者可能是照应宏,其中 collect(另见下文)是一个主要示例:请注意它“捕获”keep 词,从那时起on 指的是它的内部上下文,它被定义为 append 的临时别名。查看 source collect 输出以了解我的意思。


这是 map 的草图(从技术上讲,您的草图更像 zip,但无论如何),以提示您潜在的解决方案。

map: function [
    function [function!]
    series   [series!]
][
    spec:  spec-of :function ; ideally needs to be cleaned up
    step:  length? spec
    index: 1
    
    bind body-of :function 'index
    
    collect [
        foreach :spec series [
            keep/only do compose [(:function) (:spec)]
            index: index + step
        ]
    ]
]

示例:

>> map func [x] [reduce [index x]][a b c d]
== [[1 a] [2 b] [3 c] [4 d]]
>> map func [x y] [reduce [index x + y - index]][9 2 1 4]
== [[1 10] [3 2]]