Подтвердить что ты не робот

MATLAB: методы переопределения таблицы()

НАСТРОЙКА Win7 64b, R2015b, 16 ГБ ОЗУ, CPU i7-2700

table() представляет собой основной класс Matlab, который также запечатан, поэтому я не могу подклассифицировать его.

Я хочу исправить некоторые методы этого класса и добавить новые. Например, table.disp() фундаментально нарушена, например. попробуйте NOT disp(table(rand(1e7,1))) или забудьте ; в окне команд. Переменная занимает всего ОЗУ 76 МБ, но дисплей небуферизирован, и он остановит вашу систему!

  • Могу ли я переопределить методы, такие как table.disp(), не записывая в matlabroot\toolbox\matlab\datatypes\@table?
  • Можно ли расширить класс таблицы с помощью нового метода в C:\MATLAB\@table\ismatrixlike.m? Почему я получаю

    ismatrixlike(table)
    Undefined function 'ismatrixlike' for input arguments of type 'table'. 
    

    Очевидно, я сделал

    addpath C:\MATLAB\
    rehash toolboxcache
    

    Я также пробовал clear all.

    Путь имеет (алфавитный) приоритет над matlabroot, но отсутствует определение класса table.m. Если я добавлю определение собственного класса на C:\MATLAB\@table, тогда я могу запустить свой новый метод (после clear all). Однако:

    >> methods(table)
    
    Methods for class table:
    
    classVarNames   ismatrixlike    table           varfun          
    convertColumn   renameVarNames  unstack      
    

    перечисляет только методы в новой папке \@table, хотя (некоторые из) старых методов все еще работают, например.

    size(table)
    

    Это частично решает проблему, так как теперь родная папка \@table\private больше недоступна, и поэтому многие собственные методы нарушены!

Почему я это делаю? Потому что я не хочу ждать еще 2 года до того, как будет зафиксирован table(). Я уже потерял целые дни, потому что просто забыл о ; в командном окне, и я не могу принудительно перезагрузить компьютер, если он запускает многопользовательские симуляции, но мне нужно дождаться завершения замены диска: (.

Приложение Больше контекста о disp(table(rand(1e7,1))). Это то, что происходит, когда я ударил его (и, к счастью, я достаточно быстро добрался до CTRL-C):

введите описание изображения здесь

Виной является строка 172 table.disp(), которая преобразует числовой массив в клетку (с дополнением тоже!):

[cells, err, isLeft] = sprintfc(f, x, b);
4b9b3361

Ответ 1

После экспериментов с несколькими альтернативами я принял решение, которое наименее затрудняет реализацию Matlab native @table, и оно легко удаляется, если все идет не так.

Решение:

  • скопируйте всю папку @table, т.е. fullfile(matlabroot,'toolbox','matlab','datatypes','@table'), в пункт назначения, который поступает в алфавитном порядке до папки @table (см. Приоритет класса и путь MATLAB) и на котором у вас есть права на запись.

    Я выбрал пункт назначения fullfile(matlabroot,'toolbox','local','myfiles'), так как мне не нужно беспокоиться о кросс-совместимости ОС, т.е. matlabroot позаботится об этом для меня.

  • вставьте в место назначения всю вашу папку @table с помощью новых, перегруженных и переопределяющих методов.

  • добавить место назначения в путь matlab.

Эффекты, за и против:

  • Нативный @table класс/методы теперь затенены, попробуйте, например. which table -all. Однако этот эффект достаточно ясен, легко обнаруживается и легко удаляется (удаляет удаление и удаляет путь);
  • Нет странных конфликтов между нативными @table (теперь затененными) и новыми @table;
  • Все методы, новые и старые, видны, попробуйте methods(table);
  • Доступны приватные методы таблицы...
  • ... но вы вынуждены использовать их.
  • Предоставление новых методов (пользовательских) для частных требует большего обслуживания и прямой обработки конфликтов версий в реализациях таблиц.
  • Вам нужны права на запись в некоторых подходящих местах назначения.

Для интересующихся деталями вы можете изучить https://github.com/okomarov/tableutils. В частности, install_tableutils (readme может не обновляться).

Ответ 2

Для меня работает следующее:

  • Определите измененную функцию disp, скажем disp_modified.m, следующим образом и поместите ее в свой путь:

    function disp_modified(t)
    if istable(t)
        %// Do whatever you want to display tables
        builtin('disp', '''disp'' function intercepted!')
    else
        %// For non-tables, call `disp` normally
        builtin('disp', t)
    end
    
  • Определите disp как дескриптор функции для модифицированной функции (вы можете сделать это в startup.m, чтобы всегда иметь его по умолчанию):

    disp = @disp_modified;
    

После этого в окне команд я получаю

>> disp(1:5)
     1     2     3     4     5
>> disp({1 2 3 'bb'})
    [1]    [2]    [3]    'bb'
>> disp(table(rand(1e3,1)))
'disp' function intercepted!

Ответ 3

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

Некоторые вопросы, которые вы могли бы рассмотреть (и, возможно, уточнить), были бы следующими: Как вы собираетесь использовать новый класс? Вы хотите заменить все существующие таблицы? Вы хотите использовать его вместо аргумента класса таблицы? Или вы хотите изменить таблицу, чтобы каждое использование исходного класса таблицы в вашей среде использовало новый класс.

Если вам просто нужна новая улучшенная таблица для вашего использования, вы можете рассмотреть возможность инкапсуляции исходного класса таблицы в новый класс. Например, MyTable, делегируйте все методы, которые вам не нужны, в исходные методы таблицы, замените методы, которые вы хотели бы улучшить или добавить новые.

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