Julia: مشغلي infix مخصص

تم إنشاؤها على ١٧ يونيو ٢٠١٦  ·  65تعليقات  ·  مصدر: JuliaLang/julia

هناك مناقشة على https://groups.google.com/forum/#!topic/julia -dev / FmvQ3Fj0hHs حول إنشاء بناء جملة لمشغلي Infix المخصص.

...

تم التعديل لإضافة ملاحظة: johnmyleswhite أشار إلى أن سلسلة التعليقات أدناه عبارة عن دعوة لحضور حفل زفاف. يرجى الامتناع عن التعليقات الجديدة ما لم يكن لديك شيء جديد لإضافته. هناك العديد من المقترحات أدناه ، تتميز برموز تعبيرية "الصيحة" (مخروط متفجر). يمكنك استخدام هذه الرموز لتخطي المناقشة وقراءة الاقتراحات فقط ، أو للعثور على المقترحات المختلفة حتى تتمكن من التصويت "رائعة" أو "رائعة".

تدور عمليات التصويت لأعلى / معارضة على هذا الخطأ ككل حول ما إذا كنت تعتقد أنه يجب أن يكون لدى Julia أي مصطلح مخصص لـ infix. يجب أن تنتقل عمليات التصويت لأعلى / لأسفل للفكرة المحددة أدناه في أول تعليق لـ @ Glen-O. (حصل الخطأ على 3 تصويتات معارِضة وتصويت واحد مؤيد قبل توضيح ذلك).

...

الاقتراح الأولي (الفائدة التاريخية فقط):

الاقتراح الذي يبدو أنه فاز هو:

    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 لـ |> ؛ « ، و (/ أو) rcurry مقابل <| ؛ و (/ أو) lcurry مقابل <<| ؛ مع المرادفات ذات الحرف الواحد التي تعمل كمعاملين infix.
  • إنشاء ماكرو @infix في القاعدة والذي يقوم بإصلاح المحلل اللغوي الأول أدناه.

طويل الأمد:

  • قم بتعليم المحلل اللغوي تغيير a |>op<| b إلى op(a,b) ، لذلك لا توجد نفقات إضافية عند تشغيل الكود ، وبالتالي يمكن تعريف المشغلين بالفعل في موضع infix. (هذا مشابه للطريقة التي يتعامل بها المحلل اللغوي حاليًا مع الثنائي a:b والثالث a:b:c بشكل مختلف. للحصول على أقصى قدر من التخصيص ، يجب أن يقوم بذلك مع المرادفات المتطابقة ، ولكن ليس للمرادفات غير المتطابقة ، لذلك على سبيل المثال لا يزال يتم التعامل مع a |> b « c كمعاملين ثنائيين.)
  • تعليم المحلل اللغوي فهم الفواصل و / أو المسافات بحيث تعمل علامات الحذف في التعريفات أعلاه كما هو متوقع بدون أقواس إضافية.

(يتعلق بـ https://github.com/JuliaLang/julia/issues/6946)

parser speculative

التعليق الأكثر فائدة

ستيفان ليس أكبر مني.

ال 65 كومينتر

بترديدًا لخيط julia-dev ، أعتقد أنه سيكون من المفيد اقتباس تعليق ستيفان الرئيسي على هذا الاقتراح:

فقط لوضع التوقعات هنا ، لا أعتقد أنه سيكون هناك الكثير في طريق "الابتكار النحوي" قبل Julia 1.0. (الاستثناء الوحيد الذي يمكنني التفكير فيه هو بناء جملة الاتصال المتجه الجديد f.(v) .) في حين أن وجود طريقة ما لجعل الوظائف التعسفية تتصرف مثل مشغلي infix قد يكون أمرًا رائعًا ، إلا أنها ليست مشكلة ملحة في اللغة.

بصفتي شخصًا شارك في جزء كبير من تاريخ تطور جوليا ، أعتقد أنه سيكون من الأفضل تركيز الطاقة على التغييرات الدلالية بدلاً من التغييرات النحوية. هناك الكثير من المسائل الدلالية بالغة الأهمية التي بقيت لحلها قبل أن تصل جوليا إلى 1.0.

لاحظ على وجه الخصوص أن تنفيذ هذه الميزة ليس مجرد فرق لمرة واحدة يحتاج المؤلف فقط للتفكير فيه: سيتعين على الجميع التفكير في كيفية تفاعل عملهم مع هذه الميزة من الآن فصاعدًا ، وبالتالي فإن التغيير يزيد فعليًا على المدى الطويل عبء العمل لكل شخص يعمل في المحلل اللغوي.

أعتقد أن تعليقات johnmyleswhite مناسبة جدًا فيما يتعلق بتغييرات التحليل اللغوي "طويلة المدى" المقترحة. لكن مجموعتي "التغييرات الطفيفة" و "الاختيارية" ، بقدر ما أستطيع أن أرى ، إلى حد كبير قائمة بذاتها وقليلة التأثير.

أي: تغييرات المحلل اللغوي اللازمة لتمكين الإصدار الأدنى من هذا الاقتراح تتضمن الأسبقية والتجميع فقط للمشغلين الثنائيين العاديين ، وهو نوع التغييرات التي تكون روتينية إلى حد ما في حالات أخرى. لن يحتاج مطور محلل يعمل على شيء غير ذي صلة إلى تتبع ذلك أكثر مما يحتاج إلى تتبع معنى جميع المشغلين العديدين الموجودين بالفعل.

أنا شخصياً أجد أن بناء الجملة هذا قبيح للغاية ويصعب كتابته. لكنني أوافق على أنه سيكون من الجيد أن يكون لديك المزيد من البنية العامة للإنفكس.

أعتقد أن الطريقة الصحيحة للتفكير في هذا هي مسألة بناء الجملة فقط: ما تريده هو استخدام op مع بنية infix ، لذا فإن تحديد الوظائف والمشغلين الآخرين للحصول على ذلك هو الالتفاف. بمعنى آخر ، يجب أن يتم كل ذلك في المحلل اللغوي.

سأفكر بالفعل في استرداد | لهذا ، واستخدام a |op| b . يمكن القول إن بناء جملة infix العام أكثر أهمية من bitwise أو. (لقد تحدثنا من قبل عن استصلاح عوامل البت من قبل ؛ تبدو بالفعل وكأنها مضيعة لقواعد النحو كما هي).

يتوفر 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 ليسوا كذلك. (أعلم أن هذا الأخير يفترض أن الأسبقية هي أوقات سابقة ، ولكن بغض النظر عن الأسبقية ، فإن هذا النوع العام من الأشياء هو مصدر قلق).

بالنسبة إلى a |op| b : في البداية فضلت عرضًا مشابهًا ، a %op% b ، كما ترون في سلسلة مجموعات Google. لكن الشيء الجميل في |> و <| المقترحين هو أن كل منهما مفيد بشكل فردي كمعاملين ثنائيين ، ويتحدون بشكل طبيعي للعمل حسب الرغبة (بالنظر إلى الأسبقية والتجميع الصحيحين ، أي. ) هذا يعني أنه يمكنك تنفيذ ذلك على المدى القصير باستخدام آليات المحلل اللغوي الحالية ، وبالتالي تجنب خلق مشكلات لمطوري المحلل اللغوي في المستقبل ، كما قلت في ردي على johnmyleswhite أعلاه.

لذا بينما أحب a |op| b وبالتأكيد لن أعارضه ، أعتقد أننا يجب أن نبحث عن طريقة لامتلاك عاملين مختلفين لتبسيط تغييرات المحلل اللغوي المطلوبة. إذا أردنا تحقيق أقصى قدر من القابلية للكتابة ولم نعارض استخدام | يعني "الأنبوب" بدلاً من "bitwise أو" ، فماذا عن a |op\\ b أو a |op& b ؟

"الصداع للمطورين المحلل اللغوي" هو أقل مصدر قلق ممكن.

"الصداع للمطورين المحلل اللغوي" هو أقل مصدر قلق ممكن.

بصفتي مطورًا محللًا ، فأنا أتفق مع هذا بشكل قاطع.

|> و <| كلاهما عاملان أساسيان جيدان تمامًا ، ولكن لا فائدة من تنفيذ بناء جملة المشغل العام باستخدام عاملين آخرين. وهناك الكثير مما يجب قوله حول مدى استطالة هذه التركيبة وعدم جاذبيتها.

لا فائدة من تنفيذ بناء جملة المشغل العام باستخدام عاملين آخرين.

لكي نكون واضحين ، فإن الرؤية طويلة المدى هنا هي أنه سيكون هناك ثنائي f <| y ، وثنائي x |> f ، وثلاثي x |> f <| z ، حيث تكون الأولى مجرد وظيفة ولكن الثانية اثنان يتم تنفيذها كتحويلات في المحلل اللغوي.

فكرة أن هذا يمكن تنفيذه باستخدام وظيفتين عاديتين |> و <| هي مجرد جسر مؤقت لتلك الرؤية.

وهناك الكثير مما يجب قوله حول مدى استطالة هذه التركيبة وعدم جاذبيتها.

هذه نقطة عادلة. ماذا عن استبدال |> و <| بـ | و & ؟ إنها منطقية كزوج وفردي ، على الرغم من أنها قد تكون متنافرة بعض الشيء مع لاعب هوكي قليلاً.

سرقة كل من | و & لهذا لن يكون تخصيصًا جيدًا لـ ASCII ، وأظن أن الكثيرين يفضلون أن تكون المحددات متماثلة.

إذا كان الناس يريدون عامل تشغيل ثلاثي x |> f <| y لأسباب أخرى ، فلا بأس بذلك ، لكنني أعتقد أنه يجب النظر إليه بشكل منفصل. لست متأكدًا من أن المحلل اللغوي يجب أن يحول |> إلى <| . لا يعمل المشغلون الآخرون المشابهون مثل < بهذه الطريقة. لكن هذه أيضًا قضية منفصلة.

سرقة كلا | و & لهذا لن يكون تخصيصًا جيدًا لـ ASCII ، وأظن أن الكثيرين يفضلون أن تكون المحددات متماثلة.

موافق.

أدرك أنه من الصعب كتابة > و < . من حيث التماثل وقابلية الكتابة على لوحة مفاتيح قياسية ، أعتقد أن الأسهل قد يكون شيئًا مثل &% و %& ، لكن هذا قبيح جدًا ، R موازي أو لا. قد يكون من المفيد أيضًا التفكير في /| و |/ .

...

لست متأكدًا من أن المحلل اللغوي يجب أن يتحول |> إلى <| مقلوب

أعتقد أنك أسأت الفهم. 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)

