Delphi [10.3 리오] 델파이 언어의 새로운 변화: 인라인 변수 선언
2018.11.12 15:52
델파이 언어의 새로운 변화: 인라인 변수 선언
* 본 글은 엠바카데로 델파이 제품 담당자 마르코 칸투(Marco Cantu)의 글을 일부 발췌 및 번역한 글입니다.
전문은 다음 링크를 통해 확인할 수 있습니다: http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html
델파이 언어가 10.3 버전부터 로컬 변수 선언에 있어 훨씬 더 융통적으로 변합니다. 매우 핵심적인 기능 변화라고 볼 수 있습니다. 이번 업데이트는 본래 파스칼(Pascal) 언어의 핵심 개념을 깨는 변화이기는 합니다. 하지만 이 변화는 많은 장점을 제공하며, 이를 통해 불필요한 코드를 줄일 수 있습니다.
예전 스타일의 Var 블록
터보파스칼 1부터 지금까지 기존 파스칼 언어 규칙에 따라 모든 로컬 변수 선언은 함수(function), 프로시저(procedure), 메소드(method) 작성 전에 var 블록에 선언해야만 했습니다.
procedure Test;
var
I: Integer;
begin
I := 22;
ShowMessage (I.ToString);
end;
인라인 변수 선언
새로운 인라인 변수 선언 구문을 사용해 코드 블록에서 바로 변수를 선언할 수 있습니다 (여러 기호 허용):
procedure Test;
begin
var I, J: Integer;
I := 22;
j := I + 20;
ShowMessage (J.ToString);
end;
작은 차이로 보일 수도 있지만, 이번 변화를 통해 많은 효과를 얻을 수 있습니다.
어떤 효과를 얻을 수 있을지 아래를 통해 확인해보세요.
인라인 변수 초기화
이전 선언 방식과 비교해 가장 크게 변한 점은 변수 인라인 선언과 초기화를 한 문장에서 끝낼 수 있다는 것입니다.
함수 선언부에서 변수를 초기화 하는 것도 훨씬 더 보기에 쉽고 파악하기 좋습니다.
procedure Test; // declaration and initialization in a single statement
begin
var I: Integer := 22;
ShowMessage (I.ToString);
end;
또한 코드 블록에서만 변수를 사용하게 되면, 초기값 (0 또는 nil)을 설정하고 난 뒤에 실제 값을 할당하는 것보다
효율적입니다. 변수 선언을 적절한 초기값 지정 시점에 할 수 있기 때문입니다.
다시 말해, 이전에는 전체 코드 블록에 걸쳐 모든 로컬 변수들을 확인했다면, 이제는 변수 선언 위치에서만 그리고 코드 블록의 마지막 부분까지만 확인하면 됩니다.
procedure Test1; // multiple inline declarations (symbols declared when used)
begin
var I: Integer := 22;
var J: Integer := 22 + I;
var K: Integer := I + J;
ShowMessage (K.ToString);
end;
중첩된 블록에 선언된 인라인 변수의 범위와 수명
범위 제한은 전체 프로시저, 메소드가 아닌, begin-end 코드 블록에만 인라인 변수가 표시되기 때문에 더 의미가 있습니다. 인라인 변수 선언은 선언한 블록으로 범위가 제한되며 블록 외에서는 사용할 수 없습니다. 선언한 변수의 수명 또한 블록 안에서만 적용되는 것으로 제한됩니다. 관리 데이터 유형(인터페이스, 스트링, 관리 레코드 등)은 지금까지와 같이 프로시저나 메소드 끝 부분이 아닌 하위 블록의 마지막 부분에서 처리될 것입니다.
procedure Test2; // scope limited to local block
begin
var I: Integer := 22;
if I > 10 then
begin
var J: Integer := 3;
ShowMessage (J.ToString);
end
else
begin
var K: Integer := 3;
ShowMessage (J.ToString); // COMPILER ERROR: "Undeclared identifier: J"
end;
// J and K not accessible here
end;
위 마지막 코드에서 확인할 수 있듯, begin-end 블록에 선언된 변수는 특정 블록에만 표시되며 그 블록이 종료된 이후에는 적용되지 않습니다. if 문 끝에 위치한 J와 K 값은 이후에는 확인할 수 없는 것입니다.
앞서 설명했듯, 이와 같은 효과는 단순히 가시성 문제에만 국한되는 것은 아닙니다. 인터페이스 참조나 레코드와 같이 변수 또한 블록 마지막 부분에서 정리되는 것입니다.
procedure Test99;
begin
// some code
if (something) then
begin
var Intf: IInterface = GetInterface; // Intf.AddRef
var MRec: TManagedRecord = GetMRecValue; // MRec.Create + MRec.Assign
UseIntf(Intf);
UseMRec(MRec);
end; // Intf.Release and MRec.Destroy are implicitly called at end of scope
// more code
end; // no additional cleanup
인라인 변수에 대한 타입 유추
인라인 변수의 또 다른 큰 이점은 컴파일러가 여러 상황에서 할당된 식 또는 값의 유형을 파악해 인라인 변수의 타입을 유추할 수 있다는 것입니다.
procedure Test; begin var I := 22; ShowMessage (I.ToString); end;
r-value 표현식(":=" 다음에 오는 값)을 분석해 변수의 타입을 판별합니다. 위의 경우와 같이 숫자 값 22(ShortInt)가 Integer로 확장되는 경우와 같이 일부 데이터 유형은 더 큰 유형으로 "확장"됩니다. 일반적으로 우항의 수식 유형이 정수형이고 32비트보다 작으면 변수는 정수로 선언됩니다. 특정한 작은 숫자 유형을 사용하려면 명시적으로 유형을 지정해 사용할 수 있습니다.
이 기능은 정수 또는 문자열에 대한 일부 키입력을 줄일 수 있지만, 저너릭(Generic)의 인스턴스처럼 복잡한 유형의 경우 변수 타입 유추하는 것이 상당히 유용합니다.
아래 코드를 보면, MyDictionary 변수에 대한 TDirtionary 타입 유추와 APair 변수에 대한 TPair 타입 유추를 확인할 수 있습니다.
procedure NewTest; begin var MyDictionary := TDictionary<string, Integer>.Create; MyDictionary.Add ('one', 1); var APair := MyDictionary.ExtractPair('one'); ShowMessage (APair.Value.ToString) end;
인라인 상수
변수와 같이, 상수도 인라인으로 선언할 수 있습니다. 타입 지정 함수 또는 타입 미지정 함수 모두에 적용할 수 있습니다.
const M: Integer = (L + H) div 2; // single identifier, with type specifier const M = (L + H) div 2; // single identifier, without type specifier
For 루프에서 인라인 루프 변수 선언 사용
인라인 변수 선언을 활용할 수 있는 또다른 상황은 for-to 루프와 for-in 루프를 포함한 for 루프 문입니다.
for var I: Integer := 1 to 10 do ... for var Item: TItemType in Collection do...
형식 유추를 활용해 코드를 더 단순화 가능합니다.
for var I := 1 to 10 do ... for var Item in Collection do ...
아래 예제 코드와 같이 제한된 범위의 인라인 변수를 사용하면 더욱 유용합니다. 루프 외부에서 I 변수를 사용하면 컴파일러 오류가 발생합니다.(대부분 경우 경고가 발생합니다.)
procedure ForTest; begin var total := 0; for var I: Integer := 1 to 10 do Inc (Total, I); ShowMessage (total.ToString); ShowMessage (I.ToString); // compiler error: Undeclared Identifier ‘I’ end;
인라인 선언에 대한 정리
인라인 변수 선언은 타입 추론과 지역 범위(local scope)와 더불어 델파이 언어에 신선한 변화를 줄 것입니다. 파스칼 소스 코드의 가독성은 보존해야 할 핵심 원칙으로 남아있지만, 핵심 수준에서 언어를 최신식으로 현대화하기 위한 중요한 변화입니다. 인라인 변수는 전통적인 코딩 스타일과는 다른 다양한 이점들이 있습니다.
여전히 소스 코드를 그대로 유지하고 동료 개발자들에게 전통 선언 방식을 고수하는 것이 문제가 되지는 않지만: 기존 코드나 작성 방식이 잘못되었다는 것은 절대 아닙니다, 인라인 변수 선언은 분명히 새로운 기회가 될 것입니다. 그냥 단지.. 저의 경우에는 델파이의 오래전 버전으로 돌아가기에는 이미 어렵다는 말만 전하고 싶습니다.
관련글
- [docwiki] Inline Variable Declaration / 한글 번역
10.3 리오의 업데이트 버전들