A table holds references — commonly funcref — so you can pick a function at runtime. Declare (table 2 funcref) for two slots, or import a table from the host.
WebAssembly Easy · Lesson 1 · On the house
Tables and call_indirect
funcref table, elem init, call_indirect for dynamic dispatch. Lesson 1 is free — on the house.
Lessons · WebAssembly Easy · Lesson 1 of 10 · On the house
Tables and call_indirect
funcref table, elem init, call_indirect for dynamic dispatch.

(elem (i32.const 0) $add $mul) fills table slots starting at index 0 with function references. Active elem segments initialize at instantiate; passive ones need table.init.
call_indirect (type $binop) pops a table index (i32), looks up that funcref, and calls it. The type immediate must match the callee signature or the engine traps.
Compilers use tables for virtual calls, switch-to-call lowering, and dynamic linking. Direct call $name stays cheaper when the target is known; call_indirect is for dynamic dispatch.
Misses: omitting the type on call_indirect, indexing past table size, or putting numeric values in a funcref table instead of function refs.
tables-indirect
(module
(type $binop (func (param i32 i32) (result i32)))
(func $add (type $binop)
local.get 0 local.get 1 i32.add)
(func $mul (type $binop)
local.get 0 local.get 1 i32.mul)
(table 2 funcref)
(elem (i32.const 0) $add $mul)
(func (export "apply") (param $i i32) (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
local.get $i
call_indirect (type $binop)))
Quiz
Quiz
Quiz
Quiz
Check
Match the still for: Tables and call_indirect.
Open-book: the answers are on this page. Pass every quiz and check (5) to mark the lesson done. This visit: 0/5.