~~~~~~~~~~~~~~~~~~~~ Arc.Ask3.Ru ~~~~~~~~~~~~~~~~~~~~~ 
Номер скриншота №:
✰ 5F8BF523A6D15E8104455168CBA68FB4__1712597340 ✰
Заголовок документа оригинал.:
✰ Evaluation strategy - Wikipedia ✰
Заголовок документа перевод.:
✰ Стратегия оценки — Википедия ✰
Снимок документа находящегося по адресу (URL):
✰ https://en.wikipedia.org/wiki/Eager_evaluation ✰
Адрес хранения снимка оригинал (URL):
✰ https://arc.ask3.ru/arc/aa/5f/b4/5f8bf523a6d15e8104455168cba68fb4.html ✰
Адрес хранения снимка перевод (URL):
✰ https://arc.ask3.ru/arc/aa/5f/b4/5f8bf523a6d15e8104455168cba68fb4__translat.html ✰
Дата и время сохранения документа:
✰ 16.06.2024 10:01:14 (GMT+3, MSK) ✰
Дата и время изменения документа (по данным источника):
✰ 8 April 2024, at 20:29 (UTC). ✰ 

~~~~~~~~~~~~~~~~~~~~~~ Ask3.Ru ~~~~~~~~~~~~~~~~~~~~~~ 
Сервисы Ask3.ru: 
 Архив документов (Снимки документов, в формате HTML, PDF, PNG - подписанные ЭЦП, доказывающие существование документа в момент подписи. Перевод сохраненных документов на русский язык.)https://arc.ask3.ruОтветы на вопросы (Сервис ответов на вопросы, в основном, научной направленности)https://ask3.ru/answer2questionТоварный сопоставитель (Сервис сравнения и выбора товаров) ✰✰
✰ https://ask3.ru/product2collationПартнерыhttps://comrades.ask3.ru


Совет. Чтобы искать на странице, нажмите Ctrl+F или ⌘-F (для MacOS) и введите запрос в поле поиска.
Arc.Ask3.ru: далее начало оригинального документа

Стратегия оценки — Википедия Jump to content

Стратегия оценки

Из Википедии, бесплатной энциклопедии
(Перенаправлено из оценки Eager )

В языке программирования стратегия вычисления это набор правил вычисления выражений. [1] Этот термин часто используется для обозначения более конкретного понятия стратегии передачи параметров. [2] который определяет тип значения, передаваемого функции для каждого параметра ( стратегия привязки ) [3] и следует ли оценивать параметры вызова функции, и если да, то в каком порядке ( порядок оценки ). [4] Понятие стратегии сокращения является четким, [5] хотя некоторые авторы объединяют эти два термина, и определение каждого термина не получило широкого согласия. [6]

Чтобы проиллюстрировать, выполнение вызова функции f(a,b) может сначала оценить аргументы a и b, сохранять результаты в ссылках или ячейках памяти ref_a и ref_b, затем оцените тело функции с переданными ссылками. Это дает функции возможность искать значения аргументов, изменять их посредством присваивания , как если бы они были локальными переменными, и возвращать значения через ссылки. Это стратегия оценки по ссылке. [7]

Стратегия оценки является частью семантики определения языка программирования. Некоторые языки, такие как PureScript , имеют варианты с разными стратегиями оценки. Некоторые декларативные языки , такие как Datalog , поддерживают несколько стратегий оценки. Некоторые языки определяют соглашение о вызовах . [ нужны разъяснения ]

Таблица [ править ]

Это таблица стратегий оценки и репрезентативных языков по годам введения. Репрезентативные языки перечислены в хронологическом порядке, начиная с языка(ов), на которых была представлена ​​стратегия, и заканчивая известными языками, использующими эту стратегию. [8] : 434 

Стратегия оценки Репрезентативные языки Год первого представления
Звонок по ссылке Фортран II, PL/I 1958
Вызов по значению АЛГОЛ , C , Схема , MATLAB [9] 1960
Звонок по имени АЛГОЛ 60 , Моделирование 1960
Звонок путем копирования-восстановления Фортран IV , Да [10] 1962
Звонок по объединению Пролог 1965 [11] [12]
Звонок по необходимости САСЛ , [13] Хаскелл , Р. [14] 1971 [15]
Позвоните, поделившись CLU , Java , Python , Руби , Джулия 1974 [16]
Вызов по ссылочным параметрам С++ , PHP , [17] С# , [18] Визуальный Бейсик .NET [19] 1985 [20]
Вызов по ссылке на const С++ , С 1985 [20]

