Lua Notes

compile-time FizzBuzz
Login

compile-time FizzBuzz

Consider:

require 'string'

local function fb(n: integer)
  local by3 = 0 == n % 3
  local by5 = 0 == n % 5
  if     by3 and by5 then return 'FizzBuzz'
  elseif by3         then return 'Fizz'
  elseif by5         then return 'Buzz'
  else                    return string.format('%d', n) end
end

for i=1, 100 do print(fb(i)) end

This works, but if you look around you may be struck by how easily a Nim or a Zig or a Lisp programmer can take similar code and do it all at compile-time. Can Nelua do that too?

Option 1.) implement it in Lua instead

Typically there's still some restructuring of the code to get it to be suitable for a compile-time calculation. Most problems don't have fixed [1,100] bounds like this, but also the shift to compile-time tends to come with a shift towards producing a single large datastructure instead of producing a sequence of I/O calls. That's not so different from writing the program in a completely different language, right? At least not when the completely different language is Lua, from Nelua:

##[[
local function fb(n)
  local by3 = 0 == n % 3
  local by5 = 0 == n % 5
  if     by3 and by5 then return 'FizzBuzz'
  elseif by3         then return 'Fizz'
  elseif by5         then return 'Buzz'
  else                    return string.format('%d', n) end
end
local function fizzbuzz()
  local lines = {}
  for i=1, 100 do
    lines[i] = fb(i)
  end
  return table.concat(lines, '\n')
end
]]

print(#[fizzbuzz()]#)

Option 2.) Compile while compiling

Rewriting it in Lua (RIIL) may not always be practical. So instead, add a separate entrypoint to your codebase and reuse your code in a program that does what's required.

local M = @record{}

function M.fb(n: integer): string
  local by3 = 0 == n % 3
  local by5 = 0 == n % 5
  if     by3 and by5 then return 'FizzBuzz'
  elseif by3         then return 'Fizz'
  elseif by5         then return 'Buzz'
  else                    return string.format('%d', n) end
end

##[[
function generate_cache()
  local file = io.popen("nelua -P emit_fb_cache -i 'local FB = require(\"fizzbuzz\") FB.fizzbuzz()'")
  local cache = file:read('*a')
  file:close()
  return cache
end
]]

function M.fizzbuzz(): string
  ## if pragmas.emit_fb_cache then
    for i=1, 100 do print(M.fb(i)) end
    return ''
  ## else
    return #[generate_cache()]#
  ## end
end

return M