Julia: カスタム中置演算子

作成日 2016ĺš´06月17日  Âˇ  65コメント  Âˇ  ソース: JuliaLang/julia

カスタム中置演算子の構文の作成については、 https: //groups.google.com/forum/#!topic / julia -dev / FmvQ3Fj0hHsで説明されています。

..。

メモを追加するために編集: @johnmyleswhiteは、以下のコメントスレッドがバイクシェディングへの招待であると指摘しています。 本当に新しいものを追加する場合を除いて、新しいコメントは控えてください。 以下にいくつかの提案があり、「フーレイ」絵文字(爆発する円錐)でマークされています。 これらのアイコンを使用して、ディスカッションをスキップして提案を読むか、別の提案を見つけて「賛成」または「反対」に投票することができます。

このバグ全体に対する賛成/反対の賛成は、ジュリアがカスタムのインフィックスイディオムを持つべきだと思うかどうかについてです。 以下の特定のアイデアに対する賛成/反対の投票は、@ Glen-Oの最初のコメントに行く必要があります。 (バグが明らかになる前に、3つの反対票と1つの賛成票がありました。)

..。

最初の提案(歴史的関心のみ):

勝ったと思われる提案は次のとおりです。

    a |>op<| b #evaluates (in the short term) and parses (in the long term) to `op(a,b)`

この作業を行うには、必要な変更はわずかです。

  • <|の優先順位を、同じではなく、 |>の優先順位よりも高くします。
  • <|グループを左から右に作成します。
  • 関数を<|(a,b...)=(i...)->a(i...,b...)します。 (ディスカッションスレッドで指摘されているように、これにはスタンドアロンでの使用と、上記のイディオムでの使用があります)

オプション:

  • 適切な優先順位とグループ化を使用して、新しい関数>|(a...,b)=(i...)->b(a...,i...)と|<(a,b...)=a(b...)を作成します。

    • パイプは最初に評価を意味し、パイプは最後にそれを関数として維持しますが、>と<はどちらが関数であるかを示します。

  • 適切な優先順位とグループ化を使用して、新しい関数>>|(a...,b)=(i...)->b(i...,a...)と<<|(a,b...)=(i...)->a(b...,i...)を作成します。
  • 同義語を作成» 、 ⁍ 、および(/または) pipe for |> ; ÂŤ 、 ⁌ 、および(/または) rcurry for <| ; および(/または) lcurry for <<| ; 1文字の同義語が中置演算子として機能します。
  • 以下の最初のパーサー修正を行うベースに@infixマクロを作成します。

長期:

  • パーサーにa |>op<| bをop(a,b)に変更するように指示します。これにより、コードの実行時に余分なオーバーヘッドが発生せず、演算子を実際に中置位置で定義できます。 (これは、パーサーが現在バイナリa:bとターナリa:b:c異なる方法で処理する方法に似ています。最大限のカスタマイズ性を得るには、一致する同義語に対してこれを行う必要がありますが、一致しない同義語に対してはこれを行わないでください。 a |> b ÂŤ cは、引き続き2つの二項演算子として扱われます。)
  • 上記の定義の省略記号が余分な括弧なしで期待どおりに機能するように、コンマやスペースを理解するようにパーサーに教えます。

(https://github.com/JuliaLang/julia/issues/6946に関連)

parser speculative

最も参考になるコメント

ステファンは私より年上ではありません。

全てのコメント65件

julia-devスレッドを反映して、この提案に関するStefanの主なコメントを引用すると便利だと思います。

ここで期待を設定するためだけに、Julia1.0より前の「構文の革新」の方法はそれほど多くないと思います。 (私が考えることができる唯一の例外は、新しいf.(v)ベクトル化された呼び出し構文です。)任意の関数を中置演算子として動作させる何らかの方法があると便利かもしれませんが、それは言語の差し迫った問題ではありません。

ジュリア開発の歴史のかなりの部分に参加している人として、私は、構文的な変化よりも意味的な変化にエネルギーを集中する方が良いと思います。 Juliaが1.0に到達する前に、解決しなければならない非常に重要なセマンティック問題がたくさんあります。

特に、この機能の実装は、作成者だけが考える必要のある1回限りの違いではないことに注意してください。今後、自分の作業がこの機能とどのように相互作用するかを全員が考える必要があるため、この変更により、実際には長期的に増加します。パーサーで作業するすべての人の作業負荷。

johnmyleswhiteのコメントは、提案された「長期的な」パーサーの変更に関して非常に適切だと思います。 しかし、「マイナーチェンジ」と「オプション」のグループは、私が見る限り、かなり自己完結型で影響が少ないです。

つまり、この提案の最小バージョンを有効にするために必要なパーサーの変更には、通常の2項演算子の優先順位とグループ化のみが含まれ、他の場合は多かれ少なかれ日常的な変更です。 無関係なことに取り組んでいるパーサー開発者は、既存の多数の演算子すべての意味を追跡する必要があるのと同じように、これを追跡する必要はありません。

個人的には、この構文は非常に醜く、入力するのが難しいと思います。 しかし、私は、より一般的な中置構文があるとよいことに同意します。

これについて考える正しい方法は、構文のみの問題だと思います。必要なのは、中置構文でopを使用することです。したがって、それを取得するために他の関数や演算子を定義するのは簡単です。 言い換えれば、それはすべてパーサーで行われるべきです。

私は実際にこれのために|を再利用し、 a |op| bを使用することを検討します。 おそらく、一般的な中置構文は、ビット単位またはよりも重要です。 (ビット単位の演算子の再利用については前に説明しましたが、そのままでは構文が少し無駄に見えるようです。)

a f bは、配列連結およびマクロ呼び出し構文の外部で使用できます。

a f bは機能するかもしれませんが、かなり壊れやすいようです。 a^2 f b^2 f c^2が合法であるのに、 a f b cとa+2 f b+2 f c+2 $が合法ではない理由を誰かに説明しようとしていると想像してみてください。 (最後の1つは、優先順位がprec-timesであると想定していることを知っていますが、優先順位が何であっても、この一般的な種類のことは懸念事項です)。

a |op| bに関して:グーグルグループのスレッドで見ることができるように、最初は同様の提案、 a %op% bを好みました。 しかし、提案された|>と<|の良いところは、それぞれが2項演算子として個別に役立ち、自然に組み合わされて希望どおりに機能することです(つまり、適切な優先順位とグループ化が与えられます)。 )これは、既存のパーサーメカニズムを使用してこれを短期的に実装できることを意味します。したがって、上記のjohnmyleswhiteへの応答で述べたように、将来パーサー開発者にとって頭痛の種になることを回避できます。

したがって、私はa |op| bが好きで、確かにそれに反対することはありませんが、必要なパーサーの変更を単純化するために2つの異なる演算子を使用する方法を探す必要があると思います。 最大限の型付けを行い、 |が「ビット単位」ではなく「パイプ」を意味することに反対しない場合、 a |op\\ bまたはa |op& bどうでしょうか。

「パーサー開発者にとっての頭痛の種」は、考えられる最も低い懸念事項です。

