Есть ли в Delphi условный оператор или он когда-либо будет?

28

Я слишком долго держал руки у Дельфи, наверное; За последние пару лет я много занимался Java и PHP. Теперь, когда я вернулся к выполнению небольшой работы Delphi, я понял, что действительно скучаю по условному оператору, который поддерживается как Java, так и PHP.

На сколько мест вы найдете такие строки в своих программах 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;

где простой

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

было бы достаточно. Что мне нравится в этом, так это то, что он не только сокращает код, и я также избегаю объявления некоторой вспомогательной переменной s:string.

Почему условные операторы не являются частью Delphi и - будут ли они когда-либо поддерживаться? Я заметил, что для версии Delphi (generics) 2009 года было сделано несколько языков, поэтому почему бы не добавить эту функцию?

  • 3
    Правильное имя и метка - «условный оператор».
  • 3
    | Я думаю, что это можно назвать либо Даниилом: msdn.microsoft.com/en-us/library/e4213hs1%28VS.71%29.aspx, либо en.wikipedia.org/wiki/Ternary_operation
Показать ещё 6 комментариев
Теги:
delphi-2009
conditional-operator
language-features

10 ответов

36
Лучший ответ

Такой оператор не является частью текущей версии Delphi, поскольку он не был частью предыдущей версии, и спрос был недостаточным, чтобы оправдать затраты на его добавление. (Вы найдете, что это объяснение относится к множеству функций, которые вы хотели бы иметь в большом количестве продуктов.)

Delphi предоставляет набор функций IfThen в модулях Math и StrUtils, но у них есть неудачное свойство оценки обоих параметров значений, поэтому такой код не будет выполняться:

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

Чтобы все было правильно, нужна помощь от компилятора. В сообществе Delphi я чувствую общую неприязнь к синтаксису C-стиля, используя знак вопроса и двоеточие. Я видел предложения, которые использовали бы синтаксис следующим образом:

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

Часть того, что делает условные операторы настолько привлекательными, заключается в том, что они позволяют писать сжатый код, но стиль Delphi для написания всего делает вышеупомянутое непривлекательным, даже если положить все на одну строку.

Это не обязательно должно быть в форме оператора. Delphi Prism предоставляет компилятор-магическую функцию Iif, которая оценивает только один из двух параметров:

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

Вы спросили, почему такая функция не была бы добавлена ​​вместе со всеми другими языковыми функциями, добавленными в Delphi 2009. Я думаю, что ваша причина. Было много других изменений языка, которые уже требовали деликатной обработки; разработчикам не нужно было обременять еще больше. Особенности не являются бесплатными.

Вы спросили, будет ли у Delphi такая функция. Я не участвую в совещаниях по планированию Эмбаркадеро, и мне пришлось отправить свой хрустальный шар на ремонт, поэтому я не могу сказать наверняка, но я предсказываю, что если бы у него когда-либо была такая особенность, это получилось бы в форме функции Delphi Prism Iif. Эта идея появляется в конце обсуждение в Quality Central, и делается возражение, что, как новое зарезервированное слово, оно сломается назад совместимость с кодом других людей, который уже определяет функцию с тем же именем. Это не действительный объект, хотя, поскольку он не должен быть зарезервированным словом. Он может быть идентификатором и точно так же, как Writeln и Exit, он может быть переопределен в других единицах, даже если тот из системного блока обрабатывается специально.

  • 0
    Спасибо за вклад, интересное чтение. Надеюсь, ваш хрустальный шар вернется в целости и сохранности, и тогда вы могли бы рассказать нам больше о будущем () ?:
  • 0
    +1 Отличный ответ на сложный вопрос.
Показать ещё 7 комментариев
5

Ok. Код WTF дня:)

Как получить то, что в основном действует как тройная/условная функция.

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.

Да, это более или менее бесполезно, но это показывает, что это можно сделать.

  • 0
    Я думаю, вы неправильно поняли смысл оператора ?: Чтобы сделать код более компактным . ;)
  • 3
    хе-хе .. delphi никогда не был настоящим победителем в соревнованиях по коду-гольфу здесь.
Показать ещё 2 комментария
5

Существует несколько доступных простых типов дескрипторов для перегруженной функции IFTHEN.

StrUtils.IfThen (String)

Math.IfThen (Integer)

Math.IfThen (Int64)

Math.IfThen (Double) (работает и для TDateTime)

Эта модель падает, как показано в примере, который Андреас прокомментировал, но для простых типов это более чем разумно. Если следует соглашение методов Delphi/Pascal, а не поддаваться методу C использования наименьшего количества символов, насколько это возможно.

Лично я предпочел бы не видеть условный оператор (т.е. ?:), введенный в Delphi, поскольку я предпочитаю читаемость Delphi/Pascal над C и его производными языками. Я бы предпочел увидеть более инновационные решения типа Delphi для чего-то подобного, чем реализовать больше C-isms.

  • 0
    mini-rant: я видел очень нечитаемый код даже с очень небольшим использованием? троичный оператор в C-подобных языках. Основная причина в том, что это еще один используемый символ, и большинство людей, использующих его, забывают добавить скобки или отступы для удобства чтения. Повышение скорости, которое оно может принести, вряд ли достижимо: большая часть использования - это просто замена одного if / then / else, тогда как реальное улучшение может быть достигнуто только в сложных выражениях, которые немногие могут поддерживать.
5

Здесь есть отчет о контроле качества (8451), который имеет разумное обсуждение.

Поднято в июне 2004 года, и, похоже, от Borland/CodeGear/Embarcadero не было ответа.

  • 1
    Имеет 25 голосов и рейтинг 3,81; вероятно, недостаточно, чтобы сделать это в списке возможностей новой версии.
4

В Delphi нет условного оператора, и я серьезно сомневаюсь, что когда-нибудь будет один, но вы никогда не узнаете. Вы всегда можете выдать запрос в Embarcadero.

Альтернативой является определение функции Iff:

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

Где XXX - тип желания.

Использовать как:

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

Существует несколько причин, по которым не следует выполнять условный оператор. Одна из них - читаемость. Паскаль (а также Delphi) больше сосредоточен на читабельности, чем языки синтаксиса C, которые в большей степени сосредоточены на мощности символов (как можно больше информации на каждый символ). Условный оператор является мощным, но (по некоторым данным) нечитаемым. Но если вы посмотрите на (страшное) выражение с Delphi... (не нужно больше говорить). Другая причина заключается в том, что условный оператор не требуется. Что является правдой. Но нет необходимости в том, чтобы все еще было реализовано.

В конце концов, это просто вопрос вкуса.

Но если вы хотите оценить только один аргумент, вы всегда можете использовать следующее, что нарушает как читаемость, так и концепцию мощности символов:

[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]

  • 7
    К сожалению, это не работает как условный оператор, так как все параметры функций будут оценены. Условный оператор должен оценить тест, а затем только одно из двух оставшихся выражений.
  • 0
    Я видел эту идею ранее (в PL / SQL) ... Как бы я написал функцию Iff, которая работала бы с любым типом данных (XXX)?
Показать ещё 12 комментариев
3

Я бы предпочел, чтобы они выполняли ленивую оценку, и она будет более мощной и может использоваться в разных сценариях. Подробнее см. Ссылку ниже.

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

Приветствия

1

Другой вариант - использовать generics:

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;

Это вполне читаемо:

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

Примечание: как указал Алан Брайант (в 6/21/2004 7:26:21) в QR 8451, это будет всегда оценивайте все 3 аргумента - так что имейте в виду, что это не истинный тернарный оператор.

1

На самом деле для строк вы можете использовать функцию StrUtils.IfThen:

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

Посмотрите в wiki справки delphi: http://docwiki.embarcadero.com/VCL/en/StrUtils.IfThen

Он делает именно то, что вам нужно.

  • 0
    Я буду использовать это, просто чтобы попробовать что-то «новое» :)
  • 2
    Нет, это не так. Если значения ATrue и AFalse , передаваемые функции являются функциями, то оба истинные и ложные функции будут выполнены и оценены перед IfThen () называется. Условный оператор вычисляет только выражение, соответствующее ветвям истина или ложь, в зависимости от условного выражения.
0

Библиотека кода Jedi (JCL) реализовала трехмерный операнд с набором функций с именем Iff(). См. Здесь документацию:

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

Чтобы загрузить JCL, вы можете посетить этот сайт:

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

  • 0
    Почти -1. Поскольку это обычные функции, «ленивая» оценка отсутствует, что является обязательным компонентом оператора ?: .
0

Еще лучше - перегруженный IIF (inline if), который поддерживает несколько типов данных и результатов.

  • 5
    В модулях StrUtils и Math уже есть несколько процедур IfThen (). Они не совпадают с условным оператором, потому что процедуры IfThen () являются функциями с параметрами. Все параметры оцениваются при вызове функции. Часто допустим только 1 параметр, поэтому вызов функции завершится сбоем. Представьте, что вы вызываете IfThen (false, ClassA.X, ClassB.X), где ClassB равен нулю. Условный оператор должен оценивать только ту часть, которая определяется условием, и игнорировать другую часть.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню