Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Ingénieur
    Inscrit en
    septembre 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : septembre 2015
    Messages : 12
    Points : 7
    Points
    7

    Par défaut Surcharge d'une fonction récursive avec et sans generics

    Bonjour

    Je n'arrive pas à surcharger proprement une fonction récursive, qui peut prendre en argument un Array ou un Typed Array, et une fonction de comparaison.

    Typiquement il s'agit de l'algorithme Floyd-Rivest (les détails d'implémentation importent peu, l'algo fonctionne très bien avec un typage faible, je voulais juste définir des signatures propres).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    function swap(
      array: any[] | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array |
             Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array,
      idx1: number,
      idx2: number,
    ): void {
      const tmp = array[idx1];
      array[idx1] = array[idx2];
      array[idx2] = tmp;
    }
     
    function select(
      array: Int8Array | Uint8Array | Uint8ClampedArray | Int16Array |
             Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array,
      first: number,
      nth: number,
      last: number,
      comp: (a: number, b: number) => boolean,
    ): void;
    function select<T>(
      array: T[],
      first: number,
      nth: number,
      last: number,
      comp: (a: T, b: T) => boolean,
    ): void;
    function select<T>(
      array: Int8Array | Uint8Array | Uint8ClampedArray | Int16Array |
             Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array |
             T[],
      first: number,
      nth: number,
      last: number,
      comp: (a: number | T, b: number | T) => boolean,
    ): void {
      --last;
      while (first < last) {
        if (last - first > 600) {
          const n = last - first + 1;
          const m = nth - first + 1;
          const z = Math.log(n);
          const s = 0.5 * Math.exp(2 * z / 3);
          const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
          const newFirst = Math.max(first, Math.floor(nth - m * s / n + sd));
          const newLast = Math.min(last, Math.floor(nth + (n - m) * s / n + sd));
          select(array, newFirst, nth, newLast, comp);
        }
     
        const t = array[nth];
        let i = first;
        let j = last;
     
        swap(array, first, nth);
        if (comp(t, array[last])) swap(array, first, last);
     
        while (i < j) {
          swap(array, i++, j--);
          while (comp(array[i], t)) ++i;
          while (comp(t, array[j])) --j;
        }
     
        if (!comp(array[first], t)) {
          swap(array, first, j);
        } else {
          swap(array, ++j, last);
        }
     
        if (j <= nth) first = j + 1;
        if (nth <= j) last = j - 1;
      }
    }
    Il me sort l'erreur suivante pour l'argument array lors de l'appel récursif dans l'implémentation de la fonction (ligne 46) :
    [ts]
    L'argument de type 'Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | T[]' n'est pas attribuable au paramètre de type '(number | T)[]'.
    Impossible d'assigner le type 'Int8Array' au type '(number | T)[]'.
    La propriété 'pop' est manquante dans le type 'Int8Array'. [2345]
    Je comprends le message, mais je ne vois pas trop bien comment contourner le pb.

    Auriez vous une idée de la manière de définir proprement les signatures de la fonction, tout en gardant un typage fort?

    Des quelques modifs que j'ai pu tenter, il n'apprécie pas trop le fait d'avoir une surcharge sans <> juste après le nom de la fonction (à la ligne 12). Pourtant, avec des fonctions non récursives cela ne pose aucun problème.

  2. #2
    Futur Membre du Club
    Homme Profil pro
    Ingénieur
    Inscrit en
    septembre 2015
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Industrie

    Informations forums :
    Inscription : septembre 2015
    Messages : 12
    Points : 7
    Points
    7

    Par défaut

    Mmmhh, en fait un point m'avait échappé, la signature de l'implémentation peut être la plus générale possible puisqu'elle n'est pas reconnue dans le cas de surcharges.

    Du coup ceci fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    function select(
      array: Int8Array | Uint8Array | Uint8ClampedArray | Int16Array |
             Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array,
      first: number,
      nth: number,
      last: number,
      comp: (a: number, b: number) => boolean,
    ): void;
    function select<T>(
      array: T[],
      first: number,
      nth: number,
      last: number,
      comp: (a: T, b: T) => boolean,
    ): void;
    function select(
      array: any,
      first: number,
      nth: number,
      last: number,
      comp: (a: any, b: any) => boolean,
    ): void {
      // Implementation
    }
    Par contre, on ne bénéficie plus de typage dans l'implémentation (si on appelle la fonction par contre c'est bon), il y a peut être plus propre?

Discussions similaires

  1. Jeu du plus ou moins avec une fonction récursive
    Par Pimousse22 dans le forum C
    Réponses: 6
    Dernier message: 29/10/2014, 22h26
  2. Surchargé une fonction template avec template
    Par SKone dans le forum Langage
    Réponses: 2
    Dernier message: 12/10/2014, 21h00
  3. Réponses: 7
    Dernier message: 15/07/2011, 16h22
  4. Réponses: 3
    Dernier message: 03/03/2010, 20h05
  5. Permutation avec une fonction récursive
    Par nypahe dans le forum Débuter
    Réponses: 1
    Dernier message: 29/04/2009, 08h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo