Параметр (компьютерное программирование)
В компьютерном программировании параметр для ссылки на или формальный аргумент — это особый вид переменной, используемый в подпрограмме одну из частей данных, предоставляемых в качестве входных данных в подпрограмму. [а] [1] Эти фрагменты данных представляют собой значения [2] [3] [4] аргументов или (часто называемых фактическими аргументами . фактическими параметрами ), с которыми подпрограмма будет вызвана/вызвана Упорядоченный список параметров обычно включается в определение подпрограммы , так что при каждом вызове подпрограммы оцениваются ее аргументы для этого вызова, и результирующие значения могут быть присвоены соответствующим параметрам.
В отличие от аргумента в обычном математическом использовании, аргумент в информатике — это фактическое входное выражение, передаваемое/предоставляемое функции, процедуре или подпрограмме в операторе вызова/вызова, тогда как параметр — это переменная внутри реализации подпрограммы. Например, если определить add
подпрограмма как def add(x, y): return x + y
, затем x, y
являются параметрами, а если это называется add(2, 3)
, затем 2, 3
это аргументы. Переменные (и их выражения) из вызывающего контекста могут быть аргументами: если подпрограмма вызывается как a = 2; b = 3; add(a, b)
тогда переменные a, b
это аргументы, а не ценности 2, 3
. см. в разделе «Параметры и аргументы» Дополнительную информацию .
Семантика того, как могут быть объявлены параметры и как аргументы (значения) передаются параметрам подпрограмм, определяется стратегией оценки языка, а детали того, как это представлено в любой конкретной компьютерной системе, зависят от вызова. соглашение этой системы. В наиболее распространенном случае вызова по значению параметр действует внутри подпрограммы как новая локальная переменная, инициализируемая значением аргумента ( локальная (изолированная) копия аргумента, если аргумент является переменной), но в других случаях , например вызов по ссылке , на переменную аргумента, предоставленную вызывающей стороной, могут влиять действия внутри вызываемой подпрограммы.
Пример
[ редактировать ]Следующая программа на языке программирования C определяет функцию с именем «SalesTax» и имеет один параметр с именем «цена». Тип цены — «двойной» (т.е. число двойной точности с плавающей запятой ). Тип возвращаемого значения функции также является двойным.
double SalesTax(double price)
{
return 0.05 * price;
}
После определения функции ее можно вызвать следующим образом:
SalesTax(10.00);
В этом примере функция была вызвана с аргументом 10.00. Когда это произойдет, цене будет присвоено значение 10,00, и функция начнет рассчитывать свой результат. Шаги для получения результата указаны ниже и заключены в {}. 0.05 * price
указывает, что первое, что нужно сделать, это умножить 0,05 на значение цены, что дает 0,50. return
означает, что функция выдаст результат 0.05 * price
. Таким образом, конечный результат (без учета возможных ошибок округления, с которыми можно столкнуться при представлении десятичных дробей в виде двоичных дробей) равен 0,50.
Параметры и аргументы
[ редактировать ]Термины «параметр» и «аргумент» могут иметь разные значения в разных языках программирования. Иногда они используются как взаимозаменяемые, а для различения значения используется контекст. Термин параметр (иногда называемый формальным параметром ) часто используется для обозначения переменной, указанной в определении функции, тогда как аргумент (иногда называемый фактическим параметром ) относится к фактическому вводу, предоставляемому при вызове функции. Например, если определить функцию как def f(x): ...
, затем x
является параметром, и если он вызывается a = ...; f(a)
затем a
это аргумент. Параметр — это (несвязанная) переменная, а аргумент может быть литералом , переменной или более сложным выражением, включающим литералы и переменные. В случае вызова по значению функции передается значение аргумента, например: f(2)
и a = 2; f(a)
являются эквивалентными вызовами – при вызове по ссылке с переменной в качестве аргумента передается ссылка на эту переменную, даже если синтаксис вызова функции может остаться прежним. [5] Спецификация передачи по ссылке или передачи по значению будет сделана в объявлении и/или определении функции.
Параметры появляются в определениях процедур; аргументы появляются при вызове процедур. В определении функции f(x) = x*x
переменная x является параметром; в вызове функции f(2)
значение 2 является аргументом функции. Грубо говоря, параметр — это тип, а аргумент — это экземпляр.
Параметр — это внутреннее свойство процедуры, включенное в ее определение. Например, во многих языках процедура сложения двух предоставленных целых чисел и вычисления суммы потребует двух параметров, по одному для каждого целого числа. В общем, процедура может быть определена с любым количеством параметров или вообще без параметров. Если процедура имеет параметры, часть ее определения, в которой указаны параметры, называется списком параметров .
Напротив, аргументами являются выражения [6] передается процедуре при ее вызове, обычно это одно выражение, соответствующее одному из параметров. В отличие от параметров, которые составляют неизменную часть определения процедуры, аргументы могут меняться от вызова к вызову. Каждый раз при вызове процедуры часть вызова процедуры, определяющая аргументы, называется списком аргументов .
Хотя параметры также часто называют аргументами, иногда под аргументами понимают фактические значения или ссылки, присвоенные переменным параметра при вызове подпрограммы во время выполнения . При обсуждении кода, вызывающего подпрограмму, любые значения или ссылки, передаваемые в подпрограмму, являются аргументами, а место в коде, где передаются эти значения или ссылки, — это список параметров . При обсуждении кода внутри определения подпрограммы переменные в списке параметров подпрограммы являются параметрами, а значения параметров во время выполнения — аргументами. Например, в C при работе с потоками принято передавать аргумент типа void* и приводить его к ожидаемому типу:
void ThreadFunction(void* pThreadArgument)
{
// Naming the first parameter 'pThreadArgument' is correct, rather than
// 'pThreadParameter'. At run time the value we use is an argument. As
// mentioned above, reserve the term parameter for when discussing
// subroutine definitions.
}
Чтобы лучше понять разницу, рассмотрим следующую функцию, написанную на C :
int Sum(int addend1, int addend2)
{
return addend1 + addend2;
}
Функция Sum имеет два параметра с именами addend1 и addend2 . Она добавляет значения, переданные в параметры, и возвращает результат вызывающей стороне подпрограммы (используя метод, автоматически предоставляемый компилятором C).
Код, вызывающий функцию Sum , может выглядеть так:
int value1 = 40;
int value2 = 2;
int sum_value = Sum(value1, value2);
Переменные value1 и value2 инициализируются значениями. значение1 и значение2 являются аргументами функции суммы в этом контексте.
Во время выполнения значения, присвоенные этим переменным, передаются функции Sum в качестве аргументов. В функции Sum вычисляются параметры addend1 и addend2 , в результате чего получаются аргументы 40 и 2 соответственно. Значения аргументов суммируются, а результат возвращается вызывающей стороне, где он присваивается переменной sum_value .
Из-за разницы между параметрами и аргументами в процедуру можно передать неподходящие аргументы. Вызов может предоставить слишком много или слишком мало аргументов; один или несколько аргументов могут быть неправильного типа; или аргументы могут быть предоставлены в неправильном порядке. Любая из этих ситуаций приводит к несоответствию между списками параметров и аргументов, и процедура часто возвращает непреднамеренный ответ или генерирует ошибку времени выполнения .
Альтернативная конвенция на Эйфеле
[ редактировать ]В методе и языке разработки программного обеспечения Eiffel термины «аргумент» и «параметр» имеют разное использование, установленное соглашением. Термин «аргумент» используется исключительно в отношении входных данных подпрограммы. [7] а термин параметр используется исключительно при параметризации типа для универсальных классов . [8]
Рассмотрим следующее стандартное определение:
sum (addend1: INTEGER; addend2: INTEGER): INTEGER
do
Result := addend1 + addend2
end
рутина sum
принимает два аргумента addend1
и addend2
подпрограммы , которые называются формальными аргументами . Звонок в sum
указывает фактические аргументы , как показано ниже с помощью value1
и value2
.
sum_value: INTEGER
value1: INTEGER = 40
value2: INTEGER = 2
…
sum_value := sum (value1, value2)
Параметры также считаются либо формальными , либо фактическими . Формальные универсальные параметры используются при определении универсальных классов. В примере ниже класс HASH_TABLE
объявляется как универсальный класс с двумя формальными универсальными параметрами: G
представление данных, представляющих интерес, и K
представляющий хеш-ключ для данных:
class HASH_TABLE [G, K -> HASHABLE]
…
Когда класс становится клиентом HASH_TABLE
формальные универсальные параметры заменяются фактическими универсальными параметрами при обобщенном выводе . В следующем объявлении атрибута my_dictionary
должен использоваться как словарь на основе символьной строки . Таким образом, и данные, и ключевые формальные универсальные параметры заменяются фактическими универсальными параметрами типа STRING
.
my_dictionary: HASH_TABLE [STRING, STRING]
Типы данных
[ редактировать ]В строго типизированных языках программирования каждого параметра тип должен быть указан в объявлении процедуры. Языки, использующие вывод типов, пытаются автоматически обнаружить типы на основе тела функции и ее использования. Динамически типизированные языки программирования откладывают разрешение типов до времени выполнения. Слабо типизированные языки практически не выполняют разрешение типов, вместо этого полагаясь на правильность программиста.
В некоторых языках используется специальное ключевое слово (например, void ), чтобы указать, что у подпрограммы нет параметров; в формальной теории типов такие функции принимают пустой список параметров (тип которого не void , а unit ).
Передача аргумента
[ редактировать ]Точный механизм назначения аргументов параметрам, называемый передачей аргументов , зависит от стратегии оценки, используемой для этого параметра (обычно вызов по значению ), которая может быть указана с помощью ключевых слов.
Аргументы по умолчанию
[ редактировать ]Некоторые языки программирования, такие как Ada , C++ , Clojure , [ нужна ссылка ] Общий Лисп , [9] Фортран 90 , [10] Python , Ruby , Tcl и Windows PowerShell. [ нужна ссылка ] разрешить явно или неявно указывать аргумент по умолчанию в объявлении подпрограммы. Это позволяет вызывающей стороне опустить этот аргумент при вызове подпрограммы. Если аргумент по умолчанию указан явно, то это значение используется, если оно не предоставлено вызывающей стороной. Если аргумент по умолчанию является неявным (иногда с использованием ключевого слова, такого как «Optional» ), тогда язык предоставляет общеизвестное значение (например, null , Empty , ноль, пустую строку и т. д.), если значение не предоставлено вызывающей стороной. .
Пример PowerShell:
function doc($g = 1.21) {
"$g gigawatts? $g gigawatts? Great Scott!"
}
PS > doc
1.21 gigawatts? 1.21 gigawatts? Great Scott!
PS > doc 88
88 gigawatts? 88 gigawatts? Great Scott!
Аргументы по умолчанию можно рассматривать как особый случай списка аргументов переменной длины.
Списки параметров переменной длины
[ редактировать ]Некоторые языки позволяют определять подпрограммы, принимающие переменное количество аргументов . Для таких языков подпрограммы должны перебирать список аргументов.
Пример PowerShell:
function marty {
$args | foreach { "back to the year $_" }
}
PS > marty 1985
back to the year 1985
PS > marty 2015 1985 1955
back to the year 2015
back to the year 1985
back to the year 1955
Именованные параметры
[ редактировать ]Некоторые языки программирования, такие как Ada и Windows PowerShell, позволяют подпрограммам иметь именованные параметры . Это позволяет вызывающему коду быть более самодокументируемым . Это также обеспечивает большую гибкость для вызывающей стороны, часто позволяя изменять порядок аргументов или опускать аргументы при необходимости.
Пример PowerShell:
function jennifer($adjectiveYoung, $adjectiveOld) {
"Young Jennifer: I'm $adjectiveYoung!"
"Old Jennifer: I'm $adjectiveOld!"
}
PS > jennifer 'fresh' 'experienced'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!
PS > jennifer -adjectiveOld 'experienced' -adjectiveYoung 'fresh'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!
Несколько параметров в функциональных языках
[ редактировать ]В лямбда-исчислении каждая функция имеет ровно один параметр. То, что считается функцией с несколькими параметрами, обычно представляется в лямбда-исчислении как функция, которая принимает первый аргумент и возвращает функцию, которая принимает остальные аргументы; это преобразование известно как каррирование . Некоторые языки программирования, такие как ML и Haskell , следуют этой схеме. В этих языках каждая функция имеет ровно один параметр, и то, что может выглядеть как определение функции с несколькими параметрами, на самом деле является синтаксическим сахаром для определения функции, возвращающей функцию и т. д. Применение функций левоассоциативно . в этих языках языках, а также в лямбда-исчислении, поэтому то, что выглядит как применение функции к нескольким аргументам, правильно оценивается как функция, примененная к первому аргументу, затем результирующая функция, примененная ко второму аргументу и т. д.
Выходные параметры
[ редактировать ]Выходной параметр , также известный как выходной параметр или возвращаемый параметр , — это параметр, используемый для вывода, а не для более обычного ввода. Использование параметров вызова по ссылке или параметров вызова по значению, где значением является ссылка, поскольку выходные параметры являются идиомой в некоторых языках, особенно C и C++, [б] в то время как другие языки имеют встроенную поддержку выходных параметров. Языки со встроенной поддержкой выходных параметров включают Ada. [11] (см. подпрограммы Ada ), Fortran (начиная с Fortran 90 ; см. «намерение» Fortran ), различные процедурные расширения SQL , такие как PL/SQL (см. Функции PL/SQL ). [12] и Transact-SQL , C# [13] и .NET Framework , [14] Быстрый , [15] и язык сценариев TScript (см. объявления функций TScript ).
Точнее, можно выделить три типа параметров или режимов параметров : входной параметр s , выходные параметры и входной/выходной параметр s; их часто обозначают in
, out
, и in out
или inout
. Входной аргумент (аргумент входного параметра) должен быть значением, например инициализированной переменной или литералом, и не должен переопределяться или присваиваться; выходной аргумент должен быть назначаемой переменной, но его не нужно инициализировать, любое существующее значение недоступно, и ему должно быть присвоено значение; а аргумент ввода/вывода должен быть инициализированной назначаемой переменной, которой при необходимости может быть присвоено значение. Точные требования и порядок применения различаются в зависимости от языка — например, в Ada 83 выходные параметры могут быть только назначены, но не прочитаны, даже после присвоения (это было удалено в Ada 95, чтобы устранить необходимость во вспомогательной переменной-аккумуляторе). Это аналогично понятию, что значение в выражении представляет собой r-значение (имеет значение), l-значение (может быть присвоено) или r-значение/l-значение (имеет значение и может быть присвоено). ), соответственно, хотя эти термины имеют специализированное значение в C.
В некоторых случаях различаются только ввод и ввод/вывод, причем вывод считается конкретным использованием ввода/вывода, а в других случаях поддерживаются только ввод и вывод (но не ввод/вывод). Режим по умолчанию варьируется в зависимости от языка: в Fortran 90 ввод/вывод является значением по умолчанию, в то время как в C# и расширениях SQL ввод является значением по умолчанию, а в TScript каждый параметр явно указывается как ввод или вывод.
Синтаксически режим параметра обычно обозначается ключевым словом в объявлении функции, например: void f(out int x)
в С#. Обычно выходные параметры часто помещают в конце списка параметров, чтобы их можно было четко различать, хотя это не всегда соблюдается. TScript использует другой подход, где в объявлении функции перечислены входные параметры, затем выходные параметры, разделенные двоеточием (:), и нет типа возвращаемого значения самой функции, как в этой функции, которая вычисляет размер текста. фрагмент:
TextExtent(WString text, Font font : Integer width, Integer height)
Режимы параметров — это форма денотационной семантики , определяющая намерения программиста и позволяющая компиляторам выявлять ошибки и применять оптимизации — они не обязательно подразумевают операционную семантику (как на самом деле происходит передача параметров). Примечательно, что хотя входные параметры могут быть реализованы вызовом по значению, а выходные и входные/выходные параметры вызовом по ссылке – и это простой способ реализовать эти режимы в языках без встроенной поддержки – это не всегда так. реализовано. Это различие подробно обсуждается в Ada '83 Rationale, где подчеркивается, что режим параметров абстрагируется от того, какой механизм передачи параметров (по ссылке или путем копирования) фактически реализован. [11] Например, в то время как в C# входные параметры (по умолчанию, без ключевого слова) передаются по значению, а выходные параметры и параметры ввода/вывода ( out
и ref
) передаются по ссылке во входных параметрах PL/SQL ( IN
) передаются по ссылке, а выходные и входные/выходные параметры ( OUT
и IN OUT
) по умолчанию передаются по значению, а результат копируется обратно, но их можно передать по ссылке с помощью метода NOCOPY
подсказка компилятора. [16]
Синтаксически аналогичная конструкция выходных параметров заключается в присвоении возвращаемого значения переменной с тем же именем, что и у функции. Это можно найти в Паскале , Фортране 66 и Фортране 77 , как в этом примере Паскаля:
function f(x, y: integer): integer;
begin
f := x + y;
end;
Это семантически отличается тем, что при вызове функция просто оценивается – ей не передается переменная из вызывающей области для хранения выходных данных.
Использовать
[ редактировать ]Основное использование выходных параметров — это возврат нескольких значений из функции, а использование входных/выходных параметров — изменение состояния с помощью передачи параметров (а не через общую среду, как в глобальных переменных). Важным применением возврата нескольких значений является решение полупредикатной проблемы возврата как значения, так и статуса ошибки – см. Проблема полупредиката: многозначный возврат .
Например, чтобы вернуть две переменные из функции в C, можно написать:
int width
int height;
F(x, &width, &height);
где x
является входным параметром и width
и height
являются выходными параметрами.
Распространенным вариантом использования в C и родственных языках является обработка исключений , когда функция помещает возвращаемое значение в выходную переменную и возвращает логическое значение, соответствующее успешному выполнению функции или нет. Архетипическим примером является TryParse
метод в .NET, особенно в C#, который анализирует строку в целое число и возвращает true
об успехе и false
при неудаче. Это имеет следующую подпись: [17]
public static bool TryParse(string s, out int result)
и может использоваться следующим образом:
int result;
if (!Int32.TryParse(s, result)) {
// exception handling
}
Аналогичные соображения применимы к возврату значения одного из нескольких возможных типов, где возвращаемое значение может указывать тип, а затем значение сохраняется в одной из нескольких выходных переменных.
Недостатки
[ редактировать ]Выходные параметры часто не одобряются в современном программировании, по существу, как неуклюжие, запутанные и слишком низкоуровневые — обычные возвращаемые значения значительно легче понять и с ними работать. [18] Примечательно, что выходные параметры включают функции с побочными эффектами (изменение выходного параметра) и семантически похожи на ссылки, которые более запутанны, чем чистые функции и значения, а различие между выходными параметрами и параметрами ввода/вывода может быть тонким. Кроме того, поскольку в обычных стилях программирования большинство параметров являются просто входными параметрами, выходные параметры и параметры ввода/вывода необычны и, следовательно, могут быть неправильно поняты.
Выходные и входные/выходные параметры предотвращают композицию функций , поскольку выходные данные сохраняются в переменных, а не в значении выражения. Таким образом, сначала необходимо объявить переменную, а затем каждый шаг цепочки функций должен быть отдельным оператором. Например, в C++ следующая композиция функций:
Object obj = G(y, F(x));
при записи с выходными и входными/выходными параметрами вместо этого становится (для F
это выходной параметр, т.к. G
входной/выходной параметр):
Object obj;
F(x, &obj);
G(y, &obj);
В частном случае функции с одним выходным или входным/выходным параметром и без возвращаемого значения, композиция функции возможна, если выходной или входной/выходной параметр (или в C/C++ его адрес) также возвращается функцией. в этом случае приведенное выше становится:
Object obj;
G(y, F(x, &obj));
Альтернативы
[ редактировать ]Существуют различные альтернативы вариантам использования выходных параметров.
Альтернативой возврату нескольких значений из функции является возврат кортежа . автоматическую распаковку последовательностей и параллельное присваивание Синтаксически это будет более понятно, если можно использовать , как в Go или Python, например:
def f():
return 1, 2
a, b = f()
Вместо этого для возврата значения одного из нескольких типов тегированное объединение можно использовать ; наиболее распространенными случаями являются типы, допускающие значение NULL ( типы опций ), где возвращаемое значение может быть нулевым, что указывает на сбой. Для обработки исключений можно вернуть тип, допускающий значение NULL, или вызвать исключение. Например, в Python можно использовать либо:
result = parse(s)
if result is None:
# exception handling
или, более идиоматично:
try:
result = parse(s)
except ParseError:
# exception handling
Микрооптимизация отсутствия требования к локальной переменной и копирования возвращаемого значения при использовании выходных переменных также может быть применена к обычным функциям и возвращаемым значениям достаточно сложными компиляторами.
Обычная альтернатива выходным параметрам в C и родственных языках — возврат единой структуры данных, содержащей все возвращаемые значения. [13] Например, учитывая структуру, инкапсулирующую ширину и высоту, можно написать:
WidthHeight width_and_height = F(x);
В объектно-ориентированных языках вместо использования параметров ввода/вывода часто можно использовать вызов путем совместного использования , передачи ссылки на объект и последующего изменения объекта, но без изменения того, на какой объект ссылается переменная. [18]
См. также
[ редактировать ]- Аргумент командной строки
- Стратегия оценки
- Перегрузка оператора
- Свободные переменные и связанные переменные
Примечания
[ редактировать ]- ^ В этой статье термин «подпрограмма» относится к любой конструкции, похожей на подпрограмму, которая имеет разные имена и немного разные значения в зависимости от языка программирования . обсуждаемого
- ^ C и C++ вызываются по значению, но если тип является ссылкой (указатель C/C++ или ссылка C++), то установка значения ссылки может использоваться для создания поведения стиля вызова по ссылке.
Ссылки
[ редактировать ]- ^ «Передача информации в метод или конструктор (Изучение языка Java > Классы и объекты)» . Учебные пособия по Java™ . Проверено 9 сентября 2021 г.
Параметры относятся к списку переменных в объявлении метода. Аргументы — это фактические значения, которые передаются при вызове метода. Когда вы вызываете метод, используемые аргументы должны соответствовать параметрам объявления по типу и порядку.
- ^ Прата, Стивен (2004). C Primer Plus (5-е изд.). Сэмс. стр. 276–277. ISBN 978-0-672-32696-7 .
- ^ «Рабочий проект стандарта языка программирования C++» (PDF) . Открытые стандарты . 19 октября 2005 г. Архивировано из оригинала (PDF) 14 декабря 2005 г. Проверено 1 января 2018 г.
- ^ Гордон, Аарон. «Подпрограммы и передача параметров» . rowdysites.msudenver.edu/~gordona . Архивировано из оригинала 1 января 2018 года . Проверено 1 января 2018 г. [ мертвая ссылка ]
- ^ Доллард, Кэтлин. «Передача аргументов по значению и по ссылке (Visual Basic)» . Microsoft Learn . Проверено 27 октября 2018 г.
- ^ «Учебник по программированию GNU C» . crasseux.com . Проверено 27 октября 2018 г.
- ^ Мейер, Бертран. Объектно-ориентированное создание программного обеспечения , 2-е издание, Prentice Hall, 1997, стр. 444.
- ^ Мейер, с. 96.
- ^ «Функции» . gigamonkeys.com . Проверено 02 июня 2021 г.
- ^ «необязательные аргументы» . www.netlib.org . Проверено 02 июня 2021 г.
- ^ Перейти обратно: а б 8.2 Режимы параметров , « Обоснование разработки языка программирования Ada® »
- ^ 8. Подпрограммы PL/SQL: указание режимов параметров подпрограммы
- ^ Перейти обратно: а б Питер Халлам. «Почему в C# есть и «ref», и «out»?» . Архивировано из оригинала 26 сентября 2011 г.
- ^ Перечисление ПараметрНаправления
- ^ Функции — язык программирования Swift (Swift 4.2)
- ^ 8. Подпрограммы PL/SQL: передача больших структур данных с помощью подсказки компилятора NOCOPY.
- ^ Метод Int32.TryParse (String, Int32)
- ^ Перейти обратно: а б CA1021: Избегайте выходных параметров