40 votes

Question Scala contre F #: comment unissent-ils les paradigmes OO et FP?

Quelles sont les principales différences entre les approches adoptées par Scala et F # pour unifier les paradigmes OO et FP?

MODIFIER

Quels sont les avantages et inconvénients relatifs de chaque approche? Si, malgré le support pour le sous-typage, F # peut déduire les types d'arguments de fonction, alors pourquoi pas Scala?

43voto

Daniel C. Sobral Points 159554

J'ai regardé F#, faire des faible niveau de tutoriels, donc mes connaissances sont très limitées. Cependant, il était évident pour moi que son style a été essentiellement fonctionnelle, avec OO être plus comme un add-on, beaucoup plus d'un ADT + module de système que le vrai OO. Le sentiment que j'ai peut être mieux décrit comme si toutes les méthodes sont statiques (comme en Java statique).

Voir, par exemple, le code en utilisant le tuyau de l'opérateur (|>). Prendre cet extrait de l' article de wikipédia sur F#:

[1 .. 10]
|> List.map     fib

(* equivalent without the pipe operator *)
List.map fib [1 .. 10]

La fonction map n'est pas une méthode de la liste de l'instance. Au lieu de cela, il fonctionne comme une méthode statique sur un List module qui prend une liste d'instance que l'un de ses paramètres.

Scala, d'autre part, est entièrement OO. Commençons, tout d'abord, avec la Scala équivalent de ce code:

List(1 to 10) map fib

// Without operator notation or implicits:
List.apply(Predef.intWrapper(1).to(10)).map(fib)

Ici, map est une méthode sur l'exemple de l' List. Statique méthodes, telles que l' intWrapper sur Predef ou apply sur List, sont beaucoup plus rares. Ensuite, il y a des fonctions, telles que l' fib - dessus. Ici, fib n'est pas une méthode sur int, mais ce n'est pas une méthode statique. Au lieu de cela, il est un objet -- la deuxième principale différence que je vois entre F# et Scala.

Considérons le F# la mise en œuvre de la Wikipedia, et un équivalent de la Scala de mise en œuvre:

// F#, from the wiki
let rec fib n =
    match n with
    | 0 | 1 -> n
    | _ -> fib (n - 1) + fib (n - 2)

// Scala equivalent
def fib(n: Int): Int = n match {
  case 0 | 1 => n
  case _ => fib(n - 1) + fib(n - 2)
}

Au-dessus de la Scala de mise en œuvre est une méthode, mais Scala convertit en une fonction pour être en mesure de passer à l' map. Je vais le modifier en dessous de sorte qu'il devient une méthode qui retourne une fonction au lieu de cela, pour montrer comment les fonctions de travail en Scala.

// F#, returning a lambda, as suggested in the comments
let rec fib = function 
    | 0 | 1 as n -> n 
    | n -> fib (n - 1) + fib (n - 2)

// Scala method returning a function
def fib: Int => Int = {
  case n @ (0 | 1) => n
  case n => fib(n - 1) + fib(n - 2)
}

// Same thing without syntactic sugar:
def fib = new Function1[Int, Int] {
  def apply(param0: Int): Int = param0 match {
    case n @ (0 | 1) => n
    case n => fib.apply(n - 1) + fib.apply(n - 2)
  }
}

Donc, en Scala, toutes les fonctions sont des objets de mise en œuvre de ce trait FunctionX, ce qui définit une méthode appelée apply. Comme indiqué ici et dans la création d'une liste ci-dessus, .apply peut être omis, ce qui rend les appels de fonction ressemble juste à des appels de méthode.

À la fin, tout en Scala est un objet -- et de l'instance d'une classe, et chaque objet appartient à une classe, et de tous les codes appartiennent à une méthode, qui est exécuté en quelque sorte. Même match dans l'exemple ci-dessus est utilisé pour être une méthode, mais a été convertie en un mot-clé pour éviter des problèmes tout à fait il ya un moment.

Alors, comment sur la partie fonctionnelle de celui-ci? F# appartient à l'une des plus traditionnelles familles de langages fonctionnels. Alors qu'il n'a pas certaines fonctionnalités, certaines personnes sont importantes pour les langages fonctionnels, le fait est que le F# est la fonction par défaut, pour ainsi dire.

