compiler icon indicating copy to clipboard operation
compiler copied to clipboard

`RangeError` occurs in CP styled functions

Open magniff opened this issue 4 years ago • 3 comments

Quick Summary: I've been playing with continuation passing styled functions and stumbled upon the code, that seems to confuse the compiler.

Here is the code:

g : Int -> (Int -> a) -> a
g value cont =
    case value of
        1 -> cont 1
        _ -> g (value-1) (\result -> cont (result * value))

Expected: function g computes value's factorial Actual (repl):

> g 1 (Debug.log "result")
result: 1
1 : Int
> g 2 (Debug.log "result")
RangeError: Maximum call stack size exceeded
  • Elm: 0.19.1
  • Browser: no browser (repl)
  • Operating System: ubuntu 20

magniff avatar Aug 17 '21 14:08 magniff

Thanks for reporting this! To set expectations:

  • Issues are reviewed in batches, so it can take some time to get a response.
  • Ask questions in a community forum. You will get an answer quicker that way!
  • If you experience something similar, open a new issue. We like duplicates.

Finally, please be patient with the core team. They are trying their best with limited resources.

github-actions[bot] avatar Aug 17 '21 14:08 github-actions[bot]

This is the compiled output:

var $author$project$T$g = F2(
	function (value, cont) {
		g:
		while (true) {
			if (value === 1) {
				return cont(1);
			} else {
				var $temp$value = value - 1,
					$temp$cont = function (result) {
					return cont(result * value);
				};
				value = $temp$value;
				cont = $temp$cont;
				continue g;
			}
		}
	});

It looks like tail-call optimization accidentally broke capturing of arguments, changing the captured values. This problem is evident in perhaps another simpler example:

f x l = if x == 0 then l else f (x - 1) ((\_ -> x) :: l)
> List.map (\g -> g ()) (f 10 [])
[0,0,0,0,0,0,0,0,0,0]
    : List number

The output should be [10, 9, ... , 1]

tripack45 avatar Aug 20 '21 16:08 tripack45

For people being bitten by this in the future, using https://github.com/micahhahn/elm-safe-recursion is both going to fix this and allow mutual recursion in TCO

miniBill avatar Jun 29 '23 14:06 miniBill