iyi

Playground

samples/iyi/basics.iyi

The first half hour — what a person writes before they write anything real.

samples/iyi/basics.iyi · iyi-basics.wasm · 205 KB
# The first half hour — what a person writes before they write anything real.
#
#   ./bin/iyi run samples/iyi/basics.iyi
#
# The other samples each document a rule. This one documents nothing: it is
# here because the prelude grows only when a program in this repository needs
# something (SPEC.md 0.1.0 item 3), and a person meeting the language writes
# these six programs before they write a module. Every method this file calls
# is one somebody reached for in their first half hour and did not find.
module samples/basics

# 1. Counting, with a range rather than a `while`.
total = 0
(1..10).each { |i| total = total + i }
puts total # => 55

# 2. FizzBuzz, because it is the first thing anybody types.
(1..15).each do |i|
  if i % 15 == 0
    puts "FizzBuzz"
  elsif i % 3 == 0
    puts "Fizz"
  elsif i % 5 == 0
    puts "Buzz"
  else
    puts i
  end
end

# 3. Picking things out of a list.
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
puts numbers.first                          # => 3
puts numbers.select { |n| n > 3 }.join(",") # => 4,5,9,6
puts numbers.includes?(9)                   # => true
puts numbers.sorted.join(",")               # => 1,1,2,3,4,5,6,9
puts numbers.join(",")                      # => 3,1,4,1,5,9,2,6, untouched

# The pair. `sorted` hands back a copy and `sort_in_place` changes the array,
# and the second one is spelled out on purpose: Crystal calls the copy `sort`
# and the mutating one `sort!`, a name that cannot be written here, so a plain
# `sort` would mean one thing in this library and the opposite in Crystal's
# (SPEC.md III.1.7a).
numbers.sort_in_place { |a, b| a < b ? -1 : (a == b ? 0 : 1) }
puts numbers.join(",") # => 1,1,2,3,4,5,6,9

# 4. Adding them up two ways.
puts numbers.sum                        # => 31
puts numbers.reduce(0) { |a, b| a + b } # => 31

# 5. Text.
greeting = "Hello, World"
puts greeting.downcase           # => hello, world
puts greeting.includes?("World") # => true
puts greeting.size               # => 12

# A character is a byte here, and its code is a number to do arithmetic on:
# the Caesar shift every second program is.
shifted = ""
greeting.each_char do |c|
  if c.letter?
    base = c >= 'a' ? 'a'.ord : 'A'.ord
    shifted = shifted + ((c.ord - base + 3) % 26 + base).chr.to_s
  else
    shifted = shifted + c.to_s
  end
end
puts shifted # => Khoor, Zruog

# 6. Counting words, which is where a dictionary earns its place.
counts = {} of String => Int32
["a", "b", "a", "c", "a"].each do |word|
  counts[word] = (counts[word]? || 0) + 1
end
puts counts["a"] # => 3
puts counts.size # => 3
puts counts      # => {"a" => 3, "b" => 1, "c" => 1}, in the order they went in

# 7. The second half hour: the same count over real text, and the five most
# frequent words in order. Splitting text into words is a walk over its
# characters, a dictionary's pairs go into an array to be sorted, and the
# sort takes a key rather than a comparison.
text = "the cat sat on the mat; the mat sat under the cat. THE END"
word = ""
words = [] of String
text.each_char do |c|
  if c.alphanumeric?
    word = word + c.to_s
  elsif !word.empty?
    words << word.downcase
    word = ""
  end
end
words << word.downcase unless word.empty?
puts words.size # => 14

frequency = {} of String => Int32
words.each { |w| frequency[w] = (frequency[w]? || 0) + 1 }
pairs = [] of Tuple(String, Int32)
frequency.each { |w, n| pairs << {w, n} }
pairs.sort_in_place_by { |pair| -pair[1] }
pairs.first(3).each { |pair| puts "#{pair[0].ljust(5)} #{pair[1]}" }
# => the   5
# => cat   2
# => sat   2
puts pairs.sorted_by { |pair| pair[0] }.first(2).map { |pair| pair[0] } # => ["cat", "end"]
output
Press Run.

recorded with iyi 0.18.0 (built on Crystal 1.22.0-dev [2a9653052] (2026-10-18)) · Linux 7.0.0-38-generic x86_64, QEMU Virtual CPU version 2.5+ · 2026-10-19

You can type in the pane: nothing here compiles, so what you type cannot run, and the page says which bytes it is running the moment the text stops being the recorded file. There is no standard input, no filesystem and no threads on this target, and one sample fails on purpose for exactly that reason.

Run executes iyi-basics.wasm, the module the compiler built from this file, in your browser. How this works

Try it on your machine

Copy the program into basics.iyi, change something, and run it. Only a compiler on your own machine can run what you wrote.

sh, after installing
$ iyi run basics.iyi