Scala, d'autre part, a été créé avec l'intention d' unifier fonctionnelle et OO modèles, au lieu de la simple fourniture d'eux en tant que parties séparées de la langue. Dans la mesure où il a été couronné de succès dépend de ce que vous estimez être de la programmation fonctionnelle. Voici certaines des choses qui ont été porté par Martin Odersky:

  • Les fonctions sont des valeurs. Ils sont aussi des objets -- parce que toutes les valeurs sont des objets Scala-mais l'idée qu'une fonction est une valeur qui peut être manipulé est une question importante, avec ses racines tout le chemin du retour à l'origine Lisp mise en œuvre.

  • Un soutien fort pour immuable types de données. La programmation fonctionnelle a toujours été préoccupé par la diminution des effets secondaires sur un programme, que les fonctions peuvent être analysés comme de véritables fonctions mathématiques. Scala fait, il est facile de faire des choses immuables, mais il n'a pas faire deux choses qui FP puristes critiquent pour:

    • Il ne fait pas de la mutabilité plus difficile.
    • Il ne fournit pas un effet de système, par lequel la mutabilité peut être statique d'un suivi.
  • Support pour les Types de Données Algébriques. Types de données algébriques (appelé ADT, qui de prêter à confusion, est également un Type Abstrait de Données, une chose différente) sont très fréquents dans la programmation fonctionnelle, et sont plus utiles dans les situations où l'on utilisent généralement le modèle visiteur dans les langages à objets.

    Comme tout autre chose, ADTs en Scala sont mis en œuvre sous forme de classes et de méthodes, avec quelques sucres syntaxiques pour les rendre facile à utiliser. Cependant, la Scala est beaucoup plus bavarde que F# (ou autres langages fonctionnels, d'ailleurs) qui les soutiennent. Par exemple, au lieu de F#'s | pour les états, il utilise case.

  • Le soutien à la rigueur. Non-rigueur signifie seulement le calcul des trucs sur demande. C'est un aspect essentiel de Haskell, où il est étroitement intégré avec l'effet secondaire du système. En Scala, cependant, la non-rigueur soutien est très timide et débutante. Il est disponible et utilisé, mais dans une manière restreinte.

    Par exemple, la Scala, à la non-stricte de la liste, l' Stream, n'est pas en faveur d'une véritable non-stricte foldRight, comme Haskell n'. En outre, certains avantages de la non-rigueur sont acquis seulement lorsque c'est la valeur par défaut dans la langue, au lieu d'une option.

  • Soutien pour la compréhension de liste. En fait, Scala appelle pour-de la compréhension, que la façon dont il est mis en œuvre est complètement dissociée des listes. Dans ses termes les plus simples, interprétations de la liste peut être considéré comme l' map fonction/méthode indiquée dans l'exemple, bien que l'imbrication de la carte des états (compatible avec flatMap en Scala) ainsi que le filtrage (filter ou withFilter en Scala, selon la rigueur des exigences) sont généralement prévu.

    C'est une opération très courante dans les langages fonctionnels, et souvent de la lumière dans la syntaxe -- comme en Python in de l'opérateur. Encore une fois, la Scala est un peu plus bavard que d'habitude.

À mon avis, la Scala est inégalé dans la combinaison de FP et OO. Il s'agit de l'OO côté du spectre vers la FP côté, ce qui est inhabituel. Surtout, je vois FP langues avec OO attaquer sur elle -- et il se sent attaquer sur-le-moi. Je suppose que FP sur Scala probablement se sent de la même façon pour les langages fonctionnels programmeurs.

MODIFIER

La lecture de certains autres réponses que j'ai réalisé qu'il y avait un autre sujet important: l'inférence de type. Lisp est un typées dynamiquement de la langue, et c'est à peu près défini les attentes pour les langages fonctionnels. Le moderne typé statiquement les langages fonctionnels ont tous une forte inférence de type de systèmes, le plus souvent, le Hindley-Milner1 de l'algorithme, ce qui rend les déclarations de type essentiellement en option.

