О стоимости первого, второго и третьего класса - PullRequest
22 голосов
/ 05 апреля 2010

Первоклассное значение может быть

  1. передано в качестве аргумента
  2. возвращается из подпрограммы
  3. присвоено переменной.

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

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

Почему эти вещи должны быть определены так? Как я понимаю, «может быть передан в качестве аргумента» означает, что он может быть помещен в стек времени выполнения; «может быть назначен в переменную» означает, что он может быть перемещен в другое место в памяти; «может быть возвращен из подпрограммы» почти имеет то же значение, что и «может быть назначен переменной», поскольку возвращаемое значение всегда помещается в известный адрес, поэтому значение первого класса является полностью «подвижным» или «динамическим», второй класс значение наполовину «подвижно», а значение третьего класса просто «статично», например, метки в C / C ++, к которым можно обратиться с помощью оператора goto, и вы ничего не можете сделать с этим адресом, кроме «goto». понимание имеет смысл? или что именно означают эти три вида значений?

Ответы [ 4 ]

40 голосов
/ 06 апреля 2010

О нет, возможно, мне придется снова редактировать Википедию.

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

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

Давайте рассмотрим несколько примеров:

  • Указатели на функции в C являются первоклассными значениями, потому что они могут быть переданы в функции, возвращены из функций и сохранены в структурах данных, выделенных в куче, как любое другое значение. Функции в Pascal и Ada не являются первоклассными значениями, потому что, хотя они могут быть переданы в качестве аргументов, они не могут быть возвращены как результаты или сохранены в структурах данных, выделенных в куче.

  • Типы структур являются типами второго класса в C, потому что нет никаких литеральных выражений структурного типа. (Начиная с C99 существуют литеральные инициализаторы с именованными полями, но это все же не так широко, как наличие литерала везде, где вы можете использовать выражение.)

  • Полиморфные значения являются значениями второго класса в ML, потому что, хотя они могут быть привязаны к именам, они не могут быть привязаны к лямбде. Поэтому они не могут быть переданы в качестве аргументов. Но в Haskell, поскольку Haskell поддерживает полиморфизм более высокого ранга, полиморфные значения являются первоклассными. (Они могут даже храниться в структурах данных!)

  • В Java тип int является вторым классом, потому что вы не можете наследовать от него. Тип Integer первого класса.

  • В C метки относятся ко второму классу, потому что у них нет значений, и вы не можете с ними вычислять. В Фортране номера строк имеют значения и поэтому относятся к первому классу. Существует расширение GNU для C, которое позволяет вам определять первоклассные метки, и это очень полезно. Что значит первоклассный в этом случае? Это означает, что метки имеют значения, могут храниться в структурах данных и могут использоваться в goto. Но эти значения относятся ко второму классу в другом смысле, потому что метка из одной процедуры не может быть осмысленно использована в goto, который принадлежит другой процедуре.

Получаем ли мы представление о том, насколько бесполезна эта терминология?

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

Что касается «третьего класса», просто скажите «нет».

4 голосов
/ 06 апреля 2010

Что-то первоклассное, если явно манипулируется в коде. Другими словами, что-то является первоклассным, если им можно программно манипулировать во время выполнения.

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

  • Мы говорим о первоклассном объекте , потому что объектами можно манипулировать программно во время выполнения (это и есть цель).

  • В Java у вас есть классы , но они не первого класса, потому что код обычно не может манипулировать классом, если вы не используете отражение. Но в Smalltalk классы являются первоклассными: код может манипулировать классом, как обычный объект.

  • В java у вас есть пакетов (модулей) , но они не являются первоклассными, потому что код не манипулирует пакетами во время выполнения. Но в NewSpeak пакеты (модули) являются первоклассными, вы можете создать экземпляр модуля и передать его другому модулю, чтобы указать модульность во время выполнения.

  • В C # у вас есть замыкания, которые являются первоклассными функциями. Они существуют и могут управляться программно во время выполнения. Таких вещей не существует (пока) в Java.

Для меня граница первого класса / не первого класса не совсем строгая. Иногда трудно произнести некоторые языковые конструкции, например, Java примитивные типы. Мы могли бы сказать, что это не первый класс, потому что это не объект и он не может быть обработан через ссылку, которую можно передать, но примитивное значение все еще существует и может управляться во время выполнения.

PS: Я согласен с Норманом Рэмси, и ценность для 2-го и 3-го классов не имеет для меня никакого смысла.

2 голосов
/ 21 августа 2015
  1. Первый класс. Первоклассная конструкция - это внутренняя составляющая языка. Следующие свойства должны храниться.
    • Он должен быть частью лексического синтаксиса языка
    • Возможно, к нему применены операторы
    • Он должен быть ссылочным (например, храниться в переменной)
  2. Второй класс. Конструкция второго класса - это элемент, являющийся внутренним элементом языка со следующими свойствами.
    • Он должен быть частью лексического синтаксиса языка
    • Возможно, к нему применены операторы
  3. Третий класс. Конструкция третьего класса является частью синтаксиса языка.

в Роджер Кис и Андри Ракотонирайны. Контекстно-ориентированное программирование. В материалах 3-го Международного семинара ACM по проектированию данных для беспроводного и мобильного доступа, MobiDe '03, страницы 9–16, Нью-Йорк, Нью-Йорк, США, 2003 г.

0 голосов
/ 16 сентября 2017

Эти термины очень широки и не имеют четкого определения в глобальном масштабе, но вот наиболее логичные определения для них:

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

Это действительно не нуждается в тщательном примере, не так ли?В C int - это первый класс.

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

Например, в C функция является значением второго класса.Его нельзя изменить, но на него можно вызывать и ссылаться.

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

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

Другой пример, в C ++, структура или класс - это значение третьего класса.Это не требует особых объяснений.

...