2011-09-28 5 views
8

宿題の割り当てについては、「副作用」を導入せずにタスクを完了するよう指示されています。私はウィキペディアで「副作用」を調べましたが、理論的には「状態を変更するか、関数を呼び出す際に観察可能な相互作用がある」ということを意味しますが、具体的にはわかりません。OCaml:後で使用されるいくつかの値を格納することは "副作用"を導入するか?

たとえば、非コンパイル時の結果を保持する値を作成すると、副作用が発生しますか?

は(構文的に完璧ではないかもしれません)私が持っていたと言う:

val myList = (someFunction x y);; 
if List.exists ((=) 7) myList then true else false;; 

はこの副作用を紹介しませんか?おそらく私は、「状態を変える」ことが副作用の定義を意味するのか混乱していると思います。

+3

スタイルのヒント:「if式、true else else」パターンまたは他の同様のパターンは、初心者の間では非常に一般的です。それについて考えると、if部分を選択するには、式が真でなければならず、else部分についてはfalseでなければなりません。したがって、このパターンは削除して「式」に減らすことができます。 – LiKao

+0

そのコードを表示できますか?私は間違いなく初心者であり、いくつかの指針を用いることができます。 –

+0

確かに、それは非常に簡単です:if List.exists((=)7)myList then true true else ;; "あなたは単に "List.exists((=)7)myList ;;"と書くことができます。理由を考えるのをやめて、なぜこれら2つのステートメントが同じセマンティクスを持つのか、機能的な(そして一般的な)プログラミングについてたくさん学ぶでしょう。 – LiKao

答えて

8

いいえ;副作用とは、例えば、代入演算子:=を使用してセルをrefに変更するか、名前によって参照される値が時間とともに変化するその他のものを変更します。この場合、myListはプログラム中に決して変更されない不変の値であるため、効果がありません。

も参照してください

http://en.wikipedia.org/wiki/Referential_transparency_(computer_science)

+0

このリンクは、関数型プログラミングと副作用をよりよく理解するのに非常に役立ちます。 –

5

それについて考えるための良い方法は、「私は(後で再びこの同じ機能を実行しているを含む)、それ以降の任意のコードがこれまでにおそらく値I以外見ることができる何かを変更したあります戻ってきた?もしそうなら、それは副作用です。そうでなければ、あなたはそれがないことを知ることができます。

だから、のようなもの:それはちょうど整数vより1である新しい値を返すため

let inc_nosf v = v+1 

は副作用を持たないあなたはOCamlのトップレベルに次のコードを実行するのであれば、あなたが得ます。対応する結果:

# let x = 5;; 
val x : int = 5 
# inc_nosf x;; 
- : int = 6 
# x;; 
- : int = 5 

ご覧のとおり、xの値は変更されませんでした。戻り値を保存しなかったので、実際には何も増えませんでした。関数自体は、x自体ではなく戻り値を変更するだけです。だから、Xにそれを保存するために、私たちがしなければならないと思います。

# let x = inc_nosf x;; 
val x : int = 6 
# x;; 
- : int = 6 

inc_nosf関数は副作用を持たないので(つまり、それだけではない、他にすることによって、その戻り値を使用して外の世界と通信します変更)。

しかし、何かのように:それはrで表さ参照に格納された値が変更されるため

let inc_sf r = r := !r+1 

は副作用があります。あなたはトップレベルで同様のコードを実行するのであれば、あなたの代わりに、これを取得:

# let y = ref 5;; 
val y : int ref = {contents = 5} 
# inc_sf y;; 
- : unit =() 
# y;; 
- : int ref = {contents = 6} 

ので、このケースでは、我々はまだ、戻り値を保存していないにもかかわらず、それはとにかくインクリメントました。つまり、戻り値以外に変更があったはずです。この場合、その変更は:=を使用した割り当てで、refの格納値が変更されました。

Ocamlでは、ref、レコード、クラス、文字列、配列、およびハッシュテーブルの使用を避けると、副作用のリスクを避けることができます。 String.setやString.fillなどの関数を使用して文字列を修正しない限り、文字列リテラルを安全に使用できますが、基本的に、データ型を適切に変更できる関数は、副作用を引き起こします。

関連する問題