0

内部の foldl 呼び出し内で x の値をインクリメントしようとしているときに問題が発生しました。x を渡された shiftValue と等しくし、内側の foldl 呼び出しで #" " または #"*" を見つけるたびにそれをインクリメントしようとしますが、返される x の値は渡されたときの shiftvalue と常に同じです。 .

この関数は (string, int) のタプルを受け取ります。文字列の先頭のスペースと切り捨てられたアスタリスクは、他の文字の前に置かれます。また、末尾に他の文字が続かないスペースやアスタリスクも切り捨てられます。渡される int は、この関数に渡される前に文字列がシフトされたスペースの数を追跡する shiftValue です。先頭のスペースまたはアスタリスクを外すたびに、shiftValue "x" を 1 ずつインクリメントする必要があります。

内側の foldl 呼び出しは、先頭からアスタリスクとスペースを削除します。外側の foldl 呼び出しは、それらを背面から削除します。アスタリスクとスペースは正しく削除され、x 値は更新されません。

(*Take string str and get rid of leading and following #"*"s and #" "s. For every 
leading #"*" or #" " removed increment the shiftValue returned in the tuple*)

fun trimStarsOnNode (str, shiftValue) =
    let 
        val x = shiftValue
    in
        ((implode(rev (foldl (fn (cur, a) => 
            if length a = 0 andalso cur = #"*" then a @ []
            else
                if length a = 0 andalso cur = #" " then a @ []
                else a @ [cur]) []  (rev (foldl (fn (cur, a) => 
                    if length a = 0 andalso cur = #"*" then (x = x + 1; a @ [])
                    else
                        if length a = 0 andalso cur = #" " then (x = x + 1; a @ [])
                        else a @ [cur]) [] (explode str)))))), x)
    end;

trimStarsOnNode ("***hello", 3);(* ("hello", 6) *) を出力する必要がありますが、出力します("hello", 3)

4

2 に答える 2

3

あなたの x を見てください - あなたの関数の始めに、あなたはします:

val x = shiftValue

次に、後でこれを実行しようとします。

x = x + 1

SML では、変数の値を変更できないことを思い出してください (実際には、SML では単に値と呼ばれているのはそのためです)。と をx = x + 1比較するだけなので、ステートメントの値は booleanです。xx + 1x = x + 1false

于 2013-06-30T16:47:40.027 に答える
1

Tayacan が言うように、SML では変数は可変ではありません。可変性が必要な場合は、参照型を使用する必要がありますが、通常は避けるのが最善であり、関数型スタイルに固執することをお勧めします。

lengthまた、リスト連結とすべての反復を使用しているため、関数が非常に非効率的 (O(n^2)) になることにも注意してください。また、文字列の途中にある星も削除されるため、これは正しくありません (そして、冗長にリスト全体をもう一度調べます)。最後に、ソリューションは複雑すぎます。

FWIW、これは私が考えることができる最短の実装で、Substringライブラリモジュールと関数合成演算子を使用していますo:

fun isStarOrSpace c = (c = #"*" orelse c = #" ")
val trimStars =
    let open Substring
    in string o dropl isStarOrSpace o dropr isStarOrSpace o full end

shiftValue何をすべきか理解できないので、これは your を使用しません。古い文字列サイズと新しい文字列サイズを比較することで、削除された文字数を簡単に計算できます。つまり、意図した関数 (IIUC) は、私のものの上に簡単に表現できます。

fun trimStarsOnNode(s, shift) =
    let val s' = trimStars s in (s', size s - size s' + shift) end

しかし、正直なところ、このバージョンが何の役に立つのかわかりません。

編集:左のドロップ数を返すバージョン:

fun trimStars s =
    let
        open Substring
        val ss = dropl isStarOrSpace (dropr isStarOrSpace (full s))
    in
        (string ss, #2(base ss))
    end
于 2013-06-30T17:55:04.220 に答える