stringtranslate.com

Параметр (компьютерное программирование)

В компьютерном программировании параметр или формальный аргумент — это особый вид переменной, используемый в подпрограмме для ссылки на один из фрагментов данных, предоставленных в качестве входных данных для подпрограммы. [a] [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" и одним параметром с именем "price". Тип цены - "double" (т.е. число с плавающей точкой двойной точности ). Тип возвращаемого значения функции - также double.

двойной налог с продаж ( двойная цена ) { вернуть 0,05 * цена ; }      

После определения функции ее можно вызвать следующим образом:

Налог с продаж ( 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 ) { // Наименование первого параметра 'pThreadArgument' является правильным, а не 'pThreadParameter'. Во время выполнения используемое нами значение является аргументом. Как // упоминалось выше, зарезервируйте термин параметр для обсуждения определений подпрограмм. }      

Чтобы лучше понять разницу, рассмотрим следующую функцию, написанную на языке C :

int Sum ( int addend1 , int addend2 ) { return addend1 + addend2 ; }        

Функция Sum имеет два параметра, называемые addend1 и addend2 . Она складывает значения, переданные в параметры, и возвращает результат вызывающей подпрограмме (используя технику, автоматически предоставляемую компилятором C).

Код, вызывающий функцию Sum , может выглядеть так:

int значение1 = 40 ; int значение2 = 2 ; int сумма_значения = Сумма ( значение1 , значение2 );          

Переменные value1 и value2 инициализируются значениями. В этом контексте value1 и value2 являются аргументами функции суммы .

Во время выполнения значения, присвоенные этим переменным, передаются в функцию Sum в качестве аргументов. В функции Sum параметры addend1 и addend2 оцениваются, что дает аргументы 40 и 2 соответственно. Значения аргументов складываются, а результат возвращается вызывающей стороне, где он присваивается переменной sum_value .

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

Альтернативный съезд в Эйфеле

В рамках метода и языка разработки программного обеспечения Eiffel термины аргумент и параметр имеют различные применения, установленные соглашением. Термин аргумент используется исключительно в отношении входных данных подпрограммы, [7] а термин параметр используется исключительно в параметризации типов для универсальных классов . [8]

Рассмотрим следующее общепринятое определение:

 сумма ( сложение1 : ЦЕЛОЕ ЧИСЛО ; сложение2 : ЦЕЛОЕ ЧИСЛО ): ЦЕЛОЕ ЧИСЛО do Результат := сложение1 + сложение2 конец            

Процедура sumпринимает два аргумента addend1и , которые называются формальными аргументамиaddend2 процедуры . Вызов определяет фактические аргументы , как показано ниже с помощью и .sumvalue1value2

 значение_суммы : ЦЕЛОЕ ЧИСЛО значение1 : ЦЕЛОЕ ЧИСЛО = 40 значение2 : ЦЕЛОЕ ЧИСЛО = 2 значение_суммы := сумма ( значение1 , значение2 )               

Параметры также рассматриваются как формальные или фактические . Формальные общие параметры используются в определении общих классов. В примере ниже класс HASH_TABLE объявлен как общий класс, который имеет два формальных общих параметра, Gпредставляющих интересующие данные и Kпредставляющих хэш-ключ для данных:

класс HASH_TABLE [ G , K -> HASHABLE ]        

Когда класс становится клиентом для HASH_TABLE, формальные общие параметры заменяются фактическими общими параметрами в общем выводе . В следующем объявлении атрибута my_dictionaryдолжно использоваться как словарь на основе символьной строки . Таким образом, как данные, так и ключевые формальные общие параметры заменяются фактическими общими параметрами типа STRING.

 my_dictionary : HASH_TABLE [ СТРОКА , СТРОКА ]   

Типы данных

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

В некоторых языках используется специальное ключевое слово (например, void ), чтобы указать, что подпрограмма не имеет параметров; в формальной теории типов такие функции принимают пустой список параметров (тип которого не void , а unit ).

Аргумент передается

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

Аргументы по умолчанию

Некоторые языки программирования, такие как Ada , C++ , Clojure , [ требуется ссылка ] Common Lisp , [9] Fortran 90 , [10] Python , Ruby , Tcl и Windows PowerShell [ требуется ссылка ] позволяют явно или неявно указывать аргумент по умолчанию в объявлении подпрограммы. Это позволяет вызывающему объекту опустить этот аргумент при вызове подпрограммы. Если аргумент по умолчанию указан явно, то это значение используется, если оно не предоставлено вызывающим объектом. Если аргумент по умолчанию неявный (иногда с использованием ключевого слова, такого как Optional ), то язык предоставляет известное значение (такое как null , Empty , ноль, пустая строка и т. д.), если значение не предоставлено вызывающим объектом.

Пример PowerShell:

function  doc ( $g  =  1 . 21 )  {  "$g гигаватт? $g гигаватт? Отлично, Скотт!" }
PS > doc 1,21 гигаватт? 1,21 гигаватт? Отлично, Скотт!PS > doc  88 88 гигаватт? 88 гигаватт? Отлично, Скотт!

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

Списки параметров переменной длины

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

Пример PowerShell:

function  marty  {  $args  |  foreach  {  "назад к году $_"  } }
PS > Марти  1985 назад в 1985 годPS > Марти  2015  1985  1955 назад в 2015 год назад в 1985 год назад в 1955 год

Именованные параметры

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

Пример PowerShell:

function  jennifer ( $adjectiveYoung ,  $adjectiveOld )  {  "Молодая Дженнифер: Я $adjectiveYoung!"  "Старая Дженнифер: Я $adjectiveOld!" }
PS > jennifer  'fresh'  'experienced' Молодая Дженнифер: Я свежая! Старая Дженнифер: Я опытная!PS > jennifer  - прилагательноеOld  'опытный'  - прилагательноеYoung  'свежий' Молодая Дженнифер: Я свежая! Старая Дженнифер: Я опытная!

Множественные параметры в функциональных языках

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

Выходные параметры

Выходной параметр , также известный как выходной параметр или возвращаемый параметр , является параметром, используемым для вывода, а не более обычным использованием для ввода. Использование параметров вызова по ссылке или параметров вызова по значению, где значение является ссылкой, в качестве выходных параметров является идиомой в некоторых языках, в частности C и C++, [b], в то время как другие языки имеют встроенную поддержку выходных параметров. Языки со встроенной поддержкой выходных параметров включают Ada [11] (см. подпрограммы Ada), Fortran (начиная с Fortran 90 ; см. Fortran "intent"), различные процедурные расширения SQL , такие как PL/SQL (см. функции PL/SQL ) [12] и Transact-SQL , C# [13] и .NET Framework , [14] Swift , [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)в C#. Обычно выходные параметры часто помещаются в конец списка параметров, чтобы их было четко различать, хотя это не всегда соблюдается. TScript использует другой подход, где в объявлении функции перечисляются входные параметры, затем выходные параметры, разделенные двоеточием (:), и нет возвращаемого типа для самой функции, как в этой функции, которая вычисляет размер текстового фрагмента:

TextExtent ( WString текст , Font шрифт : целочисленная ширина , целочисленная высота )        

Режимы параметров являются формой денотационной семантики , определяющей намерение программиста и позволяющей компиляторам отлавливать ошибки и применять оптимизации – они не обязательно подразумевают операционную семантику (как на самом деле происходит передача параметров). Примечательно, что в то время как входные параметры могут быть реализованы вызовом по значению, а выходные и входные/выходные параметры – вызовом по ссылке – и это простой способ реализации этих режимов в языках без встроенной поддержки – это не всегда так, как они реализуются. Это различие подробно обсуждается в Ada '83 Rationale, где подчеркивается, что режим параметров абстрагируется от того, какой механизм передачи параметров (по ссылке или копией) фактически реализован. [11] Например, в то время как в C# входные параметры (по умолчанию, без ключевого слова) передаются по значению, а выходные и входные/выходные параметры ( outи ref) передаются по ссылке, в PL/SQL входные параметры ( IN) передаются по ссылке, а выходные и входные/выходные параметры ( OUTи IN OUT) по умолчанию передаются по значению, а результат копируется обратно, но могут быть переданы по ссылке с помощью NOCOPYподсказки компилятора. [16]

Синтаксически схожая конструкция для выходных параметров — присваивание возвращаемого значения переменной с тем же именем, что и у функции. Это встречается в Pascal , Fortran 66 и Fortran 77 , как в этом примере на Pascal:

функция f ( x , y : целое число ) : целое число ; начало f := x + y ; конец ;         

Семантическое отличие заключается в том, что при вызове функция просто вычисляется — ей не передается переменная из вызывающей области действия для сохранения выходных данных.

Использовать

Основное использование выходных параметров — возврат нескольких значений из функции, тогда как использование входных/выходных параметров — изменение состояния с помощью передачи параметров (а не общей среды, как в глобальных переменных). Важное использование возврата нескольких значений — решение полупредикатной проблемы возврата как значения, так и статуса ошибки — см. Полупредикатная проблема: Многозначный возврат .

Например, чтобы вернуть две переменные из функции в C, можно написать:

целая ширина целая высота ;  F ( x , & ширина , & высота );  

где 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 )) { // обработка исключений }     

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

Недостатки

Выходные параметры часто не приветствуются в современном программировании, по сути, как неудобные, запутанные и слишком низкоуровневые — обычные возвращаемые значения значительно проще понять и с ними легче работать. [18] Примечательно, что выходные параметры включают функции с побочными эффектами (изменение выходного параметра) и семантически похожи на ссылки, которые более запутанны, чем чистые функции и значения, а различие между выходными параметрами и параметрами ввода/вывода может быть тонким. Кроме того, поскольку в обычных стилях программирования большинство параметров являются просто входными параметрами, выходные параметры и параметры ввода/вывода необычны и, следовательно, подвержены неправильному пониманию.

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

Объект obj = G ( y , F ( x ));    

при записи с выходными и входными/выходными параметрами вместо этого становится (так как Fэто выходной параметр, для Gвходного/выходного параметра):

Объект obj ; F ( x , & obj ); G ( y , & obj );   

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

Объект obj ; G ( y , F ( x , & obj ));   

Альтернативы

Существуют различные альтернативы вариантам использования выходных параметров.

Для возврата нескольких значений из функции альтернативой является возврат кортежа . Синтаксически это будет понятнее, если можно использовать автоматическую распаковку последовательности и параллельное присваивание , как в Go или Python, например:

def  f ():  возврат  1 ,  2 a ,  b  =  f ()

Для возврата значения одного из нескольких типов вместо этого можно использовать помеченное объединение ; наиболее распространенными случаями являются типы, допускающие значение null ( типы опций ), где возвращаемое значение может быть null, чтобы указать на ошибку. Для обработки исключений можно вернуть тип, допускающий значение null, или вызвать исключение. Например, в Python можно использовать либо:

result  =  parse ( s ) if  result  is  None :  # обработка исключений

или, более идиоматично:

try :  result  =  parse ( s ) except  ParseError :  # обработка исключений

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

Обычной альтернативой выходным параметрам в C и родственных языках является возврат единой структуры данных, содержащей все возвращаемые значения. [13] Например, если задана структура, инкапсулирующая ширину и высоту, можно написать:

ШиринаВысота ширина_и_высота = F ( x );   

В объектно-ориентированных языках вместо использования входных/выходных параметров часто можно использовать вызов путем совместного использования , передавая ссылку на объект, а затем изменяя объект, не меняя при этом, на какой объект ссылается переменная. [18]

Смотрите также

Примечания

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

Ссылки

  1. ^ "Передача информации в метод или конструктор (Изучение языка Java > Классы и объекты)". Учебники Java™ . Получено 2021-09-09 . Параметры относятся к списку переменных в объявлении метода. Аргументы — это фактические значения, которые передаются при вызове метода. Когда вы вызываете метод, используемые аргументы должны соответствовать параметрам объявления по типу и порядку.
  2. ^ Прата, Стивен (2004). C Primer Plus (5-е изд.). Сэмс. стр. 276–277. ISBN 978-0-672-32696-7.
  3. ^ "Рабочий проект, стандарт языка программирования C++" (PDF) . Открытые стандарты . 2005-10-19. Архивировано из оригинала (PDF) 14 декабря 2005 г. . Получено 1 января 2018 г. .
  4. ^ Гордон, Аарон. «Подпрограммы и передача параметров». rowdysites.msudenver.edu/~gordona . Архивировано из оригинала 1 января 2018 года . Получено 1 января 2018 года .[ мертвая ссылка ]
  5. ^ Доллард, Кэтлин. «Передача аргументов по значению и по ссылке (Visual Basic)». Microsoft Learn . Получено 27.10.2018 .
  6. ^ "Учебник программирования GNU C". crasseux.com . Получено 2018-10-27 .
  7. ^ Мейер, Бертран. Объектно-ориентированное построение программного обеспечения , 2-е издание, Prentice Hall, 1997, стр. 444.
  8. Мейер, стр. 96.
  9. ^ "Функции". gigamonkeys.com . Получено 2021-06-02 .
  10. ^ "необязательные аргументы". www.netlib.org . Получено 2021-06-02 .
  11. ^ ab 8.2 Режимы параметров, «Обоснование дизайна языка программирования Ada®»
  12. ^ 8. Подпрограммы PL/SQL: указание режимов параметров подпрограммы
  13. ^ ab Питер Халлам. "Почему в C# есть и 'ref', и 'out'?". Архивировано из оригинала 2011-09-26.
  14. ^ Перечисление ParameterDirection
  15. ^ Функции — Язык программирования Swift (Swift 4.2)
  16. ^ 8. Подпрограммы PL/SQL: передача больших структур данных с помощью подсказки компилятора NOCOPY
  17. ^ Int32. Метод TryParse (Строка, Int32)
  18. ^ ab CA1021: Избегайте выходных параметров