Выражение против утверждения

Я спрашиваю относительно c #, но я предполагаю, что то же самое в большинстве других языков.

У кого-нибудь есть хорошее определение выражений и утверждений и в чем различия?

21.08.2008 00:28:00
Я нахожу ответ, который вы выбрали, неоднозначным. Выражение также что-то делает - оно оценивает значение. Я дал однозначный ответ.
Shelby Moore III 9.12.2011 19:36:28
@ShelbyMooreIII - не однозначно, а также неправильно. Принятый ответ сформулирован неформально, но эта формулировка облегчает понимание - и, самое главное, значение, которое он передает, является точным.
Justin Morgan 13.12.2012 21:56:37
@JustinMorgan К сожалению, определения в принятом ответе также явно неверны («оценивает значение» / «строка кода») для большинства современных языков, включая C-подобные: выражения могут использоваться в неоцененных контекстах, а операторы ничего не имеют делать с линиями. Даже если есть некоторые объяснения, короткий ответ сбивает с толку и вводит в заблуждение.
FrankHB 23.08.2019 01:56:44
18 ОТВЕТОВ
РЕШЕНИЕ

Выражение: что-то, что оценивает значение. Пример: 1 + 2 / x
Заявление: строка кода, которая что-то делает. Пример: GOTO 100

В самых ранних языках программирования общего назначения, таких как FORTRAN, различие было кристально ясным. В FORTRAN оператор был одной единицей исполнения, то, что вы сделали. Единственная причина, по которой его не называли «линией», заключалась в том, что иногда он занимал несколько строк. Выражение само по себе ничего не может сделать ... вы должны были присвоить его переменной.

1 + 2 / X

ошибка в Фортране, потому что она ничего не делает Вы должны были что-то сделать с этим выражением:

X = 1 + 2 / X

У Фортрана не было грамматики в том виде, в каком мы ее знаем сегодня - эта идея была изобретена вместе с формой Бэкуса-Наура (БНФ), как часть определения Алгол-60. В этот момент семантическое различие («иметь значение» и «делать что-то») было закреплено в синтаксисе : один вид фразы был выражением, а другой - выражением, и синтаксический анализатор мог их различать.

Разработчики более поздних языков размыли различие: они позволяли синтаксическим выражениям делать что-то, и они допускали синтаксические выражения, которые имели значения. Самый ранний популярный пример языка, который до сих пор сохранился, - C. Разработчики C поняли, что никакого вреда не было, если вам позволили оценить выражение и выбросить результат. В C каждое синтаксическое выражение может быть преобразовано в утверждение, просто ставя точку с запятой в конце:

1 + 2 / x;

это абсолютно законное заявление, хотя абсолютно ничего не произойдет. Аналогично, в C выражение может иметь побочные эффекты - оно может что-то изменить.

1 + 2 / callfunc(12);

потому что callfuncможет просто сделать что-то полезное.

Раз вы позволите любому выражению быть оператором, вы можете также разрешить оператор присваивания (=) внутри выражений. Вот почему С позволяет вам делать такие вещи, как

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 - все языки, которые не имеют синтаксических операторов - они имеют только выражения. Даже структурированные циклы класса и условные формы считаются выражениями, и они имеют значения, но не очень интересные.

519
21.02.2019 17:23:08
Если я не ошибаюсь в вашей интерпретации здесь, вы, похоже, утверждаете, что "(setf (third foo) 'goose)" является выражением, а не утверждением, поскольку это Lisp, который "не имеет выражений", и потому что Lisp более чем на десять лет старше, чем C, который был «самым ранним популярным языком для размытия границ [между выражениями и утверждениями]». Не могли бы вы объяснить детали этого для меня?
cjs 24.06.2009 18:24:10
@ Курт Сэмпсон, ты задавал это как отдельный вопрос?
Kelly S. French 27.10.2009 23:06:30
Если я не ошибаюсь, callfunc(x = 2);переходит xна callfuncнет 2. Если xэто поплавок, callfunc(float)будет называться, а не callfunc(int). И в C ++, если вы передаете x=yк funcи funcпринимает ссылку и изменяет его, она меняется x, не y.
Gabriel 23.09.2011 02:34:20
В ответе выше написано, что "Haskell, ... все языки, которые не имеют синтаксических операторов - они имеют только выражения". Мне любопытно, почему whereпредложение в haskell считается выражением, а не утверждением. learnyouahaskell.com/syntax-in-functions#where
skgbanga 30.11.2016 05:11:57