「パーサー開発者にとっての頭痛の種」は、考えられる最も低い懸念事項です。

パーサー開発者として、私はこれに明確に同意します。

|>と<|はどちらも完全に優れた中置演算子ですが、他の2つの演算子を使用して一般的な演算子構文を実装するメリットはありません。 そして、その構文がどれほど冗長で魅力的でないかについては、さらに多くのことを言う必要があります。

他の2つの演算子を使用して一般的な演算子構文を実装するメリットはありません。

明確にするために、ここでの長期的なビジョンは、バイナリf <| y 、バイナリx |> f 、およびターナリx |> f <| zが存在することです。ここで、最初のものは単なる関数ですが、2番目のものは2つは、パーサーで変換として実装されます。

これが2つの通常の関数|>と<|を使用して実装できるという考えは、そのビジョンへの一時的な架け橋にすぎません。

そして、その構文がどれほど冗長で魅力的でないかについては、さらに多くのことを言う必要があります。

それは公正な点です。 |>と<|を|と&に置き換えてみませんか? 彼らは少しホッケー選手にとって少し不快かもしれませんが、ペアとしても個人としても意味があります。

このために|と&の両方を盗むことは、ASCIIの適切な割り当てではなく、多くの人が区切り文字を対称にすることを好むと思います。

他の理由でx |> f <| yの三項演算子が必要な場合は問題ありませんが、個別に検討する必要があると思います。 パーサーが|>を反転した<|に変換する必要があるかどうかはわかりません。 <のような他の同様の演算子は、そのようには機能しません。 しかし、それは別の問題でもあります。

両方を盗む| そして&これはASCIIの適切な割り当てではなく、多くの人が区切り文字を対称にすることを好むと思います。

わかった。

>と<は入力が難しいことを理解しています。 標準のキーボードでの対称性とタイピング性の観点から、最も簡単なのは&%や%&のようなものかもしれませんが、それはひどく醜いです。 /|と|/も検討する価値があるかもしれません。

..。

パーサーが|>を反転した<|に変換する必要があるかどうかわかりません

あなたは誤解していると思います。 a |> bはb(a)に解析する必要があります。 (特別な解析を行わないバージョンは((x,y)->y(x))(a,b)になります。これは同じことと評価されますが、オーバーヘッドが大きくなります。)

a |> bはb(a)に解析する必要があります

ああ、わかりました、わかりました。

どのキャラクターを何年も使うかについて、私たちは自転車に乗ることができたと思います。 私は@StefanKarpinski (これまでの会話で最も上級の人物として)が裁定を下すと信じています、そして私はそれで大丈夫でしょう。 たとえそれが私が反対したものであったとしても( a f bなど)。

何が魅力的かを確認するためのいくつかのオプションは次のとおりです。
a |>op<| b (現在の|>変更されません)
a |{ op }| b (多くの一般的なキーボードで同じシフト状態に近く、醜くはありません。スタンドアロンとしては少し奇妙です。)
a \| op |\ bまたはa /| op |/ bまたはそれらの組み合わせ
a $% op %$ b (比較的タイピング可能で、Rに触発されています。しかし、ちょっと醜いです。)
a |% op %| b
a |- op -| b
a |: op :| b
a | op \\ b
a | op ||| b
a op b

ステファンは私より年上ではありません。

自分を指名したように見えますが、BDFLはこの問題に力を注いでいます! ;)

a @op@ b ?

私の投票は、 \| 、 |\ 、 /| 、および|/の4つすべてを使用することだと思います。 評価のためにダウン、カリー化のためにアップ。 関数に向かってバー。 そう:
a \| f (またはf |/ a )-> f(a)
a /| f (またはf |\\ a )-> (b...)->f(a,b...)
f |\ b (またはb //| f )-> (a...)->f(a...,b)
したがって:
a \| f |\ b (またはa /| f |/ b )-> f(a,b)
a \| f |\ b |\ c (またはa /| b /| f |/ c )-> f(a,b,c)

おそらく|/を除いて、4つの主要な演算子のそれぞれはそれ自体で役に立ちます。 冗長性は確かに非Pythonicですが、論理的な整理はジュリアンだと思います。 そして実際問題として、入力しやすいと思われる中置イディオムのバージョンを使用できます。 どちらも同じように読みやすく、どちらかを学んだら自然に両方を理解できます。

明らかに、すべてのスラッシュを入れ替えた場合も同様に意味があります。そのため、上向きの矢印は評価用で、下向きの矢印はカリー化用です。

私はまだOnHighからの言葉を待っています(そしてそれが何を意味するのか推測するのに初心者の不器用さをお詫びします)。 しかし、このバイクシェッドより背の高い人が判決を下した場合、このバージョンまたは少なくとも2つの新しいシンボルを持つ他のバージョンについては、短期パッチ(関数を使用)および/または適切なパッチ(変換を使用)を作成できれば幸いです。

可能な限りBDFLを使用しないようにしています:)

いくつかの簡単なことに注意したいと思いました。

まず、提案されている表記法の他の利点(「スタンドアロン使用」)は、読みやすさを向上させる方法で、 <|を他のコンテキストで使用できることです。 たとえば、文字列の配列Aがあり、それらすべてを左側から10まで埋めたい場合は、 map(i->lpad(i,10),A)と記述する必要があります。 これは比較的読みにくいです。 この表記では、 map(lpad<|10,A)になります。これは、かなりクリーンであることに同意すると思います。

次に、この背後にある考え方は、表記法の一貫性を保つことです。 関数呼び出しの「修正」を接頭辞から接尾辞に変更するために存在する|>演算子がすでにあります。 これは表記法を拡張するだけです。

第三に、 a f bとして直接中置を使用する可能性には、より大きな問題があります。 a + bとa * bは同じ優先順位を持つ必要があります。これは、 +と*が関数名であり、システムが優先順位は可変です。 そうしないと、既存の中置演算子を別の方法で処理する必要があり、混乱を招く可能性があります。

たとえば、文字列の配列Aがあり、それらすべてを左側から10まで埋めたい場合は、 map(i->lpad(i,10),A)と記述する必要があります。 これは比較的読みにくいです。 この表記では、 map(lpad<|10,A)になります。これは、かなりクリーンであることに同意すると思います。

私は強く同意しません。 提案された構文は、ASCIIサラダであり、PerlとAPLの最悪の犯罪のいくつかに焦点を当てていますが、他の言語では前例がなく、何が起こっているのかをカジュアルな読者に教えてくれます。 現在の構文は数文字長くなっていますが(5?)、 i->exprがラムダ構文であることを知っている人なら誰でもわかります。これは大きく成長している言語のセットです。

+と*は関数名であるため、a + bとa * bは同じ優先順位を持つ必要があり、システムが可変の優先順位を持つことは不可能です。 そうしないと、既存の中置演算子を別の方法で処理する必要があり、混乱を招く可能性があります。

これは本当の問題ではないと思います。 a f b中置辞の優先順位を言うだけで、既存のすべての優先順位レベルも維持できます。 これが機能するのは、優先順位が関数の名前によって決定されるためです。 「+」と呼ばれる関数はすべて「+」の優先順位を持ちます。

