CAML-like scope and binding

It would often be nice, in Scala, if I could re-bind a variable with the same name, and have the evaluated RHS of the evaluating use the shadowed variable. For example.

def foo[V](x:Int):Int = {
  val x = x + 1 // RHS x is the function parameter, not the val being declared.

  doSomeThingWith(x)
}

The reason this would be nice (but of course not critical) is that I’d like the publicly advertised name of the variable to be something understandable by the caller. And I’d also like the local variable name to be something understandable by the person reading the implementation.

This is especially true in a class definition which is NOT a case class. I’d like the argument names in the constructor to be evident to the caller, and I may very well want a field in the class to have the same name.

This pattern is very common in CAML and also in lisp and scheme.

(let ((x 100))
   (let ((x (+ 1 x)))
      ;; x has value 101
      ....)
  ;; x now has value 100
   ...
)

Here is a case in point, given an object dfa:Dfa I’d like to reference dfa.combineLabels, but I can’t. So I’d like to make it a field in the Dfa class. To do so, I have to change the name of the variable in the parameter list of the constructor.

I’ve used the convention of the proto prefix for the argument delta so I suppose I could keep doing that. It works, but I find it lacks elegance.

class Dfa[L,E](Qids:Set[Int], q0id:Int, Fids:Set[Int], protoDelta:Set[(Int,L,Int)], combineLabels:(L,L)=>L, fMap:Map[Int,E]) {

  def exitValue(q:State[L,E]):E =  fMap(q.id)
  def findState(id: Int): State[L,E] = {
    Q.find(s => s.id == id).get
  }
  def delta[L,E](s:State[L,E], label:L):State[L,E] = {
    s.transitions.find(tr => tr.label == label).get.destination
  }
  val Q: Set[State[L,E]] = Qids.map((id:Int) => new State[L,E](dfa=this,id))
  for{
    (from , fromTriples) <- protoDelta.groupBy(_._1)
    fromState = findState(from)
    (to, toFromTriples) <- fromTriples.groupBy(_._3)
    toState = findState(to)
    label = toFromTriples.map(_._2).reduce(combineLabels)
  } fromState.transitions += new Transition(fromState,label,toState)

  val q0: State[L,E] = findState(q0id)
  val F: Set[State[L,E]] = Fids.map(findState)
}

Oh, I see, that class definition is not a good example. I can make combineLabels a field in the class simply be prefixing it with val. That’s nice.