Когда функция считается «гражданином первого класса» на языке программирования / платформе?

61

Я много раз видел такие высказывания, как: «Пожалуйста, сделайте эту функцию первоклассным гражданином на том или ином языке / платформе». Например, говорится о перечислениях в C # /. Net. Итак, когда функция считается «гражданином первого класса» на языке программирования / платформе?

Gulshan
источник

Ответы:

40

Определение

Объект является первоклассным, когда он:

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

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

http://en.wikipedia.org/wiki/First_class_object

Waquo
источник
1
Итак, что делает перечисления объекта второго класса в .net / C #?
Гюльшан
7
@Gulshan - вы можете утверждать об отсутствии внутренней идентичности - перечисления C # в основном просто синтаксический сахар (то есть «заданное имя») для целочисленного значения. Сравните с Java, где перечисления являются объектами сами по себе.
Микера
@mikera, в .NET перечисления являются самостоятельными значениями. Ява просто не имеет никаких значений, только объекты, вот единственное отличие.
SK-logic
@mikera: Хотя это препятствует тому, чтобы перечисления Java имели некоторые хорошие свойства, такие как возможность представлять битовые поля с ними. Хотя их реализация, вероятно, более первоклассна, у большинства их API по-прежнему имеется множество целочисленных (или строковых) констант, и многие из них не могут быть легко заменены на перечисления.
Джои
Я не думаю, что перечисления могут быть созданы во время выполнения в .Net, не так ли? Я думал, что они всегда были постоянными.
Трэвис
33

Понятие «первоклассный гражданин» или «первоклассный элемент» в языке программирования было введено британским ученым Кристофером Стрейчи в 1960-х годах в контексте первоклассных функций. Наиболее известная формулировка этого принципа, вероятно, содержится в « Структуре и интерпретации компьютерных программ » Джеральда Джея Суссмана и Гарри Абельсона:

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

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

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

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

Например, операторы Java и методы Java имеют сходный вид. Вы можете определять новые методы, вы можете (несколько) свободно выбирать имена своих собственных методов, вы можете переопределять методы, вы можете перегружать методы. Джеймс Гослинг тоже может делать все это с операторами, но мы с тобой не можем. Я имею в виду, вопреки распространенному мнению, Java делает перегрузку оператора поддержки: например, +оператор перегружен byte, short, int, long, float, doubleи String, и IIRC в Java 7 также BigIntegerи BigDecimal(и , возможно, пара я забыл), это просто , что вамне иметь никакого влияния на это. Это явно делает операторов второсортными в соответствии с этим вторым определением. Обратите внимание, что методы по-прежнему не являются первоклассными объектами согласно первому определению. (Делает ли это операторы третьего класса?)

Йорг Миттаг
источник
6

Обычно это относится к конструкции, которая может быть передана в качестве параметра, может быть определена как тип возврата из функции или ей может быть присвоено значение. Обычно вы должны быть в состоянии построить их во время выполнения. Например, экземпляр класса будет гражданином первого класса в c ++ или java, но функция в C не будет.

Pemdas
источник
Что делает класс гражданином первого класса в c ++?
Бьярке Фрейнд-Хансен
2
@bjarkef: Похоже, что на это уже отвечало его соответствие описанию, предложенному в предыдущих предложениях.
двойник
@Jonathan: Да, извините, я неправильно прочитал «построить их во время выполнения». Да, вы можете создать экземпляр класса во время выполнения (объект), но не сам класс. Вот что меня смутило.
Бьярке Фрейнд-Хансен
1
Передача по параметру все еще недостаточно. В C / C ++ я все еще рассматриваю функции как граждан второго сорта. Они могут быть переданы как параметры, возвращены как результаты, размещенные внутри других объектов. Но ими нельзя манипулировать без помощи других конструкций (например, std :: bind необходим для привязки параметров к функции).
Мартин Йорк,
@ Martin Я никогда не говорил, что функции были первоклассными гражданами в C / C ++.
Пемдас
1

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

Пример:

В C / C ++ я не считаю функции гражданином первого класса (другие могут).
Это потому, что есть способы манипулировать функциями, которые напрямую поддерживаются языком, но требуют использования других языковых функций. Привязка параметров к функции напрямую не поддерживается, и вы должны создать функтор для реализации этой функции.

Мартин Йорк
источник
1
Разве это не делает связанные функции (или «замыкания») не первоклассными, в то время как сами функции есть? Как поддержка 0x для замыканий влияет на ваш анализ?
Фред Нурк
@ Фред Нурк: Все зависит от языка. В некоторых языках замыкания являются системами первого класса. В других нет. Я еще недостаточно знаком с C ++ 0x, чтобы сделать явный комментарий.
Мартин Йорк,
Скажем, язык как C или C ++ (но не 0x), как вы ответите. Разве ваше определение «первого класса» не делает связанные функции (или «замыкания») не первоклассными, в то время как сами функции есть?
Фред Нурк
@ Фред Нурк: Если вы ограничиваете, единственное, что вы можете сделать с функцией, это сделать их замыканием, тогда обязательно. Но для меня это все равно, что сказать, что ваша платформа поддерживает добавление целых чисел только путем импорта библиотеки. Тогда целые числа являются гражданами первого класса, но добавление целых чисел не рассматривается. На мой взгляд, замыкание - это операция, которая может быть выполнена для функции, которая эффективно возвращает новую функцию (но это зависит от того, как вы ее определяете). Но закрытие и связывание - это только две операции, сколько других мы исключаем из обсуждения (я не уверен, что это был вопрос).
Мартин Йорк,
@Martin: я не должен объяснять себя ясно. Учитывая, что «функция является гражданином первого класса, если она реализована исключительно языком», функции в C и C ++ реализуются исключительно языком и, таким образом, будут первоклассными. Связанные функции (которые также можно назвать «замыканиями») - это то, о чем вы говорите с параметрами привязки и т. Д., Но это другая функция.
Фред Нурк
-1

Чтобы добавить пример к уже предоставленным ответам:

В WCF / C # вы должны пометить объект класса атрибутом контракта на обслуживание, чтобы он работал как сервис. Нет такой вещи как:

public **service** MyService (in relation public **class** MyClass). 

Класс - это первоклассный гражданин в c #, где нет службы.

Надеюсь это поможет

SYG
источник