MethodHandles.Loop(MethodHandle[][]) Метод

Определение

Создает дескриптор метода, представляющий цикл с несколькими переменными цикла, которые обновляются и проверяются при каждой итерации.

[Android.Runtime.Register("loop", "([[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;", "", ApiSince=33)]
public static Java.Lang.Invoke.MethodHandle? Loop (params Java.Lang.Invoke.MethodHandle[][]? clauses);
[<Android.Runtime.Register("loop", "([[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;", "", ApiSince=33)>]
static member Loop : Java.Lang.Invoke.MethodHandle[][] -> Java.Lang.Invoke.MethodHandle

Параметры

clauses
MethodHandle[][]

массив массивов (4 кортежа) объектов MethodHandle, придерживающихся описанных выше правил.

Возвращаемое значение

дескриптор метода, воплощающий поведение цикла в соответствии с аргументами .

Атрибуты

Комментарии

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

Интуитивно каждый цикл состоит из одного или нескольких "предложений", каждое из которых задает локальную <переменную<> итерации em>и/или выход цикла. Каждая итерация цикла выполняет каждое предложение по порядку. Предложение может при необходимости обновить свою переменную итерации; он также может при необходимости выполнить тест и выход условного цикла. Чтобы выразить эту логику в терминах дескрипторов методов, каждое предложение указывает до четырех независимых действий:<ul><li><em>init:</em> Перед выполнением цикла инициализация переменной v итерации типа V. <li><em>step:</em> При выполнении предложения — шаг обновления для переменной vитерации . <li><em>pred:</em> При выполнении предложения выполняется предикат для проверки выхода цикла. <li><em>fini:</em> Если предложение вызывает выход цикла, выполнение метода завершения для вычисления возвращаемого значения цикла. </ul> Полная последовательность всех типов переменных итерации в порядке предложения будет нотирована как (V...). Сами значения будут иметь значение (v...). Когда мы говорим о "списках параметров", мы обычно будем ссылаться на типы, но в некоторых контекстах (описывающих выполнение) списки будут иметь фактические значения.

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

<Em>Parameters необязательный везде:</em> Каждая функция предложения разрешена, но не требуется принимать параметр для каждой переменной vитерации . В качестве исключения функции инициализации не могут принимать параметры v , так как эти значения еще не вычисляются при выполнении функций инициализации. Любая функция предложения может не принимать любую завершающую часть параметров, которые она имеет право принимать. На самом деле любая функция предложения может вообще не принимать аргументов.

<Em>Loop parameters:</em> Функция предложения может принимать все имеющиеся у нее значения переменных итерации, в этом случае она также может принимать больше конечных параметров. Такие дополнительные значения называются <параметрами< цикла em>/em>, а их типы и значения нотируются как (A...) и (a...). Они становятся параметрами результирующего дескриптора цикла, которые будут предоставляться при каждом выполнении цикла. (Поскольку функции инициализации не принимают переменные vитерации, любой параметр функции инициализации автоматически является параметром aцикла .) Как и в случае с переменными итерации, функции предложений разрешены, но не требуются для приема параметров цикла. Эти параметры цикла действуют как инвариантные значения цикла, видимые во всем цикле.

<Параметры em>, видимые везде:</em> Каждая функция предложения без инициализации может наблюдать за всем состоянием цикла, так как ей можно передать полный список (v... a...) текущих значений переменных итерации и входящих параметров цикла. Функции инициализации могут наблюдать начальное состояние предварительного цикла в форме (a...). Большинству функций предложений не требуются все эти сведения, но они будут формально связаны с ней, как если бы .#dropArguments "astar"> В частности, мы будем использовать нотацию (V*) для выражения произвольного префикса полной последовательности (V...) (и аналогично для (v*), (A*), (a*)). В этой нотации общая форма списка параметров функции инициализации — (A*), а общая форма списка параметров функции без инициализации — или (V*)(V... A*).

