ابهام در عملکرد rebind و immutability! مسئله این است!


#21

پس دیتا - البته بجز مواردی مثل string literals و tuple - در c# قابل تغییره، حالا اگر الیکسر به هر دلیلی به آمپلی فایر وصله بهتره سعی نکنید که یک آرایه رو تغییر بدین چون احتمال داره شیه های خونه خورد بشه.

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

راستی چرا خبری از @shahryarjb نیست؟ :hugs:


#22

خیلی ممنونم که وقت گذاشتید :pray:


#23

خواهش میکنم، امیدوارم چیز بدردبخوری گفته باشم


#24

FYI در روبی tuple نداریم. این hash و mutable هست, مثل دیکشنری در C#.

{a: 1}

#25

توماج جان بحث ها بحث های سختی هستند .دوستان حرفه ای مثل شما و @samdvr عزیز هستند . من خودم همیشه این مورد برام با اینکه متوجه شدم گنگه بخاطر همین کلا بی خیالش شدم :grinning: کار اشتباهی کنم کنسول ارور می ده :blush:


#26

با اجازه از دوستان.

این رو ببین :
x = 2
x1 = 5
اگر مثالی که زدی به شکل بالا بود، در Immutable بودن شک نمیکردی، درسته؟

حالا این رو ببین :
x = 2
x = 5
اینجا به نظر میاد که اصل Immutability نقض شده، نه؟

واقعیت ماجرا چیز دیگه ای هستش!
این مشکل به دلیل درک نادرست راجع به مفهوم Immutability بوجود میاد.
مشکلی که هست اینه که خود کلمه variable توی مخصوصا زبان های Functional مشکل ساز شده برای کسانی که با پیش زمینه زبان های Imperative برای یادگیری میان، چون خود کلمه داره میگه من تغییر میکنم.

پس مفهوم درست Immutability چیه؟
Immutability به این معناست که اون چیزی که variable به اون refer میکنه، یعنی value، قابل تغییر نیست، نه خود variable. یعنی اینکه اون memory location که اون value داخلش هست تغییر نمیکنه ولی اون variable که به اون memory location داره refer میکنه قابل تغییره.

مثال : x = 1
متغیر ما x هستش و به عدد یک refer میکنه.
Immutability به این معنیه که اون عدد یک که در memory هستش و x بهش refer میکنه چیزیه که تغییر نمیکنه، نه خود x !
در واقع x یه Label هستش برای اون memory location و اون عدد یک، و وقتی ما x = 5 رو میبینیم، به این معنیه که الان x داره به عدد پنج و به یه memory location جدید داره refer میکنه و اگه باز به چیز دیگه ای refer کنه، اون ۲ تا memory location که اون عدد یک و پنج اونجا هستن، تغییر نمیکنن، بلکه فقط value های جدید در memory location های جدید قرار داده میشه و variable ما حالا به اون جدید ها داره refer میکنه.

چاره چیه؟
چاره اینه که نحوه تفکر راجع به مفهوم variable و Immutability رو تغییر بدیم، مقایسه زیر رو ببین :

  • در زبان های Imperative :
    در این زبان ها، مفهوم varibale به این معنی هستش که ما یه جعبه داریم به اسم x و یه چیزی توی این جعبه قرار میدیم، ولی اون چیزی که توی جعبه هستش تغییر میکنه، نه خود جعبه: الان سیب توی جعبه قرار میدیم و بعدش این سیب به طرز شگفت انگیزی(!) تبدیل میشه به پرتقال و بعدش تبدیل میشه به گلابی و . . .
    یعنی اون value که در اون memory location بود پاک میشه و جاش یه چیز دیگه میاد.
    سیب پاک میشه و گلابی جاش میاد!
    خود variable ما ثابته ولی اون چیزی که داخلش هست تغییر میکنه.

  • ولی در زبان های Functional :
    در این زبان ها variable به اون معنی نیستش. تو این زبان ها بهتره که از واژه Label استفاده بشه به جای variable که فهم موضوع ساده بشه. یعنی ما یه برچسب داریم به اسم x که الان زدیمش رو پیشانی یه سیب و بعدش زدیمش رو پیشانیه یه پرتقال و . . .
    یعنی اون value که در اون memory location بود ثابت هستش و یه memory location جدید ساخته میشه که variable ما الان به اون جدیده داره refer میکنه.
    خود اون سیب و پرتقال تغییری نمیکنن، ما فقط برچسب رو برداشتیم و زدیم رو چیز دیگه ای، یعنی خود اون چیزی که variable بهش refer میکنه ثابت هستش ولی خود variable تغییر میکنه، که اینجا میگن variable ما rebind شده، یعنی اصلا به یه چیز دیگه داره refer میکنه الان.
    سیب سر جاش ثابته، برچسب رو از پیشانیش برمیداریم و رو پیشانی یه گلابی که یه جای دیگه قرار داره الصاق میکنیم!

