В репозитории 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, а не на ошибку в моем коде.
Разрешены строковые аргументы для ()
нижние индексы скобок , поскольку это отлично работает, если вы измените код для работы с ()
вместо ] {}
. (За исключением случаев, когда вы не можете вкладывать операции с индексами, что и является целью упражнения.)
Либо понимание того, что я делаю неправильно в своем коде, любые ограничения, которые делают то, что я делаю, невыполнимым, либо альтернативные реализации вложенных словарей будут оценены.