[scheme] miniKanren util

miniKanrenで使える便利関数をいくつか追加した

https://github.com/niitsuma/Racket-miniKanren/blob/recursive/miniKanren.scm
の183行から下が自分の書いた追加関数

for-eache

for-eachをminiKanrenに拡張したもの
for-eachoという拡張がすでにあるが、for-eachoは入力が1つしかとれない。
for-eacheは任意の個数のlistに適用できる

使用例1
(run* (q)  (for-eache nullo  '(() () ()) ))

これはfor-eachoでもできる

使用例2
(run* (q)
 (for-eache
   (lambda (x y)  (== x y)  )
   '(2 3 4)
    q
 ))
> ( (2 3 4) )

入力が '(2 3 4) q の2つあるのでfor-eacho ではできない

builde

Racket のbuild-list 関数をminiKanrenに拡張したもの。

使用例
(let ([vs (build-list 3 var)])
 (run* (q)
   (builde
     3 ; n-loop
    (lambda (i) (== (list-ref vs i) i)
    ))
   (== q vs)
  )) 
> '((0 1 2))

要するに i=1 2 3 の for ループを回すようなもの

build2e

buildeを2重ループに拡張したもの

使用例
(let ([vs (build-list 6 var)])
  (run*  (q)
    (build2e
      2 3
     (lambda (i j)
       (==   (list-ref vs (+ (* i 3) j ) )  
             (+ (* i 3) j ))
      ))
      (== q vs)
) )
 > '((0 1 2 3 4 5))

i = 0 1
j= 0 1 2
の合計6回ループされる

builde-nest

任意のn重ループができるbuilde

使用例
(let ([vs (build-list 6 var)])
 (run* (q)
   (builde-nest
    '(2 3)
     (lambda (i j)
      (== (list-ref vs (+ (* i 3) j ) )
          (+ (* i 3) j ))
      ))
    (== q vs)
 ) )
 
 > '((0 1 2 3 4 5))

これはbuild2eの使用例と同じ問題プログラムをbuilde-nestで書き換えたものになっている。