Выражения могут быть оценены, чтобы получить значение, тогда как операторы не возвращают значение (они имеют тип void ).

Выражения вызова функций также можно рассматривать как операторы, но, если в среде выполнения нет специальной встроенной переменной для хранения возвращаемого значения, его невозможно получить.

Языки, ориентированные на операторы, требуют, чтобы все процедуры были списком операторов. Ориентированные на выражения языки, которые, вероятно, являются всеми функциональными языками, представляют собой списки выражений или, в случае LISP, одно длинное S-выражение, представляющее список выражений.

Хотя оба типа могут быть составлены, большинство выражений может быть составлено произвольно, если типы совпадают. Каждый тип оператора имеет свой собственный способ составления других операторов, если они могут делать все это. Foreach, и если для операторов требуется либо одна инструкция, либо чтобы все подчиненные операторы помещались в блоке операторов один за другим, если только подзаголовки не допускают своих подзаголовков.

Выражения могут также включать выражения, где выражение на самом деле не включает никаких утверждений. Однако одним исключением может быть лямбда-выражение, представляющее функцию, и поэтому оно может включать в себя все, что функция может исключить, если язык не допускает только ограниченные лямбды, такие как лямбды Python с одним выражением.

В языке на основе выражений все, что вам нужно, - это одно выражение для функции, поскольку все управляющие структуры возвращают значение (многие из них возвращают NIL). Нет необходимости в операторе возврата, так как последнее вычисленное выражение в функции является возвращаемым значением.

5
21.08.2008 00:41:03
Тип заявления является нижним типом. Voidэто не нижний тип. Смотри мой ответ .
Shelby Moore III 9.12.2011 19:07:08
Разве нулевой тип не является нижним типом (одно значение null)? Не будет voidли больше похож на тип устройства (но с единственным недоступным значением)?
Mark Cidade 9.12.2011 22:04:16
Если voidэто тип возврата функции, которая никогда не возвращается (например, функция, которая throwявляется ошибкой), это тип снизу . В противном случае voidэто тип устройства . Вы правы, что утверждение, которое не может расходиться, имеет тип единицы измерения. Но утверждение, которое может расходиться, является типом дна. Из-за теоремы Остановки мы обычно не можем доказать, что функция не расходится, поэтому я думаю, что единица - это выдумка. Нижний тип не может иметь значения, поэтому он не может иметь единственного значения null.
Shelby Moore III 9.12.2011 22:40:33
Что касается того, что я сказал три года назад, я не знаю, считаю ли я все еще заявления о том, что они имеют тип void или какой-либо другой тип. В языках заявление на основе , с которыми я знаком, только значения и все , что либо хранит или возвращает значение (например, выражения, переменные, члены и функции) могут иметь типы. Я обычно думаю о нижнем типе как о пустом множестве (без значений), и поэтому все, что не существует онтологически, будет иметь этот тип. nullЗначение действительно pseudovalue обозначая , что ссылка указывает на то , что не существует.
Mark Cidade 10.12.2011 00:57:11
Марк, я оценил рациональность вашего ответа. Вы в основном вынули слова из моих уст, и я надеюсь, что было ясно, что я признался вам, что вы были правы, чтобы поднять единицу. Я думаю, что мы согласны. Я не собирался упоминать об этом, но некоторые люди здесь думают, что я настроен негативно. Я просто пытаюсь быть фактическим.
Shelby Moore III 10.12.2011 06:27:01

Выражение - это то, что возвращает значение, а выражение - нет.

Например:

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

Большая сделка между ними заключается в том, что вы можете связывать выражения вместе, тогда как операторы не могут быть связаны.

