[Swift] Sucrer un peu ma syntaxe

(Rapport au syntactic sugar bien entendu)


En cours on nous a demandé d'implémenter un algo qui nous permet de modéliser un AST de fonction mathématiques du genre f(x) = 12x + sin(3x - 5) et de faire différentes choses comme l'évaluer, la dériver et la simplifier.


 


J'ai fait l'exercice avec un enum et je me retrouve avec ces membres:



indirect enum Expr {
case IntConst(Int)
case FloatConst(Double)
case Variable
case Add(Expr, Expr)
case Sub(Expr, Expr)
case Mul(Expr, Expr)
case Div(Expr, Expr)
case Pow(Expr, Expr)
case Cos(Expr)
case Sin(Expr)
}

A un moment pour la simplification je me retrouve avec un code de ce genre pour savoir si je multiplie par 0 :



if case Expr.IntConst(let val) = l where val == 0 { return Expr.IntConst(0) }
if case Expr.FloatConst(let val) = l where val == 0 { return Expr.IntConst(0) }
if case Expr.IntConst(let val) = r where val == 0 { return Expr.IntConst(0) }
if case Expr.FloatConst(let val) = r where val == 0 { return Expr.IntConst(0) }

Est-ce qu'il y aurai moyen de rendre cette partie plus compacte ?


Les enum sont super puissants en Swift mais la syntaxe qui va avec peut être assez indigeste... Y'a des astuces pour la faire mieux passer ?


Mots clés:

Réponses

  • Hors sujet total, mais généralement en maths on interdit d'élever un nombre réel négatif à  une puissance réelle non-entière ;-)
  • Bah les maths tu sais c'est le royaume de l'étrange .. on y trouve même des racines carrées négatives !

  • AliGatorAliGator Membre, Modérateur
    septembre 2015 modifié #4

    A un moment pour la simplification je me retrouve avec un code de ce genre pour savoir si je multiplie par 0 :

    if case Expr.IntConst(let val) = l where val == 0 { return Expr.IntConst(0) }
    if case Expr.FloatConst(let val) = l where val == 0 { return Expr.IntConst(0) }
    if case Expr.IntConst(let val) = r where val == 0 { return Expr.IntConst(0) }
    if case Expr.FloatConst(let val) = r where val == 0 { return Expr.IntConst(0) }
    Est-ce qu'il y aurai moyen de rendre cette partie plus compacte ?
    Les enum sont super puissants en Swift mais la syntaxe qui va avec peut être assez indigeste... Y'a des astuces pour la faire mieux passer ?

    Puisque ton "where" est un "==" sur la variable que tu "bindes", et que tu n'utilises cette variable pour rien d'autre, autant directement comparer avec IntConst(0) :
    if case .IntConst(0) = l   { return .IntConst(0) }
    if case .FloatConst(0) = l { return .IntConst(0) }
    if case .IntConst(0) = r { return .IntConst(0) }
    if case .FloatConst(0) = r { return .IntConst(0) }
    ---

    Sinon, on peut aussi combiner le tout et donc essayer avec un switch. Par contre comme dans ton cas parfois tu compares l et parfois r, on va pas faire un "switch l" avec 2 case et un "switch r" avec 2 cases, on n'y gagnerai pas grand chose et ça serait + de lignes. D'autant que dans les 2 cas tu retournes la même chose donc c'est dommage de pas les regrouper.

    Donc je te propose d'utiliser un tuple (l,r) et de mettre à  profit l'expression spéciale "_" de Swift qui veut dire " du moins dans le contexte d'un pattern matching comme dans un "switch" ou un "if case" " en gros "je m'en fous de la valeur à  cet endroit, ça peut être n'importe quoi".
    Ca donnerait donc un truc genre :
    switch (l,r) {
    case (.FloatConst(0),_),(_,.FloatConst(0)),(.IntConst(0),_),(_,.IntConst(0)):
    return .IntConst(0) // Retourner 0 si on est dans un de ces 4 cas
    default:
    // là  tu fais le calcul pour les autres cas
    }
  • Merci Ali c'est exactement ce que je voulais !  :)


Connectez-vous ou Inscrivez-vous pour répondre.