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

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

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

Я считаю, что выбранный вами ответ неоднозначен. Выражение тоже что-то делает - вычисляет значение. Я дал однозначный ответ.

Shelby Moore III 09.12.2011 23:36

@ShelbyMooreIII - Однозначно и тоже неверно. Принятый ответ сформулирован неформально, но такая формулировка упрощает понимание - и, что самое главное, смысл, который он передает, является точным.

Justin Morgan 14.12.2012 01:56

@JustinMorgan К сожалению, определения в принятом ответе также явно неверны («оценивает значение» / «строка кода») для большинства современных языков, включая C-подобные: выражения могут использоваться в неоцененных контекстах, а утверждения не имеют ничего делать с линиями. Даже если есть некоторые объяснения, короткий ответ сбивает с толку и вводит в заблуждение.

FrankHB 23.08.2019 04:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
446
3
65 066
20
Перейти к ответу Данный вопрос помечен как решенный

Ответы 20

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

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

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

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

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

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

Тип заявления - нижний тип. Void не является нижним типом. См. мой ответ.

Shelby Moore III 09.12.2011 23:07

Разве нулевой тип не является нижним типом (единственное значение null)? Разве void не был бы больше похож на тип единицы (но с недоступным его единственным значением)?

Mark Cidade 10.12.2011 02:04

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

Shelby Moore III 10.12.2011 02:40

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

Mark Cidade 10.12.2011 04:57

Марк: Я оценил рациональность вашего ответа. Вы в основном убрали слова из моих уст. И я надеюсь, было ясно, что я признал вам, что вы были правы, когда подняли единичный балл. Думаю, мы согласны. Я не собирался упоминать об этом, но, похоже, некоторые люди здесь думают, что я веду себя отрицательно. Я просто пытаюсь быть правдой.

Shelby Moore III 10.12.2011 10:27

@ShelbyMooreIII Нет, это не так. У оператора просто нет типа. Попытка рассматривать его как значение является синтаксической ошибкой. Если выражение имеет нижний тип, оно никогда ничего не вернет. Он вызовет исключение, выполнит бесконечный цикл или изменит поток управления другими причудливыми способами.

Xwtek 07.06.2020 12:40

@Akangka в теории типов все фрагменты кода (не связанные с комментариями, прагмами, макросами препроцессора и т. д.) Имеют тип, иначе система типов не будет согласованной. Если ваш PL (например, не Scala) не позволяет вам абстрагироваться от типа Unit, это не отменяет того факта (как я писал в своих ответах правильный), что операторы не являются выражениями (т.е. не возвращают значение), таким образом, имеют тип Unit. Я также объяснил в своем ответе, что Unit, возможно, является фикцией, поэтому IMO является синонимом нижнего типа. Фрагмент кода, имеющий тип дна, не является выражением ...

Shelby Moore III 11.06.2020 03:08

@Akangka проблема здесь, на S.O. как я объяснил на примере - это групповое мышление, которое хочет объединить отдельные проблемы с отдельными моделями. Например, как я объяснил правильно в своих ответах на этой странице, получивших сильные отрицательные голоса, если выражение определено так, чтобы допускать нижний тип и / или побочные эффекты, тогда термин выражение будет определенно нечеткий w.r.t. term, потому что операторы имеют побочные эффекты и расходятся (т. е. никогда не возвращаются).

Shelby Moore III 11.06.2020 03:24

@Akangka написал «У оператора просто нет типа […] Если у выражения есть нижний тип». Не удаляйте свой комментарий, если вы понимаете, что утверждения могут вызывать выражения. Ржунимагу. Я в архиве обсуждение.

Shelby Moore III 11.06.2020 03:39

@ShelbyMooreIII «в теории типов все фрагменты кода [...] имеют тип, иначе система типов не будет согласованной». Да, вы правы ... в языке из большого семейства типизированных лямбда-исчислений, которое является наиболее широко используемой математической моделью для языка программирования. Для большинства операторов (кроме определения переменных и, вероятно, некоторых других) вы также можете определить выражение let expr = ()=>{ statement; } in expr(), которое является является выражением. Причина, по которой типизированное лямбда-исчисление не имеет операторов, заключается в том, что 1. утверждения не нужны и 2. это излишне усложняет рассуждение.