<em>Проверка структуры предложения:</em> . При наличии набора предложений выполняется ряд проверок и корректировок для соединения всех частей цикла. Они подробно описаны в приведенных ниже шагах. На этих шагах каждое вхождение слова "must" соответствует месту, где IllegalArgumentException будет выдано, если требуемое ограничение не будет выполнено входными данными для комбинатора цикла.

<Em>Эффективно идентичные последовательности:</em> "effid"> Список A параметров определяется <как em>, фактически идентичный</em> другому списку B параметров, если A и B идентичны, или если A имеет более короткий и идентичный с правильным префиксом B. Говоря о неупорядоченном наборе списков параметров, мы говорим, что набор "фактически идентичен" в целом, если набор содержит самый длинный список, а все члены набора фактически идентичны самому длинному списку. Например, любой набор последовательностей типов формы (V*) фактически идентичен, и то же самое верно при добавлении дополнительных последовательностей формы (V... A*) .

<Шаг>0. Определение структуры предложения.</em><ol type="a"><li>Массив предложений (типа MethodHandle[][]) должен быть не-null и содержать по крайней мере один элемент. <Li>Массив предложений не может содержать nulls или вложенные массивы, превышающие четыре элемента. <Предложения li>короче четырех элементов обрабатываются так, как если бы они были заполнены элементами null до четырех. Заполнение выполняется путем добавления элементов в массив. <Предложения li>со всеми nullне учитываются. <Li>Каждое предложение обрабатывается как кортеж функций с четырьмя типами, которые называются init, step, pred и fini. </Пр>

<Шаг>1А. Определение типов (V...)переменных итерации .</em><ol type="a"><li>Тип переменной итерации для каждого предложения определяется с помощью возвращаемых типов инициализации и шага предложения. <Li>Если обе функции опущены, для соответствующего предложения не существует переменной итерации (void используется в качестве типа для указания этого). Если один из них опущен, тип возвращаемого значения другого определяет тип переменной итерации предложения. Если указаны оба значения, общий тип возвращаемого значения (они должны быть идентичными) определяет тип переменной итерации предложения. <Li>Сформирует список типов возвращаемых значений (в порядке предложения), пропуская все вхождения void. <Li>Этот список типов называется "типами переменных итерации" ((V...)). </Пр>

<Шаг>1B. Определение параметров (A...)цикла .</em><ul><li>Проверьте и соберите списки параметров функции инициализации (которые имеют форму (A*)). <Li>Изучите и соберите суффиксы списков параметров шага, pred и fini после удаления типов переменных итерации. (Они должны иметь форму (V... A*); (A*) собирать только части.) <li>Не собирать суффиксы из списков параметров step, pred и fini, которые не начинаются со всех типов переменных итерации. (Эти типы будут проверены на шаге 2 вместе со всеми типами функций предложения.) <Литий>Опущенные функции предложения игнорируются. (Эквивалентно считается, что они имеют пустые списки параметров.) <Литий>Все собранные списки параметров должны быть фактически идентичными. <Li>Самый длинный список параметров (который обязательно является уникальным) называется "внешним списком параметров" ((A...)). <Li>Если такого списка параметров нет, внешний список параметров принимается как пустая последовательность. <Li>Объединенный список, состоящий из типов переменных итерации, за которыми следуют типы внешних параметров, называется "внутренним списком параметров". </ul>

<Шаг>1C. Определение типа возвращаемого значения цикла.</em><ol type="a"><li>Изучите возвращаемые типы функций fini, игнорируя опущенные функции fini. <Li>Если функции fini отсутствуют, тип возвращаемого значения цикла — void. <Li>В противном случае общий тип R возвращаемого значения функций fini (типы возвращаемых значений должны быть идентичными) определяет тип возвращаемого значения цикла. </Пр>

<Em>Шаг 1D. Проверьте другие типы.</em><ol type="a"><li>Должна быть по крайней мере одна функция pred, не опущенная. <Li>Каждая не опущенная функция pred должна иметь тип возвращаемого boolean значения. </Пр>