كل من المشغلين الرئيسيين الأربعة ، ربما باستثناء |/ ، مفيد في حد ذاته. من المؤكد أن التكرار سيكون غير بايثوني ، لكنني أعتقد أن الدقة المنطقية هي جوليان. وكمسألة عملية ، يمكنك استخدام أي إصدار من لغة infix تجد أنه من الأسهل كتابته ؛ كلاهما مقروءان بشكل متساوٍ ، فبمجرد أن تتعلم أحدهما فإنك تفهم كليهما بشكل طبيعي.

من الواضح أنه سيكون منطقيًا إذا قمت بتبديل جميع الشرطات المائلة ، بحيث تكون الأسهم لأعلى للتقييم ولأسفل للكي.

ما زلت أنتظر كلمة من On High (وأنا أعتذر عن حماقي المبتدئ في تخمين ما يعنيه ذلك). ولكن إذا أصدر أي شخص أطول من هذا الدراج قرارًا ، لهذا أو أي نسخة أخرى برمزين جديدين على الأقل ، فسأكون سعيدًا بكتابة رقعة قصيرة المدى (باستخدام الوظائف) و / أو تصحيحًا مناسبًا (باستخدام التحولات).

نحاول تجنب وجود BDFL إلى أقصى حد ممكن :)

لقد ظننت أنني سألاحظ بعض الأشياء السريعة.

أولاً ، الميزة الأخرى ("الاستخدامات المستقلة") للتدوين الذي يتم اقتراحه هي أنه يمكن استخدام <| في سياقات أخرى ، بطريقة تُحسِّن إمكانية القراءة. على سبيل المثال ، إذا كان لديك مصفوفة من السلاسل ، A ، وتريد حشوها كلها على اليسار حتى 10 ، الآن ، عليك كتابة map(i->lpad(i,10),A) . هذا صعب نسبيا للقراءة. مع هذا الترميز ، يصبح map(lpad<|10,A) ، وهو ما أعتقد أنك ستوافق عليه بشكل أكثر نظافة.

ثانيًا ، الفكرة من وراء ذلك هي الحفاظ على اتساق الرموز. يوجد بالفعل عامل تشغيل |> موجود لتغيير "إصلاح" استدعاء دالة من البادئة إلى postfix. هذا فقط يوسع التدوين.

ثالثًا ، هناك مشكلة أكبر في إمكانية استخدام infix المباشر كـ a f b . سينتهي الأمر بأن يكون لكل من a + b و a * b نفس الأسبقية ، نظرًا لأن + و * هي أسماء وظائف ، وسيكون من غير المجدي بالنسبة للنظام أن لها أسبقية متغيرة. هذا ، أو سيتعين عليه التعامل مع مشغلي infix الحاليين بشكل مختلف ، مما قد يتسبب في حدوث ارتباك.

على سبيل المثال ، إذا كان لديك مصفوفة من السلاسل ، A ، وتريد حشوها كلها على اليسار حتى 10 ، الآن ، عليك كتابة map(i->lpad(i,10),A) . هذا صعب نسبيا للقراءة. مع هذا الترميز ، يصبح map(lpad<|10,A) ، والذي أعتقد أنك ستوافق عليه أنه أكثر نظافة.

أنا بالتأكيد لا أوافق. الصيغة المقترحة هي - اغفر لي - سلطة ASCII ، التي تقترب من بعض أسوأ مخالفات Perl و APL ، دون سابقة في لغات أخرى لإعطاء القارئ العادي فكرة عما يحدث. التركيب اللغوي الحالي ، بالرغم من وجود بضعة أحرف أطول (خمسة؟) ، واضح تمامًا لأي شخص يعرف أن i->expr هو بناء جملة lambda - وهو موجود في مجموعة كبيرة ومتنامية من اللغات.

سينتهي الأمر بأن يكون لكل من a + b و a * b نفس الأسبقية ، نظرًا لأن + و * أسماء وظيفية ، وسيكون من غير المجدي أن يكون للنظام أسبقية متغيرة. هذا ، أو سيتعين عليه التعامل مع مشغلي infix الحاليين بشكل مختلف ، مما قد يتسبب في حدوث ارتباك.

