Chuyển tới nội dung chính

Biến & Hằng số trong Aiken

Bài học này hướng dẫn cách khai báo và sử dụng biến, hằng số trong Aiken.

Mục tiêu học tập

  • Hiểu cách khai báo biến với let
  • Nắm tính bất biến của dữ liệu
  • Sử dụng hằng số với const

Let Binding - Khai báo biến

Trong Aiken, biến được khai báo với từ khóa let:

lib/main.ak
fn example() {
// Khai báo biến cơ bản
let name = "Cardano"
let age = 7
let is_active = True

// Biến có annotation kiểu (optional)
let amount: Int = 1_000_000
let owner: ByteArray = #"abc123"

name
}

Tính bất biến (Immutability)

Quan trọng: Biến trong Aiken là bất biến - không thể thay đổi sau khi gán:

fn immutability_demo() {
let x = 5
// x = 10 // ❌ Lỗi! Không thể gán lại

// ✅ Thay vào đó, tạo biến mới
let y = x + 5
y // 10
}

Shadowing - Che khuất biến

Bạn có thể khai báo biến mới cùng tên (shadowing):

fn shadowing_demo() {
let value = 10
let value = value * 2 // Shadow biến cũ
let value = value + 5 // Shadow lần nữa

value // 25
}
┌─────────────────────────────────────────────────────────────┐
│ SHADOWING FLOW │
│ │
│ let value = 10 → value = 10 │
│ │ │
│ ▼ │
│ let value = value * 2 → value = 20 (shadow) │
│ │ │
│ ▼ │
│ let value = value + 5 → value = 25 (shadow) │
│ │
└─────────────────────────────────────────────────────────────┘

Const - Hằng số

Hằng số được khai báo ở cấp module với const:

lib/constants.ak
/// Số lovelace trong 1 ADA
pub const lovelace_per_ada = 1_000_000

/// Admin public key hash
pub const admin_pkh = #"abc123def456..."

/// Tên token
pub const token_name = "MyToken"

/// Danh sách whitelist
pub const whitelist = [#"aaa...", #"bbb...", #"ccc..."]

Sử dụng hằng số

lib/main.ak
use constants.{lovelace_per_ada, admin_pkh}

fn calculate_ada(lovelace: Int) -> Int {
lovelace / lovelace_per_ada
}

fn is_admin(pkh: ByteArray) -> Bool {
pkh == admin_pkh
}

So sánh let vs const

Đặc điểmletconst
Phạm viTrong function/blockModule-level
Thời điểmRuntimeCompile-time
ExportKhôngCó (với pub)
Giá trịBất kỳLiterals only

Expect - Khai báo với assertion

expect giống let nhưng sẽ fail nếu pattern không match:

fn expect_demo() {
let maybe_value = Some(42)

// Sẽ fail nếu maybe_value là None
expect Some(value) = maybe_value

value // 42
}

So sánh let vs expect

fn comparison() {
let result = Some(100)

// Với let: Phải handle tất cả cases
let value = when result is {
Some(v) -> v
None -> 0
}

// Với expect: Chỉ handle case mong đợi
expect Some(v) = result
// Nếu result = None -> fail

value
}

Ví dụ thực hành

Code: lib/wallet.ak

lib/wallet.ak
/// Số lovelace trong 1 ADA
pub const ada_to_lovelace = 1_000_000

/// Phí giao dịch tối thiểu (0.17 ADA)
pub const min_fee = 170_000

/// Kiểu dữ liệu ví
pub type Wallet {
owner: ByteArray,
balance: Int,
}

/// Tính số ADA từ lovelace
pub fn to_ada(lovelace: Int) -> Int {
lovelace / ada_to_lovelace
}

/// Tính tổng balance sau khi trừ phí
pub fn net_balance(wallet: Wallet) -> Int {
let Wallet { balance, .. } = wallet
let net = balance - min_fee

if net > 0 {
net
} else {
0
}
}

/// Kiểm tra ví có đủ tiền
pub fn has_sufficient_funds(wallet: Wallet, amount: Int) -> Bool {
let Wallet { balance, .. } = wallet
balance >= amount + min_fee
}

Test: lib/wallet_test.ak

lib/wallet_test.ak
use wallet.{Wallet, ada_to_lovelace, to_ada, net_balance, has_sufficient_funds}

test test_to_ada() {
to_ada(5_000_000) == 5
}

test test_net_balance() {
let w = Wallet { owner: #"abc", balance: 1_000_000 }
net_balance(w) == 830_000 // 1_000_000 - 170_000
}

test test_has_sufficient_funds_true() {
let w = Wallet { owner: #"abc", balance: 1_000_000 }
has_sufficient_funds(w, 500_000) == True
}

test test_has_sufficient_funds_false() {
let w = Wallet { owner: #"abc", balance: 100_000 }
has_sufficient_funds(w, 500_000) == False
}

Code mẫu

Xem code mẫu đầy đủ trong thư mục examples/:

  • lib/syntax.ak - Demo các kiểu dữ liệu và hàm cơ bản
  • lib/syntax_test.ak - Test cases cho syntax
# Chạy tests
cd examples
aiken check

Bước tiếp theo

Trong bài tiếp theo, chúng ta sẽ học về các kiểu dữ liệu nguyên thủy trong Aiken - nền tảng để xây dựng logic phức tạp.