2017-12-26 24 views
1

Schemeでオブジェクトと式を取り込む関数を作成するという質問をしています。たとえば、(foo 'x '(x 10 x x 4))と指定されたオブジェクトに続くすべてのオブジェクトを返す必要があります。上記の関数呼び出しは(10 x 4)を返します。ただし、式にはリストを含めることもできます。たとえば、(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))((3 y 5 y y 8 9) 5 y 8 12 15)を返します。彼らがリストを含んでいるとき、私は問題を抱えています。ここまでは私のコードです。式がリストに含まれている場合 リストを含む式をループするスキーム

(define (foo target expression) 
    (cond [(null? expression)] 
     [(list? (first expression)) (foo target (first expression))] 
     [(eqv? (first expression) target) (cons (first (rest expression)) (foo target (rest expression)))] 
     [(not (eqv? (first expression) target)) (foo target (rest expression))])) 

だから、私は、しかし、私が検索を続けるために、元の式に戻って取得する方法がわからない、再帰的にそのリストに関数を呼び出すしようとしています。

だから私は、私は((3 y 5 y y 8 9) 5 y 8 . #t)を取得しています(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17))を呼び出すときに、それが成功した最初のリストをループしかし、それはその後停止し、表現も

における第二のリストに到達していない、私が午前1つの他の問題があります私の結果の最後にブール値を返します。これは、cond [(null? expression)]という行のためです。式の最後にエラーが発生したため、これを追加しました。これをどのように修正できますか?

答えて

1

(cons x (cons y ...は、空のリスト'()で終了する場合にのみ、適切なリストになります。したがって(cons x (cons y ... empty))が適切で、あなたが持っているものとは対照的に(list x y ...)に相当します:(cons x (cons y ... #t))。あなたはベースケースの結果を'()にすることでこれを修正できます。

入力リストの要素が2つ未満の場合には、2番目の基本ケースもテストする必要があります。これは、関数が後で(first (rest expression))というように2番目の要素にアクセスしようとするためです。したがって、これが有効であることを確認するには、expressionに少なくとも2つの要素があることを確認する必要があります。これはあなたの条件で... (null? (rest expression)) ...として行うことができます。一方

は、あなたはそれがあるため、この行の遭遇した最初のリスト要素を反復処理のみ機能:この場合

[(list? (first expression)) (foo target (first expression))] 

、あなただけの(first expression)を処理していますが、(first expression)(rest expression)の両方を処理する必要があります。リストを再構成しているため、コンシューマを次のように使用できます。

(cons (foo target (first expression)) 
     (foo target (rest expression))) 

これは元のリストの深さを再現します。ご希望の出力例から、あなたが結果を平らにしたいと思われるので、より良いオプションはappendに彼らなりのように:

(append (foo target (first expression)) 
     (foo target (rest expression))) 

次の書き換えを考えてみましょう:

(define (foo obj expr) 
    (cond 
    [(null? expr) #f] 
    [(null? (rest expr)) '()] 
    [(pair? (first expr)) 
    (append (foo obj (first expr)) 
      (foo obj (rest expr)))] 
    [(equal? obj (first expr)) 
    (cons (second expr) 
      (foo obj (rest expr)))] 
    [else 
    (foo obj (rest expr))])) 

、あなたが持っているだろう:

(foo 'x '(x 10 x x 4)) 
=> '(10 x 4) 
(foo 'y '(y (3 y 5 y y 8 9) (10 y 12 13 y 15 y) 17)) 
=> '((3 y 5 y y 8 9) 5 y 8 12 15) 

はいますが、持っています:

(foo 'x '()) 
=> #f 
(foo 'x '(x)) 
=> '() 
+0

ありがとう、もう1つ、例題の1つは '(foo 'z' z)=>()'ですが、これをどのように追加できますか?現在、 'rest:contract violation expected:と(そして/ c list?(not/c空?)) given:z' –

+0

私は '[(not?list?expr) '()]'を追加しました。 –

+0

あなたは正しいです。これで、入力式がリストでないときは空のリストを出力します。これがあなたの最初の基本ケースとしてテストされるように、それを注文するようにしてください。 – assefamaru

関連する問題