لا أعتقد أن هذه مشكلة حقيقية ؛ يمكننا فقط تحديد أسبقية a f b infix ، والاحتفاظ بجميع مستويات الأسبقية الحالية أيضًا. يعمل هذا لأنه يتم تحديد الأسبقية من خلال اسم الوظيفة ؛ أي دالة تسمى "+" سيكون لها الأسبقية "+".

نعم ، لقد فعلنا ذلك بالفعل لبناء جملة 1+2 in 1+2 ، ولم تكن هذه مشكلة.

لا أعتقد أن هذه مشكلة حقيقية ؛ يمكننا فقط أن نقول ما هي أسبقية afb infix ، والاحتفاظ بجميع مستويات الأسبقية الموجودة أيضًا. يعمل هذا لأنه يتم تحديد الأسبقية من خلال اسم الوظيفة ؛ أي دالة تسمى "+" سيكون لها الأسبقية "+".

لم أقصد أنه من الصعب كتابة المحلل اللغوي لجعله يعمل. كنت أعني أنه يؤدي إلى مشكلات الاتساق ، ومن ثم أقول "أو سيتعين عليه التعامل مع مشغلي infix الحاليين بشكل مختلف ، مما قد يتسبب في حدوث ارتباك". من بين أشياء أخرى ، ضع في اعتبارك أن ¦ و لا يبدوان مختلفين تمامًا في المفهوم ، ومع ذلك فإن أحدهما هو عامل infix محدد مسبقًا ، بينما الآخر ليس كذلك.

أنا بالتأكيد لا أوافق. الصيغة المقترحة هي - اغفر لي - سلطة ASCII ، التي تقترب من بعض أسوأ مخالفات Perl و APL ، دون سابقة في لغات أخرى لإعطاء القارئ العادي فكرة عما يحدث. التركيب اللغوي الحالي ، بالرغم من وجود بضعة أحرف أطول (خمسة؟) ، واضح جدًا لأي شخص يعرف أن i-> expr هي صيغة lambda - وهي موجودة في مجموعة كبيرة ومتنامية من اللغات.

ربما يجب أن أكون أكثر وضوحًا فيما أقوله. أنا أقول إن القدرة على وصف العملية بأنها "lpad by 10" أوضح كثيرًا مما يجعله i->lpad(i,10) . ومن وجهة نظري ، فإن lpad<|10 هو أقرب ما يمكنك الوصول إليه ، في شكل غير محدد السياق.

ربما سيكون من المفيد لو وصفت من أين أتيت. أنا عالم رياضيات وفيزيائي رياضي ، أولاً وقبل كل شيء ، و "بناء جملة لامدا" ، رغم أنه معقول من وجهة نظر البرمجة ، إلا أنه ليس أوضح لمن هم أقل خبرة في البرمجة. تهدف جوليا ، كما أفهمها ، في المقام الأول إلى أن تكون لغة حوسبة علمية ، ومن ثم فإن التشابه القوي مع MATLAB.

يجب أن أسأل - كيف يكون lpad<|10 أي "سلطة ASCII" أكثر من ، على سبيل المثال ، x|>sin|>exp ؟ ومع ذلك ، تمت إضافة الترميز |> . قارن مع ، على سبيل المثال ، البرمجة النصية bash ، حيث يتم استخدام | لتمرير الوسيطة الموجودة على اليسار إلى الأمر الموجود على اليمين - إذا كنت تعلم أن هذا يسمى "pipe" ، فإنه يجعل _little_ أكثر منطقية ، ولكن إذا كنت لست ماهرًا في البرمجة ، فلن يكون ذلك منطقيًا. في هذا الصدد ، فإن |> أكثر منطقية ، حيث يبدو بشكل غامض مثل السهم. ثم يعد <| امتدادًا طبيعيًا للترميز.

قارن مع بعض الاقتراحات الأخرى ، مثل %func% ، والتي _فعلها_ لها سابقة في لغة أخرى ، ولكنها مبهمة تمامًا للأشخاص الذين ليس لديهم معرفة واسعة بالبرمجة في اللغة.

ضع في اعتبارك ، لقد نظرت إلى الوراء قليلاً في إحدى المناقشات القديمة ، وأرى أن هناك تدوينًا مستخدَمًا في لغة أخرى سيكون لطيفًا جدًا ، من الناحية النظرية. يبدو أن هاسكل تستخدم a |> b c d لتمثيل b(a,c,d) . إذا سمحت لك المسافات التي تلي اسم الوظيفة بتحديد "معلمات" بهذه الطريقة ، فستعمل بشكل جيد - map(lpad 10,A) . المشكلة الوحيدة التي تنشأ مع العوامل الأحادية - map(+ 10,A) قد ينتج عنها خطأ ، على سبيل المثال ، كما هو الحال عند "+10" بدلاً من i->+(i,10) .

في a f b : قد لا تكون مشكلات الأسبقية بالسوء الذي اقترحه Glen-O ، ولكن ما لم تكن وظائف infix التي يحددها المستخدم لها أدنى أسبقية ، فهي موجودة. قل ، من أجل الجدل ، نعطيهم أوقاتًا مسبقة. في هذه الحالة،
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) مبدئيًا عن غير قصد. لذا ، فإن إجراء عملية إنفكس كاري تبدو لي فكرة جيدة.
ومع ذلك ، إذا كانت هذه هي النية ، فبغض النظر عن لغة Infix التي نستقر عليها ، يمكننا إنشاء عملية الكاري الخاصة بنا. إذا كان 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 . ولكن بطريقة ما أعتقد أنهم أكثر قابلية للتحمل إذا كان بإمكانك التحدث عنها على الأقل من حيث أسبقية عامل التشغيل |> ، بدلاً من أن تكون أسبقية المشغل الثلاثي مع .

جرب lpad.(["foo", "bar"], 10) على 0.5. لا يحب الجميع تمامًا |> الحالي.

tkelman : أرى المشكلة ، ولكن ما هي وجهة نظرك؟ هل تعتقد أنه يجب علينا إصلاح |> الحالي قبل أن نضيف استخدامات إضافية له؟ إذا كان الأمر كذلك ، فكيف؟

أنا شخصياً أعتقد أننا يجب أن نتخلص من |> الموجود.

جرب lpad.(["foo", "bar"], 10) على 0.5. لا يحب الجميع تمامًا |> الحالي.

أعتقد أنك فاتتك هذه النقطة. نعم ، يعد الترميز func.() أمرًا رائعًا ويتجاوز المشكلة في بعض المواقف. لكني أستخدم الدالة map كتوضيح بسيط. أي دالة تأخذ وظيفة كوسيطة سوف تستفيد من هذا الإعداد. على سبيل المثال ، لتوضيح وجهة نظري فقط ، قد ترغب في فرز بعض الأرقام بناءً على المضاعف المشترك الأصغر مع بعض الأرقام المرجعية. أيهما يبدو أكثر إتقانًا وأسهل في القراءة: sort(A,by=i->lcm(i,10)) أم sort(A,by=lcm 10) ؟

أود أن أشير مرة أخرى إلى أن أي طريقة لتعريف مشغلي infix ستسمح بإنشاء عامل يقوم بما يريده Glen-O <| ، حتى يتمكن في أسوأ الأحوال من كتابة شيء مثل sort(A,by=lcm |> currywith 10) . الهدف من هذه الصفحة هو مناقشة كيفية صنع بعض a ... f ... b => f(a,b) . أتفهم أن ما إذا كان |> الحالي أو <| المقترح هما عاملان جديران بالاهتمام لهما علاقة بهذه النقطة ، لكن دعونا نحاول عدم الانحراف كثيرًا.

