Fable: Aide au développement de Fable 2

Créé le 21 mars 2018  ·  37Commentaires  ·  Source: fable-compiler/Fable

Je ne sais pas si la branche dev2.0 est déjà dans un état où je peux commencer à appeler à l'aide, mais je le ferai quand même :wink: Je liste ci-dessous les principaux changements qui se produisent dans cette branche, comment pouvez-vous le tester rapidement et quelles tâches sont en attente pour la première version alpha. Si vous souhaitez aider avec l'un d'entre eux, veuillez commenter ci-dessous afin que je puisse vous donner plus de détails pour travailler ensemble

Liste non exhaustive des principaux changements

  • Fable AST inclut désormais certaines des constructions les plus courantes en F# (liste, option...), il est donc plus facile de modifier leur représentation en JS si nécessaire. De plus, l'AST conserve désormais les informations de type du compilateur F#.
  • Les enregistrements et les unions ne seront pas compilés en tant que _classes_ JS mais en tant qu'objets simples et tableaux respectivement.
  • Toutes les méthodes de type sont désormais compilées en tant que fonctions de module JS pour une meilleure compatibilité avec le tremblement d'arbre (espérons que cela devrait également aider les moteurs JS à optimiser le code). La seule exception concerne les méthodes de substitution (ToString, Equals), qui sont attachées au prototype. De plus, les fonctions de module imbriquées sont compilées en tant que fonctions du module racine de fichier avec des noms mutilés.
  • Lors du transtypage d'une instance vers une interface, elle sera encapsulée avec un objet contenant les fonctions de l'interface, cela évite les conflits de noms entre les interfaces (et c'est également nécessaire car les méthodes ne sont plus attachées au prototype).
  • Certains modules de fable-core (comme List ou Array) sont maintenant écrits en F#
  • Les optimisations appliquées à la Fable AST sont désormais des passes isolées se produisant dans FableTransforms . Cela devrait rendre le code plus facile à maintenir que Fable 1, où les optimisations sont généralement appliquées à plusieurs endroits (en particulier l'optimisation sans frais, qui, espérons-le, fonctionnera beaucoup mieux dans Fable 2). Certaines optimisations restent cependant à faire lors de la dernière passe de Fable2Babel : tail-calls et arbres de décision (pattern matching).

Essayez-le rapidement

  • Clonez le dépôt si vous ne l'avez pas déjà fait
  • git checkout dev2.0
  • cd src/tools
  • bash quicktest.sh --build-core

Cela compilera et exécutera le fichier QuickTest.fs dans le même dossier. N'hésitez pas à l'utiliser comme terrain de jeu pour tester les fonctionnalités de Fable 2 (mais merci de ne pas l'inclure dans vos PR). La deuxième fois, si les fichiers src/js/fable-core n'ont pas changé, vous pouvez simplement exécuter bash quicktest.sh (si les fichiers src/dotnet/Fable.Compiler n'ont pas changé, vous pouvez également exécuter bash quicktest.sh --no-build mais avec 2.1.300-preview1, la construction d'un projet sans modifications devrait être assez rapide de toute façon).

Sous Windows, vous devriez pouvoir exécuter le script à l'aide de Git bash.

Tâches en attente

  • Il y a un certain nombre de TODO!!! commentaires répartis dans le code, je devrais probablement les gérer moi-même.

  • Comme les plugins ne seront pas inclus dans la première version alpha, les tests utilisent désormais l'API Expecto , qui est beaucoup plus facile à partager avec les testeurs JS. J'ai déjà converti certains fichiers (ArithmeticTests, ArrayTests, ListTests) mais la plupart d'entre eux attendent toujours un peu d'amour. J'utilisais Regex pour changer la signature des méthodes en testCase mais c'est probablement une bonne idée d'écrire un script pour cela. L'un des principaux défis est que, étant donné que les tests sont désormais des valeurs dans une liste, les fonctions supplémentaires qui apparaissent au milieu du fichier doivent être déplacées vers le haut, ce qui peut masquer d'autres valeurs dans certains cas.

  • Les modules Set et Map de fable-core doivent être portés en F#. Je l'ai partiellement fait pour Set (La carte peut également être extraite du référentiel FunScript où j'ai initialement volé son inspiration). Nous devons nous assurer qu'ils sont correctement compilés en JS, que les noms des fonctions publiques sont correctement exposés, vérifiez si nous devons porter les méthodes des fichiers .ts précédents (enregistrés dans src/tools/old ) et si les tests fonctionnent correctement .

  • Parce que l'AST a tellement changé, la plupart du module Remplacements doit être réécrit . J'ai déjà fait environ 1000 lignes et il en reste encore mille. C'est une tâche un peu fastidieuse, mais si quelqu'un est assez fou pour s'en charger, n'hésitez pas à me le faire savoir. Le moyen le plus rapide est peut-être d'avoir une session de partage d'écran pour vous montrer ce qui doit être fait, puis de diviser le code restant afin que nous puissions terminer plus rapidement.

Choses qui ne seront pas incluses dans la première version alpha : bigint, réflexion, plugins.

J'espère que c'est assez d'informations pour l'instant, merci beaucoup pour votre aide d'avance!

dev2.0 help wanted

Commentaire le plus utile

Juste pour info, si quelqu'un porte les fichiers de test pas besoin de porter SetTests.fs et MapTests.fs je le ferai pour tester l'intégration du module.

De plus, si vous utilisez VSCode, vous pouvez utiliser la sélection multiple pour effectuer tout le travail à la fois dans un fichier. L'écriture d'un script semble un peu trop compliquée ici :).

2018-04-18 15 14 27

Tous les 37 commentaires

@alfonsogarciacaro Je pense que je vais prendre les modules Set et Map dans la tâche Set partiellement porté afin que je puisse m'inspirer d'ici :) ?

Juste un rappel, il y a beaucoup de prises en pension que nous pouvons inspirer étole de,

  1. La bibliothèque principale officielle de visualfsharp, son implémentation de la carte ressemble vraiment à celle de FunScript :
    https://github.com/Microsoft/visualfsharp/blob/master/src/fsharp/FSharp.Core/map.fs
  2. OCaml/BucleScript, il n'y a pas beaucoup de différences entre F# et la syntaxe de base d'OCaml, je pense que nous pouvons facilement les porter vers F#.
    https://github.com/BuckleScript/bucklescript/blob/master/jscomp/stdlib/map.ml

Merci, @zaaack. Oui, le fichier FunScript a été extrait à l'origine de FSharp.Core. Je ne sais pas si c'est obsolète mais j'ai tendance à le préférer parce que ça marche déjà ( Map.ts dans Fable 1 était aussi à l'origine une traduction de celui-ci) et je pense qu'il a déjà coupé certaines des choses que nous ne faisons pas besoin en JS. À propos de Bucklescript, je ne sais pas si le fait que les modules soient des valeurs en OCaml puisse être problématique, aussi Map en F# doit être conforme à certaines interfaces, et ce qui m'a pris le plus de temps, c'est de faire en sorte que les types avec comparaison personnalisée fonctionnent correctement en tant que clés, ce qui Je suppose que c'est aussi quelque peu différent en OCaml.

