65.9K
CodeProject 正在变化。 阅读更多。
Home

Delphi 语言发展建议

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (19投票s)

2018 年 7 月 12 日

CPOL

2分钟阅读

viewsIcon

28535

我希望在 Delphi 中看到的功能还有很多,但在这里我将介绍那些易于实现,但能带来巨大收益的功能。

自从 ~Delphi 2010 以来,我们已经有了泛型、属性、迭代器以及其他一些编译器特性。虽然许多我们想要的功能难以实现,但我相信一些简单的语言特性已经迫在眉睫。

我希望在 Delphi 中看到的功能还有很多,但在这里我将介绍那些易于实现,但能带来巨大收益的功能。

块级变量声明

大多数编译器只是在内部将块级变量声明为普通的局部变量,即这只是语法上的(但非常有用!)糖衣。甚至可以通过预处理器来实现,但这会很笨拙并影响调试器。

最简单的方法是扫描块变量。在内部将它们视为局部变量。但添加一个前缀或后缀,使用否则无法使用的字符,并为每个块分配一个 ID。

例如,为每个块分配一个数字,1、2、3、4... 然后对于每个块变量,在内部将其命名为 name$1 或类似名称。实现起来非常简单,对编译器的影响也很小。

procedure Test();
begin
  for var c:string in List do begin
    ...
  end;

  var d:TStrings = TStringList.Create;
  var x:integer = 7; 

  for var f:integer := 1 to 10 do begin
    // Usable in block only. Not same as x declared before. 
    // Internally is just a normal function level var, ie as x$2 or something.
    var x:integer = 5;
    ...
  end;
end;

类型推断

function Foo(): integer;
var
  x = 1;
  xList = TStringList.Create;
begin
  ...
  for var x in xList do begin
    ...
  end; 
end;

using语句

带有隐式 finally 释放块的 try 语句

让我向您展示这将如何改变现有代码

class function TMyWriter.ToString(aSrc: TRoot): string;
var
  xStream: TStringStream;
  xWriter: TWriter;
begin
  xWriter := TWriter.Create(aSrc); try
    xStream := TStringStream.Create; try
      xWriter.SaveToStream(xStream);
      Result := xStream.DataString;
    finally xStream.Free; end;
  finally xWriter.Free; end;
end;    

使用

class function TMyWriter.ToString(aSrc: TRoot): string;
var
  xStream: TStringStream;
  xWriter: TWriter;
begin
  using var xWriter := TWriter.Create(aSrc) do begin
    using var xStream := TStringStream.Create do begin
      xWriter.SaveToStream(xStream);
      Result := xStream.DataString;
    end;
  end;
end;    

自动释放

当然,这适用于 Windows 编译器,不适用于基于 ARC 的编译器。总有一天,ARC 编译器也会达到 Windows 的水平,但在那之前,这个解决方案简单而有用。

还有其他可能的替代语法,但主要目标是功能。关键字的确切名称也不太重要。Auto 比 autofree、dynamic、finalized 等更短,更容易输入。

procedure Test2();
var
  x: integer;
  y: TStrings = TStringList.Create; auto;
begin
  ...
  auto z = TStringList.Create; 
  ...
  // At proc end, all .Free is called for all auto declared variables.
  // ie in this case, compiler emits a hidden y.Free and z.Free
end;

让我向您展示这将如何改变现有代码

class function TMyWriter.ToString(aSrc: TRoot): string;
var
  xStream: TStringStream;
  xWriter: TWriter;
begin
  xWriter := TWriter.Create(aSrc); try
    xStream := TStringStream.Create; try
      xWriter.SaveToStream(xStream);
      Result := xStream.DataString;
    finally xStream.Free; end;
  finally xWriter.Free; end;
end;    

使用 auto

class function TMyWriter.ToString(aSrc: TRoot): string;
var
  xStream: TStringStream; auto;
  xWriter: TWriter; auto;
begin
  xWriter := TWriter.Create(aSrc);
  xStream := TStringStream.Create;
  xWriter.SaveToStream(xStream);
  Result := xStream.DataString;
end;    

或者与块声明变量结合使用

class function TMyWriter.ToString(aSrc: TRoot): string;
begin
  auto xWriter := TWriter.Create(aSrc);
  auto xStream := TStringStream.Create;
  xWriter.SaveToStream(xStream);
  Result := xStream.DataString;
end;    

三元运算符

很难相信 Delphi 已经超过 20 年了,我们仍然没有三元运算符。语法可以有所不同,但其他语言中长期使用的语法可以很容易地适应 Delphi。

xValue := xCondition ? 'one' : 'two';

一位评论者还建议参考 Scala 的语法,我非常喜欢这种更像 Delphi 的语法

xValue := if xCondition then 'one' else 'two';

结论

通过这些简单的添加,Delphi 将更容易编写代码,而不会损失任何功能。

© . All rights reserved.