دوشنبه، اردیبهشت ۱۰، ۱۳۸۶

درک

این پست از وبلاگ یک لیوان چای داغ برام خیلی جالب بود...

جمعه، اردیبهشت ۰۷، ۱۳۸۶

به ازای هر کودک یک لپتاپ

قصد بدبینی یا پیش‌داوری ندارم؛ اما خیلی وقت‌ها کسانی که اعلام می‌کنند دنبال ساختن دنیای بهتری برای زندگی کردن هستند، بیشتر دنبال ارضای نیازهای مادی یا روانی درونی خودشون هستند، و بدتر با خارج کردن امور از روند طبیعی خودش دنیا رو جهنم‌تر می‌کنند. باز هم می‌گم، قصد بدبینی ندارم. امیدوارم کارهای این موسسه وضع آموزشی کودکان کم بضاعت رو (همون طور که خودشون تبلیغ می‌کنند) بهتر کنه.

چند لینک:

موسسه OLPC: One Laptop Per Child

یک مقاله از IBM در مورد مشخصات دستگاه و شبیه ساز آن برای PC

پنجشنبه، اردیبهشت ۰۶، ۱۳۸۶

پیش‌پردازنده در C++

۱.
در
C/C++ عباراتی وجود دارند که کامپایل نمی‌شوند، بلکه کامپایلر را هدایت می‌کنند. این دستورات با کاراکتر # شروع می‌شوند. مثل #define و #pragma و #if و ... به این عبارات preprocessor directive می‌گویند.

 

۲.
در
C/C++ کامپایل هر فایل دو مرحله دارد. در یک مرحله تمام preprocessor directive ها خوانده و جایگذاری می‌شوند (به غیر از آن‌هایی که سروکارشان با خود کامپایلر، یعنی مرحله بعد، است) و در مرحله بعد فایل حاصل به یک Object File کامپایل می‌شود. واحدی که وظیفه مرحله اول را بر عهده دارد preprocessor نام دارد و علت نام‌گذاری آن هم از همین نکته نشئت گرفته: واحدی که عباراتی را قبل از عمل کامپایل اصلی پردازش می‌کند.

 

۳.
برای این‌که منظور از جایگذاری
preprocessor directive ها را متوجه شویم به چند مثال توجه کنید. مثلا در عبارت

#include "somefile.h"

واحد preprocessor کل این خط را حذف می‌کند و محتویات "somefile.h" را به جایش قرار می‌دهد و فایل نهایی حاصل را به کامپایلر می‌فرستد و یا در عبارت

#define MSG "Hello"

preprocessor کلیه توکن‌هایی را که مساوی MSG باشند را با رشته "Hello" جایگزین می‌کند.

 

۴.
برای مشاهده خروجی
preprocessor، تنها و بدون کامپایل source برنامه، هنگام استفاده از gcc از دستور زیر استفاده کنید.

$ g++ -E src.cpp -o src-no-prep.cpp
[you can use gcc instead of g++ too]

و هنگام استفاده از کامپایلر Microsoft Visual C++ از دستور زیر استفاده کنید.

$ cl.exe src.cpp /E > src-no-prep.cpp

 

۵.
برای مثال برنامه کوتاه زیر را در نظر بگیرید:

C++
#include <iostream>
using namespace std;

#define MSG "Hello"

int main()
{
    cout << MSG << endl;
    return 0;
}

حالا فایل‌های خروجی preprocessor را باز کنید. جالب است بدانید که gcc فایل مبدا ۱۰ خطی شما را به یک فایل غول‌پیکر ۲۳۸۵۹ خطی تبدیل کرده. خروجی Visual C++ هم یک فایل ۴۵۰۴۱ خطی است (که البته تعداد زیادی از خط‌های آن خالی است). تنها حدود ۱۰ خط آخر این فایل‌ها را شما نوشته‌اید. این فایل‌ها بدون هیچ مشکلی قابل کامپایل کردن هستند.

 

۶.
هنوز فایل‌های خروجی تعدادی
preprocessor directive دارند که از بین نرفته‌اند. اگر دقت کنید این directive ها همگی یا #line هستند یا #pragma. کامپایلر عبارت #line را برای تولید خطا و راهنمایی برنامه‌نویس لازم دارد. همچنین #pragma هم یک سری option ها را برای کامپایلر مشخص می‌کند.

 

۷.
حالا شاید واضح‌تر شده باشد که چرا ترتیب نوشتن
preprocessor directive ها مهم است.

 

پ.ن.

۱. خیلی جاها به این عبارات به اشتباه preprocessor گفته می‌شود. در حالی که preprocessor یک قسمت از کامپایلر است. نام صحیح‌تر این عبارات preprocessor directive می‌باشد.


