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


#1

سلام دوستان
بازم من اومدم با یک سوال بحث برانگیز دیگه :smile:
البته شک ندارم که شما اساتید عزیز به خوبی پاسخ میدید

دوستان در کتابی راجع به زبان الکسیر خوندم که متغیرهای ایشون immutability هستند یعنی یکبار مقداردهی میشن و بعد امکان تغییر مقدار نیست. درحالیکه وقتی در iex متغیری مثلا به اسم x تعریف می کنم با مقدار ۲ اگه بعدش بنویسم x = ۵ این رو می پذیره و خطا نمی گیره. در داکیومنت الکسیر گفته این قابلیت rebind نام داره.

حالا من کمی گیج شدم. اگه rebind اجازه میده محتوای متغیر رو عوض کنیم اینجا دیگه مفهوم immutability زیر سوال میره!

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

سپاس فراوان :pray:


دسته‌بندی جدید با عنوان «مهندسی کامپیوتر»
#2

اصلا متغیری در الیکسر وجود نداره - یعنی نه به اون معنی که در زبان های imperative هست - علاوه بر نبودن متغیر چیزی به نام assignment یا assign کردن هم وجود نداره. این برای بیسیک ماجرا بود.

تمامی داده ها نه تنها در الیکسر که کلا در پرادایم فانکشنال غیر قابل تغییره پس واقعا به قول شما چه اتفاقی میوفته؟

هر وقت در الیکسر از عبارت = استفاده کنیم کاری که الیکسر میکنه اینه که سعی میکنه از سمت چپ به راست راهی برای تطبیق دادن المنت ها پیدا کنه، یعنی مثلا برعکس روبی یا پایتون که = برای اختصاص دادن - assignment - بکار میره همین علامت در الیکسر به معنی تساوی مثل تساوی در عبارات ریاضی هست.
اگر سمت چپ و راست به شکلی برابر باشند و تطبیق پیدا کنند مقادیر در سمت راست به المنت های سمت چپ بایند میشن.

به مثال زیر توجه کنید

foo یک نام هست که میتونه با هر چیزی برابر باشه پس در هر زمانی که در سمت چپ تساوی قرار بگیره مقدار سمت راست به اون بسته میشه. اما این معنیش این نیست که در داده ها تغییری ایجاد شده، فقط foo به داده جدید بسته شده و در اصل با داده جدید یکی شده، برای همین وقتی a به foo بایند شد، بعد ۱۰ از چپ به راست با a برابر میشه.
اما وقتی foo به پنج بسته شد دیگه مقدار بسته شده به foo یعنی ۵ با a که 10 بود برابر نیست.

foo = 10
a = foo
10 = a 
foo = 5
5 = a  error

#3

پاسخ ادامه داره؟ :thinking:


#4

بله، اضافه کردم،


#5

میشه یه توضیحی راجع به این بدید:

x = 2
x = 5
x = 12

و همینطور الی آخر
این چند خط رو توضیح میدید؟
الان اینجا مقدار ۲ داریم که اسم x بهش دادیم. بعدش ۵ داریم که اسم x میدیم. بعدشم ۱۲ که بازم اسم x میدیم؟


#6

x یک نام هست که میتونه با هر کدوم از اونها برابر باشه اما این ربطی به immutability نداره، در هر خط x به دیتای جدید بسته شده. در عمل این کار باعث خطا نمیشه چون اعداد و x ممکنه از بسته بودن به هم خارج بشن اما دیتا قابل تغییر نیست. و همین دلیل میشه که در زبان های فانکشنال loop نداشته باشیم و بجاش از recursion استفاده کنیم.


#7

یکم پیچیده‌ست. هرچی فکر می کنم متوجه نمیشم
الان اینجا دو مفهوم داریم. یکی بایند شدن و یکی pattern match درسته؟
من تو این کد از کجا تشخیص بدم کدوم بایند شدنه و کدوم خط تکنیک pattern match اتفاق میفته؟


#8

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


#9

حالا اینو تست کن

[z, 1] = [2, 1]

و این

[x, 1] = [2, 3]

در مورد immutability هم توضیح میدم اما بهتره اول بیسیکترین مورد الیکسر برات جا بیوفته


#10

فکر کنم خطا میده چون در خط دوم ۱ برابر ۳ نیست. در بقیه حالات x و z مقدار می گیرن :thinking:


#11

میتونی بگی در مثال بالا مقدار x و z چیه؟


#12

مقدار هردوشون ۲ هست


#13

اما الیکسر و من در مورد x با شما مخالف هستیم چون وقتی چپ و راست قابل تطبیق نباشند کل ماموریت کنسل میشه و چیزی بایند نمیشه. اما در مورد z حق با شماست.


#14

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

بیا یکم روبی کار کنیم:

a = {e: 1, c: 2, d: 4}
b = a
b[:e] = 1000
puts a

#15

آهااااااا. من فکر می کردم فقط اون آیتمی که مطابقت نداره بایند نمیشه ولی بقیه اعضای لیست بایند میشن


#16

بلد نیستم ولی بنویسید شاید متوجه بشم


#17

چه زبانی براتون راحته همونو بگید که من با اون مثال بزنم. بشرطی که خودم بلد باشم.
یا اگر روبی دارید روی سیستم کد بالا رو امتهان کنید و ببینید که چه بسر دیتا میاد


#18

جاوا، سی شارپ


#19

روبی ندارم ولی فکر کنم کدش رو متوجه شدم. شما یک tuple تعریف کردید به اسم a. بعدش یک tuple دیگه تعریف کردید به اسم b که اگه اشتباه نکنم a داخلش کپی میشه. حالا اینکه کپی میشه یا رفرنس مطمئن نیستم. بعدشم میگید آیتمی که کلیدش e هست مقدارش بشه ۱۰۰۰. در نهایت همون a اولی رو چاپ می کنید. ولی بسته به اینکه کپی بود یا رفرنس خروجی متفاوت میشه


#20

mutable data passed by reference :open_mouth::open_mouth::open_mouth::open_mouth::open_mouth::open_mouth:

ببینید در مثال زیر چه بلایی سر a اومده بدونه اینکه کسی بخواد تغییرش بده، البته میشه جلوی این موضوع رو با clone کردن گرفت و یک کپی جدید از a رو به b اختصاص داد، اما این مشکل در FP کلا وجود نداره. همونطور که در C# هم string literal ها read only یا frozen هستند و‌نمیشه تغییرشون داد.
مثلا اگر

a = “abcd”

بود دیگه نمیشد تغییرش داد و تا هدی فانکشنال بود.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            int[] a = {1, 2, 3, 4, 5};
            var b = a;
            b[2] = 10;
            Console.WriteLine(a[2]);
        }
    }
}

C# ندارم برای همین توی سایت زیر کدو نوشتم، اگر اشتباهه اصلاح کنید لطفا

https://rextester.com/