Блок (также говорят блок кода, блок команд, блок инструкций) в программировании — это логически сгруппированный набор идущих подряд инструкций в исходном коде программы, является основой парадигмы структурного программирования.

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

Блок в коде иногда сравнивают с параграфом в тексте, хотя эти понятия имеют существенные различия.

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

Выделение блока

править

Для выделения блоков применяются специальные конструкции языка программирования. Например, в семействе Си-подобных языков (С, C++, Java) и в языке JavaScript применяются фигурные скобки («{» и «}»). В языках, основанных на ALGOL, применяются ключевые слова begin и end (операторные скобки). В языках, основанных на Lisp, применяются S-выражения (lambda, let и т. д.) В языке Python блоки определяются различиями в отступе строк кода от левого края начала строки (обычно в 4 символа пробела).

Область видимости

править

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

Область видимости блока в некоторых языках имеет довольно нетривиальное поведение. Например, в языке JavaScript её действие зависит от нескольких обстоятельств.

Особенности

править

В языках семейства Smalltalk блоки — это объекты со всеми соответствующими возможностями.

В языке JavaScript синтаксис блока аналогичен синтаксису литерала объекта, а семантика этих конструкций определяется внешним контекстом — принадлежностью к выражению, так как, в частности, алгоритм определения семантики внутренним контекстом столкнётся с неразрешимыми неоднозначностями. Также в нём инструкция break не видит меток за пределами функции, непосредственно в которой она применяется, что может служить веским аргументом в пользу реализации в JavaScript do-выражений.

Примеры

править

Блок внутри функции на языке (Си):

 {
   int a = 1;
   int b = 2;
   int с = a + b;
   return c; 
 }

Блок на языке Pascal:

 begin
   a := 5;
   b := a - 2;
 end

Пример блока на Transact-SQL:

 BEGIN
   SET @a = 'f'
   IF @b = 1
     SET @a = @a + ',f'
   ELSE IF @b = 2
     SET @a = @a + ',e'
 END

Блок на языке JavaScript без метки:

{
    const a = 1, b = 2,
          c = a + b;
}

Пустой блок без метки вложенный в множество блоков без меток на языке JavaScript:

{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}

Демонстрация одной из особенностей области видимости блока в JavaScript:

{
    let a = 1;
    var b = 2;
    console.log(b) // 2
    console.log(a) // 1
}
console.log(b) // 2
console.log(a) // ReferenceError!

Несмотря на особенность, продемонстрированную в предыдущем примере, следующий пример кода на языке JavaScript приведёт к синтаксической ошибке.

{
    let a = 1;
    var a = 1;
}

Блок на языке JavaScript с меткой и прерыванием его выполнения инструкцией break по его же метке (обратите внимание на отсутствие конфликта между меткой и одноимённым идентификатором):

x: {
    const x = 0;
    console.log(x);
    break x;
    console.log(x);
}

Разные семантики {...} в языке JavaScript (ошибочное содержимое используется с целью продемонстрировать определение семантики внешним контекстом):

// Блок кода
{ _: 1, _: 2, } + []; // SyntaxError!

// Блок кода
eval('{ _: 1, _: 2, }') // SyntaxError!
eval('{ valueOf: _ => Math.random() }') /*Неразрешимая неоднозначность для алгоритма определения семантики внутренним контекстом*/

// Литерал объекта
eval('({ _: 1, _: 2, })')
eval('+{ valueOf: _ => Math.random() }')

// Часть синтаксиса стрелочной функции
(() => { _: 1, _: 2, })() // SyntaxError!
// Литерал объекта
(() => ({ _: 1, _: 2, }))()

Демонстрация «слепоты» инструкции break языка JavaScript:

x: {
    console.log(1);
    (() => {
        break x; // SyntaxError!
    })();
    console.log(2);
}