はい、 1+2 in 1+2構文に対してすでにこれを行っていますが、問題はありません。

これは本当の問題ではないと思います。 afb infixの優先順位を言うだけで、既存のすべての優先順位レベルも維持できます。 これが機能するのは、優先順位が関数の名前によって決定されるためです。 「+」と呼ばれる関数はすべて「+」の優先順位を持ちます。

パーサーを作成して機能させるのが難しいという意味ではありませんでした。 つまり、一貫性の問題が発生するため、「既存のインフィックス演算子を別の方法で処理する必要があり、混乱を招く可能性があります」と言いました。 特に、 ¦と∥の概念はそれほど異なっていないように見えますが、一方は事前定義された中置演算子であり、もう一方はそうではないことを考慮してください。

私は強く同意しません。 提案された構文は、ASCIIサラダであり、PerlとAPLの最悪の犯罪のいくつかに焦点を当てていますが、他の言語では前例がなく、何が起こっているのかをカジュアルな読者に教えてくれます。 現在の構文は数文字長くなっていますが(5?)、i-> exprがラムダ構文であることを知っている人なら誰でもはっきりとわかります。これは、大きく成長している言語のセットです。

おそらく、私が言っていることをより明確にする必要があります。 この操作を「lpadby10」と表現できることは、 i->lpad(i,10)よりもはるかに明確であると言っています。 そして、私の見解では、 lpad<|10は、コンテキスト固有ではない形式で、それに到達できる最も近いものです。

私がどこから来たのかを説明すると役立つかもしれません。 私は数学者であり、数学物理学者です。何よりもまず、「ラムダ構文」はプログラミングの観点からは賢明ですが、プログラミングの経験が少ない人にとっては最も明確ではありません。 Juliaは、私が理解しているように、主に科学計算言語になることを目的としているため、MATLABと非常によく似ています。

私は尋ねなければなりません- lpad<|10は、たとえばx|>sin|>expよりも「ASCIIサラダ」はどうですか? しかし、 |>表記が追加されました。 たとえば、 |を使用して左側の引数を右側のコマンドに渡すbashスクリプトと比較してください。「パイプ」と呼ばれることがわかっている場合は、「パイプ」と呼ばれる方が理にかなっていますが、 'プログラミングに熟練していない、それは意味をなさないだろう。 その点で、 |>は漠然と矢印のように見えるので、実際にはもっと理にかなっています。 そして、 <|は表記法の自然な拡張です。

%func%など、他の言語での前例はありますが、その言語でのプログラミングの知識が豊富でない人にとっては完全に不透明な他の提案と比較してください。

念のために言っておきますが、以前の議論の1つを少し振り返ると、理論的には、別の言語で使用されている表記法が非常に優れていることがわかります。 Haskellはどうやらa |> b c dを使って$# b(a,c,d) #$を表しています。 関数名に続くスペースでこの方法で「パラメーター」を指定できる場合は、うまく機能します- map(lpad 10,A) 。 唯一の問題は単項演算子で発生します。たとえば、 map(+ 10,A)は、 i->+(i,10)ではなく "+ 10"で解釈されるため、エラーが発生します。

a f bの場合:優先順位の問題はGlen-Oが提案したほど悪くはないかもしれませんが、ユーザー定義の中置関数の優先順位が最も低い場合を除いて、それらは存在します。 言う、議論のために、私たちは彼らにprec-timesを与えます。 その場合、
a^2 f b^2 => f(a^2,b^2)
a+2 f b+2 => a+f(2,b)+2
a^2 f^2 b^2 => (f^2)(a^2,b^2)
a f+2 b =>構文エラー?

これはすべて、パーサーの記述方法の自然な結果であるため、その意味で特に頭痛の種ではありません。 しかし、このイディオムのカジュアルユーザーにとっては特に直感的ではありません。

カレーイディオムの有用性について
私はGlen-Oに同意します。 (i)->lpad(i,10)はlpad<|10 (または、選択した場合はlpad |\ 10など)よりも単純に悪いです。 iは、完全に無関係な認知的負担であり、潜在的なエラーの原因です。 実際、私がちょうど今それをタイプしていたとき、私は最初に意図せずに(i)->lpad(x,10)をタイプしたことを誓います。 だから、中置カレーをするのはいい考えだと思います。
ただし、それが意図されている場合は、どのような中置イディオムを使用しても、独自のカレー操作を作成できます。 a f bの場合は、 lpad rcurry 10のようなもので十分です。 重要なのは読みやすさであり、キーストロークではありません。 したがって、これは<|の弱い議論にすぎないと思います。

a |> b c d
私はこの提案がとても好きです。 |>がどちらかの側のスペースを受け入れるようにできると思うので、 a b |> f c d => f(a,b,c,d) 。

(注: a b |> f c dの提案とGlen-Oのmap(lpad 10,A)の両方の提案の場合、これはコーナーケースを作成します: (a b) |> f c d => f((x)->a(x,b),c,d) 。しかし、私はそれは許容できると思います。)

これには、演算子の優先順位に関してa f bと同様の問題があります。 しかし、どういうわけか、 との三項演算子の優先順位ではなく、演算子|>の優先順位の観点から少なくともそれらについて話すことができれば、それらはより許容できると思います 。

0.5でlpad.(["foo", "bar"], 10)を試してください。 既存の|>は、すべての人に完全に愛されているわけではありません。

@tkelman :問題はわかりましたが、あなたのポイントは何ですか? 用途を追加する前に、既存の|>を修正する必要があると思いますか? もしそうなら、どのように?

個人的には、既存の|>を取り除くべきだと思います。

0.5でlpad.(["foo", "bar"], 10)を試してください。 既存の|>は、すべての人に完全に愛されているわけではありません。

私はあなたがポイントを逃したと思います。 はい、 func.()表記は適切であり、状況によっては問題を回避します。 しかし、私はmap関数を簡単なデモンストレーションとして使用します。 関数を引数として取る関数はすべて、この設定の恩恵を受けます。 例として、純粋に私のポイントを示すために、いくつかの参照番号を使用した最小公倍数に基づいていくつかの番号を並べ替えることができます。 sort(A,by=i->lcm(i,10))またはsort(A,by=lcm 10)のどちらがすっきりと読みやすく見えますか?

もう一度、中置演算子を定義する方法を使用すると、Glen-Oが<|で実行したいことを実行する演算子を作成できるため、最悪の場合、彼はsort(A,by=lcm |> currywith 10)のようなものを記述できるようになります。 a ... f ... b => f(a,b)の作成方法について説明することです。 既存の|>または提案された<| $のどちらが価値のある演算子であるかは、その点と何らかの関係があることを理解していますが、あまりにも見過ごされないようにしましょう。

個人的には、 a |> b cの提案がこれまでで最高だと思います。 これはHaskellの既存の規則に従います。 これは、既存の|>演算子に論理的に関連しています。 それは、適度に読みやすく、適度に入力しやすいものです。 それが自然に他の用途にも及ぶと私が感じるという事実は二次的なものです。 同意できない場合は、提案されている二次的な使用法だけでなく、少なくともコアイディオムに対するあなたの気持ちを述べてください。

