2011-12-07 11 views
4

私はfoldlから壊す必要があります。ここで私は、この例では、人工的である知っているが、抜け出すための任意の素敵な方法がありますfoldlを壊す簡単な方法

L = [1,2,3,4,10,5,6,7], 

    Res = 
     try 
     lists:foldl(
      fun(I, Value) -> 
       if (I < 10) -> 
        Value + I; 
       true -> 
        throw({too_big_value, Value}) 
       end 
      end, 
      0, L) 
     catch 
     throw:{too_big_value, Value} -> Value 
     end, 

    Res. 

(すなわち10)私は、リスト内の値の合計を数える際倍から壊れ、あまりにも大きな値を満たすためにどのようにダミーの例ですフォールド(私は倍が常に構造全体をスキャンすることを知っています)?

私は折りたたみから壊れても正しいデータを取得する必要があることに注意してください。この場合、以前の反復からデータを取得する必要があります(これは私の例で行ったとおりです)。

+0

あなたは「私は倍から壊れた場合でも、正しいデータを取得する必要がある」とはどういう意味ですか?スローに加えられた変更を含むリストが必要ですか? – Isac

答えて

6

あなたはそれを正しくしています。関数がfunからの戻り値を見て、継続するかどうかを決定する場合、それはもはやfoldlではありません。

+0

あなたはある種の哲学的な質問に答えることができますか:「それが設計されていない間に折り目から壊れてもいいですか?より良い選択肢は何ですか:1)何かを創り出す(折りたたみを折る)2)コードを書く(再帰を行う)? – ravnur

+0

私はそれが大丈夫だと思います。 throw/catchはオーバーヘッドをほとんど必要としません(それぞれの関数アプリケーションの結果の一部としてcontinue-or-notフラグをとる対応するfold-like関数よりもはるかに少ない)、はっきりと読みやすく、共通のイディオムを使用しますあなた自身の再帰関数を書くのではなく)。 – RichardC

7

ただ好奇心が強い、ここではfoldlを使用している点は何ですか?中断する必要がある場合は、再帰を使用してください。foldlはそのために設計されていません。

main([]) -> 
    L = [1,2,3,4,5,10,6,7], 

    io:format("[~w]", [s(L, 0)]). 

s([], S) -> 
    S; 

s([H|T], S) -> 
    if (H < 10) -> 
    s(T, S + H); 
    true -> 
    S 
    end. 

更新:

別のオプションtakewhileを使用することです:

lists:foldl(fun(E, A) -> A + E end, 0, lists:takewhile(fun(E) -> E < 10 end, L)) 
+0

ご返信ありがとうございます。私はより読みやすいコードを得る方法を見つけようとしています。私はErlangの初心者です。私はそれを理解するために努力しています。私はあなたの第二の変種が私のものとあなたの最初のものより優れていると思います。 – ravnur

+0

@usrおそらく、第2の亜種だけが、(コンパイラがそれを最適化することができない限り)追加のメモリを使い果たしてしまいます。 –

+0

それは明らかです。時間と答えをありがとう! – ravnur

関連する問題