15
21.08.2008 00:30:44
Конечно, заявления могут быть прикованы цепью. {stmt1; stmt2; stmt3;} является цепочкой, а также является (составным) оператором.
Hugh Allen 8.04.2009 01:54:26
foo.voidFunc(1);является выражением со значением void. whileи ifявляются заявлениями.
tzot 2.12.2009 13:57:58
Мне любопытно, чтобы не было цепочек утверждений. Было бы что-то вроде "if (x> 1) return;" считаться цепочкой двух утверждений вместе?
Simon Tewsi 29.01.2013 22:25:44
@SimonTewsi Я считаю, что returnсчитается подзаголовком.
RastaJedi 17.03.2019 04:15:27

Проще говоря: выражение оценивает значение, а утверждение - нет.

5
21.08.2008 00:31:55
Так что же делает заявление? Ничего?
Shelby Moore III 9.12.2011 19:16:59
Он может что-то делать, но ничего не оценивает. Т.е. вы не можете присвоить результат этого переменной, тогда как вы можете с помощью выражения.
Matthew Schinckel 10.12.2011 09:52:34
И поэтому у заявления должны быть побочные эффекты, о чем говорит мой сильно отрицательный ответ. Какую еще полезность может иметь заявление? Даже если бы NO-OP считался оператором (это только «оператор» в грамматике, но не на уровне семантики, потому что он стирается после синтаксического анализа, а семантика - это то, что мы обсуждаем здесь), он не объяснил бы, что черт возьми общая полезность заявления.
Shelby Moore III 25.08.2014 06:47:48
@ShelbyMooreIII Заявления не должны ничего делать или иметь побочные эффекты. Например, {}это утверждение. Помещение слова в кавычки не меняет этого. Заявления являются синтаксическими конструкциями с семантикой. Нет такого понятия, как «уровень семантики» - вы, похоже, имеете в виду выполнение . Вы говорите, что пытаетесь быть точным, но у вас ничего не получилось. Ваша жалоба о "невежестве недовольных избирателей" - это чистый ad hominem; у вас нет информации о психических состояниях downvoters.
Jim Balter 28.07.2015 23:43:39
Да, все не правы, кроме интеллектуально нечестных. {}определяется как оператор в спецификации языка C #.
Jim Balter 18.08.2015 07:40:59

Вы можете найти это в википедии , но выражения оцениваются до некоторого значения, в то время как операторы не имеют оцененного значения.

Таким образом, выражения могут использоваться в выражениях, но не наоборот.

Обратите внимание, что некоторые языки (такие как Lisp, и, я полагаю, Ruby и многие другие) не различают оператор и выражение ... в таких языках все является выражением и может быть связано с другими выражениями.

9
21.08.2008 00:35:13
  • выражение - это все, что дает значение: 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

22
21.08.2008 05:05:58
Неверная логика в том, что такое утверждение. Декларативная программа также может выполняться, но декларативная программа не имеет операторов. Заявление является и делает "побочные эффекты" , то есть является обязательным. ср мой ответ .
Shelby Moore III 9.12.2011 19:28:33

Некоторые вещи о языках, основанных на выражениях:


Самое главное: все возвращает значение


Нет никакой разницы между фигурными скобками и фигурными скобками для разграничения блоков кода и выражений, поскольку все является выражением. Это не мешает лексическому ограничению: локальная переменная может быть определена для выражения, в котором содержится ее определение, и для всех операторов, содержащихся в нем, например.


На языке выражений все возвращает значение. Поначалу это может показаться немного странным - что (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)), значение цикла for равно 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
)
4
19.12.2008 01:36:29

Оператор - это особый случай выражения, один с 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>).

Ряд других ответов подразумевает, что вы не можете связывать утверждения, как вы, с выражениями, но я не уверен, откуда взялась эта идея. Мы можем думать о том, ;что появляется после операторов, как бинарный инфиксный оператор, принимая два выражения типа voidи объединяя их в одно выражение типа void.

3
14.03.2009 17:35:38

Для объяснения важных различий в сочетаемости (цепочечности) выражений и выражений моя любимая ссылка - дипломная работа Тьюринга Джона Бэкуса: Можно ли освободить программирование от стиля фон Неймана? ,

В императивных языках (Fortran, C, Java, ...) подчеркиваются операторы для структурирования программ, а выражения являются своего рода запоздалым размышлением. Функциональные языки подчеркивают выражения. Чисто функциональные языки имеют такие мощные выражения, что операторы могут быть полностью исключены.

