Existe-t-il un équivalent à la directive du préprocesseur C## dans Erlang? Disons que je veux concaténer deux atom() en utilisant une directive de préprocesseur -define, comment est-ce que je ferais sans ayant des effets secondaires au moment de l'exécution?Erlang: existe-t-il un équivalent à la directive ## du préprocesseur C?
Répondre
Vous pouvez obtenir un résultat suffisamment proche en utilisant des transformations d'analyse. Le parse_transform suivant recherche "atom1 ++ atom2" et le convertit en "atom1atom2" au moment de la compilation.
exemple le module
-module(z).
-export([z/0]).
-compile({parse_transform, zt}).
z() -> concat ++ enate.
compilation avec 'S' prouve qu'il est en effet concaténé au moment de la compilation:
{function, z, 0, 2}.
{label,1}.
{func_info,{atom,z},{atom,z},0}.
{label,2}.
{move,{atom,concatenate},{x,0}}.
return.
fonctionne comme prévu:
1> z:z().
concatenate
le module contenant le transformer la parse:
-module(zt).
-export([parse_transform/2]).
parse_transform(AST, _Options) ->
[parse(T) || T <- AST].
parse({function, _, _, _, _} = T) ->
erl_syntax_lib:map(fun hashhash/1, T);
parse(T) -> T.
hashhash(Tree) ->
erl_syntax:revert(
case erl_syntax:type(Tree) of
infix_expr ->
Op = erl_syntax:infix_expr_operator(Tree),
Left = erl_syntax:infix_expr_left(Tree),
Right = erl_syntax:infix_expr_right(Tree),
case {erl_syntax:operator_name(Op), erl_syntax:type(Left), erl_syntax:type(Right)} of
{'++', atom, atom} ->
erl_syntax:atom(erl_syntax:atom_literal(Left) ++ erl_syntax:atom_literal(Right));
_ ->
Tree
end;
_ ->
Tree
end
).
EDIT: édité pour "surcharger" l'opérateur infix ++. La version précédente utilisait la fonction "##".
Je pense qu'il n'y en a pas. Et je pense à cause de cela, vous pouvez faire tout cela à l'exécution sans effets secondaires
Je comprends que le compilateur est dit être vraiment bon mais comment peut-il y avoir aucun effet secondaire (par exemple les cycles consommés)? – jldupont
Pouvez-vous donner un exemple de ce que vous voulez dire? –
Je ne suis pas sûr de comprendre ce que vous demandez, mais je vais essayer de le faire. Ou peut-être que vous vouliez dire cela?
-define(CATATOM(A, B), AB).
NewAtom = ?CATATOM(atom1, atom2). % NewAtom is atom1atom2
bien que je ne sois pas sûr de l'utilisation de la nouvelle seconde. Comme il serait plus simple d'écrire simplement atom1atom2 à la place de la macro.
Le second ne subira aucun effet secondaire d'exécution. La première entraînera des effets secondaires à l'exécution puisque le résultat de la macro est 3 fonctions à exécuter au moment de l'exécution.
Il y a le concept d'avoir des transformations d'analyse, qui vous permettraient de concaténer des atomes au moment de la compilation.
Cela n'aide pas beaucoup si vous n'expliquez pas comment le faire avec une transformation d'analyse. –
Vous ne pouvez pas réellement faire quoi que ce soit dans une macro, c'est juste du texte pur, du bon niveau de jeton, de la substitution. N.B. vous travaillez sur le code source et ne l'évaluez pas. Si vous avez besoin de types de substitution plus complexes, vous devez utiliser une transformation d'analyse.
Si vous écrivez une macro de concaténation, vous pouvez toujours former la forme Arg pour obtenir l'argument sous forme de chaîne. Regardez la section du préprocesseur du manuel de référence en ligne.
Bien sûr, la question vraiment intéressante est pourquoi vous voudriez concaténer deux atomes à la compilation? Je suppose que c'est la sortie d'une autre macro, sinon il n'y aurait aucun intérêt à le faire.
Je veux pouvoir "paramétrer" un module, par ex. -define (APP, app). -define (EXT, ext). -define (NOM,? APP ++? EXT). où l'opérateur '++' concaténerait les deux atomes() au moment de la compilation. – jldupont
- 1. Extension de macros de préprocesseur à une autre directive de préprocesseur
- 2. Utilisation du préprocesseur C# pour ajouter la référence
- 3. C Définition du test du préprocesseur de plusieurs macros
- 4. directive préprocesseur en C# pour l'importation basée sur la plate-forme
- 5. Directives du préprocesseur VB.NET
- 6. Directives du préprocesseur
- 7. C# C équivalent à l'union
- 8. À quoi sert la directive du compilateur @package dans Cocoa?
- 9. Style C: Macros ou préprocesseur?
- 10. directive #include: différence entre "test.h" et "./test.h"
- 11. C++ pragma GCC directive system_header
- 12. C# équivalent du mot-clé Java 'implémente'?
- 13. Macro de débogage du préprocesseur pour la journalisation facultative
- 14. Directive du compilateur Delphi Region - fichiers d'unités rétrocompatibles?
- 15. A quoi servent les macros du préprocesseur?
- 16. Résolution de l'hôte du service - C# Équivalent du registre RMI?
- 17. Le préprocesseur C peut-il effectuer un calcul arithmétique?
- 18. C# équivalent à DigestUtils.md5Hex de Java (chaîne)?
- 19. Un équivalent de javax.nio.Buffer.flip() dans C#
- 20. Les définitions du préprocesseur se détériorent. int définir la redéfinition?
- 21. Comment forcer la sensibilité à la casse du préprocesseur Visual Studio aveC#includes?
- 22. Existe-t-il un C# équivalent à unhexlify de Python?
- 23. Erlang système de type
- 24. Erlang erl_call provoque la fermeture du module gen_server
- 25. Quelqu'un peut-il expliquer la structure d'un Pid à Erlang?
- 26. Existe-t-il un équivalent C# à File.separator en Java?
- 27. Apache ignore la directive SSLRequire
- 28. Objectif C équivalent à javascripts setTimeout?
- 29. Java équivalent à
- 30. C# Convert.ToInt16 (Chaîne) C Équivalent
Cela a l'air génial! Je ne peux pas le compiler avec erlIDE: dois-je faire quelque chose de spécial? – jldupont
erlc doit avoir accès à zt.beam lors de la compilation de z.erl, vous devez donc ajouter son chemin à erlc en utilisant l'option -pa, probablement: "erlc -pa.z.erl". Vous ne savez pas comment faire avec erlIDE. – Zed
L'erlIDE n'est pas encore complet ... il ne permet pas de spécifier des chemins supplémentaires (comme avec l'option -pa). Existe-t-il un moyen de le faire avec une directive -compile? – jldupont