2014-04-11 6 views
25

E 'comune usare la parola chiave end come scorciatoia per accedere o estendere una matrice in Matlab, come inQuali sono le semantiche del 'fine' in Matlab?

>> x = [1,2,3]; 
>> x(1:end-1) 
ans = 
    1 2 
>> x(end+1) = 4 
x = 
    1 2 3 4 

Tuttavia, sono rimasto sorpreso di scoprire che il seguente funziona anche

>> x(1:min(5, end)) 
ans = 
    1 2 3 4 

I ho pensato che end potrebbe essere un modulo speciale, come :, che può essere dotato di un involucro speciale nelle operazioni di indicizzazione, quindi ho creato una classe per rilevare questo

classdef IndexDisplayer 
    methods 
    function subsref(self, s) 
     disp(s); 
    end 
    end 
end 

Si può vedere come : è speciale cased nel seguente esempio

>> a = IndexDisplayer; 
>> a(1:3) 
    type: '()' 
    subs: {[1 2 3]} 
>> a(:) 
    type: '()' 
    subs: {':'} 

Tuttavia, quando ho indice con end vedo solo

>> a(end) 
    type: '()' 
    subs: {[1]} 

Qui il end viene sostituito con un 1. Da dove viene questo 1? La mia prima risposta è stata che ogni end all'interno di un'espressione di indicizzazione x(end) sarebbe sostituita con una chiamata a length(x) così ho provato l'override length così

classdef IndexDisplayer 
    methods 
    function subsref(self, s) 
     disp(s); 
    end 
    function len = length(self) 
     len = 10; 
    end 
    end 
end 

tuttavia, che dà

>> a = IndexDisplayer; 
>> length(a) 
ans = 
    10 
>> a(end) 
    type: '()' 
    subs: {[1]} 

in modo che la teoria è fuori la finestra. Qualcuno può spiegare la semantica di end?

risposta

17

In primo luogo, penso che sia una specie di bug, o almeno una caratteristica inaspettata, che la sintassi x(1:min(5, end)) funzioni del tutto. Quando ero alla MathWorks, ricordo che qualcuno lo ha sottolineato, e alcuni sviluppatori hanno dovuto dedicare un po 'di tempo a capire cosa stava succedendo. Non sono sicuro che siano mai stati d'accordo sul fatto che fosse un problema o meno.

Per spiegare la semantica (prevista) di end: end è implementata come una funzione ind = end(obj, k, n). k è l'indice dell'espressione contenente end e n è il numero totale di indici nell'espressione.

Così, per esempio, quando si chiama a(1,end,1), k è 2, come il end è in discussione 2, e n è 3 in quanto vi sono 3 argomenti.

ind viene restituito come l'indice che può sostituire end nell'espressione.

È possibile sovraccaricare end per le proprie classi (nello stesso modo come si può sovraccaricare colon, size, subsref ecc).

di estendere il vostro esempio:

classdef IndexDisplayer 
    methods 
    function ind = end(self,k,n) 
     disp(k) 
     disp(n) 
     ind = builtin('end', self, k, n); 
    end 
    end 
end 

>> a = IndexDisplayer; 
>> a(1,end,1) 
2 
3 

Vedi here per ulteriori informazioni.

+0

Interessante, grazie. Suppongo che il valore predefinito 'end' per gli oggetti restituisca' 1'? Sarei interessato a scoprire come funziona nel caso di 'x (1: min (5, fine))'. Vai sull'albero delle chiamate finché non trovi un oggetto per cui è definita la funzione 'fine'? –

+0

Non sono sicuro di cosa stia succedendo esattamente con 'x (1: min (5, fine))', e non sono sicuro di poterlo scoprire definitivamente a meno che tu non abbia accesso ai componenti interni di MATLAB. Non è ovvio per me come sceglie quale funzione 'end' inviare a quando è in un'espressione come quella. Ad esempio, se ridefinisci 'min' come array,' end' sembra riferirsi alla fine dell'array 'min', non alla fine di' x', e non so spiegarne il motivo. Potrebbe essere necessario chiedere a MathWorks, anche se non sono sicuro che nessuno, tranne un paio di sviluppatori, sarebbe in grado di darti una spiegazione completa. –

+0

Se sei fortunato, @Edric potrebbe sentire questo batcall e spiegare le cose meglio di me ... –

4

Trovo anche questa una curiosità. Tuttavia, io uso spesso (sfruttare?) Questo comportamento per accorciare le affermazioni. Per esempio, in this answer, per ottenere tutte ma l'elemento esimo k (s) di un vettore, una soluzione pulita che si è verificato a me era,

vector(setdiff(1:end,k)) 

Questo end sostituisce una chiamata a numel(vector). Per uno scalare k, questa è un'alternativa a vector(1:end ~= k) o vector([1:k-1 k+1:end]). All'epoca sembrava perfettamente ragionevole, sebbene attirassi l'attenzione sulla stranezza di questo uso. È davvero una cattiva pratica? Forse, ma l'ho accettato per quello che vale e andare avanti.

Non offro nessuna idea di come funzioni o quali siano le regole, come Sam Roberts nella sua risposta, ma concettualmente, la vedo come una questione di contesto. Cioè, quando si verifica end, suppongo che valuti un indice (o indice di dimensione) per l'array con l'ambito più immediato, cercando "su" attraverso le istruzioni annidate per effettuare la determinazione. Non sono sicuro se questo è il testo giusto, ma sembra essere un modo utile per interpretare l'operazione di end.

Non sono ancora stato morso da questa interpretazione.

+0

Ho appena girovagato qui. Volevo solo indicarti [il commento di OP] (http://stackoverflow.com/questions/23016606/what-are-the-semantics-of-end-in-matlab#comment35248138_23017087) 3 giorni dopo il tuo post (solo nel caso lo avessi perso): questo è un comportamento ufficialmente non documentato. –

+1

@AndrasDeak L'ho visto grazie. Dovrei dire che userò solo una simile istruzione nel prompt dei comandi interattivo di MATLAB, NON quando scriverò funzioni o script che speri di usare in futuro. – chappjc

Problemi correlati