MethodHandles.Loop(MethodHandle[][]) Método
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Construye un identificador de método que representa un bucle con varias variables de bucle que se actualizan y comprueban en cada iteración.
[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
Parámetros
- clauses
- MethodHandle[][]
matriz de matrices (4 tuplas) de MethodHandles que se adhieren a las reglas descritas anteriormente.
Devoluciones
un identificador de método que incorpora el comportamiento de bucle tal como se define en los argumentos.
- Atributos
Comentarios
Construye un identificador de método que representa un bucle con varias variables de bucle que se actualizan y comprueban en cada iteración. Tras la finalización del bucle debido a uno de los predicados, se ejecuta un finalizador correspondiente y se entrega el resultado del bucle, que es el valor devuelto del controlador resultante.
De forma intuitiva, cada bucle está formado por una o varias "cláusulas", cada una de las cuales especifica una variable< de iteración local<>/em> o una salida de bucle. Cada iteración del bucle ejecuta cada cláusula en orden. Una cláusula puede actualizar opcionalmente su variable de iteración; también puede realizar opcionalmente una salida de bucle condicional y de prueba. Para expresar esta lógica en términos de identificadores de método, cada cláusula especificará hasta cuatro acciones independientes:<ul><li><em>init:</em> Before the loop executes, la inicialización de una variable v de iteración de tipo V.
<li><em>step:</em> When a clause executes, an update step for the iteraation variable v.
<li><em>pred:</em> Cuando se ejecuta una cláusula , una ejecución de predicado para probar la salida del bucle.
<li><em>fini:</em> Si una cláusula provoca una salida de bucle, una ejecución del finalizador para calcular el valor devuelto del bucle.
</ul> La secuencia completa de todos los tipos de variable de iteración, en orden de cláusulas, se notará como (V...). Los propios valores serán (v...). Cuando hablamos de "listas de parámetros", normalmente nos referiremos a tipos, pero en algunos contextos (que describen la ejecución), las listas serán de valores reales.
Algunas de estas partes de cláusulas se pueden omitir según ciertas reglas y se proporciona un comportamiento predeterminado útil en este caso. Consulte a continuación para obtener una descripción detallada.
<Em>Parameters optional everywhere:</em> Each clause function is allowed but not required to accept a parameter for each iteraation variable v. Como excepción, las funciones init no pueden tomar ningún v parámetro, ya que esos valores aún no se calculan cuando se ejecutan las funciones init. Cualquier función de cláusula puede dejar de tomar cualquier subsecuencia final de los parámetros que tenga derecho a tomar. De hecho, cualquier función de cláusula no puede aceptar ningún argumento.
<em>Loop parameters:</em> A clause function may take all the iteraation variable values iteraation iteración a los que tiene derecho, en cuyo caso también puede tomar más parámetros finales. Estos valores adicionales se denominan <parámetros< de bucle em>/em>, con sus tipos y valores notados como (A...) y (a...). Se convierten en los parámetros del controlador de bucle resultante, que se suministrarán cada vez que se ejecute el bucle. (Dado que las funciones init no aceptan variables vde iteración, ningún parámetro de una función init es automáticamente un parámetro ade bucle ). Al igual que con las variables de iteración, se permiten funciones de cláusula pero no son necesarias para aceptar parámetros de bucle. Estos parámetros de bucle actúan como valores invariables de bucle visibles en todo el bucle.
<Em>Parameters visibles everywhere:</em> Each non-init clause function is allowed to observe the entire loop state, because iteración can be passed the full list (v... a...) of current iteraation variable values and incoming loop parameters. Las funciones init pueden observar el estado inicial del bucle previo, con el formato (a...). La mayoría de las funciones de cláusula no necesitarán toda esta información, pero se conectarán formalmente a ella como si fuera .#dropArguments "astar"> Más concretamente, usaremos la notación (V*) para expresar un prefijo arbitrario de una secuencia (V...) completa (y del mismo modo para (v*), (A*), (a*)). En esa notación, la forma general de una lista de parámetros de función init es (A*)y la forma general de una lista de parámetros de función no init es (V*) o (V... A*).
<em>Checking clause structure:</em> Given a set of clauses, there is a number of checks and adjustments performed to connect all the parts of the loop. Se detallan en los pasos siguientes. En estos pasos, cada aparición de la palabra "must" corresponde a un lugar en el que IllegalArgumentException se producirá si las entradas no cumplen la restricción necesaria en el combinador de bucles.
<em>Secuencias idénticas de forma eficaz:</em> "effid"> Una lista A de parámetros se define para que sea <eficazmente>idéntica</em> a otra lista B de parámetros si A y B son idénticas, o si A es más corta y es idéntica con un prefijo adecuado de B. Al hablar de un conjunto desordenado de listas de parámetros, decimos que el conjunto es "eficazmente idéntico" como un todo si el conjunto contiene una lista más larga, y todos los miembros del conjunto son eficazmente idénticos a esa lista más larga. Por ejemplo, cualquier conjunto de secuencias de tipo del formulario (V*) es eficazmente idéntico y el mismo es true si se agregan más secuencias del formulario (V... A*) .
<em>Paso 0: Determinar la estructura de cláusulas.</em><ol type="a"><li>La matriz de cláusulas (de tipo MethodHandle[][]) debe no sernull y contener al menos un elemento.
<li>La matriz de cláusulas puede no contener nulls o sub arrays más de cuatro elementos.
<las cláusulas li>más cortas que cuatro elementos se tratan como si fueran rellenados por null elementos de longitud cuatro. El relleno tiene lugar anexando elementos a la matriz.
<se ignoran las cláusulas li>con todas las nulls.
<li>Cada cláusula se trata como una tupla de cuatro funciones, denominada "init", "step", "pred" y "fini".
</ol>
<em>Paso 1A: Determinación de los tipos (V...)de variable de iteración .</em><ol type="a"><li>El tipo de variable de iteración para cada cláusula se determina mediante los tipos de valor devuelto init y step de la cláusula.
<li>Si se omiten ambas funciones, no hay ninguna variable de iteración para la cláusula correspondiente (void se usa como tipo para indicarlo). Si se omite uno de ellos, el tipo de valor devuelto del otro define el tipo de variable de iteración de la cláusula. Si se proporcionan ambos, el tipo de valor devuelto común (deben ser idénticos) define el tipo de variable de iteración de la cláusula.
<li>Form the list of return types (in clause order), omite todas las apariciones de void.
<li>Esta lista de tipos se denomina "tipos de variable de iteración" ((V...)).
</ol>
<em>Paso 1B: Determinación de parámetros de (A...)bucle .</em><ul li>><Examine y recopile listas de parámetros de función init (que son del formato ).(A*)
<li>Examine y recopile los sufijos de las listas de parámetros step, pred y fini, después de quitar los tipos de variable de iteración. (Deben tener la forma (V... A*); recopilar solo las (A*) partes). <li>No recopile sufijos de listas de parámetros step, pred y fini que no comiencen con todos los tipos de variable de iteración. (Estos tipos se comprobarán en el paso 2, junto con todos los tipos de función de cláusula). <li>Las funciones de cláusula omitidas se omiten. (De forma equivalente, se considera que tienen listas de parámetros vacías). <li>Todas las listas de parámetros recopilados deben ser eficazmente idénticas.
<li>La lista de parámetros más larga (que es necesariamente única) se denomina "lista de parámetros externos" ((A...)).
<li>Si no hay ninguna lista de parámetros de este tipo, se toma la lista de parámetros externos para que sea la secuencia vacía.
<li>La lista combinada que consta de tipos de variables de iteración seguidos de los tipos de parámetros externos se denomina "lista de parámetros internos".
</ul>
<em>Paso 1C: Determinación del tipo de valor devuelto del bucle.</em><ol type="a"><li>Examine fini function return types, ignoreing omitted fini functions.
<li>Si no hay funciones fini, el tipo de valor devuelto del bucle es void.
<li>De lo contrario, el tipo R de valor devuelto común de las funciones fini (sus tipos devueltos deben ser idénticos) define el tipo de valor devuelto de bucle.
</ol>
<em>Paso 1D: Comprobar otros tipos.</em><ol type="a"><li>Debe haber al menos una función premitida no omitida.
<li>Todas las funciones predemitidas no omitidas deben tener un boolean tipo de valor devuelto.
</ol>
<em>Paso 2: Determinar listas de parámetros.</em><ol type="a"><li>La lista de parámetros del controlador de bucle resultante será la lista (A...)de parámetros externos .
<li>La lista de parámetros de las funciones init se ajustará a la lista de parámetros externos. (Tenga en cuenta que sus listas de parámetros ya son exactamente idénticas a esta lista). <li>La lista de parámetros de cada función no omitida, no init (paso, pred y fini) debe ser eficazmente idéntica a la lista (V... A...)de parámetros internos .
</ol>
<em>Paso 3: Rellenar funciones omitidas.</em><ol type="a"><li>Si se omite una función init, use un valor predeterminado #empty para el tipo de variable de iteración de la cláusula.
<li>Si se omite una función de paso, use una función de identidad #identity del tipo de variable de iteración de la cláusula; inserte parámetros de argumento quitados antes del parámetro de función de identidad para lasvoid variables de no iteración de las cláusulas anteriores. (Esto convertirá la variable de bucle en una variable de bucle local). <li>Si se omite una función anterior, use una función constante true . (Esto mantendrá el bucle en marcha, en lo que respecta a esta cláusula. Tenga en cuenta que, en tales casos, la función fini correspondiente no es accesible). <li>Si se omite una función fini, use un #empty valor predeterminado para el tipo de valor devuelto del bucle.
</ol>
<em>Paso 4: Rellene los tipos de parámetros que faltan.</em><ol type="a"><li>En este momento, cada lista de parámetros de función de inicialización es eficazmente idéntica a la lista (A...)de parámetros externos, pero algunas listas pueden ser más cortas. Para cada función de inicialización con una lista de parámetros corta, rellene el final de la lista.
<li>En este momento, cada lista de parámetros de función no init es eficazmente idéntica a la lista (V... A...)de parámetros internos, pero algunas listas pueden ser más cortas. Para cada función que no sea init con una lista de parámetros corta, rellene el final de la lista.
<las listas de argumentos li>se rellenan mediante #dropArgumentsToMatch(MethodHandle, int, List, int) quitando argumentos finales sin usar.
</ol>
<observaciones>finales.</em><ol type="a"><li>Después de estos pasos, todas las cláusulas se han ajustado proporcionando funciones y argumentos omitidos.
<li>Todas las funciones init tienen una lista (A...)de tipos de parámetro común, que también tendrá el identificador de bucle final.
<li>Todas las funciones fini tienen un tipo Rde valor devuelto común , que también tendrá el controlador de bucle final.
<li>Todas las funciones que no son de inicialización tienen una lista (V... A...)de tipos de parámetro común , de variables V de iteración (novoid) seguidas de parámetros de bucle.
<li>Cada par de funciones init y step acepta en su tipo Vde valor devuelto .
<li>Cada función no init podrá observar los valores (v...) actuales de todas las variables de iteración.
<li>Cada función podrá observar los valores (a...) entrantes de todos los parámetros de bucle.
</ol>
<Ejemplo em>.</em> Como consecuencia del paso 1A anterior, el loop combinador tiene la siguiente propiedad: <ul><li>Given N clause Cn = {null, Sn, Pn} con n = 1..N.
<li>Supongamos que los identificadores Pn de predicado son null o no tienen parámetros. (Solo uno Pn tiene que ser distintonull).) <li>Supongamos que los identificadores de paso tienen firmas , para algunas constantes (B1..BX)RnSnX>=N.
<li>Imagine que Q es el recuento de tipos no nulos Rny (V1...VQ) es la secuencia de esos tipos.
<li>Debe ser que Vn == Bn para n = 1..min(X,Q).
<li>Los tipos Vn de parámetro se interpretarán como elementos (V...)de estado local de bucle .
<li>Cualquier tipo BQ+1..BX restante (si Q<X) determinará los tipos (A...)de parámetros del controlador de bucle resultante.
</ul> En este ejemplo, los parámetros de identificador de (A...) bucle se derivaron de las funciones de paso, lo que es natural si la mayoría del cálculo del bucle se produce en los pasos. En algunos bucles, la carga del cálculo puede ser más pesada en las funciones pred, por lo que es posible que las funciones pred necesiten aceptar los valores del parámetro de bucle. Para los bucles con lógica de salida compleja, es posible que las funciones fini necesiten aceptar parámetros de bucle y, del mismo modo, para bucles con lógica de entrada compleja, donde las funciones init necesitarán los parámetros adicionales. Por estos motivos, las reglas para determinar estos parámetros son lo más simétricas posible, en todas las partes de la cláusula. En general, los parámetros de bucle funcionan como valores invariables comunes en todo el bucle, mientras que las variables de iteración funcionan como valores de variante comunes o (si no hay ninguna función de paso) como temporales invariables de bucle interno.
<Ejecución de bucle em>.</em><ol type="a"><li>Cuando se llama al bucle, los valores de entrada del bucle se guardan en variables locales, para pasarse a cada función de cláusula. Estas variables locales son invariables de bucle.
<li>Cada función init se ejecuta en orden de cláusula (pasando los argumentos (a...)externos ) y los valores que novoid son se guardan (como las variables (v...)de iteración ) en variables locales. Estos locales serán variables de bucle (a menos que sus pasos se comporten como funciones de identidad, como se indicó anteriormente).
<li>Todas las ejecuciones de función (excepto las funciones init) se pasarán a la lista de parámetros internos, que consta de los valores (v...) de novoid iteración (en orden de cláusula) y, a continuación, las entradas (a...) del bucle (en orden de argumento).
<li>Las funciones paso y pred se ejecutan, en orden de cláusulas (paso antes del pred), hasta que una función pred devuelve false.
<li>El resultado que novoid es de una llamada de función de paso se usa para actualizar el valor correspondiente en la secuencia (v...) de variables de bucle. El valor actualizado es visible inmediatamente para todas las llamadas de función posteriores.
<li>Si una función anterior devuelve false, se llama a la función fini correspondiente y el valor resultante (de tipo R) se devuelve del bucle como un todo.
<li>Si todas las funciones pred siempre devuelven true, nunca se invoca ninguna función fini y el bucle no puede salir excepto si se produce una excepción.
</ol>
<sugerencias>de uso.</em><ul><li>Aunque cada función de paso recibirá los valores actuales de <em all</em>> las variables de bucle, a veces una función de paso solo necesita observar el valor actual de su propia variable. En ese caso, la función step puede necesitar #dropArguments quitar explícitamente todas las variables de bucle anteriores. Esto requerirá mencionar sus tipos, en una expresión como dropArguments(step, 0, V0.class, ...).
<Las variables li>Loop no son necesarias para variar; pueden ser invariantes de bucle. Una cláusula puede crear un bucle invariable mediante una función init adecuada sin paso, pred o función fini. Esto puede ser útil para "conectar" un argumento de bucle entrante en el paso o la función pred de una variable de bucle adyacente.
<li>Si algunas de las funciones de cláusula son métodos virtuales en una instancia, la propia instancia se puede colocar convenientemente en un bucle invariable inicial "variable", utilizando una cláusula inicial como new MethodHandle[]{identity(ObjType.class)}. En ese caso, la referencia de instancia será el primer valor de la variable de iteración y será fácil usar métodos virtuales como elementos de cláusula, ya que todos ellos tomarán una referencia de instancia inicial que coincida con ese valor.
</ul>
Este es el pseudocódigo para el identificador de bucle resultante. Como se indicó anteriormente, V y v representan los tipos y valores de las variables de bucle; A y a representan argumentos pasados al bucle entero; y R es el tipo de resultado común de todos los finalizadores, así como del bucle resultante.
<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> Tenga en cuenta que las listas (V...) de tipos de parámetro y (A...) se han expandido a su longitud completa, aunque las funciones de cláusulas individuales pueden dejar de tomarlas todas. Como se indicó anteriormente, los parámetros que faltan se rellenan como si fuera .#dropArgumentsToMatch(MethodHandle, int, List, int)
Agregado en 9.
Java documentación para java.lang.invoke.MethodHandles.loop(java.lang.invoke.MethodHandle[]...).
Las partes de esta página son modificaciones basadas en el trabajo creado y compartido por el Android y se usan según los términos descritos en creative Creative Commons 2.5 Attribution License.