0

私はここで提起された問題を解決するためにClojureアルゴリズムに取り組んでいます:http ://spin.atomicobject.com/2011/05/31/use-clojure-to-move-drugs-a-programming-challenge/そして私はしゃっくりに遭遇しました。

私は再帰的アルゴリズムを使用して(おそらく最初は正しい選択ではありません)、値と重量の比率が最も高いものから最も低いものの順に並べられた「人形」構造体のベクトルを調べています。関連するコードは次のとおりです。

(defn get-carryable-dolls 
  [dolls carryable-dolls]
  (def doll (first dolls)) ;initializing for use in multiple places
  (def rest-dolls (rest dolls)) ;initializing for use in multiple places
  (
    if (will-fit? doll (get-weight-sum carryable-dolls)) 
    ( ;will fit
      (
        if 
        (= carryable-dolls {})
        (def new-doll-set [doll]) ;First trip, get rid of empty set by initializing new
        (def new-doll-set (flatten [doll carryable-dolls])) ;otherwise, flatten set into vector of structs
      )
      ;tests to see if we have any more dolls to test, and if so, recurses. Otherwise, should pass the resultant vector
      ;up the stack. it appears to be the "else" potion of this if statement that is giving me problems.
      (if (not= () rest-dolls) (get-carryable-dolls rest-dolls new-doll-set) (vec new-dolls))
    )
    ( ;will not fit
      ;gets the rest of the dolls, and sends them on without modifying the vector of structs
      ;it appears to be the "else" potion of this if statement that is giving me problems.
      (if (not= () rest-dolls) (get-carryable-dolls rest-dolls carryable-dolls) (vec carryable-dolls))
    )
  )
)

そのコードは正しく機能しています。returnable-dollsには​​、ソリューションとして返す人形構造体の目的のベクトルが含まれています。残念ながら、returnable-dollsベクトルを呼び出し位置に戻そうとすると、次のエラーが発生します。

CompilerException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector,compiling:(drugmover\tests.clj:83)

82-83行目:

(def empty-dolls {})
(def designated-dolls (get-carryable-dolls sorted-values empty-dolls))

コンパイラエラーの問題の原因が何であるかについて困惑しています。Clojureはスタックトレースよりも簡潔なエラーメッセージを好むようです(または、少なくともCloojのREPL機能はそうです)。それを修正します。誰か提案があれば、私はそれらに大いに感謝します!

前もって感謝します。

編集:

回答とコメントで提案された修正を使用してコードを変更し、進行中のフロー制御を説明するのに役立ついくつかのコメントを提供しました。うまくいけば、私の考えを説明することによって、誰かが私がどこで間違っているのかを私に教えてくれるでしょう。

4

3 に答える 3

4

次のコードには、他の回答やその他で既に受け取った提案のほとんどが組み込まれています。

  • 余分な (そして間違った) 括弧を取り除く
  • より慣用的な方法でコードをフォーマットする
  • ローカル名バインディングの代わりにloop/を使用しますletdef
  • seq空のリストをチェックするために使用します
  • carryable-dolls要素を追加する前に、空の seq の不要なチェックを削除します

あなたが持っている補助関数の定義がなければテストすることはできませんが(例will-fit?)、少なくともいくつかの問題を修正する必要があります(そしてコードをより読みやすい形式にする必要があります):

(defn get-carryable-dolls 
  [dolls carryable-dolls]
  (loop [doll (first dolls)
         rest-dolls (rest dolls)]
    (if (will-fit? doll (get-weight-sum carryable-dolls))
      (let [new-doll-set (if (seq carryable-dolls)
                           (cons doll carryable-dolls)
                           [doll])]
        (if (seq rest-dolls)
          (recur rest-dolls new-doll-set)
          (vec new-dolls)))
      (if (seq rest-dolls)
        (recur rest-dolls carryable-dolls)
        (vec carryable-dolls)))))

reduce以下は、標準関数を活用し、人形を結果に含める必要があるかどうかのコア決定ロジックを提供する関数を定義するコードの完全なリファクタリングです。

(defn add-if-fits [dolls doll]
  (if (will-fit? doll (get-weighted-sum dolls))
    (cons doll carryable-dolls)
    carryable-dolls))

(defn get-carryable-dolls [dolls carryable-dolls]
  (reduce add-if-fits carryable-dolls dolls))
于 2012-04-22T11:58:36.610 に答える
3

コードの周りに余分な括弧ifがあり、それがそのエラーの理由です:

以下のコードは、余分な括弧があるため、同じエラーを生成します (ベクトルを作成するために else 部分が呼び出された場合と同じ場合:

((vec {:a 10 :b 100}))

これを REPL で実行しようとすると、同じ例外が表示されます。

java.lang.IllegalArgumentException: Wrong number of args (0) passed to: PersistentVector (NO_SOURCE_FILE:0)
于 2012-04-22T05:49:00.570 に答える
3

このコードにはあまりにも多くの括弧があり、問題を引き起こしています。このようなエラーが目立ちやすくなるように、他の人が行うようにコードをフォーマットすることを強くお勧めします。あなたが何をしようとしているのかさえ推測できないので、スニペット全体を書き直すことはできませんが、関連することに注意する必要があります。構文ifは次のとおりです。

(if test then else)

これらのものを囲む余分な括弧は許可されていません。(if true 1 2)たとえば、は問題ありませんが、関数として(if (true) 1 2)呼び出そうとするとtrue、ブール値であるため失敗します。式をまとめて「グループ化」し、それらの副作用を評価する場合は(do expr1 expr2)、 ではなくが必要です(expr1 expr2)

于 2012-04-22T04:04:29.207 に答える