如何使用数据流组合器提取此因子词定义中的冗余?

问题描述 投票:0回答:2

我使用早期的 ProjectEuler 问题作为了解 Factor 的一种方式。已经在第一个问题我没有找到令人满意的解决方案。

我可以用这个解决除法测试

: 3or5divisible ( n -- ? ) [ 3 mod ] [ 5 mod ] bi * 0 = ;

但我不喜欢的是

mod
的重复。当然只是两次,但是另一个问题可能需要检查200。

我尝试使用

map
curry
bi
2bi
bi@
、数组和普通堆栈值等。我总是得到堆栈下溢或效果不匹配(使用
map
时)。我还没有找到在检查器中查看试验结果的方法。

如何将

mod
分解出来并将其应用于
{ 3 5 }
或等效堆栈?
很酷的是两个变体,例如
mod3and5
(包括效果规范);一种将
2 1
留在堆栈上用于输入 11,另一种则返回
{ 2 1 }

combinators factor-lang
2个回答
0
投票

我只能想到这样做,删除其中一个模组,但最终会添加一个

bi-curry@
功能。

: 3or5divisible ( n -- ? ) 3 5 [ mod ] bi-curry@ bi * 0 = ;

0
投票

一般性评论,有时重复的代码更具可读性,有时更高级别的花哨代码更好。 组合器可以发挥作用的地方是它消除了更难理解的堆栈改组。

所以,也许如果你从“最重复的”开始:

: 3or5divisible ( n -- ? )
    [ 3 mod zero? ] [ 5 mod zero? ] bi or ;

看看使用命名局部变量看起来如何,不错:

:: 3or5divisible ( n -- ? )
    n 3 mod zero? n 5 mod zero? or ;

然后使用花哨的组合器查看它的外观,可能更难阅读:

: 3or5divisible ( n -- ? )
    3 5 [ mod zero? ] bi-curry@ bi or ;

然后看看它是如何工作的,如果你向它传递了一系列数字来检查,超级容易阅读:

: 3or5divisible ( n -- ? )
    { 3 5 } [ mod zero? ] any? ;

或者也许使用宏为任意输入生成代码:

MACRO: divisible ( ns -- quot )
    [ [ '[ _ mod zero? ] ] map '[ _ cleave ] ]
    [ length 1 - [ or ] <repetition> concat ] bi
    append ;

然后看看它是否生成了您期望的代码:

IN: scratchpad [ { 3 5 } divisible ] expand-macros .
[ [ 3 mod zero? ] keep [ 5 mod zero? ] keep drop or ]

很多可能性...

© www.soinside.com 2019 - 2024. All rights reserved.