BTW, Bigint est en effet tiré de FSharp.Core mais je pense que nous le portons dans une version ultérieure.

Merci @zaaack, je garderai cela à l'esprit lorsque je travaillerai sur le port.

Salut Alfonso, je voudrais aider sur la partie test expecto

C'est super @EdouardM , merci ! Ce serait formidable si vous pouviez écrire un script pour faire la plupart de la conversion automatiquement. Si vous le souhaitez, nous pouvons organiser une courte session de partage d'écran pour montrer ce qui doit être fait :)

Bien sûr, j'aurai besoin d'un bref coup d'envoi pour me mettre sur la bonne voie.

Seriez-vous disponible ce soir à partir de 18h30 heure de paris-madrid
ou le dimanche ?

Si vous êtes s'il vous plaît envoyez-moi une invitation pour un appel skype.

Merci
Édouard

Le ven. 23 mars 2018 à 11:43, Alfonso Garcia-Caro [email protected]
un écrit :

C'est super @EdouardM https://github.com/edouardm , merci ! Ce serait
ce serait génial si vous pouviez écrire un script pour tirer le meilleur parti de la conversion
automatiquement. Si vous le souhaitez, nous pouvons organiser une courte session de partage d'écran pour
montre ce qu'il faut faire :)

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/fable-compiler/Fable/issues/1370#issuecomment-375619541 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AG_t3dil59Mz38u4cCN9f0JEZMyK7OLRks5thNHPgaJpZM4S03ig
.