8
28.11.2010 00:20:32

Заявления являются грамматически законченными предложениями. Выражения нет. Например

x = 5

читается как "х получает 5" Это полное предложение. Код

(x + 5)/9.0

гласит: «х плюс 5 все делится на 9,0». Это не полное предложение. Заявление

while k < 10: 
    print k
    k += 1

это полное предложение. Обратите внимание, что заголовок цикла не является; «в то время как k <10» является подчиненным предложением.

1
26.03.2011 01:40:12
whileЭто выражение некоторых языков, таких как Scala. Вы смешиваете грамматику с набором текста. Смотри мой ответ .
Shelby Moore III 9.12.2011 19:12:24
Вот цикл while в scala: tutorialspoint.com/scala/scala_ while_loop.htm Цикл с его предикатом и без тела не является грамматически завершенным предложением. Это не полное выражение. Вам нужно тело, чтобы завершить его как выражение.
ncmathsadist 8.05.2013 00:42:21
А whileс телом это еще выражение в Скале. Это также может быть утверждение, если оно создает побочные эффекты, что допускает мой сильно опущенный ответ (выражение также может быть утверждением). Мой ответ - единственный правильный. Извините всех тех читателей, которые не могут понять.
Shelby Moore III 22.06.2013 16:49:22

Наиболее точно, оператор должен иметь «побочный эффект» (т.е. будет императивным ) и выражение должно иметь в значении типа (т.е. не нижний тип).

Типа заявления является типом блока, но из - за останавливая теоремы блока выдумки так что позволяет сказать нижний тип .


Voidэто не совсем нижний тип (это не подтип всех возможных типов). Он существует в языках, которые не имеют полностью звуковой системы типов . Это может звучать как снобистское утверждение, но полнота, такая как аннотации отклонений, имеет решающее значение для написания расширяемого программного обеспечения.

Давайте посмотрим, что Википедия должна сказать по этому вопросу.

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

В компьютерном программировании оператор - это наименьший автономный элемент императивного языка программирования, который выражает некоторые действия, которые необходимо выполнить.

Многие языки (например, C) различают операторы и определения, причем оператор содержит только исполняемый код и определение, объявляющее идентификатор, тогда как выражение оценивается только как значение.

-10
23.05.2017 11:55:10
Заявление не должно иметь побочный эффект. Например, в python passесть утверждение. Это неоперация, и это ни к чему не приводит.
Matthew Schinckel 10.12.2011 10:01:19
-1 Это неправильно. Заявление не должно иметь побочный эффект. См. Раздел 1.5 спецификации языка C # . Мало того, что не указано , что заявления должны иметь побочные эффекты, но он также перечисляет несколько заявлений , которые не могут иметь не побочные эффекты.
NullUserException 10.12.2011 19:35:44
@NullUserException Я прочитал этот раздел. Операторы объявлений, выражений, выбора, итерации и перехода могут создавать побочные эффекты. Но если есть выражение RT, то это не утверждение. Я понимаю, что спецификация приравнивает выражения к операторам, но этот вопрос задал разницу между ними. Так что либо на вопрос нет ответа, либо вы слишком буквально воспринимаете спецификацию C #. Топ проголосовавший ответ пытается сказать, что я сделал. Но «что-то делать» не имеет смысла. «побочный эффект» - это осмысленный способ сказать «делает что-то». Мы должны думать, а не просто извергать.
Shelby Moore III 12.12.2011 06:34:16
@ShelbyMooreIII Вы правы. Официальная документация неверна . Марк Грэвелл и Джон Скит, которые, возможно, наиболее уважают постеры C #, работающие на SO вне Эрика Липперта, ошибаются . Я и все остальные, которые отрицали вашу позицию и оставили комментарии, объясняющие нашу позицию, не правы . Ты прав. Вы, очевидно, единственный человек, который знает, о чем они говорят, так как вы намного умнее, чем все остальные SO.
NullUserException 12.12.2011 07:19:58
Знание точного определения таких понятий, как оператор, выражение, приведение, преобразование и т. Д., Не оказывает влияния на 99,999% повседневных задач программирования. Подумай об этом . Также: большинство людей не заботятся о Haskell и Scala.
NullUserException 12.12.2011 07:30:58

