Est-il, ou est-il jamais, un opérateur conditionnel en Delphi?

j'ai gardé mes mains loin de Delphi trop longtemps, je suppose; occupé moi-même avec Java et PHP beaucoup au cours des deux dernières années. Maintenant, quand je suis revenu à faire un petit travail Delphi, j'ai réalisé que l'opérateur conditionnel qui est supporté à la fois par Java et PHP me manquait vraiment.

sur combien d'endroits trouveriez-vous des lignes comme celles-ci dans vos programmes Delphi?

var s : string;
begin
  ...<here the string result is manipulated>...

  if combo.Text='' then
      s := 'null'
    else
      s := QuotedStr(combo.Text);

  result := result + s;
end;

où un simple

result := result + (combo.text='')?'null':quotedStr(combo.text);

suffirait. Quel J'aime à ce sujet est que non seulement il raccourcit le code, de cette façon j'évite également de déclarer certains helper s:string variable.

pourquoi les opérateurs conditionnels ne font - ils pas partie de Delphi et-vont-ils jamais être pris en charge? J'ai remarqué qu'il y avait pas mal d'extensions linguistiques pour la version 2009 de Delphi (génériques), alors pourquoi ne pas ajouter cette fonctionnalité?

29
demandé sur Ether 2010-01-21 13:59:48

10 réponses

un tel opérateur ne fait pas partie de la version Delphi actuelle car il ne faisait pas partie de la version précédente, et la demande n'était pas assez grande pour justifier le coût de l'ajout. (Vous trouverez cette explication s'applique à beaucoup de fonctionnalités que vous aimeriez avoir en beaucoup de produits.)

Delphi fournit un ensemble de IfThen fonctions dans les unités mathématiques et StrUtils, mais ils ont la propriété malheureuse d'évaluer tous les deux leurs paramètres de valeur, de sorte que le code comme celui-ci échouera:

Foo := IfThen(Obj = nil, '<none>', Obj.Name);

pour vraiment le faire correctement, il faut l'aide du compilateur. Dans la communauté Delphi, je sens une aversion générale pour la syntaxe du style C en utilisant un point d'interrogation et deux points. J'ai vu des propositions qui utiliseraient une syntaxe comme celle-ci:

Foo := if Obj = nil then
         '<none>'
       else
         Obj.Name;

une partie de ce qui rend les opérateurs conditionnels si attrayants est qu'ils vous laissent écrire du code concis, mais le style de Delphi de écrire tout rend ce qui précède peu attrayant, même si mis tous sur une ligne.

Il n'a pas vraiment besoin d'être dans la forme d'un opérateur . Delphi Prism fournit une fonction de compilation-magie Iif qui évalue seulement un de ses deux paramètres de valeur:

Foo := Iif(Obj = nil, '<none>', Obj.Name);

vous avez demandé pourquoi une fonctionnalité comme celle-ci n'aurait pas été ajoutée avec toutes les autres fonctionnalités linguistiques ajoutées dans Delphi 2009. Je pense que c'est votre raison. Il y avait beaucoup d'autres changements de langage en cours qui nécessitaient déjà une manipulation délicate; les développeurs n'avaient pas besoin d'être surchargés avec encore plus. Les fonctionnalités ne sont pas gratuites.

vous avez demandé si Delphi aura jamais un tel dispositif. Je ne suis pas au courant des réunions de planification D'Amarcadero, et j'ai dû envoyer ma boule de cristal loin pour les réparations, donc je ne peux pas dire avec certitude, mais je prédis que si jamais aurait avoir un tel caractéristique, il viendrait sous la forme de prisme Delphi Iif fonction. Cette idée apparaît vers la fin de dans la discussion de qualité Centrale , et on objecte que, en tant que nouveau mot réservé, il briserait la rétrocompatibilité avec le code d'autres personnes qui définit déjà une fonction avec le même nom. Ce n'est pas un objet valide, parce que ça n'aurait pas besoin d'être un mot réservé. Il pourrait s'agir d'un identifiant, et tout comme Writeln et Exit , il peut être admissible à être redéfini dans d'autres unités, même si celui de l'unité du Système est spécialement traités.

39
répondu Rob Kennedy 2010-01-21 15:34:43

il y a un rapport du QC à ce sujet ( 8451 ) qui a une discussion raisonnable.

soulevé en juin 2004, et il ne semble pas y avoir de réponse de Borland/CodeGear/Embarcadero.

5
répondu glob 2010-01-21 12:18:04

Ok. Code WTF du jour:)

comment obtenir quelque chose qui agit principalement comme une fonction ternaire/conditionnelle.

program Project107;
{$APPTYPE CONSOLE}

uses SysUtils;

type
  TLazyIfThen<T:record>=record
    class function IfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T; static;
  end;

  class function TLazyIfThen<T>.IfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T;
  begin
    if aCondition then
      Result := aIfTrue
    else
      Result := aIfFalse
  end;

begin
  WriteLn(
    TLazyIfThen<Integer>.IfThen(
      True,
      function:Integer begin result := 0 end,
      function:Integer begin result := 1 end
    )
  );
  ReadLn;
end.

Oui, c'est plus ou moins inutile, mais ça montre que c'est faisable.

5
répondu Wouter van Nifterick 2011-03-09 14:08:52

il existe un certain nombre de poignées simples disponibles sur la fonction IFTHEN surchargée.

StrUtils.IfThen ( String )

Math.IfThen ( Integer )

Math.IfThen ( Int64 )

Math.IfThen ( Double ) (fonctionne pour TDateTime ainsi)

Ce modèle tombe comme indiqué dans L'exemple que Andreas a commenté, mais pour les types simples c'est plus que raisonnable. Si suit la convention Delphi/Pascal de méthodes plutôt que de succomber à la manière D'utiliser le moins de caractères possible.

personnellement, je ne voudrais pas voir un opérateur conditionnel (i.e. ?: ) introduit dans Delphi car je préfère la lisibilité de Delphi/Pascal plutôt que C et les langues dérivées de l'informatique. Je préférerais voir des solutions plus innovantes de type Delphi pour quelque chose comme ça que de mettre en œuvre de plus, C-ismes.

5
répondu Ryan J. Mills 2012-05-28 08:39:09

il n'y a pas d'opérateur conditionnel à Delphi, et je doute sérieusement qu'il y en ait un, mais vous ne le saurez peut-être jamais. Vous pouvez toujours faire une demande à L'Embarcadero.

une alternative consiste à définir la fonction Iff:

function Iff(const ACondition: Boolean; const ATrueValue, AFalseValue: XXX): XXX;
begin
  if ACondition then
    Result := ATrueValue
  else
    Result := AFalseValue;
end;

où XXX est le type desirec.

utiliser comme:

Result := Result + Iff(combo.text='', 'null', quotedStr(combo.text));

il y a plusieurs raisons pour ne pas mettre en œuvre l'opérateur conditionnel. L'un de ces est lisibilité. Pascal (et aussi Delphi) est plus centré sur la lisibilité que les langages de syntaxe C qui sont plus centrés sur la puissance de caractère (autant d'informations par caractère que possible). L'opérateur conditionnel est puissant mais (selon certains) non lisible. Mais si vous regardez le (redouté) avec la déclaration dans Delphi... (pas besoin d'en dire plus). Une autre raison est que l'opérateur conditionnel n'est pas nécessaire. Ce qui est vrai. Mais il y a plus pas nécessaire qui est encore mis en œuvre.

au final, c'est juste une question de goût.

mais si vous voulez qu'un seul argument soit évalué, Vous pouvez toujours utiliser le folowing, qui viole à la fois la lisibilité comme le concept de puissance de caractère:

[overdesignmode]

// Please don't take this that serious.
type
  TFunc = function(): XXX;
function Iff(const ACondition: Boolean; const ATrueFunc, AFalseFunc: TFunc): XXX;
begin
  if ACondition then
    ATrueFunc
  else
    AFalseFunc;
end;

[/overdesignmode]

4
répondu Toon Krijthe 2010-01-30 18:39:27

je préfère de mettre en œuvre l'évaluation différée et il sera plus puissant et peut être utilisé dans différents scénario. Voir le détail sous le lien

http://www.digitalmars.com/d/2.0/lazy-evaluation.html

Cheers

3
répondu Pham 2010-01-31 17:20:03

en fait pour les cordes vous pouvez utiliser le: StrUtils.IfThen fonction:

function IfThen(AValue: Boolean;
        const ATrue: string;
        AFalse: string = ): string; overload;

regardez dans le wiki d'aide delphi: http://docwiki.embarcadero.com/VCL/en/StrUtils.IfThen

il fait exactement ce dont vous avez besoin.

1
répondu Fabio Gomes 2010-01-21 15:19:04

une autre option est d'utiliser des génériques:

Cond<T> = class
    public class function IIF(Cond: boolean; IfVal: T; ElseVal: T): T;
  end;

implementation

class function Cond<T>.IIF(Cond: boolean; IfVal, ElseVal: T): T;
begin
  if Cond then
    Result := IfVal
  else
    Result := ElseVal;
end;

c'est tout à fait lisible:

var MyInt: Integer;
begin
  MyInt:= Cond<Integer>.IIF(someCondition, 0, 42);

remarque: comme l'a souligné Alan Bryant (à 6/21/2004 7:26:21 AM) QR 8451 , ce sera toujours évaluer tous les 3 arguments - donc être conscient que ce n'est pas un vrai opérateur ternaire.

1
répondu TmTron 2013-11-19 13:26:56

encore mieux est un IIF surchargé (inline if) qui supporte plusieurs types de données et de résultats.

0
répondu General Jackson Tackett 2010-01-23 09:50:40

Jedi Code Library ( JCL ) a implémenté l'opérateur ternaire avec un ensemble de fonctions nommées Iff(). Voir ici pour la documentation:

http://wiki.delphi-jedi.org/wiki/JCL_Help:Iff@Boolean@Boolean@Boolean

pour télécharger JCL vous pouvez visiter ce site:

http://sourceforge.net/projects/jcl /

0
répondu iluwatar 2011-03-07 13:54:49