あなたがしていることを正しく理解していればp、述語であり、lこれに従ってリストを分割し、結果の2つのリストを集計関数で集計しますk。疑似コードで:
(split-by l p k) => (k {x in l | !p(x)} {x in l | p(x)})
your を置き換える際の問題letは、loop関数が再帰的に定義されていることです。形式は次のとおりです。
(define (loop low high lst)
(cond
((null? lst) <some value>)
(<some predicate> (loop (cons (car lst) low) high (cdr lst)))
(else (loop low (cons (car lst) high) (cdr lst)))))
lambdaこれを関数で直接使用して、「内部」再帰部分を定義することは絶対にできますが、これは simple withoutを使用して作成することはできませんlet: 関数はそれ自体を参照する必要があり (再帰的であるため)、それを割り当てることによってのみそれを行うことができます名前。defineそれをしletます、あなたにそれをさせますが、どのように変えても、その自己言及が必要です。あなたが賢く、継続を渡す場合:
(lambda (low high lst cont)
(cond
((null? lst) (agg high lst))
((pred? (car lst)) (cont low (cons (car lst) high) (cdr lst) cont))
(else (cont (cons (car lst) low) high (cdr lst) cont))))
明示的にすることでその自己参照を削除しましたが、何として渡しますcontか? let を介してそれを割り当てた場合、それを参照するシンボルがあります。
(define (split-by2 lst pred? agg)
(let ((f (lambda (low high lst cont)
(cond
((null? lst) (agg low high))
((pred? (car lst)) (cont low (cons (car lst) high) (cdr lst) cont))
(else (cont (cons (car lst) low) high (cdr lst) cont))))))
(f '() '() lst f)))
または、より簡潔に adefineを使用すると、まったく同じことが行われます (継続を渡す必要はありません)。
(define (split-by3 lst pred? agg)
(define (f low high lst)
(cond
((null? lst) (agg low high))
((pred? (car lst)) (f low (cons (car lst) high) (cdr lst)))
(else (f (cons (car lst) low) high (cdr lst)))))
(f '() '() lst))
それらはすべて同様に動作します。
(split-by '(1 2 3 4) (lambda (x) (> x 2)) list)
=> ((2 1) (4 3))
(split-by2 '(1 2 3 4) (lambda (x) (> x 2)) list)
=> ((2 1) (4 3))
(split-by3 '(1 2 3 4) (lambda (x) (> x 2)) list)
=> ((2 1) (4 3))
しかし、再帰関数のシンボルを定義することから逃れることはできません*。
あなたの例がうまくいかなかった理由については、functionを作成し、引数として関数(上記で呼び出しました) を取り、その function を指定contしてロジックを適用することを除いて、完全に正常に動作しています。それを渡すための「ループ」がないため(バインドしていないため)、その関数を返し、何もしません(さらに、返されたでは定義されていません)。looplambdalowhigh
*ラムダでコンビネータを使用して実行できるため、これは完全に正しいわけではありませんが、本来よりもはるかに複雑になります。
(define Y
(lambda (h)
((lambda (x) (x x))
(lambda (g)
(h (lambda args (apply (g g) args)))))))
(define (split-ycomb lst pred? agg)
((Y
(lambda(f)
(lambda (low high l)
(cond
((null? l) (agg low high))
((pred? (car l)) (f low (cons (car l) high) (cdr l)))
(else (f (cons (car l) low) high (cdr l)))))))
'() '() lst))
または、インラインコンビネータを使用した、さらに醜い純粋なバージョンの場合:
(define (split-ycomb2 lst pred? agg)
(((lambda (h)
((lambda (x) (x x))
(lambda (g)
(h (lambda args (apply (g g) args))))))
(lambda(f)
(lambda (low high l)
(cond
((null? l) (agg low high))
((pred? (car l)) (f low (cons (car l) high) (cdr l)))
(else (f (cons (car l) low) high (cdr l)))))))
'() '() lst))
期待どおりに動作するもの (ラムダのレイヤーのおかげ):
(split-ycomb '(1 2 3 4) (lambda (x) (> x 2)) list)
=> ((2 1) (4 3))
(split-ycomb2 '(1 2 3 4) (lambda (x) (> x 2)) list)
=> ((2 1) (4 3))