Заказы на оценку [ править ]

Хотя порядок операций определяет абстрактное синтаксическое дерево выражения, порядок вычисления определяет порядок, в котором вычисляются выражения. Например, программа Python

def   f  (  x  ): 
     print  (  x  ,   end  =  ''  ) 
     return   x 

 print  (  f  (  1  )   +   f  (  2  ),  end  =  ''  ) 

результаты 123 из-за порядка вычислений Python слева направо, но аналогичная программа в OCaml :

пусть   f   x   =   print_int   x  ;      х 
  print_int   (  ж   1   +   ж   2  ) 

результаты 213 из-за порядка вычислений OCaml справа налево.

Порядок вычислений в основном виден в коде с побочными эффектами , но он также влияет на производительность кода, поскольку жесткий порядок препятствует планированию инструкций . По этой причине языковые стандарты, такие как C++, традиционно оставляют порядок неопределенным, хотя такие языки, как Java и C#, определяют порядок вычислений слева направо. [8] : 240–241  а стандарт C++17 добавил ограничения на порядок вычислений. [21]

Строгая оценка [ править ]

Аппликативный порядок — это семейство порядков вычислений, в которых аргументы функции полностью оцениваются перед применением функции. [22] Это приводит к тому, что функция становится строгой , т. е. результат функции не определен, если какой-либо из аргументов не определен, поэтому оценку аппликативного порядка чаще называют строгой оценкой . Более того, вызов функции выполняется, как только он встречается в процедуре, поэтому его также называют нетерпеливой оценкой или жадной оценкой . [23] [24] Некоторые авторы называют строгую оценку «вызовом по значению» из-за стратегии привязки вызова по значению, требующей строгой оценки. [4]

Common Lisp, Eiffel и Java оценивают аргументы функции слева направо. C оставляет порядок неопределенным. [25] Схема требует, чтобы порядок выполнения представлял собой последовательное выполнение неопределенной перестановки аргументов. [26] OCaml аналогичным образом оставляет порядок неопределенным, но на практике аргументы оцениваются справа налево из-за конструкции своей абстрактной машины . [27] Все это строгая оценка.

Нестрогая оценка [ править ]

Нестрогий порядок вычисления — это нестрогий порядок вычисления, то есть функция может вернуть результат до того, как все ее аргументы будут полностью оценены. [28] : 46–47  Прототипическим примером является оценка обычного порядка , которая не оценивает ни один из аргументов, пока они не потребуются в теле функции. [29] Вычисление обычного порядка имеет то свойство, что оно завершается без ошибок всякий раз, когда любой другой порядок вычисления завершился бы без ошибок. [30] Название «нормальный порядок» происходит от лямбда-исчисления, где приведение нормального порядка находит нормальную форму, если таковая имеется (это «нормализующая» стратегия приведения ). [31] В этой статье ленивые вычисления классифицируются как метод привязки, а не как порядок вычислений. Но это различие не всегда соблюдается, и некоторые авторы определяют ленивую оценку как оценку в обычном порядке или наоборот. [22] [32] или путайте нестрогость с ленивой оценкой. [28] : 43–44 

Во многих языках логические выражения используют форму нестрогого вычисления, называемую сокращенным вычислением , при котором вычисление оценивает левое выражение, но может пропустить правое выражение, если результат может быть определен — например, в дизъюнктивном выражении (ИЛИ), где true встречается или в союзном выражении (И), где false встречается и так далее. [32] В условных выражениях аналогично используется нестрогое вычисление — оценивается только одна из ветвей. [28]

Сравнение аппликативного порядка и порядка нормального оценки

При обычном вычислении порядка выражения, содержащие дорогостоящие вычисления, ошибки или бесконечный цикл, будут игнорироваться, если они не нужны. [4] позволяющая специфицировать определяемые пользователем конструкции потока управления, возможность, недоступная при аппликативной оценке порядка. При обычной оценке порядка используются сложные структуры, такие как преобразователи для невычисленных выражений, по сравнению со стеком вызовов, используемым при аппликативной оценке порядка. [33] При обычной оценке порядка исторически не хватало полезных инструментов отладки из-за ее сложности. [34]

Стратегии строгого связывания [ править ]

Вызов по значению [ править ]

При вызове по значению (или передаче по значению) вычисленное значение выражения аргумента привязывается к соответствующей переменной в функции (часто путем копирования значения в новую область памяти). Если функция или процедура могут присваивать значения своим параметрам, присваивается только ее локальная переменная, т. е. все, что передается в вызов функции, остается неизменным в области вызывающего объекта при возвращении функции. Например, в Pascal передача массива по значению приведет к копированию всего массива, и любые изменения этого массива будут невидимы для вызывающей стороны: [35]