چهارشنبه، اردیبهشت ۰۵، ۱۳۸۶

مخالفت با جنگ در برابر مخالفت با کشتار

مخالفین جنگ در آمریکا از کدوم آمار ناراحتند؟ چرا تعداد کم قاتل‌ها با دقت ۱ نفر در خط اول نوشته می‌شه و تعداد کثیر مقتولین بی‌گناه با دقت ۱۰۰۰ نفر با قید also در خط دوم؟

باز دم این یکی گرم که نوشته‌اش خط دوم رو داشت ...

دوشنبه، اردیبهشت ۰۳، ۱۳۸۶

آزادسازی منابع در C#

حافظه در .NET مدیریت شده است. مدیریت شده بدین معنی که اگر شیءای در حافظه باشد و به آن اشاره‌ای نشود، این شیء از دید Framework یک آشغال است و جمع‌آوری (پاک) می‌شود. به این عمل Garbage Collection می‌گویند. اما بسیاری از منابع مدیریت شده نیستند. مثلا برنامه‌نویس باید فایلی را که باز کرده، بعد از استفاده، خود، ببندد. همین طور اتصال به database باید توسط خود برنامه‌نویس قطع شود و ... می‌توان آزادسازی این منابع را در مخرب کلاس انجام داد. در C# مخرب‌ها درست مانند C++ تعریف می‌شوند.

C#
class SomeClass
{
    ~SomeClass()
    {
        // release resources here
    }
    ...
}

این تابع پس از کامپایل شدن تبدیل به تابعی virtual با نام Finalize() می‌شود. در واقع کد بالا پس از کامپایل شدن فرمی پیدا می‌کند که انگار کد زیر نوشته شده:

C#
class SomeClass
{
    virtual void Finalize()
    {
        try
        {
            // release resources here
        }
        finally
        {
            base.Finalize();
            // chaining to the base class
        }
    }
    ...
}

تابع Finalize() یا مخرب را فقط Garbage Collector (GC) می‌تواند صدا بزند نه برنامه‌نویس. همچنین برنامه‌نویس نمی‌تواند تابع Finalize() را خودش تعریف کند. هر گونه شباهت توابع برنامه‌نویس به تابع Finalize() بسته به میزان شباهت موجب ایجاد warning یا error می‌شود. تنها و تنها تابع مخرب به فرم C++ مجاز است.

 

اگر GC شیءای را پاک کند، مخربش را هم صدا می‌زند. اما معلوم نیست چه زمانی Garbage Collector به سراغ شیء می‌رود. اگر به شیء تنها یک reference اشاره کند با مساوی null قرار دادن آن reference، شیء برای جمع‌آوری شدن علامت می‌خورد و به صف آشغال‌ها اضافه می‌شود. حال اگر Garbage Collector را مجبور کنیم تمام آشغال‌ها را پاک کند، شیء ما میان مابقی آشغال‌ها پاک می‌شود. این کار زمان‌بر است چون که به بهانه پاک کردن یک شیء کل آشغال‌ها پاک خواهند شد.

C#
SomeClass someObject = new SomeClass();
// do something with it
...
// when finished set
someObject = null;
// force GC to collect all garbage
GC.Collect();

راه دیگر استفاده از IDisposable است. اگر کلاسی IDisposable را پیاده‌ (implement) کند، می‌تواند از متد Dispose() برای آزاد کردن منابع استفاده کند. این تابع را برنامه‌نویس می‌تواند صریحا صدا بزند. همان گونه که از اسم آن پیداست کلاسی که IDisposable را پیاده کند، disposable یا قابل دورانداختن می‌شود.

C#
public interface IDisposable
{
    void Dispose();
}

در پیاده‌سازی تابع Dispose() باید GC.SuppressFinalize() هم صدا زده شود تا دیگر GC شیء مذکور را برای بار دوم پاک نکند. برای پیاده کردن همچین سناریویی از یک متغیر Boolean که این‌جا اسمش را گذاشتیم disposed و دو نسخه از تابع Dispose() که یکی از آن دو متغیری Boolean به عنوان پارامتر می‌گیرد، به شکل زیر استفاده می‌شود.

C#
public class SomeClass
{
    public SomeClass()
    {
        // initialize resources
        disposed = false;
    }

    ~SomeClass()
    {
        dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if(!disposed)
        {
            if(disposing)
            {
                // dispose managed resources
                // e.g. call their Dispose()
            }
            // now dispose unmanaged resources
            // e.g. close files or database connections
            disposed = true;
        }
    }
    ...
    private bool disposed;
}

متغیر disposed موجب می‌شود که قطعه کد آزادسازی تنها یک بار اجرا شود. اگر این کار توسط فراخوانی تابع Dispose() انجام شود کلیه منابع چه مدیریت شده چه مدیریت نشده آزاد می‌شوند، چرا که دیگر قرار نیست GC به سراغ آن‌ها برود. اما اگر مخرب این کار را انجام دهد فقط منابع مدیریت نشده آزاد می‌شوند، چرا که منابع مدیریت شده قبلا توسط خود GC آزاد شده‌اند.

 

یک راه کوتاه و تمیز برای استفاده و بلافاصله آزاد کردن اشیایی که disposable‌ هستند استفاده از using است.

C#
using (someObject = new SomeClass())
{
    // use someObject
}

کد بالا پس از کامپایل به فرمی تبدیل می‌شود که انگار به شکل زیر نوشته شده بود.

C#
someObject = new SomeClass();
try
{
    // use someObject
}
finally
{
    if(someObject != null)
        someObject.Dispose();
}

مثلا در زیر روش استفاده از using برای باز کردن یک فایل و خواندن از آن نشان داده شده است.

C#
using (StreamReader sr = new StreamReader("file.txt"))
{
    // read the file
}

چهارشنبه، فروردین ۲۹، ۱۳۸۶

زندگی زیباست

چندی پیش گذرم افتاد به پروفایل یه معلم نه چندان قدیمیم در اورکات (معلم از این جهت که خیلی چیزها از ایشون یاد گرفتم، که درصد کمیش در رابطه با کامپیوتر بود). شعر و عکسی گذاشته بودند که اون شعر یادآور بزرگ‌ترین گناه‌های هر روزه‌ی من بود: کور بودن، خاموش بودن. شعر، در عین زیبایی و دل‌نشینی، دردناک و سرشار از شماتت بود...


گفته بودم زندگی زیباست
گفته و ناگفته، ای بس نکته‌ها کاین جاست
آسمان باز
آفتاب زر
باغ‌های گل
دشت‌های بی در و پیکر
سر برون آوردن گل از درون برف
تاب نرم رقص ماهی در بلور آب
بوی خاک عطر باران خورده در کهسار
خواب گندمزارها در چشمه‌ی مهتاب

آمدن، رفتن، دویدن
عـــــــــشق ورزیدن
در غم انسان نشستن
پا به پای شادمانی‌های مردم پای کوبیدن
کــــــــار کردن، کــــــــار کردن
آرمیدن

آری، آری زندگی زیباست
زندگی آتشگهی دیرینه پابرجاست
گر بیفروزیش، رقص شعله‌اش در هر کران پیداست
ور نه خاموش است و خاموشی گناه ماست

دوشنبه، فروردین ۲۷، ۱۳۸۶

is و as در C#

۱.
is یک عملگر است که بررسی می‌کند آیا یک متغیر شیءای از یک کلاس هست یا نه. چیزی شبیه به instanceof در جاوا. همان‌طور که از توصیف بر می‌آید این عملگر یک مقدار boolean برمی‌گرداند.

 

۲.
is کل درخت ارث‌بری را بررسی می‌کند. مثلا:

C#
aTextBoxObj is System.Windows.Control == true

 

۳.
در مورد استفاده از
generic ها هم حتما باید آرگومان مربوط به نوع کلاس generic ذکر بشود. مثلا:

C#
class MyClass<T> {}
...
MyClass<int> obj1 = new MyClass<int>();
MyClass<string> obj2 = new MyClass<string>();
...
obj1 is MyClass  // Syntax Error
obj1 is MyClass<int> == true
obj1 is MyClass<string> == false

 

۴.
as یک عملگر است که به شکلی تبدیل نوع در زمان اجرا را انجام می‌دهد. اگر تبدیل نوع قابل انجام باشد شیء تبدیل شده را برمی‌گرداند و در غیر این صورت مقدار null را. as در C# بسیار شبیه است به dynamic_cast در C++.

 

۵.
مزیت
as نسبت به type cast با پرانتز، این است که در آن اگر تبدیل نوع قابل انجام نباشد، دیگر Exception پرتاب نمی‌شود.

 

۶.
کاربرد
as به شکل زیر است:

C#
object someObject;
...
stirng str = someObject as string; 

if (str != null)
{
    // means someObject is a string
}

 

۷.
as را می‌توان به صورت معادل زیر نوشت:

C#
expression is type ? (type)expression : (type)null

 

یکشنبه، فروردین ۲۶، ۱۳۸۶

تغییر

«حال» را می‌شود با درد گذراند؛ اما تصور درد آلود بودن آینده و دوام بدون دگرگونی «حال»، انسان را از پا در می‌آورد. بهشت، وعده کاملی نیست.

- ابن مشغله، نادر ابراهیمی