2012-08-02 11 views
6

Czy jest możliwe aby utworzyć otoki wokół funkcji, która ma dokładnie taką samą nazwę jak pierwotnej funkcji?Jak owinąć już istniejącej funkcji z nowej funkcji o tej samej nazwie

To byłoby bardzo przydatne w sytuacji, gdy użytkownik chce zrobić jakieś dodatkowe kontrole na zmiennych wejściowych, zanim zostaną one przekazane do wbudowanej funkcji How to interrupt MATLAB IDE when it hangs on displaying very large array?

+0

zgadzam odpowiedź zostanie zaksięgowana na drugim pytaniu (http://stackoverflow.com/questions/11779511/how-to-interrupt-matlab-ide-when-it-hangs-on-displaying-very-large- array) jest dobra dla tego pytania, ale ogólne pytanie ma lepszą odpowiedź - patrz poniżej. – jmetz

Odpowiedz

11

Właściwie alternatywnie Slayton na odpowiedź nie trzeba użyj openvar. Jeśli zdefiniujesz funkcję o tej samej nazwie co funkcja matlab, będzie ona cieniała tę funkcję (np. Zostanie wywołana).

Aby następnie uniknąć rekurencyjnego wywoływania własnej funkcji, możesz wywołać oryginalną funkcję z poziomu opakowania, używając builtin.

np.

outputs = builtin(funcname, inputs..); 

Prosty przykład, nazwany rand.m i na ścieżce Matlab:

function out = main(varargin) 
disp('Test wrapping rand... calling rand now...'); 
out = builtin('rand', varargin{:}); 

Uwaga, że to działa tylko dla funkcji, które są uznane przez builtin. Dla tych, którzy nie są, podejście slaytona jest prawdopodobnie konieczne.

+0

, ale jest tak wiele funkcji, które nie są "wbudowane" i chcę je wszystkie zawinąć! –

+0

@GuntherStruyf: dlaczego chcesz owinąć je wszystkie ... w szczególności te niewbudowane? – jmetz

+0

W pracy nasze instalacje matlab są tylko do odczytu, więc sama zmiana plików nie jest możliwa. I nie jest to wygodne, aby zawsze korzystać z funkcji "myfuninstead". zwłaszcza, gdy chodzi o poprawę domyślnego zachowania. Aplikacja świata rzeczywistego: [problem Daniela Kesslera] (http://stackoverflow.com/questions/11779511/how-to-interrupt-matlab-ide-when-it-hangs-on-displaying-very-large-array) –

3

Tak to jest możliwe, ale wymaga trochę włamania. Wymaga to kopiowania wokół niektórych uchwytów funkcji.

Na przykładzie podanym w pytaniu pokażę, jak zawinąć funkcję openvar w funkcji zdefiniowanej przez użytkownika, która sprawdza rozmiar zmiennej wejściowej, a następnie pozwala użytkownikowi anulować dowolną operację otwartą dla zmiennych, które są zbyt duże.

Dodatkowo, to powinno działać, gdy użytkownik kliknie dwukrotnie zmienną w panelu Obszar roboczy Matlab IDE.

Musimy zrobić trzy rzeczy.

  1. uzyskać uchwyt do pierwotnego openvar funkcji
  2. Zdefiniuj funkcję otoki, który wywołuje openvar
  3. Przekierowanie oryginalny openvar nazwę naszej nowej funkcji.

Przykład Funkcja

function openVarWrapper(x, vector) 

    maxVarSize = 10000; 
    %declare the global variable 
    persistent openVarHandle; 

    %if the variable is empty then make the link to the original openvar 
    if isempty(openVarHandle) 
     openVarHandle = @openvar; 
    end 

    %no variable name passed, call was to setup connection 
    if narargin==0 
     return; 
    end 


    %get a copy of the original variable to check its size 
    tmpVar = evalin('base', x);   

    %if the variable is big and the user doesn't click yes then return 
    if prod(size(tmpVar)) > maxVarSize 
     resp = questdlg(sprintf('Variable %s is very large, open anyway?', x)); 
     if ~strcmp(resp, 'Yes') 
      return; 
     end 
    end 

    if ischar(x) && ~isempty(openVarHandle); 
     openVarHandle(x); 
    end 
end 

Gdy funkcja ta jest zdefiniowana wówczas wystarczy wykonać skrypt

  • Czyści wszystkie zmienne o nazwach openvar
  • uruchomić skrypt openVarWrapper do Setup połączenie
  • wskaż oryginał openVar do openVarWrapper

przykładowy skrypt:

clear openvar; 
openVarWrapper; 
openvar = @openVarWrapper; 

Wreszcie, gdy chcemy wyczyścić wszystkiego się można po prostu zadzwonić:

clear openvar; 
+0

powinno być łatwiejsze uzyskanie uchwytu do funkcji zacienionej, tylko od dokładniejszej do ścieżki. Twoje rozwiązanie wymaga pewnej inicjalizacji (za każdym razem, gdy używasz 'clear all'). [Moje rozwiązanie] (http://stackoverflow.com/a/11781650/1162609) wymaga cd'ing do ścieżki iz powrotem, ale to wszystko jest hakerem. Nadal mam nadzieję, że ktoś wymyśli lepszy sposób: p –

Powiązane problemy