Powershell: اقتراح: تنفيذ الاندماج الصفري ، والوصول المشروط الفارغ (الامتصاص الصفري) ، والتعيين الشرطي الصفري

تم إنشاؤها على ٢ مارس ٢٠١٧  ·  71تعليقات  ·  مصدر: PowerShell/PowerShell

سيكون التوحيد الفارغ والوصول الشرطي الصفري (الامتصاص الصفري) إضافات مفيدة للغة.

_Update_: تقترح BrucePay بالإضافة إلى ذلك ، الخالي المشروط_ ، مع ?= - انظر التعليق أدناه .

على سبيل المثال ، بدلاً من الكتابة:

if ($null -ne $varThatMayBeNull) { $varThatMayBeNull } else { $fallbackValue }
#
if ($null -ne $varThatMayBeNull) { $varThatMayBeNull.Name } else { $null }

يمكن للمرء أن يكتب:

$varThatMayBeNull ?? $fallbackValue  # null-coalescing
# 
$varThatMayBeNull?.Name   # null-conditional access, for Set-StrictMode -Version 2+
$varThatMayBeNull?[42]  # ditto, with indexing

إعادة الوصول المشروط: مع إيقاف تشغيل Set-StrictMode (الافتراضي) ، يمكنك فقط استخدام $varThatMayBeNull.Name - لا حاجة إلى بناء جملة خاص ؛ ومع ذلك، إذا Set-StrictMode -Version 2 أو أعلى هو في الواقع، $varThatMayBeNull.Name سوف _break_ وأن حيث المشغل-اغية مشروط ( ?. ) مفيد، للإشارة إلى نية صريحة لتجاهل $null بطريقة موجزة.


سؤال مفتوح :

$varThatMayBeNull?[42] يعالج الحالة التي يكون فيها المتغير $null ، لكن إذا لم يكن كذلك ، يجب أن يوجد عنصر مصفوفة بالفهرس المحدد.

لذلك سيكون من المفيد أيضًا جعل _indexing_ فارغة-شرطية - شيء تدعمه C # _لا _ بالمناسبة (عليك استخدام .ElementAtOrDefault() ).

الخياران الأساسيان هما:

  • ابتكر بناء جملة إضافي يشير صراحة إلى نية تجاهل _index_ غير موجود:

    • السؤال هو ما هي الصيغة التي يجب اختيارها لهذا ، بالنظر إلى أن ?[...] و [...]? ليسا خيارين بسبب الغموض.
    • ربما [...?] ، لكن هذا يبدو محرجًا.
  • اعتمد على السلوك الحالي فيما يتعلق بالوصول إلى المؤشرات غير الموجودة ، كما يتضح من إعداد Set-StrictMode - انظر الجدول أدناه .


ذات صلة: تنفيذ الشرطية الثلاثية

Issue-Enhancement Resolution-Fixed WG-Language

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

rjmholt لقد هنا . تحليل سريع: من بين ما يقرب من 400000 نص برمجي يحتوي على 22.000.000+ اسم متغير (ليس فريدًا) ، كان هناك فقط 70 متغيرًا فريدًا انتهى بـ ? .

ال 71 كومينتر

@ mklement0 يبدو أن النموذج الثاني يعمل حسب التصميم بدون "؟".
ربما تتغير إلى name() ؟

iSazonov : نقطة جيدة ، لكنها تعمل فقط بدون ? ما لم يكن Set-StrictMode -Version 2 أو أعلى _not_ - لقد قمت بتحديث المنشور الأولي لتوضيح ذلك.

أعتقد أن السكر النحوي هو شيء يمكن أن يستخدمه بوويرشيل وتستمتع به اللغات الأخرى. +1 على الاقتراح.

خذ بعين الاعتبار العينات التالية من لغات أخرى:

a="${b:-$c}"
a = b || c;
a = b or c
a := b ? c
a = b ? b : c;

حتى في

a = b if b else c

أفضل من

if (b) { a = b } else { a = c }

وغالبًا ما تحتاج إلى التوضيح مع الإسهاب الإضافي

a = (if (b -ne $ null) {b} else {c})

يجعل المرء يشعر وكأنه متسخ ومضروب.

وجدت نفسي أفعل هذا اليوم كعمل.

`` بوويرشيل
$ word = ($ null، "two"، "three"). أين ({$ _ -ne $ null}، "First")
""

أستخدم نمطًا مشابهًا:

$word = ($null, "two", "three" -ne $null)[0]

kfsone يوجد خطأ بسيط في المثال الخاص بك $a=(if ($b -ne $null) { $b } else { $c }) . يجب أن يكون $a=$(if ($b -ne $null) { $b } else { $c }) ولكن الإصدار الوحيد من PowerShell حيث كان $( ) مطلوبًا كان الإصدار 1. بدءًا من الإصدار 2 وما بعده ، يمكنك ببساطة القيام بما يلي:

$a = if ($b) { $b } else { $c }

bgshacklett ألا تقصد $word=($null,'two')[$null -ne 'three'] ؟

من المؤسف بعض الشيء أن هذا انتقل من 6.1 إلى 6.2 إلى "المستقبل".

@ TheIncorreful1 لا ، إذا قمت بنسخ ولصق ما أضفته أعلاه ، يجب أن ترى أنه تم تعيين قيمة $word على "two". هناك المزيد من التفاصيل في إجابة Stack Overflow حيث رأيت النمط لأول مرة:
https://stackoverflow.com/a/17647824/180813

في حين أن عمليات الاختراق المرنة تجذبني منذ 20 عامًا والتي كتبت شيبانغ سجلت و / أو استفسرت عن سجل مستخدم أو منظمة RIPE-DB ، فإن ما أتمناه من بوويرشيل هو شيء يشجع زملائي على استخدام اللغة بدلا من زرع الخوف فيهم.

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

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

نعم. هناك بعض الحيل الأنيقة الممكنة في PS والتي تعتبر رائعة في حالة الضرورة أو إذا كنت بحاجة إلى اختصار لمرة واحدة.

بالنسبة إلى الكود القابل للصيانة ، من الناحية المثالية ، يجب أن يكون لدينا عوامل دمج صفرية واضحة مثل C #. المشكلة الرئيسية بالنسبة لي هي - ما الذي نستخدمه لهؤلاء؟ ? غير مستعارة بالفعل إلى Where-Object (بقدر أحب لذلك إلى أن تمحى، انها في الاستعمال الشائع جدا). ضع في اعتبارك أن اسم % مستعار إلى ForEach-Object لكن هذا لا يعيق عمليات المعامل ، لذلك من الناحية النظرية على الأقل ، فإن وجود ? سيكون عامل اندماج صفري أيضًا. غرامة؛ سيتم تفسيره فقط على هذا النحو في التعبيرات ، حيث لا يكون Where-Object صحيحًا على أي حال.

@ vexx32 :

على الأقل _syntactically_ ?? يجب أن يكون جيدًا ، لأننا نتحدث عن وضع _expression_ ، بينما ? ، كأمر [اسم مستعار] ، يتم التعرف عليه فقط في وضع _argument_.
لست متأكدًا مما إذا كانت إعادة استخدام الرمز تسبب التشويش ، لكنها لن تكون المرة الأولى التي يقوم فيها الرمز بواجب مزدوج في سياقات مختلفة.

من المثير للدهشة أن استخدام ?. و ?[] للنقع الصفري سيكون من الناحية الفنية تغييرًا فاصلاً ، لأن PowerShell يسمح حاليًا ? كحرف غير أولي في اسم متغير.

PS> $foo? = @{ bar = 1 }; $foo?.bar   # !! $foo? is a legal variable name
1

ومع ذلك ، آمل أن يتم اعتبار هذا التغيير على شكل دلو 3: تغيير

لا أستطيع أن أقول أنني رأيت أي شخص يستخدم؟ في اسم متغير ... ولن أفعل ذلك ، لأنه من المحتمل أن يساء فهمه. لكن نعم ، آمل أن يكون ذلك صالحًا للاستخدام تمامًا.

أظن أن طرح هذا الأمر متأخر بعض الشيء ، لكن Bash تعاملت مع هذا (وبعض الحالات الأخرى) من خلال ميزات Parameter Substitution الخاصة بها: https://www.tldp.org/LDP/abs/html/parameter-substitution.html.

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

bgshacklett :

نعم ، يعد استبدال المعلمات أمرًا فعالاً ، ولكنه ، للأسف ، ليس مجرد وسيلة للتعلم ، ولكن أيضًا للتذكر.

لذلك ، في حين أن ميزات Bash غالبًا ما تكون مثيرة للاهتمام ، إلا أن شكلها النحوي غالبًا ما يكون غامضًا ويصعب تذكره ولا يناسب PowerShell.

_توسيع النطاق _ (على سبيل المثال ، a{1,2,3} في bash يتوسع إلى a1 a2 a3 ) هو مثال على ميزة مثيرة للاهتمام أحب أن أراها في PowerShell ، ولكن مع PowerShell مناسب النحو - راجع # 4286

أنا أتفق تماما. لقد طرحته كمثال على كيفية حل هذه المشكلة في مكان آخر أكثر من حلها الدقيق.

هناك عامل آخر يجب مراعاته:

$x ?= 12

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

تمديد هذا إلى الخصائص:

$obj.SomeProperty ?= 13

ستضيف وتهيئ خاصية ملاحظة SomeProperty على الكائن إذا لم تكن موجودة.

و - للمتعة - شكل آخر عند تهيئة متغير باستخدام -or :

$x -or ($x = 3.14) > $null

تبدو فكرة $x ?= 12 رائعة.

لقد خطر لي أنه من المحتمل أن نطبق كل هذه العوامل ليس فقط إذا لم يكن LHS موجودًا ، ولكن أيضًا إذا كان موجودًا ولكنه يحتوي على_ $null (مع [System.Management.Automation.Internal.AutomationNull]::Value تعامل مثل $null في هذا السياق).

إضافة وتهيئة خاصية ملاحظة SomeProperty

في هذا السياق ، يكون $obj.SomeProperty ?= 13 منطقيًا بالنسبة لي _ فقط_ إذا كان .SomeProperty موجودًا ويحتوي على $null ، نظرًا لأنه لا يمكنك إنشاء خصائص ضمنيًا حتى مع التعيينات العادية (على النقيض من ذلك ، لـ _hasthables_ the إنشاء الدخول الضمني أمر منطقي).

سيحتاج جميع المشغلين الذين تمت مناقشتهم إلى إعفاء LHS من فحص الوجود الصارم.

أنا أتساءل عن القصد / المنطق وراء لماذا يمنعك الوضع الصارم من الوصول إلى خاصية غير موجودة. هل نية اكتشاف الأخطاء المطبعية مثل $x.pretnd ؟ هل القصد من التحقق من الافتراضات مثل assert(x != null) ؟ هل نية منع نشر $null عن طريق الخطأ في شفرتك؟

نقع القيمة الصفرية (؟.) مفيد ، للإشارة إلى النية الصريحة لتجاهل $ null بطريقة موجزة.

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

إذا كان StrictMode له غرض حيث يكون الوصول إلى خاصية غير موجودة وإرجاع $null ممنوعًا ، فلن ينطبق نفس المنطق على ?. ، وهذا يجب أن يطرح نفس الاستثناء للسبب نفسه . إذا لم يكن كذلك ، فلماذا؟

باستخدام الاندماج الصفري ، يمكنك كتابة:

$result = Invoke-RestMethod -Uri 'https://example.org/api/test'
$test = $result?.Name

هل سيصبح من المستحسن أو المصطلح استخدام ?. دائمًا لكل مرجع خاصية ، لأنه "يتصرف مثل . ، ولن يطرح استثناءات للأشخاص الذين يستخدمون الوضع المتشدد"؟

هي الرغبة الحقيقية في الحصول على وضع صارم قابل للتكوين مع إعدادات متغيرة ، بحيث يمكن على سبيل المثال أن يكون لديك تصريح في الجزء العلوي من البرنامج النصي الخاص بك # StrictMode SkipMemberExistenceCheck ، أو خاصية فتحة الهروب للإشارة إلى كتلة unstrict code عموما؟ [أظن أن الرغبة في بناء جملة أسلوب C # مقتضب ، لكنك تعرف ما أعنيه]

شكرا على الأفكار ، HumanEquivalentUnit.

هل نية اكتشاف الأخطاء المطبعية مثل $x.pretnd ؟

لا يمكنني التحدث عن نية التصميم ، لكن هذا ما يبدو منطقيًا بالنسبة لي - مشابه لما يفعله Set-StrictMode -Version 1 لـ _variables_ (فقط).

مع المتغيرات ، يتعلق الأمر بوجودها ، وليس ما إذا كانت القيمة هي $null ، ويتبع التحقق من وجود الخاصية نفس النمط.

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


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

نعم ، ولكن في الوضع غير الصارم ، تتخلى عن عمليات التحقق من الوجود المذكورة أعلاه ، ومن الواضح أن الاختبار يدويًا مرهق للغاية - وأبطأ دائمًا من الميزة المضمنة.

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

النقطة المهمة هي أنه مع Set-StrictMode -Version 2 أو أعلى ، ستحصل على:

  • فائدة التحقق من وجود العضو _ افتراضيًا_
  • خيار إلغاء الاشتراك ، _ عند الطلب ، بإيجاز_ .?

يمكن أن يكون لديك إعلان في الجزء العلوي من البرنامج النصي الخاص بك # StrictMode SkipMemberExistenceCheck ، أو سمة فتحة الهروب للإشارة إلى كتلة من unstrict code بشكل عام

ذات صلة: النطاق الديناميكي الحالي Set-StrictMode يمثل مشكلة ؛ رؤيةlzybkr الصورة مشروع RFC لتنفيذ وضع صارم _lexical_: https://github.com/PowerShell/PowerShell-RFC/blob/master/1-Draft/RFC0003-Lexical-Strict-Mode.md

فائدة التحقق من وجود العضو بشكل افتراضي

يحتوي PS على رمز يقوم بفحص الأعضاء ، ويعيد $ null عندما لا يكونون موجودين. هذه ميزة بشكل افتراضي ، والتي يمكنك أيضًا تجنبها عن طريق كتابة اختبار وجود العضو الخاص بك باستخدام $x.psobject.properties... إذا اخترت ذلك. يزيل StrictMode هذه الميزة ويترك عقبة الاضطرار إلى كتابة اختبارات الوجود. ثم بدلاً من إعطاء طريقة لطيفة لكتابة اختبار وجود العضو بالضبط ، يمنحك ?. حلاً موجزًا ​​للحصول على ما كان يفعله دائمًا . . وإذا كان وجود العضو مهمًا ، فلا يزال يتعين عليك ترميزه بشكل منفصل.

لكن هذا يجعلني أسأل ماذا عن استدعاءات الطريقة:

$x.pretend     -> $null
$x.pretend()   -> Exception MethodNotFound
$x?.pretend  -> $null
$x?.pretend()   -> ____ what goes here? $null?

set-strictmode -version 2
$x.pretend -> Exception PropertyNotFoundStrict
$x.pretend()  -> Exception MethodNotFound
$x?.pretend  -> $null
$x?.pretend()   -> ____  ?

على سبيل المثال ، سيتصرف ?. مثل . لعمليات البحث عن الممتلكات في الوضع غير المقيد ، ولكن سيتصرف بشكل مختلف عن . لاستدعاءات الطريقة في الوضع non -rictmode ، مما يجعلها دقيقة وليست بديل قطرة. هل هذا يعني أنه عند استخدام ?. لن يكون لديك أي طريقة على الإطلاق لمعرفة ما إذا كان قد تم استدعاء طريقة أو لم يحدث أي شيء على الإطلاق؟ يمكن دعم الخصائص من خلال أساليب getter ، لكنني أعتقد أنه من الاصطلاح في DotNet ألا يقوم الحاصلون على تغيير الحالة الداخلية ، ولكنه أمر طبيعي لاستدعاءات الأسلوب لتغيير الحالة. باستخدام ?. لن يكون لديك أي فكرة عما إذا قمت بتغيير حالة الكائن؟

أتساءل عما إذا كان بإمكانك الحصول على الفوائد المرجوة ، والأفضل من ذلك ، من خلال جعل ?? قادرًا على التعامل مع استثناءات PropertyNotFoundException و MethodNotFound مباشرة من التعبير الموجود على اليسار (ولكن ليس الاستثناءات الأخرى التي أثيرت داخل الطرق) ، وكذلك التعامل مع $ خالية ، وليس لديك ?. على الإطلاق. على سبيل المثال

$varThatMayBeNull ?? $fallbackValue # null-coalescing
#
$varThatMayBeNull.Name ?? $fallbackvalue    # catching PropertyNotFoundStrict exception
$varThatMayBeNull.Name ??  # default fallback is $null
$varThatMayBeNull.Method() ??  # catching MethodNotFound Exception

# and potentially addressing the index case too
$varThatMayBeNull.first.second[3].Method() ??  # catching MethodNotFound Exception, or index not found Exception

وبعد ذلك ، بدلاً من ?. استدعاء عضو أو الوصول إلى خاصية ، يمكن أن تكون طريقة موجزة للسؤال عما إذا كان العضو موجودًا ، وإرجاع [bool].

باستخدام نفس إضافة بناء الجملة البالغة ?? و ?. يمكنك التعامل مع المزيد من المواقف ، مع تداخل أقل إرباكًا.

يزيل StrictMode هذه الميزة ويترك عائق الاضطرار إلى كتابة اختبارات الوجود

عائق أحدهم هو منفعة لشخص آخر:
كل هذا يتوقف على ما تريد أن يحدث _ افتراضيًا_:

  • إذا كنت واثقًا من عدم وجود _typos_ في التعليمات البرمجية الخاصة بك - بكل الوسائل ، استفد من السلوك _ الافتراضي_ (إيقاف الوضع الصارم) - ولن تحتاج إلى .? (للوصول إلى _property_ - راجع التعليق التالي re _method calls_ and _indexing_).

    • في ملاحظة _ شخصية: أميل إلى استخدام Set-StrictMode -Version 1 لتجنب الأخطاء المطبعية في أسماء _variable_ ، لكني أجد -Version 2 أو أعلى مزعجًا للغاية ، ويرجع ذلك أساسًا إلى # 2798 (وهو خطأ مستقل عن هذا الاقتراح).
  • إذا كنت تريد التأكد من أنك (أ) لم أخطأت في كتابة أسماء الخصائص و / أو (ب) لا تعمل شفرتك بطريق الخطأ على أنواع بيانات أخرى غير التي كنت تقصد العمل عليها ، فقم بتعيين الوضع المقيد على الإصدار 2 أو أعلى .

    • في الواقع ، هذا _ حاليًا_ يجعل من الصعب _ اختيار الخروج _ من هذه الشيكات عند الطلب ،
    • وهذا هو سبب اقتراح إدخال الوصول المشروط هنا بالتحديد: لتسهيل الانسحاب عند الطلب.

يعد الاختبار الصريح لوجود عضو حالة استخدام منفصلة يمكن أن تكون ضرورية بغض النظر عن الوضع الصارم الساري.

بالنسبة إلى _مكالمات الأسلوب_ التي لا يغطيها البروتوكول الاختياري:

_مكالمات الأسلوب_ (على سبيل المثال ، $varThatMayBeNull.Method() ) و _indexing_ (على سبيل المثال ، $varThatMayBeNull[$index] ) هما حالتان حيث يتم إيقاف تشغيل الوضع المتشدد أو في الإصدار 1 ، نظرًا لأن كلتا الحالتين حاليًا _ بشكل متغير _ تتسبب في حدوث خطأ إذا القيمة التي يتم الوصول إليها هي $null .

سيكون بناء الجملة هو نفسه بالنسبة لخصائص الطرق - $varThatMayBeNull?.Method() - ومماثل للفهرسة - $varThatMayBeNull?[$index] - كما في C #.

_Update_: هناك جانب آخر للفهرسة ، أي إذا كان المتغير غير فارغ ، لكن العنصر في الفهرس المحدد غير موجود (على سبيل المثال ، $arr = 0,1; $arr[2] ). مع الإصدار 2 من الوضع المقيد أو إصدار أقل ، يتم تقييم هذا إلى $null ، ولكن في الإصدار 3 أو أعلى يتسبب في حدوث خطأ ، وسيكون من الجيد أن تكون قادرًا على إلغاء الاشتراك في هذا الخطأ أيضًا. ومع ذلك ، فإن بناء الجملة لهذه الحالة يمثل تحديًا - راجع OP المحدث ، والذي يقترح حاليًا ربما [...?] محرجًا.

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

لاحظ أن C # لا تحتوي على فهرسة شرطية خالية بالمعنى الثاني.

يحتوي على فهرسة شرطية خالية ، ولكن ليس تمامًا كما تقترح. يسمح C # (أنا متأكد تمامًا ، على الأقل ...) array?[0] الذي يتجاوز مشكلة "الفهرس إلى مصفوفة / مجموعة فارغة" ويعيد القيمة فارغة.

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

@ vexx32 ، هذا هو أحد جوانب الفهرسة الشرطية الخالية: إذا كان array في array?[0] هو null ، يتم تجاهل عملية الفهرسة - C # لديها ذلك أيضًا ، كما ذكرت.

كنت (تحديث: _also_) أتحدث عن جانب _other_ للفهرسة الشرطية الخالية: الحالة التي يكون فيها array في array?[0] _not_ null ولكنه _the العنصر في الفهرس 0 _ غير موجود.

إنه الأخير الذي لا يمكن تجاهله في C # ، على حد علمي ، ومع ذلك أعتقد أنه سيكون مفيدًا أيضًا.

هل يمكنك التفكير في المصطلحات لإعطاء هذين الجانبين أسماء مميزة؟

ستتحول الشفرة من مشكلة JavaScript أخرى من $_.Description[0].Text إلى $_?.Description[0?]?.Text والتي أعتقد أنها ليست جميلة ؛ واقتراحي الآخر لكيفية تصرف ?? سيأخذ الأمر إلى $_.Description[0].Text ?? وهو أمر ألطف بشكل شخصي ، وسيتعامل - إن أمكن - مع الإخفاقات في أي نقطة بحث في السلسلة دفعة واحدة ، ولا يزال يسمح لك باختيار ما تريد حدوثه افتراضيًا ، ولديك احتياطي مختلف حسب الرغبة بدلاً من أن يقتصر على $null .

جانبا ، هل سيكون بناء الجملة هذا ?. تناظريًا للخصائص والطرق الثابتة ، مثل $t = [int]; $t::MaxValu; $t::Pars("1") ، هل ستصبح ?: أو ?:: ؟

ما هو السلوك المطلوب لفهرسة المصفوفة مع تحديد أكثر من فهرس؟ $array[0,4?,1,2] حيث يمكن السماح لكل واحد منهم بالفشل ، أو $array[0,4,1,2?] مع السماح للنجاح أو الفشل فقط؟

يجب أن أتراجع أولاً ، لأنني أدركت أنني خلطت بين الجوانب التي تستحق الفصل ، على الأقل من الناحية المفاهيمية:

  • _Null-value_- وصول مشروط للعضو أو الفهرس ، كما في C #:

    • إذا كانت القيمة التي يتم الوصول إليها هي $null ، فتجاهل محاولات الوصول إلى أعضائها أو الفهرس فيها وتقييمها إلى $null .
  • _العضو -وجود_ -العضو المشروط أو الوصول إلى الفهرس الخاص بـ PowerShell:

    • إذا كانت القيمة التي يتم الوصول إليها هي _non- $null _ ، فتجاهل محاولات الوصول إلى _members_ غير الموجودة (الخصائص ، واستدعاءات الأسلوب ، والفهرسة) غير الموجودة.

ملاحظة: للإيجاز ، أستخدم هنا _member_ بشكل فضفاض إلى حد ما لتشمل أيضًا _ عناصر_ من الكائنات التي تصادف أن تكون مجموعات ، والتي يتم الوصول إليها باستخدام _indexing_ بدلاً من تدوين النقطة.

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

@ mklement0 أعتقد أنك تناقش من وجهة النظر " شخص واحد يستخدم الوضع المتشدد لتحسين شفرته الخاصة " وأنا من وجهة النظر " يمكن لشخص آخر تشغيل الكود الخاص بي في وضع صارم ، ما هي التغييرات التي ستجعل الكود الخاص بي يعمل معهم أيضًا؟ "وهذا يقودني إلى تفكير مختلف. باستخدام ?. ، سيكون من المناسب جدًا استخدامه بدلاً من . وجعل الكود يعمل أيضًا في وضع صارم يمكنني استخدامه أيضًا في كل مكان بشكل معتاد ؛ لا أفقد شيئًا وأحصل على التوافق. أخشى أن جميع رموز PowerShell سوف تتقلب بهذه الطريقة لأنها "تعمل" في المزيد من الحالات.

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

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

HumanEquivalentUnit كيف تسكت هذه الأشياء؟ سيتعين عليك كتابة تحميل معالجة الاستثناءات والتحقق من القيمة الفارغة مسبقًا ، بدلاً من ذلك:

$prop = $item?.Method().PropIwant ?? 'PropActionFailed'

الخامس.

$prop = if ($null -ne $item) {
    $propIwant= $item.Method().PropIwant
    if ($null -eq $propIwant) {
        'PropActionFailed'
    }
    else {
        $propIwant
    }
}

وهذه الحالة ليست غير شائعة. أو تقوم فقط برمي $ErrorActionPreference = 'Stop' وتلف كل شيء في try/catch لتبسيط التحقق من القيمة الفارغة وهو نمط سيء (منطق مدفوع بالاستثناء).

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

@ mklement0 أعتقد أنك تناقش من وجهة النظر "_ شخص يستخدم الوضع المتشدد لتحسين كوده_" وأنا من وجهة النظر "يمكن لشخص آخر تشغيل الكود الخاص بي في وضع صارم ، ما هي التغييرات التي ستجعل الكود الخاص بي يعمل معهم أيضًا؟ _ "

هل نتحدث عن مكافئ "set -euo pipefail" (وضع bash الصارم)؟

أ- الحد من عمليات البحث المتغيرة (على الرغم من أنني لا أرى سبب اعتقادك أن إجراء فحص فارغ بسيط على عمليات البحث عن الأعضاء سيكون أمرًا سيئًا ، إلا أن البحث الفعلي عن العضو أغلى بكثير من if (result is null) )
ب- استخدم [Strict] على النطاقات / قوالب الكود لإخبار المحلل اللغوي أن يعاملهم على هذا النحو ،
ج- يعتمد الصرامة على النطاق: الكود الذي لم يتم تعليمه صارم ليس صارمًا.

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

# Their code
Function Log($Message) { Write-Host $Massege }  # not strict

# My code
[Strict]
Function DebugMsg
{
  Param([String] $Message)
  if ($DEBUG) { Log Host $Message }
}

# Your code
DebugMsg "Hello"  # you didn't define DEBUG, and by saying strict I expressed a contract whereby the variable MUST be defined.

لم يتم وضع علامة صارمة على وظيفة "السجل" لذا فهي لا تشكو من الخطأ المطبعي

🤔 الآن بعد أن ذكرت ذلك ، ستكون السمة [Strict()] طريقة _ رائعة_ لتطبيق الوضع المتشدد بطريقة مقيدة بالنطاق. يجب ذكر ذلك في سلسلة مشكلات أخرى حول مشكلات الوضع الصارم ، سأبحث عن ذلك وأعود إلى هنا ...

@ TheIncorreful1 " كيف يتم إسكات هذه الأشياء؟ " في الوضع غير المقيد يكون $null.x صامتًا ، و $null.x() استثناء. مع ?. كما تمت مناقشته ، $null?.x صامت ، $null?.x() صامت.

لذلك سيكون لديك . والذي يعمل مثل C # ?. ، باستثناء الوضع المتشدد حيث يطرح استثناءات. ثم سيكون لديك ?. والذي يعمل في الوضع الصارم مثل C # ?. ومثل PowerShell's . يعمل في الوضع غير المقيد ، ولكنه يعمل بشكل مختلف عن PowerShell . في الوضع غير المقيد لاستدعاءات الطريقة. يا له من تركيبة مروعة ، (ومجموعة حيث من الواضح أن ?. أفضل وأكثر فائدة في المزيد من تلك السيناريوهات).

سيكون عليك كتابة تحميل معالجة الاستثناءات والشيكات الفارغة مسبقًا ، بدلاً من ذلك: $prop = $item?.Method().PropIwant ?? 'PropActionFailed'

قد يؤدي استدعاء الأسلوب الخاص بك إلى طرح أو إرجاع $ null وقد يكون PropIWant مفقودًا ، ولا يزال يتعين عليك كتابة:

$prop = try {
    $item?.Method()?.PropIwant ?? 'PropActionFailed'  
} catch [someMethodException] {
    'PropActionFailed'
}

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

$prop = $item.Method().PropIWant ?? 'AnythingFailed'

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

كم مرة تكتب . في PowerShell؟ كم مرة تريد أن تشرح للمستخدمين الجدد الفرق بين . و ?. وأخبرهم أن عليهم مراعاة الفرق في كل مرة يكتبون فيها . إلى الأبد ؟

"أوه ، كيف حدث ذلك؟" "حسنًا في C # . طرح استثناءً للأعضاء المفقودين ، لذلك اخترعوا ?. وهو ما لم يفعل. كان ذلك رائعًا ، لذا فعلوا ذلك في PowerShell افتراضيًا ، . لا يرمي ثم اخترعوا الوضع المتشدد الذي يجعل . يتصرف مثل C # ويرمي ولكن فقط في هذا السياق ، لكن طريقة التحقق يدويًا من الأعضاء كانت حقًا مزعجة ومزعجة ولم يرغب أحد في كتابتها ؛ بدلا من التصدي لهذه المشكلة وجها لوجه، وجعل ذلك أكثر ملاءمة لمصلحة من strictmode، فإنها تهرب التي وaped C # الصورة ?. بدلا من ذلك للحصول على طريقة متستر من الصرامة التي سألت عنها، وهو مناسب بشكل معتدل بالنسبة لك ، ولكنه مقرف للآخرين. ولا يزال لديك أي اختبار لوجود الأعضاء ، والاستفادة من الوضع المتشدد لا يزال كلامًا ومزعجًا ، ولكن على الأقل ليس عليك أن تعاني من ذلك لأن "الوضع المتشدد" به فتحة هروب "الوضع العادي" الآن". ايك.

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

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

لا أعتقد أن هذا سيكون سيئًا ، لأن PS non -rictmode تفعل ذلك بالفعل ، وأعتقد أن هذا سيكون بديلاً مرغوبًا فيه عن ?. المقترح - مختلف جدًا ومفيد في مواقف أكثر.

لكن لاحظ أنه في PS يمكنك فعل شيء لا تستطيع C # القيام به:

(1..3)[1kb..100kb]

ولا توجد استثناءات في الوضع غير المقيد. غيّر الأرقام وانظر إلى الوقت الذي تستغرقه ؛ بالحكم على الأداء وكيف أعتقد أنه يجب أن يعمل خلف الكواليس للفهرسة إلى كائنات عشوائية ، يبدو أن هناك في الواقع ~ 100،000 استثناء يتم رفعها وإسكاتها ، من أجل راحتنا. لا تجعل PS دائمًا خيار "يجب أن يكون أسرع ما يمكن ، ودفع الإزعاج على المستخدم" ، وأنا أحب ذلك في ذلك.

HumanEquivalentUnit هناك العديد من الميزات في كل لغة قد لا تستخدمها أبدًا في حياتك المهنية ، وإذا لم يعجبك الأسلوب ، فلا بأس بذلك ، فأنت لست بحاجة إلى استخدام هذه الميزات. لا أفهم لماذا تكتبين الوضع المتشدد ؛ إنها ممارسة جيدة في النصوص ، لذا فأنت تتعامل بوعي مع المشكلات بدلاً من ترك اللغة تبتلعها (وفي جوهرها ، وجود كتل صيد فارغة ضمنية في كل مكان). مرة أخرى ، لا يزال بإمكانك عدم استخدام الميزات (على سبيل المثال ، لم أستخدم أبدًا Out-Default ).

أيضًا ، عامل التشغيل هو ? ، وليس ?. ؛ سيعمل مع الوصول إلى الفهرس أيضًا.

للاستمرار في وضع الأساس لمزيد من المناقشة ، اسمحوا لي أن ألخص كيف تؤثر الأوضاع الصارمة الحالية على الوصول المشروط للقيمة الخالية ووجود العضو (الشروط المقدمة أعلاه ):

تمثل الأعمدة أدناه إعدادات Set-StrictMode ، وتشير قيم العمود إلى:

  • 👍 ... مسموح
  • 🚫 ... محظور (يتسبب في حدوث خطأ في إنهاء العبارة)

جانبا: حقيقة أن الأخطاء هي فقط _statement-_ ، وليس _script_- إنهاء ، تتعلق بالمناقشة الأكبر حول معالجة أخطاء PowerShell - راجع https://github.com/PowerShell/PowerShell-Docs/issues/1583.

  • _Null-value_- الوصول المشروط - $obj _itself_ هو $null :

بناء | - إيقاف | - الإصدار 1 | الإصدار 2 | - الإصدار 3+
---------- | ---- | ---------- | ---------- | ------------
obj | 👍 | 🚫 | 🚫 | 🚫
obj.Prop | 👍 | 👍 | 🚫 | 🚫
$ obj [42] | 🚫 | 🚫 | 🚫 | 🚫
طريقة $ obj. () | 🚫 | 🚫 | 🚫 | 🚫

من الغريب أنه مع -Off و -Version 1 ، يُسمح بـ $obj.Prop ، بينما لا يُسمح باستخدام $obj[42] .

  • _Member -esent_-Conditional access - $obj غير- $null ، لكن العضو / العنصر الذي يتم الوصول إليه غير موجود:

بناء | - إيقاف | - الإصدار 1 | الإصدار 2 | - الإصدار 3+
---------- | ---- | ---------- | ---------- | ------------
obj.Prop | 👍 | 👍 | 🚫 | 🚫
obj $ 42 (قابل للفهرسة) | 👍 | 👍 | 👍 | 🚫
obj $ 42 (غير قابل للفهرسة) | 👍 | 👍 | 🚫 | 🚫
طريقة $ obj. () | 🚫 | 🚫 | 🚫 | 🚫

من الغريب أن الكائنات القابلة للفهرسة بطبيعتها (على سبيل المثال ، المصفوفات) تسمح بالوصول إلى العناصر غير الموجودة حتى مع -Version 2 ، بينما لا تفعل ذلك - حيث يوفر PowerShell إمكانيات فهرسة من أجل معالجة موحدة مع المجموعات.

يعد عامل التشغيل null-soaking ( null-Conditional أو Elvis in C # ) إلزاميًا تقريبًا عند التشغيل في StrictMode Latest ومحاولة الوصول إلى خاصية قد تكون موجودة أو غير موجودة. حاليا عليك أن تلجأ إلى الحيل الغبية مثل هذا:

function Get-OptionalPropertyValue($object, [string] $propertyName) {
    if (-not ([bool] (Get-Member -InputObject $object -MemberType Properties -Name $propertyName))) {
        return $null
    }

    $object.$propertyName
}

$value = Get-OptionalPropertyValue $foo "bar" # if $foo.bar exists, $value will contain its data; else $value will be $null

عندما _ حقًا_ يجب أن تكون قادرًا على كتابة:

$value = $foo?.bar # if $foo.bar exists, $value will contain its data; else $value will be $null

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

بدأت بإلقاء نظرة على هذا ووجدت بعض المشاكل.

لنفكر في ?? و ?=

$x ?= 1 و $x ?? 1 واضحان. ولكن نظرًا لأنهم مشغلون ، فنحن بحاجة إلى دعم $x?=1 و $x??1 .

المشكلة في ذلك هي $x? و $x?? كلاهما يتحقق من صحة أسماء المتغيرات في PowerShell. الطريقة الوحيدة لإزالة الغموض ستكون ${x}?=1 و ${x}??1 .

وأكثر من ذلك لوصول العضو المشروط ?. و ?[] ، سيكون علينا ${x}?.name و ${x}?[0] .
بالنسبة إلى هؤلاء ، لن يتم دعم $x ?.name و $x ?[0] .

الخيار الآخر هو إدخال تغيير كسر وعدم السماح على الإطلاق ? في اسم المتغير.

ما رأيك؟ ههههههههه

/ ccrjmholt @ daxian-dbw jamesWTruher

لم يعجبني أبدًا ولا أفهم لماذا ? اسم متغير صالح. يفتح الباب لأسماء مثل $Safe? وهو أكثر وضوحًا بشكل عام وأقل صعوبة عند كتابته كـ $IsSafe أي حال.

أعتقد أن هذا التغيير ربما كان قادمًا لفترة طويلة.

يفتح الباب لأسماء مثل $ Safe؟ والتي تكون أكثر وضوحًا بشكل عام وأقل صعوبة عند كتابتها كـ $ IsSafe على أي حال

من المثير للاهتمام أنني عبرت عن المشاعر المعاكسة. إنه مخطط كلاسيكي / تقليد روبي .

if ($questionMark?)
{
    Write-Host "That's silly!"
}

ألم يواجه المشغل الثلاثي نفس المشكلة ، حيث كانت الدقة تتطلب مسافات حول عامل التشغيل أو أقواس معقوفة حول اسم المتغير لكي يعمل بشكل صحيح مع المتغيرات التي تنتهي بـ ? ؟

أتوقع أنه مع تقديم هؤلاء المشغلين ، سيعطي PowerShell الأولوية للتعرف على ? كجزء من المشغل في بناء الجملة مثل $x?[0] ، مثل المستخدمين الذين يستخدمون أسماء متغيرة تنتهي بـ ? لتخزين مجموعة يجب أن يستخدم بناء الجملة هذا بدلاً من ذلك (حيث ستكون المسافات غير صالحة في هذه الحالة): ${x?}?[0] . نفس الشيء مقابل $x?.Name و ${x?}?.Name .

الخيار الآخر هو إدخال كسر التغيير وعدم السماح؟ في اسم المتغير على الإطلاق.

👍 نظرًا لأن هذا يعد تغييرًا رئيسيًا في الإصدار (من 6 إلى 7) ، أعتقد أنه يستحق تغييرًا مفاجئًا هنا. أتمنى أن يكون لدى GitHub بحث أفضل عن الكود لمعرفة عدد مثيلات متغيرات PS التي تنتهي بـ ? . أظن أن هذا لن يكون بهذا التأثير ولكن سيكون من الجيد التحقق من ذلك ضد GitHub. خلال 14 عامًا من استخدام PowerShell ، لم أستخدم مطلقًا ? في اسم متغير ولكن ربما هذا أنا فقط. :-)

لقد أبحرت هذه السفينة منذ فترة طويلة ، ولن أتفاجأ برؤية المتغيرات التي تنتهي بـ ? قيد الاستخدام في البرامج النصية اليوم.

في هذه المرحلة ، إذا أعطينا الأولوية لتحليل ? كجزء من عامل وليس كجزء من اسم متغير عندما يتعلق الأمر بهذه العوامل الجديدة ، فإن الأشخاص الذين يستخدمون أسماء متغيرة تنتهي بـ ? سيحتاجون لاستخدام {} أو مسافات (حيث يُسمح بالمسافات) لاستخدام هذه المتغيرات مع هذه العوامل.

من الغريب سماع عبارة "تلك السفينة أبحرت" في هذا السياق. هذا تغيير _ نسخة رئيسية_. أعتقد أنه ليس من غير المعقول أن يتغير هذا هنا.

rkeithhill لقد استخدمتها في الأشياء الشخصية ، لكنني اعتقدت أنه سيكون من غير الواضح العمل التعاوني لأنه أمر غير بديهي للمبرمجين أن يكون لديهم رموز كجزء من الأسماء المتغيرة (على غرار استخدام الرموز التعبيرية كمتغيرات)

KirkMunro يبدو أن "التوزيع حسب الأولوية" يبدو وكأنه باب مفتوح

@ vexx32 : ليس من غير المعقول حدوث تغيير ? تمامًا طالما أنهم يستخدمون {} مرفقات

لاحظ أنه يمكن أن يكون لديك اسم خاصية ينتهي بـ ? أيضًا. حاليًا ، إذا حاولت عرض مثل هذه الخاصية في PowerShell دون تغليف الاسم بعلامات اقتباس ، فستحصل على خطأ في المحلل اللغوي.

فمثلا:

PS C:\> $o = [pscustomobject]@{
    'DoesItBlend?' = $true
}
PS C:\> $o.DoesItBlend?
At line:1 char:15
+ $o.DoesItBlend?
+               ~
Unexpected token '?' in expression or statement.
+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken

PS C:\> $o.'DoesItBlend?'
True

أنا مندهش قليلاً من عدم تحليله اليوم (لماذا لا يتم تحليل ذلك؟) ، ولكن بغض النظر ، بالنسبة لمثل هذه الخصائص ، تحتاج إلى إرفاق أسمائها بين علامات اقتباس ، وفي هذه الحالة يمكنك اتباع الاقتباس بعلامة ثلاثية ، -التحالف ، وما إلى ذلك المشغل بدون فراغات وسيعمل بشكل جيد. أجد أن بناء الجملة هذا مشابه جدًا لـ ${x?}?.name ، وأنا على ما يرام مع الموقف الذي يمكنك من استخدام أسماء المتغيرات / الخصائص إذا كنت تريد ، ولكن هذه الأسماء قد تتطلب بناء جملة أو مسافات إضافية للعمل مع ثلاثي أو فارغ -* العاملين.

KirkMunro لا شيء يمنع الأشخاص من استخدام الحدود المتغيرة للمضي قدمًا إذا كانوا يريدون أسماء متغيرات مقصورة على فئة معينة. أنا أتفق مع الآخرين في أنني أتساءل ما هو الاستخدام الحالي لهذا السلوك قيد الاستخدام حاليًا.

من المحتمل أن يكون الأشخاص في PowerShell 7 من المتحمسين بالفعل وسوف يكونوا على دراية بالتغييرات العاجلة. الأشخاص الذين ليسوا كذلك ، ما زالوا يستخدمون <= v5.1 وسيستمرون في ذلك لفترة طويلة ؛ على الأرجح حتى يقوم msft بإزالته من Windows 10 (مطلقًا).

KirkMunro بالتأكيد ، لكن إزالته من الأحرف المتغيرة القياسية المسموح بها لا يمنع المستخدمين من مجرد استخدام ${Valid?} كاسم متغير على أي حال. نظرًا لأنه سيتعين عليهم القيام بذلك مع هؤلاء المشغلين بغض النظر ، أعتقد أنه سيكون من الأفضل جعله متسقًا فقط ، بدلاً من جعل ? حرفًا يعتبر - أحيانًا فقط - جزءًا من اسم متغير.

هذا بالفعل _ هو _ سيكون تغييرًا جذريًا ، وأعتقد أنه من الأفضل على الأقل أن أكون متسقًا بشأنه وأن نسير على طول الطريق بدلاً من تقديم مستوى آخر من الغموض. 🙂

adityapatwardhan أعتقد أنه سيكون من الأفضل للغة إزالة ? كحرف متغير صالح. سيمكن بسهولة كلاً من مشغلات null-soak / -coalesce والعوامل الثلاثية في صيغة مألوفة تضيف الكثير من بيئة العمل إلى عملية تأليف النص.

KirkMunro يبدو أن وجود "تحليل حسب الأولوية" يبدو وكأنه باب مفتوح

@ TheIncorreful1 : أي رمز يمكن أن يفتح الباب ? . هذا ليس معقدًا ، ولا يفتح الباب لمزيد من الأخطاء أكثر من أي تغيير آخر في الكود.

من المحتمل أن يكون الأشخاص في PowerShell 7 من المتحمسين بالفعل وسوف يكونوا على دراية بالتغييرات العاجلة. الأشخاص الذين ليسوا كذلك ، ما زالوا يستخدمون <= v5.1 وسيستمرون في ذلك لفترة طويلة ؛ على الأرجح حتى يقوم msft بإزالته من Windows 10 (مطلقًا).

@ TheIncorreful1 : ما هو الأساس / الدليل الذي لديك على هذا البيان؟ PowerShell 7 قيد المعاينة ، لذلك يستخدمه المتحمسون فقط اليوم. هذا معطى. ولكن بعيدًا عن المعاينة ، إذا كان PowerShell 7 أو إصدارًا أحدث يقدم ميزات جذابة تحتاجها الشركات ، مع دعم الوظائف التي تحتاجها ، فسيستخدمون هذه الإصدارات. هذا صحيح بشكل خاص إذا تم تثبيت PowerShell 7 مع نظام التشغيل. النقطة الوحيدة التي يلعبها المتحمسون هي المنظمات التي ليس لديها حاجة عمل لما يقدمه PowerShell 7 إلى الطاولة.

سيكون هذا بالفعل تغييرًا جذريًا ، وأعتقد أنه من الأفضل على الأقل أن أكون متسقًا بشأنه وأن نسير على طول الطريق بدلاً من تقديم مستوى آخر من الغموض. 🙂

@ vexx32 وهذا يمتد عليه. سيكون تغييرًا مفاجئًا إذا كان لديك اسم متغير ?? ، لكن احتمالية ذلك أبعد بكثير من وجود متغير ينتهي اسمه بـ ? . بخلاف ذلك ، كيف يمكن لإدخال العوامل الخالية * مع الاستمرار في دعم ? كنصوص برمجية متغيرة قياسية مسموح بها اليوم؟

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

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

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

تأمل في هذا المثال المفتعل:

$ValueIsValid? = @( $true, $false, $false, $true )

$ValueIsValid?[0]
# old behaviour? gets `$true`
# new behaviour? gets nothing, because the `?[0]` is interpreted as a null-conditional access.

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

KirkMunro إذا كان PowerShell 7 أو ما بعده يقدم ميزات جذابة تحتاجها الشركات ، مع دعم الوظائف التي تحتاجها ،

بعد أن عملت في عدد قليل من Fortune 50s مع وجود بعض قواعد الموظفين بمئات الآلاف ، حتى الابتعاد عما كان افتراضيًا في نظام التشغيل كان يمثل تحديًا (أي الانتقال إلى v5.x). لم أر أي مكان حتى الآن يتبنى Core ؛ يفضلون فقط الانتقال إلى Python من أجل التوافق المتبادل. كان تمكين ميزات Windows الاختيارية مهمة نادرة أيضًا.

أعتقد أن الشركات تعمل مع ما لديها والقاعدة المعرفية لموظفيها على البحث عن تكنولوجيا جديدة أو إصدارات لغوية لحل مشاكلهم. قد يكون البعض راضيًا تمامًا عن البقاء على الإصدار 2 إلى الأبد وعدم لمس Win10 / Server16 cmdlets التي تجعل الحياة أسهل بشكل كبير.

وجهة نظري في كل هذا ، هي أن هذه الميزات ليست في فراغ. إذا جعلت لغة ما أكثر راحة ، فستشهد اعتمادًا أكبر من قِبل الأشخاص المهتمين بالأداة لحل المشكلات التي يواجهونها بشكل أسرع. (راجع: C # والنمو في الشعبية مع ميزات لغة أكثر / أفضل)

فيما يتعلق بالمتغيرات التي تنتهي بـ ? - يمكن أن يكون ذلك تغييرًا كبيرًا بسبب المتغير التلقائي .

lzybkr أظن أن أفضل حالة للتعامل مع هذه هي حالة خاصة مثل ما هو موجود بالفعل لـ $^ و $$ .

lzybkr @ TheIncorreful1 بقدر ما أتذكر ، كل _ من هذه المتغيرات مغلفة بشكل خاص في الرمز المميز . $^ _already_ اسم متغير صالح. يحتوي الرمز المميز على حالات خاصة لكل هؤلاء قبل أن يبدأ في البحث عن أسماء المتغيرات القياسية.

الحل الوحيد هنا هو استخدام ¿ :

$ سخيف؟ ¿= 1

أنا لا أعرف ستيف ، أنا بقوة في حشد interrobang على هذا.

$silly?‽=1

lzybkr - على حد علمي ، يتم التعامل مع $? $$ و $^ بطريقة خاصة.

https://github.com/PowerShell/PowerShell/blob/8b9f4124cea30cfcd52693cb21bcd8100d39a796/src/System.Management.Automation/engine/parser/tokenizer.cs#L3001 -L3004

للتلخيص ، لدينا هذه الخيارات الأربعة

  • تغيير فاصل كبير - عدم السماح باستخدام ? في أسماء المتغيرات.
  • تفضل ?. كمعامل. هذا يعني أن الأسماء المتغيرة التي تنتهي بـ ? يجب أن تستخدم بناء الجملة ${variablename} . لا يزال هناك تغيير جذري.
  • تفضل السلوك القديم. هذا يعني أنه يجب استخدام ?. و ?[] و ${variablename}?.property . لا يوجد تغيير جذري ، ولكنه يجعل استخدام المشغلين الجدد خرقاء.
  • لا تقم بتنفيذ عوامل التشغيل الجديدة.

أنا شخصياً لا أفضل الأول والأخير.

هذا تغيير رئيسي في الإصدار. أعتقد أنه ليس من غير المعقول أن يتغير هذا هنا.

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

لاحظ أن الإصدار الرئيسي لا يعني أننا سنجري تغييرات كبيرة.

هل الخياران 1 و 2 ليسا متماثلين؟ أو هل سيستمر السماح للمتغيرات باستخدام ? في حالة عدم وجود اندماج فارغ أو عامل تشغيل ثلاثي يتبعها؟

إذا كان الأمر كذلك ، أعتقد أننا قد نواجه الكثير من المتاعب في التعامل مع منطق الترميز / التحليل بدون الكثير من التراجع. قد يؤدي هذا إلى تدهور الأداء عندما تنتهي المتغيرات بـ ? .

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

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

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

@ vexx32 يوجد فرق بسيط بين 1 و 2.

بالنسبة إلى رقم 1 ، لا نسمح باستخدام ? في أسماء المتغيرات معًا. هذا يعني أن $x? = 1 ، $x?? = 1 $x?x?x = 1 لن يتم تحليله.

بالنسبة للرقم 2 ، لا يزال $x? = 1 صالحًا ولكن $x?.name يعادل ${x}?.name . هذا فقط يكسر أسماء المتغيرات مع ? في النهاية ، والتي تقوم بالوصول إلى الأعضاء. لذلك ، سيظل $x? = 1 ، $x?? = 1 $x?x?x = 1 صالحًا.

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

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

إذا كان الأمر كذلك ، أعتقد أننا قد نواجه الكثير من المتاعب في التعامل مع منطق الترميز / التحليل بدون الكثير من التراجع. قد يؤدي هذا إلى تدهور الأداء عندما تنتهي المتغيرات بـ؟.

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

إذا كان الأمر كذلك ، أعتقد أننا قد نواجه الكثير من المتاعب في التعامل مع منطق الترميز / التحليل بدون الكثير من التراجع. قد يؤدي هذا إلى تدهور الأداء عندما تنتهي المتغيرات بـ؟.

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

استعرضت لجنة PowerShell / بوويرشيل @ هذا اليوم ، ولدينا بعض الأفكار:

  • بغض النظر عما نقوم به ، سنقوم ببعض التحليلات لمجموعة البرامج النصية الخاصة بنا لمعرفة عدد المرات التي يستخدم فيها الأشخاص ? في أسماء المتغيرات
  • لدى البعض منا فرضية (يرغب الآخرون في التحقق من صحتها) مفادها أن المستخدمين الذين يستخدمون ? في أسمائهم المتغيرة قد يكونون مستخدمين أقل تقدمًا (كما نتفق في هذه الغرفة على أننا سنبقى بعيدًا عنها لأننا من المشاكل المحتملة التي يمكن أن تنشأ). من ناحية أخرى ، سيتمكن أي شخص يستخدم الوظيفة الموضحة هنا من فهم بناء جملة أكثر تعقيدًا قليلاً (مثل ${foo}?.bar ). لذلك ، نفضل الخيار 3 لأنه يتجنب كسر التغييرات على هؤلاء المستخدمين الأقل خبرة. (لكن مرة أخرى ، سوف نتحقق من صحتها في أول رصاصة.)
  • أثار @ daxian-dbw نقطة جيدة حول جعل العثور على جميع المراجع المتغيرة أكثر صعوبة عندما يخلط المبرمجون بين استخدام $foo و ${foo} . ومع ذلك ، اتفقنا على أنه يمكن إصلاح ذلك في الأدوات (مثل امتداد VS Code PowerShell) ، ويمكن لمستخدمين مثل JamesWTruher الذين يستخدمون المحررين مثل Vim أن

يصعب العثور على جميع المراجع المتغيرة عندما يخلط المبرمجون بين استخدام $ foo و $ {foo}

يعتمد ذلك على ما إذا كان AST يميز اسم المتغير بناءً على ما إذا كان قد رأى الأقواس. أظن أن أي أداة تستخدم PowerShell AST لن تواجه مشكلة مع الأقواس هنا.

ولكن بالنسبة للتعبير العادي ، فهذا يعني بالتأكيد أنه يجب أن تكون أكثر وعياً: varname -> \{?varname\}?

rjmholt لقد هنا . تحليل سريع: من بين ما يقرب من 400000 نص برمجي يحتوي على 22.000.000+ اسم متغير (ليس فريدًا) ، كان هناك فقط 70 متغيرًا فريدًا انتهى بـ ? .

شكرًا ، mburszley - بالنسبة لي ، هذا ما يجعلها دلو 3: تغيير {...} أمر مؤسف للغاية ، وهو موازٍ للحاجة المؤسفة لـ $(...) حوالي exit / return / throw في سياق && و || .

لاستعارة المنطق من هذه المسألة:

إذا فرضنا استخدام {...} حول أسماء المتغيرات فقط حتى تتمكن من استخدام ?. :

  • لن يتوقع المستخدمون الجدد الحاجة إلى {...} ولن يعلموا بالضرورة أن _it_ هو المطلوب عندما يفشل التالي (ربما _ غير مكتشف_ ، ما لم يكن Set-StrictMode -Version 2 أو أعلى ساريًا): $o = [pscustomobject] @{ one = 1 }; $o?.one

  • حتى بمجرد أن يعرف المستخدمون _do_ الحاجة إلى {...} :

    • سوف ينسون استخدامه في بعض الأحيان ، بسبب الحاجة غير البديهية إليه.
    • عندما يتذكرون ، سيكون هذا المطلب المصطنع على ما يبدو مصدرًا مستمرًا للإحباط ، خاصة وأن كتابة {...} يصعب كتابتها.

تم وضع علامة على هذه المشكلة على أنها تم إصلاحها ولم يكن لها أي نشاط لمدة يوم واحد . تم إغلاقه لأغراض التدبير المنزلي.

rjmholt ، نقلا عنك من https://github.com/PowerShell/PowerShell/issues/10967#issuecomment -561843650:

عدم كسر الطريقة التي نحلل بها بناء الجملة الصحيح هو الطريقة الصحيحة للذهاب. مرة أخرى ، التغيير ليس هناك مجرد حالة من اتخاذنا لقرار لدعم عدد صغير من البرامج الجامحة هناك - لقد قمنا بالعديد من التغييرات المفاجئة في الحالات التي اعتقدنا فيها أن الإيجابيات تفوق السلبيات (ليس هذا ما أوافق عليه شخصيًا مع كل منهم ، أو أن هؤلاء يفعلون أو لا يبررون الآخرين). تكمن المشكلة في أن تغيير بعض جوانب أداة الرمز المميز أو المحلل اللغوي يعني أن نسختين من PowerShell لن تولد بعد ذلك نفس AST لبعض البرامج النصية ، لذلك سيرى اثنان من PowerShells نفس البرنامج النصي بشكل مختلف. هذا يعني أنه لا يمكننا حتى قراءة بناء الجملة بالطريقة نفسها ، لذلك لا توجد قاعدة PSScriptAnalyzer يمكنك كتابتها لالتقاط المشكلات المحتملة حولها ؛ سيشاهد PSScriptAnalyzer بنية مختلفة من إصدار PowerShell إلى الإصدار التالي.

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

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

نقوم بتقليل عدد البرامج النصية التي يمكن أن تعمل مع الإصدارات المختلفة
مما يعني أن المستخدمين مجبرون على كتابة نصين

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

نعم ، قد يتعطل تفسير $var?.foo في البرامج النصية القديمة التي تستخدم $var? كاسم متغير ، ولكن:

  • لم يكن مسموحًا أبدًا بالسماح لـ ? كجزء من المعرف _ بدون تضمينه في {...} _.

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

    • حتى Ruby لا تسمح إلا بـ ?! ) عند _ نهاية _ من المعرفات ، ولا يوجد سوى معرفات _method_ ، وأظن أن معظم مستخدمي Ruby يدركون أنه يجب _لا يفترض أن اللغات الأخرى تدعم نفس الشيء.

إذن ، بشكل عملي:

  • لن تتأثر الغالبية العظمى من التعليمات البرمجية الحالية - لن يتم العثور على رمز مميز مثل $var?.foo ببساطة.

  • إذا كتبت $var?.foo مع الدلالات الجديدة ، فعندئذ نعم ، قد يؤدي تشغيل ذلك في الإصدارات الأقدم إلى سلوك مختلف (بدلاً من الانهيار بطريقة واضحة) ، اعتمادًا على ماهية الوضع المتشدد - ولكن _ يجب عليك دائمًا فرض الحد الأدنى من الإصدار المطلوب لتشغيل التعليمات البرمجية على النحو المنشود على أي حال_ ( #requires -Version ، module-manifest keys).

بشكل عام ، هذه حالة واضحة لتغيير دلو 3: تغيير تقني يكسر القليل جدًا من الكود الحالي مع تقديم فوائد حقيقية (أو ، على العكس ، تجنب الصداع الدائم بسبب السلوك غير المتوقع).

@ mklement0 ، نحن نحافظ على تجربة الوصول Null-Conditional لـ PS7.0. ربما يمكنك فتح عدد جديد لمواصلة هذه المناقشة ل 7.1؟

يبدو هذا جيدًا ، @ SteveL-MSFT - يُرجى مراجعة # 11379.

أنا أشجع الجميع هنا على إظهار الدعم مرة أخرى (أو اللحظات ، عدم الدعم) هناك.

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