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}

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top