2017-04-12 2 views
0

J'essaye d'écrire un client CLI dans Elixir pour une API afin que je puisse me connecter au système d'API, aller chercher les données dont j'ai besoin pour mon calcul, puis me déconnecter. J'ai défini une structure Packet.Login supposée être ma structure de données interne avec laquelle je me retrouve après avoir analysé le JSON reçu. J'utilise Poison pour analyser le JSON. Le problème est qu'il semble que, parce que l'API retourne des propriétés capitalisées, je ne peux pas les faire correspondre lors de l'impression ou de l'analyse, car Poison retournera une carte avec ces touches majuscules. Le problème est qu'il me semble impossible d'utiliser l'alias comme ça. Si j'essaie d'utiliser une autre syntaxe,Elixir - Clés en majuscules dans les structures

packet[:Token] 

cela ne fonctionne toujours pas et à la place me donne une erreur. Mais cette fois sur Packet.Login ne pas implémenter le comportement d'accès. Je peux comprendre cette partie, mais pas le premier problème. Et j'essaie de garder le code stupide simple.

defmodule Packet.Login do 
    defstruct [:Data, :Token] 
end 

defimpl String.Chars, for: Packet.Login do 
    def to_string(packet) do 
    "Packet:\n---Token:\t\t#{packet.Token}\n---Data:\t#{packet.Data}" 
    end 
end 

loginPacket = Poison.decode!(json, as: %Packet.Login{}) 
IO.puts "#{loginPacket}" 

Lorsque vous essayez de compiler ce qui précède, je reçois ceci:

** (CompileError) lib/packet.ex:31: invalid alias: "packet.Token". If you wanted to define an alias, an alias must expand to an atom at compile time but it did not, you may use Module.concat/2 to build it at runtime. If instead you wanted to invoke a function or access a field, wrap the function or field name in double quotes 
(elixir) expanding macro: Kernel.to_string/1 

est-il un moyen pour moi de résoudre ce problème en quelque sorte? J'ai pensé à analyser la carte et à dé-capitaliser tous les champs en premier, mais je préférerais ne pas le faire. Pourquoi ne puis-je pas avoir des majuscules pour un struct?

Il semble que je puisse cependant, tant que je n'essaie pas de les utiliser.

+1

Essayez 'paquet « jeton »' et 'paquets « de données »'. . – Dogbert

+0

Wow. Oui, ça a marché. Alors, est-ce que la clé est une chaîne? Je veux une explication pour savoir pourquoi c'est nécessaire. – Simon

+0

@Dogbert Faire et répondre avec une explication de pourquoi donc je peux accepter la réponse (Étant donné que l'explication est assez explicite) :) – Simon

Répondre

2

Pour accéder à un champ d'une carte qui est un atome commençant par une lettre majuscule, vous devez soit mettre la clé entre guillemets, par ex. foo."Bar" ou utilisez la syntaxe de parenthèse, par ex. foo[:Bar]. foo.Bar dans Elixir est analysé comme un alias. Avec les structures, vous ne pouvez pas utiliser la syntaxe des parenthèses. La manière la plus simple est d'utiliser des guillemets autour du nom du champ. Dans votre code, vous devez donc changer:

"Packet:\n---Token:\t\t#{packet.Token}\n---Data:\t#{packet.Data}" 

à:

"Packet:\n---Token:\t\t#{packet."Token"}\n---Data:\t#{packet."Data"}" 

Je ne pouvais pas trouver ce clairement documenté nulle part, mais la source Elixir mentionne ce in some places et utilise également cette syntaxe pour accéder à certains fonctions dans :erlang qui ont des noms qui ne sont pas des identifiants valides dans Elixir, par ex. :erlang."=<".


Anecdote: vous pouvez définir des fonctions dans Elixir qui ne peut être appelé avec cette syntaxe de devis ainsi:.

iex(1)> defmodule Foo do 
...(1)> def unquote(:"[email protected]#")(), do: :ok 
...(1)> end 
iex(2)> Foo."[email protected]#"() 
:ok 
+0

Ce fait amusant est juste étrange, hahaha. Merci pour la réponse la plus rapide qui soit. Je pense que vous avez répondu dans la demi-minute (le commentaire), et cela m'a sauvé beaucoup de tracas en essayant de trouver cela. Comme vous l'avez dit, je n'ai trouvé cela documenté nulle part. – Simon

+1

:) Je pense avoir appris cette syntaxe quand j'ai vu des appels à ': erlang." <= "' En lisant kernel.ex depuis longtemps. – Dogbert