0

JavaScript では、

f = function(x) {
    return x + 1;
}
(5)

一見f後継関数を割り当てる必要があるように見えますが、実際には値 6 を割り当てます。これは、ラムダ式の後に括弧が続くと、パーサーによって後置式、具体的には関数呼び出しとして解釈されるためです。幸いなことに、これは簡単に修正できます。

f = function(x) {
    return x + 1;
};
(5)

期待どおりに動作します。

Python がラムダ式でブロックを許可した場合、同様の問題が発生します。

f = lambda(x):
    return x + 1
(5)

しかし今回はセミコロンがないので同じようには解けません。実際には、Pythonは複数行のラムダ式を許可しないことで問題を回避していますが、複数行のラムダ式やその他の式が必要なインデントベースの構文を使用する言語に取り組んでいるため、ブロックを回避する方法を見つけようとしています後置式の開始として解析します。これまでのところ、再帰降下パーサーの各レベルには、「このステートメントで既にブロックを食べているので、postfix を実行しないでください」という行に沿ったパラメーターが必要であると考えています。

この問題に遭遇した既存の言語はありますか? もしそうなら、どのように解決しますか?

4

2 に答える 2

1

Pythonにはセミコロンがあります。これは完全に有効です (見苦しく、推奨されませんが) Python コード: f = lambda(x): x + 1; (5).

ただし、それ以外の場合は標準の Python 構文での複数行のラムダには、他にも多くの問題があります。Python が式内のインデント (実際には一般的に空白) を処理する方法とは完全に互換性がありません。複数行のラムダに関する多数の python-ideas スレッドを読む必要があります。それは非常に難しいものから不可能なものまでのどこかです。

ラムダ内で任意に複雑な複合ステートメントが必要な場合は、すべてのステートメントを式にしたとしても、複数行の式に既存のルールを使用することはできません。式にブロックを含めることができるように、インデント処理を変更する必要があります (現在の動作については、言語リファレンスを参照してください)。これは、完全に優れた Python コードを壊さずに行うのは困難であり、多くの Python プログラマーがいくつかの点で悪いと考える言語になることは確かです: 理解するのが難しく、実装がより複雑で、いくつかのばかげたエラーを許すなど.

ほとんどの言語は、この正確な問題をまったく解決していません。ほとんどの候補 (Scala、Ruby、Lisp、およびこれら 3 つのバリアント) には、明示的なブロック終了トークンがあります。同じ問題を抱えている 2 つの言語を知っていますが、そのうちの 1 つ (Haskell) は別の回答で言及されています。また、Coffeescript は、ブロック終了トークンを使用せずにインデントを使用します。例の音訳を正しく解析します。ただし、これがどのように、またはなぜこれを行うのかについての仕様を見つけることができませんでした (パーサーのソース コードを掘り下げることはしません)。どちらも Python とは構文と設計哲学が大きく異なるため、それらの解決策は Python では (あったとしても) ほとんど役に立ちません。

于 2013-09-17T14:50:09.120 に答える
1

Haskell では、パーサーがレイアウトに依存するモードであると仮定すると、前のインデントと同じインデントで行を開始するたびに、暗黙のセミコロンがあります。

より具体的には、(レイアウトに依存する) ブロックの開始を通知するトークンが検出された後、最初のブロック項目の最初のトークンのインデント レベルが記憶されます。さらにインデントされた各行は、現在のブロック項目を継続します。同じようにインデントされた各行は新しいブロック項目を開始し、インデントが小さくなっている最初の行はブロックの閉鎖を意味します。

最後の例がどのように扱われるかf =は、ブロック内のブロック アイテムであるかどうかによって異なります。(5)そうである場合、後者は前者と同じようにインデントされるため、ラムダ式との間に暗黙のセミコロンがあります。そうでない場合、 は、(5)が含まれるブロック項目を継続するものとして扱われf =、ラムダ関数の引数になります。

詳細はこれより少し厄介です。Haskell 2010 レポートを見てください。

于 2013-09-17T11:46:18.700 に答える