つまり、一貫性の問題が発生するため、「既存のインフィックス演算子を別の方法で処理する必要があり、混乱を招く可能性があります」と言いました。

a f bの優先順位を決めるのは難しいことに同意します。 たとえば、 in明らかに比較の優先順位の恩恵を受けますが、中置辞として使用される多くの関数は比較の優先順位を望まない可能性があります。 ただし、一貫性の問題は見られません。 演算子が異なれば、優先順位も異なります。 a f bを追加しても、 +と*に同じ優先順位が与えられることはありません。

|>は、比較に隣接してすでに優先されていることに注意してください。 他の優先順位については、率直に言って、括弧は問題ないと思います。

私に同意しない場合、およびa |> f bを使用している場合は、同様の演算子|+> 、 |*> 、および|^>が存在する可能性があります。 |>と同じように機能しましたが、中央の演算子が優先されました。 それはやり過ぎだと思いますが、それは可能性です。

優先順位の問題を解決する別の可能性は、 (a f b)などのある種の括弧を含むカスタム中置演算子の構文を使用することです。

関連するディスカッション: https ://github.com/JuliaLang/julia/issues/554、https: //github.com/JuliaLang/julia/issues/5571、https : //github.com/JuliaLang/julia/pull/14476 、 https://github.com/JuliaLang/julia/issues/11608 、およびhttps://github.com/JuliaLang/julia/issues/15612。

私は尋ねなければなりません-lpad <| 10は、たとえばx |> sin |> expよりも「ASCIIサラダ」はどうですか? しかし、|>表記が追加されました。

@tkelmanが主張していると思います

既存の|>を取り除く必要があります。

一部には、_both_ lpad<|10とx|>sin|>expがASCIIサラダ領域に参入したためです:)。

@toivohの(a f b)は、必須の括弧付きで、これまでのところ最良の提案だと思います。

https://github.com/JuliaLang/julia/issues/11608に関連しています(したがって、https://github.com/JuliaLang/julia/issues/4882およびhttps://github.com/JuliaLang/julia/pull / 14653): (a f b) => f(a,b)の場合、 (a <strong i="8">@m</strong> b) => (<strong i="10">@m</strong> a b)の場合は意味があります。 これにより、 y ~ a*x+bの既存の特殊なケースのマクロロジックを通常の(したがって、はるかに透過的な) (y @~ a*x+b)に置き換えることができます。

また、「必要な括弧」は、簡潔な中置定義の好ましいイディオムである可能性があります。 (愚かな例を使用するために) a + b = string(a) * string(b)と言う代わりに、(lintツールまたはコンパイラの警告によって) (a + b) = string(a) * string(b)と言うことをお勧めします。 これは実際には、中置に「必要な括弧」オプションを選択した直接的な結果ではないことを理解していますが、LHSで中置を使用している人々に誤って警告するが、それを実行している人々を解雇することができる便利なイディオムです。目的。

私の感じでは、現在、(プレフィックスではなく)関数のインフィックスを適用している場合、
その場合、それは演算子であり、演算子のように見え、動作する必要があります。

また、Unicodeを使用して定義された中置演算子をサポートしています。
https://github.com/JuliaLang/julia/issues/552以降

元の提案のようにキーワードを追加できるように、それを拡張しておくとよいと思います。
たとえば、 1 ⊕₂ 1 == 0
中置に任意の名前を付けることができるのは少し過剰に思えます。

オペレーターのように見え、動作する必要があります。

中置演算子には強力な命名規則が必要であることに同意します。 例:Unicodeの1文字、または前置詞で終わります。 ただし、これらは、コンパイラによって強制される要件ではなく、有機的に開発される規則である必要があります。 確かに、#552が話の終わりだとは思いません。 ハードコードされた演算子が数十ある場合、新機能のプロトタイピングのためだけであれば、プログラムでさらに追加する方法があるはずです。

..。

私にとって、 (a f b) (および(a <strong i="10">@m</strong> b) )の提案は、このバグの残りの提案よりも優れています。 パッチを作りたくなりそうです。

(a f b) => f(a,b)
(a f b c d) => f(a,b,c,d)
(a f) =>構文エラー
(a+2 f+2 b+2) => (f+2)(a+2,b+2)
(t1=a t2=f t3=b) => (t1=f)((t2=a),(t3=b)) (マクロの場合のように、スペースの優先順位は可能な限り低くなります)

..。

パッチを提出するのは不適切ですか?

私は最後の2つのケースを理解していませんでした:

(a+2 f+2 b+2)=>(f+2)(a+2,b+2)
(t1=a t2=f t3=b)=>(t1=f)((t2=a),(t3=b))

(a f b c d)の構文は非常に奇妙だと思います。 1 + 2 + 3は+(1,2,3)と書くことができるので、 f(a,b,c)を(a f b f c) $と書くべきではありませんか?

全体として、私は、ジュリアが現在許可されている以上のカスタム中置演算子をサポートする必要があると個人的には確信していません。

(a f b c d)には2つの問題があります。

まず、より複雑な表現を使用すると読みにくくなります。角かっこがイライラする理由の1つは、どの角かっこが他の角かっことどのかっことペアになっているのかが一目でわかりにくい場合があるためです。 そのため、そもそも中置および後置( |> )演算子が望ましいのです。 特に後置は、毎回角かっこを使わなくても、左から右にきれいに読むことができるので好まれています。