Xwtek 11.06.2020 12:45

@ShelbyMooreIII Фактически, тип - это просто набор значений, которые может возвращать выражение (если вообще). Во всех системах типов, которые имеют функцию (даже если это не первый класс), если у меня есть функция f типа (Unit) -> a, я смогу ввести f(<anything that have type of Unit>). Однако в Python вы не можете использовать f(raise Exception("this expression should've been legal")), а в Rust вы не можете использовать f(let a = 42). Этот синтаксис не имеет аналогов в типизированном лямбда-исчислении.

Xwtek 11.06.2020 12:59

@ShelbyMooreIII Если вы думаете, что оператор имеет нижний тип, точка все равно остается в силе, потому что нижний тип является подтипом каждого типа. Также я не удалял комментарий

Xwtek 11.06.2020 13:02

Позвольте нам продолжить обсуждение в чате.

Xwtek 11.06.2020 13:07

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

Например:

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

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

Уверенные утверждения могут быть связаны. {stmt1; stmt2; stmt3;} - это цепочка, а также сам (составной) оператор.

Hugh Allen 08.04.2009 05:54

foo.voidFunc(1); - это выражение с пустым значением. while и if являются заявлениями.

tzot 02.12.2009 16:57

Мне любопытно, что утверждения не связаны. Что-нибудь вроде "if (x> 1) return;" считаться соединением двух утверждений вместе?

Simon Tewsi 30.01.2013 02:25

@SimonTewsi Я считаю, что return считается подделкой.

RastaJedi 17.03.2019 07:15

@SimonTewsi Здесь оператор return неявно находится внутри блока оператора if, поэтому он является частью оператора if, а не связан с ним. Компилятор позволяет нам опускать фигурные скобки здесь, поскольку это однострочный блок.

user2597608 05.06.2020 20:22

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

Итак, что делает заявление? Ничего?

Shelby Moore III 09.12.2011 23:16

Он может что-то делать, но ничего не оценивает. То есть, вы не можете присвоить результат переменной, а можете - выражению.

Matthew Schinckel 10.12.2011 13:52

И поэтому у утверждения должны быть побочные эффекты, как говорится в моем ответе, который сильно отклонился. Какую еще полезность может иметь утверждение? Даже если бы NO-OP считался оператором (это только «оператор» в грамматике, но не на уровне семантики, потому что он стирается после синтаксического анализа, а семантика - это то, что мы здесь обсуждаем), он не объяснил бы, что черт возьми, общая полезность утверждения есть.

Shelby Moore III 25.08.2014 10:47

Заявления @ShelbyMooreIII не требуют каких-либо действий или имеют побочные эффекты. например, {} - это заявление. Использование пугающих кавычек этого не меняет. Операторы - это синтаксические конструкции с семантикой. Не существует такой вещи, как «уровень семантики» - похоже, вы имеете в виду исполнение. Вы говорите, что пытаетесь быть точным, но вам это не удалось. Ваша жалоба на «невежество противников» - чистое ad hominem; у вас нет информации о психологическом состоянии опровергающих.

Jim Balter 29.07.2015 02:43

Да, все ошибаются, кроме интеллектуально нечестных. {} определяется как инструкция в спецификации языка C#.

Jim Balter 18.08.2015 10:40

Остерегайтесь языка с нижним шрифтом. Некоторое выражение на этом языке не дает значения.

Xwtek 07.06.2020 12:35

@ShelbyMooreIII предполагает, что существует функция a с определением function a() -> Bottom{ while(true){} }, тогда тип выражения a() - Bottom. Это справедливо даже для такого языка, как Rust, который так долго оценивают. Семантика такова, что если выражение оценивается, выражение не вернет значение, а вместо этого откажется от текущего потока управления. Это может быть исключение, или вызов / cc, или, как в примере кода, бесконечный цикл.

Xwtek 11.06.2020 12:33

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

Xwtek 12.06.2020 01:57

@Akangka Я бы подумал, что декларация является - это утверждение.

Matthew Schinckel 13.06.2020 12:31

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

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

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

