Julia: جلاب صغير: إذا كان س ثم ص

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

في العديد من المناقشات ، تم اقتراح السماح ببناء الجملة مثل:

if x then y

كتعبير قصير "إذا" وكبديل للمشترك:

x && y

بناء الجملة الذي يستفيد من عامل التشغيل قصير المدى && للتنفيذ المشروط y (مع احتواء y غالبًا على تأثيرات جانبية أخرى وليس بالضرورة إرجاع Bool ).

تتمثل المزايا الرئيسية لهذا if-then : شفرة أكثر وضوحًا ، والاعتماد بشكل أقل على إساءة استخدام && ، وتضمين نموذج بيان "if" رسميًا لا يتطلب end كلمة رئيسية.

خطر ببالي قبل أيام ، أن بناء الجملة هذا سيوفر أيضًا وسيلة ملائمة لتنفيذ # 550 ، والتي ستبدو كما يلي:

A = [if x % 2 == 0 then f(x) for x in 1:10]

الاعتماد على حقيقة أن if-then لا يتطلب كلمة رئيسية end ، والتي ربما نحتاجها في شكل ما على أي حال حتى لو استخدمنا حراس من طراز Python:

A = [f(x) for x in range(10) if x % 2 == 0]

لكي نكون واضحين ، فإن بناء جملة حارس جوليا ستقوم بشكل أساسي بإعادة الكتابة من:

A = [if x % 2 == 0 then f(x) for x in 1:10]

ل

A = [Filter(x->x % 2 == 0, f(x) for x in 1:10)]

أيضًا كملاحظة توضيحية ، سيسمح هذا ببناء جملة الحراسة على مستوى _ Generator_ بدلاً من مستوى _comprehension_ فقط (والذي يتطابق مع ما تسمح به Python أيضًا).

julep

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

ربما أنا من الأقلية لأن اللغات الأخرى قد اتبعت هذا النهج ، لكنني وجدت دائمًا أن الإجراء القادم قبل الحالة غريب حقًا ، على سبيل المثال println("positive") if x > 0 . أعتقد أنه أكثر إيجازًا من if x > 0 println("positive") end لكن على الأقل بالنسبة لي يأتي على حساب سهولة القراءة.

أفكر في الأمر كمحادثة:

جوليا: "سأطبع سلسلة ..."
هارولد: "رائع!"
جوليا: "... ولكن فقط إذا تم استيفاء بعض الشروط."
هارولد: "أوه. :("

مقابل

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

ال 53 كومينتر

يبدو أن صيغة Perl / Ruby-style if / for المُعدِّل ستختلط بشكل أفضل مع هذا. بعبارات أخرى:

println("positive") if x > 0         # conditional execution
x^2 for x=1:100                      # generator
[ x^2 for x=1:100 ]                  # comprehension
x^2 if x % 3 == 0 for x = 1:100      # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ]  # filtered comprehension

كما أن لها فائدة من وجود سابقة في لغات أخرى ، والتي لا يبدو أنها بناء الجملة if - then بدون end .

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

نعم نقطة جيدة. في الواقع ، يبدو أن رقم 6823 في منتصف المناقشة وربما لم يكن يجب إغلاقه.

ربما أنا من الأقلية لأن اللغات الأخرى قد اتبعت هذا النهج ، لكنني وجدت دائمًا أن الإجراء القادم قبل الحالة غريب حقًا ، على سبيل المثال println("positive") if x > 0 . أعتقد أنه أكثر إيجازًا من if x > 0 println("positive") end لكن على الأقل بالنسبة لي يأتي على حساب سهولة القراءة.

أفكر في الأمر كمحادثة:

جوليا: "سأطبع سلسلة ..."
هارولد: "رائع!"
جوليا: "... ولكن فقط إذا تم استيفاء بعض الشروط."
هارولد: "أوه. :("

مقابل

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

ararslan : لا أوافق ، وهذا أحد أسباب عدم ظهور هذه الميزة في Julia على الرغم من الفن السابق في Ruby و Perl. ومع ذلك ، فإنه يمتزج بشكل أفضل مع صيغة التعديل for للمولدات والفهم ، وهذا هو سبب طرحه هنا.

StefanKarpinski نعم وافق ، إنه يتوافق بشكل أفضل مع هؤلاء. ما زلت مرتبطًا بشكل ميؤوس منه بالشروط التي تسبق الإجراءات. : ابتسم: (لكن كما وجدت نفسي أقول كثيرًا مؤخرًا ، رأيي لا يهم حقًا ؛ أنا مجرد رجل.)

أفترض إذا كان لديك شيء مثل

if x % 3 == 0 then x^2 for x = 1:100

فليس من الواضح على الفور أنك بدأت بفهم / منشئ / شيء مايجيج ، لأنه يقرأ أيضًا كما لو أنه يمكن تجميعه مثل