خلاصه :
پس در elixir ، یک variable بیشتر مثل یک Label هستش برای یک value جدید، نه مثل یه جعبه برای یه چیزی که تغییر میکنه.
خود اون چیزی که variable بهش refer میکنه ثابت هستش ولی خود variable تغییر میکنه و به اصطلاح rebind میشه به یه چیز دیگه.

البته مفاهیمی مثل Lexial scoping و Closure ها و Pattern-matching و غیره هم تاثیر گذار هستن که در این پست جای بحث راجع به اونها نیست.

در لینک زیر خود سازنده elixir راجع به این موضوع که چرا variable ها re-bindable هستن، صحبت کرده :


#27

توضیح خوبی بود :+1:

در زبانهای فانکشنالی که من کار کردم مثل Haskell , Clojure و Elixir کلا واژه Variable وجود نداره و بجاش Data Binding داریم. البته مدتیه که جامعه Elixir از کلمه Variable استفاده میکنه چون در Erlang هم این کاربرد وجود داره و Elixir در اصل یک Transpiler به Erlang هست. در اصل variable ها expression هستند.

A variable is an expression. If a variable is bound to a value, the return value is this value. Unbound variables are only allowed in patterns.

http://erlang.org/doc/reference_manual/expressions.html

در مورد pattern matching هم باید بگم که تقریبا اولین اتفاقیه که در هنگام binding میوفته و اساس data binding در elixir بحساب میاد.


#28

یک انبار بزرگ رو در نظر بگیر که توش میتونی جعبه های مختلف بزاری .
وقتی میگی x=2
یعنی من روی یک جعبه برچسب x زدم و درونش عدد 2 رو گذاشتم و داخل انبار قرار دادم !
وقتی میگی x = 3
یعنی من برچسبی که روی جعبه اول زده بودم رو کَندم و روی این جعبه جدیده گذاشتم و درونش هم عدد سه رو قرار دادم ! این یعنی قوطی اول هنوز سرجاشه و درونشم عدد 2 هست اما دیگه تو برچسب رو ازش کَندی و روی یه قوطی دیگه گذاشتی :blush:
وقتی میگی x = 7
یعنی از جعبه دومی که داخلش عدد 3 بود دوباره اون برچسبی که رو نامش x بود برداشتی و به یه جعبه دیگه که داخلش 7 هست چسبوندی !
تمام جعبه های 1,2,3 سرجاشون هستن فقط سومی برچسبی بنام x داره ولی اون دوتا ندارن
برای الکسیر هم یه حالتی شبیه این نظر بگیر ! x رو فقط یک نام فرض کن که آدرس داده ها رو تو خودش نگه میداره و تو هربار آدرس یک جعبه جدید رو بهش میدی پس دلیلی نمیشه محتوای جعبه ای که برچسب(اسم) رو ازش کَندی تغییری بکنه فقط تو برچسب رو ازش کندی و داده مثل یه تازه داماد شاخ و شمشاد سرجاشه :smile:


#29

در ضمن هیچوقت دوتا جعبه نداریم که محتوای مشابهی داشته باشند چون نه لازمه و نه امکانش هست و این سرعت و اعتمادپذیری کارمونو به طرز عجیبی بالا میبره :zap::zap::zap:


#30

بچه ها نمیشه به این پاسخ ۱۰ تا لایک داد؟ :heart_eyes:
توضیحاتت فوق العاده بود واقعا ممنونم
با اینکه دوست عزیزم @toomaj خیلی زحمت کشیدن و وقت زیادی گذاشتن و واقعا برام ارزشمنده و ازشون باز هم تشکر می کنم. ولی حتی بعد مثال سی شارپ هم باز قضیه برام جا نیفتاده بود.
اما فکر می کنم با مثال شما بهتر موضوع رو فهمیدم.

اگه بخوام به شیوه‌ای ساده بگم میشه گفت که ما لیترال‌هایی داریم که در برنامه ازشون استفاده می کنیم. حالا این داده ها هر کدوم می تونه برچسبی داشته باشه و می تونه نداشته باشه. وقتی میگیم Immutability یعنی اون لیترال‌ها قابل تغییر نیستن. و وقتی برچسبی ریبایند میشه درواقع لیترال‌های قبلی از دسترس خارج میشن. اینجاست که موضوع Immutability هایلایت میشه.

