حرکت فرمتهای printf به جلو – انجمن DEV

یکی از مزایای RakuAST این است که می توانید کدهای اجرایی را به سبک شی گرا بسازید. یکی از زمینه هایی که واقعاً در این زمینه مورد توجه شما قرار گرفته، رسیدگی به آن است sprintf
فرمت ها
از لحاظ تاریخی، زبان برنامه نویسی C اولین پیاده سازی را ارائه کرد printf
منطق:
خانواده توابع printf در زبان برنامه نویسی C مجموعه ای از توابع هستند که یک رشته فرمت را به عنوان ورودی در میان لیستی با اندازه متغیر از مقادیر دیگر می گیرند و رشته ای را به عنوان خروجی تولید می کنند که با تعیین کننده فرمت و مقادیر ورودی داده شده مطابقت دارد.
و در راکو؟
البته زبان برنامه نویسی راکو هم پیاده سازی دارد printf
، با مجموعه ای از گزینه های پشتیبانی شده. با این حال پیاده سازی Rakudo زبان برنامه نویسی Raku پیاده سازی ندارد printf
فرمت های خود را دارد، اما آن را از آن وام گرفته است NQP
. که مزایا و معایب خود را دارد.
البته نکات مثبت این است که NQP به طور کلی بسیار سریعتر از Raku است (زیرا NQP به نوعی “زبان اسمبلی” راکودو است). با این حال، اجرای NQP از sprintf
با استفاده از گرامر (نوشته شده در NQP) نوشته شده است. و هر یک زمانی که یک تماس با این برقرار می شود sprintf
عملکرد (به عنوان مثال، هنگام چاپ یک خط در یک گزارش با استفاده از sprintf
)، کل دستور زبان دوباره اجرا می شود، با اقدامات مرتبط که رشته را می سازند تا برگردانده شوند. و اجرای دستور زبان از نظر حافظه پرهزینه است و CPU.
این باعث راکودو می شود sprintf
و توابع مرتبط (مانند .fmt
) یکی از کندترین ویژگی های راکو در راکودو. مطمئناً با RakuAST باید راه بهتری برای این کار وجود داشته باشد؟
Formatter را وارد کنید
تقریباً دو سال پیش، سفر شما واقعاً در RakuAST آغاز شد. ابتدا با نوشتن تست، بعداً ویژگیهای RakuAST را امتحان کنید. و یکی از اولین کارهایی که انجام شد، پورت کردن گرامر اصلی NQP بود sprintf
به راکو و یک مجموعه جداگانه از اقدامات ایجاد کنید، که می شود نه یک رشته تولید می کند، اما در عوض یک AST تولید می کند.
سپس چنین AST می تواند به کد اجرایی تبدیل شود، و سپس هر زمان که مجموعه ای از آرگومان ها نیاز به تبدیل به یک رشته داشته باشند، اجرا شود. بنابراین به جای نیاز به اجرای یک گرامر یکسان، میتوان فقط چند کد (ایستا) را فراخوانی کرد، که پس از آن، مانند هر قطعه کد دیگری در Raku، زمان اجرا برای عملکرد بهتر بهینهسازی میشود.
این پس از آن تبدیل شد Formatter
کلاس و از آنجایی که این یک ویژگی کاملاً جدید بود، فقط با استفاده از آن در دسترس قرار گرفت 6.e.PREVIEW
نسخه زبان و سپس برای 1.5 سال آینده تا حد زیادی مورد توجه و بی توجهی قرار گرفت. همانطور که واضح است هنوز زمان برای آن مناسب نبوده است.
موانع
یکی از موانعی که در حین کار با آن مواجه شد Formatter
، بود که وجود داشت نه آزمون های جامع برای sprintf
قابلیت برای Raku. بله وجود داشت آ فایل آزمایشی که برخی از ویژگیها را آزمایش کرد، اما هیچ آزمایش جامعی برای همه ترکیبهای ممکن از ویژگیهای قالب، همراه با مقادیر احتمالی که باید روی آنها کار کنند، وجود نداشت.
این یکی از اولین کارهایی بود که باید انجام می شد، تا بتوان گفت که اجرای جدید با قدیمی مطابقت دارد. در طول توسعه این آزمایشها، مشخص شد که برخی ناسازگاریها در اجرای موجود وجود دارد و بدتر از آن: اشکالات آشکار.
بنابراین این سؤال مطرح شد: آیا اجرای جدید باید از رفتار اجرای قدیمی پیروی کند یا خیر؟
نشست هسته ای راکو
سپس این به بخشی از بحث در اولین نشست هسته ای راکو تبدیل شد. در آنجا تصمیم گرفته شد که اجرای جدید به اجرای قبلی پایبند نباشد، زیرا جدید sprintf
به هر حال عملکرد به نسخه زبانی نیاز دارد. و این جریان sprintf
آزمون ها باید برای سطح زبان ثابت شوند 6.d
. و به همین ترتیب انجام شد.
تصمیم دیگری که گرفته شد، این بود که عملکرد ارائه شده توسط Formatter
کلاس (که یک رشته فرمت را به a تبدیل می کند Callable
) باید در a تعبیه شود Format
کلاس که معمولاً باید به عنوان یک رشته عمل کند، اما زمانی که به عنوان یک استفاده می شود Callable
باید پردازش را مطابق فرمت داده شده انجام دهد. این هم اکنون اجرا شده است. یعنی اکنون می توانید انجام دهید:
use v6.e.PREVIEW;
my $f = Format.new("%5s");
dd $f; # Format.new("%5s")
say $f; # %5s
dd $f("foo"); # " foo"
say "'$f'"; # '%5s'
say "'$f("foo")'"; # ' foo'
همانطور که می بینید، Format
شی بسیار به عنوان یک رشته عمل می کند. چیزی که وقتی متوجه ترتیب تفکیک روش می شوید چندان عجیب نیست Format
:
use v6.e.PREVIEW;
say Format.^mro; # ((Format) (Str) (Cool) (Any) (Mu))
فقط زمانی که به عنوان یک Callable
(با قرار دادن ()
پس از آن با آرگومان ها)، آیا عملکرد ویژه خود را نشان می دهد.
یک قید نقل قول جدید
در RCS پیشنهاد شد که Format.new("%5s")
در استفاده متداول بیش از حد بد خواهد بود. به طور جدی تر از ایجاد زمان کامپایل جلوگیری می کند Format
شی چون جستجوی متدها یک عمل زمان اجرا در Raku هستند (به طور کلی). راهی برای دور زدن آن، معرفی یک ساختار / قید / پردازنده جدید با نقل قول رشته است. این شد "format"
قید (یا "o"
برای نسخه کوتاه):
use v6.e.PREVIEW; # RAKUDO_RAKUAST=1 also required for now
my $format = q:format/%5s/;
say "'$format("foo")'"; # ' foo'
یا مستقیم تر و کوتاه تر با استفاده از قید جایگزین “o”:
use v6.e.PREVIEW;
dd q:o/%5s/("foo"); # " foo"
چرا "o"
برای نسخه کوتاه؟ زیرا "f"
قبلاً برای فعال/غیرفعال کردن درونیابی *f*function گرفته شده بود. و q:o
از نظر بصری نزدیکتر به fo
از هر چیز دیگری
کارایی
بنابراین عملکرد این روش جدید برای قالب بندی مقادیر به یک رشته چیست؟
بدون هیچ گونه بهینه سازی نسخه RakuAST، تا 30 برابر افزایش سرعت گزارش شده است. بنابراین این کاملاً یک پیشرفت است. و به طور بالقوه بهتر از بسیاری از زبان های برنامه نویسی دیگر که برای ایجاد رشته به نوعی از حالت زمان اجرا نیز وابسته هستند، نه اینکه به کدهای اجرایی وابسته باشند.
نتیجه
روشی جدید برای ایجاد رشته ها از مجموعه مقادیر معین و رشته قالب بندی (به عبارت دیگر printf
عملکرد) با استفاده از RakuAST در زبان برنامه نویسی Raku پیاده سازی شده است و آن را تا 30 برابر سریعتر می کند.
این قابلیت از نسخه 2023.06 راکودو و انتخاب آن در دسترس خواهد بود 6.e
سطح زبان با مشخص کردن use v6.e.PREVIEW
. قید نقل قول جدید در حال حاضر تنها زمانی در دسترس خواهد بود که با گرامر جدید RakuAST کامپایل شود، که می تواند با مشخص کردن RAKUDO_RAKUAST
متغیر محیطی.