Mathematica Downvalue Lhs
-
02-07-2019 - |
Pergunta
Alguém sabe se existe uma função embutida no Mathematica para obter os LHS de regras downvalue (sem qualquer exploração)? Eu sei como escrever o código para fazê-lo, mas parece bastante básico para um built-in
Por exemplo:
a[1]=2;
a[2]=3;
BuiltInIDoNotKnowOf[a]
retornos {1,2}
Solução
Isso parece funcionar; Não tenho certeza como é útil, no entanto:
a[1] = 2
a[2] = 3
a[3] = 5
a[6] = 8
Part[DownValues[a], All, 1, 1, 1]
Outras dicas
Isto é como keys()
em Perl e Python e outras linguagens que têm suporte embutido para hashes (aka dicionários). Como seu exemplo ilustra, Mathematica suporta hashes sem qualquer sintaxe especial. Basta dizer a[1] = 2
e você tem um hash. [1]
Para obter as chaves de um hash, eu recomendo adicionando isso ao seu init.m ou sua biblioteca de utilitários pessoal:
keys[f_] := DownValues[f][[All,1,1,1]] (* Keys of a hash/dictionary. *)
(Ou a seguinte versão pura função é supostamente um pouco mais rápido:
keys = DownValues[#][[All,1,1,1]]&; (* Keys of a hash/dictionary. *)
)
De qualquer maneira, keys[a]
agora retorna o que você quer. (Você pode obter os valores do hash com a /@ keys[a]
). Se você deseja permitir para hashes arity mais elevados, como a[1,2]=5; a[3,4]=6
então você pode usar isto:
SetAttributes[removeHead, {HoldAll}];
removeHead[h_[args___]] := {args}
keys[f_] := removeHead @@@ DownValues[f][[All,1]]
Que retorna {{1,2}, {3,4}}
. (Nesse caso, você pode obter os valores de hash com a @@@ keys[a]
.)
Note que DownValues
por padrão classifica as chaves, o que provavelmente não é uma boa idéia, pois na melhor das hipóteses é preciso tempo extra. Se você quiser as chaves ordenadas você pode apenas fazer Sort@keys[f]
. Então, eu realmente recomendo esta versão:
keys = DownValues[#,Sort->False][[All,1,1,1]]&;
Curiosamente, não há nenhuma menção da opção Sort
na documention DownValues
. Eu descobri sobre isso a partir de um post antigo de Daniel Lichtblau da Wolfram Research. (I confirmou que ele ainda funciona na versão atual (7.0) do Mathematica.)
Notas de rodapé:
[1] O que é realmente útil é que você pode misturar e combinar isso com definições de função. Como:
fib[0] = 1;
fib[1] = 1;
fib[n_] := fib[n-1] + fib[n-2]
Você pode então adicionar memoization alterando a última linha para
fib[n_] := fib[n] = fib[n-1] + fib[n-2]
que diz para armazenar em cache a resposta para todas as chamadas subsequentes.