Perl 내장 함수의 Raku 대응
Perl 내장 함수의 Raku 대응 (Perl functions in Raku)
이 문서는 Perl의 perlfunc 문서에 나오는 함수들을 그에 해당하는 Raku 함수로 안내하려는 (가능하면) 포괄적인 목록이에요. 함수의 상세 문서는 이 문서의 링크를 따라가면 돼요.
일반적인 한 가지 의견: Raku는 Perl보다 객체를 훨씬 더 진지하게 다뤄요. Raku에서는 모든 것이 객체지만, 언어가 유연해서 원하지 않으면 객체 지향 방식으로 작업할 필요를 강제하지는 않아요. 다만 그 의미는 function(@args) 형태의 함수 호출이 이제 @args.function 형태의 메서드 호출이기도 하다는 거예요. (드물게 메서드 호출만 존재하는 경우도 있어요.) 여기서 달리 언급하지 않으면 "function"은 func(@args) 스타일, "method"는 @args.func 스타일을 말해요.
파일 테스트 (Filetests)
Perl의 -X FILEHANDLE 등: Raku에서는 파일 테스트에 스마트매치(~~)를 쓰거나 메서드를 호출할 수 있어요. 파일을 전통적인 방식으로 열지 않아도 되고, 파일명에 .IO를 붙이면 돼요. 파일이 읽기 가능한지 스마트매치로 확인:
'/path/to/file'.IO ~~ :r
이미 열린 파일핸들도 쓸 수 있어요. $fh 핸들에 메서드 문법:
$fh.r
이전 파일 테스트 대부분은 스마트매치용 콜론 등가물이 있어요:
| 콜론 | 의미 |
|---|---|
:e |
Exists (존재) |
:d |
Directory (디렉터리) |
:f |
File (파일) |
:l |
Symbolic link (심볼릭 링크) |
:r |
Readable (읽기 가능) |
:w |
Writable (쓰기 가능) |
:x |
Executable (실행 가능) |
:s |
Size (크기) |
:z |
Zero size (빈 크기) |
이 모든 테스트는 (콜론 없이) 메서드로 쓸 수 있어요. 단 세 개의 테스트는 메서드로만 존재해요:
$fh.modified; # -M $fh
$fh.accessed; # -A $fh
$fh.changed; # -C $fh
나머지 Perl 파일 테스트는 Raku에 구현되어 있지 않아요. 파일 읽기/쓰기 정보는 io에 있어요.
함수별 대응 안내 (가나다순)
abs
함수(abs($x))와 메서드로 동작해요. 주의: 메서드 호출이 -보다 단단히 결합하므로 -15.abs는 -(15.abs)로 평가되어 -15가 돼요. (-15).abs처럼 해야 해요. abs는 값이 없을 때 $_에도 동작하지만 함수가 아니고, 메서드로는 그냥 abs가 아니라 .abs로 호출해야 해요.
accept
서버에 메서드로 호출해요($server.accept()). 압축된 주소 대신 IO::Socket 계열 객체인 소켓을 반환해요.
alarm
alarm()은 더 이상 없어요. 대신 일정 시간 후 또는 특정 시각에 코드를 실행할 수 있어요:
Promise.in(5).then: { say "five seconds have passed" }
Promise.at(now + 5).then: { say "five seconds have passed" }
소켓 관련 bind()는 Raku에 보이지 않아요. 소켓 바인딩은 새 소켓 객체를 만들 때 필요한 일이 일어날 거예요. binmode는 소켓을 열 때 파일 모드로 :bin을 쓰면 돼요(my $fh = open("path/to/file", :bin);).
bless
Raku의 클래스 생성 변경으로 쓰임이 줄었고, 메서드이자 함수예요. Raku 문서는 "invocant와 같은 타입의 새 객체를 만들고, 이름 인자로 속성을 초기화하며, 생성된 객체를 반환"한다고 해요. Perl에서 모듈을 포팅한다면 bless보다는 new를 쓰는 게 좋을 거예요.
break
Raku에 존재하지 않아요. given 블록에서 빠져나오려면 proceed와 succeed를 보세요.
caller
Raku에서 caller 정보를 얻는 몇 가지 방법이 있어요. 기본 기능은 이제 callframe이 제공해요. Raku는 서브루틴뿐 아니라 일반 블록에도 콜 프레임을 만들므로 프레임이 더 많아요. 다음은 caller가 반환하던 기본 정보를 얻는 코드:
my $frame = callframe(0); # 또는 그냥 callframe()
my ($subroutine, $package);
if $frame.code ~~ Routine {
$subroutine = $frame.code.name;
$package = $frame.code.package;
}
my $file = $frame.file;
my $line = $frame.line;
caller가 반환하던 다른 세부사항 대부분은 Perl 전용이라 Raku에선 의미가 없어요. Backtrace가 콜 스택을 탐색하는 더 쉬운 방법일 수 있어요.
chdir
Perl처럼 동작하지만 반드시 인자를 받아야 해요. chdir()의 (HOME/LOGDIR 참조) 동작은 지원되지 않아요. Raku의 chdir은 $*CWD 동적 변수만 바꾸고 OS 관점의 기본 디렉터리는 실제로 바꾸지 않아요. "OS 스레드당 기본 디렉터리" 개념이 없기 때문이에요.
chmod
Perl과 같이 동작하되 8진수를 다르게 표현해요(0755 대신 0o755). 메서드로도 쓸 수 있어요: $fh.chmod(0o755).
chomp
Perl과 달리 대상에 영향을 주지 않고 마지막 논리 줄바꿈이 제거된 사본을 반환해요. 예: $x = "howdy\n"; $y = chomp($x);는 $x가 "howdy\n", $y가 "howdy"를 담아요. 메서드($x.chomp), 할당($x.=chomp)으로도 동작해요. 인자 없는 chomp()는 Raku에서 지원되지 않아요.
chop
chomp처럼 자르는 게 아니라 잘린 문자열을 반환해요. $x = "howdy"; $y = chop($x);는 $x가 "howdy", $y가 "howd". 메서드로도 동작해요.
chr
Perl 버전과 비슷하게 대상을 정수로 강제 변환하고 그 유니코드 코드 포인트로 해당 문자를 반환해요. 함수·메서드 겸용:
chr(65); # "A"
65.chr; # "A"
close
Perl처럼 파일핸들을 닫고 Boolean을 반환해요. close $fh와 $fh.close 모두 동작해요.
connect
비동기 소켓이면 IO::Socket::Async의 connect, 동기 소켓이면 IO::Socket::INET을 만들어요.
continue
continue 블록 대신 NEXT 블록을 쓰세요. Perl의 맨 continue;에 가장 가까운 것은 proceed/succeed예요.
cos
Perl처럼 동작. 값이 없을 때 $_.cos로 메서드 호출해요.
defined
아마 예상대로이지만, 기술적으로 타입 객체에서는 False, 그 외에는 True를 반환해요. 메서드로 쓸 수 있고($num.defined), 새로 만든 클래스도 자신의 .defined 메서드를 가질 수 있어요.
delete
Raku는 새 어드바 문법, 특히 :delete 어드바로 교체했어요. 예: my $deleted_value = %hash{$key}:delete;와 my $deleted_value = @array[$i]:delete;.
die
Perl 버전처럼 동작하지만, Raku의 Exception 메커니즘이 더 강력하고 유연해요. 예외 참고. Perl의 die "...\n"처럼 스택트레이스·위치를 빼려면:
note "...";
exit 1;
do
do BLOCK은 Perl 버전과 비슷하되 do와 블록 사이에 공백이 있어야 해요. do EXPR은 Raku에서 EVALFILE로 교체됐어요.
each
정확한 등가물이 없어요. Raku에서 해시는 Pair 객체로 구성되기 때문이에요. %hash.kv가 키와 값 리스트를 반환해요: for %hash.kv -> $k, $v { say "$k: $v" }. %hash.pairs는 각 Pair를 하나의 개체로, %hash.antipairs는 키/값을 뒤집어 같은 걸 해요.
eof
Raku에서는 함수로 쓸 수 없고 메서드로만 쓸 수 있어요: $filehandle.eof. 파일 끝이면 True를 반환해요.
eval
가장 가까운 교체는 EVAL 함수예요. 단, 이 함수는 pragma로 명시적으로 허용돼야 동일하게 동작해요. EVAL은 예외 처리를 하지 않아요!
exec
Raku에는 Perl exec를 정확히 재현하는 게 없어요. shell과 run은 Perl의 system과 비슷하지만, exec의 시스템 명령 실행 후 반환하지 않는 동작은 shell($command);exit(); 같은 걸로 흉내 내야 해요. 프로세스를 대체하는 동작이 필요하면 NativeCall 인터페이스로 exec* 함수를 쓰세요.
exists
Raku에서는 함수가 아니라 어드바예요:
%hash{$key}:exists;
@array[$i]:exists;
fileno
IO::Handle의 native-descriptor 메서드가 fileno에 해당해요.
fork
내장 fork 함수가 없어요. Raku는 스레드를 광범위하게 지원하고 내부적으로 사용해요. fork는 fork를 호출한 스레드만 복제하므로, 다른 스레드들이 (잠금을 들고 알 수 없는 상태로) 빠진 프로세스가 돼요. 사전 컴파일 과정이나 VM이 내부 작업자 스레드를 만들기도 해서 스레드 존재는 거의 보장되므로, fork를 안정적으로 동작시키기 어려워요.
getc
Perl처럼 입력 스트림에서 단일 문자를 읽어요. 메서드로도 쓸 수 있어요: $filehandle.getc.
glob
코어에는 없지만 일부 기능은 dir 루틴의 test 인자로 제공돼요.
gmtime
localtime의 여러 부분처럼 gmtime 기능은 DateTime 객체에 있는 것 같아요. 현재 시각의 UTC 버전: my $gmtime = DateTime.now.utc.
goto
goto LABEL 문법은 받아들여지지만 런타임 부분은 아직 구현되지 않았어요. FOO: goto FOO;는 런타임 오류가 돼요.
grep
여전히 있지만, 블록 형태는 이제 블록 뒤에 콤마가 필요해요: @foo = grep { $_ = "bars" }, @baz. 메서드로도: @foo = @bar.grep(/^f/).
hex
Raku에서 표현식이 반드시 지정돼야 해요. 어드바 형태 :16으로 교체됨: :16("aF")는 175를 반환. Str→Int. 반대(Int→Str)는 .base 메서드: 0xaF.base(10).
index
Perl처럼 동작하고 메서드로도 쓸 수 있어요. Perl과의 주요 차이는 부분 문자열을 못 찾으면 -1 대신 Nil을 반환하는 것. with 명령과 결합하면 유용해요:
with index("foo","o") -> $index {
say "Found it at $index";
}
else {
say "Not found"
}
int
Raku에는 Perl의 int가 하는 일을 하는 truncate 함수(메서드 겸용)가 있어요. 3.9.Int와 3.9.truncate는 동등해요. int는 Raku에서 의미가 있어요 — 네이티브 정수를 나타내는 타입이에요:
my int $a = 42; # 네이티브 정수
join
Perl처럼 동작하고 메서드로도: @x.join(",").
keys
Perl처럼 동작하고 메서드로도: %hash.keys.
kill
미리 정의된 코어 대안이 없어요. 비휴대성 방법은 NativeCall을 쓰는 것:
use NativeCall;
sub kill(int32, int32) is native {*};
kill $*PID, 9; # OUTPUT: «Killed»
Proc::Async로 시작한 프로세스는 Proc::Async.kill 메서드를 쓰세요.
last / next / redo
Perl과 동일.
lc
Perl처럼, 메서드("UGH".lc)로도. Raku에서 표현식이 반드시 지정돼야 해요.
length
chars로 교체됨. 보통 메서드($string.chars)로 쓰지만 함수로도 동작해요.
link / symlink
local
Raku 등가물은 temp예요. 다만 local과 달리 주어진 변수의 값이 즉시 해제되지 않고, 할당되기 전까지 원래 값을 유지해요.
localtime
localtime 기능 대부분은 DateTime에 있어요:
my $d = DateTime.now;
my $sec = $d.second;
my $min = $d.minute;
my $hour = $d.hour;
my $mday = $d.day-of-month;
my $mon = $d.month;
my $year = $d.year;
my $wday = $d.day-of-week; # 1 => Monday
my $yday = $d.day-of-year;
Raku는 범위가 0-기반이 아니라는 점을 주의하세요.
log / exp / sin / sqrt / atan2
Perl과 동일하고 대부분 메서드로도 쓸 수 있어요. (예: atan2(100)와 100.atan2 동등.)
m// (매치 연산자)
Raku에서 정규식 문법은 좀 다르지만 매치 연산자는 여전히 존재해요. Perl 코드를 재작성할 때 가장 중요한 차이는 =~가 스마트매치 ~~로 교체된 것, !~가 !~~로 교체된 것. 정규식 수식어는 어드바이며 복잡해요 — Adverbs 참고.
map
함수로는 Perl과의 유일한 차이가 블록 뒤에 콤마가 필요하다는 것. 메서드로도: @new = @old.map: { $_ * 2 }. 펼침이 정확히 같지 않으므로 배열도 펼칠 필요가 있을 수 있어요: my @combined = map { $_ ~ ' b' }, |@old1, |@old2.
mkdir
Perl처럼 동작. 다단계 디렉터리 지정 시 자동으로 중간 디렉터리를 만들고(Perl의 File::Path "make_path"와 비슷), 0-인자(암시적 $_) 버전은 허용되지 않아요.
my / our / state
Perl과 동일하게 동작해요 (state는 state 참고).
oct
어드바 형태 :8로 교체됨: :8("100")은 64를 반환. 0x, 0o, 0b로 시작하는 문자열은 prefix:<+> 연산자를 쓰면 돼요.
open
Perl에서 가장 두드러진 변화는 파일 모드 문법이에요. 읽기 전용은 open("file", :r), 쓰기 전용/읽기-쓰기/추가는 각각 :w, :rw, :a. 인코딩과 줄바꿈 처리 옵션도 있어요. 또 파일핸들은 스코프 종료 시 자동으로 닫히지 않아서 명시적으로 close를 호출해야 해요.
opendir / readdir / closedir / rewinddir / seekdir / telldir
Raku 기본 제공이 아님. 디렉터리 내용 반복은 dir 루틴 참고.
ord
Perl과 동일. 메서드: "howdy!".ord; # 104.
pack / unpack
use experimental :pack을 지정한 스코프에서 사용 가능. 템플릿 옵션은 Perl보다 제한적이에요. 문서화된 목록은 unpack 참고.
package
S10에 따르면 Raku에서 package는 블록과 함께만 쓸 수 있어요. package Foo { ... }. 모듈과 클래스는 class 같은 별도 키워드로 선언되므로 package를 직접 쓸 일은 드물 거예요.
pop / shift / push / unshift
Raku에서 동작하고 메서드로도 쓸 수 있어요. 비-매개변수 버전은 존재하지 않고, 배열이 비어 있으면 Failure를 반환해요(의미 있게 쓰면 던져짐). push/unshift는 Perl처럼 새 요소 수를 반환하는 게 아니라 배열 자체를 반환해요. 펼침 동작도 달라 @b.push: @a는 @a를 단일 요소로 넣어요 (append 참고).
print / printf / say
print는 표준 출력에 쓰는 함수로 쓸 수 있고, 파일핸들에는 메서드($fh.print("howdy!"))로. say는 파일핸들 뒤에 콜론을 두면 돼요: say $fh: "Howdy!". 형식 지시자는 sprintf 참고.
q/qq/qw/qx 인용
대부분 그대로 남아요: q/.../는 단일 따옴표, qq/.../는 이중 따옴표와 동등하고, qw/.../는 Raku에서 더 흔히 <...>로 써요. qr/STRING/은 rx/.../로 교체됐어요.
rand
rand는 Perl처럼 동작하지만 더 이상 인자를 못 줘요. 숫자에 메서드로 쓰면 그 동작을 얻어요: Perl의 rand(100)은 Raku에서 100.rand. 난수 정수는 (^100).pick.
read
IO::Handle과 IO::Socket에 있어요. 지정된 바이트 수(문자가 아니라)를 읽어요. (Perl의 오프셋 사용은 아직 문서화되지 않음.)
readline
Raku에 없어요. .lines 메서드를 쓰는 게 좋아요.
ref
사라졌어요. 타입 이름을 정말 원하면 $var.WHAT.^name.
rename
여전히 사용 가능.
reverse
Raku에서는 리스트 요소만 뒤집어요. reverse(@a) 또는 @a.reverse. 문자열의 문자를 뒤집으려면 .flip 메서드.
rindex
Perl처럼, 메서드로도. $x.rindex("a"). 못 찾으면 -1 대신 Nil 반환.
rmdir
Raku에서 동작하고 메서드로도: "Foo".IO.rmdir.
s///
정규식 문법은 좀 다르지만 치환 연산자는 존재해요. =~→~~, !~→!~~. 세부사항은 s/// 문서 참고.
select
"[S]elect as a global concept is dead." $*OUT 등은 동적 스코프에서 오버라이드할 수 있어요.
sleep
Perl처럼 동작하지만 정수 초로 제한되지 않고 항상 Nil을 반환해요. 지정 시각까지 자려면 sleep-until(Instant 받음)을 써요. N초마다 코드를 실행하려면 Supply.interval과 함께 react/whenever를 써 보세요.
sort
sort는 존재하지만 좀 다르고, $a/$b는 더 이상 특별하지 않으며, 정렬 루틴은 0/양수/음수가 아니라 Order::Less/Order::Same/Order::More 객체를 반환해요 (sort 참고). 메서드로도: sort(@a) ≡ @a.sort.
splice
Raku에서 사용 가능하고 메서드로도 가능: @foo.splice(2, 3, <M N O P>).
split
대부분 Perl처럼. 빈 문자열의 특수 동작은 실제로 빈 문자열을 써야 해요. 구분자를 결과에 포함하려면 :all 이름 인자. 빈 조각은 (Perl처럼) 제거되지 않아요. 패턴이 반드시 필요해요 — Perl의 공백 분할 기본값은 words로 대체.
sprintf
Perl처럼 동작. 형식 지시자 표:
| 지시자 | 의미 |
|---|---|
% |
리터럴 퍼센트 부호 |
c |
주어진 코드포인트의 문자 |
s |
문자열 |
d |
십진 부호 정수 |
u |
십진 무부호 정수 |
o |
8진 무부호 정수 |
x |
16진 무부호 정수 |
e |
과학 표기법 부동소수점 |
f |
고정 소수 표기 부동소수점 |
g |
%e 또는 %f 표기 부동소수점 |
X/E/G |
대문자 변형 |
srand / rand
srand는 Raku에 존재해요.
substr
함수·메서드 겸용. substr과 변경용 substr-rw 참고. Str 리터럴에는 (불변이므로) 변경 불가:
my $a = 'Cheesy';
$a.substr-rw(4,1)="k";
say $a; # OUTPUT: «Cheeky»
system
tie
스칼라를 tie하는 Raku 대안은 Proxy 컨테이너예요:
sub lval() {
Proxy.new(
FETCH => method () { ...},
STORE => method ($new) { ... }
)
}
lval을 좌변값 sub로 만든다. 값이 요청되면 FETCH가, 할당에 쓰이면 STORE가 호출돼요. 배열/해시(Positional/Associative 역할)는 해당 역할이 요구하는 메서드만 제공하면 Perl의 tie 기능을 얻을 수 있어요.
time
시대(epoch) 이후 초(Int). Perl과 동일.
tr///
Perl과 비슷하되 범위를 다르게 지정해요. "a-z" 대신 "a..z". Raku에서 tr///는 몇 가지 추가 기능을 제공하는 trans 메서드 버전이 있어요. Perl의 /r 플래그는 TR/// 연산자로 구현되고, y/// 등가물은 없어요.
uc / ucfirst
uc는 함수·메서드로 동작("ha".uc). ucfirst는 없어졌고, titlecase 함수 tc나 tclc로 대체.
undef
Raku에는 undef가 없어요. 함수를 정의 해제할 수 없고, 가장 가까운 값은 아마 Nil이지만 그것도 쓸 일이 많지 않아요.
unlink
여전히 사용 가능하고 메서드로도: "filename".IO.unlink. 0-인자 버전은 허용되지 않아요.
use
Perl에서 최소 perl 실행 파일 버전을 요구하는 반면, Raku는 여러 실행 파일이 구현할 수 있는 사양 버전(예: 6.c)을 요구해요.
values
Raku에서 사용 가능하고 메서드로도: %hash.values.
vec
Raku에 vec() 지원이 없어요. 대신 선언된 buffer/array의 bit, uint2, uint4 등을 쓸 것을 권장했지만, 지금은 uint8/int8부터 uint64/int64 그리고 시스템 크기 uint/int까지 지원돼요.
wait / waitpid
저수준 wait 관련은 위치가 불분명해요. Supply에 wait 메서드가, Channel/Promise에 await 메서드가 있어요.
wantarray
Raku에는 wantarray가 없지만 많은 사용 사례를 쉽게 대체할 수 있어요. Raku는 List/Array를 Scalar에 담는 데 특별한 참조 문법이 필요 없으므로 그냥 리스트를 반환하면 돼요:
sub listofstuff {
return 1, 2, 3;
}
my $a = listofstuff();
print $a; # OUTPUT: «1 2 3»
print join("<", listofstuff()) # OUTPUT: «1<2<3»
warn
warn은 재개 가능한 예외를 던져요. $*ERR에 메시지를 그냥 출력하려면 note 함수를 쓰세요.
요약
Perl의 내장 함수 대부분은 Raku에 그대로 존재하거나 메서드 형태로 존재해요. 사라진 것들(dump, study, format, scalar, wantarray 등)은 대개 더 명확한 대안이 있거나 언어 설계에서 제거된 것들이에요. 많은 Perl 함수가 P5 시리즈 모듈로 원래 동작을 최대한 재현해 제공되니, 포팅 시 참고하면 도움이 돼요.