Ответ принят как подходящий

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

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

1 + 2 / X

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

X = 1 + 2 / X

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

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

1 + 2 / x;

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

1 + 2 / callfunc(12);

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

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

callfunc(x = 2);

Это вычисляет выражение x = 2 (присваивая x значение 2), а затем передает это (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 - это языки, в которых нет синтаксических операторов - у них есть только выражения. Даже циклы со структурой классов и условные формы считаются выражениями, и у них есть значения, но не очень интересные.

Если я не неправильно интерпретирую вас здесь, вы, кажется, утверждаете, что "(setf (third foo) 'goose)" является выражением, а не утверждением, потому что это Лисп, который "не имеет операторов", и потому что Lisp более чем на десять лет старше C, который был «первым популярным языком, стирающим границы [между выражениями и операторами]». Не могли бы мне объяснить подробности этого?

cjs 24.06.2009 22:24

@ Курт Сэмпсон, вы задавали это как отдельный вопрос?

Kelly S. French 28.10.2009 02:06

Если я не ошибаюсь, callfunc(x = 2); передает x на callfunc, а не 2. Если x является плавающим, будет вызываться callfunc(float), а не callfunc(int). А в C++, если вы передаете x=y в func, а func берет ссылку и изменяет ее, он меняет x, а не y.

Gabriel 23.09.2011 06:34

В ответе выше написано, что «Haskell, ... все языки, не имеющие синтаксических операторов - у них есть только выражения». Мне любопытно, почему предложение where в haskell считается выражением, а не утверждением. Learnyouahaskell.com/syntax-in-functions#where

skgbanga 30.11.2016 08:11

@skgbanga Я считаю, что where на самом деле является частью объявления функции, а не выражения или утверждения.

Xwtek 07.06.2020 12:33

@JimBalter Я прочитал справочную грамматику и был прав. haskell.org/onlinereport/haskell2010/haskellch10.html. Обратите внимание, что предложение where рассматривается как часть rhs (правая часть объявления), а не exp (выражение). Утверждение where как выражение подразумевает, что охранники тоже являются выражением.

Xwtek 11.06.2020 15:27

@Akangka Мой комментарий не имел ничего общего с вашим ... он был об ответе Джоэла Спольски.

Jim Balter 12.06.2020 06:34
  • выражение - это все, что дает значение: 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

Неправильная логика того, что такое утверждение. Декларативная программа также может выполняться, но декларативная программа не имеет операторов. Утверждение есть и делает "побочные эффекты", то есть обязательно. ср. мой ответ.

Shelby Moore III 09.12.2011 23:28

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


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


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


В языке, основанном на выражениях, все возвращает значение. Поначалу это может показаться немного странным - что возвращает (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
)

Оператор - это частный случай выражения, имеющего тип 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? Да. Все, что ему нужно сделать, это потребовать, чтобы после return следовало выражение типа void. Результатом default(void) будет тип void, а передаваемая функция должна иметь форму Func<TValue, void> (что эквивалентно Action<TValue>).

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

Утверждение - это не особый случай выражения. В некоторых языках (например, в большинстве последователей C) все наоборот.

Xwtek 07.06.2020 12:41

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

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

Утверждения - это грамматически законченные предложения. Выражений нет. Например

x = 5

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

(x + 5)/9.0

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

while k < 10: 
    print k
    k += 1

это полное предложение. Обратите внимание, что заголовка цикла нет; "в то время как k

while - это выражение некоторых языков, таких как Scala. Вы смешиваете грамматику с набором текста. См. мой ответ.

Shelby Moore III 09.12.2011 23:12

Вот цикл while в scala: tutorialspoint.com/scala/scala_ while_loop.htm Цикл со своим предикатом и без тела не является грамматически законченным предложением. Это не полное выражение. Вам нужно тело, чтобы завершить его как выражение.

ncmathsadist 08.05.2013 04:42

while с телом по-прежнему является выражением в Scala. Это также может быть утверждение, если оно создает побочные эффекты, что допускает мой ответ, получивший сильную отрицательную оценку (выражение также может быть утверждением). Мой ответ - единственно правильный. Извините всех тех читателей, которые не понимают.

Shelby Moore III 22.06.2013 20:49

Что вы имеете в виду под грамматически завершенным? В языке C (x + 5)/9.0 определенно может выступать отдельно. Кроме того, если под грамматически завершенной вы имеете в виду действительную программу, C не позволяет операторам выступать отдельно как единую программу.

Xwtek 11.06.2020 15:34

Грамматически полное: составляет законченное предложение.

ncmathsadist 13.06.2020 01:31

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

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


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

Посмотрим, что говорит Википедия по этому поводу.

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

In computer programming a statement is the smallest standalone element of an imperative programming language that expresses some action to be carried out.

Many languages (e.g. C) make a distinction between statements and definitions, with a statement only containing executable code and a definition declaring an identifier, while an expression evaluates to a value only.

Пожалуйста, не переопределяйте общие технические термины «выражение» и «утверждение». Мои комментарии и ответ верны для C#. Если f(); имеет тип void и не имеет побочных эффектов, то это NOOP. Хороший компилятор не допускает NOOP. Если f(); не имеет побочных эффектов и его возвращаемое значение не используется, это также NOOP. Я ответил на вопрос по поводу C#. Я ответил одним точным предложением. Это предложение верно для C#. Затем я подробно рассказал о том, что означает void в C# с точки зрения теории типов. Теория типов применима к C#.

Shelby Moore III 10.12.2011 10:33

См. Мои комментарии под ответом Марка Сидаде, которые объясняют, почему утверждение часто на самом деле является нижним типом, а не типом единицы. Сказать, что утверждение «что-то делает» невероятно неточно, поскольку выражение также «что-то делает» - оно дает значение. Я знаю, что люди пытаются сказать, просто они не выбирают точных слов и определений. Точное слово (утверждение не должно быть) ссылочно прозрачным (т. Е. Императивным). Это более точно, чем «что-то делает» или «побочный эффект».

Shelby Moore III 10.12.2011 10:35

Заявление не обязательно должно иметь побочный эффект. Например, в Python pass - это утверждение. Это запретная операция, и она ни к чему не приводит.

Matthew Schinckel 10.12.2011 14:01

@MatthewSchinckel Если у него нет побочного эффекта, то это либо выражение, либо NOOP. NOOP ничего не делает, поэтому его можно удалить из программы. Это простой процесс логического исключения. Если вы не определяете оператор как требующий побочного эффекта, оператор будет таким же, как выражение. Какой еще атрибут вы бы использовали, чтобы отличить утверждение от выражения?

Shelby Moore III 10.12.2011 16:05

-1 Это неправильно. У оператора имеют нет побочного эффекта. См. Раздел 1.5 Спецификация языка C#. Он не только не указывает, что операторы должен имеют побочные эффекты, но также перечисляет несколько операторов, которые могут иметь побочные эффекты нет.

NullUserException 10.12.2011 23:35

@NullUserException Я прочитал этот раздел. Операторы декларации, выражения, выбора, итерации и перехода могут создавать побочные эффекты. Но если есть выражение RT, то это не утверждение. Я понимаю, что спецификация приравнивает выражения к операторам, но в этом вопросе задавалась разница между ними. Так что либо на вопрос нет ответа, либо вы слишком буквально воспринимаете спецификацию C#. Ответ, получивший наибольшее количество голосов, пытается сказать, что я сделал. Но «что-то делает» бессмысленно. «побочный эффект» - это осмысленный способ сказать «что-то делает». Мы должны думать, а не просто срыгивать.

Shelby Moore III 12.12.2011 10:34

@ShelbyMooreIII Вы правы. Официальная документация - неправильный. Марк Грейвелл и Джон Скит, которые, возможно, являются наиболее уважаемыми авторами C#, работающими на SO, за исключением Эрика Липперта, являются неправильный. Я и все остальные, кто проголосовал против вас и оставили комментарии, объясняющие нашу позицию, - это неправильный. Ты прав. Очевидно, что вы единственный человек, который знает, о чем они говорят, поскольку вы намного умнее всех остальных в SO.

NullUserException 12.12.2011 11:19

@NullUserException Они очень правы в том, как большинство пользователей C# хотят понимать концепции. Но я показываю им общую картину, возможно, они еще не видели. Я понимаю когнитивный диссонанс, тоже страдаю. В прошлом я делал аналогичные более узкие предположения. Раньше я происходил из мира C / C++ / C#, поэтому я знаю, как сложно мне было адаптироваться к Haskell, Scala и другим общим концепциям. Но я готов согласиться с тем, что мои ответы не так полезны, как другие в этом контексте. Допустим, вы правильный в каком-то смысле

Shelby Moore III 12.12.2011 11:27

Знание точного определения таких понятий, как оператор, выражение, приведение, преобразование и т. д., Не оказывает никакого влияния на 99,999% повседневных задач программирования. Подумайте о который. Также: большинству людей наплевать на Haskell и Scala.

NullUserException 12.12.2011 11:30

@NullUserException Но если можно, подумайте об этом. Если выражение отличается от оператора, что это за отдельный атрибут? "Что-то делает"? Определите «что-то». Я думаю, вы обнаружите, что мой ответ совпадает с ответом, получившим наибольшее количество голосов. Я только что определил, что такое «что-то». Спецификация C# просто для удобства. Не следует ожидать, что вы думаете, что выражения неотличимы от утверждений. Или вы считаете, что выражения - это просто подмножество утверждений, но это не работает. Мне показать, как это не может работать?

Shelby Moore III 12.12.2011 11:35

@ShelbyMooreIII Я никогда не утверждал, что выражения - это просто подмножество утверждений. Но опять же, это не имеет значения.

NullUserException 12.12.2011 11:38

@NullUserException Действительно, Haskell тупой и из-за ленивых вычислений имеет пространственно-временную неопределенность, что затрудняет отладку. Также у него нет виртуального наследования. Scala исправляет многие из этих вещей и на данный момент является самым быстрорастущим языком, но все еще очень незначительным. Scala довольно хорош, но у его синтаксиса слишком много вариантов, например 9 способов написать функцию и другие вопросы. Также на данный момент по большей части привязан к библиотекам Java. C# работает на Android? Хорошо, что вы не думаете, что выражения - это подмножество утверждений. Что значит «что-то»? Что такое «что-то»?

Shelby Moore III 12.12.2011 11:39

давайте продолжить обсуждение в чате

NullUserException 12.12.2011 11:44

@NullUserException Я уважаю этих ребят. Я никогда не мог ответить на все их вопросы. Их знания намного шире моих. Они действительно хорошо разбираются в кодировании на этих платформах. У них, наверное, намного больше энергии, чем у меня. И они, наверное, такие же умные, если не умнее меня. Я хочу, чтобы было ясно, что это не вопрос уважения. Я просто хочу, чтобы люди были непредубежденными и давали время на все. Иногда вещи не такие, какими кажутся.

Shelby Moore III 12.12.2011 11:44

Спецификация языка C# действительно ли нет требует, чтобы операторы имели побочные эффекты. Пустые операторы допустимы (раздел 8.3) независимо от того, оставляет их компилятор или нет. Фактически, поскольку работа с операторами без операции оставлена ​​на усмотрение реализации, даже NOOP могут потенциально повлиять на скомпилированный код и производительность программы. Так что ваш ответ неверен как с академической, так и с практической точки зрения.

Justin Morgan 14.12.2012 01:46

Компилируются ли NOOP или нет, в любом случае не имеет значения. { return 5; } - это утверждение, которое не вызывает побочных эффектов, если только вы не переопределили «побочный эффект», включив в него возврат одного значения. Это не только неприемлемое значение (даже в Haskell), оно имеет смысл только в чисто академическом смысле. () => 5 и () => { return 5; } после вычисления дают один и тот же результат, но один является выражением, а другой - нет.

Justin Morgan 14.12.2012 01:53

@JustinMorgan на абстрактном уровне языкового дизайна return - это либо просто выражение, которое является значением включающей функции, либо и то, и другое, а также сокращение для написания более сложной структуры if-else, чтобы все пути кода разрешались в значение . Неудивительно, что нефункциональные языки делают это неправильно. Например, в Scala return можно опустить, и вы можете просто написать 5 в конце пути кода для функции.

Shelby Moore III 15.01.2013 21:12

@MatthewSchinckel У заявление о прохождении определенно есть побочные эффекты. Это заставляет интерпретатор тратить циклы ЦП, чтобы обойти его. Он также предназначен в качестве заполнителя для функции, которая будет добавлять побочные эффекты вместо оператора pass, таким образом, это способ указания будущих побочных эффектов.

Shelby Moore III 17.08.2015 20:44

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

FrankHB 23.08.2019 04:34

«Это заставляет интерпретатор тратить циклы ЦП, чтобы обойти его» [необходима цитата]. У вас есть дизассемблированный байт-код Python в качестве доказательства?

Xwtek 11.06.2020 15:38

@Akangka, как обычно, это будет подвергаться цензуре, но в моем заявлении 2015 года, что не о интерпретаторе байт-кода, вместо этого я ссылаюсь на интерпретатор исходного кода. Если он полностью удален в байт-коде, это эквивалентно комментарию w.r.t. побочные эффекты по сравнению с ценностями и, следовательно, не имеют отношения к моим точкам определения. А теперь шу.

Shelby Moore III 12.06.2020 04:07

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

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

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

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

for
goto
return
if

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

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

2+2

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

@AustinHenley для этого нет требований. Фактически, выражение определенно может иметь побочный эффект.

Xwtek 11.06.2020 15:31

Заявление,

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

Ряд операторов, заключенных в фигурные скобки, образуют блок кода. Тело метода - это один из примеров блока кода.

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

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

Выражение,

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

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

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

Я лучше напишу 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 29.07.2013 00:18

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

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

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

Первоначально ответил Андерс Касеорг

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

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

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

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

Я не совсем удовлетворен ни одним из ответов здесь. Я посмотрел грамматику для 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, например, помеченное заявление
  • заявление о выборе - это ifif/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 также является выражением

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

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

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

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

Это различие не имеет ничего общего с типом выражений. Синтаксически определенные операторы вообще не имеют типов во многих языках. Хотя я не против назначать тип на таких условиях в теории, разные подходы к @pragma или /*comment*/ логически несовместимы.

FrankHB 23.08.2019 04:21

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

Википедия определяет слово утверждение аналогично

In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. A program written in such a language is formed by a sequence of one or more statements

Обратите внимание на последнее утверждение. (хотя «программа» в этом случае технически неверна, потому что и C, и Java отвергают программу, которая не состоит из операторов.)

Википедия определяет слово выражение как

An expression in a programming language is a syntactic entity that may be evaluated to determine its value

Однако это неверно, потому что в Kotlin throw new Exception("") является выражением, но при оценке оно просто генерирует исключение, никогда не возвращая никакого значения.

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

Лично я определяю выражение как часть синтаксиса, которую можно составить с помощью вызова оператора или функции, чтобы получить более крупное выражение. На самом деле это похоже на объяснение выражения в Википедии:

It is a combination of one or more constants, variables, functions, and operators that the programming language interprets (according to its particular rules of precedence and of association) and computes to produce ("to return", in a stateful environment) another value

Но проблема в языке программирования C, учитывая, что функция executeSome примерно такая:

void executeSomething(void){
    return;
}

executeSomething() - это выражение или утверждение? Согласно моему определению, это утверждение, потому что, как определено в справочной грамматике Microsoft C,

You cannot use the (nonexistent) value of an expression that has type void in any way, nor can you convert a void expression (by implicit or explicit conversion) to any type except void

Но на той же странице ясно указано, что такой синтаксис является выражением.

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

if (a>=0)
printf("Hello Humen,I'm a statement");

выражение, с другой стороны, возвращает или оценивает новое значение. Например -

 if (a>=0)
    return a+10;//This is an expression because it evalutes an new value;

или же

 a=10+y;//This is also an expression because it returns a new value. 

Выражение

A piece of syntax which can be evaluated to some value. In other words, an expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also statements which cannot be used as expressions, such as while. Assignments are also statements, not expressions.

Заявление

A statement is part of a suite (a “block” of code). A statement is either an expression or one of several constructs with a keyword, such as if, while or for.

Другие вопросы по теме