2010-03-05 9 views
2

Je suis en train de concevoir une syntaxe pour les templates/génériques. Les langages de la famille C++ utilisent des chevrons pour cela, mais je cherche à utiliser un caractère séparateur à la place. Par exemple, si en Java vous pouvez écrire:Modèle/caractère de syntaxe générique

Map<String, Foo> foos = new HashMap<String, Foo>(); 

Je vise:

.foos = hmap*string*foo 

Je suis en train de décider quel sera le caractère de séparation; ça ne peut pas être littéralement *, parce que c'est déjà utilisé pour la multiplication (pas que je ne puisse pas le surcharger, mais la précédence serait fausse). En regardant les caractères disponibles, certaines options sont

.foos = hmap!string!foo 
.foos = hmap$string$foo 
.foos = hmap?string?foo 
.foos = hmap^string^foo 
.foos = hmap`string`foo 
.foos = hmap|string|foo 
.foos = hmap~string~foo 

Comme il est dans une certaine mesure une question esthétique, je me suis dit que je prendrais un sondage: quelle option préférez-vous? Y a-t-il une autre option qui serait préférable? (Comme d'habitude avec des questions comme celle-ci, si votre réponse a déjà été postée, veuillez la renvoyer plutôt que la dupliquer.)

De même, sur un clavier américain standard, `est non décalé, chacun des autres nécessite la touche Maj. Y a-t-il une différence sur les claviers internationaux? Y a-t-il des dispositions de clavier sur lesquelles l'un des candidats ci-dessus est particulièrement facile ou difficile à taper?

(Comme il est une question sans réponse unique droit, devrait-il être un wiki communautaire?)

+1

Je crois que D utilise '' (args)!. –

+0

Donc c'est le cas. Peut-être que je devrais utiliser! et suivez ce précédent, alors? (Je dois utiliser un caractère de marqueur explicite pour désambiguïser de la création d'objet, et je ne peux pas utiliser les crochets, car ils seraient ambigus par rapport aux opérateurs de comparaison.) – rwallace

+0

@rwallace: Quel genre de grammaire essayez-vous de créer? Bien sûr, vous pouvez utiliser les mêmes symboles dans différents contextes. – Dario

Répondre

0

Chevrons fonctionnent mieux pour moi que vos options, car ils créent une séparation visuelle des éléments entre les d'autres codes.

Je voudrais essayer quelque chose de similaire avec {} ou (), s'ils ne sont pas déjà utilisés.

1

Je ne pense pas que l'un de ces symboles clarifie vraiment le fait que vous appliquez une liste d'arguments de type à un type générique.

Pourquoi ne pas simplement une sorte de syntaxe de support comme dans les langues les plus courantes, que ce soit

Map<String, Foo> 

ou

Map[String, Foo] 

(ou {}/() respectivement)

Notez que - comme dans OCaml ou Haskell - les espaces peuvent aussi être utilisés de façon assez complète.

foos : int list 

ou

foos :: Map String Foo 

Un peu de théorie plus large: Un simple type générique est un type avec kind* -> * - Par conséquent, il doit être considéré comme une fonction de types de types

List<Int>s'applique la construction de type générique List<α> sur le type de béton Int, ce qui donne un autre type de béton - La liste spécialisée.Par conséquent, j'aime la spécialisation générique à ressemble en quelque sorte à une application de la fonction.

L'utilisation de * peut avoir du sens en tant que types tuples! Donc, Map String*Foo pourrait être une bonne option si vous voulez vous fier à la syntaxe de l'opérateur, car elle distingue les constructeurs de type et les arguments de type (tupled).

+0

Je pense aussi à la spécialisation générique comme étant similaire à l'application de la fonction. Comme dans certains langages fonctionnels, j'utilise juxtaposition pour les paramètres de fonction, donc f (a, b) est simplement écrit comme f a b. Si je vais avec quelque chose comme hmap! String! Foo pour la spécialisation générique, j'aime penser à cela comme une variante de l'application de la fonction où l'espace est juste remplacé par un caractère différent à désambiguïser. – rwallace

+0

@rwallace: Eh bien, alors '$' pourrait être quelque peu approprié;) Mais cette syntaxe implique nécessairement l'exécution de type qui peut être un peu couterintuitive dans un langage non-fonctionnel. Par conséquent, l'approche en tuple ou les parenthèses simples sont probablement meilleures (juste mon avis). – Dario

+0

Notez que l'un de ces symboles rend difficile la distinction des types simples d'un simple point de vue optique. Un espace ou au moins un symbole de taille différente comme 'ou * est un must! – Dario

0

Je pense

.foos = hmap(string, foo) 

est une belle syntaxe: permettant types à utiliser comme « fonctions » qui renvoient de nouveaux types.

0

Je ne suis pas trop friand de l'un d'eux, pour les raisons que d'autres personnes ont mentionnées. Les crochets sont seulement utiles pour désigner ce genre de chose, peu importe que ce soit < {[(etc. Il y a 4 choisir à partir de là

Quelques points spécifiques sur les options que vous avez énumérés.

.foos = hmap!string!foo - could be confused with negation. 
    .foos = hmap$string$foo 
    .foos = hmap?string?foo - just doesn't look very definitive, the question mark makes me think you are saying it may be a string 
    .foos = hmap^string^foo 
    .foos = hmap`string`foo - tricky to find the key! 
    .foos = hmap|string|foo - could be confused with an 'or' operation 
    .foos = hmap~string~foo 
+0

Les parenthèses sont toutes bien parlé, hélas. Mais vous soulevez quelques bons points. D'accord, ? est dehors; et 'pourrait être déconseillé, tentant bien que le symbole non décalé soit. Au moins, j'utilise un mot-clé pour ne pas, donc! est sans ambiguïté. – rwallace

+0

Il est peut-être univoque dans votre langage oui, mais vous devez vous rappeler que les personnes lisant le code doivent être capables d'avoir une idée vague de ce qui se passe sans connaître tous les détails les plus fins de la syntaxe. Si vous utilisez un symbole qui représente généralement quelque chose d'autre dans la plupart des langues, vous devez faire attention à ce que sa signification soit claire. –

+0

True. C'est un autre argument pour utiliser $, qui a été utilisé ailleurs pour connecter des parties d'un nom composé, un usage vaguement lié. – rwallace

0

I ne pas comme un opérateur infixe pour cela en général, car elle soulève des questions sur l'associativité.

par exemple est hmap*string*foo un hmap<string, foo> ou un hmap<string<foo>> ou peut-être un foo<string<hmap>>?

+0

Vous soulignez un bon point sur l'associativité. Je pense que la réponse est qu'il est resté associatif et automatiquement curry - voir ma réponse à Dario sur le type currying. – rwallace

0

Peut-être que vous devriez utiliser le "de" mot-clé:

map = HashMap of String, Foo() 

En Boo, il ressemblerait à ceci:

map = HashMap[of string, Foo]() 
Questions connexes