أنا شخصياً أعتقد أن عرض a |> b c هو الأفضل حتى الآن. يتبع اتفاقية قائمة من هاسكل ؛ يرتبط منطقيًا بالمعامل الموجود |> ؛ يمكن قراءته بشكل معقول وسهل الكتابة بشكل معقول. حقيقة أنني أشعر أنه يمتد بشكل طبيعي إلى استخدامات أخرى هي حقيقة ثانوية. إذا كنت لا توافق ، فيرجى على الأقل ذكر مشاعرك حول المصطلح الأساسي ، وليس فقط الاستخدامات الثانوية المقترحة.

كنت أعني أنه يؤدي إلى مشكلات الاتساق ، ومن ثم أقول "أو سيتعين عليه التعامل مع مشغلي infix الحاليين بشكل مختلف ، مما قد يتسبب في حدوث ارتباك".

أوافق على أنه من الصعب تحديد أسبقية a f b . على سبيل المثال ، من الواضح أن in يستفيد من أسبقية المقارنة ، ولكن من المحتمل جدًا أن العديد من الوظائف المستخدمة مثل infix لا تريد أسبقية المقارنة. ومع ذلك ، لا أرى أي مشكلة تتعلق بالاتساق. العوامل المختلفة لها أسبقية مختلفة. إضافة a f b لا تجبر يدنا على إعطاء + و * نفس الأسبقية.

لاحظ أن |> له بالفعل أسبقية مجاورة للمقارنة. لأي أسبقية أخرى ، بصراحة ، أعتقد أن الأقواس جيدة.

إذا كنت لا تتفق معي ، وإذا كنا نستخدم a |> f b ، فقد يكون هناك عوامل تشغيل مماثلة |+> ، |*> ، و |^> ، والتي عملت بنفس طريقة عمل |> ، لكن كانت لها أسبقية عامل التشغيل المركزي. أعتقد أن هذا مبالغة لكنه احتمال.

هناك إمكانية أخرى لحل مشكلة الأسبقية وهي استخدام بناء جملة لمشغلي Infix المخصص الذي يتضمن أقواسًا من نوع ما ، على سبيل المثال (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 أي أكثر من "ASCII salad" من ، على سبيل المثال ، x |> sin |> exp؟ ومع ذلك ، تمت إضافة التدوين |>.

أتخيل أن @tkelman يجادل

يجب أن نتخلص من |> الموجود.

جزئيًا لأن _both_ lpad<|10 و x|>sin|>exp يدخلون منطقة سلطة ASCII :).

أعتقد أن toivoh 's (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) . أدرك أن هذا ليس في الواقع نتيجة مباشرة لاختيار خيار "parens required" لـ infix ، ولكنه مصطلح مناسب يسمح لنا بتحذير الأشخاص الذين يستخدمون infix على LHS عن طريق الخطأ مع الاستغناء عن الأشخاص الذين يقومون بذلك غرض.

أشعر حاليًا أنه إذا كنت تقوم بتطبيق دالة infix (بدلاً من البادئة) ،
إذن فهو عامل ، ويجب أن يبدو ويتصرف كمشغل.

ولدينا دعم لمشغلي infix الذين تم تعريفهم باستخدام unicode.
منذ https://github.com/JuliaLang/julia/issues/552

أعتقد أنه قد يكون من الجيد الحصول على ذلك حتى تتمكن من إضافة الكلمات الرئيسية كما في الاقتراح الأصلي.
لذلك يمكن أن يكون لدينا ، على سبيل المثال ، 1 ⊕₂ 1 == 0
يبدو أن القدرة على الحصول على أسماء عشوائية لـ infix الخاصة بك مبالغ فيها بعض الشيء.

يجب أن يبدو ويتصرف مثل عامل.

أوافق على وجوب وجود اصطلاحات تسمية قوية لمشغلي infix. على سبيل المثال: حرف واحد من unicode ، أو ينتهي بحرف جر. ولكن يجب أن تكون تلك الاتفاقيات التي يتم تطويرها بشكل عضوي ، وليس المتطلبات التي يفرضها المترجم. بالتأكيد لا أعتقد أن # 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)) (للمسافة أدنى أولوية ممكنة ، كما هو الحال في وحدات الماكرو)

...

هل سيكون من غير المناسب بالنسبة لي تقديم التصحيح؟

لم أفهم الحالتين الأخيرتين:

(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) ؟

بشكل عام ، لست مقتنعًا شخصيًا بضرورة دعم Julia لمشغلي infix المخصص بما يتجاوز المسموح به حاليًا.

أستطيع أن أرى مشكلتين في (a f b c d) .

أولاً ، سيكون من الصعب القراءة عندما يكون لديك تعبير أكثر تعقيدًا - أحد الأسباب التي تجعل الأقواس محبطة هو أنه غالبًا ما يكون من الصعب تحديد الأقواس التي تقترن مع الأقواس الأخرى بنظرة واحدة. هذا هو السبب في أن عاملي infix و postfixing ( |> ) مرغوب فيهما في المقام الأول. يعد Postfixing على وجه الخصوص محبوبًا لأنه يسمح بقراءة لطيفة وأنيقة من اليسار إلى اليمين دون الحاجة إلى التعامل مع الأقواس في كل مرة.