if x % 3 == 0 then (x^2 for x = 1:100)

أي ، إذا كان هناك بعض الشرط ثم المولد. لا أمانع

if x % 3 == 0 x^2 end for x = 1:100            # More obvious what's happening, IMO
filter(x -> x % 3 == 0, [x^2 for x = 1:100])   # Verbose, but... ¯\_(ツ)_/¯

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

x^2 for x = 1:100 where x % 3 == 0

أعتقد أن where يجعل الأمر أكثر وضوحًا أنك تقوم بتصفية قيم x التي تنتجها for من if .

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

هل يمكنك توضيح ما تعنيه بذلك؟

تولد "القيم" $ # for 1:n # $ ، ويقوم if x % 3 == 0 بتصفية هذه القيم ، ويقوم x^2 بتحويلها - تتدفق المولدات بالفعل من اليمين إلى اليسار وللحفاظ على هذا التدفق ، يحتاج المرشح إلى الانتقال إلى وسط. إذا انتقلت عبارة if إلى يمين جملة for فإن البيانات "تتدفق" من الوسط إلى أقصى اليمين ثم إلى أقصى اليسار ، وهذا أمر غريب. إذا كانت عبارة if على اليسار فإن البيانات "تتدفق" من أقصى اليمين إلى أقصى اليسار إلى المنتصف. أعلم أن SQL تضع جملة where على يمين أسماء الجداول والتعبيرات إلى اليسار - لأن هذا يشبه إلى حد كبير اللغة الإنجليزية - لكنني دائمًا أجد هذا مزعجًا للقراءة وأعتقد أن القراءة مثل الإنجليزية ليس إرشاديًا يجب أن يؤخذ بعيدًا في تصميم لغة البرمجة.

الأشياء التي لا أحبها في if x then y :

  1. يقدم الكلمة الرئيسية الجديدة then .
  2. من الأقصر كتابة if x y end من if x then y ؛ x && y أقصر من ذلك.
  3. تُستخدم الكلمة الأساسية then على نطاق واسع في اللغات للنوع المعاكس تمامًا من بناء الجملة: بناء جملة متعدد الأسطر if يتطلب كلمة رئيسية end (أو fi في bash ، yuck).

أوه نعم ، أرى ما تعنيه الآن بشأن التدفق. منطقي. شكرا على الشرح!

هل سيكون من الغريب أن تكون قادرًا على القيام بذلك

x^2 if x % 3 == 0 for x = 1:100

و _ لا _ تكون قادرة على القيام به

println("positive") if x > 0

؟

كل النقاط الجيدة.

أنا في الواقع أحب بناء الجملة StefanKarpinski الذي اقترحه لأول مرة في تعليقه الأول. أنا مهتم بشكل أساسي بالحصول على مولدات شرطية ، مع نموذج _if_ قصير أكثر عمومية كمكافأة.

فيما يتعلق بالمولدات ، كنت أقرأ if (أو where - ليس لدي رأي في ذلك) لأكون جزءًا من النطاق ... إنه ينشئ مكررًا x = 1:10 if/where x % 2 == 0 ، والذي ثم يتم دمجها مع التعبير الموجود على اليسار لإنشاء مصفوفة (أو منشئ).

بمعنى ما ، x = 1:10 where x % 2 == 0 بحد ذاته مولد لنوع من التكرارات. يمكن أن يكون هذا بناء جملة مستقل ، أليس كذلك؟

أشعر أن التصفية عملية مختلفة إلى حد ما عن البيان الشرطي if a then b . تعمل التصفية على نطاق التكرار. عندما يتم دمج if a then b مع التعبير الموجود على يسار المولد ، أتوقع أن يصدر nothing في الحالات a كان false . قارن ما يحدث بشكل منطقي إذا أضفت أقواس:

[(x^2 if i % 2 == 1) for i = 1:10] # [nothing, 4, nothing, 16, nothing, 36, nothing, 64, nothing, 100]
[x^2 (for i = 1:10 where i % 2 == 0)] # [4, 16, 36, 64, 100]

أخذ أمثلة ararslan ، إذا سمحنا بذلك

println("positive") if x > 0

ثم IMHO يتبع ذلك

x^2 if x % 3 == 0 for x = 1:100

ربما ينبعث منها nothing, nothing, 9, nothing, nothing, 36, ...

أخيرًا ، إذا كنا سنتبنى اختصارًا if مشروطًا ، فإن تصويتي سيكون للشرط قبل البيان ، للأسباب التي حددتها أول مشاركة لـ ararslan - كونها المبدأ الأقل مفاجأة في قراءة الكود. (تذكر ، إذا قالوا إن الشفرة تمت قراءتها أكثر من كونها مكتوبة ، فإن بناء الجملة if a then b هو بناء جملة أفضل ثم a && b حتى لو كان الأخير أقصر). وهذا يعني أيضًا أن النوعين المحتملين من if داخل المولد سيكونان مختلفين - في أقصى اليسار - مع التعبير - أو في أقصى اليمين - مع النطاق.

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

