Je modélise un langage de programmation pour le plaisir, et la syntaxe est fortement influencée par Scala - en particulier les définitions de fonction.
J'ai rencontré un problème de conception car mon langage ne fait pas de distinction entre les fonctions définies via la def
syntaxe (méthodes de classe) et les fonctions anonymes affectées aux valeurs (créées à l'aide =>
) - il supprime les différences d' implémentation et de comportement .
Le résultat est que les deux définitions suivantes signifient la même chose:
def square(x: Int) = x*x
val square = (x: Int) => x*x
Il n'y a aucune raison d'utiliser ce dernier formulaire (affectation de fonction anonyme immédiate) dans toute situation normale - il est simplement possible de l'utiliser à la place du def
formulaire.
Une telle syntaxe en double pour définir des fonctions nommées nuirait-elle à l'orthogonalité du langage ou à un autre aspect de la conception?
Je préfère cette solution car elle permet des définitions courtes et intuitives des méthodes et des fonctions nommées (via def
), et des définitions courtes des fonctions anonymes (via =>
).
Edit: Scala fait la différence entre les deux - les fonctions anonymes ne sont pas les mêmes que les méthodes définies avec def
Scala. Les différences sont cependant relativement subtiles - voir les articles que j'ai liés auparavant.
la source
However, assigning existing functions
semble manquer la fin de la phraseval
notation?fun
pour définir une fonction récursive.def
fait. C'est juste un effet secondaire du fait qu'une fonction anonyme, disons(x : Int) => x + 1
est un objet, et que les objets peuvent être affectés à des valeurs avecval f = ...
. Les concepteurs de langage auraient dû faire tout leur possible pour interdire la syntaxe. Ce n'est pas tout à fait la même chose que de faire explicitement l'effort de prendre en charge deux syntaxes différentes qui font (approximativement) la même chose.Réponses:
Je pense qu'avoir deux constructions qui signifient la même chose mais qui semblent différentes devrait être réduit au strict minimum dans une langue. Toute duplication augmente la difficulté de lire (et donc d'écrire / modifier du code dans) votre langue. L'élimination de toute duplication est inévitable dans un langage qui peut créer des constructions arbitraires (par exemple, l'équivalence de l'itération contre la récursivité).
Donc, dans ce cas, je pense qu'il pourrait être mieux conçu ici. Une seule façon de définir les fonctions est la plus logique pour moi. Dans ce cas, il semble que les deux déclarations scala que vous avez aient des implications légèrement différentes, ce qui n'est probablement pas une bonne conception (il est probablement préférable d'avoir quelque chose de clair qui indique quelles sont les différences, comme un mot-clé).
En fait, vous pouvez appliquer ce principe non seulement aux fonctions nommées, mais à n'importe quelle fonction. Pourquoi y a-t-il une différence dans la définition des fonctions nommées et des fonctions anonymes? Dans Lima , les fonctions sont toujours définies comme suit:
fn[<arguments>: <statements>]
. Si vous voulez qu'il soit « nommé » vous pouvez l' assigner à une variable:var x = fn[<arguments: <statements>]
et si vous voulez passer dans une autre fonction anonyme:function[fn[<arguments: <statements>]]
. Si vous voulez qu'il soit hissé, rendez-le constantconst var x = fn[<arguments: <statements>]
. La forme unique rend évident qu'ils signifient la même chose.la source
const
provoque le levage, mais c'est parfaitement logique. Dans JSfunction myFunc
, le levage entraîne, maisvar myFunc =
pas, ce qui est peut-être un peu moins intuitif car ils se comportent à peu près de la même manière sinon.function fnName()...
forme crée en fait une constante, ce qui fait que le levage est une chose valable à faire avec. Javascript rend les choses assez déroutantes lorsque vous utilisez le formulaire,var fn = function anotherFnName()...
car cela rend le nomanotherFnName
non palpable, même s'il est clairement constant.Ce que vous avez publié est une scala valide et fonctionne très bien.
Étant donné que le doublement n'a pas causé de problèmes avec scala (à ma connaissance), je vais dire que ce ne sera pas un problème pour votre langue non plus.
la source
J'ai trouvé une différence fondamentale entre les lambdas et les
def
méthodes dans Scala - que je ne suis toujours pas sûr de vouloir implémenter. Je dois faire d'autres recherches à ce sujet, puis je rendrai compte de ma décision.Essentiellement, seules les méthodes peuvent
return
- et lorsque le mot-clé est utilisé à partir d'un lambda, il revient en fait à partir de la méthode englobante.Comme je l'ai dit, je ne suis pas sûr de vouloir cela. Mais cela pourrait suffire à justifier cette syntaxe. Ou peut-être trop dangereux car des différences subtiles peuvent inopinément nuire.
Détails
la source