<Шаг>2. Определение списков параметров.</em><ol type="a"><li>Список параметров для результирующего дескриптора цикла будет списком (A...)внешних параметров . <Li>Список параметров для функций инициализации будет изменен на список внешних параметров. (Обратите внимание, что их списки параметров уже фактически идентичны этому списку.) <Литий>Список параметров для каждой функции без инициализации (step, pred и fini) должен быть фактически идентичен внутреннему списку (V... A...)параметров. </Пр>

<Шаг>3. Заполнение опущенных функций.</em><ol type="a"><li>Если функция инициализации опущена, используйте значение #empty по умолчанию для типа переменной итерации предложения. <Li>Если функция step опущена, используйте функцию #identity identity типа переменной итерации предложения; вставьте удаленные параметры аргумента перед параметром функции identity для переменных, отличныхvoid от итерации предыдущих предложений. (Переменная цикла превратится в инвариантный локальный цикл.) <Литий>Если функция pred опущена, используйте функцию константы true . (Это позволит сохранить цикл, что касается данного условия. Обратите внимание, что в таких случаях соответствующая функция fini недоступна.) <Литий>Если функция fini опущена, используйте #empty значение по умолчанию для возвращаемого типа цикла. </Пр>

<Шаг>4. Заполните отсутствующие типы параметров.</em><ol type="a"><li>На этом этапе каждый список параметров функции инициализации фактически идентичен списку (A...)внешних параметров , но некоторые списки могут быть короче. Для каждой функции инициализации с коротким списком параметров необходимо заполнить конец списка. <Li>На этом этапе каждый список параметров функции без инициализации фактически идентичен списку внутренних параметров (V... A...), но некоторые списки могут быть короче. Для каждой функции, не являющейся инициализацией, с коротким списком параметров, заполните конец списка. <Списки аргументов li>заполняются #dropArgumentsToMatch(MethodHandle, int, List, int) удалением неиспользуемых конечных аргументов. </Пр>

<Em>Заключительные наблюдения.</em><ol type="a"><li>После выполнения этих действий все предложения были скорректированы путем указания опущенных функций и аргументов. <Li>Все функции инициализации имеют общий список (A...)типов параметров , который также будет иметь дескриптор заключительного цикла. <li>Все функции fini имеют общий тип возвращаемого значения R, который также будет иметь конечный дескриптор цикла. <Li>Все функции, не являющиеся инициализацией, имеют общий список (V... A...)типов параметров , из переменных V итерации ,void за которыми следуют параметры цикла. <Li>Каждая пара функций инициализации и шага согласуется с типом возвращаемого значения V. <Li>Каждая функция без инициализации сможет наблюдать текущие значения (v...) всех переменных итерации. <Li>Каждая функция сможет наблюдать за входящими значениями (a...) всех параметров цикла. </Пр>

<Пример em>.</em> В результате шага 1A выше комбинатор loop имеет следующее свойство: <ul><li>Given N clauses Cn = {null, Sn, Pn} с n = 1..N. <Li>Предположим, что дескрипторы Pn предиката являются или null не имеют параметров. (Только один Pn должен быть не-null.) <Li>Предположим, что дескрипторы Sn шагов имеют сигнатуры (B1..BX)Rnдля некоторой константы X>=N. <Li>Предположим Q , является числом типов Rnnon-void , а (V1...VQ) — последовательностью этих типов. <li>Должно быть, что Vn == Bn для n = 1..min(X,Q). <Li>Типы Vn параметров будут интерпретироваться как элементы (V...)локального состояния цикла . <Li>Любые оставшиеся типы BQ+1..BX (если Q<X) определяют типы (A...)параметров результирующего дескриптора цикла . </ul> . В этом примере параметры (A...) дескриптора цикла были получены из функций шага, что естественно, если большая часть вычислений цикла выполняется на этапах. Для некоторых циклов вычисление может быть самым тяжелым в функциях pred, поэтому функции pred могут принимать значения параметров цикла. Для циклов со сложной логикой выхода функции fini могут потребоваться принимать параметры цикла, а также для циклов со сложной логикой входа, где функции инициализации будут нуждаться в дополнительных параметрах. По таким причинам правила определения этих параметров максимально симметричные для всех частей предложения. Как правило, параметры цикла функционируют как общие инвариантные значения во всем цикле, а переменные итерации — как общие значения вариантов или (если нет функции step) как внутренние инвариантные временные циклы.

