matlab subsref: {} со строковым аргументом не работает, почему?

В репозитории Mathworks File Exchange есть несколько реализаций класса хэша или словаря. Все, что я рассмотрел, использует перегрузку скобок для ссылок на ключи, например

d = Dict;
d('foo') = 'bar';
y = d('foo');

, что кажется разумным интерфейсом. Однако было бы предпочтительнее, если вы хотите легко иметь словари, которые содержат другие словари, использовать фигурные скобки {} вместо скобок, поскольку это позволяет вам обойти ограничение синтаксиса MATLAB (произвольное, как кажется). что несколько круглых скобок не разрешены, но разрешены несколько скобок, т.е.

t{1}{2}{3}  % is legal MATLAB
t(1)(2)(3)  % is not legal MATLAB

Так что, если вы хотите легко вкладывать словари в словари,

dict{'key1'}{'key2'}{'key3'}

как обычная идиома в Perl, и это возможно и часто полезно на других языках, включая Python, тогда, если вы не хотите использовать промежуточные переменные n-1 для извлечения словарной статьи на n слоев глубоко, это кажется хорошим выбором. И казалось бы, легко переписать класс subref и ] subsasgn , чтобы сделать то же самое для {} , как они ранее делали для () , и все должно работать.

За исключением того, что это не так, когда я пробую.

Вот мой код. (Я сократил его до минимума.Настоящий словарь здесь не реализован, каждый объект имеет один ключ и одно значение, но этого достаточно, чтобы продемонстрировать проблему.)

classdef TestBraces < handle

    properties
        % not a full hash table implementation, obviously
        key
        value
    end

    methods(Access = public)


        function val = subsref(obj, ref)
            % Re-implement dot referencing for methods.
            if strcmp(ref(1).type, '.')
                % User trying to access a method             
                % Methods access
                if ismember(ref(1).subs, methods(obj))
                    if length(ref) > 1
                        % Call with args
                        val = obj.(ref(1).subs)(ref(2).subs{:});
                    else
                        % No args
                        val = obj.(ref.subs);
                    end
                    return;
                end                
                % User trying to access something else.
                error(['Reference to non-existant property or method ''' ref.subs '''']);
            end
            switch ref.type
                case '()'
                    error('() indexing not supported.');
                case '{}'
                    theKey = ref.subs{1};
                    if isequal(obj.key, theKey)
                        val = obj.value;
                    else
                        error('key %s not found', theKey);
                    end
                otherwise
                    error('Should never happen')
            end
        end    

        function obj = subsasgn(obj, ref, value)
            %Dict/SUBSASGN  Subscript assignment for Dict objects.
            %
            %  See also: Dict
            %

            if ~strcmp(ref.type,'{}')
                error('() and dot indexing for assignment not supported.');
            end

            % Vectorized calls not supported
            if length(ref.subs) > 1
                error('Dict only supports storing key/value pairs one at a time.');
            end
            theKey = ref.subs{1};
            obj.key = theKey;
            obj.value = value;
        end % subsasgn        
    end     
end

Используя этот код, я могу назначить, как и ожидалось:

t = TestBraces;
t{'foo'} = 'bar'

(И ясно, что присвоение работают из вывода на дисплей по умолчанию для t .) Таким образом, подсистема работает правильно.

Но я не могу получить значение ( subsref не работает):

t{'foo'}
??? Error using ==> subsref
Too many output arguments.

Сообщение об ошибке не имеет смысла для меня, и точка останова в первой исполняемой строке моего Обработчик subsref никогда не выполняется, поэтому, по крайней мере, внешне это похоже на проблему MATLAB, а не на ошибку в моем коде.

Разрешены строковые аргументы для () нижние индексы скобок , поскольку это отлично работает, если вы измените код для работы с () вместо ] {} . (За исключением случаев, когда вы не можете вкладывать операции с индексами, что и является целью упражнения.)

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

5
задан jmhl 3 January 2012 в 14:26
поделиться