let، mut و state
سه نوع نام و مدل اجرا که پشت آنهاست: مقداری که هرگز عوض نمیشود، مقداری که در هر کندل دوباره تعیین میشود، و مقداری که نگه داشته میشود.
برای خواندن یک اسکریپت باید یک واقعیت را بدانید: کل فایل برای هر کندل از بالا تا پایین دوباره اجرا میشود. نامی که داخل فایل ساخته میشود، در هر کندل دوباره ساخته میشود. سه واژهٔ let، mut و state میگویند یک نام از یک کندل تا کندل بعدی چه سرنوشتی دارد.
مدل اجرا#
در کندل 1 اسکریپت از اولین خط تا آخرین خط اجرا میشود، بعد در کندل 2 هم از اولین خط تا آخرین خط، و همینطور تا جدیدترین کندل. هر چیزی که اسکریپت در یک کندل حساب میکند وقتی کندل تمام شود دور ریخته میشود، مگر آنچه از اسکریپت بخواهید نگه دارد.
| واژه | معنا |
|---|---|
let | مقداری که در هر اجرا یک بار تعیین میشود و در طول همان اجرا هرگز عوض نمیشود. |
mut | مقداری که در هر اجرا از نو شروع میشود و در طول همان اجرا میتواند مقدار تازه بگیرد. |
state | مقداری که اولین بار که اسکریپت اجرا میشود تعیین میشود و از یک کندل تا کندل بعد نگه داشته میشود. |
indicator "Three kinds of name"
edition = 1
state kept = 0
mut capped = high - low
let body = close - open
kept += 1
if capped > 10
capped = 10
plot(kept, name = "state: counts the bars")
plot(capped, name = "mut: this bar's range, at most 10")
plot(body, name = "let: this bar's body", style = histogram)فقط خط state چیزی را به یاد میآورد. در کندل 500ام، kept برابر 500 است؛ capped و body دوباره از قیمتهای همان کندل ساخته میشوند.
indicator "A counter that restarts"
edition = 1
mut count = 0
count += 1
plot(count)اگر میخواهید مقدار نگه داشته شود، بنویسید state. اگر واقعاً میخواهید روی مقدار نهایی کندل قبل ادامه بدهید، آن را با [1] بخوانید:
indicator "Running total from the bar before"
edition = 1
mut total = 0.0
total = (total[1] ?? 0) + (close - open)
plot(total, name = "Running total of bar bodies")total[1] مقداری است که total در کندل قبل با آن تمام شد؛ ?? 0 مقدار اول را که خالی است به 0 تبدیل میکند.
let عوض نمیشود#
دادن مقدار تازه به نام let خطاست. پیام میگوید چه بنویسید:
indicator "Changing a let"
edition = 1
let total = 0
total += 1
plot(total)نوشتن نامی که تعریف نکردهاید هم خطاست (E3102): اول آن را با let، mut یا state تعریف کنید. تعریف یک نام دو بار در یک جا E3101 است. این بررسیها رایجترین لغزش را میگیرند، یعنی غلط تایپیای که در غیر این صورت یک متغیر دوم میساخت و اولی را بدون تغییر میگذاشت.
بدون نسخهٔ پنهان#
انتساب هرگز نام تازه نمیسازد. خطی مثل x = 5، حتی عمیقاً داخل یک if، همان xی را عوض میکند که با mut یا state تعریف کردهاید؛ اگر چنین نامی نباشد خطاست. نامی داخل یک تابع که همنام نامی بیرون از آن باشد مجاز است ولی اخطار میگیرد (W-SHADOW-GLOBAL)، چون تقریباً همیشه اشتباه است.
تابع نمیتواند نام mut یا stateای را که بیرون از آن تعریف شده عوض کند. مقدار را به تابع بدهید و مقدار را از آن بگیرید:
indicator "A function that writes outside"
edition = 1
state hits: int = 0
fn count_up(): int
hits += 1
return hits
plot(count_up())فراخوانیهایی که state نگه میدارند بالای اسکریپت میآیند#
تابعهایی مثل tech.ema، tech.crosses_above و tech.rsi از یک کندل تا کندل بعد حافظه نگه میدارند. هر جای اسکریپت که یکی از آنها را صدا بزنید حافظهٔ خودش را دارد و فقط کندلهایی را به یاد میآورد که آن فراخوانی در آنها اجرا شده است. پس آنها را بالای اسکریپت و در هر کندل صدا بزنید و if را دور کاری بگذارید که با جواب میکنید. اگر یکی را داخل if صدا بزنید، فقط کندلهایی را میبیند که if در آنها درست بوده است:
indicator "Same call, two places"
edition = 1
let always = tech.ema(close, 10)
mut sometimes = na
if bar.index % 3 == 0
sometimes = tech.ema(close, 10)
plot(always, name = "On every bar")
plot(sometimes, name = "Only on every third bar")خط دوم همان میانگین خط اول نیست که فقط بعضی نقطههایش نشان داده شده باشد: میانگینی است که از هر سه کندل فقط یکی را میبیند، و بررسیگر این را با هشدار W3302 میگوید. فراخوانیای که state نگه میدارد، داخل حلقه، به همین دلیل رد میشود (E3301)؛ انتخابها و حلقهها را ببینید.
مقدار نگهداشتهای که دوباره شروع میشود#
state میتواند طبق یک زمانبندی از نو شروع شود. state day در اولین اجرای هر روز معاملاتی از نو شروع میشود، و state session در هر اجرای یک سشن. اینها همراه با سشنها در روز معاملاتی و سشنها آمدهاند.
نگاه کنید به: مقدارها و نوعها، تابعها، نوعها و enumها، اشتباههای رایج.