web-dev-qa-db-fra.com

Renvoyer des valeurs dans Elixir?

J'ai récemment décidé d'apprendre Elixir. Venant d'un arrière-plan C++/Java/JavaScript, j'ai eu beaucoup de mal à comprendre les bases. Cela peut sembler stupide, mais comment les déclarations de retour fonctionneraient-elles dans Elixir? J'ai regardé autour de moi et il semble que ce ne soit que la dernière ligne d'une fonction, c'est-à-dire.

def Hello do 
  "Hello World!"
end

Cette fonction retournerait-elle "Hello World!", Existe-t-il une autre façon de faire un retour? De plus, comment rentreriez-vous tôt? en JavaScript, nous pourrions écrire quelque chose comme ceci pour trouver si un tableau a une certaine valeur:

function foo(a){
   for(var i = 0;i<a.length;i++){
      if(a[i] == "22"){
         return true;
      }
   }
   return false;
}

Comment cela fonctionnerait-il dans Elixir?

22
Joe Thomas

Elixir n'a pas de mot clé 'break out' qui serait équivalent au mot clé 'return' dans d'autres langues.

En règle générale, ce que vous feriez serait de restructurer votre code afin que la dernière instruction exécutée soit la valeur de retour.

Vous trouverez ci-dessous un moyen idiomatique dans elixir pour effectuer l'équivalent de votre test de code, en supposant que vous vouliez dire "a" comme quelque chose qui se comporte comme un tableau comme dans votre exemple initial:

def is_there_a_22(a) do
  Enum.any?(a, fn(item) -> item == "22" end.)
end

Ce qui se passe réellement ici, c'est que nous restructurons un peu notre pensée. Au lieu de l'approche procédurale, où nous recherchons dans le tableau et retournons tôt si nous trouvons ce que nous recherchions, nous allons demander ce que vous recherchez vraiment dans l'extrait de code: "Ce tableau a-t-il un 22 n'importe où ? "

Nous allons ensuite utiliser la bibliothèque elixir Enum pour parcourir le tableau pour nous et fournir le any? fonctionne avec un test qui nous dira si quelque chose correspond aux critères qui nous intéressaient.

Bien que ce cas soit facilement résolu par l'énumération, je pense qu'il est possible que le cœur de votre question s'applique davantage à des choses telles que le `` modèle de videur '' utilisé dans les méthodes procédurales. Par exemple, si je remplis certains critères dans une méthode, revenez tout de suite. Un bon exemple de ceci serait une méthode qui retourne false si la chose sur laquelle vous allez travailler est nulle:

function is_my_property_true(obj) {
  if (obj == null) {
    return false;
  }
  // .....lots of code....
  return some_result_from_obj;
}

La seule façon de vraiment accomplir cela dans l'élixir est de mettre la garde à l'avant et de factoriser une méthode:

def test_property_val_from_obj(obj) do
  # ...a bunch of code about to get the property
  # want and see if it is true
end

def is_my_property_true(obj) do
   case obj do
     nil -> false
     _ -> test_property_value_from_obj(obj)
   end
end

tl; dr - Non, il n'y a pas d'équivalent - vous devez structurer votre code en conséquence. D'un autre côté, cela a tendance à garder vos méthodes petites - et votre intention claire.

15
TreyE

Vous avez raison, la dernière expression est toujours renvoyée. Encore plus - il n'y a pas de déclarations dans le langage - juste des expressions. Chaque construction a une valeur - if, case, etc. Il n'y a pas non plus de retour anticipé. Cela peut sembler limitant, mais vous vous y habituez rapidement.

Une façon normale de résoudre votre exemple avec Elixir serait d'utiliser une fonction d'ordre supérieur:

def foo(list) do
  Enum.any?(list, fn x -> x == "22" end)
end
5
michalmuskala