2016-05-09 4 views
1

私はSMLを初めて使用しており、構文についても理解していません。リストを逆転させない標準的なMLのパリンドローム

私はリストを逆にすることなく回文をチェックすることを練習しています。ここに私のコードです

fun symmetric(i,n,inlist) = 
if List.nth(inlist,i-1) = List.nth(inlist,n-i) 
    then true 
else 
    false; 

fun palindrome(n, inlist) = 
let 
    val i = ref 1 
in 
    while !i < n do (
     if symmetric(!i,!n,!inlist) = false 
      then false 
     else() 
     i := !i + 1 
    ) 
    true 
end; 

私は楽しいパリンドロームでのみエラーが発生しましたが、自分で修正することはできません。

+3

"エラーが発生しました"有用なエラーの説明ですが、式は 'bool'(' false')型と 'unit'(') '型の両方を持つことはできません。あなたは命令的な考え方に悩まされているようです。参照を避け、ループの代わりに再帰を使用することを検討してください。 – molbdnilo

+0

ありがとうございます。そして今、私は回帰だけで回文を完成させました。私はちょうど数日間機能プログラミングを始めました。以前は、Java、Rubyなどの言語で作業していました。 MLでのプログラミングは私にとって非常に特別な経験です。 – WilsonHoHK

答えて

4

あなたもリストにあなたの文字列を変換せずに回文チェッカーを行うことができます。ここでは

fun palindrome s = 
    let fun check i j = 
      i >= j orelse 
      String.sub (s, i) = String.sub (s, j) andalso 
      check (i+1) (i-1) 
    in check 0 (String.size s - 1) end 

は、あなたのコードのいくつかのフィードバックです:

  1. 当然のことながら、むしろ反復よりも再帰を使用することを検討してください。

  2. 機能していないプログラマーの共通の問題は、多くのステートメントを副作用のためだけに連続して実行したがっているように思えることです。関数型プログラミングでは、の値に非常に頼ってプログラムの結果を導きます。そこはいえ、;オペレータであり、それはこのように使用することができます:

    fun palindrome s = 
        let val i = ref 0 
         val j = ref (String.size s - 1) 
         val result = ref true 
        in while !i < !j do 
          (if String.sub (s, !i) = String.sub (s, !j) 
          then (i := !i + 1 ; j := !j - 1) 
          else (i := !j ; result := false)) 
        ; !result 
        end 
    

    多くの場合、しかし、あなたが行に複数のものをしたい場合は、聞かせて、式は;と同じようにきちんとしていますオペレーター。

  3. 本当に

    と同じでさらに

    if A 
    then B 
    else false 
    

    に向上させることができる

    if A = false 
    then false 
    else B 
    

    if not (A) 
    then false 
    else B 
    

    のように書くことができるコード3210

    だから、道徳は、次のとおりです。

    1. 代わりのA = falsenot A書き込み(と代わりにA = trueのを、Aを書きます)。
    2. if ... then <true/false> else <true/false>は、いつでもandalsoorelseの組み合わせで置き換えることができます。つまり、結果のタイプがboolの場合は、のif-then-elseは必要ありません(しかし、ロジックが非常に畳み込まれている場合は、まだそれが望ましいかもしれません)。
3

リストを反転に対する制限が暗黙的にリストを逆rev内蔵ではなく、計算を使用して禁止することを意図していた場合は、ここでスタックベースのアプローチがあります。その考え方は、文字をスタック(リストとして表現)にプッシュし、それらをポップアウトして元の文字リストと照合することです。スタックまたは元のリストが最初に空の場合、またはポップされたアイテムが元のリストの対応する文字と一致しない場合 - それはプラレンドロームではありません

fun pushAll [] stack = stack 
| pushAll (x::xs) stack = pushAll xs (x::stack) 

fun popCheck [] [] = true 
| popCheck [] _ = false 
| popCheck _ [] = false 
| popCheck (x::xs) (y::ys) = x = y andalso popCheck xs ys 

fun palindrome s = 
    let val chars = explode s 
     val stack = pushAll chars [] 
    in 
     popCheck chars stack 
    end; 
関連する問題