MethodHandles.Loop(MethodHandle[][]) Metodo
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Costruisce un handle di metodo che rappresenta un ciclo con diverse variabili di ciclo aggiornate e controllate in ogni iterazione.
[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
Parametri
- clauses
- MethodHandle[][]
una matrice di matrici (4 tuple) di MethodHandles aderendo alle regole descritte in precedenza.
Valori restituiti
handle di metodo che incorpora il comportamento di ciclo come definito dagli argomenti.
- Attributi
Commenti
Costruisce un handle di metodo che rappresenta un ciclo con diverse variabili di ciclo aggiornate e controllate in ogni iterazione. Al termine del ciclo a causa di uno dei predicati, viene eseguito un finalizzatore corrispondente e restituisce il risultato del ciclo, ovvero il valore restituito dell'handle risultante.
In modo intuitivo, ogni ciclo è formato da una o più "clausole", ognuna delle quali specifica una variabile< di iterazione locale<>/em> e/o un'uscita del ciclo. Ogni iterazione del ciclo esegue ogni clausola in ordine. Una clausola può facoltativamente aggiornare la variabile di iterazione; può anche eseguire facoltativamente un test e un'uscita del ciclo condizionale. Per esprimere questa logica in termini di handle di metodo, ogni clausola specifica fino a quattro azioni indipendenti:ul>li em init:</em> Prima dell'esecuzione del ciclo, l'inizializzazione di una variabile v di iterazione di tipo V.>><<<
<li><em>step:</em> Quando viene eseguita una clausola , un passaggio di aggiornamento per la variabile vdi iterazione .
<li><em>pred:</em> Quando viene eseguita una clausola , un'esecuzione del predicato per testare l'uscita del ciclo.
<li><em>fini:</em> Se una clausola determina l'uscita di un ciclo, un'esecuzione del finalizzatore per calcolare il valore restituito del ciclo.
</ul> La sequenza completa di tutti i tipi di variabile di iterazione, nell'ordine della clausola, verrà notata come (V...). I valori stessi saranno (v...). Quando si parla di "elenchi di parametri", in genere si farà riferimento a tipi, ma in alcuni contesti (che descrivono l'esecuzione) gli elenchi saranno di valori effettivi.
Alcune di queste parti di clausola possono essere omesse in base a determinate regole e in questo caso viene fornito un comportamento predefinito utile. Per una descrizione dettagliata, vedere di seguito.
<la funzione della clausola em>Parameters facoltativa everywhere:</em> Each è consentita ma non è necessaria per accettare un parametro per ogni variabile vdi iterazione . Ad eccezione, le funzioni init non possono accettare parametri v , perché tali valori non vengono ancora calcolati quando vengono eseguite le funzioni init. Qualsiasi funzione di clausola può non accettare qualsiasi sottosequenza finale dei parametri che ha diritto di accettare. In effetti, qualsiasi funzione di clausola potrebbe non accettare argomenti.
<la funzione di clausola em>Loop parameters:</em> A può accettare tutti i valori delle variabili di iterazione a cui ha diritto, nel qual caso può anche accettare più parametri finali. Tali valori aggiuntivi sono denominati <<parametri ciclo em/em>>, con i relativi tipi e valori notati come (A...) e (a...). Questi diventano i parametri dell'handle di ciclo risultante, da fornire ogni volta che viene eseguito il ciclo. Poiché le funzioni init non accettano variabili vdi iterazione , qualsiasi parametro per una funzione init è automaticamente un parametro adi ciclo . Come per le variabili di iterazione, le funzioni della clausola sono consentite ma non necessarie per accettare i parametri del ciclo. Questi parametri del ciclo fungono da valori invarianti di ciclo visibili nell'intero ciclo.
<em>Parameters visible everywhere:</em> Each non-init clause function is permitted to observe the entire loop state, because it can be pass the full list (v... a...) of current iteration variable values and incoming loop parameters. Le funzioni init possono osservare lo stato iniziale del pre-ciclo, nel formato (a...). La maggior parte delle funzioni delle clausole non richiederà tutte queste informazioni, ma sarà formalmente connessa ad essa come se fosse #dropArguments. "astar"> in particolare, useremo la notazione (V*) per esprimere un prefisso arbitrario di una sequenza (V...) completa (e allo stesso modo per (v*), , (A*)(a*)). In tale notazione, la forma generale di un elenco di parametri di funzione init è e la forma generale di un elenco di parametri di funzione non init è (A*)(V*) o (V... A*).
<em>Checking clause structure:</em> Dato un set di clausole, è presente una serie di controlli e regolazioni eseguiti per connettere tutte le parti del ciclo. Vengono evidenziati in dettaglio nei passaggi seguenti. In questi passaggi, ogni occorrenza della parola "must" corrisponde a una posizione in cui IllegalArgumentException verrà generata se il vincolo richiesto non viene soddisfatto dagli input al combinatore di cicli.
<em>Effettivamente identico sequences:</em> "effid"> Un elenco A di parametri viene definito come <em>in modo efficace identico</em> a un altro elenco B di parametri se A e B sono identici o se A è più breve ed è identico con un prefisso corretto di B. Quando si parla di un set non ordinato di elenchi di parametri, si dice che il set sia "effettivamente identico" nel suo complesso se il set contiene un elenco più lungo e tutti i membri del set sono effettivamente identici a tale elenco più lungo. Ad esempio, qualsiasi set di sequenze di tipi del modulo (V*) è effettivamente identico e lo stesso vale se vengono aggiunte più sequenze del modulo (V... A*) .
<em>Passaggio 0: Determinare la struttura della clausola.</em><ol type="a"><li>La matrice di clausole (di tipo MethodHandle[][]) deve essere non-null e contenere almeno un elemento.
<li>La matrice di clausole non può contenere nullmatrici secondarie o più lunghe di quattro elementi.
<Le clausole li>più brevi di quattro elementi vengono considerate come se fossero riempite da null elementi di lunghezza quattro. La spaziatura interna viene eseguita aggiungendo elementi alla matrice.
<Le clausole li>con tutte le nullclausole vengono ignorate.
<la clausola li>Each viene considerata come una tupla di quattro funzioni, denominata "init", "step", "pred" e "fini".
</ol>
<em>Passaggio 1A: Determinare i tipi di (V...)variabile di iterazione .</em><ol type="a"><li>Il tipo di variabile di iterazione per ogni clausola viene determinato usando i tipi restituiti init e step della clausola.
<li>Se entrambe le funzioni vengono omesse, non esiste alcuna variabile di iterazione per la clausola corrispondente (void viene usata come tipo per indicare che). Se uno di essi viene omesso, il tipo restituito dell'altro definisce il tipo di variabile di iterazione della clausola. Se vengono specificati entrambi, il tipo restituito comune (deve essere identico) definisce il tipo di variabile di iterazione della clausola.
<li>Form l'elenco dei tipi restituiti (in ordine di clausola), omettendo tutte le occorrenze di void.
<li>Questo elenco di tipi è denominato "tipi di variabile di iterazione" ((V...)).
</ol>
<em>Passaggio 1B: Determinare i parametri del (A...)ciclo .</em><ul><li>Examine e collect init function parameter lists (che sono del formato (A*)).
<li>Esaminare e raccogliere i suffissi degli elenchi di parametri step, pred e fini, dopo aver rimosso i tipi di variabile di iterazione. (Devono avere il formato (V... A*); raccogliere solo le (A*) parti. <li>Non raccogliere suffissi da elenchi di parametri step, pred e fini che non iniziano con tutti i tipi di variabile di iterazione. Questi tipi verranno controllati nel passaggio 2, insieme a tutti i tipi di funzione della clausola. <li>Le funzioni delle clausole omesse vengono ignorate. (In modo equivalente, vengono considerati con elenchi di parametri vuoti. <li>Tutti gli elenchi di parametri raccolti devono essere effettivamente identici.
<li>L'elenco di parametri più lungo (che è necessariamente univoco) è denominato "elenco di parametri esterni" ((A...)).
<li>Se non esiste un elenco di parametri di questo tipo, l'elenco di parametri esterni viene considerato come la sequenza vuota.
<li>L'elenco combinato costituito da tipi di variabile di iterazione seguiti dai tipi di parametri esterni è denominato "elenco di parametri interni".
</ul>
<em>Passaggio 1C: Determinare il tipo restituito del ciclo.</em><ol type="a"><li>Esaminare i tipi restituiti della funzione fini, ignorando le funzioni fini omesse.
<li>Se non sono presenti funzioni fini, il tipo restituito del ciclo è void.
<li>In caso contrario, il tipo R restituito comune delle funzioni fini (i relativi tipi restituiti devono essere identici) definisce il tipo restituito del ciclo.
</ol>
<em>Passaggio 1D: Controllare altri tipi.</em><ol type="a"><li>Deve essere presente almeno una funzione pred non omessa.
<li>Ogni funzione pred non omessa deve avere un boolean tipo restituito.
</ol>
<em>Passaggio 2: Determinare gli elenchi di parametri.</em><ol type="a"><li>L'elenco di parametri per l'handle di ciclo risultante sarà l'elenco (A...)di parametri esterni .
<li>L'elenco dei parametri per le funzioni init verrà modificato nell'elenco di parametri esterni. Si noti che i relativi elenchi di parametri sono già identici a questo elenco. <li>L'elenco di parametri per ogni funzione non omessa, non init (step, pred e fini) deve essere effettivamente identica all'elenco (V... A...)di parametri interni .
</ol>
<em>Passaggio 3: Compilare le funzioni omesse.</em><ol type="a"><li>Se viene omessa una funzione init, usare un valore predefinito #empty per il tipo di variabile di iterazione della clausola.
<li>Se viene omessa una funzione step, usare una funzione identity #identity del tipo di variabile di iterazione della clausola; inserire parametri di argomento eliminati prima del parametro della funzione Identity per levoid variabili non iterazioni delle clausole precedenti. Questa operazione trasformerà la variabile di ciclo in un ciclo locale invariante. <li>Se una funzione pred viene omessa, usare una funzione costante true . In questo modo il ciclo verrà mantenuto, per quanto riguarda questa clausola. Si noti che in questi casi la funzione fini corrispondente non è raggiungibile. <li>Se una funzione fini viene omessa, usare un valore predefinito #empty per il tipo restituito del ciclo.
</ol>
<em>Passaggio 4: Compilare i tipi di parametro mancanti.</em><ol type="a"><li>A questo punto, ogni elenco di parametri di funzione init è effettivamente identico all'elenco (A...)di parametri esterni, ma alcuni elenchi potrebbero essere più brevi. Per ogni funzione init con un breve elenco di parametri, chiudere la fine dell'elenco.
<li>A questo punto, ogni elenco di parametri di funzione non init è effettivamente identico all'elenco (V... A...)di parametri interni, ma alcuni elenchi possono essere più brevi. Per ogni funzione non init con un elenco di parametri brevi, chiudere la fine dell'elenco.
<gli elenchi di argomenti li>vengono riempiti da #dropArgumentsToMatch(MethodHandle, int, List, int) eliminando gli argomenti finali inutilizzati.
</ol>
<osservazioni>finali.</em><ol type="a"><li>Dopo questi passaggi, tutte le clausole sono state modificate fornendo funzioni e argomenti omessi.
<li>Tutte le funzioni init hanno un elenco (A...)di tipi di parametro comune , che l'handle di ciclo finale avrà anche.
<li>Tutte le funzioni fini hanno un tipo Rrestituito comune , che l'handle di ciclo finale avrà anche.
<li>Tutte le funzioni non init hanno un elenco (V... A...)di tipi di parametro comune , di variabili V di iterazione (nonvoid) seguite dai parametri del ciclo.
<li>Ogni coppia di funzioni init e step accetta nel tipo Vrestituito .
<li>Ogni funzione non init sarà in grado di osservare i valori (v...) correnti di tutte le variabili di iterazione.
<li>Ogni funzione sarà in grado di osservare i valori (a...) in ingresso di tutti i parametri del ciclo.
</ol>
<esempio em>.</em> Come conseguenza del passaggio 1A precedente, il loop combinatore ha la proprietà seguente: <ul><li>Given N clauses Cn = {null, Sn, Pn} con n = 1..N.
<li>Si supponga che gli handle Pn di predicato siano null o non abbiano parametri. (Solo uno Pn deve essere diversonull da).) <li>Si supponga che gli handle Sn di passaggio abbiano firme (B1..BX)Rn, per alcune costanti X>=N.
<li>Si supponga che Q sia il conteggio dei tipi Rnnon void ed (V1...VQ) è la sequenza di tali tipi.
<li>Deve essere che Vn == Bn per n = 1..min(X,Q).
<li>I tipi di Vn parametro verranno interpretati come elementi (V...)dello stato locale del ciclo .
<li>Tutti i tipi BQ+1..BX rimanenti (se Q<X) determineranno i tipi di (A...)parametro dell'handle di ciclo risultante.
</ul> In questo esempio, i (A...) parametri di handle del ciclo sono stati derivati dalle funzioni di passaggio, che è naturale se la maggior parte del calcolo del ciclo avviene nei passaggi. Per alcuni cicli, il carico di calcolo potrebbe essere più pesante nelle funzioni pred e pertanto le funzioni predefinite potrebbero dover accettare i valori dei parametri del ciclo. Per i cicli con logica di uscita complessa, le funzioni fini potrebbero dover accettare parametri di ciclo e, analogamente, per i cicli con logica di immissione complessa, in cui le funzioni init richiederanno i parametri aggiuntivi. Per questi motivi, le regole per determinare questi parametri sono il più simmetrico possibile, in tutte le parti della clausola. In generale, i parametri del ciclo funzionano come valori invarianti comuni nell'intero ciclo, mentre le variabili di iterazione funzionano come valori varianti comuni o (se non esiste alcuna funzione di passaggio) come temporaneamente invarianti del ciclo interno.
<esecuzione del ciclo em>.</em><ol type="a"><li>Quando viene chiamato il ciclo, i valori di input del ciclo vengono salvati nelle variabili locali, da passare a ogni funzione di clausola. Queste variabili locali sono invarianti del ciclo.
<li>Ogni funzione init viene eseguita in ordine di clausola (passando gli argomenti (a...)esterni ) e i valori nonvoid vengono salvati (come variabili (v...)di iterazione ) in variabili locali. Queste variabili locali saranno variabili a ciclo variabile (a meno che i relativi passaggi non si comportino come funzioni di identità, come indicato in precedenza).
<li>Tutte le esecuzioni di funzione (ad eccezione delle funzioni init) verranno passate all'elenco di parametri interni, costituito dai valori (v...) divoid non iterazione (nell'ordine delle clausole) e quindi dagli (a...) input del ciclo (in ordine di argomento).
<li>Le funzioni step e pred vengono quindi eseguite, in ordine di clausola (passaggio prima della pred), fino a quando una funzione pred non restituisce false.
<li>Il risultato non-void da una chiamata di funzione step viene usato per aggiornare il valore corrispondente nella sequenza (v...) di variabili del ciclo. Il valore aggiornato è immediatamente visibile a tutte le chiamate di funzione successive.
<li>Se una funzione pred restituisce false, viene chiamata la funzione fini corrispondente e il valore risultante (di tipo R) viene restituito dal ciclo nel suo complesso.
<li>Se tutte le funzioni predefinite restituiscono sempre true, non viene mai richiamata alcuna funzione fini e il ciclo non può uscire tranne generando un'eccezione.
</ol>
<em>Suggerimenti sull'utilizzo.</em><ul><li>Anche se ogni funzione di passaggio riceverà i valori correnti di <em>all</em> le variabili del ciclo, a volte una funzione di passaggio deve solo osservare il valore corrente della propria variabile. In tal caso, la funzione step potrebbe dover #dropArguments eliminare in modo esplicito tutte le variabili del ciclo precedente. Ciò richiederà la menzione dei relativi tipi, in un'espressione come dropArguments(step, 0, V0.class, ...).
<Le variabili del ciclo li>non sono necessarie per variare; possono essere invarianti del ciclo. Una clausola può creare un ciclo invariante da una funzione init appropriata senza alcuna funzione step, pred o fini. Ciò può essere utile per "collegare" un argomento del ciclo in ingresso nel passaggio o nella funzione pred di una variabile di ciclo adiacente.
<li>Se alcune funzioni della clausola sono metodi virtuali in un'istanza, l'istanza stessa può essere inserita facilmente in un ciclo invariante iniziale "variabile", usando una clausola iniziale come new MethodHandle[]{identity(ObjType.class)}. In tal caso, il riferimento all'istanza sarà il primo valore della variabile di iterazione e sarà facile usare i metodi virtuali come parti della clausola, poiché tutti accettano un riferimento all'istanza iniziale corrispondente a tale valore.
</ul>
Di seguito è riportato lo pseudocodice per l'handle di ciclo risultante. Come illustrato in precedenza, V e v rappresentano i tipi e i valori delle variabili A del ciclo e a rappresentano gli argomenti passati all'intero ciclo ed R è il tipo di risultato comune di tutti i finalizzatori e del ciclo risultante.
<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> Si noti che il tipo di parametro elenca (V...) ed (A...) è stato espanso fino alla lunghezza intera, anche se le singole funzioni della clausola potrebbero non essere necessarie. Come indicato in precedenza, i parametri mancanti vengono compilati come se fosse #dropArgumentsToMatch(MethodHandle, int, List, int).
Aggiunta in 9.
Documentazione java per java.lang.invoke.MethodHandles.loop(java.lang.invoke.MethodHandle[]...).
Le parti di questa pagina sono modifiche basate sul lavoro creato e condiviso dal progetto Open Source Android e usato in base ai termini descritti nella licenza Creative Commons 2.5 Attribuzione.