В статье представлен набор некоторых хитростей и трюков заложенных в язык программирования Delphi.
Большая часть из них является бесполезным пережитком прошлого, но знание некоторых из этих тонкостей может пригодиться и, что самое важно, избежать некоторых ошибок.

1. Избавляемся от begin/end

В условных операторах могут быть использованы скобки для локализации тела условия:
if a > 0 then ( if a > 1 then a := 1; ) else a := 0;
В данном случае, else будет оноситься к условию a > 0, а скобки выполнять роль begin/end

2. Добраться до элемента массива

Если в самом кошмарном сне вам придётся писать код на клавиатуре с отсутствующими квадратными скобками, то владея данной тонкостью, вы не проснётесь в холодном поту :) А тонкость заключается в том, что существует документированная (!!!) возможность, замены скобочек при обращении к элементу массива на такую вот конструкцию:
a(.Y.) := 10; // присваиваем Y-ому элементу массива значение a[Y] := 10; // аналогично

3. Пределы цикла for

Многие не догадываются, что результатом работы следующего кода:
Count := 100; for i := 1 to Count do begin Count := 10; Result := i; end;
будет Result = 100. А дело всё в том, что несмотря на мнение многих идиотов авторов учебников по Delphi, цикл for не является универсальным (как например в С++). Eго пределы задаются при старте и по мере выполнения не изменяются. За счёт этого for даёт большую производительность, по сравнению с аналогичными реализациями через while и repeat.

4. В бесконечность и дальше!

В Delphi для чисел с плавающей точкой существуют 3 "дополнительных" значения, которые можно применять в операциях сравнения.
const c : array [0..2] of Single = (1/0, -1/0, 0/0); // +INF, -INF, NAN
Соответственно +бесконечность, -бесконечность и неопределённое значение. На заметку: в старых версиях Delphi, вещественные поля классов инициализировались в NAN.

5. Последовательность передачи параметров

По умолчанию, все методы и функции в Delphi имеют соглашение вызова register, что означает, что параметры передаются через регистры по возможности, и последовательность их передачи - от последних к первым. На деле это выглядит так:
var i : Integer; function inci: Integer; begin i := i + 1; Result := i; end; procedure Show(i1, i2, i3, i4: Integer); // pascal; begin Writeln(i1, i2, i3, i4); end; begin i := 0; Show(inci, inci, inci, inci); // выведет строку 4321 end;
Т.е. сначала вычисляется и передаётся последний параметр, затем предпоследний и т.д. что при неосведомлённом использовании может привести к ряду казусов. Изменяется эта последовательность при помощи смены соглашения вызова (например на pascal)

6. Строки и числа

Стандартные системные функции Delphi позволяют с лёгкостью реализовать перевод целых и вещественных чисел в строки. При этом для вещественных имеется возможность задания кол-ва знаков после запятой.
function IntToStr(Value: Integer): string; begin Str(Value, Result); end; function FloatToStr(Value: Single; Digits: Integer = 6): string; begin Str(Value:0:Digits, Result); end;
Обратный перевод из строки в число также не обделён дополнительными возможностями. Для целых чисел возможна конвертация из Hex строки (Например: $FFAABBCC), а для вещественных конвертация числа универсально для обоих разделителей (точка или запятая). Для обоих существует возможность задания значения по умолчанию в случае неудавшейся конвертации.
function StrToInt(const Str: string; Def: Integer = 0): Integer; var Code : Integer; begin Val(Str, Result, Code); if Code <> 0 then Result := Def; end; function StrToFloat(const Str: string; Def: Single = 0): Single; var Code : Integer; begin Val(Str, Result, Code); if Code <> 0 then Result := Def; end;

7. Объявление типа без type

Существует возможность объявления структур любой сложности прямо в var. Или же в const с заданием всех или части значений полей. Исключения составляют записи с методами.
const RoyalBlue : record R, G, B : Byte end = (G: $6B; B: $FF); var TShader : array [(stVertex, stPixel)] of record Name : string; Size : Integer; Uniform : array of record Name : string; DType : (dtInt, dtFloat, dtMatrix); Size : Integer; end; end;

8. const или var?

Глобальные переменные инициализируются нулями при старте приложения, но существует возможность задания значения переменной, прямо как при объявлении коснтанты.
var // глобальный MyVar : Integer = 10;
Более того, все типизированные константы по сути являются переменными, за попытки присвоить значения которым, компилятор бьёт по рукам. Исправляется это при помощи специальной директивы компилятора.
{$J+} const MyConst : Integer = 10; {$J-} ... MyConst := 20;

9. Как не намешать мух с котлетами

Иногда бывает полезна строгая типизация при помощи директивы type of
type TMyInt = type of Integer; var i : Integer; j : TMyInt; ... i := j; // Incompatible types: 'Integer' and 'TMyInt'

10. Использование ключевых слов в качестве имён

Естественно, это невозможно. Однако, Delphi IDE несколько лояльно относится к & в начале имён переменных и методов, и не отображает его при вызове автозавершения кода (Ctrl + Space). Что может быть удобно в случае если вам абасраца как очень надо использовать ключевые слова не по назначению.
TMyClass = class procedure &Begin; procedure &End; end;

11. Переменное число аргументов функции

Начиная с шестой версии Delphi появилась возможность передавать в функцию переменное число параметров избегая при этом array of const. Это бывает нужно либо в личных извращённых целях, либо при написании заголовков к С++ библиотекам написанным другими извращенцами. Но есть пара ограничений, параметры функции должны передаваться через стек (stdcall или cdecl) и сама функция не должна быть явно задана в коде, а лишь в виде ссылки или external.
type VarProc = procedure (Hello: PChar) stdcall varargs; // может и не иметь постоянных параметров procedure Test(Hello: PChar; Params: Pointer); stdcall; var p : array [0..31] of record case Integer of 0 : (i : LongInt); 1 : (s : PChar); end absolute Params; begin Writeln(Hello, #9, p[0].i, #9, p[1].i, #9, p[2].i, #9, p[3].s); end; ... VarProc(@Test)('Hi', 1, 2, 3, 'test'); // вызов