أيضًا ، إذا كان لدينا if/where في النطاقات ، فهل نحتاج إلى توخي الحذر للتأكد من أن النطاق يظل ديكارتيًا للمولدات متعددة الأبعاد؟

# Make a circular array (filled with distance to center)
r = 5
[sqrt(x^2 + y^2) for x = -5:5, y = -5:5 where x^2 + y^2 <= r^2]

هذا نوع من الهدوء والفظاعة!

أشعر أن التصفية عملية مختلفة إلى حد ما عن الشرط إذا كانت عبارة b ثم.

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

أشعر أيضًا مثل andyferris أن if بين التعبير والتكرار يبدو أنه "يحول" قيمة التعبير بدلاً من شكل التكرار ، ويجب أن ينتج nogthing عندما لم يتم استيفاء الشرط (لكن قد أفسدني فهم بايثون / هاسكل).

من الواضح أن x if false ستكون nothing عندما لا تكون في سياق تعبير منشئ. سيكون من المعقول تمامًا دعم [x^2 if x % 3 == 0 for x=1:100] ولكن ليس x if y بمفرده.

أنا شخصياً أفضل أن أتمكن من حذف end إذا كان هناك بيان واحد فقط.

if length(A) != length(B) throw(ArgumentError("..."))

إذا لم يكن هناك end ، فيمكن أن يفترض وجود تعبير واحد فقط. أظن أن هذا قد نوقش باستفاضة من قبل؟
ألاحظ أنني أفضل عدم وجود فاصلة منقوطة بعد الشرط - بعد التعبير ... _ربما _... لا أحب ذلك بالرغم من ذلك.

أفضل ذلك ، على أن يكون لدينا تركيبان مختلفان لشكل مماثل من عبارة if ؛if x; ...; end و if x then; ... . _ (تحرير: if condition then action نمت علي.) _

سيكون من المعقول تمامًا دعم [x ^ 2 إذا كانت x٪ 3 == 0 لـ x = 1: 100] ولكن ليس x إذا كانت y وحدها.

@ StefanKarpinski أنا موافق تمامًا على هذا. ومع ذلك...

إذا كانت عبارة if على اليسار ، فإن البيانات "تتدفق" من أقصى اليمين إلى أقصى اليسار إلى المنتصف.

قرأت x^2 if x % 2 == 0 for x in 1:10 كـ x^2 where x % 2 == 0 for each x in 1:10 ، وهو أمر منطقي بالنسبة لي نظرًا لفهمه ؛ أنت مهتم أكثر بالتحول.
في استعلامات SQL ، نفس النقطة صحيحة ، أليس كذلك؟

لذلك لا أعتقد أن وجود "المولد" هو نقطة البداية لقراءته ، فهذا صحيح تمامًا _للتفهم_. حلقة for من ناحية أخرى ... هذا منطقي أكثر.

أنا شخصياً أفضل أن أكون قادرًا على حذف كلمة end إذا كان هناك بيان واحد فقط.

لقد اقترحت هذا منذ وقت طويل ولكنه لم يحصل على أي تأثير: https://github.com/JuliaLang/julia/issues/1657. سيكون هذا في الواقع تغييرًا غير معطل نسبيًا لأنه سيكون غريبًا ونادرًا أن نرى بعض التعليمات البرمجية المكتوبة مثل هذا:

if cond body
end

ما رأيك في استخدام كتل do بدلاً من then ؟ على سبيل المثال: if x do y end

مجرد تعليق جانبي صغير: لا أرى بأي طريقة أن if x y بمفرده (أي خارج المولد) يمكن التعامل معه بشكل صحيح داخل محرر بدون محلل جوليا الكامل ، حيث يجب أن تكون قادر على تحديد عدد الرموز المميزة التي تتبع if . أفكر في vim ، لكني أفترض أن المحررين الآخرين قد يكونون في نفس الموقف. قد يكون الأمر نفسه صحيحًا بالنسبة y if x ، لكنني لست متأكدًا (الإفصاح الكامل: أنا أيضًا لا أحب y if x بمفرده ؛ أنا لست ضد if x y حيث المبدأ ولكن أعتقد أنه قد يكون من الصعب بعض الشيء تحليله للبشر أيضًا ، وليس فقط المحررين).

diegozea نفس المشكلة ، على ما أعتقد. ما زلت أفضل if x y .

carlobaldassi هناك بعض الأشياء التي يمكنك القيام بها لتسهيل التحليل على البشر.

يمكنك فرض أن لا تحتوي عبارة if المفردة على سطر جديد بين الشرط والتعبير.
لست متأكدًا من أنني أرغب في أن أجبر على فعل ذلك بسبب التعبيرات الطويلة.

بدلاً من ذلك ، يمكنك فرض وجود سطر جديد بعد التعبير إذا كان هناك سطر جديد بعد الشرط ؛ لذلك ، لن يتم تجميع ما يلي ، ولكنه يعطي رسالة خطأ واضحة بالطبع:

if length(A) != length(B)
    throw(ArgumentError("lengths must match")
if some_condition(A, B)
   N *= 2

لكن هذا من شأنه:

if length(A) != length(B) throw(ArgumentError("lengths must match")
if some_condition(A, B) N *= 2

وهذا من شأنه:

if length(A) != length(B)
    throw(ArgumentError("lengths must match")

if some_condition(A, B)
   N *= 2

سيمنعك هذا أيضًا من ارتكاب هذا النوع من الأخطاء:

if is_present(x)
    y = 2 * x[]

    return y * 2

أعتقد أن أكبر حجة لـ if x then y لا تزال تفوز على أي صيغة أخرى هي قابلية القراءة . أن if x y end أو if x y أو x && y أقصر لا علاقة له بكتابي (بخلاف حقيقة أننا نتحدث عن اختلاف تافه من 1 إلى 5 أحرف) لأن أيا من هؤلاء تقريبًا بنفس وضوح if x then y . كما أنه يتجنب المحرر تحليل المشاكل أو كسر محتمل للشفرة السابقة. إنها مجرد صيغة لطيفة ونظيفة ومختصرة لعبارات if القصيرة.

ومع ذلك ، فإنني أدرك الارتباك المحتمل لاستخدام if-then في حالة المولد ؛ بالنظر إلى ذلك ، أوافق على ذلك

x^2 if x % 3 == 0 for x = 1:100      # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ]  # filtered comprehension

هو أوضح ، مع إدراك أن بنية التعبير هي

generated_value_expr  value_generator_expr  =>  generator_expression

[generator_filter_expr]  for_generator_expr  => value_generator_expr

على سبيل المثال ، يتم تطبيق generator_filter_expr مباشرة على القيم الناتجة من for_generator_expr قبل تمرير القيم غير المفلترة إلى generated_value_expr .

أعتقد أن التمييز مهم هنا ، لأنه ليس نفس المنطق الذي سيسمح بذلك

println("positive") if x > 0 

TL ؛ DR: يجب أن يكون لدينا x^2 if x % 3 == 0 for x = 1:100 للمولدات التي تمت تصفيتها ، لكن نفس منطق بناء الجملة لا ينطبق على println("hey") if x > 0 ، وبالتالي ، لا يزال يتعين علينا التفكير في if x then y للنموذج القصير إذا- بناء الجملة. على الرغم من أنه من الواضح أن الفكرتين هنا الآن غير مرتبطتين تمامًا.

@ H-225 هذا يبدو غريبًا وغير جوليان في النهاية بالنسبة لي ، خاصةً مع الإجراء على سطر جديد بدون end .

سيظل تحليله كابوسًا بالنسبة للمحرر لأن المحررين (مثل Vim) لا يهتمون بما هو وليس شرطًا أو إجراءً - في الواقع ، ليس لديهم طريقة للمعرفة بدون محلل جوليا - لكنهم بالأحرى اهتم بوضع أشياء مثل if و end . أعتقد أنه سيكون من الصعب للغاية جعل Vim يدرك أن end غير مطلوب في هذا السيناريو. أدرك أن تسهيل الأمر على المحررين ليس حجة جيدة لاتخاذ قرار التصميم ، أنا فقط أقول '.

بالتأكيد: -1: مقابل if x y مني. أفضل if x then y على ذلك ، لأنه من السهل على عقلي الصغير التحليل. :اللسان الى الخارج وعين تغمز:

هل هناك سبب لعدم استخدام عامل تشغيل علامة الاستفهام الثلاثية لبيان if أيضًا؟ يمكنك بالفعل تقليد عبارة if عن طريق القيام بذلك

condition ? if_condition_true_eval_expr : nothing

لماذا لا تجعلها فقط بحيث إذا لم تقم بتضمين النقطتين ، فستكون عبارة if ، فعندئذٍ سيكون لديك فقط

condition ? if_condition_true_eval_expr

بهذه الطريقة لن تضطر إلى إدخال أي كلمات رئيسية جديدة ، هل سينجح هذا؟

esproff مضحك بما فيه الكفاية ، كنت سأقترح العكس: توسيع فكرة if-then في هذه الجلابة إلى تعبير if-then-else

if cond then a else b

حيث تكون جملة else اختيارية. قد تنخفض بشكل مماثل إلى cond ? b : c . بالنسبة لي ، هذا كله يتعلق بالابتعاد عن النمط C الثلاثي ونحو كود أكثر قابلية للقراءة من قبل الإنسان. (لقد استخدمت بالتأكيد condition ? a : nothing من قبل - يبدو الأمر وكأنه اختراق (لأنه كان ، nothing كان مهمًا لسبب غامض) وهو أمر محير للآخرين لقراءته).

لكن بالطبع ، لماذا لا يمكننا الحصول على كل هذه الأفكار في وقت واحد؟

andyferris نعم هذا هو الآخر ، Pythonic ، الطريق للذهاب. أعتقد أن الأمر يعتمد على مدى رغبتك في أن تكون مقتضبًا ، يبدو أن علماء الرياضيات عمومًا يقدّرون الاختصار ، لكن بصراحة سأكون سعيدًا بأي منهما ، طالما أنني لست مضطرًا إلى استخدام هذا الأمر

if condition; eval_expr; end

لكن بصراحة سأكون سعيدًا بأي منهما ، طالما أنني لست مضطرًا إلى استخدام clunky

if condition; eval_expr; end

بالفعل!

لما تستحقه ، أنا أحب تدوين x && y ولا أعتبره إساءة.

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

تمت مناقشة فكرة ? باستفاضة في # 6823 ، وقد تستحق إعادة قراءة تلك المناقشة.

لقد وصلت إلى هنا من تلك المناقشة ، لكنني اعتقدت أن هذا مكان أفضل للتعليق. أعتقد أن استخدام if a then b واستخدام ? فقط بدون : سيكون كل منهما مربكًا إلى حد ما ، لكن لن يشتكي طالما أنهما يوفران الوظيفة نفسها.

أنا أتفق معEricForgy. ربما كنت معتادًا على التعامل معهم في هذه المرحلة ، ولكن بالنسبة لي ، باستخدام && و || بهذه الطريقة أشعر بعبارات اصطلاحية لـ Julia ، خاصة للتحقق من الأخطاء (على سبيل المثال x || throw(y) ). لا تبدو غامضة أو غير مقروءة على الإطلاق. أيضًا ، لا أفهم حقًا سبب أهمية إرجاع $ x && y false إذا كان x خطأ لأنه ربما لا يجب استخدامه في نهاية الوظيفة على أي حال ، حيث سيؤثر على القيمة المرجعة للدالة.

الثلاثية على غرار C هي في كل مكان إلى حد كبير ؛ كنت أزعم أن علماء الرياضيات ليسوا وحدهم من يقدر بناء الجملة. اللغة الوحيدة التي يمكنني التفكير بها والتي تحتوي على ثلاثيات ولكنها لا تدعم النمط C هي لغة Python ، ويحتقر FWIW ثلاثيات Python. condition ? action1 : action2 مضغوط وقابل للقراءة طالما أنك تستخدم مسافات بيضاء وتحترم أطوال الأسطر. لظروف وإجراءات أطول ، يجب على المرء أن يستخدم

if condition
    somelongaction1
else
    somelongaction2
end

على أي حال لسهولة القراءة.

فيما يتعلق then ، موضوع هذه المناقشة ، FWIW ربما لن أستخدمه حتى لو تم تنفيذه لأن ، مرة أخرى ، && و || أشعر بالعبارات الاصطلاحية بالنسبة لي. على الرغم من أنني كنت آخذ then في نبضة قلب تزيد عن if x y أو x ? y أو x ? y : nothing .

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

image

لا _أحب _ استخدام && أو || لهذا ، لأنني لا أتذكر أبدًا أن x && y = z لا يحلل بالطريقة التي أتوقعها. أعتقد أنه يحتوي على حمل معرفي أعلى من y if x ؛ هذا يصل إلى if x y أيضًا.

IMO ، x ? y _ smells_ مثل خطأ في بناء الجملة ، بغض النظر عما إذا كان صحيحًا بالفعل.

ربما x ?? y ؟ x ?: y هو امتداد GNU C يعني x ? x : y ، لذلك ?? و ?: يمكن أن يكونا إصدارات منخفضة الأسبقية من && و || ربما

ترتيب التفضيل الخاص بي: y if x == x ?? y < if x then y < x && y < x ? y < if x y .

FWIW. أفضّل الاختصار والفصل الواضح للشفرة مع ? و && و || ، على الرغم من أن بناء الجملة cond ? expr قد يكون أكثر وضوحًا من && .

أحب أن أفعل بشكل متكرر نوع التدفق goodcondition || return ، وهو ليس بالأمر السهل مع عبارات if. لا أريد أن أفقد ذلك (أو أن أتعرض للتنمر لعدم استخدامه)

بالنسبة للثلاثية التي لا تحتوي على : ، قد يكون من الجيد السماح للكتل المقتضبة if / elseif بدون شرط else :

x==5 ? f1() :
x==6 ? f2()

ويمكن للمرء أن يتخيل توسيع هذا إلى عبارات من نوع التبديل:

match x:
    5 ? f1() :
    6 ? f2()

من حيث المقروئية ، هذا يعتمد. بالنسبة للعديد من الشروط / الإجراءات القصيرة ، يكون من السهل قراءتها (مع تباعد نظيف !!) لتكون قادرًا على محاذاة الشروط / الإجراءات على سطور متتالية مع فواصل واضحة.

بالنسبة للمولدات ، أفضل استخدام where أو when على إعادة تعيين الغرض من if ، لأنه عامل تصفية ، وليس شرطيًا:

x = [i^2 for i in 1:10 when i%2 == 0]

أعتقد أنه من الواضح أن هذا يعني x = [i^2 for i in filter(..., 1:10)] .

سألاحظ أنه منذ مناقشة هذا الأمر ، لم أعد أعترض على if condition then action - إنه بالأحرى نما علي.
تميل جوليا إلى الاتكاء على الجانب "كثير الكلام" ، باستخدام function و end ، وما إلى ذلك ، لذا أعتقد أنه سيكون مناسبًا. كما أنه من المزعج بعض الشيء أن تضطر إلى إضافة أقواس حول تعبيرات إذا انتقلت ذهابًا وإيابًا بين بناء الجملة condition && action .

فيما يتعلق ببناء جملة Perl / Ruby "action if condition": أنا حقًا أحب هذا النحو ، وبينما أوافق على أنه يمكن أن يقلل من قابلية القراءة عند استخدامه بشكل غير صحيح ، أعتقد أيضًا أنه في بعض الأحيان _ يزيد_ من سهولة القراءة.

فمثلا:

throw(DomainError()) if some_condition || some_other_condition && so_on

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

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

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

بصفتي يدًا قديمة في لغة بيرل ، فأنا متعاطف مع هذا النحو ، لكنني أعتقد أنه سيكون من الصعب بيعه للآخرين الذين لا ينتمون إلى خلفية لغة بيرل. إحدى الحجج المؤيدة هي أنها تطابق صيغة المرشح في الفهم. الحجة المعارضة هي أنه من الغريب أن يكون لديك بنية لا يكون فيها أمر التقييم من اليسار إلى اليمين. بالطبع ، الفهم بالضبط ذلك ، لذا 🤷‍♂️

بالنسبة لي ، فإن السؤال ذو الصلة هو: هل نقوم بتعميم التفريع أو التصفية؟ هذا تعميم للدلالات المتفرعة if (والصيغة) ، لذلك ربما سيكون من المؤسف استعارة بناء الجملة من الفهم / المولدات لهذا الغرض حيث يشير هذا التركيب بالفعل إلى التصفية.

(بالمناسبة ، أحب بعض الصيغ الجيدة للتصفية ، مثل بناء الجملة الرائع . . لتوضيح وجهة نظري أعلاه ، ربما يبدو map - filter مثل f.(a) if g.(a)

f(x) for x in a # lazy map
f(x) for x in a if g(x) # lazy map - filter
x for x in a if g(x) # lazy filter where `f` is `identity`

f.(a) # map / broadcast
f.(a) if g.(a) # like a map/broadcast - filter operation
a if g.(a) # like the above where `f` is implicitly `identity`
[1,2,3] if [true, false, true] == [1, 3] # or something... here we simply make `if` an infix operator for filtering

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

أخيرًا - أتفق نوعًا ما مع ملاحظاتtbreloff أعلاه ... يعتبر النظام الثنائي ? الصيغة الأكثر إحكاما (والهدف الكامل من هذا الموضوع هو إنشاء بناء جملة مضغوط) ، ودائمًا ما وجدت if اختيارًا مفاجئًا إلى حد ما لتصفية المولد.

StefanKarpinski كتب:

يبدو أن صيغة Perl / Ruby-style if / for المُعدِّل ستختلط بشكل أفضل مع هذا. بعبارات أخرى:
julia println("positive") if x > 0 # conditional execution x^2 for x=1:100 # generator [ x^2 for x=1:100 ] # comprehension x^2 if x % 3 == 0 for x = 1:100 # filtered generator [ x^2 if x % 3 == 0 for x = 1:100 ] # filtered comprehension
كما أن لها فائدة من وجود سابقة في اللغات الأخرى ، والتي لا يبدو أن بناء جملة if-then بدون نهاية.

وسيكون أفضل للقواعد أيضًا.

أعتقد أن [x^2 if x % 3 == 0 for x = 1:100] يجب أن يكون:

[(x^2 if x % 3 == 0) for x = 1:100]
 ```
Then `for` stay's in infix position which is currently an error. Of course we can change its meaning because of leading `[` but it would not work as generator:
```julia
x^2 if x % 3 == 0 for x = 1:100

أعتقد أن [x^2 if x % 3 == 0 for x = 1:100] يجب أن يكون:

لن يكون ذلك مولدًا مصفيًا. يعيد $ 2 if x 2 عندما يكون x صحيحًا ، ولكن يجب أيضًا إرجاع شيء عندما يكون x خطأ ؛ عادةً ما يكون ذلك nothing . وهذا من شأنه أن يعطي مصفوفة من الأعداد والأشياء. هذا جزئيًا هو السبب في أن if يجب أن يأتي بعد for في صيغة المولد المصفاة.

نعم كلامك صحيح. ربما يجب أن يكتب على هذا النحو:

[for x = 1:100 x^2 if x % 3 == 0]

Afaics ، سيكون هذا صالحًا للتحليل بدون استخدام الأقواس ، رائع!

فقط أفكر...

[ for x = 1:100 if x % 3 == 0 push x^2]
for x = 1:100 if x % 3 == 0 push x^2  # other keyword could be used, e.g. yield

هذا يشبه إلى حد كبير البناء الطبيعي

for x=1:100 
    if x%3==0 
          push!(somearray, x^2)
    end
end

لقد رأيت هذا الجلاب مرة أخرى أثناء النظر إلى شيء آخر.

ما زلت أتمنى شيئًا مثل نموذج السطر الفردي if a then b ؛ أجد أن البديل جوليان a && b غير قابل للقراءة إلى حد ما حتى بعد استخدامه لعدة سنوات: لا توجد طريقة لقراءته مباشرة كجملة إنجليزية.

أشعر أيضًا أن الحاجة إلى شرح المصطلح a && b للوافدين الجدد هو نوع من الإحراج عندما يكون لدينا صيغة بديلة واضحة بذاتها ولفترة أطول قليلاً.

لا توجد طريقة لقراءتها مباشرة كجملة إنجليزية

يقرأ a && b كـ "a و b" كما في "if a ثم فعل b أيضًا"
يُقرأ a || b على أنه "a أو b" كما في "a يجب أن يكون صحيحًا ، وإلا افعل b"

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

في المقابل ، وجدت دائمًا أن الحرف "a أو b" مقروء إلى حد ما.

من المضحك أن جوانب مختلفة من هذا ظهرت مرتين اليوم في العمل.

في الصباح ، كان لدينا جوليا العلاقات العامة التي استخدمت && بدلاً من if ... end وأشرت إلى أنه ، كقارئ كود (مراجع العلاقات العامة) ، استغرق الأمر جهدًا إضافيًا (وكان من السهل تفويته ) الفروع التي قد يتم تنفيذها أو لا يتم تنفيذها. كان المثال على شكل a() && b!() حيث b! متغير للغاية. (في هذه الحالة ، قام b!() بنقل الملفات أو حذفها في نظام الملفات ، والتي بدت خطيرة على الفور ، لكن عقلي لم يستطع معرفة أن هذا كان مشكلة فقط عندما !a() وهذه الحالة كان في الواقع محصنًا بشكل صحيح ضد).

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

موقفي من هذه المشكلة طوال الوقت هو أن استخدام && (أو || ) هو بناء جملة قصير للتفرع يمكن قراءته فقط من قبل الأشخاص الذين لديهم خلفية PL قوية ، وحتى بعد ذلك يضيف القليل من الحمل المعرفي / المرئي (ببساطة للتمييز بين & مقابل && ). أشعر أنه عند العمل في فرق متعددة التخصصات (خليط من العلماء ومهندسي البرمجيات) ، فإن ذلك يؤدي إلى إرباك نصف الفريق. حتى كمهندس برمجيات ، أشعر أن لدينا انفصالًا غريبًا بين &(::Bool, ::Bool) --> Bool والمنطقي &&(::Bool, ::Any) --> Any (نعم ، هذا الأخير ليس في الواقع وظيفة ، لكن آمل أن تحصل على وجهة نظري) . بصرف النظر عن الأنواع نفسها ، أتوقع في جوليا عادةً أن يكون الأول "وظيفيًا" بينما يتضمن الشكل الأخير غالبًا آثارًا جانبية محتملة - خاصة في التعبير الثاني.

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

في بعض الحالات ، أعتقد أن "الأولوية" تكون أكثر وضوحًا مع if a then b :

guard && c += 1    # probably an error because it's parsed as (guard && c) += 1
guard && (c += 1)  # parentheses required 

if guard then c += 1  # no ambiguity here

كما أن تمييز بناء الجملة في المحررين سيساعد في وضع علامة if في بداية التعبير.

كما أن لها فائدة من وجود سابقة في لغات أخرى ، والتي لا يبدو أنها بناء الجملة if - then بدون end .

وتجدر الإشارة إلى أن _ هناك الكثير_ من السوابق لبناء جملة if-then-else :

ويمكن استخدام هذا النحو مع سطر واحد في جميع اللغات المذكورة أعلاه.

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

يبدو لي أن خيارات ماس ​​كهربائى لـ "&&" و "||" تُستخدم لأننا نريد عبارات if بسيطة في سطر واحد ، بدون فاصلة منقوطة. لكن يبدو أن قصر الدائرة كحل يخلق مشكلة أخرى: بصفتك هامامًا ، من الصعب فهم هذا النحو وتحليله دون أن يبدو عليه من قبل ، أو معرفة أن التعبير الثاني لا يتم تقييمه إلا عند الضرورة. يبدو أن القراءة غير البديهية (كإنسان) ناتجة عن عيوب بصرية ومنطقية مع قصر الدائرة. حتى أنه يبدو أنه بعد معرفة ما تعنيه ، قد تكون القراءة أصعب مما ينبغي.

إذا لم أكن مخطئًا ، فيمكن إصلاح كلتا المشكلتين باستخدام ماكرو:

if نتيجة الشرط

يمكن التعامل مع النفي مع! قبل الشرط ، أو بدلاً من ذلك ، ماكرو ifnot . أنا فقط ، أم أن هذا خالي من الغموض بالنسبة للكمبيوتر ، ويسهل قراءته للإنسان ، وكل ذلك في سطر واحد؟

حتى أنه يبدو أنه بعد معرفة ما تعنيه ، قد تكون القراءة أصعب مما ينبغي.

^ أنا أتفق بشدة مع هذا.

if نتيجة الشرط

يمكنك بالفعل القيام بما يلي ، والذي يبدو متشابهًا تقريبًا:

if condition result end

يوجد أدناه ماكرو لبناء جملة if-then-else الكامل. ومع ذلك ، نظرًا لأن if و else كلمات رئيسية محجوزة ، فإن الماكرو يستخدم If و Then و Else بدلاً من ذلك.

syntax_error() = error("Valid syntax is either `<strong i="20">@If</strong> cond Then ex` or `<strong i="21">@If</strong> cond Then ex1 Else ex2`")

function If(exprs...)
    n_args = length(exprs)

    if n_args == 3
        if exprs[2] != :Then
            syntax_error()
        end

        ex = quote
            if $(exprs[1])
                $(exprs[3])
            end
        end
    elseif n_args == 5
        if ( exprs[2] != :Then ) || ( exprs[4] != :Else )
            syntax_error()
        end

        ex = quote
            if $(exprs[1])
                $(exprs[3])
            else
                $(exprs[5])
            end
        end
    else
        syntax_error()
    end

    return esc(ex)
end

macro If(exprs...)
    If(exprs...)
end

foo(x) = <strong i="22">@If</strong> x > 0 Then println("greater than zero") Else println("less than zero")

وهنا يمكننا رؤية foo أثناء العمل:

julia> foo(3)
greater than zero

julia> foo(-3)
less than zero

أفضل شيء مثل

x0 = 1
x1 = 2
x3 = 3 when y>0  # y>0 is evaluated first
x4 = 4

عندما يكون لها أسبقية أقل من = وتعمل من اليمين إلى اليسار.

يمكنك بالفعل القيام بما يلي ، والذي يبدو متشابهًا تقريبًا:

if condition result end

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

if condition result end

يجعل استخدام && فائضًا تمامًا ، وبالتالي لا توجد مشكلة! أرى أنه يمكن للمرء حتى القيام بما يلي:

if condition result_1 else result_2 end

في هذه الحالة ، من المحتمل أن تكون إضافة الكلمة الرئيسية end أسهل من إنشاء ماكرو. لكن شكرًا على الوقت الذي استغرقته لجعل الأمر على أي حال ^ _ ^ هل هو فكرة جيدة لإضافة إمكانية إلى عبارات if ذات السطر الواحد في الوثائق؟ أرى أنه إذا قام أحدهم بعمل ?If<enter> فإن النتيجة هي بالفعل بضعة أسطر ... لكني أشعر أنه يجب الإعلان عن هذه الميزة أكثر.

فيما يتعلق بالمناقشة الأصلية ، أؤيد إضافة "If x ثم y" ، على الرغم من أنني أجدها مكررة قليلاً مع إصدار سطر واحد من "if". لكن مهلا ، اكتب كودًا كيفما كان منطقيًا بالنسبة لك ، أليس كذلك؟

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