ثانيًا ، لا يترك أي طريقة للقيام بأشياء بشكل جيد مثل جعلها عنصرية. ما أفهمه هو أن f.(a,b) سيكون تدوينًا في 0.5 لجعل f يعمل بطريقة أساسية على حججه مع البث. لن تكون هناك طريقة رائعة لفعل الشيء نفسه باستخدام تدوين اللاحق ، إذا كان (a f b) . في أحسن الأحوال ، يجب أن يكون (a .f b) ، والذي من وجهة نظري يفقد جمال التناظر الذي يوفره .( مع .+ و .* .

قارن ، على سبيل المثال ، حالة الرغبة في استخدام مثال هاسكل. أوضح shashi في # 6946 النقطة التي لها ما يعادلها هنا. في هاسكل ، ستكتب 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 مع المعلمات b و c set) ، وبالتالي ستكون معادلة لـ i->f(i,b,c) . هذا يسمح لها بالعمل ليس فقط من أجل التثبيت ، ولكن في المواقف الأخرى التي قد ترغب في تمريرها وظيفة (خاصة وظيفة داخلية) مع معلمات (مع ملاحظة أن المعيار هو أن يكون هدف الوظيفة أولاً).

يوضح |> أيهما هو الوظيفة. إذا كان لديك ، على سبيل المثال ، (tissue wash fire dirty metal) ، فسيكون من الصعب جدًا ، في لمحة ، التعرف wash كوظيفة. من ناحية أخرى ، يحتوي tissue|>wash fire dirty metal على مؤشر كبير يقول " wash هي الوظيفة".

تبدو لي بعض الاعتراضات الأخيرة وكأنها تقول "لكن يمكنك إساءة استخدام هذه الميزة!" جوابي هو: بالطبع يمكنك ذلك. يمكنك بالفعل كتابة رمز غير قابل للقراءة تمامًا باستخدام وحدات الماكرو إذا أردت. وظيفة المحلل هي تمكين الاستخدامات المشروعة ؛ لوقف الانتهاكات ، لدينا اصطلاحات / مصطلحات وفي بعض الحالات محددون. على وجه التحديد:

لم أفهم الحالتين الأخيرتين:

لا يُقصد بهذه الأشياء بأي شكل من الأشكال أن تكون نموذجًا يحتذى به ؛ إنهم يعرضون فقط النتائج الطبيعية لقواعد الأسبقية. أعتقد أن كلا المثالين الأخيرين سيكونان مؤهلين لإساءة استخدام بناء الجملة ، على الرغم من أن (a^2 ಠ_ಠ b^2) => ಠ_ಠ(a^2,b^2) واضح بما فيه الكفاية.

لا يجب كتابة f (a، b، c) كـ (afbfc)

كان اقتراحي بـ (a f b c d) ، بصراحة ، فكرة متأخرة. أعتقد أنه منطقي ، ويمكنني أن أتوصل إلى أمثلة حيث يكون مفيدًا ، لكنني لا أريد تعليق هذا الاقتراح بشأن هذه المسألة إذا كان مثيرًا للجدل.

[على سبيل المثال:

  • f هي "طريقة كائن" لشيء ، ربما تكون معقدة ، باستخدام b و c و d ، ربما تكون أبسط.
  • f هي طريقة "بث طبيعي" مثل push! ]

في حين أن (a f b f c) سيكون منطقيًا إذا كان f مثل + ، أعتقد أن معظم المشغلين ليسوا مثل + ، لذلك لا ينبغي أن يكون نموذجنا.

سيكون من الصعب قراءتها عندما يكون لديك تعبير أكثر تعقيدًا

مرة أخرى ، ستكون إجابتي ، "لذا لا تسيء استخدامها".

لنفترض أننا نريد طريقة ما لكتابة تعبير معقد مثل a / (b + f(c,d^e)) مع f infix. في اقتراح toivoh ، سيكون هذا a / (b + (c f d^e)) . في الاستخدام الشبيه بـ Haskell ، سيكون a / (b + (c |> f d^e)) أو في "الأفضل" ، إذا تم تغيير الأسبقية |> لإصلاح هذا المثال بعينه ، a / (b + c |> f d^e) . أعتقد أن toivoh 's جيدة بسهولة هنا.

(tissue wash fire dirty metal)

أعتقد أن الحل لهذا هو اصطلاحات تسمية قوية لمشغلي infix. على سبيل المثال ، إذا كانت هناك اتفاقية مفادها أن مشغلي infix يجب أن يكون حرفًا واحدًا من unicode ، أو ينتهي بحرف جر أو شرطة سفلية ، فسيكون ما سبق شيئًا مثل (tissue wash_ fire dirty metal) وهو واضح كما يأمل هذا التعبير في أن يكون .

...

عنصر الحكمة

هذا هو مصدر قلق صالح. (a .f b) فكرة سيئة ، لأنه يمكن قراءتها على أنها ((a.f) b) . اقتراحي الأول هو (a ..f b) لكنه لا يجعلني سعيدًا جدًا.

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

لقد استخدمت jquery ، لذلك أرى بالتأكيد ميزة تسلسل الوظائف من هذا القبيل. لكنني أعتقد أنها ليست نفس مشكلة مشغلي infix. باستخدام عرض (a f b) ، يمكنك كتابة ما ورد أعلاه على النحو التالي:

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

... وهي ليست مقتضبة تمامًا مثل نسخة هاسكل ، لكنها ما زالت سهلة القراءة.

ربما يمكن أن يقتصر على ثلاثة أشياء فقط داخل () :
(a f (b,c))
.(a f (b,c)) باستخدام عامل التشغيل .(

وأخيرا رد على النقطة العامة:

بشكل عام ، لست مقتنعًا شخصيًا بضرورة دعم Julia لمشغلي infix المخصص بما يتجاوز المسموح به حاليًا.

من الواضح أننا جميعًا مؤهلون لآرائنا. (ليس من الواضح ما إذا كانت علامة الإعجاب تشير إلى هذا الجزء من التعليق ، ولكن إذا كان الأمر كذلك ، فسيكون ذلك ثلاثة أضعاف.)

لكن حججي المضادة هي:

  • جوليا لديها بالفعل العشرات من مشغلي infix ، العديد منهم متخصصون للغاية. لا مفر من أن يتم اقتراح المزيد. عندما يقول شخص ما "كيف يمكنك الحصول على ولكن ليس § ؟" ، فأنا أفضل الرد "افعل ذلك بنفسك" وليس "الانتظار حتى يتم اعتماد الإصدار التالي على نطاق واسع".
  • شيء مثل (a § b) يمكن قراءته بشكل بارز ، وبناء الجملة خفيف بما يكفي للتعلم من مثال أو مثالين.
  • لست الشخص الأول الذي أثار هذه القضية ، ولن أكون الأخير. أتفهم أن مصممي اللغة يجب أن يكونوا متشككين جدًا في الميزات الزاحفة (الخاطئة) ، لأنه بمجرد إضافة ميزة قبيحة ، من المستحيل إصلاحها لاحقًا. ولكن كما قلت أعلاه ، أعتقد أن (a f b) نظيف بما يكفي بحيث لن تندم عليه.

لست متأكدًا حقًا من وضوح (a f b)

فيما يلي حالة استخدام محتملة:
select((((:emp_id, :last_name) from employee_tbl) where (:city, == ,'indianapolis')) orderby :emp_id));

هذا بالتأكيد استخدام قابل للتطبيق لوظائف infix.
الوظيفة select هي إما دالة الهوية ، أو ترسل الاستعلام المدمج إلى قاعدة البيانات.

هل هذا رمز واضح؟
أنا فقط لا أعرف.

.(a f b)

نعم ، هذا منطقي. لكنها ليست سهلة القراءة.

هل يمكن قراءة (a @. f b) بشكل أكبر؟ لأن الماكرو @. لتمكين ذلك سيكون مجرد سطر واحد.

[[[فكر في الأمر ، إذا سمحنا بوحدات ماكرو infix دون الحاجة إلى أقواس ، يمكن لـ @ Glen-O استخدامها للقيام بما يريد: circle(10) @> move 0 0 @> animate "scale" "ease" => @> (@> circle(10) move 0 0) animate "scale" "ease" = ماكرو> 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);

أنا بالتأكيد أفضل استخدام ماكرو لـ "حيث" حتى لا يتم اقتباس التعبير الشرطي بشكل غريب. لذا:

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);

الأقواس مزعجة إلى حد ما ، لكن من ناحية أخرى لا أرى طريقة معقولة للمحلل للتعامل مع هذا النوع من التعبير بدونهم.

في الفكر الثاني ، الأسبقية في هذا التعبير هي فقط من اليمين إلى اليسار. لذلك ، باستخدام وحدات ماكرو infix ، يمكن أن تكون كذلك:

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) ، بدأت أرى أن وحدات ماكرو infix هي إجابة جيدة أيضًا.

إليك الاقتراح الكامل من خلال الأمثلة ، متبوعًا بالمزايا والعيوب:

الاستخدامات الرئيسية:

  • 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] (الوقت المقدر للسفر: كلا ، مع التصحيح يأتي هذا كـ <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)

مزايا:

  • حدد وحدات ماكرو infix ، واحصل على وظائف infix مجانًا (مع تكلفة إضافية للتقييم الكلي لمرة واحدة. هذا ليس بنفس مقدار التكلفة المنخفضة مثل سحر المحلل اللغوي ، ولكنه أفضل بكثير من إجراء استدعاءات وظائف إضافية لكل تقييم)
  • يمكن أن يؤدي إلى DSLs قوية ، كما هو موضح في المثال الشبيه بـ SQL أعلاه
  • يزيل الحاجة إلى عامل تشغيل منفصل |> ، لأن هذا ماكرو ذو سطر واحد. وبالمثل مقابل <| وبقية مقترحات @ 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 .