یعنی در اصل ما چیزی به اسم متغیر نداریم بلکه مقادیری داریم که به هرکدوم راهی برای ارجاع و دسترسی به اون پیدا می کنیم. حالا موقع ریبایند ارتباط با داده های قبلی قطع میشه.

درست گفتم آیا؟ :smiley:


#31

مثلا در اینجا:
a = 5

داده ای داریم با مقدار ۵ که توسط برچسب a بهش دسترسی داریم و می تونیم بخونیمش ولی نمی تونیم عوضش کنیم. یعنی ۵ رو نمیشه کرد ۳. حالا اگه باز بنویسیم:
a = 12

ایندفه برچسب a به داده دیگه ای اشاره می کنه که مقدارش ۱۲ هست که باز read-only هست. حالا دیگه a نمی تونه مقدارهای قبلی رو در اختیار ما بزاره. اونها در اصل وجود دارن ولی در دسترس ما نیستن. البته تو مستندات الکسیر خوندم که با ^ میشه دوباره رفت سراغ داده قبلی:
a = ^a

ولی قبلیها رو دیگه نمیشه بدست آورد.
مفهوم Immutability هم یعنی اینکه داده ها رو نمیشه عوض کرد. مثلا در بالا ۵ و ۱۲ رو نمیشه چیز دیگه ای کرد.

اساتید درست گفتم؟


#32

عالی بود مهندس.
حالا چون برچسب رو روی جعبه سومی زدم دیگه به داده هایی که در جعبه های یک و دو بود دسترسی ندارم. درسته؟


#33

متغیری وجود نداره :+1::+1::+1:
فقط یک مورد کوچیک هست، اونم اینه که وقتی x = 5 باند شد دیگه x و 5 یکی هستند مگر اینکه x به داده دیگه ای بایند بشود.
در مورد فانکشن ها هم به هین صورت، فانکشن همون دیتاست و برعکس، خروجی فانکشن همیشه بر اساس ورودی قابل پیشگوییه.
حالا ممنکه کسی بپرسه پس randdom چطور؟ اونم نکته خودشو داره و از قواعد fp پیروی میکنه


#34

تو کتابای پایه راجع به برنامه نویسی (در مورد زبانهای imperative)، معمولاً نویسنده هاشون میان توضیح میدن که متغیر تو زبان برنامه نویسی با متغیری که تو ریاضیات ازش صحبت میشه، فرق داره.و کلی طول میکشه تا یه آدم مبتدی اینو درک کنه و ذهنیتش رو عوض کنه.
ولی تو زبانای فانکشنال متغیر همون رفتاری رو داره که تو ریاضی ازش میبینیم و لازم نیست طرز فکرمون رو عوض کنیم؟ از صحبتایی که شد من اینو فهمیدم.


#35

من که استاد نیستم ولی درست بود :slightly_smiling_face::rose:
اون ( ^ ) هم کاری که میکنه اینه که از re-binding جلوگیری میکنه.
در اصل در elixir، علامت (=) به معنای assigning نیست، به معنای match کردن چپ و راست هستش.


#36

آره دیگه انگار یه کتابه که روش یه کاغذ چسبوندی « هنوز نخوندمش!» . بعد از اینکه کتاب رو خوندی تموم کردی اون کاغذی که چسبوندی رو برمیداری و کتاب رو میدی به دوستت میگی بیا بخون باو کچلم کردی ! خب اینجا کتاب از دسترس تو خارج میشه و میره دست دوستت و یادت باشه تو برچسب کاغذی که روش زده بودی برداشتی و کتاب الان دست دوستت هست و اونم بخونه تموم کنه میده به اون یکی دوستت که اونم میخواد بخونه ! تو این مثال دوستها همان توابعی هستن که به کتاب احتیاج دارن و ازش استفاده میکنن و بالاخره کار همه از کتاب تموم شد میندازنش آشغال! تو برچسب رو از کتاب کَندی ولی دوستات که همون توابع و… هستند ازش استفاده میکنند و بعد که تموم شد محو میشه میره


#37

دقیقا درست درست فهمیدی ! یه جعبه در نظر بگیر که فقط یکبار میتونی داخلش چیزی بزاری و بعد اون قفل میشه و اجازه نمیده داخلش چیز جدید بزاری یا عوض کنی