Mon email est : edouard. [email protected]

Le ven. 23 mars 2018 à 11:43, Alfonso Garcia-Caro [email protected]
un écrit :

C'est super @EdouardM https://github.com/edouardm , merci ! Ce serait
ce serait génial si vous pouviez écrire un script pour tirer le meilleur parti de la conversion
automatiquement. Si vous le souhaitez, nous pouvons organiser une courte session de partage d'écran pour
montre ce qu'il faut faire :)

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/fable-compiler/Fable/issues/1370#issuecomment-375619541 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AG_t3dil59Mz38u4cCN9f0JEZMyK7OLRks5thNHPgaJpZM4S03ig
.

Choses qui ne seront pas incluses dans la première version alpha : bigint, réflexion, plugins.

Juste curieux, existe-t-il une feuille de route / un plan pour inclure ces éléments après l'Alpha ?

@jgrund Aucune feuille de route spécifique, mais bigint devrait être facile à ajouter (il suffit de porter le code de FSharp.Core) et la réflexion devrait également être prête pour la version stable. À propos des plugins, j'aimerais collecter des informations sur la façon dont ils sont utilisés, puis décider ensemble comment nous devons les apporter ou s'ils sont vraiment nécessaires.

Merci pour cela! J'ai dû apporter une petite modification à quicktest.sh pour que cela fonctionne dans Git-Bash :
https://github.com/fable-compiler/Fable/blob/07ddd104cbeb6ad7adf98b6600ac3fe4d1fcfd70/src/tools/quicktest.sh#L30 -L33
Modification de la ligne 32 en simplement :
./quickfsbuild.sh --no-build
puisque le bash là-dedans (que je ne pense pas nécessaire de toute façon ?) faisait que WSL essayait de démarrer à la place, ce que je n'ai pas configuré.

Salut @EdouardM ! C'est ce dont nous avons discuté à fsharpX à propos de la mise à jour des tests :

  • Utilisation de l'API Expecto (sera en fait traduit en moka pour JS)
  • Utilisez regex let ``(.*)``.*= et remplacement testCase "$1" <| fun () -> pour changer la signature des tests
  • Supprimer les attributs [<Test>] , [<TestFixture>]
  • Ajoutez le fichier à Main.fsproj et allTests dans tests/Main/Main.fs
  • Une attention particulière est nécessaire pour l'async et les fonctions au milieu des tests, nous pourrons en parler plus tard.

@alfonsogarciacaro Je lis le code source de la branche dev2.0, essayant d'être le "fou" pour travailler sur le reste de Replacement.fs puisque les deux autres sont tous les deux pris 😄. J'ai rencontré quelques problèmes lors du portage de la fonction parse de l'ancien Replacement.fs , la fonction parse dépend de returnType qui existe dans Fable.ApplyInfo dans Fable 1.0, mais je ne le trouve pas dans CallInfo , je ne sais pas comment gérer cela, pourriez-vous m'aider ?

Voici mon commit :
https://github.com/fable-compiler/Fable/compare/dev2.0...zaaack :dev2.0?expand=1#diff-a34e57b30a53951ff9b99ce4076feaa4R1390

