视频课程目录16
全部视频课程

02 · HHY 1.7.0

Values, Bindings, and Collections

Build a user record, update a counter, and distinguish reusable collections from ranges.

4:53 · 英文旁白与字幕

学习进度保存在此浏览器,无需登录。

阅读对应手册章节

章节与讲稿

点击时间跳转视频,展开标题查看讲稿与代码。

Represent a small user record

This lesson turns a few pieces of information into a small, readable data model. We will keep a user record, count a visit, extend a list, and inspect a range. Before executing each example, predict the result. HHY chooses value types at runtime, but clear names and simple checks still matter. A record named user tells the reader more than a variable named data, especially once a script grows beyond a few lines.

values.hhy
let user = { name: "Ada", active: true }
let mut visits = 0
visits = visits + 1
print(user.name)
print(visits)

Follow along with the downloadable example.

Bindings and reassignment

Let introduces a binding. Add mut when the binding needs reassignment, as our visit counter does. The update reads the old counter, adds one, and stores the new value. A plain let binding communicates that the name will keep its assigned value. Start with the simplest binding that matches your intention. Mutability of a binding and the behavior of collection operations are separate ideas; we will inspect collection results explicitly instead of assuming in place updates.

hhy
let name = "Ada"
let mut visits = 0
visits = visits + 1
print(name)
print(visits)

Follow along with the downloadable example.

Recognize basic values

Here are a Boolean, an integer, a floating point number, and null. Null represents absence; it is different from the text null and different from zero. The type function helps inspect a value, while is type checks a named type and returns a Boolean. These functions are useful when learning or handling external data. Prefer an explicit check when a later operation depends on a value being a particular kind.

types.hhy
let enabled = true
let count = 42
let ratio = 0.75
let missing = null
print(type(count))
print(is_type("HHY", "String"))

Follow along with the downloadable example.

Keep a reusable list

A list stores values in order and can be kept for reuse. Append returns an extended list, so assign that result to a name. Printing both names demonstrates the distinction: original still contains two entries, while extended has three. Length tells us how many entries are present. This is a helpful habit for unfamiliar APIs: keep the input, capture the output, and observe both before building more logic on top of them.

hhy
let original = ["Flow", "System"]
let extended = append(original, "Pipe")
print(original)
print(extended)
print(length(extended))

Follow along with the downloadable example.

Read and update maps

A map associates keys with values. This example uses named fields so the source reads like a compact record. Dot access reads the known name field. Get is useful when the key is chosen as a string, and a missing key returns null. Put produces an updated map; capture that result as we did with append. Do not treat a missing key as proof that a numeric field contains zero. Decide how your application handles absence.

hhy
let user = { name: "Ada", active: true }
let updated = put(user, "visits", 1)
print(user.name)
print(get(updated, "visits"))
print(get(user, "missing"))

Follow along with the downloadable example.

Ranges describe a sequence

A range describes a sequence of numbers without spelling each number in a list. Run this example and inspect its endpoint behavior: zero, one, and two are printed, while three is the exclusive end. This distinction prevents off by one mistakes. A for loop can visit the range directly. In a later lesson we will convert ranges into streams when we want the lazy transformation operators rather than an explicit loop.

hhy
let indexes = 0..3
for index in indexes {
    print(index)
}

Follow along with the downloadable example.

Use units intentionally

HHY also has literal forms for quantities such as duration, size, and percentage. They express intent more clearly than unexplained numbers. In the tested runtime, five seconds prints as five billion nanoseconds, and ten mebibytes prints as ten million four hundred eighty five thousand seven hundred sixty bytes. The displayed unit can differ from the source spelling. These literals will become useful for timeouts and size filters; do not replace them blindly with plain integers.

units.hhy
print(5s)
print(10mib)
print(80%)

Follow along with the downloadable example.

A deliberate binding error

This deliberately broken example reassigns a binding that was not declared mutable. Run the separate error file to see the diagnostic, then compare it with the working counter. The repair is to declare the counter with let mut when repeated updates are part of the design. Do not change every binding to mutable just to silence one error. Keep the lesson small: identify the name being reassigned and explain why that name needs to change.

immutable-error.hhy
let visits = 0
visits = visits + 1
# Fix: declare let mut visits = 0

Follow along with the downloadable example.

Practice a second user

For practice, create another user, add a visit count, and print selected fields rather than depending on the display order of map keys. Then create a list of two user maps and check its length. You now have the basic shapes needed for real scripts: single values, stable and mutable bindings, ordered lists, keyed maps, and ranges. Next we will put decisions and repeated work around those values using functions and control flow.

hhy
let user = { name: "Grace", active: false }
let updated = put(user, "visits", 2)
print(updated.name)
print(get(updated, "visits"))

Follow along with the downloadable example.