программа   Главная  ; 
  использует   ЭЛТ  ; 

  процедура   PrintArray  (  a  :   Массив   целых   чисел  )  ; 
  вар 
   я  :   целое число  ; 
  start 
   for   i   :=   Low  (  a  )   to   High  (  a  )   do 
     Write  (  a  [  i  ])  ; 
    НаписатьLn  ()  ; 
  конец  ; 

  Процедура   Modify  (  строка   :   массив   чисел   целых  )  ;   
  начать   
   PrintArray  (  строка  )  ;    // 123 
   строка  [  1  ]   :=   4  ; 
    PrintArray  (  строка  )  ;    // 143 
 конец  ; 

  Var 
   A   :   Массив   чисел   целых  ;  
  начало 
   A   :=   [  1  ,  2  ,  3  ]  ; 
    ПечатьАррай  (  А  )  ;    // 123 
   Изменить  (  А  )  ; 
    ПечатьАррай  (  А  )  ;    // 123 
 конец  . 

Семантический дрейф [ править ]

Строго говоря, при вызове по значению никакие операции, выполняемые вызываемой подпрограммой, не могут быть видны вызывающей стороне, кроме как как часть возвращаемого значения. [16] Это подразумевает форму чисто функционального программирования в семантике реализации. Однако оборот «вызов по значению, где значение является ссылкой» стал обычным явлением, например, в сообществе Java. [36] По сравнению с традиционной передачей по значению, передаваемое значение — это не значение в его обычном значении, например целое число, которое можно записать как литерал, а внутренний дескриптор ссылки реализации . Изменения этого дескриптора ссылки видны в вызывающем объекте. Из-за видимой мутации эту форму «вызова по значению» правильнее называть вызовом путем совместного использования . [16]

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

Звонок по ссылке [ править ]

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

Из-за различий в синтаксисе разница между вызовом по ссылке (где ссылочный тип является неявным) и вызовом путем совместного использования (где ссылочный тип является явным) часто неясна на первый взгляд. Простой лакмусовой бумажкой является возможность написать традиционный swap(a, b) функционировать в языке. [36] Например, на Фортране:

программа  Основная 
     неявная none 
     целое   ::   a   =   1 
     целое   ::   b   =   2 
     вызов  Swap  (  a  ,   b  ) 
     print   *  ,   a  ,   b   !   2 1 
 содержит 
 подпрограмму  Swap  (  a  ,   b  ) 
         целое число  ,   намерение  (  inout  )   ::   a  ,   b 
         целое число   ::   temp 
         temp   =   a 
         a   =   b 
         b   =   temp 
     end подпрограмма  Swap 
 end program  Main 

Таким образом, Фортран inoutнамерение реализует вызов по ссылке; любая переменная может быть неявно преобразована в ссылочный дескриптор. Напротив, самое близкое, что можно получить в Java:

класс   Main   { 
     статический   класс   Box   { 
         int   value  ; 
          public   Box  (  int   value  )   { 
             this  .   значение   =   значение  ; 
          } 
     } 
     static   void   swap  (  Box   a  ,   Box   b  )   { 
         int   temp   =   a  .   ценить  ; 
          а  .   значение   =   б  .   ценить  ; 
          б  .   значение   =   температура  ; 
      } 
     Public   static   void   main  (  String  []   args  )   { 
         Box   a   =   new   Box  (  1  ); 
          Коробка   b   =   новая   коробка  (  2  ); 
          поменять местами  (  а  ,   б  ); 
          Система  .   вне  .   println  (  String.format  "  %  (  %d  ,   a.value  b.value  ,  )   d  ;  "  ) 
      } 
 } 
 // вывод: 2 1 

где явное Boxtype должен использоваться для введения дескриптора. Java использует вызов путем совместного использования, но не вызов по ссылке. [36]

Вызов путем копирования-восстановления [ править ]

Вызов путем копирования-восстановления, также известный как «копирование-вход-выход», «вызов по результату значения», «вызов по возврату значения» (как это называется в сообществе Фортрана ), представляет собой вариант вызова по ссылке. При вызове методом копирования-восстановления содержимое аргумента копируется в новую переменную, локальную для вызова вызова. Затем функция может изменить эту переменную, аналогично вызову по ссылке, но поскольку переменная является локальной, изменения не видны за пределами вызова во время вызова. Когда вызов функции возвращает значение, обновленное содержимое этой переменной копируется обратно, чтобы перезаписать исходный аргумент («восстановлено»). [37]