Ce serait génial @zaaack , merci beaucoup. Et oui, désolé, je modifie un peu la signature des fonctions dans les remplacements pour qu'elles ressemblent davantage à des fonctions dans d'autres modules, où se trouvent généralement les trois premiers arguments (le contexte peut également venir après en second lieu):

let myFableHelper (com: ICompiler) (range: SourceLocation option) (typ: Type) ... =

Pour cette raison, j'ai déplacé le type de retour (et la plage) de CallInfo aux premiers arguments de la fonction. Vous pouvez utiliser quelque chose comme let parse com r t info thisArg args = (oui, j'utilise habituellement juste t et je suis d'accord que ce n'est pas très significatif).

Je travaille également dans le module Remplacements. Je peux m'attaquer aux collections (Seq, List, Array) pendant que vous remplissez les autres fonctions, qu'en pensez-vous ?

J'ai récemment ajouté un type statique Helper afin d'utiliser des membres statiques avec des paramètres facultatifs. Veuillez consulter le code existant pour voir comment les aides InstanceCall , CoreCall ... sont utilisées. Autres notes:

  • Il est important de transmettre correctement les types d'arguments (spécialement s'il y a des fonctions) pour l'optimisation continue qui se produit à un stade ultérieur. Si les arguments ne sont pas modifiés, transmettez-les directement depuis CallInfo . S'ils le sont, les types d'arguments doivent être recalculés.
  • ThisArg est facultatif. S'il est présent, il sera adopté en premier lieu. Dans Fable 2, les membres d'instance de type sont en fait compilés en tant que fonctions statiques et c'est pourquoi this est passé en argument. ArgTypes n'inclut pas ThisArg .
  • Cependant, lorsque InstanceCall kind est spécifié, l'expression ThisArg sera compilée en tant qu'appel d'instance réel : thisArg.member(arg1, arg2...) .

Cela devrait suffire pour le moment :) Veuillez vérifier avec moi si vous avez des questions et encore une fois, merci beaucoup pour votre aide !

Merci pour votre réponse rapide et détaillée, j'essaierai demain.

Je travaille également dans le module Remplacements. Je peux m'attaquer aux collections (Seq, List, Array) pendant que vous remplissez les autres fonctions, qu'en pensez-vous ?

Super, je pense que je peux passer deux heures en semaine et une journée entière le week-end, principalement.

Juste pour info, si quelqu'un porte les fichiers de test pas besoin de porter SetTests.fs et MapTests.fs je le ferai pour tester l'intégration du module.

De plus, si vous utilisez VSCode, vous pouvez utiliser la sélection multiple pour effectuer tout le travail à la fois dans un fichier. L'écriture d'un script semble un peu trop compliquée ici :).

2018-04-18 15 14 27

Merci Maxime je vais m'occuper des conversions des fichiers de tests.
Edouard

Le 18 avril 2018 15:16, "Maxime Mangel" [email protected] a écrit :

Juste pour info, si quelqu'un porte les fichiers de test, pas besoin de porter
SetTests.fs et MapTests.fs Je vais le faire pour tester l'intégration du module.

De plus, si vous utilisez VSCode, vous pouvez utiliser la sélection multiple pour faire tout le travail
à la fois dans un fichier. Écrire un script semble un peu trop compliqué
ici :).

[image: 2018-04-18 15 14 27]
https://user-images.githubusercontent.com/4760796/38934173-59a5fc84-431b-11e8-81be-13f624e72817.gif

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/fable-compiler/Fable/issues/1370#issuecomment-382382463 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AG_t3YjH5jvU1CXc-27gpz4-tGQNC7AHks5tpzyegaJpZM4S03ig
.