ومع ذلك ، أعتقد أن المزيد من التعليقات المتبادلة لن تحقق أي تقدم إضافي ، وأنا أشجع الناس على استخدام علامات الإبهام أو الإبهام لأسفل من الآن فصاعدًا ما لم يكن لديهم شيء جديد حقًا يقترحونه (ذلك هو ، ليس مجرد تغيير إملائي لمقترح موجود). لقد أضفت رموز "الصيحة" (مخروط متفجر) إلى "المقترحات القابلة للتصويت". إذا كنت تعتقد أنه لا ينبغي أن يكون لدينا بناء جملة متخصص للوظائف التعسفية في موضع infix ، فقم بالتصويت على الخطأ ككل.

...

إيتا: أعتقد أن هذه المناقشة أصبحت الآن ناضجة بما يكفي للحصول على علامة decision .

للإشارة ، (وتوقعت من شخص آخر أن يشير إلى ذلك).
إذا كنت تريد تضمين بناء جملة يشبه SQL ، فإن الأداة المناسبة لهذه الوظيفة هي Nonstandard String Literals ، على ما أعتقد.
مثل جميع وحدات الماكرو ، يمكنهم الوصول إلى جميع المتغيرات في النطاق عند استدعائهم ،
وتسمح لك بتحديد 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.
لكن يمكنهم فعل ذلك.

وفي هذه الحالة أعتقد أن النتيجة أنظف كثيرًا من أي عملية تثبيت يمكن تحديدها.
على الرغم من أنه يحتوي على عبء الاضطرار إلى كتابة microparser / tokenizer الخاص بك.


أنا حقًا لا أرى الحاجة إلى علامة قرار.
هذا ليس له تنفيذ باعتباره العلاقات العامة ، ولا أي نموذج أولي قابل للاستخدام.
يتيح للناس اختباره.
على النقيض من https://github.com/JuliaLang/julia/issues/5571#issuecomment -205754539 مع 8 نماذج أولية قابلة للاستخدام

