Replies: 2 comments
|
私はSML#の実装の詳細を熟知しているわけではないので、私の理解が正しければ、という前置きがつきますが。SML#は再帰呼び出しの際にCスタックを使っており、Cスタックオーバーフローは普通は致命的なエラー(アプリケーションで捕捉ができず、クラッシュに直結するエラー)なので、SML#の設計上仕方がない、ということになるかと思います。 他のSML処理系(SML/NJ等)は再帰呼び出しに独自のスタックを使っている場合があり、そういう処理系ではすぐにクラッシュはせず、スタックオーバーフローの旨のエラーメッセージが出るかもしれません。 |
0 replies
|
minokiさま。 私個人は以前から関数型言語に少しばかり興味があり、先日、大型書店を訪れる機会があった際に、目に止まった「プログラミング言語 StandardML入門」を入手してしまいました。 私は仕事などでプログラミングしているわけではなく、興味本位でいろいろ試しているだけの万年素人です。(^^; |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
初めまして。当方、SML#だけでなく、プログラミング初級者ですので、ご容赦ください。
以下のスクリプトを実行してエラーが発生しました。そもそも私のスクリプトに間違いがあるのが原因ですが、SML#そのものがクラッシュしてしまいました。報告の必要があるのかどうかも判断できませんので、念の為、記します。外していたらすみません。以下、GEMINIとのやりとりです。
(私の質問)
次のスクリプトの定義・実行結果を確認して、エラーの原因を特定できますか
fun fib n = if n = 0 then 0
fib 0
fib 1;
val it = 1 : int
fib 2;
zsh: segmentation fault smlsharp
(GEMINI回答)
スクリプトの定義と実行結果を確認しました。fib 2; の実行でzsh: segmentation fault(セグメンテーション違反)が発生しているとのこと、これは$\text{SML#}$のコードに致命的な論理エラーがあり、**無限再帰(Infinite Recursion)**を引き起こしているのが原因です。
エラーの原因: 演算子の優先順位と無限再帰 💥
セグメンテーション違反は、通常、プログラムが利用可能なメモリ領域を超えてアクセスしようとしたり、$\text{REPL}$環境でスタックオーバーフローが発生したりしたときに起こります。今回の原因は、まさに無限に続く再帰呼び出しによるスタックの枯渇です。
問題の核心は、fib 関数の再帰ケースの定義にあります。
SML
else fib n-2 + fib n-1;
SML#では、**関数の適用(呼び出し)**は、加算・減算よりも高い優先順位を持ちます。
コンパイラの解釈 (誤った優先順位):
fib (n)−2+fib (n)−1
ではなく、
fib (n−2)+fib (n−1)
でもありません。
SML#の実際の解釈 (演算子の優先順位):
コンパイラはこれを以下のように解釈しています。
fib(n)−2+fib(n)−1
つまり、fib n の評価結果(int)から 2 を引こうとしています。
正確な解釈は、関数の引数が n−2 や n−1 ではなく、n そのものになっていることです。
fib(n)−2+fib(n)−1
2. 無限再帰の発生
この誤った解釈により、再帰呼び出しが引数 n の値を減らさずに行われています。
fib n を計算しようとすると、それは fib n−2+fib n−1 を計算しようとし、結果的に引数が n のままで自身を呼び出し続けてしまいます。
n=0 や n=1 に到達するパスがないため、再帰は終了せず、スタックが溢れてセグメンテーション違反となります。
修正案 ✅
再帰呼び出しの引数には、必ず括弧を付けて、演算子 − が減算ではなく関数の引数を構成するようにコンパイラに指示する必要があります。
修正後の正しい定義
SML
fun fib n = if n = 0 then 0
以上となります。
All reactions