Salut à tous encore ! Nous devons encore implémenter les méthodes suivantes dans src/js/fable-core/List.fs (notez qu'il s'agit d'un fichier F# bien qu'il soit distribué en JS) :

  • [x] tronquer
  • [x] concaténer
  • [ ] findRetour
  • [ ] findIndexBack
  • [ ] essayezRechercher
  • [ ] tryFindIndexBack
  • [x] indexé
  • [ ] mapFold
  • [ ] mapFoldBack
  • [x] tryItem
  • [x] déplier
  • [x] splitAt

Ceux-ci sont implémentés mais les tests ne réussissent pas :

  • [x] foldBack2
  • [x] partition

Ceux-ci sont un peu particuliers car Fable doit injecter IEqualityComparer comme argument supplémentaire. Je peux le faire moi-même mais si vous êtes assez courageux vous pouvez prendre sort comme exemple :

  • [x] distincts
  • [x] distinctPar
  • [ ] par groupe
  • [ ] compterPar
  • [ ] contient
  • [ ] sauf

J'ai mis les tests défaillants dans le fichier QuickTest.fs , vous devriez donc pouvoir recompiler Fable + fable-core et exécuter les tests simplement en tapant :

cd src/tools
sh quicktest.sh --build-core

Des volontaires? ;) @valery-vitko @zaaack

Je vais voir ce que je peux faire ce week-end.

Je suis emballé complet pour les semaines à venir, malheureusement. (Et surtout avec des trucs non liés à la programmation 😢) . Amusez-vous sans moi, les gars.

J'ai corrigé les partition et foldBack2 dans #1405.
Je vais essayer de faire d'autres fonctions simples, j'ai fait truncate et indexed .

Implémenté unfold , tryItem , splitAt et concat .

Salut! Il y a encore quelques méthodes manquantes dans la liste ci-dessus . Est-ce que quelqu'un travaille dessus ? Sinon, je vais essayer :+1:

@alfonsogarciacaro Désolé d'avoir pensé qu'ils étaient tous pris, je prendrai le reste.

PR : https://github.com/fable-compiler/Fable/pull/1406

Question considérant la nouvelle manière de traiter les méthodes et les interfaces ; comment seront traités les éléments suivants ?

type Base () =
  abstract M: unit -> string
  default __.M () = "base"

type A () =
  inherit Base ()
  member __.M () = "a" // NOTE: Not override, hides parent M

type B () =
  inherit Base ()
  override __.M () = "b"

let a = A ()
let b = B ()

printfn "%s" <| (a :> Base).M ()
printfn "%s" <| (b :> Base).M ()

Fable 2 implémente ses propres membres en tant que fonctions de module et résout les références au moment de la compilation. Cependant, les méthodes virtuelles sont attachées au prototype JS afin qu'elles puissent être appelées même après la conversion ascendante de l'objet. Donc cette version légèrement étendue de votre code (pour montrer comment un objet peut appeler le membre parent) :

type Base () =
  abstract M: unit -> string
  default __.M () = "base"

type A () =
  inherit Base ()
  member __.M () = base.M() + " + a" // NOTE: Not override, hides parent M

type B () = 
  inherit Base ()
  override __.M () = base.M() + " + b"

let a = A ()
let b = B ()

printfn "A:        %s" <| a.M ()
printfn "A upcast: %s" <| (a :> Base).M ()
printfn "B:        %s" <| b.M ()
printfn "B upcast: %s" <| (b :> Base).M ()

Compilé avec le dernier dotnet-fable 2.0.0-alpha devient :

function Base() {}

function Base$$$$002Ector() {
  return this != null ? Base.call(this) : new Base();
}

Base.prototype.M = function () {
  return "base";
};

function A() {
  Base$$$$002Ector.call(this, null);
}

(0, _Types.inherits)(A, Base);

function A$$$$002Ector() {
  return this != null ? A.call(this) : new A();
}

function A$$M(__$$1) {
  return Base.prototype.M.call(this) + " + a";
}

function B() {
  Base$$$$002Ector.call(this, null);
}

(0, _Types.inherits)(B, Base);

function B$$$$002Ector() {
  return this != null ? B.call(this) : new B();
}

B.prototype.M = function () {
  return Base.prototype.M.call(this) + " + b";
};

const a = exports.a = A$$$$002Ector();
const b = exports.b = B$$$$002Ector();
(0, _String.toConsole)((0, _String.printf)("A:        %s"))(A$$M(a));
(0, _String.toConsole)((0, _String.printf)("A upcast: %s"))(a.M());
(0, _String.toConsole)((0, _String.printf)("B:        %s"))(b.M());
(0, _String.toConsole)((0, _String.printf)("B upcast: %s"))(b.M());

Et imprime :

A:        base + a
A upcast: base
B:        base + b
B upcast: base + b

@alfonsogarciacaro Y aura-t-il un moyen de désactiver complètement la méthode -> conversion de module et d'obtenir le résultat propre de la Fable 1 ?

@vbfox Non, désolé. Cela affecterait beaucoup le fonctionnement de Fable 2 et, malheureusement, je n'ai pas les ressources nécessaires pour maintenir les indicateurs du compilateur afin de générer différentes sorties :/

Je comprends parfaitement le problème de ressources mais c'est triste car cela casse beaucoup de compatibilité entre fable et le monde JS au moins lors de l'utilisation de classes n'importe où :

  • Création d'un package npm avec fable pour la consommation JS
  • Utiliser plusieurs langages pour accéder à la classe générée par la fable (dactylographe) ou doit avoir des liaisons très étranges...

(Les cas où des bibliothèques externes effectuent une détection de méthode nécessiteront également la création d'une interface, mais c'est surtout une bonne pratique)

C'est aussi s'éloigner de JS dont tu peux être fier au moins pour les cours - même si on s'en fout ;)

Oui, le code généré sera un peu _moins beau_ dans Fable 2. Mais il y a d'autres avantages (meilleure secousse des arbres, répartition statique) qui, j'espère, compenseront ce fait. À propos de la création de bibliothèques dans Fable pour la consommation JS, ce sera toujours possible, même si je n'ai vu aucun exemple réel de cela. Et j'ai déjà renoncé à utiliser Typescript dans mes projets Fable car il compile toujours chaque fois que j'essaie d'importer un fichier .fs ;)

Le moyen d'interopérer avec JS devrait être des interfaces. Fable va maintenant générer des wrappers d'objets avec des noms non mutilés pour les interfaces afin que vous puissiez les utiliser pour envoyer des types à JS ou à d'autres langages.

@alfonsogarciacaro J'ai vraiment voulu créer des bibliothèques pour la consommation en JS faites avec Fable, mais c'était une douleur tellement importante que j'ai abandonné. C'est la principale raison pour laquelle je n'utilise pas Fable beaucoup plus qu'actuellement. J'ai conclu que cela ne fonctionne que pour la création d'applications (qu'elles soient Web ou non).

Merci pour la confirmation @Alxandr. C'était donc déjà douloureux dans Fable 1, ce qui signifie que Fable 2 ne peut pas aggraver les choses ;)

@alfonsogarciacaro en quelque sorte vrai. Et je ne pense pas que passer à la statique va avoir de l'importance (car les objets d'interface sont une très bonne solution). Mais je pense que cela pourrait justifier de parler de POURQUOI c'est extrêmement douloureux, parce que je pense qu'une partie de cela pourrait être résolue par la fable 2. Et je pense que le principal problème est le fait que fable-core vit sur nuget et non sur npm (le js fichiers qui est). Cela signifie que si j'ai une bibliothèque et une application intégrée en F#, j'ai maintenant deux copies de Map et List , etc. Et vous avez également cassé instanceof .. .

