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» и имеет один параметр с именем «цена». Тип цены — «двойной» (т.е. число двойной точности с плавающей запятой ). Тип возвращаемого значения функции также является двойным.

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

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

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

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

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

целое значение1 = 40 ; целое значение2 = 2 ; int sum_value = Сумма ( значение1 , значение2 );          

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

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

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

Альтернативная конвенция на Эйфеле

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

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

 сумма ( addend1 : INTEGER ; addend2 : INTEGER ): INTEGER do Result := addend1 + addend2 end            

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

 sum_value : ЦЕЛОЕ значение1 : ЦЕЛОЕ = 40 значение2 : ЦЕЛОЕ = 2 sum_value := сумма ( значение1 , значение2 )               

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

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

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

 мой_словарь : HASH_TABLE [ STRING , STRING ]   

Типы данных

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

В некоторых языках используется специальное ключевое слово (например, 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 > док 1,21 гигаватт? 1,21 гигаватт? Отличный Скотт!PS > док  88 88 гигаватт? 88 гигаватт? Отличный Скотт!

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

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

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

Пример PowerShell:

функция  Марти  {  $args  |  foreach  {  "назад в год $_"  } }
PS > Март  1985 года вернулся в 1985 годPS > Марти  2015  1985  1955 назад в 2015 год назад в 1985 год назад в 1955 год

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

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

Пример PowerShell:

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

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

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

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

Выходной параметр , также известный как выходной параметр или возвращаемый параметр , — это параметр, используемый для вывода, а не для более обычного ввода. Использование параметров вызова по ссылке или параметров вызова по значению, где значением является ссылка, поскольку выходные параметры являются идиомой в некоторых языках, особенно C и C++, [b] , в то время как другие языки имеют встроенную поддержку выходных параметров. Языки со встроенной поддержкой выходных параметров включают Ada [11] (см. Подпрограммы Ada), Fortran (начиная с Fortran 90 ; см. «Намерение» Fortran), различные процедурные расширения 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 , шрифт шрифта : целочисленная ширина , целочисленная высота )        

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

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

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

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

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

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

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

int ширина int высота ;  F ( х , ширина и высота ) ; _  

где x– входной параметр, и widthheightвыходные параметры.

Распространенным вариантом использования в C и родственных языках является обработка исключений , когда функция помещает возвращаемое значение в выходную переменную и возвращает логическое значение, соответствующее успешному выполнению функции или нет. Типичным примером является TryParseметод в .NET, особенно в C#, который преобразует строку в целое число и возвращает результат trueв случае успеха или falseнеудачи. Это имеет следующую подпись: [17]

public static bool TryParse ( строка s , результат int ) _       

и может использоваться следующим образом:

int результат ; if ( ! Int32 . TryParse ( s , result )) { // обработка исключений }     

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

Недостатки

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

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

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

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

Объект объект ; F ( х и объект ) ; G ( у , & объект );   

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

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

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

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

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

def  f ():  вернуть  1 ,  2 a ,  b  =  f ()

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

result  =  parse ( s ) , если  результат  равен  None :  # обработка исключений

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

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

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

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

WidthHeight width_and_height = F ( x );   

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

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

Примечания

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

Рекомендации

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