web-dev-qa-db-fra.com

Qu'est-ce que le mot de passe et comment fonctionne-t-il exactement?

J'ai vérifié Wikipedia et googlé, mais je ne peux toujours pas comprendre comment fonctionne le mot de passe par nom dans ALGOL 60.

35
bdd

J'ai trouvé une bonne explication à Pass-By-Name Parameter Passing . Essentiellement, le corps d'une fonction est interprété au moment de l'appel après avoir substitué textuellement les paramètres réels dans le corps de la fonction. En ce sens, la méthode d'évaluation est similaire à celle des macros de préprocesseur C.

En substituant les paramètres réels dans le corps de fonction, le corps de fonction peut à la fois lire et écrire les paramètres donnés. En ce sens, la méthode d'évaluation est similaire au passage par référence. La différence est que, avec le nom de passe, le paramètre est évalué à l'intérieur de la fonction, un paramètre tel que a[i] dépend de la valeur actuelle de i à l'intérieur de la fonction, plutôt que de faire référence à la valeur à a[i] avant l'appel de la fonction.

La page que j'ai liée ci-dessus contient d'autres exemples de cas où le mot de passe est à la fois utile et dangereux. Les techniques rendues possibles par le nom de passe sont largement remplacées aujourd'hui par d'autres techniques plus sûres telles que les fonctions de passe par référence et lambda.

37
Greg Hewgill

Je suppose que vous voulez dire appel par nom dans ALGOL 60.

Appel par nom est similaire à l'appel par référence dans la mesure où vous pouvez modifier la valeur du paramètre passé. Il diffère de l'appel par référence en ce que le paramètre n'est pas évalué avant l'appel de la procédure mais est plutôt évalué paresseusement. Autrement dit, il est évalué lorsque et uniquement lorsque le paramètre est réellement utilisé.