<Выполнение цикла em>.</em><ol type="a"><li>При вызове цикла входные значения цикла сохраняются в локальных значениях, которые передаются каждой функции предложения. Эти локальные значения являются инвариантными циклами. <Li>Каждая функция инициализации выполняется в порядке предложения (передавая внешние аргументы (a...)), а неvoid - значения сохраняются (как переменные (v...)итерации) в локальные. Эти локальные значения будут циклически разными (если их шаги не ведут себя как функции идентификации, как указано выше). <Li>Всем выполнениям функций (кроме функций инициализации) будет передан внутренний список параметров, состоящий из значений (v...) , отличныхvoid от итерации (в порядке предложений), а затем входных данных цикла (в порядке аргументов (a...) ). <Li>Затем функции step и pred выполняются в порядке предложения (шаг перед pred), пока функция pred не вернет false. <Li>Результат, отличныйvoid от вызова функции шага, используется для обновления соответствующего значения в последовательности (v...) переменных цикла. Обновленное значение сразу становится видимым для всех последующих вызовов функций. <Li>Если функция pred возвращает false, вызывается соответствующая функция fini, а результирующее значение (типа R) возвращается из цикла в целом. <li>Если все функции pred всегда возвращают значение true, функция fini никогда не вызывается, и цикл не может выйти, кроме как вызвать исключение. </Пр>

<Em>Советы по использованию.</em><ul><li>. Хотя каждая функция step будет получать текущие значения <переменных цикла em>all</em> , иногда функции step требуется только наблюдать текущее значение собственной переменной. В этом случае функции step может потребоваться явно #dropArguments удалить все предыдущие переменные цикла. Для этого потребуется упомянуть их типы в выражении, например dropArguments(step, 0, V0.class, ...). <Переменные цикла li>не требуются для изменения; они могут быть инвариантными. Предложение может создать инвариантный цикл с помощью подходящей функции инициализации без функции step, pred или fini. Это может быть полезно для "подключения" входящего аргумента цикла в функцию step или pred соседней переменной цикла. <Li>Если некоторые из функций предложения являются виртуальными методами экземпляра, сам экземпляр можно удобно поместить в начальный инвариантный цикл "переменная", используя исходное предложение, например new MethodHandle[]{identity(ObjType.class)}. В этом случае ссылка на экземпляр будет первым значением переменной итерации, и виртуальные методы будет легко использовать в качестве частей предложения, так как все они будут принимать ссылку на ведущий экземпляр, соответствующую данному значению. </ul>

Ниже приведен псевдокод для результирующего дескриптора цикла. Как описано выше, V и v представляют типы и значения переменных цикла; A и a представляют аргументы, передаваемые всему циклу; и R является общим типом результата для всех методов завершения, а также результирующего цикла. <blockquote>

{@code
            V... init...(A...);
            boolean pred...(V..., A...);
            V... step...(V..., A...);
            R fini...(V..., A...);
            R loop(A... a) {
              V... v... = init...(a...);
              for (;;) {
                for ((v, p, s, f) in (v..., pred..., step..., fini...)) {
                  v = s(v..., a...);
                  if (!p(v..., a...)) {
                    return f(v..., a...);
                  }
                }
              }
            }
            }

</blockquote> Обратите внимание, что тип параметра содержит (V...) список и (A...) был расширен до полной длины, несмотря на то, что отдельные функции предложений могут не принимать их все. Как отмечалось выше, отсутствующие параметры заполняются как будто .#dropArgumentsToMatch(MethodHandle, int, List, int)

Добавлено в 9.

Документация по Java для java.lang.invoke.MethodHandles.loop(java.lang.invoke.MethodHandle[]...).

Части этой страницы являются изменениями, основанными на работе, созданной и совместно используемой проектом Android и используемой в соответствии с условиями, Creative Commons 2.5 Attribution License.

Применяется к