Delphi를 한 라이너로 쓸 수 있습니다.
18255 단어 델파이
Delphi의 원라이너란?
기세로 「원 라이너 자랑 대회」란 Advent Calendar를 만든 것은 좋은 것의, 원래 Delphi에서는 원 라이너다운 원 라이너 쓸 수 없다! ? 라고...
제 안에서의 「원라이너다운 원라이너」는 단순히 1행으로 실행할 수 있다는 뜻은 아니고 콘솔로부터 기동하고 싶다고 하는 생각이 있어, 그러면 컴파일 언어인 Object Pascal 는 그것이 할 수 없는 것입니다.
그래서 먼저 콘솔에서 컴파일러를 호출하는 프로그램을 만들었습니다.
그것이 dcce입니다.
dcce
소스 코드는 이렇게!
program dcce;
{$APPTYPE CONSOLE}
{$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])}
{$WEAKLINKRTTI ON}
uses
System.SysUtils, System.IOUtils, Winapi.Windows;
function GetReg(const iKey: HKEY; const iAddress, iValue: String): String;
begin
var hReg: HKEY := 0;
var Ret := RegOpenKeyEx(iKey, PChar(iAddress), 0, KEY_QUERY_VALUE, hReg);
try
if Ret = ERROR_SUCCESS then
begin
SetLength(Result, $ff);
var RegType: DWORD := REG_SZ;
var VarSize: DWORD := Length(Result);
Ret :=
RegQueryValueEx(
hReg,
PChar(iValue),
nil,
@RegType,
PByte(PChar(Result)),
@VarSize
);
if Ret = ERROR_SUCCESS then
begin
SetLength(Result, VarSize div SizeOf(Char));
Result := Result.Trim;
end
else
Result := '';
end;
finally
RegCloseKey(hReg);
end;
end;
procedure Exec(const iCmd: String; const iNeedOutput: Boolean);
var
SI: TStartUpInfo;
PI: TProcessInformation;
begin
ZeroMemory(@SI, SizeOf(SI));
with SI do
begin
cb := SizeOf(SI);
if not iNeedOutput then
dwFlags := STARTF_USESTDHANDLES;
end;
if CreateProcess(nil, PChar(iCmd), nil, nil, True, 0, nil, nil, SI, PI) then
with PI do
try
while WaitForSingleObject(PI.hProcess, 100) = WAIT_TIMEOUT do
;
finally
CloseHandle(hProcess);
CloseHandle(hThread);
end;
end;
begin
var DprPath := TPath.ChangeExtension(TPath.GetTempFileName, '.dpr');
var ExePath := TPath.ChangeExtension(DprPath, '.exe');
try
var Writer := TFile.CreateText(DprPath);
try
Writer.Write('begin ');
for var i := 1 to ParamCount do
Writer.Write(ParamStr(i) + ' ');
Writer.Write(' end.');
finally
Writer.DisposeOf;
end;
Exec(
TPath.Combine(
GetReg(HKEY_CURRENT_USER, 'Software\Embarcadero\BDS\20.0', 'RootDir'),
'bin\dcc32.exe -Q -CC '
) + DprPath,
False);
Exec(ExePath, True);
finally
if TFile.Exists(DprPath) then
TFile.Delete(DprPath);
if TFile.Exists(ExePath) then
TFile.Delete(ExePath);
end;
end.
하는 일은 간단하고,
소스 코드는 이렇게!
program dcce;
{$APPTYPE CONSOLE}
{$RTTI EXPLICIT METHODS([]) FIELDS([]) PROPERTIES([])}
{$WEAKLINKRTTI ON}
uses
System.SysUtils, System.IOUtils, Winapi.Windows;
function GetReg(const iKey: HKEY; const iAddress, iValue: String): String;
begin
var hReg: HKEY := 0;
var Ret := RegOpenKeyEx(iKey, PChar(iAddress), 0, KEY_QUERY_VALUE, hReg);
try
if Ret = ERROR_SUCCESS then
begin
SetLength(Result, $ff);
var RegType: DWORD := REG_SZ;
var VarSize: DWORD := Length(Result);
Ret :=
RegQueryValueEx(
hReg,
PChar(iValue),
nil,
@RegType,
PByte(PChar(Result)),
@VarSize
);
if Ret = ERROR_SUCCESS then
begin
SetLength(Result, VarSize div SizeOf(Char));
Result := Result.Trim;
end
else
Result := '';
end;
finally
RegCloseKey(hReg);
end;
end;
procedure Exec(const iCmd: String; const iNeedOutput: Boolean);
var
SI: TStartUpInfo;
PI: TProcessInformation;
begin
ZeroMemory(@SI, SizeOf(SI));
with SI do
begin
cb := SizeOf(SI);
if not iNeedOutput then
dwFlags := STARTF_USESTDHANDLES;
end;
if CreateProcess(nil, PChar(iCmd), nil, nil, True, 0, nil, nil, SI, PI) then
with PI do
try
while WaitForSingleObject(PI.hProcess, 100) = WAIT_TIMEOUT do
;
finally
CloseHandle(hProcess);
CloseHandle(hThread);
end;
end;
begin
var DprPath := TPath.ChangeExtension(TPath.GetTempFileName, '.dpr');
var ExePath := TPath.ChangeExtension(DprPath, '.exe');
try
var Writer := TFile.CreateText(DprPath);
try
Writer.Write('begin ');
for var i := 1 to ParamCount do
Writer.Write(ParamStr(i) + ' ');
Writer.Write(' end.');
finally
Writer.DisposeOf;
end;
Exec(
TPath.Combine(
GetReg(HKEY_CURRENT_USER, 'Software\Embarcadero\BDS\20.0', 'RootDir'),
'bin\dcc32.exe -Q -CC '
) + DprPath,
False);
Exec(ExePath, True);
finally
if TFile.Exists(DprPath) then
TFile.Delete(DprPath);
if TFile.Exists(ExePath) then
TFile.Delete(ExePath);
end;
end.
하는 일은 간단하고,
그리고 이것만입니다.
덧붙여서 dcc32 에 건네주고 있는 인수의 -Q 는 침묵 컴파일 (불필요한 정보가 출력되지 않게 된다), -CC 는 컴파일 대상이 콘솔용,이라는 것을 나타냅니다.
-CC 를 지정하지 않으면 GUI 타겟이 되어 기동에 실패합니다.
실행하면 이런 느낌입니다.
역시 Delphi! 마치 인터프리터 같은 속도로 움직인다!
원라이너 FizzBuzz
라고 dcce 따위 만들고 있었기 때문에 당초 예정하고 있던 원라인 BrainF*ck 가 완성되지 않았습니다…
그렇다면 원라인 FizzBuzz에서 차를 탁하게 ...
그것이 이것입니다.
for var i := 1 to 100 do Writeln((function(const M: array of String): String begin Result := M[Ord(i mod 3 = 0) or Ord(i mod 5 = 0) * 2] end)([(function(N: Integer): String begin Str(N, Result) end)(i), 'Fizz','Buzz','FizzBuzz']))
위의 코드를 읽기 쉽게 한 것이 이것입니다.
for var i := 1 to 100 do
Writeln(
(
function(const S: array of String): String
begin
Result := S[Ord(i mod 3 = 0) or Ord(i mod 5 = 0) * 2]
end
)([
(
function(N: Integer): String
begin
Str(N, Result)
end
)(i),
'Fizz',
'Buzz',
'FizzBuzz'
])
)
Object Pascal 에서의 원라이너는 기본적으로 세미콜론리스 와 같을까 생각하고 있습니다.
그렇다고 하는 것으로, 익명 함수를 꽉 사용하고 있습니다.
물론 세미콜론을 사용할 수 없기 때문에 uses 도 없음. System 유닛의 함수만으로 만듭니다.
Str 절차 라든지 오랜만에 사용했다.
다만 Delphi 10.3 Rio 에서는 Pascal 전통의 var 블록 없이 인라인 변수 선언과 유형 추론을 사용할 수 있습니다. 때문에 세미콜론리스가 이전보다는 간편하게 실현되고 있습니다.
수행한 결과
요약
기세로 Advent Calendar 만들면 안돼!
덤
만약 이 기사에서 Delphi가 신경이 쓰이는 분은, 상용판과 같은 기능을 사용할 수 있는 완전 무료의 델파이 10.3 리오 커뮤니티 에디션 를 사용해 보세요!
무료로 Windows, macOS, Android, iOS를 개발할 수 있어요!
Reference
이 문제에 관하여(Delphi를 한 라이너로 쓸 수 있습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/pik/items/e40d95f63508c75f2736
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
for var i := 1 to 100 do Writeln((function(const M: array of String): String begin Result := M[Ord(i mod 3 = 0) or Ord(i mod 5 = 0) * 2] end)([(function(N: Integer): String begin Str(N, Result) end)(i), 'Fizz','Buzz','FizzBuzz']))
for var i := 1 to 100 do
Writeln(
(
function(const S: array of String): String
begin
Result := S[Ord(i mod 3 = 0) or Ord(i mod 5 = 0) * 2]
end
)([
(
function(N: Integer): String
begin
Str(N, Result)
end
)(i),
'Fizz',
'Buzz',
'FizzBuzz'
])
)
기세로 Advent Calendar 만들면 안돼!
덤
만약 이 기사에서 Delphi가 신경이 쓰이는 분은, 상용판과 같은 기능을 사용할 수 있는 완전 무료의 델파이 10.3 리오 커뮤니티 에디션 를 사용해 보세요!
무료로 Windows, macOS, Android, iOS를 개발할 수 있어요!
Reference
이 문제에 관하여(Delphi를 한 라이너로 쓸 수 있습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/pik/items/e40d95f63508c75f2736
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Delphi를 한 라이너로 쓸 수 있습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/pik/items/e40d95f63508c75f2736텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)