代码之家  ›  专栏  ›  技术社区  ›  Reverent Lapwing

使用另一个单词计算的引号会导致编译错误

  •  0
  • Reverent Lapwing  · 技术社区  · 8 年前

    背景

    加载下面的代码段将导致错误消息 无法将“call”应用于运行时计算值 :

    : subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
    : subtract-sum-seq ( seq -- x ) dup subtract-sum map ;
    

    我的理解是,这是一种预期行为,因为内部调用 呼叫 在里面 地图 要求在编译时提供已处理报价的输入和输出。

    问题

    然而,我在听众中测试了我认为是两个等价的表达,它们工作得很好。

    例1:

    # : subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
    # : subtract-sum-seq ( seq -- seq call ) dup subtract-sum ;
    # { 1 2 3 4 } subtract-sum-seq
    { 1 2 3 4 }
    [ 10 - ]
    # map
    { -9 -8 -7 -6 }
    

    例2:

    # : subtract-sum-seq ( seq -- x ) dup '[ _ - ] map ;
    # { 1 2 3 4 } subtract-sum-seq
    { -9 -8 -7 -6 }
    

    问题

    原始代码和导致前一个错误而不是其他两个错误的工作示例之间有什么区别?显然,我对报价有些不理解。

    附加信息

    有趣的是,我试着把电话转到 地图 在监听器内部,从第一个示例变为一个单词,它导致了与原始代码相同的错误:

    # { 1 2 3 4 } subtract-avg-seq map
    { -9 -8 -7 -6 }
    # : apply ( -- seq ) { 1 2 3 4 } subtract-avg-seq map ; ! error: Cannot apply "call" to a run-time computed value
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   fede s.    7 年前

    在这个例子中,有两个不同的问题在起作用。

    第一个问题是,在交互代码中,侦听器不会检查引用的堆栈效果,但在定义中编译代码时会检查引用的堆栈效果。这就是在听者中手动扩展单词的原因。

    第二个问题是,为引用声明的嵌套效果在大多数单词中都被忽略。你可以替换 ( n -- quot: ( n -- n ) ) 具有 ( n -- q ) 它也会有同样的效果。

    在这种情况下,第一个单词中的引号声明不会带到第二个单词。这就是为什么即使理论上都是正确的,编译器也不能证明它;它只是不知道引用的效果。

    解决方案是在呼叫站点声明报价的影响:

    : subtract-sum ( seq -- quot: ( n -- n ) ) sum '[ _ - ] ;
    : subtract-sum-seq ( seq -- x ) dup subtract-sum [ call( n -- n ) ] curry map ;
    { 1 2 3 4 } subtract-sum-seq .
    
    ! -> { -9 -8 -7 -6 }
    

    https://docs.factorcode.org/content/article-effects.html

    https://docs.factorcode.org/content/article-inference-escape.html

    推荐文章