6
votes

Scala - Récursion d'une fonction anonyme

Je travaille sur les trucs Scala Labs et je construis une fonction qui va, à la fin, renvoie quelque chose comme ça: Tails (liste (1,2,3,4)) = Liste (liste (1,2,3,4), liste (2,3,4), liste (3,4), liste (4) , List ()) code>

Je l'ai obtenu en utilisant deux fonctions et en utilisant une nouvelle récursive sur le second. P> xxx pré>

C'est tout bon Mais ça me dérange que j'ai besoin de deux fonctions pour faire cela. J'ai essayé de changer: Trailutil (liste () ::: Liste (L)) Code> Pour une fonction anonyme mais j'ai reçu cette erreur type inadéquation; Trouvé: Liste [Liste [t]] requise: int code> de l'IDE. P>

val ret : List[List[T]] = (ll:List[List[T]]) => {
    if ( ll.last.length == 0) ll else ret(ll :+ ll.last.init)
}
ret(List() ::: List(1))


1 commentaires

Le titre de votre question comprenait "anonyme". Ce ne sont pas des fonctions anonymes, qui auraient la forme (entrées) => expression , c'est-à-dire non nom. Je ne sais pas si dans Scala, il est possible de recueillir une fonction sans nom. Dans JavaScript, il peut être fait avec le déprécié callee .


4 Réponses :


4
votes

Quoi de ce sujet: xxx

et un peu moins idiomatique version: xxx

BTW Essayez d'éviter la liste . Longueur , il fonctionne dans O (n) heure.

Mise à jour: Comme suggéré par Tenshi , solution récursive queue: xxx < / pré>


7 commentaires

Great ça marche mais je comprends seulement environ la moitié de ce qui se passe. La principale chose que je ne comprends pas est l'endroit où le x vient. Et merci de l'info de la longueur;


@Locrizak: Eh bien, je ne comprends pas où x vient de l'un ou l'autre, il n'y a pas de x dans ma solution ;-). Essayez de traverser ce code avec un papier et un crayon, vous verrez comment la récursivité fonctionne ici.


Wtf! Je suppose que je vois des choses! Où est le h dans cas h ?


Le H est une variable dont la valeur provient de l'objet correspondant. Cela signifie juste :: queue. Si vous le souhaitez, il pourrait ensuite être utilisé dans la déclaration de cas. Par exemple, vous pourriez dire: Cas d'abord :: Deuxième :: troisième :: nil => println (premier + "+ seconde +" "+ troisième). Cela correspondra à n'importe quelle liste avec exactement trois éléments et assigner ces éléments aux variables d'abord, deuxième et troisième. Usage: Scala> Liste (1,2,3) Match {Cas d'affaire :: Deuxième :: Third :: nil => println (premier + "" + second + "" + troisième) cas _ => println ("Pas de match ")} 1 2 3 Liste (1,2,3,4) Imprime" Pas de match "


Il fait partie du modèle correspondant . Un très large sujet, voir Le point de correspondance de modèle dans Scala . Vous trouverez les mêmes constructions dans plusieurs langues de Prolog, à travers Haskell à Clojure.


Cette solution a l'air bien, mais malheureusement, il n'est pas récursif de la queue. (Et je crois que @locrizak tente de mettre en œuvre une version récursive queue)


Merci beaucoup les gars @ttenshi, je tente d'accomplir la même tâche de la même manière que possible pour que je puisse obtenir un bon gérant dans la langue. @Tomasz motif correspondant est dans le intermédiaire laboratoires, je ne suis que sur le de base et essayant de le prendre une étape à la fois :)



2
votes

Vous pouvez réellement définir def à l'intérieur d'un autre def . Il permet de définir la fonction qui a réellement le nom qui peut être référencé et utilisé pour la récursivité. Voici comment Tails peut être implémenté: xxx

Cette implémentation est également récursive de la queue. J'ai ajouté @ annotation.tailrec Annotation afin de vous assurer que c'est vraiment (le code ne compilera pas si ce n'est pas).


Vous pouvez également utiliser la fonction d'introduction queues (voir Scaladoc ): xxx

queues renvoie itérateur , vous devez donc la convertir à la liste (comme je l'ai fait) , si vous le voulez. Le résultat contiendra également un supplément vide à la fin (dans mon exemple de résultat serait Liste (liste (1, 2, 3, 4), liste (2, 3, 4), liste (3, 4), liste (4), liste ()) ), vous avez donc besoin de traiter.


2 commentaires

Bien que cela soit vrai, ce n'est pas très différent de ce que j'ai.


@Locrizak: Je ne pense pas que vous puissiez avoir une récursion avec une fonction de première classe, vous avez besoin def pour cela.



1
votes

Ce que vous faites mal est-ce: xxx pré>

donc ret code> est une liste de la liste de T. Ensuite, vous faites ceci: p>

def tails[T](l: List[T]): List[List[T]] = {
  lazy val ret : List[List[T]] => List[List[T]] = { (ll:List[List[T]]) => 
    if ( ll.last.length == 0) ll 
    else ret(ll :+ ll.last.init)
  }
  if ( l.length > 1 )ret(List() ::: List(l))
  else List() ::: List(l);
}


0 commentaires

1
votes

Vous pouvez également utiliser le pliage:

val l = List(1,2,3,4)

l.foldLeft(List[List[Int]](l))(  (outerList,element) => {
    println(outerList)
    outerList.head.tail :: outerList
})


5 commentaires

Ballin! Savez-vous s'il y a une surcharge supplémentaire lorsque vous utilisez FIXTLEFT sur les autres exemples?


Je ne le pense pas. Jetez un coup d'œil à la source: Lampsvn.epfl.ch/trac/scala/Browser/scala/tags/r_2_9_1_final/ src / ... 106 Remplacement / * TRAVERSABLELIKIKIKIKIKIKE * / 107 DEF FIXLEFT [B] (Z: B ) (F: (B, A) => B): b = {108 var acc = z 109 var ceci = ceci 110 tandis que (! ces.Impty) {111 acc = f ces.tail 113} 114 ACC 115}


Wow ça n'a pas posté proprement. Quoi qu'il en soit, il y a une raccourcie pour plier à gauche /: je l'oublie toujours et il suffit de taper repliolft


Beaucoup de bibliothèques de collections Scala ont été écrites à ressembler à elles sont récursives, quand elles sont vraiment écrites de manière itérative en raison des contraintes de la taille de la JVM et de la pile. Ce serait un exemple. Il y a une bonne explication de ce qu'ils ont essayé d'atteindre ici: Artima.com/scalazine/articles / ... (également tiré de la programmation du livre à Scala, que je recommande vivement.)


Yup j'ai cette et environ 250 pages. Je voulais essayer certains exercices mon auto donc j'ai trouvé Scala Labs. Maintenant, je rebondissais chaque fois qu'il y a un exercice que je ne comprends pas