Par exemple, supposons que nous ayons une procédure f(x, y) et que nous la transmettions i et i/2i est initialement égal à 10. Si f définit x sur 42 puis évalue y il verra la valeur 21 (alors qu'avec appel par référence ou appel par valeur, il verrait toujours 5). En effet, l'expression i/2 n'est pas évalué tant que y n'est pas évalué.

À bien des égards, cela semble se comporter comme une substitution de texte littérale des paramètres (avec un changement de nom pour éviter les conflits de noms). En pratique, cependant, ceci est implémenté en utilisant des "thunks" (essentiellement des fermetures) pour les expressions passées.

L'article Wikipédia sur Jensen's Device montre quelques exemples intéressants d'utilisation de l'appel par nom. Voici l'un d'entre eux:

real procedure Sum(k, l, u, ak)
     value l, u;
     integer k, l, u;
     real ak;
     comment k and ak are passed by name;
 begin
     real s;
     s := 0;
     for k := l step 1 until u do
         s := s + ak;
     Sum := s
 end;

Dans la procédure, la variable d'index k et le terme de sommation ak sont passés par nom. L'appel par nom permet à la procédure de modifier la valeur de la variable d'index lors de l'exécution de la boucle for. L'appel par nom entraîne également la réévaluation de l'argument ak lors de chaque itération de la boucle. En règle générale, ak dépendra de la modification (effet secondaire) k.

Par exemple, du code pour calculer la somme des 100 premiers termes d'un vrai tableau V[] serait:

Sum(i, 1, 100, V[i]).
16

En fait, l'appel par son nom n'est pas seulement une curiosité historique. Vous pouvez faire appel par nom dans les fichiers batch de Windows (et une myriade d'autres langages de script). Savoir comment cela fonctionne et comment l'utiliser efficacement dans la programmation peut ouvrir des solutions intéressantes aux problèmes. Je sais qu'il ne fait que passer des chaînes pour une expansion ultérieure, mais il peut être manipulé pour avoir des effets similaires à l'appel par le nom.

call :assign x 1
exit /b
:assign
setlocal enabledelayedexpansion
(endlocal
:: Argument 1 is the name of the variable
set %1=%2
)
exit /b

Pour ceux du futur:

Concepts in Programming Languages ​​par John C. Mitchell a également été utile.

Pass-by-Name. Rétrospectivement, la caractéristique la plus étrange d'ALGOL 60 est l'utilisation du mot de passe. Dans pass-by-name, le résultat d'un appel de procédure est le même que si le paramètre formel était substitué dans le corps de la procédure. Cette règle pour définir le résultat d'un appel de procédure en copiant la procédure et en remplaçant les paramètres formels s'appelle la règle de copie ALGOL 60. Bien que la règle de copie fonctionne bien pour les programmes fonctionnels purs, comme l'illustre la réduction β du calcul lambda, l'interaction avec les effets secondaires du paramètre formel est un peu étrange. Voici un exemple de programme montrant une technique appelée périphérique de Jensen: passage d'une expression et d'une variable qu'elle contient à une procédure afin que la procédure puisse utiliser un paramètre pour changer l'emplacement désigné par l'autre:


 begin integer i;
        integer procedure sum(i, j);
            integer i, j;
                comment parameters passed by name;
            begin integer sm; sm := 0;
                for i := 1 step 1 until 100 do sm := sm + j;
                sum := sm
            end;
        print(sum(i, i*10 ))
 end

Dans ce programme, la somme de la procédure (i, j) additionne les valeurs de j lorsque i passe de 1 à 100. Si vous regardez le code, vous vous rendrez compte que la procédure n'a de sens que si les modifications apportées à i provoquent une modification de la valeur de j; sinon, la procédure calcule simplement 100 * j. Dans la somme des appels (i, i * 10) montrée ici, la boucle for dans le corps de la procédure somme additionne la valeur de i * 10 lorsque i passe de 1 à 100.

3
bdd

Je sais que je rejoins tard le club et ce n'est pas nécessairement une réponse, mais je voulais ajouter une chose qui pourrait aider à clarifier un peu. J'ai toujours considéré le mot de passe ALGOL comme un processus similaire à lorsque les directives du préprocesseur C++ (macros, en particulier) remplacent le nom d'une fonction/variable par le morceau de code réel pendant la compilation. Le mot de passe remplace essentiellement le nom du paramètre formel par le paramètre réel et s'exécute. Je n'ai jamais écrit en ALGOL, mais j'entends que le mot de passe aura le même résultat que le mot de passe par référence de C++.

1
nhershy

ALGOL a été conçu pour les algorithmes mathématiques. J'aime la fonction de sommation comme exemple d'appel par nom.

Désolé mon ALGOL est un peu rouillé la syntaxe n'est probablement pas correcte.

.FUNCTION SUM(var,from,to,function)
.BEGIN
  .REAL sum =0;
  .FOR var = from .TO to .DO sum = sum + function;
  return sum;
.END

Vous pourriez utiliser une somme comme

  Y = sum(x,1,4,sum(y,3,8,x+y));

Dans ce qui précède, la somme intérieure (y, 3,8, x + y) générerait une fonction sans nom pour passer à l'appel de somme extérieure. Les variables x et y ne sont pas transmises par valeur mais par nom. Dans le cas des variables, l'appel par nom est équivalent à l'appel par référence d'adresse en C. Cela devient un peu déroutant lorsque la récursivité est impliquée.

Les emprunteurs fabriquaient des machines ALGOL. Ils avaient une mémoire Word de 48 bits avec 3 bits de drapeau. Les bits de drapeau ont implémenté le cal par le nom d'ALGOL. c'était une machine à pile, donc lorsque la fonction était chargée sur la pile, l'appel par son nom fag la faisait appeler. Le compilateur générerait des fonctions sans nom lorsque des expressions étaient utilisées comme arguments. Une variable serait une simple référence indirecte. Une erreur se produirait lors de l'écriture dans une fonction.

1
G K

Vous pouvez passer "nom" sous la forme symbolique d'une variable qui lui permet d'être à la fois mise à jour et accessible simultanément. Par exemple, disons que vous voulez tripler une variable x qui est de type int:

start double(x);
real x;
begin
x : = x * 3
end;
1
Tawanda Moyo

Flatlander a un exemple éclairant de la façon dont cela fonctionne dans Scala ici . Supposons que vous vouliez implémenter tandis que :

def mywhile(condition: => Boolean)(body: => Unit): Unit =
  if (condition) {
    body
    mywhile(condition)(body)
  }

Nous pouvons appeler cela comme suit:

var i = 0
mywhile (i < 10) {
  println(i)
  i += 1
}

Scala n'est pas ALGOL 60, mais peut-être qu'elle éclaire un peu.

1