Pourquoi les noms de fonctions numériques ne sont-ils pas autorisés?


10

Considérer ce qui suit:

$ ksh -c '1(){ echo hi;};1'
ksh: 1: invalid function name
$ dash -c '1(){ echo hi;};1'
dash: 1: Syntax error: Bad function name
$ bash -c '1(){ echo hi;};1'
bash: `1': not a valid identifier
bash: 1: command not found
$ mksh -c '1(){ echo hi;};1'
hi

Fondamentalement, j'essayais de déclarer des fonctions 1et 0qui seraient des raccourcis pour trueet false, mais comme vous pouvez le voir, j'ai rencontré des problèmes avec l'utilisation de noms numériques dans les fonctions. Le même comportement se produit avec les alias et les noms à deux chiffres.

La question est "pourquoi"? Est-ce mandaté par POSIX? ou juste un caprice de coquilles bourne?

Voir aussi la question connexe à celle-ci.


1
Les choses qui sont mandatées par posix sont généralement des caprices de coquilles de type Bourne. : P
muru

Je vois ce que tu as fait là . . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem Veuillez vous référer à meta.askubuntu.com/q/13807/295286 Les scripts shell / shell sont et ont toujours été sur le sujet sur Ask Ubuntu :) C'est un sujet essentiel pour une bonne administration système de tout système Ubuntu
Sergiy Kolodyazhnyy

4
Il convient de noter que cela se 0trouve truedans les scripts shell et 1est false(vraiment, tout non différent de zéro est traité comme faux), au cas où quiconque le lirait ne le sait pas. C'est à l'envers de la plupart des autres langages de programmation.
Ethan Kaminski

2
@EthanKaminski yep, en ce qui concerne les états de sortie des commandes , c'est absolument vrai. La valeur de retour de 0 est truedans le shell. Cependant, dans l'expansion arithmétique, les $((...))états de retour sont inversés - 1 est trueet 0 est falsepour la cohérence avec la syntaxe du langage C. Essayez par exemple bash -c 'echo $((1==1));echo $((1==2))' Ce que j'essayais de faire en dehors de cette question était en fait "d'inverser" le comportement. Voir le dernier exemple de ma réponse ici pour voir exactement ce que j'essayais de faire. Idée idiote, mais fonctionne néanmoins
Sergiy Kolodyazhnyy

Réponses:


14

POSIX dit:

2.9.5 Commande de définition de fonction

Une fonction est un nom défini par l'utilisateur qui est utilisé comme une simple commande pour appeler une commande composée avec de nouveaux paramètres de position. Une fonction est définie avec une "commande de définition de fonction".

Le format d'une commande de définition de fonction est le suivant:

 fname ( ) compound-command [io-redirect ...]

La fonction est nommée fname ; l'application doit s'assurer qu'il s'agit d'un nom (voir Nom XBD ) et qu'il ne s'agit pas du nom d'un utilitaire intégré spécial. Une implémentation peut autoriser d'autres caractères dans un nom de fonction en tant qu'extension. L'implémentation doit conserver des espaces de noms séparés pour les fonctions et les variables.

Et:

3.235 Nom

Dans le langage de commande shell, un mot composé uniquement de traits de soulignement, de chiffres et d'alphabets du jeu de caractères portable. Le premier caractère d'un nom n'est pas un chiffre.

Remarque: le jeu de caractères portable est défini en détail dans le jeu de caractères portable.

Un mot commençant par un chiffre ne peut donc pas être un nom de fonction.


POSIX ne dit toujours pas pourquoi, mais je le considérerai comme une réponse "Parce que les normes". Merci
Sergiy Kolodyazhnyy

4
@SergiyKolodyazhnyy Je dirais que c'est une chose héritée. Cette norme pour les noms est également assez courante dans d'autres choses (les noms C de l'IIRC suivent également la même norme), donc c'est probablement une chose Unix. De plus, en C, il est plus facile d'analyser
muru

3
@muru en C cela apporterait une certaine ambiguïté s'il était autorisé. Par exemple, qu'est-ce que cela 1Lsignifierait? Un nom de fonction? Ou un long intlittéral?
Ruslan

2
En ajoutant à ce qui précède, il convient de noter qu'en C, un nom de fonction nu peut agir comme un pointeur vers cette fonction. Cela vous permet de passer des fonctions en tant que paramètres à une fonction, de stocker des références à celles-ci dans des variables, etc. Souvent utilisé pour les rappels. Ceci contrairement au nom de la fonction suivi (), éventuellement avec des arguments à l'intérieur, qui dénote un appel à la fonction en question (et prend la valeur qui est retournée par la fonction appelée). Donc, si vous avez une fonction int f() { return 42; }en C, fest valide dans un contexte de pointeur et f()est valide dans un contexte entier sans pointeur.
un CVn

13

Il s'agit d'une norme dans de nombreux langages pour éviter toute confusion entre les opérations mathématiques et les variables ou fonctions ou méthodes.

Considérer:

var 1 = 100

print 1*10 //should return 10 but would instead return 1000

var x = 5
x += 1
print x //returns 105, not 6    

def 100(num)
  return num * 1000
end

var y = 10 + 100(10)
print y // returns 100010 instead of 1010

Comme vous pouvez le voir, si les nombres étaient autorisés en tant que noms de variable ou de fonction, faire des calculs plus tard dans un programme pourrait devenir très déroutant et vous devriez trouver des solutions de rechange créatives si vous aviez besoin de faire des calculs avec ces nombres plus tard. Il peut également produire des résultats inattendus dans certaines langues. Imaginez que vous incrémentez un nombre pour une boucle, mais l'un des chiffres est déjà une variable équivalente à une chaîne. Cela déclencherait immédiatement une erreur. Si vous n'étiez pas l'auteur original du code, cette erreur pourrait prendre un certain temps à trouver.

En un mot, c'est pourquoi la plupart des langues ne vous permettent pas d'utiliser un nombre comme nom d'une variable ou d'une fonction ou d'une méthode ou etc.


J'allais commenter "mais les variables dans le shell doivent $être complétées pour être développées" mais là encore, si le shell est inspiré par d'autres langages, c'est OK, je suppose, en plus dans les ((variables d' expansion arithmétiques , il n'est pas nécessaire d'avoir un leader $. OK, je peux comprendre que
Sergiy Kolodyazhnyy

3
Oui, c'est une convention car cela créera des résultats inattendus dans presque toutes les langues, mais, même dans une situation où cela fonctionnerait, cela peut rendre le code très difficile à comprendre pour quiconque devrait travailler sur votre code après vous.
Josh

2
L'extension arithmétique @SergiyKolodyazhnyy permet de référencer les noms de variables sans $, donc il y a ça. Mais c'est probablement secondaire à l'autre raison de "suivre la convention commune"
hobbs

@hobbs yep, absolument d'accord avec cela
Sergiy Kolodyazhnyy

1
Cette explication "la plupart des langues" n'a guère de sens pour les coquilles. Tous les shells de type Bourne ont des paramètres dont les noms ressemblent littéraux numériques ou des opérateurs: 0le nom de script shell ou, 1, 2, ..., pour les paramètres de position, *pour les joints, -pour les options activées, ?le dernier état de sortie, et !pour la PID du travail asynchrone le plus récent. (Ainsi, même dans $(( )), le $est souvent nécessaire.) Le code montré ici pour démontrer la justification suggérée n'est pas un script pour un shell de style Bourne, car il n'y a aucun moyen de le démontrer de cette façon, car il ne s'applique pas à leur.
Eliah Kagan

10

En C, considérez une expression comme:

1000l + 2.0f;

Est-ce 1000lune variable ou une constante? Étant donné que les noms de variables ne peuvent pas commencer par un chiffre, il doit s'agir d'une constante. Cela rend l'analyse plus facile et plus stricte (les fautes de frappe comme 1000kpeuvent être facilement détectées). Il est également plus facile d'avoir une seule règle pour les variables et les noms de fonction, car les fonctions peuvent également être traitées comme des variables. Maintenant , bien sûr, les analyseurs sont beaucoup plus complexes et puissants, et nous avons des choses comme les littéraux personnalisés en C ++. Mais à l'époque de la préhistoire, sacrifier un peu de flexibilité inutile pouvait raccourcir considérablement la durée de votre compilation (ou interprétation) (et les gens se plaignent toujours des temps de compilation en C ++).

Et vous pouvez voir les effets d'une influence C dans tout le langage shell, il n'est donc pas surprenant que le shell Bourne (ou shell C) et donc POSIX, ait restreint la classe des noms autorisés à la même chose que celle de C.


2
Au fur et à mesure des explications , c'est la bonne. Il est pas que les mêmes considérations valent pour toutes les langues ou que les shells de type Bourne ont une syntaxe similaire à celle de C, mais que la culture associée à C était forte et les concepteurs de coquillages ont dû trouver des garanties quant à ce que les identificateurs seraient permis. Je pense que cela pourrait utiliser des exemples de "vous pouvez voir les effets d'une influence C dans tout le langage shell", car les similitudes entre eux ne compensent pas vraiment les différences (pensez aux nombres considérés comme vrais , par exemple). Néanmoins, cette réponse est correcte.
Eliah Kagan

@Eliah, sans doute, le nombre est également une conséquence directe des états de sortie pour le succès et l'échec en C, donc j'ai tendance à penser en termes de succès et d'échec au lieu de vrai et faux lors de l'écriture de tests shell. Vous avez raison dans le fait que l'abondance de la syntaxe du shell ne ressemble en rien à C, mais les exemples incluent les accolades, les points-virgules, les courts-circuits &&et ||, le manque de prise en charge de l'ASCII nul dans les chaînes,
Olorin
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.