Je m'intéresse moi-même aux langages fonctionnels et visite divers sites Certains sites décrivent soigneusement les mérites des langages fonctionnels et vous font penser que "les langages fonctionnels sont bons", tandis que d'autres disent "bien, cela ne vous fait pas ressentir les mérites des langages fonctionnels". Ce que je voudrais écrire à propos de cette époque, ce sont les caractéristiques d'un "site qui ne vous fait pas ressentir les mérites des langages fonctionnels".
L'exemple est Site Code IQ. Le but du site ci-dessus semble être que le traitement du tableau soit écrit dans le langage de type instruction (langage C) et le langage de type de fonction (Haskell), et le langage de type de fonction (Haskell) est facile à comprendre en comparant les deux.
Je conviens sincèrement que la description du langage fonctionnel (Haskell) est très concise, mais je pense personnellement qu'il y a quelques problèmes avec la logique du langage C donné comme exemple du langage impératif. .. Je ne suis donc pas sûr que ce que l'on dit être le bénéfice du dernier langage fonctionnel (Haskell) sur le site en profite vraiment. Par exemple, si réduire et cartographier, qui sont considérés comme les mérites du langage fonctionnel sur ce site, ne demandent pas beaucoup de temps et d'efforts lorsqu'ils sont mis en œuvre dans le langage pédagogique, on ne peut pas dire qu'il y a un vrai mérite.
Ci-dessous, je vais énumérer les problèmes de l'exemple de programme que j'ai personnellement ressenti.
Que signifie vraiment i ou N dans l'exemple de programme? Je ne savais pas ce que représentaient les noms de variables, donc je ne pouvais pas comprendre à quoi servait la logique simplement en lisant le programme. À tout le moins, i devrait être compteur et N devrait être ARRAY_LIMITTED_NUMBER pour clarifier le rôle de la variable.
Si vous utilisez un initialiseur lors de l'initialisation d'un tableau, pourquoi ne pas définir le nombre d'éléments dans le tableau?
Il peut y avoir des malentendus en ce qui concerne l'étrangeté, mais n'est-il pas plus facile d'écrire le processus en utilisant des pointeurs plutôt que des indices pour accéder aux tableaux? Si vous y accédez avec un pointeur, au moins la variable i devrait être inutile
N'est-ce pas mieux qu'un problème? C'est une proposition. Il semble préférable d'introduire NULL pour représenter la fin du tableau De cette façon, vous n'avez pas à comparer l'indice avec le nombre maximum d'éléments dans le tableau lors de la détermination de la condition de sortie de la boucle. Eh bien, dans ce cas, il y a un problème de savoir quoi faire si NULL est inséré au milieu du tableau, mais tant que vous utilisez le langage C, vous devez créer des règles pour la fin du tableau. L'exemple de programme utilise également define pour définir secrètement le nombre maximum d'éléments dans le tableau comme 5.
Dans le programme d'origine, le contrôle des données (traitement en boucle) et le traitement des données (simulation de serpent et de grenouille) sont effectués en un seul endroit. Mais n'est-ce pas contraire à la programmation structurée qui a été dite pendant des décennies avant les langages fonctionnels? Si vous faites du développement moderne, quel que soit le langage que vous utilisez, le contrôle et le traitement des données doivent être découpés en fonctions distinctes.
Ci-dessous, je publierai le code du langage C que j'ai amélioré
sample.c
#include "stdafx.h"
//Calculez le nombre de grenouilles survivantes
int calc(int snakes, int flogs) {
if (flogs >= snakes) return flogs - snakes;
else return 0;
}
//Une fonction qui manipule un tableau de grenouilles et de serpents
int execute(int snakes[], int flogs[]) {
int survivors = 0; //Nombre total de grenouilles survivantes
while (true) {
//Échapper à la boucle lorsque vous atteignez la fin du tableau
if (*snakes == NULL) break;
survivors += calc(*snakes++, *flogs++);
}
return survivors;
}
int main()
{
int snakes[] = { 5,4,3,2,1,NULL };//serpent
int flogs[] = { 7,6,1,2,2 ,NULL };//Grenouille
printf("Nombre de grenouilles qui ont survécu%5d", execute(snakes, flogs));
getchar();
return 0;
}
En utilisant la déclaration de prototype, nous avons également permis de réduire et de mapper le comportement des langages fonctionnels.
sample.c
#include "stdafx.h"
typedef int(*FUNCPTR)(int a, int b);
//Une fonction qui manipule un tableau de grenouilles et de serpents
//Passez un pointeur de fonction à FUNCPTR qui simule la compétition de survie entre les grenouilles et les serpents.
int zip_and_reduce(int snakes[], int flogs[],FUNCPTR func) {
int survivors = 0; //Nombre total de grenouilles survivantes
while (true) {
//Échapper à la boucle si NULL apparaît dans le tableau
if (*snakes == NULL) break;
survivors += func(*snakes++, *flogs++);
}
return survivors;
}
//Calculez le nombre de grenouilles survivantes
int calc(int snakes, int flogs) {
if (flogs >= snakes) return flogs - snakes;
else return 0;
}
//Calculez le nombre lorsque les grenouilles et les serpents coexistent
int calc_kyouzon(int snakes, int flogs) {
return flogs + snakes;
}
int main()
{
int snakes[] = { 5,4,3,2,1,NULL };//serpent
int flogs[] = { 7,6,1,2,2 ,NULL };//Grenouille
printf("Nombre de grenouilles qui ont survécu%5d", zip_and_reduce(snakes, flogs,&calc));
printf("Nombre lorsque les serpents et les grenouilles coexistent%5d", zip_and_reduce(snakes, flogs, &calc_kyouzon));
getchar();
return 0;
}
Je publierai également le Ver implémenté en Java.
sample.java
package test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class MyTest {
public static void main(String args[]){
List<Integer>snakes = new ArrayList<Integer>();
Collections.addAll(snakes, 1,2,3,20);
List<Integer>flogs = new ArrayList<Integer>();
Collections.addAll(flogs, 10,2,3,4,5);
System.out.println(execute(snakes,flogs));
}
//Fonctions à exposer à l'extérieur
//Passez les arguments du serpent et de la grenouille comme arguments
public static int execute(List<Integer>snaeks,List<Integer>flogs){
//La première valeur totale est 0
return execute(snaeks.iterator(),flogs.iterator() ,0);
}
//Fonctions utilisées en interne
//Iterator<Integer>snakes :Type de dénombrement des serpents
//Iterator<Integer> :type d'énumération des flogs
//sum :Valeur totale des flogs
private static int execute(Iterator<Integer>snakes,Iterator<Integer>flogs ,int sum){
//Lorsqu'il n'y a pas de serpents ou de grenouilles, le processus est terminé
if(!snakes.hasNext() && !flogs.hasNext())return sum;
//Continuer le traitement si un serpent ou une grenouille est présent
else return execute(snakes,flogs,sum + calc(ifExists(snakes),ifExists(flogs) ) );
}
//Trouvez le nombre de grenouilles
//Renvoie le nombre de grenouilles moins le nombre de serpents lorsqu'il y a plus de grenouilles que de serpents
//serpents int: nombre de serpents
//int flogs: nombre de grenouilles
private static int calc(int snakes,int flogs){
if(snakes<= flogs) return flogs - snakes;
else return 0;
}
//Renvoie l'élément si l'énumérateur en a un, sinon renvoie 0
private static int ifExists(Iterator<Integer>ite){
if(ite.hasNext())return ite.next();
else return 0;
}
}
En regardant la source de langue impérative améliorée et la source de langue fonctionnelle, je pense que chaque personne pense différemment. Je ne suis pas très doué pour les langages fonctionnels (Haskell),
--Facile à gérer les tableaux par rapport au langage C
Je sens qu'il y a un mérite
Au contraire, que diriez-vous de l'explication qu'il est pratique parce que vous pouvez utiliser réduire et cartographier? je pense
Recommended Posts