A Hash
имеет Str
клавиш.Любой ключ, который не является Str
, будет приведен к одному до сохранения значения под этим строковым ключом.{}
создает пустой Hash
.
Это поведение можно изменить, указав аргументы типа Hash
.Например, у Hash[Int]
все еще есть строковый ключ с автоматическим приведением, но он может хранить только значения Int
(так же, как Array[Int]
может хранить только значения Int
).Также можно передать аргумент второго типа, чтобы выбрать тип ключа.Это создает то, что часто называют «хэшем объекта», и в нем хранятся точные ключи, предоставленные в индексаторе.Таким образом, Hash[Mu,Any]
- это хеш с неограниченными значениями и ключом Any
(почти все типы подпадают под Any
, за исключением Junction
)..WHICH
ключа используется для хеширования.
В большинстве случаев не создаются хэши объектов с использованием Hash[TValue,TKey]
, а вместо этого используется синтаксис объявления;например, я мог бы представить ребра в DAG, используя что-то вроде has Array %!edges-from{Mu}
.Существует также способ создания хеша анонимного объекта, :{}
, который вы наблюдаете в этом примере.
Итак, какая разница?Здесь:
$seen-numbers{$n} = True;
$n
будет сохранен как Int
, его .WHICH
используется для хеширования для получения поиска O (1).Если бы мы просто использовали {}
вместо этого, мы бы принуждали Int
к ключу Str
.Это различие становится важным здесь:
return False if $n ∈ $seen-numbers;
Поскольку оператор набора членства ищет значения, которые будут идентичны.Поэтому, когда у нас есть хеш объекта :{}
, в котором хранятся Int
с, тогда $n
может быть идентичен одному из ключей в хеше;если это так, алгоритм завершается.Однако с обычным хэшем, созданным с помощью {}
, ключи Str
, поэтому никогда не идентичны Int
, и поэтому проверка на членство в наборе всегда будет неудачной, что приведет к не прекращению работы алгоритма.
Программа соответствует собственным решениям.Можно написать:
return False if $seen-numbers{$n}:exists;
И тогда это будет работать и с {}
(Hash
).Тем не менее, он будет принудительно вводить числа в Str
для хранения и поиска каждый раз, а стоимость :{}
будет исключена.Таким образом, мы можем сказать, что программа сделала более эффективный выбор структуры данных, используя :{}
, и это, в свою очередь, позволило использовать ∈
, что можно было бы считать более читабельным (особенно если целевая аудитория - люди, привыкшие кчитать такие математические операторы).
Еще один способ написать программу, которая, возможно, была более понятной:
my %seen-numbers is SetHash;
while $n > 1 {
return False if $n ∈ %seen-numbers;
%seen-numbers{$n} = True;
$n = $n.comb.map(*²).sum
}
return True;
Что делает более ясным, что мы думаем о %seen-numbers
как о наборе,хотя в этом случае название оставляет относительно небольшой вопрос о его назначении.