Семантика вызова путем копирования-восстановления во многих случаях аналогична вызову по ссылке, но отличается, когда два или более аргумента функции псевдонимируют друг друга (т. е. указывают на одну и ту же переменную в среде вызывающего объекта). При вызове по ссылке запись в один аргумент повлияет на другой во время выполнения функции. При вызове путем копирования-восстановления запись в один аргумент не повлияет на другой во время выполнения функции, но в конце вызова значения двух аргументов могут отличаться, и неясно, какой аргумент копируется первым и, следовательно, какое значение получает переменная вызывающего объекта. [38] Например, Ада определяет, что назначение копирования для каждого in out или out параметр встречается в произвольном порядке. [39] Из следующей программы (незаконно в Ada 2012) [40] видно, что поведение GNAT заключается в копировании в порядке слева направо:

с   Ada.Text_IO  ;    используйте   Ada.Text_IO  ; 

  процедура   Test_Copy_Restore   — это 
   процедура   Modify   (  A  ,   B   :  in   out   Integer  )  
   начало 
       A   :=   A   +   1  ; 
        Б   :=   Б   +   2  ; 
    конец   изменения  ; 
    X   :   Целое число   :=   0  ; 
  начать 
   изменение  (  X  ,   X  ); 
    Put_Line  (  "X ="   &   Integer  '  Image  (  X  )); 
  конец   Test_Copy_Restore  ; 
  -- $ gnatmake -gnatd.E test_copy_restore.adb;   ./test_copy_restore 
 -- test_copy_restore.adb:12:10: предупреждение: фактическое значение, доступное для записи для "A", совпадает с фактическим значением для "B" [-gnatw.i] 
 -- X = 2 

Если бы программа вернула 1, она бы копировала справа налево, а при вызове по семантике ссылки программа вернула бы 3.

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

Эта стратегия привлекла внимание при многопроцессорной обработке и удаленных вызовах процедур . [41] поскольку в отличие от вызова по ссылке он не требует частого взаимодействия между потоками выполнения для доступа к переменным.

Позвоните, поделившись [ править ]

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

Впервые этот метод был описан Барбарой Лисковой в 1974 году для языка CLU . [16] Он используется во многих современных языках, таких как Python (общие значения называются «объектами»), [42] Java (объекты), Ruby (объекты), JavaScript (объекты), Scheme (структуры данных, такие как векторы), [43] AppleScript (списки, записи, даты и объекты сценариев), OCaml и ML (ссылки, записи, массивы, объекты и другие составные типы данных), Maple (таблицы и таблицы) и Tcl (объекты). [44] Термин «вызов путем совместного использования», используемый в этой статье, не широко используется; терминология противоречива в разных источниках. Например, в Java-сообществе говорят, что Java — это вызов по значению. [36]

Для неизменяемых объектов нет реальной разницы между вызовом путем совместного использования и вызовом по значению, за исключением случаев, когда идентификатор объекта виден в языке. Использование вызова путем совместного использования с изменяемыми объектами является альтернативой параметрам ввода/вывода : параметр не назначается (аргумент не перезаписывается и идентификатор объекта не изменяется), но объект (аргумент) мутируется. [45]

Например, в Python списки изменяемы и передаются при вызове путем совместного использования, поэтому:

защита   f  (  a_list  ): 
     a_list  .   добавить  (  1  ) 

 м   =   [] 
 ж  (  м  ) 
 распечатать  (  м  ) 

результаты [1] поскольку append Метод изменяет объект, для которого он вызывается.

Напротив, присвоения внутри функции не заметны для вызывающей стороны. Например, этот код привязывает формальный аргумент к новому объекту, но он не виден вызывающей стороне, поскольку не изменяется. a_list:

def   f  (  a_list  ): 
     a_list   =   a_list   +   [  1  ] 
     print  (  a_list  )   # [1] 

 m   =   [] 
 f  (  m  ) 
 print  (  m  )   # [] 

Звонок по адресу [ править ]

Вызов по адресу , передача по адресу или вызов/передача по указателю — это метод передачи параметра, при котором адрес аргумента передается как формальный параметр. Внутри функции адрес (указатель) может использоваться для доступа или изменения значения аргумента. Например, операция замены может быть реализована в C следующим образом: [46]

#include   <stdio.h> 

 void   swap  (  int  *   a  ,   int  *   b  )   { 
     int   temp   =   *  a  ; 
      *  а   =   *  б  ; 
      *  б   =   температура  ; 
  } 

 Int   main  ()   { 
     int   a   =   1  ; 
      интервал   б   =   2  ; 
      поменять местами  (  &a  a   ,   &  б  ); 
      printf  (  "%d %d"  ,   a  ,   b  );    // 2 1 
     возвращаем   0  ; 
  } 

Некоторые авторы рассматривают & как часть синтаксиса вызова swap. С этой точки зрения C поддерживает стратегию передачи параметров по ссылке. [47] Другие авторы придерживаются иной точки зрения, что представленная реализация swap в C — это всего лишь симуляция вызова по ссылке с использованием указателей. [48] С этой точки зрения «симуляции» изменяемые переменные в C не являются первоклассными (то есть l-значения не являются выражениями), а типы указателей. С этой точки зрения представленная программа подкачки является синтаксическим сахаром для программы, которая повсюду использует указатели. [49] например эта программа( read и assign были добавлены, чтобы подчеркнуть сходство с Java Box программа совместного вызова выше ):

#include   <stdio.h> 

 int   read  (  int   *  p  )   { 
   return   *  p  ; 
  } 

 void   Assign  (  int   *  p  ,   int   v  )   { 
   *  p   =   v  ; 
  } 

 void   swap  (  int  *   a  ,   int  *   b  )   { 
     int   temp_storage  ;    int  *   temp   =   &  temp_storage  ; 
      назначить  (  temp  ,   прочитать  (  a  )); 
      назначить  (  a  ,   прочитать  (  b  )); 
      назначить  (  b  ,   прочитать  (  temp  )); 
  } 

 Int   Main  ()   { 
     int   a_storage  ;    int  *   a   =   &  a_storage  ; 
      int   b_storage  ;    int  *   b   =   &  b_storage  ; 
      назначить  (  а  ,  1  ); 
      назначить  (  б  ,  2  ); 
      поменять местами  (  а  ,   б  ); 
      printf  (  "%d %d"  ,   read  (  a  ),   read  (  b  ));    // 2 1 
     возвращаем   0  ; 
  } 

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

C++ еще больше запутывает проблему, позволяя swap должен быть объявлен и использован с очень легким «эталонным» синтаксисом: [50]

void   swap  (  int  &   a  ,   int  &   b  )   { 
     int   temp   =   a  ; 
      а   =   б  ; 
      б   =   температура  ; 
  } 

 Int   main  ()   { 
     int   a   =   1  ; 
      интервал   б   =   2  ; 
      поменять местами  (  а  ,   б  ); 
      std  ::  cout   <<   a   <<   b   <<   std  ::  endl  ;    // 2 1 
     возвращаем   0  ; 
  } 

Семантически это эквивалентно примерам на C. Таким образом, многие авторы считают вызов по адресу уникальной стратегией передачи параметров, отличной от вызова по значению, вызова по ссылке и совместного использования.

Призыв по объединению [ править ]

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

Стратегии нестрогого связывания [ править ]

Звонить по имени [ править ]

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

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

Языки .NET могут имитировать вызов по имени с помощью делегатов или Expression<T>параметры. Последнее приводит к тому, что абстрактное синтаксическое дерево функции передается . Eiffel предоставляет агенты, которые представляют собой операцию, которую необходимо оценить при необходимости. Seed7 обеспечивает вызов по имени с параметрами функции. Программы Java могут выполнять аналогичные ленивые вычисления, используя лямбда-выражения и java.util.function.Supplier<T> интерфейс.

Звонок по необходимости [ править ]

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

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

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

Ленивая оценка — это наиболее распространенная реализация семантики вызова по необходимости, но ее варианты, такие как оптимистическая оценка существуют . Языки .NET реализуют вызов по необходимости, используя тип Lazy<T>.

Сокращение графа — это эффективная реализация ленивых вычислений.

Вызов расширением макроса [ править ]

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

Звонок из будущего [ править ]

«Звонок по будущему», также известный как «параллельный вызов по имени» или «снисходительная оценка», [51] — это стратегия параллельной оценки, сочетающая нестрогую семантику с нетерпеливой оценкой. Этот метод требует детального динамического планирования и синхронизации, но подходит для машин с массовым параллелизмом.

Стратегия создает будущее (обещание) для тела функции и каждого из ее аргументов. Эти фьючерсы вычисляются одновременно с остальной частью программы. Когда фьючерсу A требуется значение другого фьючерса B, которое еще не было вычислено, фьючерс A блокируется до тех пор, пока фьючерс B не завершит вычисление и не обретет значение. Если будущий B уже завершил вычисления, значение возвращается немедленно. Условные выражения блокируются до тех пор, пока их условие не будет оценено, а лямбда-выражения не создают фьючерсы до тех пор, пока они не будут полностью применены. [52]

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

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

ж   x   =   1  /  x 
 g   y   =   1 
 main   =   печать   (  g   (  f   0  )) 

может иметь g закончить раньше fи выход 1, или может привести к ошибке из-за вычисления 1/0. [28]

Вызов по будущему аналогичен вызову по необходимости в том, что значения вычисляются только один раз. При тщательной обработке ошибок и незавершений, в частности, прерывании фьючерсов на полпути, если определено, что они не понадобятся, вызов по будущему также имеет те же свойства завершения, что и оценка вызова по необходимости. [52] Однако вызов по будущему может выполнять ненужную спекулятивную работу по сравнению с вызовом по необходимости, например глубокую оценку ленивой структуры данных. [28] Этого можно избежать, используя ленивые фьючерсы, которые не начинают вычисления до тех пор, пока не будет уверенности, что значение необходимо.

Оптимистическая оценка [ править ]

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

См. также [ править ]

Ссылки [ править ]

  1. ^ Араки, Шота; Нисидзаки, Син-я (ноябрь 2014 г.). «Оценка исчислений RPC и RMI по имени». Теория и практика вычислений . п. 1. дои : 10.1142/9789814612883_0001 . ISBN  978-981-4612-87-6 . Проверено 21 августа 2021 г.
  2. ^ Турбак, Франклин; Гиффорд, Дэвид (18 июля 2008 г.). Концепции проектирования в языках программирования . МТИ Пресс. п. 309. ИСБН  978-0-262-30315-6 .
  3. ^ Кранк, Эрик; Феллейзен, Матиас (1991). «Передача параметров и лямбда-исчисление». Материалы 18-го симпозиума ACM SIGPLAN-SIGACT по принципам языков программирования — POPL '91 . п. 2. CiteSeerX   10.1.1.23.4385 . дои : 10.1145/99583.99616 . ISBN  0897914198 . S2CID   5782416 .
  4. ^ Перейти обратно: а б с Вильгельм, Рейнхард; Зайдль, Гельмут (10 ноября 2010 г.). Проектирование компилятора: виртуальные машины . Springer Science & Business Media. п. 61. ИСБН  978-3-642-14909-2 .
  5. ^ Нита, Стефания Лоредана; Михайлеску, Мариус (2017). "Введение" . Практический параллельный Haskell . стр. 3. два : 10.1007/978-1-4842-2781-7_1 . ISBN  978-1-4842-2780-0 .
  6. ^ Пирс, Бенджамин К. (2002). Типы и языки программирования . МТИ Пресс . п. 56. ИСБН  0-262-16209-1 .
  7. ^ Дэниел П. Фридман; Митчелл Ванд (2008). Основы языков программирования (третье изд.). Кембридж, Массачусетс: MIT Press . ISBN  978-0262062794 .
  8. ^ Перейти обратно: а б Скотт, Майкл Ли (2016). Прагматика языка программирования (Четвертое изд.). Уолтем, Массачусетс: Эльзевир. ISBN  9780124104778 .
  9. ^ «Избегайте ненужных копий данных — MATLAB & Simulink» . www.mathworks.com . Проверено 28 января 2023 г.
  10. ^ Хасти, Ребекка. «Передача параметров» . CS 536: Введение в языки программирования и компиляторы . Университет Висконсина . Проверено 22 августа 2021 г.
  11. ^ Дж. А. Робинсон (январь 1965 г.). «Машинно-ориентированная логика, основанная на принципе разрешения» . Журнал АКМ . 12 (1): 23–41. дои : 10.1145/321250.321253 . S2CID   14389185 . ; Здесь: разд.5.8, стр.32
  12. ^ Дж. А. Робинсон (1971). «Вычислительная логика: унификация вычислений» . Машинный интеллект . 6 : 63–72.
  13. ^ Банди, Алан; Валлен, Линкольн (1984). «САСЛ». Каталог инструментов искусственного интеллекта . п. 117. дои : 10.1007/978-3-642-96868-6_222 . ISBN  978-3-540-13938-6 . Вероятно, это был первый язык, который систематически использовал возможности ленивых вычислений.
  14. ^ Фэй, Колин (30 июля 2018 г.). «О ленивой оценке» . R-блогеры . Проверено 21 августа 2021 г.
  15. ^ Уодсворт, Кристофер П. (1971). Семантика и прагматика лямбда-исчисления (доктор философии). Оксфордский университет.
  16. ^ Перейти обратно: а б с д Это Лисков, Варвара; Аткинсон, Расс; Блум, Тоби; Мосс, Элиот; Шафферт, Крейг; Шайфлер, Крейг; Снайдер, Алан (октябрь 1979 г.). «Справочное руководство CLU» (PDF) . Лаборатория компьютерных наук . Массачусетский Институт Технологий. стр. 14–15. Архивировано (PDF) из оригинала 22 сентября 2006 г. Проверено 19 мая 2011 г.
  17. ^ «PHP: Передача по ссылке — Руководство» . www.php.net . Проверено 4 июля 2021 г.
  18. ^ Вагнер, Билл (12 апреля 2023 г.). «Передача параметров — Руководство по программированию на C#» . Документы Майкрософт . Проверено 10 сентября 2023 г.
  19. ^ Доллард, Кэтлин (15 сентября 2021 г.). «Передача аргументов по значению и по ссылке — Visual Basic» . Документы Майкрософт . Проверено 10 сентября 2023 г.
  20. ^ Перейти обратно: а б «История С++» . ru.cppreference.com . Проверено 11 июня 2022 г.
  21. ^ Филипек, Бартломей (16 августа 2021 г.). «Строгий порядок вычисления выражений в C++17» . Истории С++ . Проверено 24 августа 2021 г.
  22. ^ Перейти обратно: а б Абельсон, Гарольд ; Сассман, Джеральд Джей (1996). «Нормальный порядок и аппликативный порядок» . Структура и интерпретация компьютерных программ (2-е изд.). Кембридж, Массачусетс: MIT Press . ISBN  0-262-01153-0 . Архивировано из оригинала 02 марта 2005 г. Проверено 6 марта 2006 г. См. также сноску Temp 576.
  23. ^ Риз, Ричард М. (14 октября 2015 г.). Изучение функционального программирования на Java . Packt Publishing Ltd. с. 106. ИСБН  978-1-78528-935-4 .
  24. ^ Антани, Вед; Тиммс, Саймон; Мантила, Дэн (31 августа 2016 г.). JavaScript: функциональное программирование для разработчиков JavaScript . Packt Publishing Ltd. с. 614. ИСБН  978-1-78712-557-5 .
  25. ^ Сикорд, Роберт С. «EXP30-C. Не зависит от порядка оценки побочных эффектов» . SEI CERT Стандарт кодирования C. Университет Карнеги Меллон . Проверено 23 августа 2021 г.
  26. ^ Англаде, С.; Лакрамп, Джей Джей; Кейннек, К. (октябрь 1994 г.). «Семантика сочетаний в схеме» (PDF) . Указатели Lisp ACM SIGPLAN . VII (4): 15–20. дои : 10.1145/382109.382669 . S2CID   2987427 .
  27. ^ «Почему аргументы функции OCaml оцениваются справа налево?» . ОКамл . 30 ноября 2017 г.
  28. ^ Перейти обратно: а б с д Это Трамбле, Г. (апрель 2000 г.). «Снисходительная оценка не является ни строгой, ни ленивой». Компьютерные языки . 26 (1): 43–66. CiteSeerX   10.1.1.137.9885 . дои : 10.1016/S0096-0551(01)00006-6 .
  29. ^ Джордж, Лай (март 1987 г.). Эффективная оценка нормального порядка посредством информации о строгости (MSc). Университет Юты. п. 10.
  30. ^ Борнинг, Алан (осень 1999 г.). «Аппликативное и нормальное вычисление порядка в функциональных языках» (PDF) . CSE 505: Концепции языков программирования . Университет Вашингтона . Проверено 23 августа 2021 г.
  31. ^ Маццола, Гуэрино; Мильмейстер, Жерар; Вайсманн, Джоди (21 октября 2004 г.). Комплексная математика для специалистов по информатике 2 . Springer Science & Business Media. п. 323. ИСБН  978-3-540-20861-7 .
  32. ^ Перейти обратно: а б Штурм, Оливер (11 апреля 2011 г.). Функциональное программирование на C#: классические методы программирования для современных проектов . Джон Уайли и сыновья. п. 91. ИСБН  978-0-470-74458-1 .
  33. ^ Марлоу, Саймон. «Почему я не могу получить трассировку стека?» . Семинар разработчиков Haskell 2012 . Проверено 25 августа 2021 г.
  34. ^ Нильссон, Хенрик (1999). «Трассировка по частям: доступная отладка для ленивых функциональных языков». Материалы четвертой международной конференции ACM SIGPLAN по функциональному программированию . стр. 36–47. CiteSeerX   10.1.1.451.6513 . дои : 10.1145/317636.317782 . ISBN  1581131119 . S2CID   13954359 .
  35. ^ «Параметры открытого массива» . www.freepascal.org . Проверено 20 января 2024 г.
  36. ^ Перейти обратно: а б с д «Java — это передача по значению, черт возьми!» . 16 мая 2001 года . Проверено 24 декабря 2016 г.
  37. ^ Коэнен, Франс. «СООТВЕТСТВИЕ ПАРАМЕТРА» . cgi.csc.liv.ac.uk. ​ Проверено 22 января 2024 г.
  38. ^ «Вызов по ссылке, проблемы с псевдонимами» (PDF) . Курс MPRI 2-36-1: Проверка программы (конспекты лекций) . п. 53.
  39. ^ Справочное руководство по языку Ada 2022 (PDF) , 13 октября 2023 г., стр. 215
  40. ^ Барнс, Джон (2013). Обоснование Ada 2012: язык, стандартные библиотеки (PDF) . Гейдельберг: Спрингер. п. 15-16,87-88. ISBN  978-3-642-45210-9 .
  41. ^ Терлоу, Роберт (май 2009 г.). «RPC: Спецификация протокола удаленного вызова процедур, версия 2» . www.tools.ietf.org . IETF . Проверено 7 апреля 2018 г.
  42. ^ Лунд, Фредрик. «Вызов по объекту» . Effbot.org . Архивировано из оригинала 19 мая 2011 г. Проверено 19 мая 2011 г.
  43. ^ Джонс, Рис Прайс (2010). «Вызов Scheme по значению?» . CS 145 Языки программирования. Лабораторная работа 9: Передача параметров . Университет Джорджа Вашингтона. Архивировано из оригинала 16 октября 2014 года . Проверено 20 января 2024 г.
  44. ^ «Процедуры библиотеки Tcl — страница руководства Tcl_Obj» . www.tcl.tk.
  45. ^ «CA1021: Избегайте выходных параметров» . Майкрософт. 15 ноября 2016 г.
  46. ^ Лео, Рэй (ноябрь 1996 г.). Маленький C++ (сделано проще) . LeoSudo Inc., стр. 79–80. ISBN  978-0-9654634-1-6 .
  47. ^ Дандамуди, Шиварама П. (15 июля 2005 г.). Руководство по программированию на языке ассемблера в Linux . Springer Science & Business Media. п. 232. ИСБН  978-0-387-25897-3 .
  48. ^ Шривастава, СК; Шривастава, Дипали (6 июня 2018 г.). C в глубине . Публикации БПБ. п. 206. ИСБН  978-93-87284-94-4 .
  49. ^ «Изменяемые переменные и ссылочные типы» . okmij.org . Проверено 20 января 2024 г.
  50. ^ Вермейр, Дирк (28 июня 2011 г.). Мультипарадигмальное программирование с использованием C++ . Springer Science & Business Media. стр. 10–11. ISBN  978-1-4471-0311-0 .
  51. ^ МакКоллин, Томас Гвинфрин; Морелл, Тобиас. «Игра парадигм: исследование удобства использования функциональных идиом в программировании игрового процесса» (PDF) . Ольборгский университет. п. 6 . Проверено 11 января 2022 г.
  52. ^ Перейти обратно: а б Шаузер, Клаус Э.; Гольдштейн, Сет К. (1995). «Какой степени нестрогости требуют мягкие программы?» (PDF) . Материалы седьмой международной конференции «Функциональные языки программирования и компьютерная архитектура — FPCA '95» . стр. 216–225. дои : 10.1145/224164.224208 . ISBN  0897917197 . S2CID   2045943 . Проверено 7 января 2022 г.
  53. ^ Энналс, Роберт; Джонс, Саймон Пейтон (август 2003 г.). «Оптимистическая оценка: стратегия быстрой оценки для нестрогих программ» .

Дальнейшее чтение [ править ]

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец оригинального документа.
Arc.Ask3.Ru
Номер скриншота №: 5F8BF523A6D15E8104455168CBA68FB4__1712597340
URL1:https://en.wikipedia.org/wiki/Eager_evaluation
Заголовок, (Title) документа по адресу, URL1:
Evaluation strategy - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть, любые претензии не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, денежную единицу можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)