Заявления -> Инструкции для последовательного следования
выражений -> Оценка, которая возвращает значение

Утверждения в основном похожи на шаги или инструкции в алгоритме, результатом выполнения оператора является актуализация указателя инструкции (так называемого в ассемблере)

Выражения не подразумевают и порядок исполнения с первого взгляда, их цель - оценить и вернуть значение. В императивных языках программирования оценка выражения имеет порядок, но это только из-за императивной модели, но не в их сущности.

Примеры заявлений:

for
goto
return
if

(все они подразумевают переход строки (оператора) выполнения к другой строке)

Пример выражения:

2+2

(это подразумевает не идею исполнения, а оценку)

2
5.09.2012 15:47:14
Как насчет побочных эффектов?
Austin Henley 23.09.2012 03:20:45

Заявление ,

Оператор - это процедурный строительный блок, из которого создаются все программы на C #. Оператор может объявить локальную переменную или константу, вызвать метод, создать объект или присвоить значение переменной, свойству или полю.

Серия операторов, окруженная фигурными скобками, образует блок кода. Тело метода является одним из примеров блока кода.

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

Выражения в C # часто содержат выражения. Выражение в C # - это фрагмент кода, содержащий буквальное значение, простое имя или оператор и его операнды.

Выражение ,

Выражение - это фрагмент кода, который может быть оценен для одного значения, объекта, метода или пространства имен. Два самых простых типа выражений - литералы и простые имена. Литерал - это постоянное значение, которое не имеет имени.

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

И i, и s - простые имена, идентифицирующие локальные переменные. Когда эти переменные используются в выражении, значение переменной извлекается и используется для выражения.

1
17.09.2012 12:11:07
Я бы лучше написал if(number >= 0) return true; else return false;или даже лучше bool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;}:)
Mahdi Tahsildari 28.07.2013 20:18:10

Я предпочитаю значение statementв формально-логическом смысле этого слова. Это та, которая изменяет состояние одной или нескольких переменных в вычислении, позволяя сделать истинное или ложное утверждение об их значениях.

Я предполагаю, что всегда будет путаница в вычислительном мире и науке в целом, когда вводится новая терминология или слова, существующие слова «перепрофилируются» или пользователи не знают о существующей, установленной или «правильной» терминологии в отношении того, что они описывают.

1
7.05.2013 15:18:17

Вот краткое изложение одного из самых простых ответов, которые я нашел.

Первоначально ответил Anders Kaseorg

Оператор - это полная строка кода, которая выполняет какое-то действие, а выражение - это любой раздел кода, который оценивает значение.

Выражения могут быть объединены «горизонтально» в более крупные выражения с использованием операторов, тогда как выражения могут быть объединены «вертикально» только путем записи одного за другим или с блочными конструкциями.

Каждое выражение может быть использовано как оператор (чей эффект заключается в оценке выражения и игнорировании полученного значения), но большинство операторов нельзя использовать в качестве выражений.

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

0
8.09.2014 13:29:54