Vrai. En fait, nous avons essayé de résoudre ce problème à un moment donné (dans Fable 0.7 je pense, lorsque fable-core et Fable lui-même ont été distribués via npm) mais fable-core a beaucoup changé et gérer correctement les versions était un cauchemar (nous devions également conserver les versions pour différents systèmes de modules). La situation est bien meilleure depuis Fable 1 où les fichiers fable-core sont juste injectés par le compilateur et nous avons toujours les fichiers synchronisés. Je ne pense pas que la création de bibliothèques Fable pour npm qui soient également utilisées nativement par Fable soit faisable. Vous créez soit une bibliothèque JS (exposant une surface d'API JS et de préférence un regroupement), soit écrivez une bibliothèque Fable/F# qui est distribuée via Nuget.

L'écosystème JS est très large et Fable ouvre de nombreuses opportunités pour F#. Malheureusement, ma portée est limitée et je ne peux pas tout prendre en compte lors de la prise de décisions de conception. Jusqu'à présent, généralement l'introduction de Fable dans différents domaines : applications Web Elmish, React Native, Electron... Mais je n'ai pas encore vu cela pour les bibliothèques JS créées avec Fable, à l'exception de quelques petits échantillons.

Ouais, non, je comprends tout à fait. Ma solution "be-all-end-all" serait probablement une situation dans laquelle vous construisez fable-core (bibliothèques andy F#/js) sur un CI et publiez sur NuGet et NPM en même temps. De cette façon, vous n'auriez pas non plus besoin de fichiers source F# sur nuget (vous n'auriez que des métadonnées de construction, mais vous auriez besoin du nom d'importation npm). Cependant, de nombreux éléments doivent être réunis pour que cela fonctionne, et cela peut nécessiter le stockage d'un tas de métadonnées dans le package nuget (mappage vers les noms de fonction JS qui ont été générés).

J'ai donc beaucoup réfléchi à la nouvelle sortie de Fable aujourd'hui et j'ai proposé quelques problèmes que j'aimerais soulever au cas où ils n'auraient pas été pris en compte :

Classes vs fonctions

Je ne suis pas moi-même un grand fan des classes en JS, cependant, elles servent un objectif important qui ne peut pas être atteint avec des fonctions (pour autant que je sache), à ​​savoir étendre les classes natives (comme Map ou Array ). Maintenant, je suppose que les principales raisons de l'utilisation de fonctions au lieu de classes sont le fait que vous devez gérer plusieurs constructeurs, mais je suis raisonnablement certain que cela peut être résolu d'autres manières (je vais y regarder un peu plus demain). Maintenant, juste pour être clair, je ne parle pas de revenir à tout attacher au prototype. Je parle juste de faire du constructeur primaire (ou synthétique) une classe. Quant à la possibilité d'appeler les constructeurs sans new , je pense que c'est un point plutôt discutable, compte tenu du fait que F# est un langage typé, et Fable devrait être capable de déterminer statiquement s'il doit émettre new ou pas en fonction de la fonction qu'il appelle.

Casting d'interface et contrôles de type

J'ai vu du code qui traite bien les hiérarchies de types et permet la vérification de type et l'appel de membres virtuels, ce qui est assez agréable, mais comment la nouvelle sortie fonctionne-t-elle avec les interfaces en conjecture avec les vérifications de type ? Prenons par exemple le code suivant :

type IFoo =
  abstract Foo: string

type IBar =
  abstract Bar: string

type FooBar () =
  interface IFoo with
    member __.Foo = "foo"

  interface IBar with
    member __.Bar = "bar"

let check (t: bool) =
  if not t then failwithf "test failed"

let test () =
  let foobar = FooBar ()
  let foo = foobar :> IFoo
  let bar = foobar :> IBar
  let obj = foobar :> obj

  check (foo :? FooBar)
  check (bar :? FooBar)
  check (foo :? IBar)
  check (bar :? IFoo)
  check (obj :? IFoo)
  check (obj :? IBar)
  ()

Nous pouvons clore ce problème maintenant, merci beaucoup à tous pour votre aide dans la sortie de Fable 2 !

Cette page vous a été utile?
0 / 5 - 0 notes