مشاعري تجاه هذا ترتفع وتنخفض في كل مرة أقرأ فيها الموضوع. لا أعتقد أنني سأعرف حقًا حتى أحاول ذلك. وأنا الآن لا أعرف حتى ما الذي سأستخدمه من أجله. (على عكس بعض تعريفات |> و <| التي استخدمتها في F #)

بناء جملة يشبه SQL ، الأداة المناسبة لهذا العمل هي Nonstandard String Literals

سواء كان من الأفضل استخدام SQL أم لا باستخدام NSLs ، أعتقد أن هناك مستوى من DSL معقدًا بما يكفي بحيث تكون وحدات الماكرو المضمنة مفيدة جدًا ، ولكنها ليست معقدة جدًا لدرجة أنه يستحق كتابة microparser / tokenizer الخاص بك.

في الوقت الحالي ، لا أعرف حتى ما الذي سأستخدمه من أجله. (على عكس بعض تعريفات |> و <| التي استخدمتها في F #)

سيمكن اقتراح الماكرو المضمن الأشخاص ، من بين أشياء أخرى ، من إنشاء وحدات الماكرو الخاصة بهم |> مثل أو <| مثل وحدات الماكرو ، لذا يمكنك استخدامها لأي شيء قمت به في F #.

(لا أريد الخوض في حجج تسيير الدراجات ذهابًا وإيابًا ، لكنني كنت أستجيب على أي حال بسبب ما يلي ، وأعتقد أن اقتراح الماكرو المضمن يقتل طيورًا متعددة بحجر واحد ناعم نسبيًا).

أنا حقًا لا أرى الحاجة إلى علامة قرار.

سألت في وقت سابق عما إذا كان من المناسب بالنسبة لي إنشاء تصحيح محلل ، ولم يجبني أحد. الكلمة الوحيدة في ذلك حتى الآن هي:

لا أعتقد أنه سيكون هناك الكثير في طريق "الابتكار النحوي" قبل Julia 1.0.

الذي يبدو أنه يجادل ضد عمل رقعة الآن ، لأنه قد يجلس فقط ويتعفن. ومع ذلك ، أنت الآن تقول إن الأمر لا يستحق اتخاذ قرار بشأن هذا (بما في ذلك قرار عدم اتخاذ القرار الآن؟) ما لم يكن لدينا "تنفيذ كنموذج أولي [أو] قابل للاستخدام".

ماذا يعني ذالك؟ (ما هي العلاقات العامة؟) هل الماكرو الذي يستخدم الحرف '@' بدلاً من الرمز @ يؤدي المهمة ، بحيث <strong i="22">@testinline</strong> a '@'f b => @f(a, b) ؟ أم يجب أن أرسل رقعة إلى julia-parser.scm؟ (لقد بدأت بالفعل في البحث الأولي في كتابة مثل هذا التصحيح ، ويبدو أنه يجب أن يكون بسيطًا ، لكن مخططي صدئ جدًا.) هل أحتاج إلى إنشاء حالات اختبار؟

الآن ، هناك 13 مشاركًا في هذا الخطأ. هناك ما مجموعه 5 أشخاص قاموا بالتصويت على واحد أو أكثر من المقترحات و / أو قاموا بالتصويت على الخطأ نفسه ، وفعل واحد منهم (أنا) ذلك بعد أن كان اقتراح الماكرو المضمّن مطروحًا على الطاولة. هذا لا يجعلني واثقًا من أن وقت النماذج الأولية قد حان. عندما يكون عدد الأشخاص الذين صوتوا منذ الاقتراح الجاد الأخير أشبه بنصف عدد المشاركين ، آمل أن يصبح نوعًا من الإجماع التقريبي واضحًا ، وبعد ذلك سيحين وقت وضع النماذج الأولية والاختبار والبت (أو ، كما قد يكون الأمر ، التخلي عن الفكرة).

من خلال "التنفيذ كنموذج أولي للعلاقات العامة [أو] نموذج أولي قابل للاستخدام".
أعني شيئًا يمكن اللعب به.
لذلك يمكن أن نرى كيف تشعر في الممارسة.

PR هو طلب سحب ، لذا فإن التصحيح هو المصطلح الذي كنت تستخدمه.

إذا قمت بعمل PR ، فيمكن تنزيله واختباره.
بشكل أكثر بساطة إذا قمت بتطبيقه باستخدام وحدات الماكرو
أو سلسلة حرفية غير قياسية ،
يمكن اختباره دون الحاجة إلى بناء جوليا.

لم يعجبني ذلك ، لكنني أشك في أنني سأكون باليًا لأخذ رأيي الخاص بدون أي شيء يمكنني اللعب به.

+1 أيضًا لعدم الذهاب إلى سفك الدراجات ذهابًا وإيابًا.

... أو ربما حزمة Infix.jl تحتوي على وحدات ماكرو وسلسلة حرفية غير قياسية.

لقد وصلنا بالتأكيد إلى نقطة "رمز العمل أو GTFO" في هذه المحادثة.

حسنًا ، إليك رمز العمل إذن: https://github.com/jamesonquinn/JuliaParser.jl

الوقت المقدر لوسائل النقل: هل يجب أن أشير إلى التزام محدد ، أم أن الرابط أعلاه إلى أحدث نسخة رئيسية على ما يرام؟

...

(لا يحتوي هذا على أي من وحدات الماكرو الملائمة التي أتوقعها ، مثل المعادلات لـ |> و <| و ~ و @defineinfix من المثال أعلاه. كما أنه لا يزيل _deprecate_ منطق الحالة الخاصة عديم الفائدة الآن لعامل التشغيل ~ أو عامل التشغيل |> . إنه فقط تغييرات المحلل اللغوي لتشغيله. لقد اختبرت الوظائف الأساسية ولكن ليس كل الحالات الجانبية.

...

أعتقد أن الاختراق القبيح الحالي بـ ~ يظهر أن هناك حالة استخدام واضحة لهذا النوع من الأشياء. باستخدام هذا التصحيح ، ستقول @~ عندما تحتاج إلى سلوك ماكرو ؛ أنظف كثيرًا ، بدون حالة خاصة. أو هل يعتقد أي شخص بجدية أن ~ فريد تمامًا ولن يرغب أحد في فعل ذلك مرة أخرى؟

لاحظ أن التصحيح (ليس علاقات عامة حتى الآن لأنه يستهدف المحلل اللغوي الأصلي ، ولكن في الوقت الحالي ، المخطط الذي يجب أن يأتي المرء أولاً من حيث العلاقات العامة) مفيد بشكل عام أكثر من اسم المشكلة هنا. اسم الإصدار هو "عوامل تشغيل مخصصة" ؛ يعطي التصحيح وحدات ماكرو infix ، مع ظهور عوامل infix فقط كأثر جانبي لذلك.

التصحيح كما هو ليس تغييرًا مفاجئًا ، لكنني أتوقع أنه إذا أصبح هذا هو الخطة ، فستكون الخطوة التالية هي إهمال ~ و |> الموجود حاليًا ، الأمر الذي سيؤدي في النهاية إلى كسر التغييرات.

...

تمت إضافة بعض الاختبارات البسيطة.

تم إغلاق 11608 بإجماع واضح جدًا على أن الكثير منا لا يريدون وحدات ماكرو infix وأن الحالة الحالية الوحيدة التي ~ كانت عملية التحليل خطأ (تم ارتكابها في وقت مبكر من أجل توافق R وليس هناك سبب وجيه آخر بشكل خاص). نحن عازمون على إهمالها والتخلص منها في النهاية ، ولكننا لم نقم بذلك (جنبًا إلى جنب مع عمل تعديل واجهة برمجة التطبيقات لواجهة الصيغة في حزم JuliaStats) حتى الآن.

أصبحت وحدات الماكرو الآن عامة من الناحية الفنية ، لكن وسيطات الإدخال الخاصة بها دائمًا ما تكون Expr أو Symbol أو حرفية. لذلك فهي ليست قابلة للتوسيع حقًا لأنواع جديدة محددة في الحزم بالطريقة التي تكون بها الوظائف (infix أو غير ذلك). يتم تقديم حالات الاستخدام المحتملة لوحدات ماكرو infix بشكل أفضل من خلال وحدات 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

===

المزيد من الوظائف لجوليا التي يتعين على الأشخاص تنفيذها وصيانتها واختبارها وتعلم كيفية استخدامها وما إلى ذلك.

والتي يتم الرد عليها (جزئيًا) (وتثبيتها) هنا بواسطة:

"الصداع للمطورين المحلل اللغوي" هو أقل مصدر قلق ممكن.

===

لا توجد طريقة لحزمتين للحصول على تعريفات في نفس الوقت لنفس مشغل الماكرو التي يمكن استخدامها معًا بشكل لا لبس فيه في قاعدة رمز مستخدم واحد؟

هذه نقطة مثيرة للاهتمام. من الواضح ، إذا كان الماكرو يستدعي وظيفة فقط ، فعندئذٍ لدينا كل قوة إرسال الوظيفة. ولكن إذا كان ماكروًا حقيقيًا ، كما هو الحال مع ~ ، فهو أكثر تعقيدًا. نعم ، يمكنك أن تتخيل الحلول البديلة ، مثل محاولة تسميتها كوظيفة ، والقبض على أي أخطاء لاستخدامها كوحدة ماكرو ... ولكن لا ينبغي تشجيع هذا النوع من القبح.

ومع ذلك ، فإن هذا يمثل مشكلة كبيرة بالنسبة لأي ماكرو. إذا قامت كلتا الحزمتين بتصدير ماكرو ، فلا يمكنك ببساطة الحصول على كليهما باستخدام "استخدام".

هل من المحتمل أن تكون هذه مشكلة في وحدات ماكرو infix؟ حسنًا ، يعتمد الأمر على ما يستخدمه الأشخاص في النهاية:

  • مجرد طريقة للحصول على وظائف infix المعرفة من قبل المستخدم. في هذه الحالة ، فهي ليست أسوأ من أي وظيفة أخرى ؛ إيفاد يعمل بشكل جيد.
  • كطريقة لاستخدام أنماط البرمجة الأخرى ، باستخدام عوامل تشغيل مثل |> و <| التي ناقشها @ Glen-O أعلاه. في هذه الحالة ، أعتقد أنه سيتم تطوير اتفاقيات مشتركة بسرعة حول ما يعنيه الماكرو ماذا ، مع فرصة ضئيلة للتصادم.
  • كطريقة لإنشاء DSLs لأغراض خاصة ، مثل مثال SQL أعلاه. أعتقد أنه سيتم استخدام هذه في سياقات محددة وفرصة الاصطدام ليست سيئة للغاية.
  • لأشياء مثل R ~ . في البداية ، يبدو هذا هو الأكثر إشكالية ؛ في R ، يتم استخدام ~ لأشياء مختلفة. ومع ذلك ، أعتقد أنه حتى هناك ، يمكن التحكم فيه ، بشيء مثل:

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

بعد ذلك ، يمكن إرسال الوظيفة ~ بناءً على نوع LHS ، ولكن سيكون RHS دائمًا Expr. سيسمح هذا النوع من الأشياء للاستخدامات الرئيسية الموجودة في R (الانحدار والرسوم البيانية) بالتعايش ، أي الإرسال بشكل صحيح على الرغم من أنه يأتي من حزم مختلفة.

(ملاحظة: تم تحرير ما ورد أعلاه. في البداية ، اعتقدت أن تعبير R مثل a ~ b + c يستخدم ربط b و c من خلال التقييم البطيء لـ R. لكنه ليس كذلك ' t؛ b و c هي أسماء الأعمدة في إطار البيانات التي تم تمريرها بشكل صريح ، وليست أسماء المتغيرات في النطاق المحلي التي يتم تمريرها ضمنيًا.)

===

السبيل الوحيد للمضي قدمًا هنا هو تطوير تنفيذ فعلي.

الذي فعلته.

===

أصبحت وحدات الماكرو الآن عامة من الناحية الفنية ، لكن وسيطات الإدخال الخاصة بها تكون دائمًا Expr أو Symbol أو literals. لذلك فهي ليست قابلة للتوسيع حقًا لأنواع جديدة محددة في الحزم بالطريقة التي تكون بها الوظائف (infix أو غير ذلك).

هذا يتعلق بالنقطة أعلاه. بقدر ما يستدعي ماكرو infix وظيفة معينة ، فإن هذه الوظيفة لا تزال قابلة للتوسيع من خلال الإرسال بالطريقة العادية. بقدر ما لا تستدعي وظيفة معينة ، فهي تقوم بشيء هيكلي / نحوي (مثل ما يفعله |> الآن) لا ينبغي تمديده أو إعادة تعريفه. لاحظ أنه حتى لو استدعت دالة ، فإن حقيقة أنها ماكرو يمكن أن تظل مفيدة ؛ على سبيل المثال ، يمكنه اقتباس بعض وسائطه ، أو معالجتها في عمليات نداء ، أو حتى التفاعل في وقت واحد مع اسم المتغير وربطه ، بطريقة لا يمكن لاستدعاء الوظيفة المباشرة القيام بها.

===

يتم تقديم حالات الاستخدام المحتملة لوحدات ماكرو infix بشكل أفضل من خلال وحدات DSL ذات التعليقات التوضيحية المسبقة للماكرو أو القيم الحرفية للسلسلة.

كما تمت الإشارة إليه في الموضوع المشار إليه:

[Infix] أسهل في التحليل (للغة الإنجليزية ومعظم المتحدثين الغربيين) ، لأن لغتنا تعمل بهذه الطريقة. (نفس الشيء ينطبق بشكل عام على المشغلين.)

على سبيل المثال ، أيهما أكثر قابلية للقراءة (وقابلية للكتابة):

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 الخاص بي الذي تم اختراقه. لا أنوي فرض إرادتي ؛ فقط لتقديم وجهة نظري.

أنا أجادل لصالح وحدات ماكرو infix ( a <strong i="6">@m</strong> b => <strong i="8">@m</strong> a b ). هذا لا يعني أنني لست على علم بالحجج ضد. إليك كيفية تلخيص أفضل حجة ضد:

تبدأ ميزات اللغة من -100. ما الذي تقدمه وحدات ماكرو infix التي يمكنها التغلب على ذلك؟ بحكم طبيعتها ، لا يوجد شيء يمكنك إنجازه باستخدام وحدات ماكرو infix التي لا يمكن إنجازها باستخدام وحدات ماكرو البادئة.

إجابتي هي: جوليا هي أولاً وقبل كل شيء لغة لمبرمجي العلوم والتكنولوجيا والهندسة والرياضيات (STEM). علماء الرياضيات ، والمهندسون ، والإحصائيون ، والفيزيائيون ، وعلماء الأحياء ، والمتعلمون الآليون ، والكيميائيون ، وعلماء الاقتصاد القياسي ... والشيء الوحيد الذي أعتقد أن معظم هؤلاء الناس يدركون فائدة التدوين الجيد. لأخذ مثال أنا على دراية به في الإحصاء: إضافة متغيرات عشوائية مستقلة تعادل تحويل ملفات PDF ، أو حتى إلى مشتقات ملتفة من CDFs ، ولكن غالبًا ما يكون التعبير عن شيء باستخدام الأول أمرًا أكثر إيجازًا ومفهومًا من الأخير .

إن Infix مقابل البادئة مقابل postfix ، إلى حد ما ، مسألة ذوق. ولكن هناك أيضًا أسباب موضوعية لتفضيل infix في كثير من الحالات. في حين تؤدي البادئة وما بعد الإصلاح إلى رواسب غير قابلة للهضم من مشغلين متتاليين مثل أولئك الذين يجعلون مبرمجي فورث يبدون مثل السياسيين الألمان ، أو أولئك الذين يجعلون مبرمجي Lisp يبدو وكأنهم كاريكاتير تشومسكي ، فإن infix يضع المشغلين في أكثر ما يكون معرفيًا في كثير من الأحيان مكان طبيعي ، بالقرب من جميع معاملاتهم قدر الإمكان. هناك سبب لعدم كتابة أحد أوراق الرياضيات في Forth ، ولماذا يستخدم علماء الرياضيات الألمان عوامل infix عند كتابة المعادلات.

نعم ، يمكن استخدام وحدات ماكرو infix لكتابة التعليمات البرمجية المبهمة. لكن وحدات ماكرو البادئة الحالية معرضة للإساءة. إذا لم يتم إساءة استخدامها ، يمكن أن تؤدي وحدات ماكرو infix إلى تعليمات برمجية أكثر وضوحًا .

  • (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")) .

أدرك أن هذه مجرد أمثلة على لعبة لكنني أعتقد أن المبدأ صالح.

هل يمكن عمل ما سبق باستخدام حرفية سلسلة غير قياسية؟ حسنًا ، يعمل المثالان الثاني والثالث كخطابات أمنية وطنية. لكن المشكلة في خطابات الأمن القومي هي أنها تمنحك قدرًا كبيرًا من الحرية: ما لم تكن على دراية بقواعد معينة ، فلا توجد طريقة للتأكد حتى من الرموز المميزة لخطاب الأمن القومي ، ناهيك عن ترتيب عملياتها. مع وحدات ماكرو infix ، لديك حرية كافية للقيام بكل الأمثلة المذكورة أعلاه ، ولكن ليس كثيرًا لدرجة أنه ليس من الواضح عند قراءة الكود "الجيد" ما هي الرموز المميزة وأين تذهب الأقواس الضمنية.

إنه يحتاج إلى أشياء معينة ليتم نقلها من مجهولين إلى مجهولين معروفين. ولسوء الحظ ، لا توجد آلية للقيام بذلك. تحتاج حججك إلى هيكل غير موجود.

الآن بما أن <| هو رابط الحق (# 24153) ، هل يعمل الاقتراح الأولي a |>op<| b ؟

لقد صنعت حزمة للاختراق الذي ذكره ستيفن في https://github.com/JuliaLang/julia/pull/24404#issuecomment -341570934:

لست كم عدد مشغلي infix المحتملين الذين يؤثر ذلك ، لكني أود حقًا استخدام <~ . لن يتعاون المحلل اللغوي - حتى لو قمت بوضع مسافة بين الأشياء بعناية ، فإنه يريد أن يعني $ # a <~ b a < (~b) .

يواجه <- مشكلة مماثلة.

آسف إذا تمت تغطية هذا بالفعل عن طريق هذه المشكلة أو غيرها ، ولكن لم أتمكن من العثور عليها.

من المحتمل أن نطلب مسافات في a < ~b ؛ أضفنا قواعد كهذه من قبل. ثم يمكننا إضافة <- و <~ كمعاملين infix.

شكرًا JeffBezanson ، سيكون ذلك رائعًا! هل ستكون هذه حالة خاصة أم قاعدة عامة؟ أنا متأكد من أن هناك بعض التفاصيل حول ما يجب أن تكون عليه القاعدة للسماح بمزيد من مشغلي infix ، وإعطاء رمز واضح ويمكن التنبؤ به ، وكسر أقل قدر ممكن من الكود الحالي. على أي حال ، أنا أقدر المساعدة والاستجابة السريعة. سنة جديدة سعيدة!

في حالة اختلاف a <~ b عن a < ~b أود رؤية a =+ 1 كخطأ (أو تحذير على الأقل)

أعلم أن هذه مناقشة قديمة إلى حد ما ، وقد تم طرح السؤال المطروح منذ بعض الوقت ، لكنني اعتقدت أنه يستحق الإجابة:

الآن بما أن <| هو رابط الحق (# 24153) ، هل يعمل الاقتراح الأولي a |>op<| b ؟

لا ، للأسف ، لا تزال الأسبقية تحصل على |> . التحديث الذي تم إجراؤه يجعله ، إذا قمت بتعريف <|(a,b)=a(b) ، فيمكنك تنفيذ a<|b<|c بنجاح للحصول على a(b(c)) ... لكن هذا مفهوم مختلف.

مجمد خلال عامين ، تعليق والتزام منذ يومين و 5 أيام!

راجع مستند المعاملات الثنائية القابلة للتخصيص f45b6be

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات