Warning: Undefined array key 0 in /var/www/tgoop/function.php on line 65

Warning: Trying to access array offset on value of type null in /var/www/tgoop/function.php on line 65
968 - Telegram Web
Telegram Web
این آیدی زیبا اینجا بماند به یادگاری.

A8B13B5D-B013-4556-B98B-F2A5D8268E5E
خرسِ برنامه نویس
Photo
از همه تخیلی تر‌ فقط اجایل! ؛ )
خرسِ برنامه نویس
دوستان کار‌ مقدمه کورس رو به اتمام هست، با محتوای انگلیسی راحت تر هستید یا فارسی کنیمش؟
امروز درحال کار روی این موضوع بودم و نظریه مجموعه هارو داشتم به مقاله اضافه میکردم که به مفهوم Closure برخورد کردم، دیدم این بحث خودش یک مقاله جمع و جور خوب میخواد. از کجا اومده ؟ ریشه ریاضیاتی داره؟ نداره؟ چرا در programming آداپته شده و ...
ساعت ۸ امشب از همینجا 🤘🏻منتشر میشه.
خرسِ برنامه نویس
امروز درحال کار روی این موضوع بودم و نظریه مجموعه هارو داشتم به مقاله اضافه میکردم که به مفهوم Closure برخورد کردم، دیدم این بحث خودش یک مقاله جمع و جور خوب میخواد. از کجا اومده ؟ ریشه ریاضیاتی داره؟ نداره؟ چرا در programming آداپته شده و ... ساعت ۸ امشب از…
پیش‌درآمد: سفر هیلبرت و منطق مرتبه اول

اوایل قرن بیستم، دیوید هیلبرت—یکی از بزرگ‌ترین ریاضی‌دان‌های وقت—آرزویی بزرگ در سر داشت: این‌که بتواند تمام ریاضیات را تبدیل کند به یک زبان کاملاً رسمی و دقیق از نمادها و قواعدی که از آن‌ها، بدون هیچ حدس و گمانی، همهٔ نتیجه‌های ریاضی را بشود مثل یک دستور کامپیوتری استخراج کرد. هیلبرت می‌خواست زبانی بسازد که هیچ جا برای ابهام یا تفاسیر شخصی نباشد و بشود با روش‌های ساده و کاملاً مطمئن، درستی آن را اثبات کرد.

دستگاهِ صوری (formal system) یعنی یک چارچوب انتزاعی که دو چیز اصلی دارد:
- زبان صوری: مجموعه‌ای از نمادها (حروف، علامت‌ها) و قواعدی که می‌گوید چطور این نمادها را کنار هم بگذاری.

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

وقتی با این چارچوب کار می‌کنی، فقط به شکل ظاهری عبارات (syntactic) نگاه می‌کنی—یعنی دنباله‌ای از نمادها—و کاری به «معنی» پشت‌شان نداری، اما در عوض می‌توانی ساختار منطقی و استدلال ریاضی را دقیق ببینی.

هستهٔ کارِ هیلبرت منطق مرتبهٔ اول (first-order logic) بود. این منطق چیزهایی مثل «∀» به‌معنای «برای هر» و «∃» به‌معنای «وجود دارد» را معرفی می‌کند تا بتوانی دربارهٔ عناصر یک مجموعه (مثلاً اعداد یا نقاط) صحبت کنی. فرقش با منطق‌های قوی‌تر این است که فقط می‌توانی دربارهٔ خودِ عناصر کمّی‌سازی (quantify) کنی، نه دربارهٔ «همهٔ خواص» یا توابع. این‌کار باعث می‌شود هم زبان رسمی، قابل فهم و هم تا حدی تصمیم‌پذیر (decidable) باشد. مثلاً می‌نویسیم:

∀x (Prime(x) → ∃y (Prime(y) ∧ y > x))

یعنی «برای هر عدد اول x، عدد اول بزرگ‌تری به نام y وجود دارد.»

سال ۱۹۲۸، هیلبرت و همکارش ویلهم آکرمن پرسیدند: آیا می‌شود یک برنامه یا الگوریتم ساخت که برای هر جمله در منطق مرتبهٔ اول بگوید «در همهٔ شرایط درسته» یا «نیست»؟ اگر جواب مثبت بود، می‌توانستیم همهٔ ریاضیات را با اجرای یک برنامه رایانه‌ای حل کنیم.

اما در ۱۹۳۶، آلونزو چرچ ثابت کرد که چنین الگوریتمی وجود ندارد. او ثابت کرد که این سؤال به مسائل غیرقابل‌حلِ دیگری مثل lambda calculus می‌رسد. تقریباً هم‌زمان، آلن تورینگ با مفهوم «ماشین تورینگ» به همان نتیجه رسید: هیچ روش کامپیوتری‌ای نیست که بتواند همهٔ جملات منطق مرتبهٔ اول را بررسی کند.

این دو کشف، پایهٔ نظریهٔ محاسبات مدرن را گذاشت و نشان داد که برنامهٔ بزرگ هیلبرت—ساختن یک دستگاه کاملاً مکانیزه برای همهٔ ریاضیات—به طور ذاتی محدود است. اما در عوض، فهم عمیقی از ماهیت محاسبه و مرزهای آن به ما داد و مسیر را برای پیدایش علم رایانه هموار کرد.

#بخش1
خرسِ برنامه نویس
پیش‌درآمد: سفر هیلبرت و منطق مرتبه اول اوایل قرن بیستم، دیوید هیلبرت—یکی از بزرگ‌ترین ریاضی‌دان‌های وقت—آرزویی بزرگ در سر داشت: این‌که بتواند تمام ریاضیات را تبدیل کند به یک زبان کاملاً رسمی و دقیق از نمادها و قواعدی که از آن‌ها، بدون هیچ حدس و گمانی، همهٔ…
همه چیز از یک λ لعنتی شروع شد!

در میانهٔ دههٔ ۱۹۳۰، آلونزو چرچ در دفترش در دانشگاه پرینستون مشغولِ کار روی «مسئلهٔ تصمیم» (Entscheidungsproblem) بود. او از خود پرسید: «محاسبه دقیقاً چیست؟» برای یافتن پاسخ، تصمیم گرفت همهٔ چیزهای اضافه را کنار بگذارد و محاسبه را در ساده‌ترین شکلش—فقط توابع و نحوهٔ کاربردشان روی ورودی‌ها—درنظر بگیرد.

از همین ایده بود که محاسبات لامبدا (lambda calculus) به وجود آمد: یک سیستم صوری بسیار مینیمال با سه بخش اصلی:

1. متغیرهای بدون نام مثلا x و y
2. انتزاع (abstraction) که با λx.E نوشته می‌شود و به معنی «یک تابع ناشناس با پارامتر x خروجی میدهد E» است
3. کاربرد (application) که با F A نمایش داده می‌شود و یعنی «تابع F را روی آرگومان A اجرا کن»

چرچ نشان داد که همین دستورهای ساده می‌توانند هر الگوریتم قابل اجرا را مدل کنند. با ترکیب متغیرها، انتزاع‌ها و کاربردها، قدرت این سیستم به اندازهٔ ماشین‌های تورینگ (Turing machines) بود و تمام توابع «قابل محاسبه» را در یک چارچوب یکپارچه جا می‌داد.

خودِ استفاده از حرف یونانی λ هم اتفاقی نبود. چرچ در یک نامهٔ منتشرنشده در ۱۹۶۴ توضیح داده بود که اول از علامت «∧x» در کارهای Whitehead و Russell استفاده کرده، بعد برای تمایز‌دادن و چاپ بهتر آن را تبدیل «λx» کرده هرچند بعد شوخی کرد که شاید می‌توانست یک حرف رندوم دیگری انتخاب کند!

چرا اسمش را «Calculus» گذاشتند؟ در لاتین، *calculus* اول یعنی «سنگریزهٔ کوچک» که برای حساب با چرتکه استفاده می‌شد. بعد کم‌کم معنایش به هر «سیستم محاسبهٔ نمادی» تعمیم یافت: از دیفرانسیل تا منطق گزاره‌ای و نهایتاً تا lambda calculu رسید، پس میتوان گفت lambda calculus یعنی «محاسبهٔ تابع‌ها و جایگزینی»
خیلی یواشکی و کوتاه بگم اسم دیگه این عمل میشه substitution.

اصل کار در lambda calculus شبیه یک دستور آشپزی ساده است. مثلا بنویسید λx.x+1؛ یعنی «یکی به x اضافه کن». وقتی این را روی عدد ۵ اجرا کنید، یعنی (λx.x+1) 5،عدد ۵ را به‌جای x می‌گذارید و نتیجهٔ ۶ به‌دست می‌آید. این جایگزینی دقیقاً موتور محاسبهٔ این زبان کوچک است.

همین سیستم کوچک دانشمندان را متعجب کرد که با فقط همین سه سازوکار—انتزاع، کاربرد و جایگزینی—سیستم چرچ به کامل بودن تورینگ (Turing completeness) رسید. آن‌ها عددها، بولین‌ها و ساختار داده را به‌صورت توابع Church numerals و Church booleans کدگذاری کردند و ثابت کردند که این سیستم می‌تواند هر ماشین تورینگ را شبیه‌سازی کند.

نتیجهٔ نهایی، «فرضیهٔ چرچ–تورینگ» شد: هر تابعی که انسان بتواند به‌صورت شهودی محاسبه کند، می‌تواند هم با یک ماشین تورینگ و هم با lambda calculus محاسبه شود. این فرضیه—گرچه قابل اثبات رسمی نیست—سنگ بنای نظریهٔ محاسبه و علوم رایانه شد.

امروز هر بار که در JavaScript یا C# یک تابع ناشناس (anonymous function) می‌نویسید یا از closures استفاده می‌کنید، روی شانه‌های چرچ و ایدهٔ lambda calculus ایستاده‌اید—پاسخ ساده و درعین‌حال عمیق او به سوال «محاسبه چیست؟»

#بخش2
این وسط هم یک ناسزایی بگم به مسئله راست چین و چپ چین که هنوز درست حل نشده
خرسِ برنامه نویس
همه چیز از یک λ لعنتی شروع شد! در میانهٔ دههٔ ۱۹۳۰، آلونزو چرچ در دفترش در دانشگاه پرینستون مشغولِ کار روی «مسئلهٔ تصمیم» (Entscheidungsproblem) بود. او از خود پرسید: «محاسبه دقیقاً چیست؟» برای یافتن پاسخ، تصمیم گرفت همهٔ چیزهای اضافه را کنار بگذارد و محاسبه…
چیشد و چرا یهو lambda calculus رو به Closure ربط داد؟

از جایی شروع کنیم که هنوز خبری از Closure نبود؛ روزهایی که برنامه‌نویسان با زبان‌هایی مثل Algol 60 تازه با مفهوم توابع تو در تو آشنا می‌شدند. در آن دوران، گروهی از پژوهشگران در نشست ۱۹۵۸ زوریخ قواعد «block structure» را برای ALGOL 60 تصویب کردند و واژه‌هایی مثل begin … end را وارد ادبیات کدنویسی کردند. همین تصمیم ساده نقطهٔ آغاز چیزی شد که بعدها lexical scope نام گرفت: قانونی که می‌گوید دامنهٔ یک نام/متغیر دقیقاً همان جایی است که در متن برنامه نوشته شده، نه جای دیگری در زمان اجرا.

واژهٔ «lexical» نخستین‌بار حوالی ۱۹۶۷ در گزارش‌های Cambridge ظاهر شد؛ کریستوفر استراچی با الهام از ریشهٔ یونانی lexis تأکید کرد که دامنهٔ متغیر، خصیصهٔ خودِ source code است، نه call stack. چنین نگرشی روشن می‌کرد که اگر تابع inner داخل تابع outer تعریف شود، بدون هیچ جست‌وجویی در زمان اجرا به متغیرهای outer دسترسی خواهد داشت. در قطعهٔ زیر، inner حتی بعد از تمام شدن outer همچنان مقدار count را می‌بیند، زیرا ساختار نوشتاری برنامه آن را در بر گرفته است:

function outer() {
let count = 0;
function inner() {
console.log(count);
}
return inner;
}

outer() // 0

این رفتارِ به‌ظاهر جادویی اما در عمل به جایی می‌رسید که دیگر call stack پاسخ‌گو نبود؛ پس از برگشت مقدار از outer، متغیرهای محلی عملاً از حافظهٔ فعال حذف می‌شدند. درست همین‌جاست که Peter J. Landin وارد داستان می‌شود. او برای حفظ آن «private state» ماشینی انتزاعی به نام SECD machine طراحی کرد. ایده‌اش ساده بود: هر تابع را همراه با محیط متغیرهایی که در لحظهٔ تعریف در دسترسش بودند بسته‌بندی کن و این بسته را Closure بنام. از آن پس، توابع می‌توانستند مثل کوله‌پشتی، مقادیر بیرونی را با خود حمل کنند حتی وقتی از محدودهٔ اصلی خارج می‌شدند.
عمل دسترسی داشتن به متغیر ها توسط lexical scope تعیین میشد ولی این Closure بود که تضمین میکرد که متغیر های محلی حتما باقی بمانند.
اما Landin این ایده را از کجا آورد؟ پاسخ در lambda calculus نهفته است؛ همان زبان نمادینی که Alonzo Church برای مدل‌سازی «محاسبه» ابداع کرد. در lambda calculus نوشتن
λx. f(x, y)

یعنی تعریف تابعی بدون نام که یک پارامتر دارد (x). این x را bound variable می‌نامیم چون داخل همان abstraction تعریف و مقداردهی می‌شود. در برابر آن، y یک free variable است؛ در بدنهٔ تابع ظاهر شده اما پارامتر نیست و باید از محیط بیرونی گرفته شود. معنی Closure دقیقاً «بستن» این free variableهاست: هنگام ساخت تابع، مقدار آن‌ها ذخیره می‌شود تا تابع در هر زمان دیگری اجرا شد، هنوز به همان مقدار دست یابد.

حالا ممکنه بگید که آقا زبان ریاضی رو ول کن یه کد به ما نشون بده! معادل نوشته بالا میشه کد پایین
const g = x => f(x, y);

ولی بزارید یکم باز ترش کنم
// یک مقدار خارجی برای y
const y = 5;

// تعریف تابع f که دو آرگومان x و y می‌گیرد
const f = (x, y) => {
// در این مثال f فقط جمع می‌زند؛
return x + y;
};

// معادل عبارت λx. f(x, y)
const g = x => f(x, y);


console.log(g(3)); // خروجی: 8 (چون 3 + 5)
خرسِ برنامه نویس
چیشد و چرا یهو lambda calculus رو به Closure ربط داد؟ از جایی شروع کنیم که هنوز خبری از Closure نبود؛ روزهایی که برنامه‌نویسان با زبان‌هایی مثل Algol 60 تازه با مفهوم توابع تو در تو آشنا می‌شدند. در آن دوران، گروهی از پژوهشگران در نشست ۱۹۵۸ زوریخ قواعد «block…
در خط اول یک ثابت به نام ‎y تعریف کرده‌ایم و مقدار ۵ را در آن گذاشته‌ایم. این عدد قرار است همان متغیر آزاد (free variable) باشد که تابع‌های بعدی از محیط بیرونی بردارند.
بعد تابع ‎f را می‌بینید که دو ورودی ‎x و ‎y می‌گیرد. این تابع در ساده‌ترین حالت فقط این دو عدد را با هم جمع می‌کند و حاصل را برمی‌گرداند. بنابراین اگر ‎f(3, 5) را صدا بزنیم جواب ۸ می‌شود.
در ادامه تابع ‎g را تعریف کرده‌ایم؛ ‎g خودش فانکشن است که تنها پارامترش ‎x است. داخل بدنهٔ ‎g، تابع ‎f را صدا می‌زنیم و ‎x را به عنوان آرگومان اول و ‎y بیرونی را به عنوان آرگومان دوم به ‎f می‌دهیم. به این ترتیب ‎g یک Closure تشکیل می‌دهد، چون ‎y را همراه خودش «می‌بندد» و هر جا ‎g را اجرا کنیم همان مقدار ۵ را کنار ‎x قرار می‌دهد.

در نهایت با ‎console.log(g(3)) تابع ‎g را برای ورودی ‎3 اجرا کرده‌ایم. ‎g مقدار ۳ را به ‎f می‌دهد، ‎f هم ۳ و ۵ را جمع می‌کند و نتیجه‌ی ۸ را برمی‌گرداند.

بعد ها Guy Sussman و Gerald Steele هنگام طراحی زبان Scheme دریافتند که اگر قرار است lexical scope تعیین کند چه نامی در دسترس است، Closure باید تضمین کند آن نام‌ها بعد از پایان تابع بیرونی از بین نرود. با جا افتادن این الگو، Closure به بخش جدایی‌ناپذیر پیاده‌سازی تمام زبان‌های امروزی—from JavaScript و C# تا Python—تبدیل شد؛ سازوکاری که اجازه می‌دهد callbackها context خود را «به خاطر بسپارند»، فکتوری فانکشن ها state مخصوص به خود بسازند و کد بدون اتکا به global متغیرهای خصوصی نگه دارد.

داستان از λ‑calculus شروع شد، جایی که مفهوم متغیرهای free و bound شکل گرفت. با ورود lexical scope فهمیدیم که جای قرارگیری کد در متن، دسترسی به نام‌ها را مشخص می‌کند. Peter Landin ایدهٔ closure را اضافه کرد تا یک تابع بتواند محیط تعریفِ خود را همراه داشته باشد. در نتیجه، آنچه از نظریهٔ محاسبه آغاز شده بود، در closure به کاربردی عملی تبدیل شد و امروز در بیشتر زبان‌ها به‌عنوان روشی ساده برای نگه‌داشتن state در کنار توابع به‌کار می‌رود.

پایان
#بخش3
لامبورگینی در خیابان‌های تهران

اخیراً که بحث ارزش‌گذاری شرکتهای استارتاپی در کشور ما داغ شده، بعضی از مدیران استارتاپی گله می‌کنند که بازار ما نگاه سنتی و گذشته‌نگر دارد و ارزش‌گذاری روی استارتاپها را بلد نیست.

در این باره مطلبی نوشتم که شاید حوصله داشته باشید و بخواهید بخوانید:


لامبورگینی در خیابان‌های تهران

#روزنوشته
Audio
صوت جلسه 5 خوانش کتاب یادگیری تفکر سیستمی

مواردی که خارج از کتاب بهشون اشاره شد در جلسه.
- اهمیت تفاوت قایل شدن بین انواع #تجربه که قبلا در این پست هم بهش تاکید کردیم
- اهمیت به تقسیم بندی صحیح برای درک بهتر و مدل سازی شفاف تر مثلا در خصوص تقسیم مهارت ها به دو نوع سخت و نرم که قبلا باز اینجا در موردشون صحبت کردیم.
Forwarded from TondTech (مسعود بیگی)
مرگ بر جنگ..
خرسِ برنامه نویس
Photo
عزیزان این رو من خیلی رندوم در اینترنت پیدا کردم و کار من نیست.
کردیت به سازنده ناشناس 🙏
تو این شرایط فقط همدلی نیازه
Forwarded from Novara
- جنگ هیچوقت خوب نیست
-مرگ کسایی که مسبب این وضعیتن میتونه خوشحالمون کنه
-کشته شدن کسایی که مظلومانه میرن باید ناراحت و خشمگینمون کنه
-خیلی از چیزا دست من و شما نیست
-اتحاد کنار همه تفاوت ها مهم ترین قسمت حفظ قدرت مردمیه
-باز کردن امکان گفت و گو از مهم ترین گام ها برای برداشتن قدم به سوی دموکراسیه
-هزینه دادن برای تغییر اجتناب ناپذیره
-حداقل هزینه دادن بهترین حالت برای تغییره
-جنگ ها همیشه بیشترین هزینه ها رو برای تغییر میدن
-جامعه ای که به سوی اگاهی پیش بره و توان استفاده از فرصت مطالبه گری داشته باشه میتونه نجات پیدا کنه
- همیشه بازی بزرگتری وجود داره که نمیبینیمش
- جنگ یه بازی نیست، یه بحث خیلی تکنیکال و پیچیدس
- خیلی از کارای ساده و عمل کردن به یک سری دستور العمل در بحبوحه‌ی جنگ میتونه جلوی خیلی از مشکلات رو بگیره
-دشمن دشمن من، لزوما دوست من نیست
-با هم مهربون تر باشیم، همه داریم احساسات ضد و نقیصی رو تجربه می‌کنیم و حالمون از شرایطی که توش هستیم اصلا خوب نیست
-وسط بحران، داشتن آرامش فکری یک عمل انقلابیه
-آدم میتونه از جنگ زنده بیرون بیاد اما از ناامیدی نه
-ما برای نجات به اگاهی ، گفت و گو و همدلی نیاز داریم نه اسطوره سازی یا نفرت
-فقط دنبال ترند نباش ، یادبگیر تحلیل کنی
-حافظه تاریخی تو نگه دار
-بعدِ جنگ، آدمای زنده‌ی سالم مهم‌ترین سرمایه‌ برای ساختن دوباره‌ن
-توی بدترین شرایط، نفس کشیدن هم یه جور مقاومته
چرا اینترنت؟
عقیده ات مال خودته به زور به کسی فرو نکن!
2025/06/26 22:35:58
Back to Top
HTML Embed Code: