Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request] Support for mutual recursion where the functions have different signatures. #27

Open
elfprince13 opened this issue May 3, 2017 · 0 comments

Comments

@elfprince13
Copy link
Contributor

I'm currently writing a program that utilizes copy-on-write semantics, which means writing a lot code that looks something like this:

class COWList(var v:Int, var n:COWList) {
  var shared:Boolean = false
  def clone():COWThing = { shared = true; this }
  def write(newV:Int = v, newN:COWList = n):COWThing = {
    if(shared){ new COWThing(newV, newN) }
    else { v = newV; n = newN; this }
  }

  @tailrec def final addAndFind(test:Int, delta:Int):COWList = {
    val nullTail = (n == null)
    val newSelf = write(v + delta + (if(nullTail){ 1 } else { 0 }))
    if(nullTail){ None }
    else if(newSelf.v == test){ Some(newSelf) }
    else { newSelf.n.addAndFind(test, newSelf.v) }
  }
}

The implementation of a method like addAndFind is error prone since it's easy to forget to place newSelf. everywhere it should be used, and is a natural fit for mutual tail recursion, since we can fake this = newSelf by calling a method on newSelf immediately.

  @mutualrec def final addAndFind(test:Int, delta:Int):COWList = {
    val nullTail = (n == null)
    write(v + delta + (if(nullTail){ 1 } else { 0 })).addAndFindPost(test, nullTail)
  }

  @mutualrec def final addAndFindPost(test:Int, nullTail:Boolean):COWList = {
    if(nullTail){ None }
    else if(v == test){ Some(newSelf) }
    else { n.addAndFind(test, v) }
  }

There are definitely some work-arounds here, but none of them are nearly as elegant, and there isn't an intuitive reason why this shouldn't work, since it's essentially a resugaring from something that tailrec was happy with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants