سؤال

أنا أسأل فيما يتعلق بـ C#، ولكني أفترض أنه هو نفسه في معظم اللغات الأخرى.

هل لدى أي شخص تعريف جيد ل التعبيرات و صياغات وما هي الاختلافات؟

هل كانت مفيدة؟

المحلول

تعبير: شيء يتم تقييمه إلى قيمة.مثال: 1+2/س
إفادة: سطر من التعليمات البرمجية الذي يفعل شيئا.مثال: اذهب إلى 100

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

1 + 2 / X

هو خطأ في FORTRAN، لأنه لا يفعل أي شيء.كان عليك أن تفعل شيئًا بهذا التعبير:

X = 1 + 2 / X

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

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

1 + 2 / x;

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

1 + 2 / callfunc(12);

لأن callfunc قد تفعل شيئا مفيدا فقط.

بمجرد السماح لأي تعبير بأن يكون عبارة، يمكنك أيضًا السماح لعامل الإسناد (=) داخل التعبيرات.لهذا السبب يتيح لك C القيام بأشياء مثل

callfunc(x = 2);

يؤدي ذلك إلى تقييم التعبير x = 2 (تعيين قيمة 2 إلى x) ثم تمرير ذلك (2) إلى الدالة callfunc.

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

إن وجود "فئتين نحويتين" (وهو الاسم الفني لنوع البيانات والتعبيرات) يمكن أن يؤدي إلى ازدواجية الجهود.على سبيل المثال، لغة C لديها شكلين من الشرط، نموذج البيان

if (E) S1; else S2;

وصيغة التعبير

E ? E1 : E2

وأحيانا الناس يريد ازدواجية غير موجودة:في المعيار C ، على سبيل المثال ، يمكن للبيان فقط أن يعلن عن متغير محلي جديد - لكن هذه القدرة مفيدة بدرجة كافية بحيث يوفر برنامج التحويل البرمجي GNU C امتدادًا GNU الذي يتيح التعبير عن إعلان متغير محلي أيضًا.

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

نصائح أخرى

أود إجراء تصحيح بسيط على إجابة جويل أعلاه.

لا تسمح لغة C# باستخدام كافة التعبيرات كبيانات.على وجه الخصوص، يمكن فقط استخدام تعبيرات التعيين والاستدعاء والزيادة والنقصان كعبارات.

على سبيل المثال، سيشير مترجم C# إلى التعليمة البرمجية التالية كخطأ في بناء الجملة:

1 + 2;

  • التعبير هو أي شيء ينتج عنه قيمة:2 + 2
  • البيان هو أحد "الكتل" الأساسية لتنفيذ البرنامج.

لاحظ أنه في لغة C، "=" هو في الواقع عامل تشغيل، يقوم بأمرين:

  • تُرجع قيمة التعبير الفرعي الأيمن.
  • نسخ قيمة التعبير الفرعي الأيمن إلى المتغير الموجود على الجانب الأيسر.

إليك مقتطف من قواعد ANSI C.يمكنك أن ترى أن لغة C لا تحتوي على العديد من أنواع العبارات المختلفة...غالبية العبارات في البرنامج هي عبارات تعبيرية، أي.تعبير بفاصلة منقوطة في النهاية.

statement
    : labeled_statement
    | compound_statement
    | expression_statement
    | selection_statement
    | iteration_statement
    | jump_statement
    ;

expression_statement
    : ';'
    | expression ';'
    ;

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

التعبير هو شيء يُرجع قيمة، في حين أن العبارة لا تفعل ذلك.

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

1 + 2 * 4 * foo.bar()     //Expression
foo.voidFunc(1);          //Statement

والأمر المهم بين الاثنين هو أنه يمكنك ربط التعبيرات معًا، في حين لا يمكن ربط العبارات.

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

وبالتالي، يمكن استخدام التعبيرات في البيانات، ولكن ليس العكس.

لاحظ أن بعض اللغات (مثل Lisp وRuby والعديد من اللغات الأخرى) لا تفرق بين البيان والتعبير...في مثل هذه اللغات، كل شيء هو تعبير، ويمكن تقييده بتعبيرات أخرى.

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

تؤكد اللغات الأمرية (Fortran، C، Java، ...) على عبارات هيكلة البرامج، ولها تعبيرات كنوع من التفكير اللاحق.تؤكد اللغات الوظيفية على التعبيرات. بحتة تحتوي اللغات الوظيفية على تعبيرات قوية جدًا بحيث لا يمكن حذف العبارات تمامًا.

ببساطة:يتم تقييم التعبير إلى قيمة، بينما لا يتم تقييم العبارة.

يمكن تقييم التعبيرات للحصول على قيمة، في حين أن العبارات لا تُرجع قيمة (فهي من النوع فارغ).

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

تتطلب اللغات الموجهة للبيانات أن تكون جميع الإجراءات عبارة عن قائمة بيانات.اللغات الموجهة نحو التعبير، والتي ربما تكون جميع اللغات الوظيفية، هي عبارة عن قوائم من التعبيرات، أو في حالة LISP، تعبير S طويل يمثل قائمة من التعبيرات.

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

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

في اللغة المبنية على التعبير، كل ما تحتاجه هو تعبير واحد للدالة نظرًا لأن جميع بنيات التحكم تُرجع قيمة (الكثير منها يُرجع NIL).ليست هناك حاجة إلى عبارة إرجاع نظرًا لأن التعبير الذي تم تقييمه مؤخرًا في الدالة هو القيمة المرجعة.

بعض الأشياء حول اللغات القائمة على التعبير:


الأهم:كل شيء يعود بقيمة


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


في اللغة القائمة على التعبير، كل شيء يُرجع قيمة.يمكن أن يكون هذا غريبًا بعض الشيء في البداية - ماذا يفعل (FOR i = 1 TO 10 DO (print i)) يعود؟

بعض الأمثلة البسيطة:

  • (1) عائدات 1
  • (1 + 1) عائدات 2
  • (1 == 1) عائدات TRUE
  • (1 == 2) عائدات FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) عائدات 10
  • (IF 1 == 2 THEN 10 ELSE 5) عائدات 5

بعض الأمثلة الأكثر تعقيدًا:

  • بعض الأشياء، مثل بعض استدعاءات الوظائف، ليس لها حقًا قيمة ذات معنى لإرجاعها (الأشياء التي تنتج آثارًا جانبية فقط؟).الاتصال OpenADoor(), FlushTheToilet() أو TwiddleYourThumbs() سيُرجع نوعًا ما من القيمة العادية، مثل OK أو Done أو Success.
  • عندما يتم تقييم عدة تعبيرات غير مرتبطة ضمن تعبير واحد أكبر، تصبح قيمة آخر شيء تم تقييمه في التعبير الكبير هي قيمة التعبير الكبير.لنأخذ المثال (FOR i = 1 TO 10 DO (print i)), ، قيمة الحلقة هي "10"، وتؤدي إلى حدوث (print i) سيتم تقييم التعبير 10 مرات، وفي كل مرة يتم إرجاع i كسلسلة.المرة الأخيرة من خلال العودة 10, ، إجابتنا النهائية

غالبًا ما يتطلب الأمر تغييرًا طفيفًا في العقلية لتحقيق أقصى استفادة من اللغة القائمة على التعبير، نظرًا لأن حقيقة أن كل شيء عبارة عن تعبير تجعل من الممكن "تضمين" الكثير من الأشياء

كمثال سريع:

 FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO
 (
    LotsOfCode
 )

هو بديل صالح تمامًا للصيغة غير المستندة إلى التعبير

IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 
FOR i = 1 TO TempVar DO
(    
    LotsOfCode  
)

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

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

IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO
(
    LotsOfCode
)

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

على سبيل المثال، في C# لدينا المفيد جدًا Func<T1, T2, T3, TResult> مجموعة مثقلة من المندوبين عامة.ولكن علينا أيضًا أن يكون لدينا ما يقابلها Action<T1, T2, T3> تم ضبطها أيضًا، ويجب دائمًا تكرار البرمجة عالية الترتيب للأغراض العامة للتعامل مع هذا التشعب المؤسف.

مثال تافه - دالة تتحقق مما إذا كان المرجع خاليًا قبل الاتصال بوظيفة أخرى:

TResult IfNotNull<TValue, TResult>(TValue value, Func<TValue, TResult> func)
                  where TValue : class
{
    return (value == null) ? default(TValue) : func(value);
}

هل يمكن للمترجم التعامل مع إمكانية TResult كون void؟نعم.كل ما عليها فعله هو أن يتطلب أن يتبع الإرجاع تعبير من النوع void.نتائج default(void) سيكون من النوع void, ، ويجب أن تكون الوظيفة التي يتم تمريرها بالصيغة Func<TValue, void> (والتي من شأنها أن تعادل Action<TValue>).

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

البيانات -> تعليمات يجب اتباعها بالتسلسل
التعبيرات -> التقييم الذي يُرجع قيمة

البيانات هي في الأساس مثل الخطوات، أو التعليمات في الخوارزمية، ونتيجة تنفيذ العبارة هي تفعيل مؤشر التعليمات (ما يسمى في المجمع)

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

أمثلة على البيانات:

for
goto
return
if

(كلها تعني تقدم خط (بيان) التنفيذ إلى خط آخر)

مثال على التعبيرات:

2+2

(لا يتضمن فكرة التنفيذ، بل التقييم)

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

x = 5

يقرأ باسم "X Gets 5." هذه جملة كاملة.الرمز

(x + 5)/9.0

يقرأ ، "X Plus 5 مقسومًا على 9.0." هذه ليست جملة كاملة.البيان

while k < 10: 
    print k
    k += 1

هي جملة كاملة.لاحظ أن رأس الحلقة ليس كذلك؛"بينما k <10،" عبارة عن جملة ثانوية.

إفادة,

البيان عبارة عن لبنة بناء إجرائية يتم من خلالها إنشاء جميع برامج C#.يمكن للبيان أن يعلن عن متغير محلي أو ثابت، أو استدعاء أسلوب، أو إنشاء كائن، أو تعيين قيمة لمتغير، أو خاصية، أو حقل.

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

bool IsPositive(int number)
{
    if (number > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

غالبًا ما تحتوي البيانات في C# على تعبيرات.التعبير في لغة #C هو جزء من التعليمات البرمجية يحتوي على قيمة حرفية، أو اسم بسيط، أو عامل التشغيل ومعاملاته.

تعبير,

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

int i = 5;
string s = "Hello World";

كل من i وs هما اسمان بسيطان يحددان المتغيرات المحلية.عند استخدام هذه المتغيرات في تعبير، يتم استرداد قيمة المتغير واستخدامها للتعبير.

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

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

أنا لست راضيا حقا عن أي من الإجابات هنا.نظرت إلى القواعد ل سي++ (آيزو 2008).ومع ذلك، ربما من أجل الأمور التعليمية والبرمجة، قد تكون الإجابات كافية للتمييز بين العنصرين (على الرغم من أن الواقع يبدو أكثر تعقيدًا).

تتكون العبارة من صفر أو أكثر من التعبيرات، ولكن يمكن أن تكون أيضًا مفاهيم لغوية أخرى.هذا هو نموذج Backus Naur الممتد لقواعد اللغة (مقتطف من البيان):

statement:
        labeled-statement
        expression-statement <-- can be zero or more expressions
        compound-statement
        selection-statement
        iteration-statement
        jump-statement
        declaration-statement
        try-block

يمكننا أن نرى المفاهيم الأخرى التي تعتبر عبارات في C++.

  • بيان التعبيرs تشرح نفسها بنفسها (يمكن أن تتكون العبارة من صفر أو أكثر التعبيرات، اقرأ القواعد بعناية، فهي صعبة)
  • case على سبيل المثال هو بيان مسمى
  • بيان الاختيارهي if if/else, case
  • بيان التكرارهي while, do...while, for (...)
  • بيان القفزهي break, continue, return (يمكن إرجاع التعبير)، goto
  • بيان إعلان هي مجموعة من الإعلانات
  • محاولة كتلة هو بيان يمثل try/catch كتل
  • وقد يكون هناك المزيد في القواعد

هذا مقتطف يوضح جزء التعبيرات:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • التعبيرات هي أو تحتوي في كثير من الأحيان على المهام
  • التعبير الشرطي (يبدو مضللاً) يشير إلى استخدام عوامل التشغيل (+, -, *, /, &, |, &&, ||, ...)
  • رمي التعبير - أوه؟ال throw الجملة هي تعبير أيضا

إليكم ملخص إحدى أبسط الإجابات التي وجدتها.

تم الرد عليه في الأصل بواسطة Anders Kaseorg

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

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

يمكن استخدام كل تعبير كتعبير (يكون تأثيره هو تقييم التعبير وتجاهل القيمة الناتجة)، ولكن لا يمكن استخدام معظم العبارات كتعبيرات.

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python

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

التعبير له نوع آخر غير النوع السفلي، أي.لها قيمة.يحتوي البيان على نوع الوحدة أو القاع.

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

من الواضح أ @pragma أو أ /*comment*/ ليس لها نوع، وبالتالي يتم تمييزها عن البيانات.وبالتالي فإن النوع الوحيد من البيان الذي لن يكون له أي آثار جانبية هو عدم إجراء عملية جراحية.يعد عدم إجراء العملية مفيدًا فقط كعنصر نائب للآثار الجانبية المستقبلية.أي إجراء آخر بسبب بيان سيكون له أثر جانبي.مرة أخرى تلميح مترجم، على سبيل المثال. @pragma, ، ليس بيانًا لأنه ليس له نوع.

على وجه التحديد، يجب أن يحتوي البيان على "أثر جانبي" (أي. تكون حتمية) ويجب التعبير يملك أ قيمة النوع (أيوليس النوع السفلي).

ال نوع البيان هو نوع الوحدة، ولكن بسبب نظرية التوقف، تعتبر الوحدة خيالية، لذا دعنا نقول النوع السفلي.


Void ليس بالضبط النوع السفلي (ليس النوع الفرعي لجميع الأنواع الممكنة).إنه موجود في اللغات التي ليس لديك نظام صوتي بالكامل.قد يبدو هذا وكأنه بيان متعجرف، ولكن اكتمال مثل التعليقات التوضيحية المتباينة تعتبر حاسمة لكتابة البرامج القابلة للتوسيع.

دعونا نرى ما تقوله ويكيبيديا حول هذا الموضوع.

https://en.wikipedia.org/wiki/Statement_(computer_science)

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

العديد من اللغات (على سبيل المثال.ج) التمييز بين البيانات والتعريفات، مع عبارة تحتوي فقط على تعليمات برمجية قابلة للتنفيذ وتعريف يعلن عن معرف، بينما يتم تقييم التعبير إلى قيمة فقط.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top