Scala ne pouvez pas utiliser la Hindley-Milner algorithme en raison de la Scala de soutien pour l'héritage2. Scala a à adopter une beaucoup moins puissant algorithme d'inférence de types, en fait, l'inférence de type en Scala est intentionnellement pas défini dans le cahier des charges, et sous réserve de l'amélioration continue (perfectionnement est l'une des plus grandes caractéristiques de la prochaine version 2.8 de la Scala, par exemple).

En fin de compte, cependant, Scala exige que tous les paramètres pour avoir leurs types déclaré lors de la définition des méthodes. Dans certaines situations, comme la récursivité, types de retour pour les méthodes doivent également être déclarés.

Fonctions Scala ont souvent leurs types inférés au lieu d'déclaré, cependant. Par exemple, pas de déclaration de type est nécessaire ici: List(1, 2, 3) reduceLeft (_ + _)_ + _ est en fait une fonction anonyme de type Function2[Int, Int, Int].

De même, la déclaration de type de variables est souvent inutile, mais l'héritage peuvent l'exiger. Par exemple, Some(2) et None ont une commune de la superclasse Option, mais en réalité, appartiennent à différents subclases. Donc, en général, déclarer var o: Option[Int] = None à assurez-vous que le type est affecté.

Cette forme limitée de l'inférence de type est beaucoup mieux que les langages à objets à typage statique offrent habituellement, qui donne à la Scala un sentiment de légèreté, et bien pire que statiquement typé FP langues offrent habituellement, qui donne à la Scala un sentiment de heavyness. :-)

Notes:

  1. En fait, l'algorithme est originaire de Damas et Milner, qui l'a appelé "Algorithme W", selon wikipédia.

  2. Martin Odersky mentionné dans un commentaire ici que:

    La raison de la Scala n'a pas de Hindley/Milner, l'inférence de type est qu'il est très difficile de combiner avec des fonctionnalités telles que la surcharge (ad-hoc variante, pas de classes de type), record la sélection, et le sous-typage

    Il poursuit en affirmant qu'il ne peut pas être impossible, et il est descendu à un compromis. S'il vous plaît ne allez à ce lien pour plus d'informations, et si vous venez avec une meilleure instruction ou, mieux encore, certains le papier d'une manière ou d'une autre, je lui en serais reconnaissant pour la référence.

    Permettez-moi de remercier Jon Harrop pour regarder cela, comme je l'ai été en supposant que c'était impossible. Eh bien, peut-être que c'est, et je ne pouvais pas trouver un lien. Notez, cependant, qu'il n'est pas d'héritage à lui seul à l'origine du problème.

14voto

Dario Points 26259

F# est fonctionnel, Il permet OO assez bien, mais le design et la philosophie est fonctionnel, tout de même. Exemples:

  • Haskell fonctions de style
  • Automatique de nourrissage
  • Automatique des génériques
  • L'inférence de Type pour les arguments

Il se sent relativement maladroit d'utiliser F# dans un principalement orientée objet, de façon, on pourrait décrire l'objectif principal que pour intégrer OO en programmation fonctionnelle.

Scala est multi-paradigme avec l'accent sur la flexibilité. Vous pouvez choisir entre authentique de la FP, de la programmation orientée objet et procédural de style en fonction de ce qui convient le mieux. Il s'agit vraiment d' unifier OO et la programmation fonctionnelle.

13voto

Tomas Petricek Points 118959

Il ya quelques points que vous pouvez utiliser pour comparer les deux (ou trois). Tout d'abord, voici quelques points importants que je peux penser:

  • La syntaxe
    Du point de vue syntaxique, F# et OCaml sont basées sur la programmation fonctionnelle, la tradition (séparés par un espace et plus léger), tandis que Scala est basé sur le style orienté objets (bien que Scala rend plus léger).

  • L'intégration de OO et FP
    Les deux F# et Scala très bien intégrer OO avec FP (car il n'y a pas de contradiction entre ces deux-là!!) Vous pouvez déclarer des classes de tenir des données immuables (aspect fonctionnel) et de fournir aux membres relatives à l'utilisation des données, vous pouvez également utiliser les interfaces pour l'abstraction (orienté objet aspects). Je ne suis pas aussi familier avec OCaml, mais je pense qu'il met davantage l'accent sur l'OO côté (par rapport à F#)

  • Le style de programmation en F#
    Je pense que le style de programmation utilisé dans F# (si vous n'avez pas besoin d'écrire .NET-library et n'ont pas d'autres limitations) est sans doute plus fonctionnel et que vous souhaitez utiliser OO fonctions uniquement lorsque vous en avez besoin. Cela signifie que vous groupe de fonctions à l'aide de fonctions, des modules et des types de données algébriques.

  • Le style de programmation en Scala
    En Scala, la valeur par défaut du style de programmation est plus orienté objet (dans l'organisation), mais vous avez encore (probablement) écrire des programmes fonctionnels, parce que le "standard" consiste à écrire du code qui évite de mutation.

13voto

Jon Harrop Points 26951

Quelles sont les principales différences entre les approches adoptées par Scala et F# pour unifier OO et FP paradigmes?

La principale différence est que la Scala essaie de mélanger les paradigmes de faire des sacrifices (en général sur le FP côté) alors que F# (et OCaml) généralement tracer une ligne entre les paradigmes et de permettre au programmeur de choisir entre eux, pour chaque tâche.

Scala a dû faire des sacrifices afin d'unifier les paradigmes. Par exemple:

  • La première des fonctions de classe sont une caractéristique essentielle de tout langage fonctionnel (ML, le Régime et les Haskell). Toutes les fonctions sont de première classe en F#. Les fonctions de membres de seconde classe en Scala.

  • Les surcharges et les sous-types d'entraver l'inférence de type. F# fournit un grand sous-langue que les sacrifices de ces OO fonctionnalités afin de fournir une inférence de type, lorsque ces fonctions ne sont pas utilisés (nécessitant des annotations de type lorsqu'ils sont utilisés). Scala pousse ces fonctionnalités partout afin de maintenir la cohérence des OO le coût des problèmes de l'inférence de type partout.

Une autre conséquence de cela est que F# est basée sur essayé et testé des idées alors que Scala est l'un des pionniers dans ce domaine. C'est idéal pour des motivations derrière les projets: F# est un produit commercial et de la Scala est le langage de programmation de la recherche.

En aparté, Scala sacrifié aussi d'autres fonctions de base de FP comme la queue d'appel d'optimisation pour des raisons pragmatiques, en raison des limites de leur VM de choix (la JVM). Cela rend également Scala programmation orientée objet beaucoup plus que FP. Notez qu'il y a un projet pour apporter de la Scala de .NET qui va utiliser le CLR pour faire une véritable coût total de possession.

Quels sont les mérites et les inconvénients de chaque approche? Si, en dépit de l'appui pour le sous-typage, F# pouvons en déduire que les types des arguments d'une fonction alors pourquoi ne peut-Scala?

L'inférence de Type est en contradiction avec OO centrée sur des caractéristiques comme la surcharge et de sous-types. F# a choisi l'inférence de type par rapport à la cohérence avec le respect de la surcharge. Scala a choisi omniprésent, les surcharges et les sous-types sur l'inférence de type. Cela rend le F# plus comme OCaml et Scala plus comme C#. En particulier, la Scala est pas plus un langage de programmation fonctionnel que C# est.

Qui est mieux, c'est totalement subjectif, bien sûr, mais personnellement, je préfère de beaucoup l'énorme souci de concision et de clarté qui vient de puissants l'inférence de type, dans le cas général. OCaml est un langage fantastique mais le mal est l'absence de surcharge d'opérateur que nécessaire programmeurs + pour les entiers, +. pour les flotteurs, +/ pour les rationnels et ainsi de suite. Une fois de plus, F# choisit le pragmatisme sur l'obsession par le sacrifice d'une inférence de type pour la surcharge en particulier dans le contexte des objets numériques, non seulement sur les opérateurs arithmétiques, mais aussi sur l'arithmétique des fonctions telles que sin. Chaque coin du langage F# est le résultat d'soigneusement choisis pragmatique compromis de ce genre. Malgré les incohérences, je crois que cela rend le F# beaucoup plus utile.

7voto

Eric Grindt Points 1

À partir de cet article sur les Langages de Programmation:

Scala est un solide, expressive, strictement supérieure de remplacement pour Java. Scala est la programmation langue que je voudrais utiliser pour une tâche de l'écriture d'un serveur web ou un client IRC. Contrairement à OCaml [ou F#], qui était un langage fonctionnel avec une système orientée objet greffés à celui-ci, Scala se sent plus comme un vrai hybride orientée-objet et fonctionnelle de la programmation. (Qui est orienté objet, les programmeurs doivent être en mesure de commencer utilisation de Scala immédiatement, ramasser les parties fonctionnelles que comme ils choisir d'.)

J'ai d'abord appris à propos de la Scala à POPL 2006 quand Martin Odersky a donné un invitée sur elle. Au moment où je l'ai vu programmation fonctionnelle comme strictement supérieure à l'orienté objet la programmation, donc je n'ai pas besoin pour une langue qui a fondu fonctionnelle et la programmation orientée objet. (C' était sans doute parce que tout que j'ai écrit puis étaient des compilateurs, des interprètes et analyseurs statiques.)

La nécessité pour Scala n'est pas devenu évident pour moi jusqu'à ce que j'ai écrit un simultanées HTTPD à partir de zéro pour le soutien à long interrogés AJAX pour yaplet. Afin d'obtenir une bonne multicœur soutien, j'ai écrit la première version en Java. Comme une langue, je ne pense pas que Java est si mauvais que ça, et que je puisse en profiter bien fait de la programmation orientée objet. En tant que programmeur fonctionnel, cependant, le manque d' (ou inutilement verbeux) le soutien de la programmation fonctionnelle caractéristiques (comme les fonctions d'ordre supérieur) les grilles de moi quand je programme en Java. Donc j'ai donné à la Scala une chance.

Scala tourne sur la JVM, afin que je puisse progressivement port mon projet existant en Scala. Cela signifie également que la Scala, en plus de ses propres plutôt grand bibliothèque, a accès à l'ensemble de Java bibliothèque ainsi. Cela signifie que vous pouvez travailler en Scala.

Comme j'ai commencé à utiliser Scala, je suis devenu impressionné par la façon dont habilement l' fonctionnel et orienté objet mondes mélangés ensemble. En particulier, la Scala a une puissante cas classe/pattern-matching system qui adressée bêtes noires persistantes de mon expériences avec Standard ML, OCaml et Haskell: le programmeur peut décider les champs d'un objet doit être contrepartie (plutôt que d'être forcé pour correspondre sur eux tous), et variable-arité arguments sont permise. En fait, Scala permet même programmeur définie. J'écris un beaucoup de fonctions qui opèrent sur syntaxe abstraite des nœuds, et c'est agréable pour être en mesure de faire correspondre uniquement sur les syntaxique des enfants, mais encore champs pour des choses telles que les annotations ou de lignes dans le programme d'origine. L' classe de cas de système permet de diviser le définition d'un type de données algébrique dans plusieurs fichiers ou à travers plusieurs pièces d'un même fichier, ce qui est remarquablement pratique.

Également Scala prend en charge bien défini plusieurs l'héritage par la classe de dispositifs de appelée traits.

Scala permet également une degré considérable de surcharge; même fonction de l'application et de la matrice de mise à jour peut être surchargé. Dans mon l'expérience, ce qui tend à faire mon Scala programmes plus intuitive et concis.

Une fonctionnalité qui s'avère pour enregistrer un beaucoup de code, de la même manière que le type de les classes d'enregistrer le code dans Haskell, est implicites. Vous pouvez imaginer implicites une API pour la reprise après erreur de phase de la type-checker. En bref, quand le vérificateur de types a besoin d'un X, mais il a obtenu un Y, il va vérifier pour voir si il y a un implicite de la fonction dans la portée qu' convertit en Y dans X; si il en trouve un, il "jette" à l'aide de l'implicite. Cela rend il est possible de regarder comme vous êtes l'extension de n'importe quel type de Scala, et il permet de resserrement du les incorporations de DSLs.

À partir de l'extrait ci-dessus, il est clair que la Scala, l'approche pour unifier OO et FP paradigmes est beaucoup plus supérieure à celle de OCaml ou F#.

HTH.

En ce qui concerne,
Eric.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X