تمامی فعالیت ها
این جریان به طور خودکار بروزرسانی می شود
- هفته گذشته
-
بررسی تغییرات و بهبودهای .NET 10
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیبا انتشار .NET 10 در نوامبر 2025 به عنوان نسخه LTS (پشتیبانی بلندمدت)، مایکروسافت بار دیگر تعهد خود را به بهبود عملکرد، امنیت و تجربه توسعهدهندگان نشان داد. این نسخه با مجموعهای از قابلیتهای جدید و بهینهسازیها، توسعه اپلیکیشنهای مدرن را سریعتر و کارآمدتر کرده است. در این مقاله، به بررسی تغییرات کلیدی در runtime، کتابخانهها، ابزارهای توسعه، ASP.NET Core و Entity Framework Core میپردازیم. اگر توسعهدهنده .NET هستید، این مقاله شما را با ویژگیهای جدید این نسخه آشنا خواهد کرد. لیست کلی تغییرات1. Runtime و SDK پایهبهبود عملکرد و کاهش مصرف حافظه در سناریوهای سنگین. ارتقای ابزار CLI با امکاناتی مانند --cli-schema و dotnet tool exec. پشتیبانی از Native AOT برای تولید برنامههای با سرعت بالا و مصرف پایین حافظه. 2. زبان C# 14افزودن قابلیتهای جدید مانند field-backed properties و extension blocks. بهبود دسترسی به پارامترهای generic و امکانات پیشرفتهتر برای لامبداها. پشتیبانی از ویژگیهای مدرن برای بهبود خوانایی و انعطافپذیری کد. 3. ASP.NET Core و Blazorبهبود مدیریت assetها و فشردهسازی خودکار در Blazor برای کاهش حجم دانلود. افزودن قابلیتهایی مانند RowClass در QuickGrid و حفظ موقعیت اسکرول هنگام استفاده از NavigateTo. پشتیبانی از passkeys برای احراز هویت بدون رمز عبور و امنیت بالاتر. ارتقای OpenAPI به نسخه 3.1 و امکانات پیشرفتهتر برای مستندسازی APIها. 4. Entity Framework Coreبهبود عملکرد queryها و پشتیبانی بهتر از پایگاه دادههای مدرن مانند Azure Cosmos DB. اضافه شدن قابلیت Vector similarity search و انعطاف بیشتر در طراحی queryها. 5. .NET MAUI و توسعه چندپلتفرمیبهبود کنترلهای رابط کاربری و تجربهٔ توسعه در اپلیکیشنهای موبایل و دسکتاپ. امکانات جدید برای telemetry، مدیریت پیکربندی و سازگاری بهتر با معماریهای cloud-native. 6. Windows Forms و WPFبهبود کیفیت کنترلهای UI و ویرایش نوع UITypeEditorها. اصلاح عملکرد clipboard و افزایش پایداری در پروژههای دسکتاپ. جزییات تغییرات:بهبودهای Runtime: عملکردی بهینهتر و هوشمندترRuntime در .NET 10 با تمرکز بر بهینهسازی اجرای کد، کاهش فشار روی Garbage Collector (GC) و پشتیبانی از سختافزارهای جدید، پیشرفتهای قابل توجهی داشته است. بهینهسازیهای JIT Compilerکامپایلر JIT در .NET 10 با تکنیکهایی نظیر devirtualization متدهای آرایه و بهبود loop inversion، عملکرد را بهبود بخشیده است. برای مثال، در حلقههای foreach روی آرایهها، JIT حالا میتواند virtual callها را حذف کرده و کد را inline کند، که منجر به عملکردی مشابه حلقههای for میشود. static int Sum(int[] array) { int sum = 0; IEnumerable<int> temp = array; // اکنون devirtualize میشود foreach (var num in temp) { sum += num; } return sum; }این کد در .NET 10 تا 20% سریعتر اجرا میشود. علاوه بر این، الگوریتم 3-opt برای بهینهسازی layout کد استفاده شده که مسیرهای پراستفاده (hot paths) را بهینهتر کنار هم قرار میدهد و فاصله branchها را کاهش میدهد. تخصیص حافظه روی Stackیکی از ویژگیهای برجسته، گسترش escape analysis برای تخصیص حافظه روی stack است. آرایههای کوچک از value typeها (مانند int[]) و حتی reference typeها (مانند string[]) در صورت محدود بودن scope، روی stack تخصیص مییابند. این قابلیت فشار روی GC را تا 15-20% کاهش میدهد. static void Sum() { int[] numbers = { 1, 2, 3 }; // تخصیص روی stack int sum = 0; for (int i = 0; i < numbers.Length; i++) { sum += numbers[i]; } Console.WriteLine(sum); // خروجی: 6 }پشتیبانی از AVX10.2 و Arm64.NET 10 از دستورات AVX10.2 در معماری x64 پشتیبانی میکند (هرچند فعلاً غیرفعال است تا سختافزارهای جدید عرضه شوند). همچنین، بهینهسازی write-barrier در Arm64 عملکرد GC را تا 8-20% بهبود داده که برای اپلیکیشنهای موبایل و edge computing بسیار مفید است. کتابخانهها: APIهای مدرن و امنکتابخانههای استاندارد .NET 10 با APIهای جدید در حوزههای امنیت، پردازش رشتهها و سریالسازی، توسعهدهندگان را مجهزتر کردهاند. رمزنگاری پساکوانتومیپشتیبانی از الگوریتمهای post-quantum cryptography (PQC) مانند ML-KEM، ML-DSA و SLH-DSA اضافه شده است. این الگوریتمها با استفاده از ویژگی IsSupported قابل بررسی هستند. X509Certificate2Collection coll = store.Certificates.FindByThumbprint(HashAlgorithmName.SHA256, thumbprint); var cert = coll.SingleOrDefault(); // استفاده از SHA-256 برای امنیت بالاترGlobalization و پردازش رشتههاکلاس ISOWeek حالا با DateOnly سازگار است و عملیات string normalization با spans انجام میشود تا تخصیص حافظه کاهش یابد. همچنین، NumericOrdering در CompareOptions برای مقایسه عددی رشتهها اضافه شده است. سریالسازی و CollectionsOrderedDictionary<TKey, TValue> با متدهای TryAdd و TryGetValue بهبود یافته و برای JsonObject تا 20% سریعتر است. در سریالسازی JSON، قابلیت ReferenceHandler برای مدیریت cycleها و preset Strict برای رعایت بهترین استانداردها اضافه شده است. [JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)] [JsonSerializable(typeof(SelfReference))] internal partial class ContextWithPreserveReference : JsonSerializerContext { }ZIP و WebSocketZipArchive حالا از APIهای async پشتیبانی میکند و فرآیند extraction به صورت موازی انجام میشود. همچنین، WebSocketStream abstraction جدیدی برای WebSocketهای مبتنی بر stream ارائه میدهد. ابزارهای توسعه: سادهسازی فرآیندهاSDK در .NET 10 روی سادهسازی توسعه و پشتیبانی از پلتفرمهای مختلف تمرکز دارد. حذف خودکار پکیجهای بلااستفاده: قابلیت pruning package references به طور پیشفرض فعال است و زمان بیلد را کاهش میدهد. اجرای ابزارها بدون نصب: با dotnet tool exec میتوانید ابزارها را بدون نصب دائم اجرا کنید. انتشار به AOT: امکان انتشار اپلیکیشنها به صورت native AOT با دستور dotnet publish app.cs. ایمیجهای کانتینری: دستور dotnet publish /t:PublishContainer برای انتشار مستقیم به container. همچنین، پشتیبانی از tab-completion در shellهایی مانند bash و zsh اضافه شده است. ASP.NET Core 10: وب سریعتر و امنترASP.NET Core 10 با بهبودهایی در Blazor، امنیت و Minimal APIs، توسعه وب را به سطح جدیدی برده است. Blazor: رابط کاربری پویاترحالت پایدار (Persistent State): با [PersistentState]، وضعیت کامپوننتها در prerendering حفظ میشود. [PersistentState] public List<Movie>? MoviesList { get; set; } protected override async Task OnInitializedAsync() { MoviesList ??= await MovieService.GetMoviesAsync(); }QuickGrid: قابلیتهایی مانند RowClass برای استایلدهی و HideColumnOptionsAsync برای بهبود UI. Response Streaming: به طور پیشفرض برای HttpClient فعال است. JavaScript Interop: متدهای جدید مانند InvokeConstructorAsync. امنیت و احراز هویتپشتیبانی از passkey authentication با WebAuthn و FIDO2 برای احراز هویت بدون رمزعبور. همچنین، RedirectHttpResult.IsLocalUrl برای جلوگیری از حملات open redirect. Minimal APIsبهبودهایی در query compiler برای LINQ و پشتیبانی از OpenAPI 3.1. Entity Framework Core 10: دیتابیس و AIEF Core 10 با قابلیتهای جدید برای AI و دیتابیسهای مدرن طراحی شده است. جستجوی وکتوری و JSONپشتیبانی از vector data type در SQL Server 2025 و Azure SQL برای جستجوی معنایی و RAG. public class Blog { [Column(TypeName = "vector(1536)")] public SqlVector<float> Embedding { get; set; } } // جستجو: var topSimilar = context.Blogs .OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, sqlVector)) .Take(3).ToListAsync();JSON type نیز به صورت native پشتیبانی میشود. Cosmos DBپشتیبانی از full-text search با EF.Functions.FullTextContains و RRF برای جستجوی هیبریدی. LINQ و عملیات Bulkبهبود translation برای joinها و سادهسازی bulk updates. چالشها و نکات مهم برای مهاجرتسازگاری با پروژههای قدیمی: برخی APIها تغییر کرده یا deprecated شدهاند و بررسی دقیق لازم است. بازنویسی بخشی از کد: استفاده از قابلیتهای جدید Blazor و C# ممکن است نیازمند تغییر در کد باشد. یادگیری تیم توسعهدهنده: آشنایی با امکانات C# 14 و ویژگیهای جدید Blazor و MAUI ضروری است. پایش و تست پس از ارتقا: مانیتورینگ و تست جامع برای اطمینان از عملکرد صحیح پروژه ضروری است. نتیجهگیری.NET 10 با تمرکز بر عملکرد، امنیت و تجربه توسعهدهنده، ابزار قدرتمندی برای ساخت اپلیکیشنهای مدرن ارائه میدهد. اگر از نسخههای قبلی مهاجرت میکنید، مستندات مایکروسافت را بررسی کنید تا با تغییرات breaking آشنا شوید. پیشنهاد میکنیم با یک پروژه Blazor یا قابلیتهای vector search شروع کنید تا قدرت این نسخه را تجربه کنید.
-
سی شارپ 14:ویژگیهای جدید و کاربردی برای توسعهدهندگان
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیدر دنیای سریعالسیر برنامهنویسی، زبان C# همیشه یکی از پیشتازان بوده است. مایکروسافت هر سال با معرفی نسخههای جدید، ابزارهایی تازه برای سادهسازی کد، افزایش کارایی و بهبود ایمنی ارائه میدهد. حالا که به سال ۲۰۲۵ رسیدهایم، C# 14 – که بصورت preview همراه با .NET 10 معرفی شده و بصورت رسمی در نوامبر ۲۰۲۵ منتشر میشود – وعده تغییرات جذابی را میدهد. این نسخه نه تنها بر پایه تجربیات نسخههای قبلی مثل C# 13 ساخته شده، بلکه تمرکز ویژهای روی کاهش boilerplate code، بهبود عملکرد و انعطافپذیری بیشتر در نوشتن کدهای مدرن دارد. اگر توسعهدهندهای هستید که با ASP.NET، Unity یا حتی اپلیکیشنهای دسکتاپ کار میکنید، ویژگیهای جدید C# 14 میتواند workflow شما را دگرگون کند. در این مقاله، به بررسی دقیق تغییرات C# 14 میپردازیم: از extension members گرفته تا بهبودهای lambda و span. هدف این است که نه تنها لیست ویژگیها را مرور کنیم، بلکه با مثالهای عملی و توضیحات گامبهگام، بفهمیم چطور از آنها در پروژههای واقعی استفاده کنیم. آمادهاید؟ بیایید شروع کنیم. چرا C# 14 مهم است؟ نگاهی به زمینه انتشارقبل از غوطهور شدن در جزئیات، بیایید کمی عقب برویم. C# از زمان معرفی در سال ۲۰۰۰، همیشه با .NET همگام بوده. نسخه ۱۳ در ۲۰۲۴، ویژگیهایی مثل primary constructors و collection expressions را آورد، اما C# 14 یک قدم جلوتر میرود. طبق اعلام مایکروسافت، این نسخه در نوامبر ۲۰۲۵ به عنوان بخشی از .NET 10 (که یک LTS یا Long-Term Support است) عرضه میشود. این یعنی پشتیبانی طولانیمدت تا سال ۲۰۲۸، که برای پروژههای enterprise ایدهآل است. تغییرات C# 14 عمدتاً بر سه اصل تمرکز دارند: سادگی syntax، بهبود عملکرد و ایمنی بیشتر. مثلاً، اگر قبلاً با extension methods کلنجار میرفتید، حالا همه چیز طبیعیتر شده. این تغییرات نه تنها برای تازهکاران مفیدند، بلکه برای veteran developerها هم ابزارهای جدیدی برای refactoring کدهای قدیمی فراهم میکنند. در ادامه، هر ویژگی را با مثال کد بررسی میکنیم – همه کدهای ارائهشده در Visual Studio 2022 (نسخه ۱۷.۱۲ به بعد) یا .NET 10 SDK قابل تست هستند. Extension Members: گسترش کلاسها بدون دردسریکی از ستارههای C# 14 new features، معرفی extension members است. قبلاً، extension methods فقط برای متدهای static محدود بودند، اما حالا میتوانید extension properties، operators و حتی static members تعریف کنید. این ویژگی مثل این است که بگویید: "هی، این کلاس را بدون تغییر منبع اصلی، غنیتر کن." syntax جدید و مثال عملیفرض کنید با IEnumerable<T> کار میکنید و میخواهید یک property ساده مثل IsEmpty اضافه کنید. در C# 14، از بلوک extension استفاده میکنید: public static class EnumerableExtensions { extension<TSource>(IEnumerable<TSource> source) { public bool IsEmpty => !source.Any(); // Property extension } }حالا، در کد اصلیتان: var sequence = new List<int> { 1, 2, 3 }; Console.WriteLine(sequence.IsEmpty); // خروجی: Falseاینجا، IsEmpty مثل یک عضو واقعی کلاس عمل میکند – نه مثل یک متد static که باید با نام کلاس فراخوانی شود. برای static extension members هم همینطور: extension<TSource>(IEnumerable<TSource>) { public static IEnumerable<TSource> Identity => Enumerable.Empty<TSource>(); public static IEnumerable<TSource> operator +(IEnumerable<TSource> left, IEnumerable<TSource> right) => left.Concat(right); }استفاده: var emptyList = IEnumerable<int>.Identity; var combined = list1 + list2; // Operator overloading به سبک extensionمزایا و نکات پیادهسازیاین ویژگی boilerplate را کاهش میدهد و کد را خواناتر میکند. مثلاً در پروژههای بزرگ، جایی که LINQ extensions زیاد دارید، این کار refactoring را آسانتر میکند. فقط یادتان باشد، extension blocks باید static باشند و receiver (پارامتر اول) با this implicit کار کند. اگر از Unity استفاده میکنید، تصور کنید چطور میتوانید به GameObjectها extension property برای health اضافه کنید – بدون نیاز به inheritance پیچیده. طبق spec مایکروسافت، این ویژگی از زبان reference کامل پشتیبانی میکند و هیچ deprecation ای ندارد. کلمه کلیدی field: خداحافظی با backing fields دستیاگر از نوشتن private fields خسته شدهاید، field keyword در C# 14 نجاتدهنده شماست. این کلمه کلیدی اجازه میدهد accessorهای property بدون تعریف explicit backing field بنویسید – کامپایلر خودش یکی synthesize میکند. قبل و بعد: مقایسه syntaxدر نسخههای قبلی: private string _message; public string Message { get => _message; set => _message = value ?? throw new ArgumentNullException(nameof(value)); }در C# 14: public string Message { get; set => field = value ?? throw new ArgumentNullException(nameof(value)); }ساده، نه؟ field مستقیماً به backing field اشاره میکند. میتوانید فقط برای get یا set body بنویسید، و کامپایلر بقیه را هندل میکند. سناریوهای واقعی و هشدارهاتصور کنید در یک کلاس User Profile، چندین property validation-heavy دارید. این ویژگی زمان توسعه را نصف میکند. اما یک نکته: اگر در scopeتان متغیری به نام field دارید، از @field یا this.field استفاده کنید تا conflict پیش نیاید. این ویژگی preview در C# 13 بود و حالا stable است – عالی برای migration کدهای legacy. در عمل، تست کنید: یک console app بسازید و ببینید چطور IntelliSense field را پیشنهاد میدهد. این تغییر کوچک، اما تأثیر بزرگی روی productivity دارد. Implicit Span Conversions: عملکرد بالا بدون زحمتSpan<t></t> و ReadOnlySpan<t></t> از C# 7.2 آمدند، اما C# 14 آنها را first-class میکند. حالا implicit conversions بیشتری دارید، که کد را طبیعیتر و performantتر میکند – بدون allocation اضافی روی heap. مثالهای کلیدیمثلاً، string literals حالا مستقیم به Span تبدیل میشوند: ReadOnlySpan<char> span = "Hello, World!"; // Implicit! foreach (char c in span) { Console.Write(c); // بدون copy }یا در generic methods: public static int SumDigits(ReadOnlySpan<int> numbers) => numbers.Sum(); var result = SumDigits([1, 2, 3, 4]); // Array به Span implicitچرا این ویژگی game-changer است؟در اپهای high-throughput مثل web servers، Spanها garbage collection را کم میکنند. طبق benchmarks مایکروسافت، این conversions تا ۲۰% بهبود در I/O-bound tasks میدهند. اگر با System.IO کار میکنید، این را از دست ندهید – مثلاً parsing فایلهای بزرگ بدون bufferهای دستی. هیچ deprecation ای نیست، اما مطمئن شوید target framework .NET 10 است. Unbound Generic Types در nameof: انعطاف بیشتر در reflectionیک تغییر کوچک اما مفید: nameof حالا unbound generics را پشتیبانی میکند. قبلاً فقط closed types مثل List<int> کار میکرد، اما حالا List<> هم ok است. syntax و استفادهstring typeName = nameof(List<>); // خروجی: "List" Console.WriteLine(typeName);کاربردهادر serialization یا logging، جایی که نام type بدون type arguments نیاز دارید، این عالی است. مثلاً در یک logger generic: public void Log<T>(T item) => Console.WriteLine($"Logging {nameof(T)}: {item}");این تغییر reflection را سادهتر میکند و کد را future-proof نگه میدارد. Simple Lambda Parameters: modifiers بدون type hassleLambdas در C# همیشه قدرتمند بودند، اما حالا parameters بدون explicit type و با modifiers مثل out یا ref کار میکنند. مثال قبل و بعدقبلاً: Func<string, out int, bool> parse = (text, out int result) => int.TryParse(text, out result);حالا: Func<string, out int, bool> parse = (text, out result) => int.TryParse(text, out result);فواید در LINQ و asyncدر LINQ queries یا async lambdas، این syntax کوتاهتر است. فقط params هنوز type میخواهد. این ویژگی code golf را بدون از دست دادن readability ممکن میکند. Partial Members بیشتر: constructors و events partialC# 9 partial methods را آورد، اما C# 14 constructors و events را هم partial میکند. یعنی defining declaration در یک فایل، implementing در دیگری. برای constructors// File1.cs partial class MyClass(int x) { // Primary constructor partial } // File2.cs partial class MyClass { partial int x; // Implementing partial MyClass(int x) { this.x = x > 0 ? x : throw new ArgumentException(); // Initializer فقط در implementing } }برای eventsDefining: partial event EventHandler MyEvent;Implementing: partial event EventHandler MyEvent { add { /* logic */ } remove { /* logic */ } }سناریوهای team developmentدر تیمهای بزرگ، این برای code generation یا generated files عالی است – مثلاً در Blazor components. User-Defined Compound Assignment: operators سفارشی برای += و غیرهآخرین ویژگی: حالا میتوانید compound assignments مثل += را user-defined کنید، با operator overloading. مثالpublic static class VectorExtensions { public static Vector operator +(Vector left, Vector right) => new(left.X + right.X, left.Y + right.Y); // Compound public static Vector operator +(Vector left, double scalar) => new(left.X + scalar, left.Y + scalar); } // استفاده Vector v = new(1, 2); v += 3; // Implicit به + با scalarاین برای math libraries یا game physics فوقالعاده است. نتیجهگیری: قدم بعدی برای C# developersC# 14 با این تغییرات، زبان را به سطح جدیدی میبرد – سادهتر، سریعتر،از extension members برای غنیسازی APIs گرفته تا Span conversions برای performance، هر ویژگیای داستانی برای گفتن دارد. اگر تازهکارید، از Visual Studio Insiders شروع کنید؛ اگر pro هستید، پروژههایتان را migrate کنید و benchmarks بگیرید. آینده؟ C# 15 احتمالاً روی AI integrations تمرکز دارد، اما فعلاً، C# 14 را امتحان کنید. منابع: docs.microsoft.com
-
ویژوال استودیو 2026: نسلی جدید از توسعه نرمافزار با قلب هوش مصنوعی
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیپس از چهار سال انتظار، مایکروسافت بالاخره ویژوال استودیو 2026 را معرفی کرد و این بار خبری از یک بهروزرسانی معمولی نیست. این IDE جدید وعده میدهد که تجربه توسعه نرمافزار را به شکل واقعیای متحول کند. ادغام کامل با هوش مصنوعییکی از برجستهترین تغییرات ویژوال استودیو 2026، ادغام عمیق هوش مصنوعی در فرآیند توسعه است. برخلاف نسخههای قبلی که GitHub Copilot بیشتر یک افزونه جانبی بود، حالا AI به صورت یکپارچه در pipeline توسعه جای گرفته و با استفاده از مدلهای پیشرفته زبان طبیعی و تحلیل کد، به توسعهدهنده کمک میکند. این سیستم شامل یک Language Server Protocol (LSP) بهبود یافته است که قادر به درک context کامل پروژه و تحلیل real-time dependency هاست. با بهرهگیری از الگوریتمهای machine learning، الگوهای کدنویسی پروژهها را یاد میگیرد و پیشنهادات خود را شخصیسازی میکند. وقتی روی پروژههای جدید کار میکنید، محیط توسعه به صورت هوشمند شما را در درک ساختار و عملکرد کد همراهی میکند. همچنین میتواند تستهای مناسب را بر اساس الگوهای موجود در مخزن کد پیشنهاد دهد و مستندات و توضیحات را همزمان با تغییرات کد بهروزرسانی کند. ویژگی «Adaptive Paste» هم قابل توجه است. این سیستم با استفاده از AST parsing و الگوریتمهای pattern matching، قطعات کد کپیشده را تحلیل کرده و مطابق با code style guides، naming conventions و الگوهای معماری پروژه، تغییرات لازم را اعمال میکند. Semantic Code Analysis و IntelliSense نسل جدیدیکی دیگر از نقاط قوت این نسخه، ارتقای چشمگیر موتور IntelliSense است. با استفاده از نسخه بهینهشده Roslyn Compiler Platform، این موتور قادر به تحلیل semantic عمیقتر کد و ارائه پیشنهادات context-aware است. همچنین پشتیبانی از cross-project type inference برای پروژههای multi-solution اضافه شده که کار توسعهدهندگان را بسیار آسان میکند. بهبود چشمگیر کارایی و سرعتیکی از چالشهای همیشگی IDEها، کارایی و سرعت در پروژههای بزرگ است. مایکروسافت میگوید ویژوال استودیو 2026 در این زمینه پیشرفت قابل توجهی داشته است. فرآیندهای اصلی توسعه شامل بارگذاری solutionها، جستجو و ناوبری در کد، عملیات Build و اجرای برنامهها به شکل محسوسی سریعتر شدهاند. این بهبودها برای هر دو معماری x64 و Arm64 در دسترس است. بازخوردهای اولیه کاربران نشان میدهد که سرعت عملکرد در تمامی پروژهها به شکل قابل توجهی افزایش یافته و تمرکز تیم توسعه روی مسائل عملکردی واقعی بوده است. طراحی مدرن و رابط کاربری جدید ویژوال استودیو 2026 از Fluent Design System بهره میبرد و محیط کاری متمرکزتر و آرامتری ایجاد کرده است. خطوط واضحتر، آیکنهای بهینهشده و فاصلهگذاری مناسب بین عناصر، باعث شده محیط کاری کمتر شلوغ و گیجکننده به نظر برسد. پنل تنظیمات هم بازطراحی شده تا فرآیند شخصیسازی محیط توسعه سادهتر و دسترسپذیرتر شود. علاوه بر این، 11 طرح رنگی جدید اضافه شده که نه تنها ظاهر جذابی دارند، بلکه استانداردهای دسترسیپذیری را نیز رعایت میکنند. ابزارهای جدید برای تحلیل عملکردProfiler Agent یکی از ابزارهای جدید و کاربردی است که میتواند مشکلات عملکردی را شناسایی کرده و حتی پیشنهادهایی برای بهبود ارائه دهد. این ابزار به خصوص برای توسعهدهندگان بازی یا اپلیکیشنهایی که نیاز به عملکرد بالا دارند، بسیار مفید است. با این سیستم، دیگر نیازی به حدس زدن هنگام مواجهه با مشکلات عملکرد نیست؛ راهنماییها بر اساس traceهای واقعی و benchmarkها ارائه میشوند، بنابراین تغییرات با اطمینان بیشتری اعمال میشوند. بررسی هوشمند کد قبل از Pull Requestویژگی دیگر، تحلیل کد قبل از ارسال pull request است. این سیستم نکات قابل اجرا و عملی درباره صحت، عملکرد و امنیت کد ارائه میدهد و همه تحلیلها روی دستگاه محلی توسعهدهنده انجام میشود. این قابلیت باعث کاهش زمان بررسیهای متعدد و افزایش کیفیت نهایی محصول میشود. کانال Insiders و نگاه به آیندهمایکروسافت برای اولین بار کانال Preview را با Insiders جایگزین کرده و قصد دارد بهروزرسانیهای ماهانه ارائه دهد. این بروزرسانیها شامل بهبود عملکرد، اصلاح طراحی و نوآوریهای هوش مصنوعی هستند و دیگر لازم نیست سالها منتظر نسخه جدید بمانید. نصب همزمان و سازگاریویژوال استودیو 2026 میتواند کنار نسخههای قبلی نصب شود و کاربران میتوانند componentها و تنظیمات قبلی را وارد کرده و بلافاصله کدنویسی را شروع کنند. جمعبندیپس از پنج سال از آخرین نسخه major، ویژوال استودیو 2026 نشان میدهد که مایکروسافت روی نیازهای واقعی کاربران تمرکز کرده است. ادغام عمیق هوش مصنوعی، بهبود عملکرد و طراحی مدرن همه در جهت یک هدف ساده اما قدرتمند هستند: کاهش زمان صرفشده برای مقابله با ابزار و تمرکز بیشتر روی حل مسائل واقعی توسعه. البته هنوز زود است که قضاوت قطعی کرد؛ نسخه Insider در دسترس است و طی هفتههای آینده جزئیات بیشتری منتشر خواهد شد. اما نگاه اولیه نوید یک تحول واقعی در دنیای IDEها را میدهد.
-
فایل llms.txt چیست و چرا مهم است؟
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیدر دنیای وب و هوش مصنوعی، وقتی مدلهای زبانی عظیم (Large Language Models یا به اختصار LLM) میخواهند مطلبی را از یک وبسایت بخوانند، معمولاً به مشکل میخورند: صفحات وب پر از المانهایی هستند که برای انسان مفیدند ولی برای مدلهای زبانی مزاحمت ایجاد میکنند — مانند تبلیغات، منوهای ناوبری پیچیده، اسکریپتها، CSSهای زیاد، و جاوااسکریپتهایی که محتوا را بهصورت دینامیک بارگذاری میکنند. اینها حجم محتوا را زیاد میکنند و باعث میشوند مدلها زمان یا حافظه زیادی صرف خواندن چیزهایی کنند که اغلب الزامی نیست. اینجا دقیقاً جایی است که llms.txt کاربردی میشود: یک فایل متن ساده به فرمت Markdown که وبسایتها میتوانند در ریشه (root) دامنهشان قرار دهند تا به مدلهای زبان کمک کنند سریعتر و بهینهتر بخشهای مهم سایت را بشناسند، بدون اینکه نیاز باشد کل HTML پیچیده و ناپایدار را تفسیر کنند. ساختار استاندارد llms.txtبر اساس پیشنهاد اصلی و مقالات متعدد: نام پروژه یا وبسایت — یک هِدِر سطح اول Markdown (# ProjectName). مثال: # MyAwesomeWebsite خلاصه کوتاه / توضیح بلاککووت — یک قطعه توضیحی در قالب Markdown که هدف وبسایت، کاربرانش، یا محتوای اصلی را بیان میکند. معمولاً بین ۱ تا چند جمله. بخشهای مهم (Sections) — با هِدِرهای سطح دوم (##) که لینکهایی به صفحات مهم سایت با توضیح مختصر زیرشان دارند. مثلاً ## Documentation - [Getting Started](https://example.com/docs/getting-started): how to install and begin - [API Reference](https://example.com/docs/api): endpoints and parameters ## Blog - [Latest Articles](https://example.com/blog): اخبار و مقالات جدید بخشهای اختیاری (Optional) — مواردی که مهماند ولی نه برای هرکاربر یا برای مدلها اولویت اول را دارند؛ مثل صفحه تماس، فرصتهای شغلی، منابع جانبی. نسخه کامل / llms-full.txt — بعضی سایتها علاوه بر این فایل خلاصه، یک فایل کاملتر دارند به نام llms-full.txt که کل محتوای مستنداتی یا داکیومنتها را به Markdown آوردهاند. این نسخه برای مواقع نیاز به بافت کامل مطالب مفید است، ولی برای مدلهای زبانی که پنجرهی زمینهای (context window) محدود دارند باید به دقت استفاده شود. تفاوت llms.txt با فایلهای دیگر مثل robots.txt یا sitemap.xmlبرای سئوی وبلاگ و فهم بهتر: فایل هدف اصلی خواننده / مخاطب هدف فرمت معمول robots.txt کنترل دسترسی رباتها به بخشهای سایت (چه چیزی ایندکس شود یا نشود) موتورهای جستجو مانند Googlebot و سایر کراولرها متن ساده با فرمت مخصوص (disallow, allow…) sitemap.xml فهرست کامل یا تقریباً کامل صفحات سایت برای کمک به کراولرها برای ایندکسینگ بهتر موتورهای جستجو XML llms.txt راهنمایی مدلهای زبان بزرگ برای فهم سریع ساختار و محتوای مهم سایت، کاهش نویز و پیچیدگی LLMها، ابزارهای هوش مصنوعی، جوابدهندههای خودکار Markdown ساده با لینکها و توضیح مختصر چون llms.txt مخصوصِ کمک به مدلهای هوش مصنوعی طراحی شده، باید محتوای مهم را واضح و مختصر معرفی کند و از المانهای زائد کم کند. مزایا و چالشهامزایابهبود دیدهشدن در نتایج AI: وقتی مدلها بفهمند کدام بخشها برای پرسشهایتان مهماند، احتمال اینکه در پاسخها نشان داده شوید زیادتر میشود. سرعت بخشی به فرایند پاسخدهی AI: خواندن محتوای مهم بهصورت مستقیم و بدون سرگردانی در المانهای غیرضروری. کنترل بیشتر بر محتوای سایت: شما تعیین میکنید چه بخشهایی باید در معرض دید AI باشند. سازگاری بیشتر با آینده: چون استفاده از مدلهای زبانی و جستجوی هوشمند روز به روز افزایش مییابد، داشتن چنین ساختاری، وبسایت را آمادهتر میکند. چالشها و محدودیتهاپذیرش در میان مدلها / سرویسها: هنوز همهی پلتفرمها تضمین نکردهاند که llms.txt را جدی بگیرند یا بخوانند. بهروزرسانی مستمر لازم است: اگر مطالب سایت تغییر کند و فایل llms.txt بهروز نشود، ممکن است لینکها یا توضیحات قدیمی در آن بمانند. محدودیت اندازه کاملترین نسخهها: فایلهایی مثل llms-full.txt ممکن است خیلی بزرگ شوند و برای مدلهایی با پنجره زمینهای (context window) محدود قابل پردازش نباشند. خطر افشای محتوا یا تحلیل رقابتی: وقتی کل محتوای مهم سایت به سادگی قابل دسترس باشد، ممکن است رقبا بتوانند راحتتر آن را تحلیل کنند. این هم نکتهای است که باید در نظر گرفت. چگونه llms.txt را بسازی و پیادهسازی کنییه روند عملی و قدمبهقدم: لیست بخشهای مهم سایتت را مشخص کن ابتدا بررسی کنید کدام صفحات واقعاً برای کاربر یا برای سؤالاتی که مدلهای هوش مصنوعی ممکن است مطرح کنند، بسیار مهماند: مستندات، مقالات کلیدی، بخش آموزش، محصولات اصلی، درباره ما، تماس، سیاست حفظ حریم خصوصی و … نوشتن فایل به فرمت Markdown استاندارد رعایت ساختار: یک هِدِر اصلی (#) بلاککووت با خلاصهای که سایت چیست، هدف آن چیست بخشها (##) و لینکها همراه با توضیح کوتاه بخش اختیاری در انتها قرار دادن فایل در ریشه دامنه فایل را با نام llms.txt در ریشه سایت (مثلاً https://domain.com/llms.txt) آپلود کنید تا قابل دسترسی عمومی باشد. آزمایش و تأیید مطمئن شوید فایل بهصورت ساده قابل دانلود است، بدون HTML اضافی یا رندر واسطهای. تست کنید لینکها درست کار میکنند و توضیحات معنادارند. بهروزرسانی منظم وقتی محتوای سایت تغییر کرد، صفحات جدید اضافه شد یا بخشهایی حذف شدند، فایل llms.txt را نیز بهروزرسانی کنید. در صورت نیاز، نسخه کامل (llms-full.txt) را بساز اگر سایت مستندات زیاد دارد یا محتوا برای کاربران حرفهای یا توسعهدهنده مهم است، نسخه کاملتر ممکن است مفید باشد، اما مراقب حجم و اندازهش باشید. نکات کاربردی برای بهبود سئو و افزایش خوانایی انسانیتا این مرحله تمرکز اصلی بر نقش llms.txt در تعامل با مدلهای زبانی بود. با این حال، برای آنکه محتوای وبسایت از نظر سئو نیز جایگاه مناسبی پیدا کند و در عین حال برای خوانندگان انسانی نیز قابل استفاده و ارزشمند باشد، رعایت نکات زیر توصیه میشود: استفاده از کلمات کلیدی مرتبط مانند “llms.txt”، “فایل ai-friendly”، “راهنمای هوش مصنوعی برای سایت”، “Markdown llms.txt” و “AI discovery file” در عناوین اصلی و فرعی به افزایش شانس دیدهشدن در نتایج جستجو کمک میکند. بهکارگیری لینکهای داخلی به مقالات یا آموزشهای مرتبط (بهویژه اگر پیشتر مطالبی درباره SEO یا هوش مصنوعی منتشر کردهاید) موجب بهبود ساختار سایت و افزایش زمان حضور کاربر میشود. ارائه نمونههای عملی و قابل درک بسیار مؤثر است. برای مثال میتوان وبسایتی فرضی با بخشهای مستندات، وبلاگ و محصولات را در نظر گرفت و توضیح داد که چگونه این بخشها در فایل llms.txt معرفی میشوند. بیان تأثیر llms.txt بر تجربه انسانی نیز اهمیت دارد؛ چراکه این فایل تنها برای بهینهسازی تعامل با هوش مصنوعی نیست، بلکه میتواند به بهبود اعتماد مخاطب، ارتقای برندینگ و افزایش کارایی در دسترسی به محتوا نیز منجر شود. در صورت امکان، استفاده از نمایههای بصری یا اسکرینشات از فایل llms.txt واقعی، به خوانندگان کمک میکند درک دقیقتر و ملموستری از ساختار این فایل داشته باشند. منابع (References)llmstxt.org – Official Proposal for llms.txt Search Engine Land – “LLMs.txt proposed as new standard for guiding AI crawlers” Mintlify Blog – “How to generate llms.txt file automatically” LangChain Documentation – “LLMs.txt Overview” Medium – “LLMs.txt explained” Bluehost Blog – “What is llms.txt?”
- جدیدا
-
سیستم مدیریت حافظه در ویندوز 11؛ نگاهی به گذشته و مقایسه با نسخههای قبلی
sina پاسخی ارسال کرد برای یک مطلب در سیستم عامل و زیر ساختاگر تجربهی کار با چند نسل از ویندوز را داشته باشید، احتمالاً متوجه شدهاید که یکی از چالشهای همیشگی کاربران، مصرف حافظه (RAM) بوده است. از ویندوز XP که روی سیستمهایی با ۵۱۲ مگابایت رم اجرا میشد گرفته تا ویندوز ۱۱ که عادیترین لپتاپها هم حداقل ۸ گیگابایت رم دارند، همیشه این سؤال مطرح بوده: چرا ویندوز اینقدر رم میخورد و آیا واقعاً بهینه است؟ پاسخ کوتاه این است که مدیریت حافظه در ویندوز طی این سالها مدام تغییر کرده و پیچیدهتر شده است. اما جواب کامل نیاز به یک بررسی تاریخی دارد؛ اینکه ویندوز ۱۱ چه تفاوتهایی با ویندوز ۷، ۸ و ۱۰ دارد و اصلاً چرا رویکرد مایکروسافت نسبت به حافظهی رم تغییر کرده است. نگاهی کوتاه به مفاهیم پایهقبل از اینکه مستقیم سراغ نسخهها برویم، باید چند مفهوم کلیدی را مرور کنیم: Virtual Memory (حافظهی مجازی): ویندوز همیشه ترکیبی از رم و دیسک سخت (pagefile) را برای اجرای برنامهها به کار میگیرد. وقتی رم پر شود، دادهها به دیسک منتقل میشوند. Memory Compression: قابلیتی که دادههای بلااستفاده یا کممصرف را فشرده میکند تا فضای بیشتری در رم آزاد شود. Prefetch & Superfetch (یا SysMain): مکانیزمی که رفتار کاربر را یاد میگیرد و برنامههای پرمصرف را از قبل در رم بارگذاری میکند تا اجرای آنها سریعتر باشد. Memory Prioritization: تعیین اینکه کدام پردازهها (processes) دسترسی سریعتر به رم داشته باشند. این مفاهیم تقریباً در همه نسخههای اخیر ویندوز وجود دارند، اما نحوهی پیادهسازی و شدت استفاده از آنها در هر نسل متفاوت بوده است. ویندوز XP و ویستا: دوران ابتدایی مدیریت حافظه مدرنویندوز XP در سال ۲۰۰۱ عرضه شد؛ زمانی که اکثر سیستمها رم بسیار محدودی داشتند. مدیریت حافظه در این نسخه سادهتر بود. تمرکز اصلی روی Pagefile بود و اگر رم پر میشد، سیستم بهشدت کند میشد. ویندوز ویستا (۲۰۰۷) اولین جایی بود که مایکروسافت به صورت جدی Superfetch را معرفی کرد. ایده این بود که سیستم عادتهای شما را یاد بگیرد و اپلیکیشنهایی مثل مرورگر یا آفیس را از قبل در حافظه نگه دارد. البته ویستا بهخاطر مصرف رم بالا بدنام شد و همین باعث شد خیلیها به سرعت به ویندوز ۷ مهاجرت کنند. ویندوز 7: نقطهی تعادلویندوز ۷ در سال ۲۰۰۹ آمد و برای خیلیها بهترین نسخهی تاریخ ویندوز شد. دلیلش هم یک مدیریت حافظهی متعادل بود. Superfetch بهینهتر شد، مصرف Pagefile کمتر شد و سیستم میتوانست با رمهای ۲ یا ۴ گیگابایتی روان کار کند. نکتهی مهم این بود که ویندوز ۷ مصرف رم را بهعنوان استفادهی مفید نشان میداد؛ یعنی حتی اگر ۱ گیگ رم پر بود، لزوماً به معنای کندی نبود، بلکه نشاندهندهی caching سیستم بود. این همان چیزی است که هنوز هم خیلیها درک درستی از آن ندارند و فکر میکنند "چرا ویندوز رم زیادی میخورد". ویندوز 8 و 8.1: شروع تغییرات جدیویندوز ۸ در سال ۲۰۱۲ ویژگی جدیدی به اسم Memory Compression معرفی کرد. این یعنی بهجای اینکه دادهها مستقیماً به دیسک منتقل شوند، اول در رم فشرده میشدند. نتیجه این بود که سیستم سریعتر باقی میماند چون دسترسی به رم—همیشه فشردهشده—خیلی سریعتر از دیسک است. همچنین مایکروسافت در ویندوز ۸ مکانیزم Memory Prioritization را جدیتر گرفت. به این صورت که اپلیکیشنهای Modern UI (همان مترو) میتوانستند در پسزمینه “Suspend” شوند و رم آزاد شود. این ایده بعدها پایهی مدیریت حافظه در ویندوز ۱۰ و ۱۱ شد. ویندوز 10: یادگیری از رفتار کاربرویندوز ۱۰ (۲۰۱۵) مدیریت حافظه را یک پله جلوتر برد. در این نسخه: Memory Compression بهصورت پیشفرض فعال بود. سیستم میتوانست براساس اولویت اپلیکیشنها، رم را بین foreground و background تقسیم کند. مکانیزمهای Containerization (بهویژه برای اپلیکیشنهای UWP) باعث شد هر برنامه در یک فضای ایزوله رم اجرا شود. این تغییرات باعث شدند ویندوز ۱۰ نسبت به نسخههای قبل بهینهتر باشد، اما کاربران هنوز از مصرف زیاد رم (مثلاً توسط کروم یا سیستم) گلهمند بودند. ویندوز 11: نسل جدید مدیریت حافظهو اما ویندوز ۱۱ (۲۰۲۱ به بعد). در ظاهر شاید فکر کنید تفاوت زیادی با ویندوز ۱۰ ندارد، اما پشت پرده اتفاقات مهمی افتاده است. ۱. مدیریت حافظه آگاه از اولویت اپلیکیشنویندوز ۱۱ بهشکل پیشرفتهتری بین پردازهها تمایز قائل میشود. مثلاً وقتی شما یک مرورگر را باز میکنید اما پنجرهی دیگری را فعال دارید، ویندوز ۱۱ میتواند پردازههای پسزمینهی مرورگر را در سطح پایینتری از دسترسی رم قرار دهد. این یعنی سیستم در اولویتبندی aggressiveتر عمل میکند. ۲. بهبود در Memory Compressionمایکروسافت الگوریتم فشردهسازی حافظه را در ویندوز ۱۱ بهبود داده تا فشار کمتری روی CPU بیاورد. در ویندوز ۱۰، این فشردهسازی گاهی مصرف CPU را بالا میبرد، اما در ۱۱ کارآمدتر شده است. ۳. Integration با Virtualizationاز آنجایی که ویندوز ۱۱ روی ماشینهای مدرن و حتی Cloud PCها هدفگذاری شده، مدیریت حافظهاش tightly coupled با فناوریهای مجازیسازی مثل Hyper-V و WSL2 است. یعنی حافظه بین سیستم اصلی و ماشینهای مجازی بهینهتر تقسیم میشود. ۴. Memory Management در Microsoft Edge و اپلیکیشنهاویندوز ۱۱ با اپلیکیشنهای خودش (مثل Edge) همکاری نزدیک دارد تا مصرف رم کنترل شود. Edge میتواند تبهای غیرفعال را Suspend کند و ویندوز ۱۱ هم این حالت را بومی مدیریت میکند. ۵. انرژی و مصرف باترییکی از دلایل اصلی طراحی جدید مدیریت حافظه در ویندوز ۱۱، بهینهسازی برای لپتاپهاست. اپلیکیشنهای پسزمینه سریعتر به حالت Sleep میروند و همین باعث صرفهجویی در باتری میشود. مقایسهی عملی: ویندوز ۷ در برابر ویندوز ۱۱فرض کنید دو سیستم مشابه دارید: یکی با ویندوز ۷ و دیگری با ویندوز ۱۱. هر دو ۸ گیگابایت رم دارند. در ویندوز ۷، اگر چند مرورگر و نرمافزار آفیس باز کنید، احتمالاً نزدیک به ۷۰٪ رم پر میشود. وقتی رم پر شد، بخشی از دادهها به Pagefile میرود و سیستم کند میشود. در ویندوز ۱۱، همان سناریو باعث میشود دادهها ابتدا فشرده شوند. پس شاید ۸۰٪ رم پر شود، اما سیستم همچنان سریع بماند. همچنین پردازههای غیرفعال به پسزمینه تبعید میشوند و فشار کمتری روی CPU و باتری میآید. به زبان ساده: ویندوز ۱۱ رم بیشتری مصرف میکند، اما مدیریت هوشمندانهتری دارد. ویندوز ۷ کمتر مصرف میکند، اما وقتی پر شود، سیستم سریعتر دچار لگ میشود. چرا کروم اینقدر رم میخورد؟اینجا باید یک نکتهی مهم را هم اضافه کنیم: بخش زیادی از مصرف رم نه به ویندوز بلکه به اپلیکیشنها برمیگردد. مرورگرهایی مثل کروم یا حتی Edge از معماری چند-پردازه (multi-process) استفاده میکنند. یعنی هر تب و افزونه یک پردازهی جدا میشود و حافظهی بیشتری میگیرد. ویندوز ۱۱ فقط وظیفه دارد این پردازهها را بهینه مدیریت کند، اما نمیتواند جلوی مصرف بالای خود اپلیکیشن را بگیرد. نتیجهگیریاگر بخواهیم خلاصه کنیم: ویندوز XP و ۷ بیشتر متکی به Pagefile بودند. ویندوز ۸ و ۱۰ مفهوم Memory Compression و Prioritization را جدی وارد بازی کردند. ویندوز ۱۱ این روند را تکمیل کرده و آن را با دنیای مدرن لپتاپها، مجازیسازی و صرفهجویی انرژی هماهنگ کرده است. پس بله، ویندوز ۱۱ شاید رم بیشتری نشان دهد که مصرف شده، اما در عمل سیستم روانتر و کارآمدتر عمل میکند. دیگر مثل ویندوز ۷ وقتی رم پر میشود کل سیستم به زانو درنمیآید. این همان جایی است که باید نگاهمان را عوض کنیم: پر بودن رم همیشه چیز بدی نیست؛ رم برای استفاده شدن ساخته شده، نه برای خالی ماندن.
-
خسوف کامل امشب - ۱۶ شهریور ۱۴۰۴
sina پاسخی ارسال کرد برای یک مطلب در مطالب علمی و اطلاعات عمومیامشب، یکشنبه ۱۶ شهریور ۱۴۰۴ (۷ سپتامبر ۲۰۲۵)، آسمان ایران میزبان یکی از زیباترین نمایشهای کیهانی سال خواهد بود: خسوف کامل ماه، که به «ماه خونین» معروف است. اگر به نجوم علاقه دارید یا حتی فقط دوست دارید لحظاتی از زیباییهای طبیعت و آسمان لذت ببرید، این رویداد را از دست ندهید. در این مقاله، همهچیز درباره این پدیده شگفتانگیز، زمانبندی دقیق، چگونگی رصد و چند نکته کاربردی برای لذت بردن از آن را برایتان توضیح میدهم. خسوف چیست و چرا ماه قرمز میشود؟خسوف یا ماهگرفتگی زمانی اتفاق میافتد که زمین دقیقاً بین خورشید و ماه قرار میگیرد و سایهاش روی ماه میافتد. امشب، ماه بهطور کامل وارد سایه زمین (اومبرا) میشود و اینجاست که جادوی طبیعت شروع میشود. برخلاف نور سفید و درخشان همیشگی ماه، در خسوف کامل، ماه به رنگ سرخ یا نارنجی مسی درمیآید. دلیلش؟ نور خورشید از جو زمین عبور میکند و به دلیل پدیدهای به نام پراکندگی رایلی، نور آبی پراکنده شده و نور قرمز به ماه میرسد. انگار ماه غروب خورشید را روی سطح خودش بازتاب میدهد! این رنگ سرخ و وهمانگیز همان چیزی است که باعث شده این پدیده را «ماه خونین» بنامند. این خسوف نهتنها در ایران، بلکه در بخشهای وسیعی از آسیا، اروپا، آفریقا و استرالیا قابلمشاهده است. نکته جالب اینجاست که حدود ۷۷ درصد از جمعیت جهان میتوانند امشب این نمایش آسمانی را ببینند، و ایران یکی از بهترین نقاط برای رصد آن است. زمانبندی دقیق خسوف در ایرانبرای اینکه بتوانید برنامهریزی کنید و بهترین لحظات این رویداد را از دست ندهید، زمانبندی دقیق خسوف به وقت تهران را اینجا آوردهام: ورود ماه به نیمسایه (پنومبرا): ۱۸:۵۸ آغاز گرفتگی جزئی: ۱۹:۵۷ آغاز خسوف کامل: ۲۱:۰۰ اوج خسوف (بهترین زمان برای تماشا): ۲۱:۴۱:۴۶ پایان خسوف کامل: ۲۲:۲۳ پایان گرفتگی جزئی: ۲۳:۲۶ خروج کامل از نیمسایه: ۰۰:۲۵ (بامداد ۱۷ شهریور) کل این پدیده حدود ۳ ساعت و نیم طول میکشد، و بخش کامل آن (وقتی ماه کاملاً قرمز است) حدود ۸۲ دقیقه ادامه دارد. این یکی از طولانیترین خسوفهای قرن است، پس فرصت خوبی دارید که حسابی از آن لذت ببرید. چطور ماه خونین را تماشا کنیم؟خوشبختانه برای تماشای خسوف نیازی به تجهیزات خاص نیست. برخلاف خورشیدگرفتگی که به عینکهای محافظ نیاز دارد، خسوف کامل را میتوانید با چشم غیرمسلح ببینید و کاملاً ایمن است. با این حال، چند نکته میتواند تجربه شما را بهتر کند: مکان مناسب انتخاب کنید: جایی با آسمان صاف و بدون آلودگی نوری، مثل مناطق مرتفع یا خارج از شهر، بهترین انتخاب است. اگر در شهر هستید، پشتبام یا پارکی با دید باز به افق شرقی هم کارتان را راه میاندازد. دوربین یا تلسکوپ (اختیاری): اگر دوربین دوچشمی یا تلسکوپ دارید، میتوانید جزئیات سطح ماه و تغییرات رنگش را بهتر ببینید. اما همانطور که گفتم، چشم غیرمسلح هم کافی است. عکاسی از ماه خونین: اگر دوست دارید این لحظه را ثبت کنید، از یک دوربین با قابلیت تنظیم دستی استفاده کنید. تنظیمات پیشنهادی: ایزو ۲۰۰–۸۰۰، دیافراگم f/5.6 تا f/8، و سرعت شاتر متناسب با نور محیط. حتماً از سهپایه استفاده کنید تا عکسها تار نشود. برای ثبت تغییرات رنگ، چند عکس در بازههای زمانی مختلف بگیرید. لباس مناسب و صبر: با توجه به اینکه این رویداد چند ساعت طول میکشد و در شب اتفاق میافتد، لباس گرم بپوشید و کمی صبر به خرج دهید. زیبایی خسوف در روند آرام و تدریجی آن است. چرا این خسوف خاص است؟این خسوف چند ویژگی خاص دارد که آن را به یک رویداد نجومی ویژه تبدیل کرده: مدتزمان طولانی: ۸۲ دقیقه خسوف کامل، فرصتی عالی برای تماشا و عکاسی است. رؤیتپذیری در ایران: تمام مراحل خسوف از همه نقاط ایران قابلمشاهده است، که این خودش یک امتیاز بزرگ است. نادر بودن: به گفته کارشناسان، این یکی از نادرترین خسوفهای قرن است و مشابه آن تا چند سال دیگر (حدود ۷ سال) در ایران دیده نمیشود. نزدیکی به حضیض ماه: این خسوف فقط ۳ روز قبل از رسیدن ماه به نزدیکترین نقطه به زمین (حضیض) رخ میدهد، به همین دلیل ماه کمی بزرگتر و درخشانتر به نظر میرسد. کمی حس و حال کیهانیماه همیشه برای ما انسانها چیزی بیشتر از یک جرم آسمانی بوده است. از داستانهای عاشقانه و شعرهای حافظ گرفته تا افسانههای قدیمی درباره ماهگرفتگی، این پدیدهها همیشه حس کنجکاوی و شگفتی ما را برانگیختهاند. امشب وقتی به ماه سرخ نگاه میکنید، لحظهای به عظمت کیهان و جای ما در این دنیای بزرگ فکر کنید. این نمایش طبیعت، یادآوری است که چقدر دنیای ما پر از شگفتیهای کوچک و بزرگ است. نکات نهاییاگر هوا ابری بود، ناامید نشوید. گاهی ابرها برای لحظاتی کنار میروند و میتوانید بخشی از خسوف را ببینید. این رویداد برای همه سنین مناسب است، پس میتوانید با خانواده یا دوستانتان این تجربه را به اشتراک بگذارید. اگر عکسی از ماه خونین گرفتید، آن را در شبکههای اجتماعی با هشتگ #ماه_خونین یا #خسوف_۱۴۰۴ به اشتراک بگذارید و حس و حالتان را با دیگران شریک شوید. امشب، ساعت ۲۱:۴۱، به آسمان نگاه کنید و از این نمایش کیهانی لذت ببرید. ماه خونین منتظر شماست!
-
دستور NOP: سادهترین و پیچیدهترین دستور پردازنده
sina پاسخی ارسال کرد برای یک مطلب در مطالب علمی و اطلاعات عمومیاگر به دنیای برنامهنویسی و معماری پردازندهها علاقه دارید، حتماً با اصطلاح NOP آشنا شدهاید یا دستکم نام آن را شنیدهاید. این دستور کوچک که مخفف "No Operation" است، در نگاه اول ممکن است بیفایده به نظر برسد، اما در واقعیت نقشهای مهم و جالبی در دنیای محاسبات دارد NOP چیست؟دستور NOP به سادگی یک دستور است که هیچ کاری انجام نمیدهد. آن را میتوان "عملیات خالی" یا "دستور تهی" ترجمه کرد. وقتی پردازنده این دستور را اجرا میکند، تنها کاری که انجام میدهد این است که شمارنده برنامه (Program Counter) را یک واحد جلو میبرد و به دستور بعدی میرود. هیچ رجیستری تغییر نمیکند، هیچ محاسبهای صورت نمیگیرد، و هیچ دادهای جابهجا نمیشود و به واقع یک سیکل خالی ایجاد میکند. در اکثر معماریهای پردازنده، NOP معمولاً یک بایت یا چند بایت فضا اشغال میکند. برای مثال، در معماری x86، دستور NOP کد عملیاتی 0x90 دارد و تنها یک بایت حافظه اشغال میکند. چرا به دستوری نیاز داریم که هیچ کاری نکند؟این سؤال طبیعی است که چرا طراحان پردازنده زحمت تعریف کردن دستوری را کشیدهاند که هیچ کاری انجام نمیدهد. در ادامه به دلایل مهم استفاده از NOP میپردازیم. 1. تراز کردن کد (Code Alignment)یکی از کاربردهای اصلی NOP در تراز کردن کد است. پردازندههای مدرن بهترین عملکرد را زمانی دارند که کد در مرزهای خاصی از حافظه قرار گیرد. برای مثال، ممکن است عملکرد بهتر باشد اگر تابعها در آدرسهایی قرار گیرند که بر ۱۶ بخشپذیر باشند. ; مثال تراز کردن با NOP my_function: mov eax, 1 add eax, 2 nop ; برای تراز کردن nop ret aligned_function: ; این تابع در مرز مناسب قرار دارد mov ebx, 5 sub ebx, 1 ret2. زمانبندی و تأخیر (Timing and Delay)در برخی موارد، بهویژه در برنامهنویسی سیستمهای تعبیهشده، نیاز به ایجاد تأخیرهای کوچک وجود دارد. NOP راهی ساده برای ایجاد چنین تأخیری است: ; مثال ایجاد تأخیر کوتاه output_to_port: out 0x80, al ; خروجی به پورت nop ; تأخیر کوتاه nop ; برای اطمینان از پردازش nop in al, 0x81 ; خواندن از پورت دیگر3. جایگزینی دستورات (Instruction Replacement)در فرآیند دیباگ کردن یا وصلهگذاری نرمافزار، گاهی نیاز است دستوری را غیرفعال کنیم بدون اینکه ساختار کلی برنامه تغییر کند. NOP برای این منظور بسیار مناسب است: ; قبل از وصله problematic_instruction: call dangerous_function ; این دستور مشکل دارد ; بعد از وصله problematic_instruction: nop ; دستور مشکلدار غیرفعال شد nop nop nop nop ; تعداد NOP برابر با اندازه دستور اصلی4. بهینهسازی pipelineپردازندههای مدرن از تکنیک pipeline استفاده میکنند تا چندین دستور را همزمان در مراحل مختلف اجرا کنند. گاهی NOP به عنوان "حباب" در pipeline عمل میکند و به حل تداخلهای دادهای کمک میکند. انواع مختلف NOPجالب است بدانید که NOP تنها یک دستور نیست، بلکه خانوادهای از دستورات است: NOP تکبایتیnop ; کد 0x90 در x86NOP چندبایتیدر معماریهای مدرن، NOPهای چندبایتی نیز وجود دارند: ; NOP دوبایتی در x86 0x66 0x90 ; NOP سهبایتی 0x0F 0x1F 0x00 ; NOP چهاربایتی 0x0F 0x1F 0x40 0x00NOP در زبانهای برنامهنویسی سطح بالاحتی در زبانهای سطح بالا نیز مفهوم NOP وجود دارد، اگرچه معمولاً به صراحت از این اصطلاح استفاده نمیشود: در پایتون: if condition: pass # معادل NOP # در C++ if (condition) { ; // دستور خالی - معادل NOP }در Rust: if condition { // هیچ کد خاصی - کامپایلر ممکن است NOP تولید کند } // یا به صراحت unsafe { std::arch::asm!("nop"); }تأثیر NOP بر عملکردممکن است فکر کنید NOP هیچ تأثیری بر عملکرد ندارد، اما این تصور کاملاً درست نیست. هر NOP: زمان اجرا میبرد (معمولاً یک چرخه ساعت) فضای حافظه اشغال میکند بر cache instruction تأثیر میگذارد بنابراین استفاده بیرویه از NOP میتواند عملکرد برنامه را کاهش دهد. کاربردهای پیشرفته NOP1. Side-Channel Attack Preventionدر امنیت سیستمها، NOP گاهی برای جلوگیری از حملات تایمینگ استفاده میشود: secure_compare: ; مقایسه امن با زمان ثابت cmp al, bl jne not_equal nop nop jmp end_compare not_equal: nop nop end_compare: ret2. ROP Chain Breakingدر امنیت، NOP میتواند برای شکستن ROP chainها استفاده شود: ; قرار دادن NOP برای مختل کردن ROP gadgetها function_start: nop pop eax nop retNOP در معماریهای مختلفهر معماری پردازنده NOP خود را دارد: x86/x64: 0x90 ARM: 0x00000000 (mov r0, r0) RISC-V: 0x00000013 (addi x0, x0, 0) MIPS: 0x00000000 نتیجهگیریدستور NOP نمونهای عالی از اصل "سادگی در پیچیدگی" است. این دستور به ظاهر ساده، نقشهای مهمی در بهینهسازی، امنیت، و عملکرد سیستمها ایفا میکند. درک صحیح از NOP و کاربردهای آن، به برنامهنویسان کمک میکند تا کد بهتر و کارآمدتری بنویسند. در دنیای امروز که عملکرد و امنیت اهمیت فراوانی دارند، حتی "هیچکاری نکردن" نیز هنری است که باید به درستی فرا گرفته شود. NOP یادآور این نکته است که گاهی قدرت واقعی در سادگی نهفته است.
-
آشنایی با Linear Data Structure در برنامهنویسی
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیدر دنیای برنامهنویسی، دادهها مثل آجرهای یک ساختمان هستند؛ نحوه سازماندهی و مدیریت آنها میتواند سرعت و کارایی برنامه ما را تعیین کند. یکی از پرکاربردترین روشهای سازماندهی دادهها، استفاده از Linear Data Structure است. در این مقاله، قصد داریم این مفهوم یعنی ساختار داده خطی را به زبانی ساده توضیح دهیم، انواع آن را بررسی کنیم و مثالهایی برای درک بهتر ارائه دهیم. Linear Data Structure چیست؟Linear Data Structure یا ساختار دادهی خطی، نوعی ساختار داده است که در آن عناصر به صورت خطی و ترتیبی ذخیره میشوند. این یعنی هر عنصر، حداکثر یک عنصر قبل و یک عنصر بعد دارد (به جز اولین و آخرین عنصر). به زبان سادهتر، دادهها مثل یک صف یا یک زنجیره پشت سر هم قرار میگیرند. مزیت این ساختار این است که دسترسی و پیمایش دادهها ساده و قابل پیشبینی است. اما نقطه ضعفش این است که افزودن یا حذف عناصر میتواند هزینهبر باشد، بهخصوص اگر بخواهید وسط زنجیره را تغییر دهید. انواع Linear Data Structure1. Array (آرایه)آرایه یکی از سادهترین و شناختهشدهترین ساختارهای خطی است. در آرایه، اندازه مشخص است و دادهها در خانههای پشت سر هم حافظه ذخیره میشوند. ویژگیها: دسترسی سریع به هر عنصر با استفاده از اندیس (Index) اندازه ثابت (در بسیاری از زبانها) افزودن یا حذف عنصر در وسط آرایه پرهزینه است مثال در Python: # تعریف یک آرایه از اعداد numbers = [10, 20, 30, 40, 50] # دسترسی به عنصر سوم print(numbers[2]) # خروجی: 30 # اضافه کردن عنصر به انتهای آرایه numbers.append(60) print(numbers) # خروجی: [10, 20, 30, 40, 50, 60] 2. Linked List (لیست پیوندی)لیست پیوندی از چند گره (Node) تشکیل شده است که هر گره شامل داده و اشارهگر به گره بعدی است. برخلاف آرایه، اندازه لیست پیوندی انعطافپذیر است. ویژگیها: افزودن یا حذف عنصر در هر نقطه آسانتر از آرایه است دسترسی به عناصر به صورت ترتیبی است، نه مستقیم مصرف حافظه بیشتر به خاطر ذخیره اشارهگرها مثال ساده در Python: class Node: def __init__(self, data): self.data = data self.next = None class LinkedList: def __init__(self): self.head = None def append(self, data): new_node = Node(data) if not self.head: self.head = new_node return last = self.head while last.next: last = last.next last.next = new_node def print_list(self): current = self.head while current: print(current.data, end=" -> ") current = current.next print("None") # استفاده llist = LinkedList() llist.append(10) llist.append(20) llist.append(30) llist.print_list() # خروجی: 10 -> 20 -> 30 -> None 3. Stack (پشته)پشته یک ساختار دادهی خطی است که بر اساس قانون LIFO (Last In, First Out) عمل میکند؛ یعنی آخرین دادهای که وارد میشود، اولین دادهای است که خارج میشود. ویژگیها: استفاده در Undo/Redo برنامهها، مدیریت حافظه و الگوریتمهای بازگشتی عملیات اصلی: push (اضافه کردن) و pop (حذف کردن) مثال ساده: stack = [] stack.append(1) # push stack.append(2) stack.append(3) print(stack.pop()) # خروجی: 3 print(stack) # خروجی: [1, 2] 4. Queue (صف)صف یک ساختار دادهی خطی دیگر است که بر اساس قانون FIFO (First In, First Out) عمل میکند؛ یعنی اولین دادهای که وارد میشود، اولین دادهای است که خارج میشود. ویژگیها: استفاده در مدیریت پردازشها، صف پرینترها و شبکه عملیات اصلی: enqueue (اضافه کردن) و dequeue (حذف کردن) مثال ساده: from collections import deque queue = deque([1, 2, 3]) queue.append(4) # enqueue print(queue.popleft()) # dequeue -> خروجی: 1 print(queue) # خروجی: deque([2, 3, 4]) جمعبندیLinear Data Structure پایه و اساس بسیاری از الگوریتمها و سیستمهای نرمافزاری است. انتخاب نوع ساختار مناسب بستگی به نیاز شما دارد: اگر سرعت دسترسی مهم است، آرایه انتخاب خوبی است. اگر اندازه دادهها پویا است و تغییرات زیادی در وسط دادهها دارید، لیست پیوندی بهتر است. اگر ترتیب ورود و خروج اهمیت دارد، Stack و Queue گزینههای عالی هستند. با تسلط بر این مفاهیم، شما آمادهاید تا دادهها را در برنامههایتان هوشمندانه مدیریت کنید و الگوریتمهای بهینهتری بنویسید.
-
هوش مصنوعی و برنامهنویسی: آینده شغلی برنامهنویسها در عصر AI
sina پاسخی ارسال کرد برای یک مطلب در هوش مصنوعیهوش مصنوعی (AI) به سرعت در حال تغییر دادن دنیای برنامهنویسی است. ابزارهای هوشمند از پیشنهاد کد گرفته تا اتوماسیون تست و تحلیل کیفیت، برنامهنویسان را قادر میسازند تا بهرهوری خود را افزایش دهند و روی مسائل پیچیدهتر تمرکز کنند. با این حال، ورود AI به این حوزه سوالات مهمی ایجاد میکند: آیا برنامهنویسها جایگاه خود را از دست خواهند داد؟ نقش انسانی در طراحی و توسعه نرمافزار چه خواهد شد؟ در این مقاله، نگاهی دقیق و علمی به تاثیر AI بر برنامهنویسی، فرصتها و چالشها و آینده شغلی توسعهدهندگان خواهیم داشت. هوش مصنوعی و تکامل برنامهنویسیتوسعه نرمافزار از دههها قبل به صورت دستی انجام میشد؛ برنامهنویسها الگوریتمها را طراحی و کد را خط به خط مینوشتند. با ظهور AI و مدلهای زبانی پیشرفته، مانند GPT، Codex و ابزارهایی مانند GitHub Copilot، روند تولید کد تغییر کرده است. این ابزارها قادرند: تولید خودکار کد: از خطوط ساده تا بلوکهای کد پیچیده با کمترین دخالت انسانی. پیشنهاد هوشمند در IDE: تکمیل کد و پیشنهاد بهترین الگوهای کدنویسی در زمان واقعی. تشخیص باگ و مشکلات امنیتی: ارزیابی کد و ارائه توصیه برای اصلاح مشکلات بالقوه. اتوماسیون تست و مستندسازی: تولید تست واحد و مستندات به صورت خودکار، کاهش بار کاری برنامهنویس. این امکانات، نه تنها بهرهوری برنامهنویسان را افزایش میدهد، بلکه امکان تمرکز روی طراحی سیستم، بهینهسازی الگوریتمها و حل مسائل پیچیده را فراهم میکند. مزایای استفاده از AI در توسعه نرمافزار۱. افزایش بهرهوریAI میتواند کدهای تکراری و استاندارد را خودکار تولید کند، به طوری که برنامهنویسها بتوانند انرژی خود را روی مسائل با ارزشتر متمرکز کنند. تحقیقات نشان میدهند استفاده از ابزارهای AI در توسعه نرمافزار میتواند تا ۳۰-۵۰٪ زمان توسعه را کاهش دهد. ۲. بهبود کیفیت کدبا تحلیل الگوهای کدنویسی و شناسایی مشکلات احتمالی، AI میتواند کیفیت کد را بهبود دهد. ابزارهایی مانند static analyzers مبتنی بر AI، با ارائه پیشنهادات اصلاحی و هشدارهای امنیتی، امکان تولید کدی امن و پایدار را فراهم میکنند. ۳. پشتیبانی از تصمیمگیریهای پیچیدهبرنامهنویسان با کمک AI میتوانند بهترین الگوریتمها، ساختار دادهها و الگوهای طراحی را انتخاب کنند. این ابزارها با تحلیل کد و سابقه پروژه، توصیههای بهینه ارائه میدهند. محدودیتها و چالشهای AI در برنامهنویسیبا وجود مزایا، AI محدودیتهای مهمی دارد: درک زمینه و هدف پروژه AI نمیتواند نیازهای دقیق مشتری یا هدف کلی پروژه را درک کند. برنامهنویسها همچنان مسئول تحلیل نیازمندیها و طراحی سیستم هستند. حل مسائل پیچیده و انتزاعی مسائل پیشرفته طراحی الگوریتم، معماری سیستمهای بزرگ و بهینهسازی منابع، هنوز نیاز به تفکر انسانی دارد. مسائل اخلاقی و امنیتی AI ممکن است پیشنهاداتی بدهد که از لحاظ امنیتی یا اخلاقی مشکلساز باشد. انسان باید کنترل نهایی را حفظ کند. وابستگی به داده و مدلها کیفیت خروجی AI به دادههای آموزش آن بستگی دارد. دادههای ناقص یا سوگیرانه میتوانند منجر به تولید کد نادرست یا ناامن شوند. نقش برنامهنویس در عصر AIبر خلاف تصور عمومی، AI برنامهنویسان را حذف نخواهد کرد؛ بلکه نقش آنها را تغییر میدهد: طراح و ناظر کد: برنامهنویسها به جای نوشتن هر خط کد، سیستمها و الگوریتمها را طراحی کرده و AI را برای تولید کد به کار میگیرند. تصمیمگیرنده در مسائل پیچیده: مسائل معماری، امنیت و بهینهسازی هنوز به تحلیل انسانی نیاز دارند. مدیر و بهینهساز AI: متخصصانی که AI را به عنوان ابزار مدیریت میکنند، توصیهها را بررسی کرده و بهینه میسازند. مهارتهای ضروری برای برنامهنویسان آیندهبرای موفقیت در عصر AI، برنامهنویسان باید مهارتهای ترکیبی توسعه دهند: تسلط بر ابزارهای AI یادگیری ابزارهایی مانند GitHub Copilot، ChatGPT API و مدلهای مشابه، توانایی استفاده موثر از AI را فراهم میکند. تفکر انتقادی و حل مسئله AI ممکن است کد تولید کند، اما توانایی ارزیابی کارآمدی، امنیت و بهینهسازی آن با انسان است. تخصص در حوزههای تخصصی امنیت سایبری، سیستمهای توزیعشده، پردازش دادههای بزرگ و یادگیری ماشین حوزههایی هستند که نیاز به دانش عمیق انسانی دارند. مهارتهای نرم و همکاری تیمی AI نمیتواند روابط بین اعضای تیم، مذاکره و مدیریت پروژه را جایگزین کند. فرصتهای شغلی جدید در دوران AIظهور AI فرصتهای شغلی تازهای ایجاد کرده است: AI-assisted Developer: توسعهدهندگانی که AI را ابزار خود میدانند و فرآیند توسعه را بهینه میکنند. AI Code Auditor: متخصصانی که کدهای تولید شده توسط AI را بررسی و بهینه میکنند. AI System Designer: طراحی سیستمهای پیچیده که با همکاری AI بهینه عمل میکنند. این نقشها نیازمند ترکیبی از مهارتهای برنامهنویسی، دانش AI و توانایی تصمیمگیری انسانی هستند. نکات عملی برای سازگاری با عصر AIادغام AI در گردش کار: AI را به عنوان ابزار مکمل ببینید، نه جایگزین. تمرکز بر مهارتهای انسانی و تفکر انتقادی: توانایی حل مسئله و طراحی سیستم هنوز ارزشمند است. یادگیری مادامالعمر: AI به سرعت در حال پیشرفت است. برنامهنویسان موفق کسانی هستند که همواره دانش خود را بهروز نگه میدارند. مستندسازی و کدنویسی پایدار: حتی کد تولید شده توسط AI نیاز به بررسی و بهینهسازی دارد. نتیجهگیریهوش مصنوعی دنیای برنامهنویسی را متحول کرده است، اما این تحول به معنای پایان کار برنامهنویسها نیست. AI ابزاری است که میتواند بهرهوری، کیفیت و سرعت توسعه نرمافزار را افزایش دهد، اما تصمیمگیری، طراحی سیستم و تحلیل پیچیده همچنان در حوزه تخصص انسانی باقی میماند. برنامهنویسان آینده کسانی هستند که نه تنها کد مینویسند، بلکه تفکر تحلیلی، طراحی معماری و خلاقیت را با توانایی استفاده از AI ترکیب میکنند. آینده متعلق به کسانی است که AI را به ابزار قدرتمند خود تبدیل کنند، نه تهدیدی برای جایگاهشان.
-
Spread Operator در جاوا اسکریپت
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیوقتی صحبت از زبان جاوا اسکریپت میشود، یکی از قابلیتهایی که در چند سال اخیر بسیار محبوب شده، Spread Operator یا همان عملگر ... است. این عملگر ساده اما قدرتمند، میتواند کدنویسی شما را هم کوتاهتر و هم خواناتر کند. شاید در نگاه اول فقط سه نقطهی ساده به نظر برسد، اما پشت همین سه نقطه، امکانات زیادی برای کار با آرایهها، آبجکتها و حتی توابع پنهان شده است. در این مطلب قصد دارم به صورت کامل و مرحله به مرحله، همه چیز دربارهی Spread Operator در جاوا اسکریپت را توضیح بدهم. اگر تازهکار هستید یا حتی سالهاست با جاوا اسکریپت کار میکنید، مطمئنم نکتههایی پیدا میکنید که به کارتان بیاید. Spread Operator چیست؟Spread Operator در واقع یک سینتکس (...) است که به ما اجازه میدهد مقادیر یک آرایه یا خواص یک آبجکت را باز کنیم و در یک ساختار جدید قرار دهیم. به بیان ساده، انگار محتویات را از داخل ظرفشان بیرون میریزیم و مستقیم استفاده میکنیم. مثال ساده: const numbers = [1, 2, 3]; console.log(...numbers); // خروجی: 1 2 3 اینجا آرایهی numbers باز شده و هر عنصر به صورت جداگانه چاپ میشود. کاربردهای Spread Operator در آرایهها1. کپی کردن آرایهقبلاً اگر میخواستیم یک آرایه را کپی کنیم باید از متدهایی مثل slice() استفاده میکردیم. حالا خیلی راحت با Spread: const arr1 = [10, 20, 30]; const arr2 = [...arr1]; console.log(arr2); // [10, 20, 30] console.log(arr1 === arr2); // false (دو آرایهی مجزا هستند) نکته: این کپی فقط سطحی (shallow copy) است. یعنی اگر داخل آرایه آبجکتهای تو در تو داشته باشید، فقط مرجع آنها کپی میشود. 2. ترکیب آرایهها (Array Concatenation)به جای استفاده از concat، میتوانیم چند آرایه را خیلی ساده ترکیب کنیم: const fruits = ["apple", "banana"]; const moreFruits = ["orange", "kiwi"]; const allFruits = [...fruits, ...moreFruits]; console.log(allFruits); // ["apple", "banana", "orange", "kiwi"] 3. افزودن عناصر جدیدبا Spread میتوانیم به راحتی مقادیری را قبل یا بعد از آرایه اضافه کنیم: const base = [2, 3, 4]; const extended = [1, ...base, 5]; console.log(extended); // [1, 2, 3, 4, 5] کاربردهای Spread Operator در آبجکتهااز نسخهی ES2018 به بعد، Spread Operator برای آبجکتها هم معرفی شد. این یعنی حالا میتوانیم خیلی راحت آبجکتها را ترکیب یا کپی کنیم. 1. کپی آبجکتconst user = { name: "Sara", age: 25 }; const newUser = { ...user }; console.log(newUser); // { name: "Sara", age: 25 } console.log(user === newUser); // false باز هم توجه داشته باشید که این کپی سطحی است. 2. ترکیب چند آبجکتاگر بخواهید خصوصیات چند آبجکت را در هم ادغام کنید، Spread راه خیلی سادهای است: const person = { name: "Ali", age: 30 }; const job = { title: "Developer", company: "TechCorp" }; const employee = { ...person, ...job }; console.log(employee); // { name: "Ali", age: 30, title: "Developer", company: "TechCorp" } 3. بازنویسی خصوصیاتاگر خصوصیات مشترک داشته باشید، آخرین مقدار جلوی قبلی را میگیرد: const obj1 = { name: "Reza", age: 20 }; const obj2 = { age: 25, city: "Tehran" }; const result = { ...obj1, ...obj2 }; console.log(result); // { name: "Reza", age: 25, city: "Tehran" } استفاده از Spread در توابعیکی از جذابترین کاربردهای Spread این است که میتوانیم عناصر یک آرایه را به عنوان ورودیهای یک تابع پاس بدهیم. function sum(a, b, c) { return a + b + c; } const nums = [5, 10, 15]; console.log(sum(...nums)); // 30 این خیلی بهتر از نوشتن sum(nums[0], nums[1], nums[2]) است. تفاوت Spread Operator با Rest Parameterشاید کمی گیجکننده باشد چون هر دو با ... نوشته میشوند. اما Spread و Rest دو چیز کاملاً متفاوت هستند: Spread: برای باز کردن آرایه یا آبجکت استفاده میشود. Rest: برای جمع کردن چند مقدار در قالب یک آرایه استفاده میشود. مثال Rest: function multiply(factor, ...numbers) { return numbers.map(num => num * factor); } console.log(multiply(2, 1, 2, 3)); // [2, 4, 6] اینجا ...numbers تمام ورودیهای اضافی را در قالب یک آرایه جمع کرده است. محدودیتها و نکات مهم Spread Operatorکپی سطحی (Shallow Copy): اگر با دادههای تو در تو (nested) سر و کار دارید، باید حواستان باشد که Spread فقط سطح اول را کپی میکند. const obj = { user: { name: "Sara" } }; const copy = { ...obj }; copy.user.name = "Ali"; console.log(obj.user.name); // "Ali" (تغییر در هر دو اعمال شده) ترتیب اهمیت دارد: وقتی چند آبجکت یا آرایه را ترکیب میکنید، ترتیب قرارگیری Spread اهمیت دارد و مقادیر بعدی روی مقادیر قبلی overwrite میشوند. قابل استفاده فقط در iterableها: برای آرایهها و آبجکتها کار میکند، ولی روی چیزهایی مثل اعداد مستقیم یا null جواب نمیدهد. در نهایتSpread Operator در جاوا اسکریپت یک ابزار ساده اما بسیار کاربردی است که کدنویسی شما را کوتاهتر، تمیزتر و خواناتر میکند. از کپی و ترکیب آرایهها و آبجکتها گرفته تا ارسال آرایه به توابع، همه را میتوان با همین سه نقطه انجام داد. اگر تازه شروع کردهاید، پیشنهاد میکنم در پروژههای کوچک استفاده کنید تا به مرور دستتان بیاید. و اگر حرفهای هستید، مطمئنم میتوانید با استفاده خلاقانه از Spread Operator کدهایی بنویسید که نگهداریشان خیلی راحتتر باشد.
-
مرز بین Low-Level و High-Level در زبان Rust کجاست؟
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیRust زبانیست که خیلیها آن را «سطح پایین» میدانند، درحالیکه بعضی دیگر از قدرت انتزاعهایش حرف میزنند و آن را بهخاطر ویژگیهای مدرنش تحسین میکنند. این دو دیدگاه متضاد در مورد یک زبان واحد، سؤال مهمی را مطرح میکند: مرز بین سطح پایین و سطح بالا در Rust دقیقاً کجاست؟ در این مقاله، سعی میکنم این مرز را نه با تعریفهای صرفاً تئوریک، بلکه از زاویه دید یک توسعهدهنده بررسی کنم؛ کسی که هم درگیر ابزارهای نزدیک به سیستم بوده، هم از امکانات سطح بالای Rust بهره برده است. High-Level و Low-Level: دقیقاً یعنی چه؟قبل از وارد شدن به جزئیات، بهتر است ابتدا نگاهی کوتاه به تعاریف بیندازیم: زبانهای سطح پایین (Low-Level) معمولاً کنترل دقیقی روی حافظه، مدیریت منابع، و عملکرد دارند. C و Assembly بهترین مثالهای این دسته هستند. زبانهای سطح بالا (High-Level) روی سادگی، انتزاع و راحتی توسعهدهنده تمرکز دارند. پایتون و جاوا اسکریپت در این دسته قرار میگیرند. اما Rust در این تقسیمبندی کلاسیک، جای مشخصی ندارد. برخلاف C، شما در Rust نیازی به free کردن حافظه ندارید، اما در عین حال هیچ Garbage Collector هم در کار نیست. شما میتوانید در سطح انتزاع بسیار بالا کار کنید یا به کمک unsafe مستقیماً با اشارهگر خام کار کنید. این انعطاف، جاییست که موضوع جالب میشود. ابزارهای سطح بالا در RustRust امکانات زیادی دارد که آن را بهعنوان یک زبان سطح بالا مطرح میکند. این موارد باعث میشوند که توسعهدهندگان راحتتر، امنتر و سریعتر کدنویسی کنند: Pattern Matchingبا match و if-let و سایر ابزارهای الگو، میتوان منطق پیچیده را بهسادگی و خوانایی بالا پیادهسازی کرد. match value { Some(v) => println!("Value is: {}", v), None => println!("No value."), } Traits و Genericsانتزاعهایی شبیه به interfaces در زبانهای دیگر، اما با کنترل بیشتر و عملکرد بهتر در زمان اجرا و کامپایل. Sum Types (Enums با داده متصل)مفهوم enum در Rust با چیزی که در C یا Java میبینید متفاوت است. قابلیت پیوست کردن داده به هر variant، همراه با pattern matching، ابزار بسیار قدرتمندی برای طراحی API میدهد. async/awaitپشتیبانی native از async I/O بدون نیاز به توابع بازگشتی عجیبوغریب یا پیچیدگی زیاد، با ترکیب دقیق کنترل و راحتی توسعه. ماکروهای قدرتمندچه ماکروهای declarative (macro_rules!) و چه procedural macroها، امکان تولید کد تکراری را با کنترل کامل فراهم میکنند. ابزارهای سطح پایین در Rustدر طرف دیگر ماجرا، Rust یک زبان «سیستم» محسوب میشود، و دلیل خوبی هم دارد. امکاناتی که برای نزدیک شدن به سختافزار و کنترل دقیق رفتار برنامه در اختیارتان میگذارد، در بسیاری از زبانهای سطح بالا وجود ندارند: Unsafe CodeRust به شما اجازه میدهد با قرار دادن بخشهایی از کد در بلاک unsafe، به رفتارهایی خارج از سیستم بررسی ایمنی زبانی دسترسی داشته باشید؛ مثل: کار با اشارهگر خام دسترسی مستقیم به حافظه تعامل با کدهای C یا اسمبلی Layout کنترلشدهی حافظهبا استفاده از attributes مثل #[repr(C)] یا #[repr(packed)]، میتوانید دقیقاً مشخص کنید که ساختار دادهها در حافظه چگونه چیده شوند. Assembly Inlineقابلیت استفاده از کد اسمبلی مستقیماً درون کد Rust با asm! یا llvm_asm! برای کنترل دقیق روی CPU instructions. Manual Allocationبا استفاده از Box::into_raw() و Vec::with_capacity() میتوانید بهصورت کاملاً کنترلشده حافظه را مدیریت کنید. یک مثال دوگانه: کار همزمان در دو سطحفرض کنیم میخواهیم یک buffer ساده بسازیم. نسخهی سطح بالا میتواند از Vec<u8> استفاده کند. اما اگر بخواهیم کنترل دقیق روی حافظه داشته باشیم، میتوانیم با unsafe و pointerها این کار را انجام دهیم. نسخهی High-Level:fn allocate_buffer(size: usize) -> Vec<u8> { vec![0; size] } نسخهی Low-Level:fn allocate_buffer(size: usize) -> *mut u8 { let layout = std::alloc::Layout::from_size_align(size, 1).unwrap(); unsafe { std::alloc::alloc(layout) } }هر دو نسخه معتبرند. نسخهی اول امن و راحت است، نسخهی دوم دقیق و خطرناک. همزیستی بهجای تضادRust یک زبان دوگانه نیست چون بین این دو دنیا درگیر است؛ بلکه چون راهی برای همزیستی داده است. شما میتوانید بیشتر زمان خود را در دنیای ایمن، خوانا و قابل نگهداری Rust بگذرانید، اما در لحظهای که نیاز باشد، دقیقاً تا سطح سختافزار پایین بروید—بدون ترک کردن زبان. مفهومی که این تعادل را ممکن کرده، zero-cost abstraction است: امکانات سطح بالا در Rust، در بسیاری از موارد، هیچ هزینهی اضافهای در زمان اجرا ندارند. به زبان ساده، abstraction بدون قربانی کردن performance. نتیجهگیریRust زبانیست که مرز بین سطح پایین و بالا را نه تنها محو کرده، بلکه در بسیاری از موارد، این مرز را به یک قابلیت تبدیل کرده است. در جهانی که گاهی کارایی و کنترل با راحتی و ایمنی در تضادند، Rust نشان داده که میتوان به هر دو دست یافت—اگر ابزار را خوب بشناسی. Rust نه صرفاً یک زبان low-level است، نه صرفاً high-level. Rust یک انتخاب معماریست.
-
چاپ و حروف چینی کتاب و روزنامه در دهه 40 و 50
sina پاسخی ارسال کرد برای یک مطلب در مطالب علمی و اطلاعات عمومیدر دهههای ۱۳۴۰ و ۱۳۵۰ خورشیدی، روزنامهها نقش پررنگی در زندگی فرهنگی و سیاسی مردم ایران داشتن؛ اونم تو دورانی که نه خبری از کامپیوتر بود، نه چاپگر لیزری، نه حتی نرمافزارهای طراحی صفحه. با این حال، روزنامهها هر روز صبح میرسیدن؛ با ستونهای مرتب و عکسهایی که کیفیتشون با استانداردهای اون زمان، واقعاً چشمگیر بود. اما سؤال اصلی اینه: چطور این کار انجام میشد؟ تو این مقاله، قراره نگاهی بندازیم به روند تولید روزنامه تو اون سالها؛ از چاپ متن گرفته تا درج عکس، با همهی ابزارها و مهارتهایی که تو دنیای تماماً آنالوگ دهه ۴۰ و ۵۰ شمسی، باعث میشدن چیزی به اسم «روزنامه» هر روز متولد بشه. حروفچینی: تایپ بدون کیبورداولین مرحلهی تولید هر روزنامه، حروفچینی بود؛ همون کاری که امروز با یه لپتاپ و کیبورد تو چند دقیقه انجامش میدیم. اما اون موقع همهچی دستی و مکانیکی بود. حروفچینی دستی (چاپ سربی)تو سادهترین حالت، حروفچینی یعنی واقعاً «چیدن حروف». هر حرف، یه قطعهی کوچیک فلزی (معمولاً سربی) بود که اپراتورها با دست میچیدن کنار هم تا یه کلمه یا جمله ساخته شه. این حروف روی یه قالب فلزی (بهاسم فرم) چیده میشدن و آماده چاپ میشدن. کار زمانبر و طاقتفرسایی بود، ولی تو نبود گزینهی سریعتر، همین روش استاندارد صنعت چاپ محسوب میشد. یک دستگاه Linotype دستگاههای حروفچینی (Linotype)کمکم دستگاههایی مثل Linotype وارد بازی شدن. اپراتور متن رو تایپ میکرد، دستگاه خودش حروف رو میساخت و کنار هم میچید و خروجیاش یه نوار فلزی برجسته از متن بود. این نوار مستقیماً تو چاپ استفاده میشد. سرعت کار نسبت به حالت دستی خیلی بیشتر بود. عکس در روزنامه: ماجرای کلیشهسازیگذاشتن عکس تو روزنامههای اون دوره خودش ماجرایی مفصل داشت. چون برعکس متن که با قالب فلزی چاپ میشد، عکس با یه تکنیک کاملاً متفاوت وارد صفحه میشد. نمونه ای از تصویر هافتون شده هافتونسازی و کلیشهاول باید تصویر تبدیل میشد به نسخهای قابل چاپ؛ چون چاپ با جوهر سیاه انجام میشد، باید تصویر به صورت نقطهنقطه (هافتون) در میاومد تا سایهروشنها شبیهسازی بشه. این کار با دوربینهای خاص و نگاتیو انجام میشد. بعدش تصویر نقطهدار رو منتقل میکردن روی یه ورق فلزی (معمولاً آلومینیوم یا روی) که بهش میگفتن کلیشه یا زینک. اسیدکاری کلیشهحالا نوبت اسیدکاری بود. قسمتهایی از فلز که قرار نبود جوهر بگیرن، با اسید خورده میشدن و بخشهای برجسته باقی میموندن. این کلیشهها میتونستن جوهر بگیرن و عکس رو چاپ کنن. طراحی صفحه: چسب و قیچیبعد از آماده شدن کلیشههای متن و عکس، نوبت میرسید به طراحی صفحه. این کار یه ترکیب از مهارت فنی و خلاقیت بود. طراحها با برش و چسبوندن تکهها روی یه ماکت، چیدمان نهایی صفحه رو میساختن. گاهی هم برای دقت بیشتر، از کاغذ شفاف استفاده میشد تا جای دقیق هر عنصر مشخص شه. همهچی با دست انجام میشد، بدون حتی یک پیکسل دیجیتال. دستگاه لترپرس چاپ: لترپرس یا افست؟وقتی صفحه نهایی آماده میشد، چاپ آغاز میشد. بسته به تجهیزات چاپخانه، از یکی از دو روش اصلی استفاده میکردن: چاپ لترپرستو این روش سنتی، فرمهای فلزی آغشته به جوهر بودن و مستقیم روی کاغذ فشار داده میشدن. روش قدیمیای بود ولی کیفیت قابلقبولی داشت. چاپ افستتوی افست، اول تصویر روی یه لاستیک مخصوص منتقل میشد و بعدش از اون روی کاغذ. این روش سریعتر بود و کیفیت بالاتری داشت، مخصوصاً برای چاپ رنگی یا تیراژ بالا. حرف آخرتولید روزنامه تو دهههای ۴۰ و ۵۰ شمسی، یه ترکیب جالب از هنر، مهارت و تکنولوژی مکانیکی بود. از حروفچینی دستی گرفته تا کلیشهسازی و طراحی صفحه با دست، همهی این کارها در نهایت منجر به یه روزنامه میشد که صبح فردا تو دکهها آماده بود. شاید امروز با یه لپتاپ و اینترنت بتونیم یه نشریه آنلاین تو چند ساعت بالا بیاریم، ولی نباید یادمون بره که همهی این راحتیها، نتیجهی راهی هست که اون نسل با زحمت و دقت طی کرده. واقعاً باید کلاه از سر برداشت جلوی اونهایی که با سرب و جوهر، دنیای رسانه رو ساختن.
-
چرا اینترنت طبقاتی و محدودیتهای اینترنتی به ضرر همه ماست؟
sina پاسخی ارسال کرد برای یک مطلب در شخصی و روزانهموضوع اینترنت طبقاتی و محدودیتهای دسترسی به اینترنت در سالهای اخیر به یکی از مسائل مورد بحث در جامعه تبدیل شده است. اینترنت طبقاتی به معنای ارائه دسترسی متفاوت به اینترنت بر اساس جایگاه شغلی، اجتماعی یا معیارهای دیگر است که در آن گروهی خاص از دسترسی آزاد و بدون محدودیت برخوردار میشوند، در حالی که دیگران با موانعی مانند فیلترینگ یا سرعت پایین مواجهاند. این رویکرد، همراه با محدودیتهای اینترنتی، نه تنها حقوق کاربران عادی را تضعیف میکند، بلکه به اقتصاد، آموزش و پیشرفت کلی جامعه آسیب میرساند. در این نوشتار، دلایلی برای مخالفت با این سیاستها ارائه میشود و بر ضرورت دسترسی برابر به اینترنت تأکید میگردد. اینترنت: حقی همگانیاینترنت در دنیای امروز دیگر یک ابزار تشریفاتی نیست، بلکه ضرورتی اساسی برای زندگی مدرن است. از دانشجویان در جستوجوی منابع علمی گرفته تا کارآفرینانی که به دنبال توسعه کسبوکار خود در فضای دیجیتال هستند، همه به دسترسی سریع و بدون محدودیت به اینترنت وابستهاند. اینترنت طبقاتی این حق را از بخشهایی از جامعه سلب میکند. به عنوان مثال، فردی که در یک شهر کوچک قصد راهاندازی کسبوکاری آنلاین دارد، اگر به دلیل عدم عضویت در گروههای خاص از دسترسی آزاد محروم باشد، فرصت رشد و رقابت را از دست خواهد داد. این امر نابرابری در دسترسی به فرصتها را تشدید میکند. فیلترینگ نیز پیامدهای مشابهی دارد. محدود شدن دسترسی به پلتفرمهای بینالمللی مانند اینستاگرام یا واتساپ، نه تنها کاربران عادی را متأثر میکند، بلکه کسبوکارهای کوچک را که به این ابزارها برای بازاریابی و ارتباط با مشتریان وابستهاند، با چالشهای جدی مواجه میسازد. برای نمونه، فروشگاهی که از طریق شبکههای اجتماعی محصولات خود را عرضه میکند، با فیلتر شدن این پلتفرمها ممکن است بازار خود را یکشبه از دست بدهد. آسیب به اقتصاد دیجیتالاقتصاد دیجیتال یکی از ستونهای اصلی رشد اقتصادی در جهان معاصر است. از فریلنسرهایی که در پلتفرمهای بینالمللی فعالیت میکنند تا استارتاپهایی که با نوآوری بازار را متحول میسازند، همگی به اینترنت آزاد و پایدار نیاز دارند. اینترنت طبقاتی با محدود کردن دسترسی عادلانه، فرصتهای این گروهها را کاهش میدهد. فریلنسری که برای انجام پروژههای بینالمللی به پلتفرمهای فیلترشده وابسته است، با محدودیتهای اینترنتی از رقابت در بازار جهانی بازمیماند. این امر نه تنها به زیان افراد است، بلکه اقتصاد کشور را از پتانسیلهای موجود محروم میکند. به عنوان نمونه، در سالهای اخیر، فیلترینگ برخی پلتفرمها باعث شده برنامهنویسان و طراحان با دشواریهای فراوانی مواجه شوند. بسیاری از آنها مجبور به استفاده از ابزارهای دور زدن فیلتر شدهاند که هزینهبر و ناامن است. اینترنت طبقاتی این نابرابری را عمیقتر میکند، زیرا تنها گروههای خاصی به دسترسی آزاد مجهز میشوند و دیگران در محدودیت باقی میمانند. تأثیر بر آموزش و پژوهشمحدودیتهای اینترنتی تأثیر منفی قابل توجهی بر آموزش و پیشرفت علمی دارد. بسیاری از منابع علمی، از مقالات تخصصی تا ویدیوهای آموزشی، در پلتفرمهایی قرار دارند که ممکن است در معرض فیلترینگ باشند. دانشجویی که برای انجام پژوهش خود به یک ژورنال بینالمللی نیاز دارد، در صورت مواجهه با محدودیت، یا باید هزینههای گزافی برای ابزارهای دور زدن فیلتر متحمل شود یا از ادامه کار خود صرفنظر کند. اینترنت طبقاتی این مشکل را تشدید میکند، زیرا دسترسی آزاد ممکن است تنها به گروههای خاصی مانند اساتید دانشگاه محدود شود، در حالی که دانشجویان عادی از آن محروم میمانند. این امر شکاف آموزشی را افزایش داده و پیشرفت علمی کشور را کند میکند. تهدید امنیت و حریم خصوصییکی از پیامدهای اینترنت طبقاتی و فیلترینگ، افزایش خطرات امنیتی برای کاربران است. وقتی دسترسی آزاد محدود میشود، بسیاری از افراد به استفاده از ابزارهای غیررسمی مانند فیلترشکنها روی میآورند. این ابزارها اغلب ناامن بوده و خطر سرقت اطلاعات شخصی یا هک شدن را افزایش میدهند. در حالی که دسترسی آزاد و امن به اینترنت میتواند نیاز به این ابزارهای پرریسک را از بین ببرد و امنیت کاربران را تضمین کند. اینترنت طبقاتی و تقویت نابرابریشاید یکی از مهمترین اشکالات اینترنت طبقاتی، ترویج نابرابری در جامعه باشد. وقتی دسترسی به اینترنت بر اساس معیارهای خاص محدود میشود، حس تبعیض در میان شهروندان تقویت میگردد. این که گروهی به دلیل جایگاه خاص خود به منابعی دسترسی داشته باشند که برای دیگران در دسترس نیست، چه تفاوتی با دیگر اشکال تبعیض دارد؟ دسترسی برابر به اینترنت، به عنوان یک زیرساخت عمومی، باید برای همه تضمین شود. پیشنهادهایی برای بهبودبه جای اعمال محدودیتهای اینترنتی و اینترنت طبقاتی، میتوان رویکردهایی را در پیش گرفت که دسترسی همگانی به اینترنت را تقویت کند: تقویت زیرساختهای اینترنتی: سرمایهگذاری در بهبود سرعت و کیفیت اینترنت به جای هزینه برای فیلترینگ، میتواند دسترسی بهتری برای همه فراهم کند. حمایت از کسبوکارهای دیجیتال: ایجاد بستری که پلتفرمهای داخلی و خارجی بتوانند به طور منصفانه فعالیت کنند، به رشد اقتصاد دیجیتال کمک میکند. شفافیت در سیاستگذاری: هرگونه قانونگذاری در حوزه اینترنت باید با شفافیت کامل و با در نظر گرفتن نظرات همه اقشار جامعه انجام شود. سخن پایانیاینترنت طبقاتی و محدودیتهای اینترنتی نه تنها حقوق کاربران عادی را نقض میکند، بلکه به اقتصاد دیجیتال، آموزش و حس برابری در جامعه آسیب میرساند. در جهانی که اینترنت به یکی از مهمترین ابزارهای پیشرفت تبدیل شده، دسترسی آزاد و برابر به آن باید به عنوان یک حق همگانی به رسمیت شناخته شود. به جای ایجاد محدودیت، باید به سمت سیاستهایی حرکت کنیم که اینترنت را برای همه سریع، امن و در دسترس کند. این رویکرد نه تنها به نفع افراد است، بلکه به پیشرفت و توسعه پایدار کشور کمک خواهد کرد.
-
ابزارها و کتابخانههای ساخت رابط کاربری گرافیکی در زبان Rust
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیزبان برنامهنویسی Rust به دلیل ایمنی حافظه، عملکرد بالا، و قابلیتهای مدرن خود به یکی از محبوبترین زبانها برای توسعه نرمافزارهای سیستمی تبدیل شده است. اگرچه Rust در ابتدا برای برنامهنویسی سیستمی طراحی شده بود، اما در سالهای اخیر، ابزارها و کتابخانههای متعددی برای ساخت رابطهای کاربری گرافیکی (GUI) در این زبان توسعه یافتهاند. این مقاله به معرفی و بررسی مهمترین ابزارها و کتابخانههای موجود برای ایجاد رابطهای کاربری گرافیکی در Rust میپردازد و ویژگیها، مزایا، و معایب هر یک را مورد بحث قرار میدهد. چرا رابط کاربری گرافیکی در Rust؟Rust با ویژگیهایی مانند ایمنی حافظه، عدم استفاده از زبالهروب (Garbage Collector)، و عملکرد نزدیک به زبانهای سطح پایین مانند C++، گزینهای جذاب برای توسعه برنامههایی است که نیاز به رابط کاربری گرافیکی دارند. در مقایسه با زبانهایی مثل پایتون که کتابخانههای GUI بالغی مانند Tkinter یا PyQt دارند، اکوسیستم Rust در حوزه GUI هنوز در حال توسعه است. با این حال، جامعه فعال Rust و حمایت شرکتهایی مانند موزیلا باعث شده تا ابزارهای قدرتمندی برای این منظور در دسترس قرار گیرند. ساخت رابط کاربری گرافیکی در Rust میتواند برای پروژههایی که نیاز به عملکرد بالا، امنیت حافظه، و کنترل دقیق منابع دارند، بسیار مناسب باشد. از برنامههای دسکتاپ گرفته تا ابزارهای چندپلتفرمی، Rust امکان توسعه برنامههایی با رابط کاربری جذاب و کارآمد را فراهم میکند. معیارهای انتخاب کتابخانه GUIقبل از معرفی کتابخانهها، مهم است که معیارهای انتخاب یک کتابخانه GUI مناسب را در نظر بگیریم: عملکرد: کتابخانه باید با فلسفه Rust برای ارائه عملکرد بالا همخوانی داشته باشد. چندپلتفرمی بودن: پشتیبانی از سیستمعاملهای مختلف (ویندوز، مک، لینوکس) ضروری است. سادگی استفاده: رابط برنامهنویسی (API) باید کاربرپسند و همراستا با سینتکس Rust باشد. جامعه و پشتیبانی: وجود مستندات جامع و جامعه فعال برای رفع مشکلات اهمیت دارد. قابلیتهای گرافیکی: پشتیبانی از ویجتهای متنوع، انیمیشنها، و رندرینگ پیشرفته. اندازه و وابستگیها: کتابخانههای سبکتر با وابستگیهای کمتر برای پروژههای کوچک مناسبتر هستند. حالا به بررسی برخی از مهمترین کتابخانههای GUI در Rust میپردازیم. 1. DruidDruid یک فریمورک GUI متنباز است که به طور خاص برای Rust طراحی شده و بر عملکرد و سادگی تمرکز دارد. این کتابخانه توسط تیم توسعهدهنده Xi Editor ایجاد شده و برای ساخت برنامههای دسکتاپ چندپلتفرمی مناسب است. ویژگیها:معماری دادهمحور: Druid از الگوی دادهمحور (data-driven) استفاده میکند که در آن رابط کاربری به صورت واکنشی (reactive) به تغییرات دادهها پاسخ میدهد. پشتیبانی چندپلتفرمی: روی ویندوز، مک، و لینوکس به خوبی کار میکند. رندرینگ پیشرفته: از موتور رندرینگ Piet استفاده میکند که امکان رندرینگ دوبعدی با کیفیت بالا را فراهم میآورد. سبک و سریع: Druid تلاش میکند تا با حداقل سربار، عملکردی نزدیک به زبانهای سطح پایین ارائه دهد. مزایا:ادغام عالی با اکوسیستم Rust. مستندات مناسب و جامعه رو به رشد. مناسب برای برنامههای دسکتاپ با نیاز به رندرینگ گرافیکی پیشرفته. معایب:هنوز در مراحل اولیه توسعه است و ممکن است برخی ویژگیهای پیشرفته GUI را نداشته باشد. ویجتهای آماده محدودتری نسبت به فریمورکهای بالغ مانند Qt دارد. مثال استفاده:use druid::widget::{Button, Flex, Label}; use druid::{AppLauncher, LocalizedString, Widget, WindowDesc}; fn build_ui() -> impl Widget<u32> { let text = Label::new(|data: &u32, _env: &_| format!("شمارنده: {}", data)); let button = Button::new("افزایش").on_click(|_ctx, data, _env| *data += 1); Flex::column().with_child(text).with_child(button) } fn main() { let main_window = WindowDesc::new(build_ui()).title("برنامه ساده"); AppLauncher::with_window(main_window) .launch(0) .expect("خطا در راهاندازی"); }2. eguiegui یک کتابخانه GUI سبک و فوری (immediate mode) است که برای ساخت رابطهای کاربری ساده و سریع مناسب است. این کتابخانه به دلیل استفاده در ابزارهای گرافیکی و بازیها شناخته شده است. ویژگیها:حالت فوری: برخلاف حالتهای مبتنی بر ویجت (retained mode)، egui در هر فریم رابط کاربری را بازسازی میکند که این روش برای برنامههای پویا مناسب است. سبک و بدون وابستگی: نیازی به کتابخانههای سنگین خارجی ندارد. پشتیبانی از WebAssembly: امکان اجرای برنامههای GUI در مرورگر را فراهم میکند. ادغام با موتورهای بازی: به راحتی با کتابخانههایی مثل wgpu یا ggez ادغام میشود. مزایا:بسیار سبک و مناسب برای پروژههای کوچک یا ابزارهای توسعه. یادگیری آسان برای توسعهدهندگانی که با Rust آشنا هستند. مناسب برای برنامههای تعاملی و گرافیکی مانند ابزارهای ویرایشگر یا داشبورد. معایب:ویجتهای محدودتر نسبت به فریمورکهای سنتی. ممکن است برای برنامههای پیچیده دسکتاپ مناسب نباشد. مثال استفاده:use eframe::egui; fn main() -> Result<(), eframe::Error> { let options = eframe::NativeOptions::default(); eframe::run_simple_native("برنامه egui", options, |ctx, _frame| { egui::CentralPanel::default().show(ctx, |ui| { ui.heading("سلام، egui!"); if ui.button("کلیک کنید").clicked() { println!("دکمه کلیک شد!"); } }); }) }3. SlintSlint (که قبلاً به نام SixtyFPS شناخته میشد) یک فریمورک GUI چندپلتفرمی است که برای ساخت رابطهای کاربری جذاب و مدرن طراحی شده است. این کتابخانه از یک زبان توصیفی (DSL) برای تعریف رابط کاربری استفاده میکند. ویژگیها:زبان توصیفی: رابط کاربری با استفاده از یک سینتکس شبیه به QML تعریف میشود. پشتیبانی از WebAssembly: امکان اجرای برنامهها در مرورگر. عملکرد بالا: بهینهسازی شده برای دستگاههای با منابع محدود. پشتیبانی از انیمیشنها: قابلیت افزودن انیمیشنهای پیچیده به رابط کاربری. مزایا:رابط کاربری زیبا و مدرن با حداقل کدنویسی. مناسب برای برنامههای چندپلتفرمی و تعاملی. مستندات خوب و جامعه رو به رشد. معایب:نیاز به یادگیری زبان توصیفی Slint. هنوز به اندازه Qt یا GTK بالغ نیست. مثال استفاده:import { Button, VerticalBox } from "slint"; MainWindow { title: "برنامه Slint"; VerticalBox { Button { text: "کلیک کنید"; clicked => { println!("دکمه کلیک شد!"); } } } } 4. IcedIced یک کتابخانه GUI متنباز است که از معماری Elm الهام گرفته شده و برای ساخت برنامههای دسکتاپ و وب مناسب است. این کتابخانه بر سادگی و عملکرد تمرکز دارد. ویژگیها:معماری Elm: از الگوی پیاممحور برای مدیریت حالت استفاده میکند. چندپلتفرمی: پشتیبانی از ویندوز، مک، لینوکس، و WebAssembly. رندرینگ انعطافپذیر: از wgpu برای رندرینگ استفاده میکند. جامعه فعال: به سرعت در حال توسعه و بهبود است. مزایا:سینتکس تمیز و قابل فهم. مناسب برای توسعهدهندگانی که با معماریهای واکنشی آشنا هستند. پشتیبانی از WebAssembly برای برنامههای وب. معایب:ویجتهای محدودتر نسبت به فریمورکهای قدیمیتر. مستندات هنوز در حال تکمیل است. مثال استفاده:use iced::widget::{button, column, text}; use iced::{Element, Sandbox, Settings}; #[derive(Default)] struct Counter { value: i32, } #[derive(Debug, Clone)] enum Message { Increment, } impl Sandbox for Counter { type Message = Message; fn new() -> Self { Counter::default() } fn title(&self) -> String { String::from("برنامه Iced") } fn update(&mut self, message: Message) { match message { Message::Increment => self.value += 1, } } fn view(&self) -> Element<Message> { column![ text(format!("شمارنده: {}", self.value)), button("افزایش").on_press(Message::Increment), ] .into() } } fn main() -> iced::Result { Counter::run(Settings::default()) }5. GTK-rsGTK-rs یک اتصال (binding) برای کتابخانه GTK است که به زبان C نوشته شده و یکی از محبوبترین ابزارهای ساخت GUI در لینوکس است. این کتابخانه امکان استفاده از قابلیتهای GTK را در Rust فراهم میکند. ویژگیها:ویجتهای غنی: مجموعه گستردهای از ویجتهای آماده برای ساخت برنامههای پیچیده. پشتیبانی قوی از لینوکس: بهویژه در محیطهای گنوم. ادغام با Glade: امکان طراحی رابط کاربری با ابزارهای گرافیکی. مزایا:بسیار بالغ و پایدار. مناسب برای برنامههای دسکتاپ پیچیده. مستندات و جامعه قوی به دلیل قدمت GTK. معایب:وابستگی به کتابخانههای سیستمی که ممکن است نصب را پیچیده کند. کمتر با فلسفه Rust همخوانی دارد (به دلیل استفاده از C). 6. Qt (با اتصال Rust)Qt یک فریمورک قدرتمند و بالغ برای ساخت GUI است که از طریق اتصالهایی مانند qt-rs در Rust قابل استفاده است. این کتابخانه برای برنامههای دسکتاپ و موبایل مناسب است. ویژگیها:ویجتهای حرفهای: مجموعهای کامل از ابزارهای گرافیکی. چندپلتفرمی: پشتیبانی عالی از ویندوز، مک، لینوکس، و حتی موبایل. ابزارهای طراحی: امکان استفاده از Qt Designer برای طراحی رابط کاربری. معایب:اتصالهای Rust برای Qt هنوز در حال توسعه هستند و ممکن است ناپایدار باشند. وابستگی به کتابخانههای سنگین Qt. نتیجهگیریاکوسیستم Rust در زمینه توسعه رابط کاربری گرافیکی در حال رشد سریع است. کتابخانههایی مانند Druid، egui، Slint، و Iced هر یک ویژگیهای منحصربهفردی ارائه میدهند که بسته به نیاز پروژه میتوانند مناسب باشند. برای پروژههای سبک و سریع، egui و Iced گزینههای عالی هستند، در حالی که Druid و Slint برای برنامههای پیچیدهتر مناسباند. اگر به دنبال فریمورکهای بالغ هستید، GTK-rs و Qt میتوانند انتخابهای خوبی باشند، هرچند ممکن است با پیچیدگیهای بیشتری همراه باشند. توصیه میشود قبل از انتخاب کتابخانه، نیازهای پروژه خود را به دقت بررسی کنید و مستندات و نمونهکدهای هر کتابخانه را آزمایش کنید. با توجه به رشد سریع جامعه Rust، انتظار میرود که در آینده ابزارهای بیشتری برای توسعه GUI در این زبان ارائه شوند.
-
4 تیر ماه 1404
sina پاسخی ارسال کرد برای یک مطلب در شخصی و روزانهخب دیروز جنگ به ظاهر تموم شد و آتش بس برقرار شد. میانجیگری ایالات متحده، قطر و فشارهای پشت پرده از سوی چین و اتحادیه اروپا نهایتاً دو طرف رو پای میز یک آتشبس غیررسمی نشاند. دونالد ترامپ، با بیانیهای رسمی اعلام کرد که "آتشبس برقرار شده و دو طرف متعهد به توقف حملات شدهاند." با این حال، هیچ توافقنامهی مکتوب یا چارچوب دیپلماتیکی تاکنون منتشر نشده! طبق آمار رسمی و سازمانهای مستقل، تلفات ایرانیها بهصورت مختصر به شرح زیر است: وزارت بهداشت ایران: تا ۲۴ ژوئن: ۶۰۶ کشته و ۵٬۳۳۲ زخمی گروه Human Rights Activists (HRANA): بر اساس گزارش تا ۱۹ ژوئن: حدود ۶۳۹ کشته شامل نظامیان، نیروهای امنیتی و غیرنظامی منابع آمریکایی و انگلیسی: برآورد کلی: بین ۶۱۰ تا ۶۱۰+ کشته خلاصه که گلولهها فعلاً ساکت شدهاند، اما صدای تهدید هنوز خاموش نشده! برای منطقهای که از دیرباز درگیر زخمهای عمیق و تنشهای ریشهدار است، آتشبس معنای چندانی نداره
-
1 تیر ماه 1404
sina پاسخی ارسال کرد برای یک مطلب در شخصی و روزانهامروز تولدمه. رسماً وارد سی سالگی شدم... سال پیش تولدم یکی از بهترین روزهای زندگیم بود—کنار کسی که دوستش داشتم، با کلی حس خوب، لبخند و یه عالمه امید به آینده. اصلاً فکر نمیکردم فقط یه سال بعد، تولدم بیفته وسط جنگ، قطعی برق و اینترنت، دلنگرونی، و بدون حضور کسی که بودنش همهچی رو قشنگتر میکرد. زندگی گاهی اونقدر بیرحم و غیرقابل پیشبینی میشه که فقط میتونی نگاهش کنی و بگی: «واقعاً چرا؟» نمیدونم چی باید بنویسم، یا اصلاً چرا دارم مینویسم. شاید فقط دلم میخواد این روزها رو یهجایی ثبت کنم، یهجایی که بعداً که برگشتم و خوندم، یادم بیاد که گذشتم، که تموم شد، که هنوز زندهم. امیدوارم این وضعیت لعنتیِ جنگ خیلی زود مشخص بشه، بدون اینکه اتفاق بدتری بیفته، و اگه قراره چیزی تغییر کنه، حداقل به نفع همه باشه. امیدوارم تولد سال بعد، همین موقع، با کلی خبر خوب و حال بهتر بیام اینجا و برگردم به این پست بخندم؛ نه از غم، از سبک شدن. امیدوارم تا اون موقع، همهمون از این حال بد رد شده باشیم...
-
دفاع از خاک ایران فراتر از اختلافات داخلی است
sina پاسخی ارسال کرد برای یک مطلب در شخصی و روزانهدر شرایط فعلی، هر حمله نظامی بیمحابا به خاک ایران – یا هر کشور دیگری – نهتنها مغایر با اصول بنیادین حقوق بینالمللی است، بلکه منجر به قربانی شدن بیگناهان و نابودی زیرساختهای حیاتی میشود. حمله گسترده و پیشدستانهی اسرائیل به زیرساختهای هستهای و نظامی ایران در تاریخ جمعه ۱۳ ژوئن ۲۰۲۵ (۲۳ خرداد ۱۴۰۴)، که بهادعای رسانههای مختلف شامل بیش از ۲۰۰ هواپیمای جنگی و کشتار ده ها نفر از جمله فرماندهان ارشد نظامی و دانشمندان هستهای بوده، مصداق بارز تجاوز بوده و باید قویاً محکوم شود . ممکن است برخی با این توجیه پاسخ دهند که این حمله برای جلوگیری از توسعه سلاح هستهای بوده، اما این نگرانی هرچقدر هم معتبر باشد، نمیتواند مجوز مبنایی برای نقض حاکمیت ملی، شدتی از آسیب به مردم عادی و استفاده گسترده از ظرفیت نظامی باشد. تجربه نشان داده ضربه زدن به زیرساختها نه منجر به امنیت پایدار میشود و نه اسباب راهحل دیپلماتیک را فراهم میآورد. همواره باید این سؤال کلیدی را پرسید که آیا چنین اقدامی ارزش جان انسان بیگناه را داشت؟ حملات مشابه در گذشته حتی بهصورت نقطهای نیز توانسته آتش تنشها را کمتر کند، دشمنیها را تشدید کرده و خطری قریب الوقوع برای تبدیل شدن منطقه به «دورهای از جنگهای تمامعیار» به همراه داشته است . ایران در واکنش،بیش از ۱۰۰ پهپاد به سوی اسرائیل شلیک کرد؛ اتفاقی که نشان میدهد این تجاوز نهتنها باعث کاهش تهدید نشده بلکه احتمال انتقامجویی را افزایش داده است . ما ممکن است با نظام حاکم بر کشورمان موافق نباشیم، ممکن است اعتقاد داشته باشیم که ساختارهای داخلی نیازمند اصلاح و تحول هستند، اما این به هیچ وجه توجیهی برای پذیرش تجاوز خارجی نیست. اصل استقلال، تمامیت ارضی، و حق دفاع از ملت، از برجستهترین اصول قابل قبول در شکلگیری هر جامعهای هستند. اگر اجازه دهیم یک کشور ثالث با ادعای امنیت خود به خاک ایران حمله کند، چگونه میتوانیم مدعی دفاع از حقوق شهروندی، آزادی و حاکمیت ملی باشیم؟ بهعنوان شهروندی که با مفهوم عدالت اجتماعی و احترام متقابل بزرگ شدهایم، باید بگوییم: نه، هیچ حق اخلاقی برای تجویز تجاوز وجود ندارد؛ و بدون توقف و بازخواست حکومتهای متجاوز، هیچ تضمینی برای صلح و ثبات نخواهد بود. مهمتر از همه؛ جوانان، خانوادهها و نسلهای آینده ما نباید هزینه تصمیمات احساسی و نظامی دیگران را بپردازند. پس بیایید با زبان منطق و اصول حقوقبشری، صدای مخالفتمان را بالا ببریم: تجاوز اسرائیل به ایران، در هر شکل و بهانهای، باید محکوم شود – نه برای حمایت از دولت یا نظام فعلی، بلکه برای حفاظت از جان انسانها، حرمت حاکمیت ملی و شرافت انسانی.
-
کلیدواژه volatile در زبان C: یک ابزار قدرتمند و کمتر شناختهشده برای برنامهنویسی سطح پایین
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیزبان برنامهنویسی C به دلیل انعطافپذیری و کنترل سطح پایینی که به برنامهنویس ارائه میدهد، یکی از محبوبترین زبانها برای توسعه سیستمهای نهفته، درایورهای سختافزاری و نرمافزارهای بلادرنگ است. اما یکی از ویژگیهای این زبان که اغلب در آموزشهای ابتدایی کمتر به آن پرداخته میشود، کلیدواژه volatile است. این کلیدواژه، که ممکن است در نگاه اول ساده به نظر برسد، نقش مهمی در بهینهسازی و اطمینان از عملکرد صحیح برنامهها در سناریوهای خاص ایفا میکند. در این مقاله، به بررسی عمیق کلیدواژه volatile، کاربردهای آن، و دلایلی که هر برنامهنویس C باید با آن آشنا باشد، میپردازیم. volatile چیست و چرا اهمیت دارد؟کلیدواژه volatile در زبان C به کامپایلر اطلاع میدهد که مقدار یک متغیر ممکن است بهصورت غیرمنتظره تغییر کند، حتی اگر در کد برنامه به نظر نرسد که این متغیر تغییر میکند. این ویژگی بهویژه در برنامهنویسی سطح پایین، مانند کار با سختافزار، سیستمهای نهفته، یا برنامههای چندنخی، حیاتی است. بدون استفاده از volatile، کامپایلر ممکن است بهینهسازیهایی انجام دهد که منجر به رفتار نادرست برنامه شود. به عنوان مثال، فرض کنید متغیری دارید که مقدار آن توسط یک وقفه سختافزاری یا یک رشته (thread) دیگر تغییر میکند. اگر این متغیر با volatile مشخص نشده باشد، کامپایلر ممکن است فرض کند که مقدار آن ثابت است و بهینهسازیهایی مانند ذخیرهسازی مقدار در یک ثبات (register) یا حذف دسترسیهای مکرر به آن را انجام دهد. این کار میتواند باعث شود که تغییرات واقعی متغیر در حافظه نادیده گرفته شوند. کاربردهای اصلی volatile در زبان Cبرای درک بهتر اهمیت volatile، بیایید به چند سناریوی کاربردی کلیدی نگاه کنیم: 1. کار با سختافزار و رجیسترهای حافظهیکی از رایجترین کاربردهای volatile در برنامهنویسی سیستمهای نهفته است. در این سیستمها، متغیرها اغلب به رجیسترهای سختافزاری (مانند رجیسترهای ورودی/خروجی) نگاشت میشوند. این رجیسترها ممکن است توسط سختافزار بهصورت غیرمنتظره تغییر کنند. به مثال زیر توجه کنید: volatile int *hardware_register = (volatile int *)0x1000;در این کد، متغیر hardware_register به یک آدرس حافظه خاص اشاره دارد که ممکن است توسط سختافزار تغییر کند. استفاده از volatile به کامپایلر میگوید که هر بار که به این متغیر دسترسی پیدا میکند، باید مقدار آن را مستقیماً از حافظه بخواند و نه از ثباتهای داخلی CPU. 2. برنامهنویسی چندنخیدر برنامههای چندنخی، متغیرهایی که بین نخها به اشتراک گذاشته میشوند، ممکن است بهصورت غیرمنتظره تغییر کنند. اگر یک نخ مقداری را تغییر دهد، نخ دیگر باید به مقدار بهروز شده دسترسی داشته باشد. بدون volatile، کامپایلر ممکن است فرض کند که متغیر در یک نخ ثابت است و بهینهسازیهایی انجام دهد که باعث از دست رفتن تغییرات شود. برای مثال: volatile int shared_flag = 0; void thread1() { while (!shared_flag) { // منتظر تغییر پرچم } } void thread2() { shared_flag = 1; // تغییر پرچم }در این مثال، اگر shared_flag بهعنوان volatile تعریف نشود، کامپایلر ممکن است حلقه while را بهینه کند و تغییرات اعمالشده توسط نخ دوم را نادیده بگیرد. 3. مدیریت وقفهها (Interrupts)در سیستمهایی که از وقفههای سختافزاری استفاده میکنند، متغیرهایی که توسط روالهای سرویسدهی وقفه (ISR) تغییر میکنند، باید volatile باشند. این کار تضمین میکند که تغییرات این متغیرها به درستی توسط برنامه اصلی دیده شوند. به مثال زیر توجه کنید: volatile int interrupt_flag = 0; void ISR() { interrupt_flag = 1; } int main() { while (!interrupt_flag) { // منتظر وقفه } // ادامه پردازش }بدون volatile، کامپایلر ممکن است فرض کند که interrupt_flag هرگز تغییر نمیکند و حلقه را بهصورت بینهایت اجرا کند. نکات مهم در استفاده از volatileاستفاده از volatile نیازمند دقت است، زیرا استفاده نادرست از آن میتواند عملکرد برنامه را تحت تأثیر قرار دهد. در ادامه چند نکته کلیدی آورده شده است: استفاده بیش از حد ممنوع: استفاده غیرضروری از volatile میتواند مانع بهینهسازیهای مفید کامپایلر شود و عملکرد برنامه را کاهش دهد. تنها متغیرهایی که واقعاً ممکن است بهصورت غیرمنتظره تغییر کنند را volatile کنید. ترکیب با سایر کلیدواژهها: volatile میتواند با کلیدواژههایی مانند const ترکیب شود. به عنوان مثال، volatile const int نشاندهنده متغیری است که نمیتوان آن را در کد تغییر داد، اما ممکن است توسط عوامل خارجی (مثل سختافزار) تغییر کند. محدودیتها در چندنخی: volatile بهتنهایی برای همگامسازی نخها کافی نیست. برای مدیریت دسترسیهای همزمان، باید از ابزارهایی مانند قفلها (locks) یا موانع حافظه (memory barriers) استفاده کنید. تفاوت volatile با سایر مفاهیم مشابهبرخی ممکن است volatile را با مفاهیمی مانند atomic یا مکانیزمهای همگامسازی اشتباه بگیرند. volatile صرفاً به کامپایلر میگوید که بهینهسازیهای خاصی را انجام ندهد، اما تضمین نمیکند که عملیات روی متغیر بهصورت اتمیک (atomic) انجام شوند. برای عملیات اتمیک، باید از کتابخانههایی مانند stdatomic.h در C11 استفاده کنید. مثال عملی: پیادهسازی یک پرچم وقفهبرای درک بهتر، بیایید یک مثال عملی از استفاده volatile در یک سیستم نهفته ببینیم: #include <stdio.h> volatile int sensor_data = 0; void sensor_interrupt() { sensor_data++; // داده حسگر بهروزرسانی میشود } int main() { while (1) { if (sensor_data > 0) { printf("داده حسگر دریافت شد: %d\n", sensor_data); sensor_data = 0; } } return 0; }در این کد، متغیر sensor_data توسط یک وقفه بهروزرسانی میشود. اگر volatile استفاده نشود، ممکن است کامپایلر شرط if را بهینه کند و تغییرات sensor_data را نادیده بگیرد. چالشها و محدودیتهایکی از چالشهای استفاده از volatile این است که درک دقیق زمان استفاده از آن نیازمند تجربه است. برنامهنویسان تازهکار ممکن است بهاشتباه از آن استفاده کنند یا آن را نادیده بگیرند. همچنین، در برخی معماریهای خاص، ممکن است نیاز به تنظیمات اضافی (مانند موانع حافظه) باشد تا رفتار مورد انتظار تضمین شود. چرا volatile کمتر شناختهشده است؟با وجود اهمیت volatile، این کلیدواژه در آموزشهای ابتدایی C کمتر مورد توجه قرار میگیرد، زیرا کاربردهای آن بیشتر در زمینههای تخصصی مانند سیستمهای نهفته یا برنامهنویسی بلادرنگ دیده میشود. در برنامههای سادهتر، که نیازی به تعامل با سختافزار یا چندنخی نیست، این کلیدواژه کمتر به کار میرود. اما برای برنامهنویسان حرفهای که با سیستمهای پیچیده کار میکنند، volatile یکی از ابزارهای کلیدی است. نتیجهگیریکلیدواژه volatile در زبان C یکی از ابزارهای قدرتمند برای مدیریت متغیرهایی است که ممکن است بهصورت غیرمنتظره تغییر کنند. این ویژگی در سناریوهایی مانند برنامهنویسی سختافزار، سیستمهای نهفته، و برنامههای چندنخی نقش حیاتی دارد. با درک صحیح و استفاده مناسب از volatile، میتوانید از رفتار غیرمنتظره برنامهها جلوگیری کنید و عملکرد قابل اعتمادی را تضمین کنید. اگر به برنامهنویسی سطح پایین علاقهمند هستید، یادگیری و تسلط بر این کلیدواژه میتواند شما را یک قدم به حرفهای شدن نزدیکتر کند. برای مطالعه بیشتر، پیشنهاد میکنم به استانداردهای زبان C (مانند C11) و مستندات کامپایلر خود (مثل GCC یا Clang) مراجعه کنید تا با جزئیات بیشتری از نحوه عملکرد volatile در پروژههای خود آشنا شوید.
-
sina عکس نمایه خود را تغییر داد
-
معرفی ویژگی Readonly Classes در PHP 8.2
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیدر PHP 8.1، ویژگی Readonly Properties معرفی شد که به توسعهدهندگان اجازه میداد متغیرهای یک کلاس را بهگونهای تعریف کنند که فقط یکبار مقداردهی شوند و بعد از آن غیرقابل تغییر باشند. این قابلیت برای جلوگیری از تغییرات ناخواسته در متغیرها و افزایش ایمنی کد بسیار مفید بود. اما PHP 8.2 یک قدم فراتر رفت و مفهوم Readonly Classes را معرفی کرد. با این ویژگی، میتوانید یک کلاس را بهصورت کامل فقط خواندنی تعریف کنید، به این معنا که تمام متغیرهای (Properties) آن کلاس بهصورت پیشفرض فقط خواندنی خواهند بود، بدون نیاز به تعریف جداگانه برای هر متغیر. برای درک بهتر، بیایید یک مثال ساده را بررسی کنیم: readonly class UserProfile { public function __construct( public string $username, public string $email, public int $age ) {} }در این کد، کل کلاس UserProfile بهعنوان یک کلاس فقط خواندنی تعریف شده است. این یعنی متغیرهای username، email و age همگی بهصورت خودکار فقط خواندنی هستند و نمیتوان بعد از مقداردهی اولیه، آنها را تغییر داد. اگر سعی کنید مقداری را تغییر دهید، مثلاً: $profile = new UserProfile('ali', 'ali@example.com', 30); $profile->username = 'reza'; // خطا!مفسر PHP خطایی با این مضمون تولید میکند: "Cannot modify readonly property UserProfile::$username". این ویژگی تضمین میکند که دادههای کلاس شما پس از ایجاد نمونه (Instantiation) تغییر نمیکنند و به این ترتیب، یک لایه امنیتی و پایداری به کد اضافه میشود. چرا Readonly Classes مهم است؟شاید با خودتان فکر کنید که این ویژگی خیلی هم جدید نیست و میتوانستید با استفاده از Readonly Properties در PHP 8.1 به نتیجه مشابهی برسید. اما تفاوت اصلی در سادگی و خوانایی کد است. وقتی یک کلاس را بهصورت readonly تعریف میکنید، دیگر نیازی نیست که برای هر متغیر کلمه کلیدی readonly را بهصورت جداگانه بنویسید. این کار نه تنها کد را تمیزتر میکند، بلکه از خطاهای احتمالی ناشی از فراموش کردن افزودن readonly به یک متغیر جلوگیری میکند. علاوه بر این، Readonly Classes به شما کمک میکند تا قصد طراحی (Design Intent) خود را بهوضوح به سایر توسعهدهندگان نشان دهید. وقتی کلاسی را فقط خواندنی تعریف میکنید، به تیم خود (یا حتی خود آیندهتان!) اعلام میکنید که این کلاس قرار است بهعنوان یک موجودیت تغییرناپذیر (Immutable) عمل کند. این موضوع در پروژههای بزرگ که چندین توسعهدهنده روی کد کار میکنند، بسیار ارزشمند است. کاربردهای عملی Readonly Classesحالا بیایید به چند سناریوی واقعی نگاه کنیم که در آنها Readonly Classes میتواند بدرخشد: 1. مدلهای دادهای (Data Models)یکی از رایجترین کاربردهای Readonly Classes در تعریف مدلهای دادهای است که قرار نیست پس از مقداردهی اولیه تغییر کنند. فرض کنید در حال توسعه یک سیستم مدیریت کاربران هستید. میتوانید از یک کلاس فقط خواندنی برای ذخیره اطلاعات پروفایل کاربر استفاده کنید: readonly class User { public function __construct( public int $id, public string $name, public string $email ) {} }این کلاس تضمین میکند که اطلاعات کاربر، مثل شناسه یا ایمیل، پس از ایجاد نمونه تغییر نمیکنند. این موضوع در برنامههایی که نیاز به حفظ یکپارچگی دادهها دارند، مثل سیستمهای مالی یا مدیریت هویت، بسیار مفید است. 2. DTOها (Data Transfer Objects)Readonly Classes برای پیادهسازی اشیاء انتقال داده (DTO) بسیار مناسب هستند. DTOها معمولاً برای انتقال داده بین لایههای مختلف یک برنامه (مثلاً بین لایههای دیتابیس و API) استفاده میشوند. با استفاده از یک کلاس فقط خواندنی، میتوانید مطمئن شوید که دادههای منتقلشده در طول مسیر تغییر نمیکنند: readonly class OrderDTO { public function __construct( public int $orderId, public float $totalAmount, public string $status ) {} }در اینجا، شیء OrderDTO بهعنوان یک بسته دادهای عمل میکند که اطلاعات سفارش را بدون امکان تغییر منتقل میکند. 3. افزایش امنیت در برنامههای وبیکی از چالشهای رایج در توسعه وب، جلوگیری از تغییرات ناخواسته در دادهها به دلیل خطاهای برنامهنویسی یا حملات است. با استفاده از Readonly Classes، میتوانید اطمینان حاصل کنید که دادههای حساس، مثل تنظیمات پیکربندی یا اطلاعات کاربر، بهصورت تصادفی یا مخرب تغییر نمیکنند. 4. بهبود عملکرد در پروژههای بزرگوقتی کلاسی بهصورت فقط خواندنی تعریف میشود، مفسر PHP میتواند بهینهسازیهای بیشتری روی آن اعمال کند، زیرا میداند که متغیرهای این کلاس تغییر نخواهند کرد. این موضوع در پروژههای بزرگ که عملکرد اهمیت زیادی دارد، میتواند تأثیر قابلتوجهی داشته باشد. محدودیتها و نکات قابل توجههرچند Readonly Classes ویژگی قدرتمندی است، اما محدودیتهایی هم دارد که باید به آنها توجه کنید: عدم امکان تغییر پس از مقداردهی: وقتی کلاسی را فقط خواندنی تعریف میکنید، هیچیک از متغیرهای آن قابل تغییر نیستند، حتی اگر در شرایط خاصی نیاز به تغییر داشته باشید. در چنین مواردی، باید از یک کلاس معمولی استفاده کنید یا منطق برنامه را بازطراحی کنید. محدودیت در ارثبری: اگر یک کلاس فقط خواندنی را به ارث ببرید، کلاس فرزند هم باید فقط خواندنی باشد. این موضوع میتواند در برخی طراحیهای پیچیده محدودیت ایجاد کند. سازگاری با نسخههای قدیمی: این ویژگی فقط در PHP 8.2 و بالاتر در دسترس است. اگر پروژه شما نیاز به پشتیبانی از نسخههای قدیمیتر PHP دارد، باید راهحلهای جایگزین (مثل Readonly Properties یا Getterها) را در نظر بگیرید. چگونه از Readonly Classes استفاده کنیم؟برای استفاده از این ویژگی، کافی است کلمه کلیدی readonly را قبل از تعریف کلاس قرار دهید. همچنین، بهتر است متغیرهای عمومی (Public Properties) را در Constructor تعریف کنید تا مقداردهی اولیه بهصورت شفاف انجام شود. مثال زیر یک نمونه کاملتر را نشان میدهد: readonly class Product { public function __construct( public string $name, public float $price, public int $stock ) {} public function getSummary(): string { return "Product: {$this->name}, Price: {$this->price}, Stock: {$this->stock}"; } } $product = new Product('Laptop', 999.99, 10); echo $product->getSummary(); // خروجی: Product: Laptop, Price: 999.99, Stock: 10در این مثال، کلاس Product نه تنها دادهها را بهصورت فقط خواندنی نگه میدارد، بلکه با استفاده از متد getSummary، میتوانید منطق نمایش دادهها را بهراحتی پیادهسازی کنید. مقایسه با سایر زبانهاویژگیهایی مثل Readonly Classes در زبانهای دیگر هم وجود دارند. برای مثال، در جاوا میتوانید از کلمه کلیدی final برای متغیرها یا کلاسها استفاده کنید تا تغییرناپذیر شوند. در پایتون هم با استفاده از کتابخانههایی مثل dataclasses و ویژگی frozen=True میتوانید رفتار مشابهی را پیادهسازی کنید. اما آنچه PHP را متمایز میکند، سادگی و یکپارچگی این ویژگی با سینتکس موجود است که آن را برای توسعهدهندگان وب بسیار کاربردی میکند. نتیجهگیریویژگی Readonly Classes در PHP 8.2 شاید در نگاه اول یک تغییر کوچک به نظر برسد، اما تأثیر آن در نوشتن کدهای تمیز، امن و قابل نگهداری قابلتوجه است. این ویژگی به شما کمک میکند تا دادههای تغییرناپذیر را بهسادگی مدیریت کنید، از خطاهای ناخواسته جلوگیری کنید و قصد طراحی خود را بهوضوح به سایر توسعهدهندگان منتقل کنید. اگر در حال کار روی یک پروژه جدید هستید یا قصد دارید پروژه موجودتان را به PHP 8.2 ارتقا دهید، حتماً این ویژگی را امتحان کنید. با کمی تمرین، متوجه خواهید شد که Readonly Classes میتواند به یکی از ابزارهای اصلی شما در توسعه وب تبدیل شود.
-
نگاهی به ماکرو ها در زبان برنامهنویسی Rust
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیماکروها (Macros) یکی از ویژگیهای قدرتمند زبان Rust هستند که به شما امکان میدهند کدهایی بنویسید که کدهای دیگری تولید کنند. این ویژگی در مواردی مانند حذف کد تکراری، ایجاد DSLهای خاصمنظوره، یا پیادهسازی metaprogramming patterns بسیار کاربردی است. در این مقاله با انواع ماکروها در Rust، مزایا، معایب و نحوهی استفادهی صحیح از آنها آشنا میشویم. چرا ماکرو؟ماکروها زمانی بهکار میآیند که کد شما دارای الگوهای تکراری زیادی باشد که با فانکشنها بهراحتی قابل بازنویسی نیستند. برخلاف توابع، ماکروها قبل از مرحلهی کامپایل اجرا میشوند و میتوانند ساختارهای مختلفی از کد را تولید کنند. بهعبارت دیگر، ماکروها به شما اجازه میدهند تا در مرحلهی کامپایل کد تولید کنید. انواع ماکروها در RustRust از دو نوع اصلی ماکرو پشتیبانی میکند: 1. Declarative Macros (با استفاده از macro_rules!)این نوع ماکروها که با macro_rules! تعریف میشوند، از الگوهای تطبیقی برای تولید کد استفاده میکنند. این همان چیزی است که بیشتر توسعهدهندگان Rust در ابتدا با آن برخورد میکنند. macro_rules! say_hello { () => { println!("Hello!"); }; } fn main() { say_hello!(); }ماکرو بالا هر بار که فراخوانی شود، کدی تولید میکند که println! را اجرا میکند. کاربرد آن بسیار شبیه توابع است، اما با این تفاوت که در مرحلهی pre-processing اجرا میشود. از قابلیتهای پیشرفتهتر macro_rules! میتوان به الگوهای چندگانه، تکرار با * و +، و پترنمچینگ اشاره کرد. مثلاً: macro_rules! create_functions { ($($name:ident),*) => { $( fn $name() { println!("You called {:?}!", stringify!($name)); } )* } } create_functions!(foo, bar, baz);2. Procedural Macrosماکروهای پردازشی نوع پیشرفتهتری از ماکروها هستند که امکان اعمال تغییر روی AST (Abstract Syntax Tree) را فراهم میکنند. این ماکروها به سه دسته تقسیم میشوند: - #[derive]برای تولید کد بهصورت خودکار روی ساختارها. مثلاً: #[derive(Debug, Clone, PartialEq)] struct Point { x: i32, y: i32, }- Attribute-like Macrosماکروهایی که با علامت #[] روی آیتمهایی مثل تابع یا ساختار اعمال میشوند: #[route(GET, "/")] fn index() {}- Function-like Macrosشبیه به macro_rules! ولی با انعطاف بیشتر. مثلاً: my_macro!(...);این نوع ماکروها معمولاً در crate جداگانهای نوشته میشوند و از proc_macro استفاده میکنند. نحوهی نوشتن یک ماکرو Procedural سادهنوشتن ماکروهای procedural نیاز به استفاده از crate proc-macro دارد. بهطور معمول، این کدها در crate جداگانه با نوع proc-macro = true تعریف میشوند. extern crate proc_macro; use proc_macro::TokenStream; #[proc_macro] pub fn make_answer(_item: TokenStream) -> TokenStream { "fn answer() -> u32 { 42 }".parse().unwrap() }مزایای استفاده از ماکروهاکاهش کد تکراری: میتوانید با چند خط ماکرو، صدها خط کد مشابه تولید کنید. افزایش خوانایی در برخی موارد: ماکروهای خوب طراحیشده میتوانند کدی شفافتر ارائه دهند. ایجاد DSL: ماکروها امکان ساخت syntax سفارشی را فراهم میکنند. معایب ماکروهاعیبیابی دشوار: خطاهای کامپایل در ماکروها ممکن است گنگ و پیچیده باشند. کاهش وضوح کد: اگر بیشازحد از ماکرو استفاده شود، کد میتواند مبهم و غیرقابلخواندن شود. افزایش زمان کامپایل: چون ماکروها قبل از کامپایل اجرا میشوند، میتوانند زمان build را افزایش دهند. چه زمانی ماکرو ننویسیم؟اگر میتوانید با یک تابع ساده یا generic مشکل را حل کنید، ماکرو ننویسید. ماکروها باید آخرین گزینه باشند، نه اولین. آنها ابزاری قدرتمند ولی دو لبهاند: هم میتوانند کدتان را زیباتر کنند، هم آن را به یک هیولای غیرقابل نگهداری تبدیل کنند. مثال کاربردی: DSL برای تستهافرض کنید میخواهید یک DSL برای تست بنویسید: macro_rules! test_case { ($name:ident, $body:block) => { #[test] fn $name() $body }; } test_case!(simple_addition, { assert_eq!(2 + 2, 4); });نتیجهگیریماکروها در Rust ابزاری بسیار قدرتمند برای تولید کد هستند که با درک صحیح و استفادهی هوشمندانه میتوانند کدهای پیچیده را ساده کنند. اما باید با احتیاط از آنها استفاده کرد، چرا که سوءاستفاده از آنها منجر به ایجاد کدی میشود که نه تنها نگهداری آن سخت است، بلکه ممکن است شما را در کامپایلهای نیمساعته غرق کند.
-
همهچیز درباره فایل Cargo.toml در Rust: راهنمای جامع
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیدر زبان برنامهنویسی Rust، ابزار Cargo نقش کلیدی در مدیریت پروژهها ایفا میکند. این ابزار قدرتمند به توسعهدهندگان کمک میکند تا فرآیند ساخت، مدیریت وابستگیها و انتشار پروژهها را بهسادگی انجام دهند. در مرکز هر پروژهای که با Cargo مدیریت میشود، فایلی به نام Cargo.toml قرار دارد. این فایل، که به نوعی تنظیمات اصلی پروژه را در خود جای داده، مشخص میکند که پروژه چگونه باید ساخته شود، چه وابستگیهایی دارد و چه ویژگیهایی باید فعال شوند. در این مقاله، قصد داریم بهصورت جامع و دقیق تمام جنبههای فایل Cargo.toml را بررسی کنیم تا بتوانید با تسلط بیشتری از آن در پروژههای خود استفاده کنید. فایل Cargo.toml چیست و چه اهمیتی دارد؟فایل Cargo.toml در واقع فایل پیکربندی اصلی پروژههای Rust است که با استفاده از ابزار Cargo مدیریت میشوند. این فایل در ریشه پروژه قرار میگیرد و اطلاعاتی مانند نام پروژه، نسخه، وابستگیها و تنظیمات مختلف را در خود نگه میدارد. فرمت این فایل بر پایه TOML (مخفف Tom's Obvious, Minimal Language) است که یک زبان ساده و خوانا برای تعریف تنظیمات محسوب میشود. هر زمان که دستوری مانند cargo build یا cargo run اجرا میکنید، Cargo ابتدا به سراغ این فایل میرود تا اطلاعات لازم را از آن بخواند. به همین دلیل، درک ساختار و قابلیتهای این فایل برای هر توسعهدهنده Rust ضروری است. ساختار کلی فایل Cargo.tomlیک فایل Cargo.toml ساده ممکن است به این شکل باشد: [package] name = "my_project" version = "0.1.0" edition = "2021" [dependencies] serde = "1.0"در این مثال، دو بخش اصلی دیده میشود: بخش [package] که اطلاعات پایه پروژه را مشخص میکند و بخش [dependencies] که وابستگیهای پروژه را تعریف میکند. اما این تنها بخش کوچکی از قابلیتهای این فایل است. در ادامه، تمام بخشها و فیلدهای ممکن را بهصورت دقیق بررسی خواهیم کرد. بخش [package]: اطلاعات پایه پروژهبخش [package] شامل اطلاعات اصلی پروژه است که برای شناسایی و مدیریت آن استفاده میشود. فیلدهای مهم این بخش عبارتاند از: name: نام پروژه را مشخص میکند. این نام باید منحصربهفرد باشد، بهخصوص اگر قصد دارید پروژه را در crates.io منتشر کنید (مثال: "my_project"). version: نسخه پروژه، که معمولاً از فرمت Semantic Versioning پیروی میکند (مثال: "0.1.0"). edition: نسخه ادیشن Rust که پروژه از آن استفاده میکند (مانند "2021", "2018" یا "2015"). این فیلد مشخص میکند که کد شما با کدام مجموعه از قوانین و ویژگیهای Rust سازگار است. authors: فهرست نویسندگان پروژه (مثال: ["Sina Jalalvandi <sina@example.com>"]). description: توضیحی کوتاه درباره پروژه، که در صورت انتشار در crates.io نمایش داده میشود. license: نوع مجوز پروژه (مانند "MIT" یا "Apache-2.0"). repository: آدرس مخزن پروژه (مثلاً لینک گیتهاب). homepage: آدرس وبسایت پروژه (در صورت وجود). keywords: کلمات کلیدی مرتبط با پروژه برای جستجو در crates.io (مثال: ["web", "rust", "api"]). categories: دستهبندیهای پروژه (مثال: ["web-development", "data-structures"]). readme: مسیر فایل README پروژه (مثال: "README.md") که در زمان انتشار استفاده میشود. rust-version: حداقل نسخه Rust موردنیاز برای پروژه (مثال: "1.60")؛ این فیلد اختیاری است. یک نمونه کاملتر از بخش [package]: [package] name = "cool_app" version = "0.2.0" edition = "2021" authors = ["Sara Ahmadi <sara@example.com>"] description = "یه برنامه ساده برای تست Rust" license = "MIT" repository = "https://github.com/sara/cool_app" homepage = "https://sara.example.com/cool_app" keywords = ["rust", "test", "app"] categories = ["development-tools"] rust-version = "1.65" بخش [dependencies]: تعریف وابستگیهابخش [dependencies] برای مشخص کردن پکیجهای خارجی (crates) موردنیاز پروژه استفاده میشود. میتوانید نسخه دقیق یا بازهای از نسخهها را برای هر وابستگی تعیین کنید. چند روش رایج برای تعریف وابستگیها: نسخه ساده: مانند serde = "1.0" که نسخه 1.0 از crate موردنظر را مشخص میکند. بازه نسخه: مانند serde = ">1.0, <2.0" که هر نسخهای بین 1.0 و 2.0 را شامل میشود. با ویژگیها (features): اگر crate موردنظر قابلیتهای اختیاری داشته باشد، میتوانید آنها را فعال کنید: [dependencies] serde = { version = "1.0", features = ["derive"] }مسیر محلی: اگر crate در سیستم شما باشد: [dependencies] my_local_crate = { path = "../my_local_crate" }مخزن گیت: برای استفاده مستقیم از یک مخزن گیت: [dependencies] some_crate = { git = "https://github.com/user/some_crate" }بخش [dev-dependencies]: وابستگیهای توسعهاین بخش برای وابستگیهایی است که فقط در مرحله توسعه و تست استفاده میشوند و در نسخه نهایی پروژه (هنگام اجرای cargo build --release) وارد نمیشوند. مثال: [dev-dependencies] assert_approx_eq = "1.1"بخش [build-dependencies]: وابستگیهای ساختاگر پروژه شما از اسکریپت ساخت (build script) استفاده میکند، وابستگیهای موردنیاز آن را میتوانید در این بخش تعریف کنید: [build-dependencies] cc = "1.0"بخش [features]: قابلیتهای اختیاریبخش [features] به شما امکان میدهد قابلیتهای اختیاری برای پروژه تعریف کنید که کاربران بتوانند آنها را فعال یا غیرفعال کنند. مثال: [features] default = ["logging"] logging = ["log"] extra = []در این مثال، default مشخص میکند که ویژگی logging بهصورت پیشفرض فعال باشد. ویژگی extra نیز تعریف شده اما فعلاً وابستگیای ندارد. بخش [lib]: تنظیمات کتابخانهاگر پروژه شما یک کتابخانه (library) است، میتوانید تنظیمات آن را در این بخش مشخص کنید: name: نام کتابخانه (در صورتی که با نام پکیج متفاوت باشد). path: مسیر فایل اصلی کتابخانه (پیشفرض: src/lib.rs). crate-type: نوع خروجی کتابخانه (مانند "cdylib" برای کتابخانههای سازگار با C). مثال: [lib] name = "my_lib" path = "src/my_lib.rs" crate-type = ["rlib"]بخش [[bin]]: تنظیمات فایلهای اجراییاگر پروژه شما شامل برنامههای اجرایی (binary) است، میتوانید چندین فایل اجرایی را در این بخش تعریف کنید: [[bin]] name = "my_app" path = "src/main.rs" [[bin]] name = "another_app" path = "src/another.rs"بخش [profile]: تنظیمات بهینهسازیاین بخش برای تنظیم نحوه بهینهسازی پروژه در مراحل مختلف ساخت استفاده میشود. سه پروفایل اصلی وجود دارد: [profile.dev]: برای مرحله توسعه (با دیباگ فعال). [profile.release]: برای نسخه نهایی (بهینهسازی بالا). [profile.test]: برای تستها. مثال: [profile.release] opt-level = 3 # حداکثر بهینهسازی debug = falseبخش [workspace]: مدیریت چند پروژهاگر چندین پروژه مرتبط دارید، میتوانید آنها را در یک Workspace مدیریت کنید: [workspace] members = ["crate1", "crate2"] بخش [badges]: نمایش وضعیت پروژهبخش [badges] در فایل Cargo.toml به شما امکان میدهد وضعیت پروژه را بهصورت بصری و با استفاده از برچسبهای کوچک (badges) نمایش دهید. این برچسبها معمولاً در صفحه پروژه در crates.io یا در مستندات (مثلاً README گیتهاب) نشان داده میشوند و اطلاعاتی درباره وضعیت توسعه، تستها یا کیفیت پروژه به کاربران ارائه میدهند. استفاده از بجها میتواند پروژه شما را حرفهایتر نشان دهد و اعتماد کاربران را جلب کند. بجهای رایجدر ادامه، چند نمونه از بجهای رایجی که میتوانید در این بخش تعریف کنید، آورده شده است: maintenance: این بج وضعیت نگهداری پروژه را نشان میدهد. مقادیر ممکن برای آن عبارتاند از: "actively-developed": پروژه در حال توسعه فعال است. "passively-maintained": پروژه بهصورت غیرفعال نگهداری میشود. "as-is": پروژه بدون تغییر ارائه شده است. "experimental": پروژه آزمایشی است. "deprecated": پروژه منسوخ شده است. مثال: [badges] maintenance = { status = "actively-developed" }codecov: برای نمایش پوشش تست (code coverage) پروژه، اگر از سرویسی مثل Codecov استفاده میکنید. مثال: [badges] codecov = { repository = "user/repo", branch = "main", service = "github" }بجهای دیگر: بجهای دیگری مانند travis-ci (برای Travis CI)، circle-ci (برای CircleCI)، یا is-it-maintained-issue-resolution (برای نمایش میانگین زمان حل مسائل) نیز وجود دارند که بسته به نیاز پروژه میتوانید از آنها استفاده کنید. نکات مهم درباره بجهامحدودیت نمایش: همه بجها در crates.io نمایش داده نمیشوند. برای مثال، بج maintenance در crates.io نشان داده میشود، اما بجهای مربوط به CI/CD (مانند github-actions) بیشتر در README گیتهاب استفاده میشوند. تنظیمات اضافی: برای بجهای مربوط به CI/CD یا پوشش تست، باید ابتدا سرویس مربوطه (مثلاً GitHub Actions یا Codecov) را در پروژه خود تنظیم کرده باشید. نمایش در README: برای نمایش بجها در README، میتوانید از لینکهای مستقیم بج (مثلاً از shields.io یا خود سرویس) استفاده کنید. بهعنوان مثال: استفاده از بجها نهتنها اطلاعات مفیدی به کاربران ارائه میدهد، بلکه نشاندهنده توجه شما به کیفیت و نگهداری پروژه است. نکات تکمیلی و کاربردیفایل Cargo.lock: این فایل همراه با Cargo.toml ایجاد میشود و نسخه دقیق وابستگیها را قفل میکند. برای پروژههای اجرایی توصیه میشود آن را در گیت نگه دارید، اما برای کتابخانهها معمولاً نیازی نیست. دستورات مفید: میتوانید از cargo check برای بررسی سریع پروژه یا از cargo update برای بهروزرسانی وابستگیها استفاده کنید. فیلدهای سفارشی: امکان افزودن فیلدهای سفارشی با پیشوند metadata وجود دارد (مثال: [package.metadata.docs]). حرف آخرفایل Cargo.toml یکی از مهمترین اجزای هر پروژه Rust است که با ابزار Cargo مدیریت میشود. این فایل با ساختار ساده اما قدرتمند خود، امکان مدیریت پروژه، وابستگیها و تنظیمات مختلف را فراهم میکند. در این مقاله، تمام بخشها و قابلیتهای این فایل را بررسی کردیم تا بتوانید با اطمینان بیشتری از آن در پروژههای خود استفاده کنید. اگر سؤال یا نکتهای در این زمینه دارید، خوشحال میشوم در بخش نظرات با شما در میان بگذارم.
-
سندروم ایمپاستر بین برنامهنویسها و مهندسهای نرمافزار: چرا همیشه فکر میکنیم به اندازه کافی خوب نیستیم؟
sina پاسخی ارسال کرد برای یک مطلب در مطالب علمی و اطلاعات عمومیسندروم ایمپاستر یا همون حس جعل هویت، یه موضوع خیلی رایج بین برنامهنویسها و مهندسهای نرمافزاره که شاید خودمون هم گاهی نفهمیم داریم باهاش دستوپنجه نرم میکنیم. فکرش رو بکن: ساعتها کد زدی، پروژه رو به موقع تحویل دادی و حتی تونستی باگهای پیچیده رو حل کنی، ولی هنوز یه صدای کوچیک توی سرت میگه: «تو فقط شانسی این کار رو کردی، بالاخره یه روز همه میفهمن که تو به اندازه کافی خوب نیستی.» اگه این حس برات آشناست، بدون که تنها نیستی. توی این مقاله قراره با هم نگاه عمیقتری به سندروم ایمپاستر بندازیم، ببینیم چرا توی دنیای برنامهنویسی اینقدر شایعه و چطور میتونیم باهاش کنار بیایم یا حتی ازش به نفع خودمون استفاده کنیم. سندروم ایمپاستر چیه و چرا برنامهنویسها رو هدف گرفته؟سندروم ایمپاستر یه حس روانشناختیه که باعث میشه آدما موفقیتهاشون رو به شانس، زمانبندی خوب یا حتی اشتباه بقیه نسبت بدن، نه به توانایی و تلاش خودشون. حالا چرا توی دنیای برنامهنویسی و مهندسی نرمافزار اینقدر این حس قویه؟ یه دلیلش اینه که این حوزه همیشه در حال تغییره. یه روز داری با یه فریمورک جدید کار میکنی، فردا یه تکنولوژی دیگه میاد که انگار همهچیز رو از نو باید یاد بگیری. این سرعت تغییرات باعث میشه خیلی از برنامهنویسها فکر کنن که همیشه یه پله عقبتر از بقیهان. یه چیز دیگه هم هست: فرهنگ مقایسه توی این صنعت. توی شبکههای اجتماعی مثل توییتر یا لینکدین، مدام میبینیم که فلان برنامهنویس یه پروژه خفن رو توی دو روز تموم کرده یا یه نفر دیگه توی ۲۵ سالگی مدیر فنی یه شرکت بزرگ شده. این مقایسهها باعث میشه خودمون رو زیر سؤال ببریم و فکر کنیم که «من چرا هنوز اونجا نیستم؟» نشانههای سندروم ایمپاستر توی زندگی یه برنامهنویسشاید برات پیش اومده که یه پروژه رو با موفقیت تموم کنی، ولی به جای اینکه به خودت افتخار کنی، بشینی فکر کنی که «اگه بیشتر وقت گذاشته بودم، بهتر نمیشد؟» یا مثلاً موقع کد زدن، مدام از خودت بپرسی که «اگه همکارم این کد رو ببینه، فکر نمیکنه خیلی مبتدیام؟» اینا همشون نشونههای سندروم ایمپاستره. بیایم چند تا از این نشانهها رو با هم مرور کنیم: ترس از لو رفتن: همیشه فکر میکنی که یه روز بقیه میفهمن تو اون آدم باهوشی که فکر میکنن نیستی. کم اهمیت دونستن موفقیتها: مثلاً میگی «این پروژه که چیزی نبود، هرکی دیگه هم بود میتونست انجامش بده.» فشار برای کامل بودن: اگه کدت ۱۰۰٪ بینقص نباشه، حس میکنی شکست خوردی. خودت رو با بقیه مقایسه میکنی: مدام خودت رو با برنامهنویسهای دیگه که به نظرت موفقترن مقایسه میکنی و حس میکنی به گرد پاشون هم نمیرسی. چرا برنامهنویسها بیشتر درگیر این حس میشن؟یه لحظه فکر کن به محیط کار یه برنامهنویس: ددلاینهای فشرده، پروژههای پیچیده و انتظاراتی که گاهی از واقعیت خیلی دورن. توی این موقعیتها، حتی اگه کارمون رو خوب انجام بدیم، ممکنه فکر کنیم که فقط داریم ادای یه برنامهنویس حرفهای رو درمیآریم. یه دلیل دیگه هم اینه که توی برنامهنویسی، همیشه یه راه حل «بهتر» وجود داره. مثلاً کدت کار میکنه، ولی یه نفر میگه «اگه از این الگوریتم استفاده کرده بودی، بهینهتر بود.» این جور بازخوردها، حتی اگه سازنده باشن، میتونن حس ناکافی بودن رو تقویت کنن. یه موضوع دیگه هم هست: خیلی از برنامهنویسها خودشون یاد گرفتن که چطور کد بزنن. این یعنی ممکنه مدرک رسمی نداشته باشن و همین باعث بشه فکر کنن که از بقیه «کمترن». در حالی که توی دنیای واقعی، مهارت و تجربه خیلی بیشتر از یه تکه کاغذ ارزش داره. چطور با سندروم ایمپاستر کنار بیایم؟حالا که فهمیدیم این حس از کجا میاد، بیایم ببینیم چطور میتونیم باهاش روبهرو بشیم. خبر خوب اینه که سندروم ایمپاستر یه چیز قابل مدیریته و حتی میتونه به یه نیروی مثبت تبدیل بشه. این چند تا راهکار رو امتحان کن: موفقیتهات رو ثبت کن: یه دفترچه داشته باش و هر بار که یه باگ رو حل کردی، یه پروژه رو تموم کردی یا حتی یه خط کد خوب نوشتی، یادداشتش کن. این کار باعث میشه به مرور ببینی که چقدر توانایی داری. با بقیه حرف بزن: یه بار با همکارات یا دوستات که برنامهنویس هستن راجع به این حس صحبت کن. میبینی که خیلیها همین حس رو دارن و تو تنها نیستی. کمالگرایی رو بذار کنار: قبول کن که هیچ کدی توی دنیا کامل نیست. مهم اینه که کار کنه و مشکل رو حل کنه. یادگیری رو بپذیر: به جای اینکه از تغییرات سریع تکنولوژی بترسی، بهش به چشم یه فرصت نگاه کن. هر چی بیشتر یاد بگیری، اعتماد به نفست بیشتر میشه. از مقایسه دست بکش: به جای اینکه خودت رو با بقیه مقایسه کنی، پیشرفت خودت رو نسبت به گذشتهات بسنج. مثلاً ببین پارسال کجا بودی و الان کجایی. وقتی سندروم ایمپاستر میتونه مفید باشهباور کن یا نه، این حس گاهی میتونه به نفعمون باشه. مثلاً همین که همیشه دنبال بهتر شدن هستی و نمیخوای توی کارات کم بذاری، خودش یه نقطه قوته. خیلی از برنامهنویسهای موفق میگن که این حس باعث شده بیشتر مطالعه کنن، کدهای بهتری بنویسن و توی کارشون پیشرفت کنن. فقط کافیه نذاری این حس کنترلت کنه و به جاش ازش به عنوان یه انگیزه استفاده کنی. حرف آخر: تو به اندازه کافی خوبی!سندروم ایمپاستر یه چیزیه که خیلی از برنامهنویسها و مهندسهای نرمافزار باهاش روبهرو میشن، ولی قرار نیست همیشه باهات بمونه. دفعه بعدی که حس کردی به اندازه کافی خوب نیستی، یه نفس عمیق بکش و به خودت یادآوری کن که همین که داری کد میزنی، پروژه تحویل میدی و هر روز یه چیز جدید یاد میگیری، یعنی داری راه رو درست میری. دنیای برنامهنویسی جای آدمای باهوش و باپشتکاره، و تو قطعاً یکی از اونایی.
-
Parsidate -کامل ترین کتابخانه کار با تاریخ و ساعت شمسی در اکوسیستم Rust
sina پاسخی ارسال کرد برای یک پروژه در پروژه های مناگر تاکنون با زبان Rust کار کرده باشید و خواسته باشید تاریخهای شمسی (Jalali/Shamsi) را مدیریت کنید، احتمالاً متوجه شدهاید که امکانات استاندارد Rust و حتی کرِیتهای معروف مانند chrono بیشتر بر روی تاریخ میلادی تمرکز دارند. اینجاست که به کتابخانه ParsiDate به عنوان یک راهحل جامع برای مدیریت تاریخ و زمان فارسی نیاز پیدا میکنید. ParsiDate یک کتابخانه Rust است که امکانات گستردهای برای کار با تاریخ و زمان شمسی ارائه میدهد. این کتابخانه نه تنها میتواند تاریخهای ساده را مدیریت کند، بلکه تبدیل بین تاریخ میلادی و شمسی، محاسبات زمانی، اعتبارسنجی و پشتیبانی از زمانهای با منطقه زمانی را نیز فراهم میکند. ویژگیهای کلیدی ParsiDate۱. سه نوع داده اصلیکتابخانه ParsiDate سه نوع داده اصلی دارد که هرکدام کاربرد خاص خود را دارند: ParsiDate: نمایشی ساده از تاریخ (سال، ماه، روز) بدون اطلاعات زمانی. ParsiDateTime: نمایشی از تاریخ و زمان (ساعت، دقیقه، ثانیه) بدون توجه به منطقه زمانی. ZonedParsiDateTime: تاریخ و زمان با توجه به منطقه زمانی، شامل پشتیبانی از تغییر ساعت تابستانی و آفستها. این ویژگی نیاز به فعالسازی timezone feature دارد. ۲. تبدیل و تعامل با chronoیکی از نقاط قوت اصلی ParsiDate امکان تبدیل آسان بین تاریخهای میلادی (NaiveDate, NaiveDateTime) و تاریخهای شمسی است. این بدان معنی است که شما میتوانید دادههای موجود خود را بدون دردسر به تاریخ شمسی تبدیل کنید و بالعکس. use parsidate::ParsiDate; use chrono::NaiveDate; let g_date = NaiveDate::from_ymd_opt(2024, 7, 23).unwrap(); let pd = ParsiDate::from_gregorian(g_date).unwrap(); assert_eq!(pd.to_gregorian().unwrap(), g_date); ۳. اعتبارسنجی و ایمنیتمام تاریخها و زمانها در ParsiDate به صورت دقیق اعتبارسنجی میشوند. برای مثال، تلاش برای ایجاد یک روز نامعتبر مانند ۳۰ اسفند در سال غیرکبیسه، خطا ایجاد میکند. assert!(ParsiDate::new(1404, 12, 30).is_err()); // روز نامعتبر۴. فرمتبندی و پارسینگ پیشرفتهParsiDate امکان نمایش و تبدیل تاریخها و زمانها با الگوهای مشابه strftime را فراهم میکند. شما میتوانید از نامهای فارسی ماهها، روزهای هفته، فصلها و تمام اجزای تاریخ و زمان استفاده کنید. let pd = ParsiDate::new(1403, 5, 2).unwrap(); assert_eq!(pd.format("%d %B %Y"), "02 مرداد 1403"); همچنین، پارس کردن رشتهها به تاریخ شمسی با فرمتهای مختلف به آسانی ممکن است: let parsed = ParsiDate::parse("1403/05/02", "%Y/%m/%d").unwrap(); assert_eq!(parsed, pd); ۵. محاسبات زمانی (Arithmetic)ParsiDate امکان جمع و تفریق روزها، ماهها و سالها را با در نظر گرفتن طول ماهها و سالهای کبیسه فراهم میکند. همچنین با استفاده از chrono::Duration میتوان محاسبات دقیق زمان را انجام داد. let next_day = pd.add_days(1).unwrap(); // اضافه کردن یک روز۶. اطلاعات کامل تاریخ و زمانکتابخانه امکانات متنوعی برای استخراج اطلاعات از تاریخها فراهم کرده است: روز هفته شمسی روز سال فصل شماره هفته اجزای تاریخ و زمان (سال، ماه، روز، ساعت، دقیقه، ثانیه) همچنین امکان دریافت اولین و آخرین روز ماه، سال و فصل وجود دارد. ۷. پشتیبانی از زمان واقعی سیستمParsiDate::today() – دریافت تاریخ امروز شمسی ParsiDateTime::now() – دریافت تاریخ و زمان کنونی ZonedParsiDateTime::now(tz) – دریافت زمان کنونی با منطقه زمانی use parsidate::ParsiDateTime; let now = ParsiDateTime::now(); println!("Current ParsiDateTime: {}", now); ۸. پشتیبانی از سریالسازی (Serde)با فعال کردن serde feature، تمامی نوعهای تاریخ و زمان میتوانند سریالسازی و دیسریالسازی شوند که برای ذخیرهسازی یا ارسال دادهها بسیار مفید است. نصب و فعالسازی امکاناتبرای اضافه کردن ParsiDate به پروژه Rust کافیست Cargo.toml را به شکل زیر تنظیم کنید: [dependencies]parsidate = "1.7.1"chrono = "0.4"فعالسازی ویژگیهای اضافی: serde – سریالسازی و دیسریالسازی timezone – پشتیبانی از ZonedParsiDateTime و مناطق زمانی مثال: parsidate = { version = "1.7.1", features = ["serde", "timezone"] } chrono-tz = "0.8" # مورد نیاز برای timezoneمثالهای کاربردیایجاد و مدیریت تاریخ شمسیuse parsidate::ParsiDate; let pd = ParsiDate::new(1403, 5, 2).unwrap(); println!("تاریخ شمسی: {}", pd.format("%d %B %Y")); محاسبات زمانیlet tomorrow = pd.add_days(1).unwrap(); println!("فردا: {}", tomorrow); مدیریت زمان با منطقه زمانی#[cfg(feature = "timezone")] { use parsidate::ZonedParsiDateTime; use chrono_tz::Asia::Tehran; let tehran_now = ZonedParsiDateTime::now(Tehran); println!("زمان فعلی تهران: {}", tehran_now); } دریافت فصل و محدوده آنuse parsidate::{ParsiDate, Season}; let winter_date = ParsiDate::new(1403, 11, 10).unwrap(); assert_eq!(winter_date.season().unwrap(), Season::Zemestan); let end_of_winter = winter_date.end_of_season().unwrap(); println!("پایان زمستان: {}", end_of_winter); جمعبندیکتابخانه ParsiDate یک ابزار کامل و حرفهای برای کار با تاریخ و زمان شمسی در Rust است. این کتابخانه برای برنامهنویسانی که میخواهند: تاریخ شمسی را با دقت و اعتبار بالا مدیریت کنند، محاسبات زمانی پیچیده را انجام دهند، و با تاریخ میلادی و مناطق زمانی تعامل داشته باشند، یک راهحل بسیار مطمئن و کاربردی محسوب میشود. با توجه به پشتیبانی از serde، امکانات فرمتبندی، پارسینگ، و محاسبات دقیق زمان، ParsiDate میتواند هستهی سیستمهای تاریخ و زمان فارسی را در پروژههای Rust شما تشکیل دهد. دسترسیصفحه ی parsidate در crates.io : https://crates.io/crates/parsidate صفحه ی parsidate در lib.rs: https://lib.rs/crates/parsidate صفحه ی مستندات parsidate در docs.rs : https://docs.rs/parsidate WiKi: https://github.com/parsicore/ParsiDate/wiki آخرین تغییرات: https://github.com/parsicore/ParsiDate/blob/master/CHANGELOG.md
-
SubAI Web: ابزاری برای ترجمه زیرنویسها با PHP و Gemini API
sina پاسخی ارسال کرد برای یک پروژه در پروژه های منSubAI، یک وباپلیکیشن برای ترجمه خودکار فایلهای زیرنویس (SRT) با استفاده از API Gemini است. هدف این پروژه، ارائه ابزاری ساده و کاربردی برای ترجمه زیرنویسها به زبانهای مختلف و مدیریت فایلهای ترجمهشده است ویژگیهای اصلیترجمه خودکار زیرنویسها با انتخاب زبان مقصد. امکان مشاهده، جستجو و دانلود فایلهای ترجمهشده. تنظیمات پیشرفته شامل کلید API، مدل ترجمه و کش. امنیت تضمینشده با CSRF و فیلتر ورودیها. تکنولوژیهای مورد استفادهPHP: برای بکاند و منطق اصلی. MySQL: برای ذخیرهسازی دادهها. Gemini API: برای پردازش ترجمه. Bootstrap: برای رابط کاربری. JavaScript: برای تعاملات کاربر. نحوه کاردریافت Gemini API و وارد کردن آن در تنظیمات. فایل SRT را آپلود و زبان مقصد را انتخاب کنید. ترجمه با نمایش پیشرفت انجام میشود. فایل ترجمهشده را دانلود یا در بخش "Translated Files" مدیریت کنید. کاربردمناسب علاقهمندان به فیلم و سریال برای ترجمه زیرنویس. ابزار کمکی برای مترجمان حرفهای. برنامههای آیندهپشتیبانی از فرمتهای دیگر (مثل VTT). افزودن سایر مدل ها برای استفاده در ترجمه دسترسی و اجرابرنامه از طریق (این لینک) قابل دسترسی میباشد. کلید API Gemini نیز مورد نیاز است.
-
اتصال Rust به C: یه راهنمای کاربردی برای برنامهنویسها
sina پاسخی ارسال کرد برای یک مطلب در برنامه نویسیاگه برنامهنویس باشی و با Rust کار کرده باشی، حتما شنیدی که این زبان چقدر رو سرعت و امنیت تمرکز داره. از اون طرف، C هم که یه زبان قدیمی و قدرتمنده و هنوز توی خیلی از پروژهها، مخصوصا پروژههای سیستمی، حرف اول رو میزنه. حالا فکر کن بخوای این دو تا رو با هم ترکیب کنی! هم قدرت و انعطاف C رو داشته باشی، هم ایمنی و مدرن بودن Rust رو. توی این مطلب میخوام بهت نشون بدم چطور میتونی Rust و C رو به هم وصل کنی و کدات رو بین این دو تا جابجا کنی. چرا اصلا Rust و C رو به هم وصل کنیم؟قبل از اینکه بریم سراغ کد و جزییات، بذار یه لحظه ببینیم چرا این کار منطقیه. Rust یه زبان نسبتا جدیده که خیلی از مشکلات C مثل مدیریت دستی حافظه و خطاهای اشارهگر (pointer errors) رو حل کرده. اما خب، C یه اکوسیستم عظیم داره؛ کتابخونههایی مثل POSIX یا حتی کدهای قدیمی پروژهات که نمیخوای از صفر با Rust بازنویسیشون کنی. اینجا اتصال این دو زبان به کار میاد. میتونی از کتابخونههای C توی Rust استفاده کنی یا برعکس، کدهای Rust رو توی پروژههای C وارد کنی. مفاهیم اولیه: FFI چیه؟برای اینکه Rust و C با هم حرف بزنن، از یه چیزی به اسم FFI استفاده میکنیم. FFI مخفف "Foreign Function Interface" هست و به زبون ساده، یه جور پل ارتباطی بین زبونهای مختلفه. توی این مورد، FFI به Rust اجازه میده توابع C رو فراخوانی کنه و برعکس. اما این کار یه سری اصول داره که باید رعایت کنی، چون Rust و C توی مدیریت حافظه و ساختار دادهها خیلی فرق دارن. قدم اول: یه تابع C بنویسبیا با یه مثال ساده شروع کنیم. فرض کن توی C یه تابع داری که دو تا عدد رو میگیره و جمعشون میکنه: // math.c int add(int a, int b) { return a + b; }برای اینکه Rust بتونه این تابع رو ببینه، باید یه فایل هدر (header) هم بسازی: // math.h #ifndef MATH_H #define MATH_H int add(int a, int b); #endifحالا این فایل C رو کامپایل میکنیم تا یه کتابخونه استاتیک بسازیم: gcc -c math.c -o math.o ar rcs libmath.a math.oتا اینجا یه کتابخونه به اسم libmath.a داریم که قراره توی Rust ازش استفاده کنیم. قدم دوم: اتصال به Rustتوی پروژه Rust، باید به کامپایلر بگی که این کتابخونه خارجی رو لینک کنه. برای این کار از build.rs استفاده میکنیم. اگه پروژهات هنوز فایل build.rs نداره، توی ریشه پروژه یه فایل با این اسم بساز و این کد رو توش بذار: // build.rs fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rustc-link-lib=math"); println!("cargo:rustc-link-search=native=."); }این کد به Rust میگه که کتابخونه libmath.a رو پیدا کنه و به پروژه لینک کنه. یادت باشه فایل libmath.a رو توی همون دایرکتوری پروژهات کپی کنی. قدم سوم: تعریف تابع در Rustحالا باید به Rust بگیم که تابع add توی C چه شکلیه. این کار رو با استفاده از بلاک extern "C" انجام میدیم. توی فایل main.rs اینجوری مینویسی: // main.rs extern "C" { fn add(a: i32, b: i32) -> i32; } fn main() { unsafe { let result = add(5, 3); println!("Result: {}", result); } }ری میکنه که مسئولیت هر مشکلی گردن خودته! اجرا و تستحالا کافیه پروژه رو با cargo run اجرا کنی. اگه همه چیز درست پیش بره، خروجی باید این باشه: Result: 8تبریک! تونستی یه تابع C رو توی Rust فراخوانی کنی. برعکسش چطوره؟ Rust به Cحالا فرض کن بخوای یه تابع توی Rust بنویسی و توی C ازش استفاده کنی. بیایم یه مثال بزنیم. توی Rust یه تابع میسازیم که یه رشته رو میگیره و طولش رو برمیگردونه: // lib.rs #[no_mangle] pub extern "C" fn string_length(s: *const i8) -> i32 { unsafe { let c_str = std::ffi::CStr::from_ptr(s); c_str.to_bytes().len() as i32 } }#[no_mangle]به Rust میگه اسم تابع رو تغییر نده تا C بتونه پیداش کنه. حالا این پروژه رو به صورت کتابخونه کامپایل میکنیم: cargo build --releaseفایل librust.a توی پوشه target/release ساخته میشه. توی C اینجوری ازش استفاده میکنیم: // main.c #include <stdio.h> #include <stdint.h> extern int32_t string_length(const char* s); int main() { const char* text = "Hello from Rust!"; int32_t len = string_length(text); printf("Length: %d\n", len); return 0; }کامپایلش میکنیم: gcc -L ./target/release -lrust main.c -o testاگه اجرا کنی، خروجی میشه: Length: 16نکات مهم و چالشهااتصال Rust و C خیلی هم ساده نیست. باید حواست به مدیریت حافظه باشه؛ مثلا اگه توی C حافظه تخصیص دادی، Rust انتظار نداره خودش آزادش کنه. یا برعکس، اگه Rust یه چیزی رو آزاد کرد، C نباید دوباره بخواد باهاش کار کنه. یه ابزار خوب برای این کار، استفاده از کتابخونههایی مثل cbindgen و bindgen هست که فایلهای هدر و تعاریف رو خودکار تولید میکنن و کار رو راحتتر میکنن. جمعبندیوصل کردن Rust به C یه راه عالیه برای اینکه از بهترینهای هر دو دنیا استفاده کنی. با FFI و چند خط کد، میتونی پروژههات رو قویتر و انعطافپذیرتر کنی.