/**
 * Feedback pour le mini-projet 1 (partie fonctionelle)
 * 
 * Ce fichier contient des exemples de code de qualité médiocre
 * trouvés parmi les solutions et présente comment améliorer la
 * qualité du code.
 *
 * @author Philipp Haller
 * @date   2007/10/17
 */
object feedback1 extends Application {

  // Fonction auxiliaire utilisée plus bas

  def even(x: Int) = x % 2 == 0

  // Evitez les expressions 'if' inutiles !
  //
  // NB. Dans les projets 2 et suivants des points vous
  //     seront déduits pour de telles horreurs!

  def f(y: Int) =
    if (even(y)) false else true

  // La fonction `f` s'écrit plus simplement:

  def f2(y: Int) = !even(y)

  // Eviter d'utiliser l'instruction 'return' pour
  // retourner des expressions!
  //
  // Scala est un langage fonctionnel ou
  // 1. Applying a function evaluates to a value!
  // 2. The if construct is an _expression_ that has a value
  // 3. The last expression of a block of expressions
  //    evaluates to the value of the block.
  //
  // Instead of using return it is often much better
  // to restructure the program in a functional way,
  // so that return becomes unnecessary.
  // The program is then often shorter and easier to understand.

  def longFun(x: Int): Int = {
    if (even(x) && x < 10)
      return x + 10
    else
      return x + 100
  }

  // La fonction 'longFun' s'écrit plus simplement:

  def longFun2(x: Int) =
    if (even(x) && x < 10) x + 10
    else x + 100


  // Ou encore (dans la mesure ou la condition est
  // suffisamment simple):

  def longFun3(x: Int) =
    x + (if (even(x) && x < 10) 10 else 100)

  type Set = Int => Boolean
  def pseudoExists(s: Set, p: Int => Boolean) = true
  
  // Evitez de déclarer des fonctions nommées lorsque
  // celles-ci sont appelées une seule fois et que leur
  // code est court! Utilisez des fonctions anonymes!
  //
  // Exemple tiré du projet 1:

  def map(s: Set, f: Int => Int): Set = {
    def fun_test(test_elem: Int) = {
      def test(elem: Int): Boolean = {
        if (f(elem) == test_elem) true
	  else false
      }
      if (pseudoExists(s, test)) true
      else false
    }
    fun_test
  }

  // Voici comment l'usage de fonctions anonymes
  // rend votre code plus lisible:

  def map2(s: Set, f: Int => Int): Set =
    (y: Int) => pseudoExists(s, x => y == f(x))

  // En résumé:
  // Qui dit moins de code dit aussi moins de bogues!
  //
  // Dans les prochains mini-projets nous supposerons 
  // que l'écriture de fonctions anonymes vous est
  // acquise!
}