التلاعب بالمكدس أمر مقبول مع الكلمات القصيرة. وعندما تكون لكلمة عدة مدخلات وتحتاج إلى الإشارة إليها بالاسم، فإن Factor يقدّم المتغيرات المحلية: ارتباطات مسمّاة تُقدَّم بـ :: (لتعريفات الكلمات) أو [| | ] (لامبدا المضمّنة).
:: ( inputs -- outputs )استبدل : بـ ::، فتصبح أسماء المدخلات متغيرات محلية في الجسم:
USING: locals ;
:: hypotenuse ( a b -- c )
a a *
b b *
+ sqrt ;
قارن ذلك بنسخة تبديل المكدس:
! DOCTEST: SKIP (shown for comparison — would re-define hypotenuse)
: hypotenuse ( a b -- c )
[ sq ] bi@ + sqrt ;
كلاهما صالح. تتألق المتغيرات المحلية حين يُشار إلى المدخل أكثر من مرة، أو حين لا يتوافق ترتيب العمليات بطبيعته مع ترتيب المكدس.
:>
داخل جسم :: (أو لامبدا مضمّنة [| ... |])، يسحب :> قيمة من مكدس البيانات ويربطها بمتغير محلي جديد:
value :> name ! immutable binding
value :> name! ! mutable binding (name! is its setter)
الصيغة غير القابلة للتغيير هي الشائعة. استخدمها لتسمية قيمة وسيطة بحيث يُقرأ الجسم من الأعلى إلى الأسفل:
USING: locals math ;
:: average-3 ( x y z -- avg )
x y + z + :> sum
sum 3 / ;
صيغة ! تعلن أن المتغير المحلي قابل للتغيير؛ ولاحقًا في الجسم، تعيد value name! (بدون نقطتين، وبدون :>) إسناد قيمته:
USING: kernel locals math math.order ;
:: clamped ( x lo hi -- y )
x :> v!
v lo < [ lo v! ] when
v hi > [ hi v! ] when
v ;
تتألق المتغيرات المحلية القابلة للتغيير داخل كلمات التكرار التي ستلتقي بها في تمارين لاحقة (مثل while).
[let: نطاق من أي مكانلا يعمل :> إلا داخل نطاق معجمي، وهو ما ينشئه :: و[| ... |] تلقائيًا. لإدخال متغيرات محلية من كلمة : عادية أو عند المستمع، لفّ الكود بـ [let ... ]:
[let code :> name code :> name ... body ]
كل :> name يربط قيمة أعلى المكدس للتعبير السابق؛ وتكون الارتباطات مرئية لبقية الصيغة.
USING: locals math ;
[let 3 :> x 4 :> y x x * y y * + ] . ! => 25
[let هو الجسر بين تعريفات : بأسلوب المكدس والارتباطات المسمّاة، وهو مفيد حين يستفيد جزء فقط من كلمة من المتغيرات المحلية.
[| inputs | body ]
داخل الاقتباس، يُدخل [| inputs | body ] متغيرات محلية يمكن للجسم الإشارة إليها بالاسم. وهذا مفيد بشكل خاص مع الكلمات عالية الرتبة مثل assoc-map، التي يستقبل اقتباسها key و value:
USING: assocs locals ;
H{ { "a" 1 } { "b" 2 } }
[| key value | key value neg ] assoc-map .
! => H{ { "a" -1 } { "b" -2 } }
يعمل النمط نفسه مع map-index (في [sequences][sequences])، الذي يستقبل اقتباسه العنصر و فهرسه. توضّح الأسماء أي معامل يؤدي أي دور:
USING: locals sequences ;
! Divide each element by its 1-based position:
{ 10 80 270 } [| elt i | elt i 1 + / ] map-index .
! => { 10 40 90 }
يتحدد أثر المكدس للامبدا بقائمة المدخلات وما ينتجه جسمها.
استخدم المتغيرات المحلية عندما:
dup/swap/rot لإصلاح ذلك صعبة القراءة.assoc-map).عندما يكون الجسم تدفقًا خطيًا نظيفًا، تبقى تعريفات : العادية أقصر وقابلة للقراءة بالقدر ذاته على الأقل.
assoc-map: مدخل واحد في كل مرةيطبّق assoc-map (في assocs) اقتباسًا على كل مدخل من مدخلات مجموعة ترابطية:
assoc-map ( assoc quot: ( key value -- newkey newvalue ) -- newassoc )
لامبدا المتغيرات المحلية هي أنظف طريقة لكتابة الاقتباس.
cond مرة أخرىعندما تحتاج إلى التفرّع بناءً على f أو على قيمة عددية، يكون cond هو الشكل الصحيح تمامًا، فلا حاجة إلى case لأنه لا توجد قيمة واحدة للمقارنة بها.
لقد عُدتَ إلى المطبخ لتحسين وصفة اللازانيا الواردة في لازانيا ليا اللذيذة. تطلب منك المهام هنا التعامل مع عدة مدخلات في آنٍ واحد، وهنا بالضبط تُثبت المتغيرات المحلية (الارتباطات المسماة في Factor) قيمتها.
عرّف cooking-status بحيث تأخذ قراءة المؤقّت من المكدّس وتُرجع سلسلة نصية تمثّل الحالة.
0 → "Lasagna is done."
f (لم يُضبط المؤقّت مطلقًا) → "You forgot to set the timer."
"Not done, please wait."
12 cooking-status . ! => "Not done, please wait."
0 cooking-status . ! => "Lasagna is done."
f cooking-status . ! => "You forgot to set the timer."
عرّف preparation-time بحيث تأخذ مصفوفة بأسماء الطبقات ومتوسط عدد الدقائق لكل طبقة، وتُرجع زمن التحضير الإجمالي.
{ "sauce" "noodles" "sauce" "meat" "mozzarella" "noodles" } 3 preparation-time .
! => 18
عرّف quantities بحيث تأخذ مصفوفة بأسماء الطبقات وتُرجع قيمتين: عدد غرامات المعكرونة اللازمة (50 غرامًا لكل طبقة معكرونة) وعدد لترات الصلصة اللازمة (1/5 لتر لكل طبقة صلصة).
{ "sauce" "noodles" "sauce" "meat" "mozzarella" "noodles" } quantities .s
! => 100
! => 2/5
يرسل لك صديقك قائمة مكوّنات، والعنصر الأخير فيها هو سرّه. عرّف add-secret-ingredient بحيث تأخذ قائمته وقائمتك وتُرجع قائمتك بعد إلحاق السرّ بها.
{ "noodles" "sauce" "mozzarella" "kampot pepper" }
{ "noodles" "meat" "sauce" "mozzarella" }
add-secret-ingredient .
! => { "noodles" "meat" "sauce" "mozzarella" "kampot pepper" }
تكفي وصفة الكتاب لحصتين. عرّف scale-recipe بحيث تأخذ وصفة (جدول تجزئة يربط اسم المكوّن بكميته) وعددًا مستهدفًا من الحصص، وتُرجع وصفة جديدة مُحجّمة بما يتناسب مع ذلك.
H{ { "noodles" 200 } { "sauce" 1/2 } { "mozzarella" 1 } { "meat" 100 } }
4 scale-recipe .
! => H{ { "noodles" 400 } { "sauce" 1 } { "mozzarella" 2 } { "meat" 200 } }
سجّل في Exercism لتتعلّم وتتقن Factor عبر 47 مفهومًا163 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.