Я не очень удовлетворен ни одним из ответов здесь. Я посмотрел на грамматику для C ++ (ISO 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например, это помеченное заявление
  • Выбор-заявление s является if if/else,case
  • итерация-заявление s являются while, do...while,for (...)
  • перепрыжка заявление s являются break, continue, return(может возвращать выражение),goto
  • объявление-заявление является набором объявлений
  • try-block это оператор, представляющий try/catchблоки
  • и там может быть еще немного вниз по грамматике

Это отрывок, показывающий часть выражений:

expression:
        assignment-expression
        expression "," assignment-expression
assignment-expression:
        conditional-expression
        logical-or-expression assignment-operator initializer-clause
        throw-expression
  • выражения являются или содержат часто присваивания
  • условно-выражение (звуки , вводит в заблуждение) относится к использованию операторов ( +, -, *, /, &, |, &&, ||, ...)
  • бросающее выражение - а? throwположение является выражением слишком
1
21.06.2015 00:56:22

Чтобы улучшить и подтвердить мой предыдущий ответ, определения терминов языка программирования должны быть объяснены из теории типов компьютерных наук, когда это применимо.

Выражение имеет тип, отличный от типа Bottom, то есть имеет значение. Оператор имеет тип Unit или Bottom.

Из этого следует, что оператор может иметь какой-либо эффект в программе только тогда, когда он создает побочный эффект, поскольку он либо не может вернуть значение, либо возвращает только значение типа Unit, которое либо не присваивается (в некоторых языках, например, C void) или (например, в Scala) могут быть сохранены для отложенной оценки оператора.

Очевидно, что a @pragmaили a не /*comment*/имеют типа и поэтому отличаются от утверждений. Таким образом, единственным типом заявления, которое не будет иметь побочных эффектов, будет неоперация. Неоперация полезна только в качестве заполнителя для будущих побочных эффектов. Любое другое действие из-за заявления будет побочным эффектом. Снова подсказка компилятора, например @pragma, не является оператором, потому что у него нет типа.

-5
17.08.2015 18:48:32
Различие не имеет ничего общего с типом выражений. Синтаксически определенные операторы вообще не имеют типов во многих языках. Хотя я не против, чтобы назначить тип на таких терминах в теории, различные трактовки @pragmaили /*comment*/логически несовместимы.
FrankHB 23.08.2019 01:21:17

Де-факто основой этих понятий является:

Выражения : синтаксическая категория, экземпляр которой может быть оценен по значению.

Утверждение : синтаксическая категория, экземпляр которой может быть связан с оценками выражения, и результирующее значение оценки (если есть) не гарантировано доступно.

Помимо самого начального контекста ФОРТРАНА в первые десятилетия, оба определения выражений и утверждений в принятом ответе явно неверны:

  • Выражения могут быть неоцененными операндами. Ценности никогда не производятся от них.
    • Субэкспрессия в нестрогих оценках может быть определенно недооценена.
      • Большинство C-подобных языков имеют так называемые правила оценки короткого замыкания, чтобы условно пропустить некоторые оценки подвыражения, не изменяя конечный результат, несмотря на побочные эффекты.
    • C и некоторые C-подобные языки имеют понятие неоцененного операнда, который может быть даже нормативно определен в спецификации языка. Такие конструкции используются, чтобы избежать определенных оценок, поэтому оставшаяся контекстная информация (например, типы или требования выравнивания) может быть статически выделена без изменения поведения после перевода программы.
      • Например, выражение, используемое в качестве операнда sizeofоператора, никогда не вычисляется.
  • Утверждения не имеют ничего общего с линейными конструкциями. Они могут делать что-то большее, чем выражения, в зависимости от языковых спецификаций.
    • Современный Fortran, как прямой потомок старого FORTRAN, имеет концепции исполняемого оператора s и неисполнимого оператора s.
    • Точно так же C ++ определяет объявления как подкатегорию верхнего уровня единицы перевода. Объявление в C ++ - это утверждение. (Это не так в C.) Существуют также операторы выражений, такие как исполняемые операторы Фортрана.
    • Для сравнения выражений важны только «исполняемые» операторы. Но нельзя игнорировать тот факт, что операторы уже обобщены, чтобы быть конструкциями, формирующими единицы перевода на таких императивных языках. Итак, как вы можете видеть, определения категории сильно различаются. (Возможно) единственное оставшееся общее свойство, сохраняемое среди этих языков, заключается в том, что операторы должны интерпретироваться в лексическом порядке (для большинства пользователей слева направо и сверху вниз).

(Кстати, я хочу добавить [цитата нужна] к этому ответу относительно материалов о C, потому что я не могу вспомнить, есть ли у DMR такие мнения. Кажется, нет, в противном случае не должно быть никаких причин сохранять дублирование функциональности в дизайне C : в частности, оператор запятой против операторов.)

(Следующее обоснование не является прямым ответом на первоначальный вопрос, но я считаю необходимым уточнить кое-что, на что здесь уже дан ответ.)

Тем не менее, сомнительно, что нам нужна особая категория «операторов» в языках программирования общего назначения:

  • Утверждения не гарантируют, чтобы иметь больше семантических возможностей по сравнению с выражениями в обычных проектах.
    • Многие языки уже успешно отказались от понятия утверждений, чтобы получить чистый, аккуратный и согласованный общий дизайн.
      • В таких языках выражения могут делать все, что могут делать операторы старого стиля: просто отбрасывать неиспользуемые результаты при оценке выражений, либо оставляя результаты явно неуказанными (например, в схеме R n RS), либо имея специальное значение (как значение типа единицы) не может быть получено из вычислений нормального выражения.
      • Правила лексического порядка вычисления выражений могут быть заменены оператором явного контроля последовательности (например, beginна схеме) или синтаксическим сахаром монадных структур.
      • Правила лексического порядка других видов «операторов» могут быть получены как синтаксические расширения (например, с использованием гигиенических макросов), чтобы получить аналогичную синтаксическую функциональность. (И это действительно может сделать больше .)
    • Напротив, у заявлений не может быть таких общепринятых правил, потому что они не сочетаются с оценкой: просто нет такого распространенного понятия «оценка подзаголовка». (Даже если таковые имеются, я сомневаюсь, что может быть нечто гораздо большее, чем копирование и вставка из существующих правил оценки выражений.)
      • Как правило, операторы, сохраняющие языки, также будут иметь выражения для выражения вычислений, и существует подкатегория верхнего уровня операторов, сохраненная для вычислений выражений для этой подкатегории. Например, C ++ имеет так называемый оператор выражения в качестве подкатегории и использует правила оценки выражения с отброшенными значениями для определения общих случаев оценки полного выражения в таком контексте. Некоторые языки, такие как C #, выбирают для уточнения контекстов, чтобы упростить варианты использования, но это больше раздувает спецификацию.
  • Для пользователей языков программирования значение утверждений может еще больше запутать их.
    • Разделение правил выражений и утверждений на языках требует больше усилий для изучения языка.
    • Наивная интерпретация лексического порядка скрывает более важное понятие: оценка выражения. (Это, вероятно, наиболее проблематично из всех.)
      • Даже вычисления полных выражений в выражениях ограничены лексическим порядком, а подвыражения - нет (обязательно). Пользователи должны в конечном счете изучить это помимо любых правил, связанных с утверждениями. (Подумайте, как заставить новичка понять, что ++i + ++iдля C. бессмысленно)
      • Некоторые языки, такие как Java и C #, еще более ограничивают порядок вычислений подвыражений, чтобы разрешить игнорирование правил оценки. Это может быть еще более проблематичным.
        • Это кажется чрезмерным для пользователей, которые уже изучили идею оценки выражений. Это также побуждает сообщество пользователей следовать размытой ментальной модели языкового дизайна.
        • Это еще больше расширяет спецификацию языка.
        • Это вредно для оптимизации, так как пропускает выразительность недетерминизма в оценках, прежде чем вводятся более сложные примитивы.
      • Некоторые языки, такие как C ++ (в частности, C ++ 17), задают более тонкий контекст правил оценки в качестве компромисса вышеперечисленных проблем.
        • Это сильно раздувает спецификацию языка.
        • Это полностью противоречит простоте для средних пользователей ...

Так почему заявления? Во всяком случае, история уже беспорядок. Кажется, большинство языковых дизайнеров не принимают свой выбор тщательно.

Хуже того, он даже дает некоторым энтузиастам систем типов (которые недостаточно знакомы с историей PL) некоторые заблуждения о том, что системы типов должны иметь важные вещи, связанные с более существенными разработками правил операционной семантики.

Серьезно, рассуждение в зависимости от типов не так уж плохо во многих случаях, но особенно неконструктивно в этом особом. Даже эксперты могут все испортить.

Например, кто-то подчеркивает типизирующую природу как центральный аргумент против традиционного подхода к неограниченным продолжениям . Хотя этот вывод несколько обоснован, и понимание составных функций в порядке ( но все же слишком наивно для сути ), этот аргумент не верен, поскольку на практике он полностью игнорирует подход «побочного канала», такой как _Noreturn any_of_returnable_types(в C11) для кодирования Falsum. И, строго говоря, абстрактная машина с непредсказуемым состоянием не идентична «разбитому компьютеру».

0
23.08.2019 04:35:09