Простейшие новые возможности

Просмотров: 16423

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

  • Операторы +=, -=, *=, /=
  • Инициализация переменной при описании
  • Внутриблочные описания переменных
  • Автоопределение типа переменной при описании
  • Описание переменных в заголовке цикла for

Ометим, что их использование, хотя и удобно, но не всегда является оправданным: такие программы не будут работать в других версиях языка Object Pascal.

Операторы +=, -=, *=, /=

Данные операторы пришли из языка C. Запись a+=2 воспринимается легче, чем a:=a+2, и уж подавно легче, чем Inc(a,2). Кроме того, записи

a += 2;

можно обучать буквально на первом занятии по программированию, а запись Inc(a,2) нуждается в пояснениях: что такое стандартные процедуры и что такое передача параметра по ссылке.

Небольшая тонкость: если i: integer, то i /= 2 вызовет ошибку компиляции, поскольку будет трактоваться как i := i / 2.

Разумеется, для множеств определены только операторы +=, -=, *=, а для строк определен только оператор +=:

var
  s: string := 'PascalABC';
  d: set of integer := [200..300];
begin
  s += '.NET';
  d -= [100..298];
  writeln(s);
  writeln(d);
end.

Вот файл этой программы.

Данные операторы имеются также в Free Pascal (должна быть включена опция C-like operators). Кроме того, операции += и -= активно используются для делегатов .NET (процедурные переменные в PascalABC.NET) и присутствуют также в этом качестве в системе Chrome.NET.

Инициализация переменной при описании

Переменная может быть инициализирована при описании:

var i: integer := 1;

Подобное можно сделать и в Delphi Object Pascal, но только для глобальных переменных. В PascalABC.NET можно производить также инициализацию локальной переменной и поля записи или класса:

procedure p;
var i: integer := 1;
begin
end;
 
type
  Frac = record
    num: integer := 0;
    denom: integer := 1;
  end;
  MyClass = class
    s: string := 'NET';
  end;

Инициализация полей класса производится в конструкторе объекта этого класса до других действий.

Кроме того, можно инициализировать переменные не только константными, но и неконстантными выражениями, в частности, вызовам конструкторов:

var L: List<integer> := new List<integer>;

Внутриблочные описания переменных

Если какая-то переменная используется лишь в одном месте алгоритма, то описывать ее в разделе описаний вместе с другими, более важными переменными, неудобно. Кроме того, сразу не всегда понятно, сколько переменных может потребоваться для реализации алгоритма. Выход прост: описать в разделе описаний очевидные переменные, а если при написании алгоритма понадобится дополнительная переменная, описать ее прямо внутри блока.

Например, пусть дано x и требуется вычислить y=x7, используя как можно меньше умножений. Сколько при этом понадобится дополнительных переменных - неизвестно. Начнем решение:

var x,y: real;
begin
  readln(x);

Вычислим во вспомогательных переменных x2, x3, после чего воспользуемся формулой x7=x2*x2*x3

  var a: real := x * x;
  var b: real := a * x;
  y := a * a * b;
  writeln(y);
end.

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

Кроме того, тесты показывают, что доступ к внутриблочным переменным в PascalABC.NET по скорости примерно в 2 раза быстрее, чем к глобальным.

Автоопределение типа переменной при описании

Имя типа в описании

var i: integer := 1;

избыточно. Ведь константа 1 имеет тип integer. Поэтому достаточно написать:

var i := 1;

Тип переменной i автоопределится по типу константы.

Еще более показательно автоопределение типа в случае обобщенных типов:

var d := new Dictionary<string,integer>;

вместо

var d: Dictionary<string,integer> := new Dictionary<string,integer>;

Описание переменных в заголовке цикла for

Одной из проблем использования циклов for в языке Pascal является некорректное использование переменной-параметра цикла после цикла. Кроме того, описание такой переменной в разделе описаний замусоривает его.

В PascalABC.NET можно описывать параметр цикла for непосредственно в заголовке цикла:

var str := '';
for c: char := 'a' to 'z' do
  str += c;

Oбласть видимости такой переменной ограничена заголовком и телом цикла. Кроме того, можно использовать автоопределение типа параметра цикла, пользуясь следующей разновидностью описания в заголовке цикла:

var p := 1;
for var i := 1 to 10 do
  p *= i;

Вывод

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

Новости

29.08.16. Вышла версия 3.2. Реализован оператор yield.

12.02.16. Вышла версия 3.1. Добавлены кортежи в стиле (a,b) и кортежное присваивание (a,b) := (b,a)

31.12.15. Версия 3.0.0.1128. Реализованы обобщенные методы расширения для операций

22.12.15. Версия 3.0.0.1116. Реализован новый синтаксис extension-методов

Случайная программа

// Минимальный в массиве и его индекс
// Уровень сложности: 1
function MinInd(a: array of real): integer;
begin
  var min := a[0];
  Result := 0;
  for var i:=1 to a.Length-1 do
    if a[i]<min then
    begin
      min := a[i];
      Result := i;
    end;
end;


const n = 20;

begin
  var a := ArrRandomReal(n);
  Writeln('Исходный массив: ');
  a.Println;

  var ind := MinInd(a);
  Writeln('min=',a[ind],' индекс=',ind);
end.