Recursion: Difference between revisions

From JookWiki
(Save current page incarnation)
(Add examples)
Line 1: Line 1:
Warning: This article is a work in progress! No refunds if it moves!
Warning: This article is a work in progress! No refunds if it moves!


TODO: This article is about tail calls
Recursion is a fantastic and often ignored feature of programming languages. Most introductions show an example you'd never use in practice, so this article is my attempt at showing some better ones.


- introduction/overview
==Loops==
Recursion can create loops!


- 'magic of recursion'?
Here's an infinite loop:
function infinite_loop()
  print("Hello there!")
  return infinite_loop()
end
infinite_loop()


- lua
Here's a counting loop:
function count_down(number)
  if number == 0 then return end
  print(number)
  return count_down(number - 1)
end
count_down(100)


- lambdas, etc
Here's a loop that asks a user to pick a valid choice:
 
  function get_choice(choices)
== Function calls==
  local line = io.read()
Let's look at a hypothetical hello world program:
   choice = choices[line]
  function main()
  if choice then
   value = 0
    return choice
   print("Hello world!")
   else
   return value
    print("Invalid choice! Try again")
    return get_choice(choices)
   end
  end
  end
 
print("Select a letter to get a number: A, B, C")
The main function does two things here:
choice = get_choice({A=1, B=2, C=3})
 
print("You picked number " .. choice)
*Creates a variable with the value 0
*Calls the print function with the value "Hello world!"
* Returns with the value of the variable
 
Calling a function is fairly easy:
 
* You save your work and current location
* You set the function's arguments
* You jump to the beginning of the function
 
Returning from a function is just as easy:
 
* You restore the previous work
*You set the return value
* You jump to the previous location
This system works well in most cases.
 
== Tail calls==
 
== Tail call elimination ==
What if we
 
- we've been writing code as there's no stack
 
- tail call elimination
 
- NOT an optimization, how many optimizations decide which way you can program?
 
- hints deeper at function calls vs jumps
 
- structured programming, goto wars
 
==Loops==
- recursion can implement loops!
 
- implementing a for loop
 
- implementing a while loop
 
- implementing a do while loop
 
- each loop iteration only shares global and function args


==State machines==
==State machines==
- implementing a stateful algorithm
Mutual recursion can be used to make state machines!


- some kind of menu system
Here's a tiny adventure game with the player choosing state transitions:
 
function dark_room()
- the code makes sense to read
  print("You are in a dark room.")
 
  print("Pick a door: fuzzy or metal")
- this is mutual recursion
  choice = get_choice({fuzzy=1,metal=2})
 
  if choice == 1 then return fuzzy_room()
- very hard to do in a traditional structured language
  elseif choice == 2 then return metal_room()
 
  end
==Lambdas==
end
- lambdas to actually replace looping constructs/switch statements
function fuzzy_room()
 
  print("This room feels pretty fuzzy...")
- most mainstream languages support lambas
  print("Pick a door: dark, metal")
 
  choice = get_choice({dark=1,metal=2})
- recursion-based control flow
  if choice == 1 then return dark_room()
  elseif choice == 2 then return metal_room()
  end
end
function metal_room()
  print("This room feels really metallic.")
  print("Pick a door: dark, fuzzy or win")
  choice = get_choice({dark=1, fuzzy=2, win=3})
  if choice == 1 then return dark_room()
  elseif choice == 2 then return fuzzy_room()
  elseif choice == 3 then return metal_room()
  end
end
function win_room()
  print("You found the treasure!")
  return
end
dark_room()


==Mainstream support==
==Mainstream support==

Revision as of 04:14, 3 February 2022

Warning: This article is a work in progress! No refunds if it moves!

Recursion is a fantastic and often ignored feature of programming languages. Most introductions show an example you'd never use in practice, so this article is my attempt at showing some better ones.

Loops

Recursion can create loops!

Here's an infinite loop:

function infinite_loop()
  print("Hello there!")
  return infinite_loop()
end
infinite_loop()

Here's a counting loop:

function count_down(number)
  if number == 0 then return end
  print(number)
  return count_down(number - 1)
end
count_down(100)

Here's a loop that asks a user to pick a valid choice:

function get_choice(choices)
  local line = io.read()
  choice = choices[line]
  if choice then
    return choice
  else
    print("Invalid choice! Try again")
    return get_choice(choices)
  end
end
print("Select a letter to get a number: A, B, C")
choice = get_choice({A=1, B=2, C=3})
print("You picked number " .. choice)

State machines

Mutual recursion can be used to make state machines!

Here's a tiny adventure game with the player choosing state transitions:

function dark_room()
  print("You are in a dark room.")
  print("Pick a door: fuzzy or metal")
  choice = get_choice({fuzzy=1,metal=2})
  if choice == 1 then return fuzzy_room()
  elseif choice == 2 then return metal_room()
  end
end
function fuzzy_room()
  print("This room feels pretty fuzzy...")
  print("Pick a door: dark, metal")
  choice = get_choice({dark=1,metal=2})
  if choice == 1 then return dark_room()
  elseif choice == 2 then return metal_room()
  end
end
function metal_room()
  print("This room feels really metallic.")
  print("Pick a door: dark, fuzzy or win")
  choice = get_choice({dark=1, fuzzy=2, win=3})
  if choice == 1 then return dark_room()
  elseif choice == 2 then return fuzzy_room()
  elseif choice == 3 then return metal_room()
  end
end
function win_room()
  print("You found the treasure!")
  return
end
dark_room()

Mainstream support

- functional programming languages

- lua

- clang mustcall

- webassembly