第二に、それはそれを要素的にするようなことをうまく行う方法を残しません。 私の理解では、 f.(a,b)は、 fをブロードキャストとの引数で要素ごとに動作させるために、0.5の表記になります。 (a f b)の場合、中置記法で同じことを行うための適切な方法はありません。 せいぜい、それは(a .f b)でなければならないでしょう、それは私の見解では.(が.+と.* $で提供する対称性の素晴らしさを失います。

たとえば、Haskellの例を使用したい場合を比較してください。 #6946のshashiは、ここで同等のポイントを作成しました。 Haskellでは、 circle 10 |> move 0 0 |> animate "scale" "ease"と書くでしょう。 この表記を使用すると、これは((circle(10) move 0 0) animate "scale" "ease")になります。これは、 animate(move(circle(10),0,0),"scale","ease")よりも明確ではありません。 また、 |>表記を使用して円を複数の場所にコピーする場合は、 circle 10 .|> copy [1 15 50] [3 14 25]を使用できます。 私の見解では、これがアイデアを実装するための最も簡単な方法です。そして、ブラケットは、操作の順序の問題を処理するという通常の役割を果たします。

そして、私が指摘したように、 a|>f b cには、同じ表記法をより多く使用できるようにする自然な拡張機能もあるという利点があります。 f b cは、「関数f with」として解析されます。パラメータbおよびcが設定されているため、 i->f(i,b,c)と同等になります。これにより、固定だけでなく、渡す必要のある他の状況でも機能します。パラメータを持つ関数(特に組み込み関数)(標準では関数のオブジェクトを最初に持つことに注意してください)。

|>は、どちらが関数であるかも明確にします。 たとえば、 (tissue wash fire dirty metal)がある場合、一見するとwashを関数として認識するのは非常に困難です。 一方、 tissue|>wash fire dirty metalには、「 washが関数です」という大きなインジケーターがあります。

最近の反対意見のいくつかは、「しかし、この機能を悪用する可能性があります!」と言っているように聞こえます。 私の答えは:もちろんできます。 必要に応じて、マクロを使用してまったく読めないコードを作成することもできます。 パーサーの仕事は、合法的な使用を可能にすることです。 虐待を防ぐために、慣用句や慣用句があり、場合によってはデリンターがあります。 具体的には:

私は最後の2つのケースを理解していませんでした:

これらは、従うべき例となることを意味するものではありません。 それらは、優先順位ルールの自然な結果を示しているだけです。 (a^2 ಠ_ಠ b^2) => ಠ_ಠ(a^2,b^2)は十分に明確ですが、最後の2つの例はどちらも構文を悪用していると見なされます。

f(a、b、c)を(afbfc)と書くべきではありません

私の(a f b c d)の提案は、率直に言って、後付けでした。 それは理にかなっていると思いますし、それが役立つ例を思いつくこともできますが、物議を醸すのであれば、この問題についてこの提案を止めたくありません。

[例えば:

  • fは、オブジェクトaの「オブジェクトメソッド」であり、おそらく複雑で、b、c、およびdを使用しており、おそらくより単純です。
  • fは、 push!のような「自然にブロードキャストされる」メソッドです]

(a f b f c)はfが+のようであれば意味がありますが、ほとんどの演算子は実際には+のようではないと思うので、私たちのモデルではありません。

もっと複雑な表現をすると読みづらくなります

繰り返しますが、私の答えは「だからそれを乱用しないでください」です。

f中置したa / (b + f(c,d^e))のような複雑な式を書く方法が必要だとします。 @toivohの提案では、それはa / (b + (c f d^e))になります。 Haskellのような使用法では、この1つの特定の例a / (b + c |> f d^e)を修正するために|>の優先順位が変更された場合、 a / (b + (c |> f d^e))または「最高」になります。 @toivohはここでも簡単に良いと思います。

(tissue wash fire dirty metal)

これに対する解決策は、中置演算子の強力な命名規則だと思います。 たとえば、中置演算子がUnicodeの1文字であるか、前置詞またはアンダースコアで終わるという規則がある場合、上記は(tissue wash_ fire dirty metal)のようになります。これは、その式が期待できることと同じくらい明確です。 。

..。

要素ごと

これは有効な懸念事項です。 (a .f b)は、 ((a.f) b)と読み取られる可能性があるため、お勧めできません。 私の最初の提案は(a ..f b)ですが、それは私をあまり幸せにしません。

circle 10 |> move 0 0 |> animate "scale" "ease"

私はjqueryを使用したことがあるので、そのような関数チェーンの利点を確実に理解しています。 しかし、それは中置演算子と同じ問題ではないと思います。 (a f b)の提案を使用すると、上記のように書くことができます。

circle 10 |> (move <| 0 0) |> (animate <| "scale" "ease")

...これはHaskellバージョンほど簡潔ではありませんが、それでもかなり読みやすいです。

たぶんそれは()内の3つだけに制限することができます:
(a f (b,c))
演算子.( $を使用して.(a f (b,c)) #$

最後に、一般的なポイントへの応答:

全体として、私は、ジュリアが現在許可されている以上のカスタム中置演算子をサポートする必要があると個人的には確信していません。

明らかに、私たち全員が私たちの意見を受け入れる権利があります。 (いいねがコメントのその部分を参照しているかどうかはわかりませんが、参照している場合は3倍になります。)

しかし、私の反論は次のとおりです。

  • ジュリアにはすでに数十の中置演算子があり、その多くは非常にニッチです。 より多くが提案されることは避けられません。 誰かが「どうすれば⅋を手に入れることができますが、$$ § $は手に入れることができませんか?」と言うとき、私は「次のバージョンが広く採用されるまで待つ」ではなく、「自分でやる」と答えたいと思います。
  • (a § b)のようなものは非常に読みやすく、構文は1つか2つの例から学ぶのに十分軽量です。
  • 私はこの問題を提起する最初の人ではありません、そして私は最後ではありません。 醜い機能を追加すると、後で修正することは基本的に不可能であるため、言語設計者は忍び寄る(誤った)機能に非常に懐疑的である必要があることを理解しています。 しかし、私が上で言ったように、私はあなたがそれを後悔しないように(a f b)は十分にきれいだと思います。

(a f b)明確さについてはよくわかりません

考えられるユースケースは次のとおりです。
select((((:emp_id, :last_name) from employee_tbl) where (:city, == ,'indianapolis')) orderby :emp_id));

これは確かに中置関数の実行可能な使用法です。
select関数は、恒等関数であるか、作成されたクエリをデータベースに送信します。

これは明確なコードですか?
わからない。

.(a f b)

はい、それは理にかなっています。 しかし、それはあまり読みにくいです。

(a @. f b)は読みやすくなっていますか? なぜなら、それを有効にするための@.マクロは単純なワンライナーになるからです。

[[[考えてみると、括弧を必要とせずに中置マクロを許可した場合、@ Glen-Oはそれらを使用して自分のやりたいことを実行できます: circle(10) @> move 0 0 @> animate "scale" "ease" => @> (@> circle(10) move 0 0) animate "scale" "ease" = macro> animate(move(circle(10),0,0),"scale","ease") 。 解決策は(a f b)よりも醜いと思いますが、少なくとも私の目にはこの全体的なバグを解決するでしょう。]]]

..。

select((((:emp_id, :last_name) from employee_tbl) where (:city, = ,'indianapolis')) orderby :emp_id);

条件式を奇妙に引用する必要がないように、私は間違いなく「where」にマクロを使用したいと思います。 そう:

select((((:emp_id, :last_name) from employee_tbl) <strong i="22">@where</strong> city == 'indianapolis') orderby :emp_id);

かっこはやや煩わしいですが、一方で、かっこなしでこの種の表現を処理するための合理的な方法はありません。

select((((:emp_id, :last_name) from employee_tbl) <strong i="6">@where</strong> city == 'indianapolis') orderby :emp_id);

かっこはやや煩わしいですが、一方で、かっこなしでこの種の表現を処理するための合理的な方法はありません。

考え直してみると、その式の優先順位は右から左です。 したがって、中置マクロを使用すると、次のようになります。

select((:emp_id, :last_name) <strong i="11">@from</strong> employee_tbl <strong i="12">@where</strong> city == 'NYC' <strong i="13">@orderby</strong> :emp_id)

あるいは:

<strong i="17">@select</strong> (:emp_id, :last_name) <strong i="18">@from</strong> employee_tbl <strong i="19">@where</strong> city == 'NYC' <strong i="20">@orderby</strong> :emp_id

ですから、私はまだ(a f b)が好きですが、中置マクロも良い答えであることがわかり始めています。

これが例による完全な提案であり、その後に長所と短所が続きます。

主な用途:

  • a <strong i="28">@m</strong> b => <strong i="30">@m</strong> a b
  • a <strong i="33">@m</strong> b c => <strong i="35">@m</strong> a b c
  • a <strong i="38">@m</strong> b <strong i="39">@m2</strong> c => <strong i="41">@m2</strong> (<strong i="42">@m</strong> a b) c
  • <strong i="45">@defineinfix</strong> f; a <strong i="46">@f</strong> b => macro f(a,b...) :(f($a,$b...)) end; <strong i="48">@f</strong> a b => f(a,b)

コーナーケース:(パーサーがどのように機能するかを示すためだけに、適切なコードを意図したものではありません)

  • t1=a <strong i="54">@m</strong> t2=b t3=c => <strong i="56">@m</strong> t1=a t2=b t3=c (これは良いプログラミングスタイルではありませんが)
  • t1 + a <strong i="59">@m</strong> t2 + b => <strong i="61">@m</strong> t1+a t2+b (これは良いプログラミングスタイルではありませんが)
  • a b <strong i="64">@m</strong> c =>構文エラー(??)
  • a <strong i="67">@m</strong> b [c,d] =>しないでください、しかし<strong i="70">@m</strong> a b[c,d] ETA:いいえ、パッチを使用すると、これは<strong i="72">@m</strong> a b ([c,d])として出力されます。これはおそらくより良いでしょう。)
  • a <strong i="75">@m</strong> b ([c,d]) => <strong i="77">@m</strong> a b ([c,d])
  • [a <strong i="80">@m</strong> b] =>スタイルが悪いので、かっこを使って明確にしてください。ただし、 [a (<strong i="83">@m</strong> b)] ??)
  • a @> f b => @> a f b => f(a,b)
  • <strong i="90">@outermacro</strong> a b <strong i="91">@m</strong> c d => <strong i="93">@outermacro</strong> a (<strong i="94">@m</strong> b c d)

利点:

  • 中置マクロを定義し、中置関数を無料で取得します(マクロ評価の1回限りのオーバーヘッドがあります。これは、パーサーマジックほどオーバーヘッドは低くありませんが、評価ごとに追加の関数呼び出しを行うよりもはるかに優れています)
  • 上記のSQLのような例に見られるように、強力なDSLにつながる可能性があります
  • ワンライナーマクロであるため、個別の|>演算子は不要です。 同様に、 <|と残りの@ Glen-Oの提案についても同様です。
  • (a f b)とは異なり、明示的で、偶然に使用されるリスクが非常に低い
  • 示されているように、 @defineinfixマクロを使用すると、マクロではなく関数を簡単に使用できます。

(マイナー)デメリット:

  • 優先順位とグループ化は、ほとんどの場合RtoLでうまく機能するようですが、括弧が必要な例外もあります。
  • a @> f b 、さらにa <strong i="112">@f</strong> bは、 (a f b)ほど読みにくいと思います(ただし、それほどひどいものではありません)。

このスレッドがどれほどアクティブになったかを考えると、このトピックに関する私の当初の懸念を人々に思い出させます。構文に関する問題は、多くの場合、大量のアクティビティを生成しますが、そのアクティビティの量は、通常、長期的な価値に比例しません。議論されている変更の。 これは主に、構文に関するスレッドが、好みに関する純粋な議論に近くなるためです。

その活動量は一般的に不均衡です

ごめんなさい。 私はおそらく行き来することで最も有罪です。

一方で、このスレッドは明らかに「使える」進歩を遂げたと思います。 最新の提案(a f b)または[ a @> f b 、ショートカットとして定義可能なa <strong i="10">@f</strong> b ]のいずれかは、 a %f% bやa |> f <| b 。

それでも、これ以上の前後のコメントはおそらくこれ以上進展しないと思います。本当に新しい提案がない限り、今後は賛成または反対の意見を使用することをお勧めします(つまり、既存の提案に対する正書法の変更だけではありません)。 「投票可能な提案」に「フーレイ」の絵文字(爆発する円錐形)を追加しました。 中置位置にある任意の関数に特化した構文を使用するべきではないと思われる場合は、バグ全体に反対票を投じてください。

..。

ETA:この議論は今やdecisionタグを取得するのに十分成熟していると思います。

参考までに(そして私は他の誰かがそれを指摘することを期待していました)。
SQLのような構文を埋め込みたい場合、その仕事に適したツールは非標準の文字列リテラルだと思います。
すべてのマクロと同様に、呼び出されたときにスコープ内のすべての変数にアクセスできます。
また、独自の優先度を選択して独自のDSLを指定でき、コンパイル時に実行されます。

select((((:emp_id, :last_name) from employee_tbl) where (:city, == ,"indianapolis")) orderby :emp_id));

書かれた方がいい

sql"SELECT emp_id, last_name FROM employee_tbl WHERE city == 'indianapolis' ORDER BY emp_id"

非標準の文字列リテラルは、非常に強力な構文です。
DSLの埋め込みに使用されている良い例は見つかりません。
しかし、彼らはそれを行うことができます。

そしてこの場合、結果は定義できるどの中置演算よりもはるかにクリーンだと思います。
ただし、独自のマイクロパーサー/トークンライザーを作成する必要があるというオーバーヘッドがあります。


決定タグの必要性は本当にわかりません。
これには、PRとしての実装も、使用可能なプロトタイプもありません。
それは人々がそれをテストすることを可能にします。
https://github.com/JuliaLang/julia/issues/5571#issuecomment -205754539とは対照的に、 8つの使用可能なプロトタイプがあります

スレッドを読むたびに、これに対する私の気持ちは上下します。 やってみるまでは本当にわからないと思います。 そして今、私はそれを何に使うのかさえ知りません。 (私がF#で使用した|>と<|のいくつかの定義とは異なります)

SQLのような構文で、このジョブに適したツールは非標準の文字列リテラルです。

SQLがNSLで最適に実行されるかどうかにかかわらず、インラインマクロが非常に役立つほど複雑なDSLのレベルがあると思いますが、独自のマイクロパーサー/トークンライザーを作成する価値があるほど複雑ではありません。

今は何に使うのかすらわかりません。 (私がF#で使用した|>と<|の定義のいくつかとは異なります)

インラインマクロの提案により、人々は、とりわけ、独自の|>のようなマクロまたは<|のようなマクロをロールできるようになるため、F#で行ったことすべてに使用できます。

(私は前後のバイクシェディングの議論に入りたくありませんが、とにかく以下の理由で応答していました、そしてインラインマクロの提案は1つの比較的滑らかな石で複数の鳥を殺すと思います。)

決定タグの必要性は本当にわかりません。

パーサーパッチを作成するのが適切かどうかを以前に尋ねましたが、誰も答えませんでした。 これまでのところ、それに関する唯一の言葉は次のとおりです。

Julia 1.0より前では、「構文の革新」の邪魔になるものはあまりないと思います。

それはただ座って少し腐敗するかもしれないので、これは今パッチを作ることに反対しているように思われるでしょう。 ただし、「PR [または]使用可能なプロトタイプとしての実装」がない限り、これについて決定する価値はないと言っています(今すぐ決定しないという決定を含む?)。

どういう意味ですか? (PRとは何ですか?)トークン@ $の代わりに文字'@'を使用したマクロが機能するので、 <strong i="22">@testinline</strong> a '@'f b => @f(a, b) ? または、julia-parser.scmにパッチを送信する必要がありますか? (私は実際にそのようなパッチの作成を最初に検討し始めました。それは単純なはずのように見えますが、私のスキームは非常に錆びています。)テストケースを作成する必要がありますか?

現在、このバグには13人の参加者がいます。 1つ以上の提案に投票したり、バグ自体に反対票を投じたりした人は合計5人いますが、インラインマクロ提案がテーブルに掲載された後、そのうちの1人(私)だけが投票しました。 それでは、まだプロトタイピングの時期だとは確信できません。 前回の真剣な提案以降に投票した人の数が参加者の半分に近いとき、ある種の大まかなコンセンサスが明らかになり、プロトタイプ作成、テスト、決定の時期になることを願っています(または場合によっては、アイデアをあきらめるかもしれません)。

「PR [または]使用可能なプロトタイプとしての実装」による。
私は遊ぶことができる何かを意味します。
それで、それが実際にどのように感じられるかを見ることができます。

PRはプルリクエストであるため、パッチはあなたが使用している用語です。

PRを作成した場合は、ダウンロードしてテストできます。
マクロで実装した場合はもっと簡単です
または非スターダード文字列リテラル、
ジュリアを作成せずにテストできます。

それは私の呼びかけではありませんが、私が遊ぶことができる何かなしで自分の意見を作るために私がベールになるとは思えません。

また、自転車の脱落を行ったり来たりしないように+1します。

...または、マクロと非標準の文字列リテラルを含むInfix.jlパッケージ。

この会話では、間違いなく「作業コードまたはGTFO」のポイントに到達しました。

OK、ここに動作するコードがあります: https ://github.com/jamesonquinn/JuliaParser.jl

ETA:特定のコミットを参照する必要がありますか、それとも最新のマスターへの上記のリンクで問題ありませんか?

..。

(これには、 |> 、 <| 、 ~ 、および@defineinfixに相当するものなど、必要な便利なマクロはありません。上記の例から~または|>演算子の現在は役に立たない特殊なケースのロジックを_deprecate_削除しません。これは、パーサーを変更するだけで機能します。基本的な機能をテストしましたが、すべてのコーナーケースではありません。

..。

~を使った現在の醜いハックは、この種のものの明確なユースケースがあることを示していると思います。 このパッチを使用すると、マクロの動作が必要なときに@~と言います。 特別な場合がなく、はるかにきれいです。 または、 ~が完全にユニークであり、誰もそれを二度とやりたくないと真剣に信じている人はいますか?

パッチ(ネイティブのブートストラップされたパーサーを対象としているため、まだPRではありませんが、今のところ、PRの観点から最初に来るスキーム)は、ここでの問題名よりも一般的に有用であることに注意してください。 問題名は「カスタム中置演算子」です。 パッチは中置マクロを提供し、中置演算子はその副作用としてのみ提供されます。

現状のパッチは重大な変更ではありませんが、これが計画になった場合、次のステップは現在存在する~と|>を非推奨にすることであり、最終的には重大な変更。

..。

いくつかの簡単なテストが追加されました。

11608は、私たちの多くが中置マクロを望まないというかなり明確なコンセンサスで締めくくられました。現在の~解析の1つのケースは間違いでした(Rの互換性のために早い段階で行われ、他の特に正当な理由はありません)。 私たちは非推奨になり、最終的にはそれを取り除くつもりですが、まだそれを行っていません(JuliaStatsパッケージの式インターフェースのAPIを変更する作業と一緒に)。

マクロは技術的に一般的ですが、入力引数は常にExpr 、 Symbol 、またはリテラルです。 したがって、関数(中置またはその他)のようにパッケージで定義された新しい型に実際に拡張することはできません。 中置マクロの考えられる使用例は、プレフィックス注釈付きマクロDSLまたは文字列リテラルによってより適切に提供されます。

(申し訳ありませんが、時期尚早に投稿しました。現在修正されています。)

#11608には、いくつかの否定的な議論があります。

===

次は何に変わりますか?
..。
y = 0.0 @in@ x == 1.0 ? 1 @in@ 2 : 3 @in@ 4

これはスレッドで扱われました:

そのような場合、私はいつも括弧を使用します...

と

同じ前例...マクロでなくても適用: 0.0 in 1 == 1.0 ? 2 in 2 : 3 in 4

===

人々が実装、維持、テスト、使用法を学ぶ必要があるジュリアへのより多くの機能など。

これは(部分的に)ここで答えられます(そして出向します):

「パーサー開発者にとっての頭痛の種」は、考えられる最も低い懸念事項です。

===

2つのパッケージが、単一のユーザーコードベースで明確に一緒に使用できる同じマクロ演算子の定義を同時に持つ方法はありませんか?

これは興味深い点です。 明らかに、マクロが関数を呼び出すだけの場合、関数のすべてのディスパッチ能力があります。 しかし、 ~のように、それが真のマクロである場合は、より複雑になります。 はい、それを関数として呼び出そうとしたり、エラーをキャッチしてマクロとして使用したりするなど、ハック的な回避策を想像することができます...しかし、それは一種の醜さを奨励するべきではありません。

それでも、これはどのマクロでも同じくらいの問題です。 2つのパッケージの両方がマクロをエクスポートする場合、「using」で両方を使用することはできません。

これは、中置マクロでより問題になる可能性がありますか? まあ、それは人々がそれらを何のために使うことになったのかによります:

  • ユーザー定義の中置関数を持つための単なる方法。 その場合、それらは他のどの機能よりも悪くはありません。 ディスパッチは正常に機能します。
  • 他のプログラミングスタイルを使用する方法として、@ Glen-Oが上記で説明した|>や<|などの演算子を使用します。 その場合、衝突の可能性がほとんどなく、マクロが何を意味するかについての一般的な慣習がすぐに発展すると思います。
  • 上記のSQLの例のように、特別な目的のDSLを作成する方法として。 これらは特定の状況で使用され、衝突の可能性はそれほど悪くないと思います。
  • Rぎ~のようなもののために。 最初は、これが最も問題があるように見えます。 Rでは、 ~はいくつかの異なる目的に使用されます。 ただし、それでも、次のように管理できると思います。

macro ~(a,b) :(~(:$a, quote($b))) end

次に、関数~はLHSのタイプに基づいてディスパッチできますが、RHSは常にExprになります。 この種のことにより、プリンシパルがR(回帰とグラフ化)で使用することを共存させることができます。つまり、異なるパッケージからのものであるにもかかわらず、正しくディスパッチすることができます。

(注:上記は編集されています。当初、 a ~ b + cのようなR式は、Rの遅延評価によってbとcのバインディングを使用していると思いましたが、そうではありません。 t; bおよびcは、明示的に渡されるデータフレーム内の列の名前であり、暗黙的に渡されるローカルスコープ内の変数の名前ではありません。)

===

ここで前進する唯一の方法は、実際の実装を開発することです。

私がやったこと。

===

マクロは技術的に一般的ですが、入力引数は常にExpr、Symbol、またはリテラルです。 したがって、関数(中置またはその他)のようにパッケージで定義された新しい型に実際に拡張することはできません。

これは上記の点に関連しています。 中置マクロが特定の関数を呼び出す限り、その関数は通常の方法でディスパッチすることで拡張できます。 特定の関数を呼び出さない限り、拡張または再定義してはならない構造的/構文的( |>が現在実行していることなど)を実行しています。 関数を呼び出したとしても、それがマクロであるという事実は依然として有用である可能性があることに注意してください。 たとえば、引数の一部を引用したり、それらをコールバックに処理したり、変数の名前やバインディングと同時に対話したりすることもできます。これは、直接の関数呼び出しでは不可能です。

===

中置マクロの考えられる使用例は、プレフィックス注釈付きマクロDSLまたは文字列リテラルによってより適切に提供されます。

参照されたスレッドで指摘されたように:

[中置辞は]私たちの言語がそのように機能するため、(英語とほとんどの西洋人の話者にとって)構文解析が簡単です。 (一般的に、同じことがオペレーターにも当てはまります。)

たとえば、これはより読み取り可能(および書き込み可能)です。

select((:emp_id, :last_name) <strong i="8">@from</strong> employee_tbl <strong i="9">@where</strong> city == 'NYC' <strong i="10">@orderby</strong> :emp_id)

また

send(orderby((<strong i="14">@where</strong> selectfrom((:emp_id, :last_name), employee_tbl) city == 'NYC'), :emp_id))

?

===

ついに:

11608はかなり明確なコンセンサスで締めくくられました

「誰が仕事をするのか」が決定票を投じて、私にはかなり均等に分かれているように見えます。 これは現在、少なくとも部分的に議論の余地があります。 私はJuliaParserで作業を行いましたが、このアイデアが気に入った場合は、Schemeで作業を行います。

ハッキングされたjuliaparserに肯定的な反応がない限り、これがこのスレッドの最後の投稿です。 私の意志を押し付けることは私の意図ではありません。 私の見解を示すためだけに。

私は中置マクロ( a <strong i="6">@m</strong> b => <strong i="8">@m</strong> a b )を支持すると主張しています。 それは私が反対の議論に気づいていないという意味ではありません。 これが私が反対する最良の議論を要約する方法です:

言語機能は-100から始まります。 それを克服できる可能性のある中置マクロは何を提供しますか? その性質上、プレフィックスマクロでは達成できなかったインフィックスマクロで達成できることは何もありません。

私の回答は次のとおりです。JuliaはまずSTEMプログラマー向けの言語です。 数学者、エンジニア、統計学者、物理学者、生物学者、機械学習者、化学者、計量経済学者...そして、それらの人々のほとんどが理解していることの1つは、優れた表記法の有用性です。 統計でよく知っている例を挙げると、独立確率変数を追加することは、PDFの畳み込み、またはCDFの畳み込み導関数と同等ですが、前者を使用して何かを表現することは、後者よりも桁違いに簡潔で理解しやすい場合があります。 。

中置対接頭辞対後置は、ある程度、好みの問題です。 しかし、多くの場合、中置を好む客観的な理由もあります。 接頭辞と接尾辞は、Forthプログラマーをドイツの政治家のように聞こえさせるものや、LispプログラマーをChomskian風刺画のように聞こえさせるもののように、連続した演算子の消化できない沈殿物につながりますが、中置辞は、演算子をしばしば認知的に最も多いものに置きます自然な場所、可能な限りすべてのオペランドに近い。 Forthで数学の論文を書く人がいないのには理由があり、ドイツの数学者でさえ方程式を書くときに中置演算子を使用するのには理由があります。

はい、難読化されたコードを書くために中置マクロを使用できます。 ただし、既存のプレフィックスマクロも同様に悪用される傾向があります。 悪用されない場合、中置マクロははるかに明確なコードにつながる可能性があります。

  • (a+b <strong i="18">@choose</strong> b)はbinomial(a+b,b) $を打ち負かします;
  • score ~ age + treatmentはlinearDependency(:score, :(age + treatment)) $を打ち負かします;
  • domSelect("#logo") @| css "color" "red" @| fadeIn "slow" <strong i="25">@thenApply</strong> addClass "dummy"はaddOneTimeEventListener(fadeIn(css(domSelect("#logo"),"color","red"),"slow"),"done",(obj,evt)->addClass(obj,"dummy"))から聖なる地獄を打ち負かします。

これらは単なるおもちゃの例だと思いますが、原則は正しいと思います。

上記は非標準の文字列リテラルで実行できますか? 2番目と3番目の例はNSLとして機能します。 ただし、NSLの問題は、自由度が高すぎることです。特定の文法に精通していない限り、NSLのトークンが何であるかを確認する方法はなく、操作の順序は言うまでもありません。 中置マクロを使用すると、上記のすべての例を実行するのに十分な自由がありますが、「適切な」コードを読んでトークンが何であるか、および暗黙の括弧がどこにあるかが明確でないほどではありません。

未知の未知から既知の未知に移すには、特定のものが必要です。 そして残念ながら、これを行うメカニズムはありません。 あなたの議論は存在しない構造を必要とします。

<|が右結合(#24153)になったので、最初のa |>op<| bプロポーザルは機能しますか?

https://github.com/JuliaLang/julia/pull/24404#issuecomment-341570934でStevenが言及したハックのパッケージを作成しました。

これが影響する潜在的な中置演算子の数はわかりませんが、 <~を使用したいと思います。 パーサーは連携しません。慎重に間隔を空けても、 a <~ bはa < (~b) $を意味します。

<-にも同様の問題があります。

これがすでにこの問題または別の問題でカバーされている場合は申し訳ありませんが、見つかりませんでした。

a < ~bにスペースが必要になる可能性があります。 以前にそのようなルールを追加しました。 次に、 <-と<~を中置演算子として追加できます。

@JeffBezansonに感謝します、それは素晴らしいことです! これは特別な場合ですか、それともより一般的なルールですか? より多くの中置演算子を許可し、明確で予測可能なコードを提供し、既存のコードをできるだけ壊さないようにするためのルールには、いくつかの詳細があると確信しています。 とにかく、私は助けと迅速な対応に感謝します。 明けましておめでとう!

a <~ bがa < ~bと異なる場合は、 a =+ 1をエラー(または少なくとも警告)として表示したいと思います。

私はこれがかなり古い議論であることを知っています、そして尋ねられた質問はかなり前に尋ねられました、しかし私はそれが答える価値があると思いました:

<|が右結合(#24153)になったので、最初のa |>op<| bプロポーザルは機能しますか?

いいえ、残念ながら、 |>が引き続き優先されます。 行われた更新により、 <|(a,b)=a(b)を定義すると、 a<|b<|c a(b(c)) $を取得できるようになります...しかし、これは別の概念です。

2年間凍結、2日前と5日前のコメントとコミット!

ドキュメントのカスタマイズ可能な二項演算子f45b6beを参照してください

このページは役に立ちましたか?
0 / 5 - 0 評価