• [^] # Re: Jai: Language for game programmming

    Posté par . En réponse à la dépêche C++17, Genèse d’une version mineure. Évalué à 1.

    J'ai l'impression que l'on ne se comprend pas, ou que tu ne sais pas ce qu'est la programmation fonctionnelle.

    Premièrement, pour la curryfication et les applications partielles, un langage fonctionnel digne de ce nom (donc basé sur le lambda-calcul) n'a pas besoin d'artifice particulier à la std::bind pour faire cela.

    (* le principe de la curryfication se voit dans le type inféré :
     * c'est une fonction qui prend un int et renvoie une fonction
     * qui prend un int pour retourner un int *)
    let plus i j = i + j;;
    val plus : int -> int -> int = <fun>
    (* donc si je lui donne un int, j'obtiens une fonction des
     * int vers les int *)
    let plus_2 = plus 2;;
    val plus_2 : int -> int = <fun>
    plus_2 3;;
    - : int = 5
    (* la curryfication, ça se voit aussi comme cela : *)
    let plus = fun i -> fun j -> i + j;;
    val plus : int -> int -> int = <fun>
    let plus_2 = plus 2;;
    val plus_2 : int -> int = <fun>
    plus_2 3;;
    - : int = 5

    Ensuite ton exemple avec macollection.iterer, je ne vois pas où il illustre le statut de citoyen de première classe pour les fonctions. De ce que je comprends, iterer est une méthode d'un objet itérable qui prend une fonction en paramètre : mais cela fait partie du type même de la méthode d'attendre un tel paramètre. De ce que je comprends, c'est équivalent à ça :

    let (+=) x i = x := !x + i;;
    val ( += ) : int ref -> int -> unit = <fun>
    let sum a = fun x -> Array.iter ((+=) x) a;;
    val sum : int array -> int ref -> unit = <fun>
    let x = ref 3 in
    sum [|1; 2; 3|] x; !x;;
    - : int = 9

    Moi ce que je disais c'est que le type des tableaux 'a array est polymorphe et contient des éléments de n'importe quel type 'a qui peut être un type de fonction, comme dans l'exemple :

    let tab = Array.init 5 (fun i -> fun x -> x += i);;
    val tab : (int ref -> unit) array = [|<fun>; <fun>; <fun>; <fun>; <fun>|]

    Ici le type 'a est instancié à la valeur particulière int ref -> unit qui est celui des fonctions qui appliquent des effets de bords sur les pointeurs sur int. On peut en user ainsi :

    let a = Array.init 5 (fun i -> ref 1);;
    val a : int ref array =
     [|{contents = 1}; {contents = 1}; {contents = 1}; {contents = 1};{contents = 1}|]
    Array.iteri (fun i f -> f a.(i)) tab;;
    - : unit = ()
    a;;
    - : int ref array = 
     [|{contents = 1}; {contents = 2}; {contents = 3}; {contents = 4};{contents = 5}|]

    Mais en fait selon le problème que tu cherches à résoudre ce n'est pas toujours le même modèle de programmation (objet, fonctionnel, procédural) le plus efficace et avoir plusieurs outils ne nuit pas.

    Je n'ai jamais dit le contraire, d'ailleurs OCaml permet d'utiliser les paradigmes impératif, orienté objet et fonctionnel (mais vraiment du fonctionnel, pas l'ersatz que tu as illustré jusqu'à maintenant).

    En attendant, quand je ne trolles pas pour répondre à du troll, je fournis des réponses plus pertinentes et adaptées aux autres commentaires. Comme quand dans cette dépêche, freem se demandait à quoi pouvait servir les shared_ptr et que je lui ai proposé de s'en servir pour implémenter des tableaux immuables. D'ailleurs, j'attends toujours des adeptes du C++ qu'ils m'éclairent sur la pertinence de mon exemple.

    P.S: Bon, le lambda-calcul ça date de 1936, et on a du attendre C++11 pour en avoir un ersatz à lire tes exemples. Pour l'inférence de type et l'argorithme d'unification de Robinson qui en est la base, ça date de 1965. Il va falloir attendre combien de temps, pour celui-là ? L'algorithme en question est présenté sur le blog de la Société Informatique de France par Gilles Dowek.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.