Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type safe method chaining that doesn't allow repeats of operations

I want to implement method chaining like in those questions:

Best practice to implement Scala trait which supports method chaining ;

Scala DSL: method chaining with parameterless methods

However, I want that once a "property" has been used, it cannot be used anymore. For example lets assume that I have a class "Myclass" for which I want to allow the use of definition "foo" and definition "bar" at most once and I don't care about the final return type. Thus:

val c = new Myclass
c foo //ok !
c foo bar // ok!
c foo foo // refuse to compile
c foo bar foo //refuse to compile

I'm struggling with this problem for a while and my vision starts becoming fuzzy! I tried to use implicit classes, however, whether they need to parse objects that has not used the associated property, and I can't find how, whether they need to "consume" the property by removing it from the object available property, and, again, I can't find how.

I'm currently searching in the reflection API, but it is still a little obscure for me.

Help would be appreciated! =)

like image 945
Coo LHibou Avatar asked Jul 26 '13 13:07

Coo LHibou


People also ask

Which of the following is also known as chaining method?

Method chaining, also known as named parameter idiom, is a common syntax for invoking multiple method calls in object-oriented programming languages. Each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results.

What is method chaining Why is it bad?

The drawback to self-referential method chaining is that you communicate that multiple method calls are required to do something, and that each call builds off the last. If this is not true, then method chaining could be communicating the wrong thing to other programmers.

Which method call is chained in JavaScript?

Method chaining is the mechanism of calling a method on another method of the same object. This ensures a cleaner and readable code. Method chaining uses this keyword in the object's class to access its methods. In javascript, the this keyword refers to the current object in which it is called.

How does JavaScript method chaining work?

In method chaining, we call separate methods of a single object like a chain without assigning the same object multiple times by assignment operators. Method chaining works well when we use asynchronous functions with promises. Sometimes we take data from a network which does not synchronous to our code.


1 Answers

See Phantom Types In Haskell and Scala by James Iry.

You could also use type-safe builder pattern:

trait TTrue
trait TFalse

@annotation.implicitNotFound(msg = "Cannot call same method twice.")
sealed abstract class =^=[From, To]
object =^= {
  private val singleton_=^= = new =^=[Any, Any]{}
  implicit def tpEquals[A]: A =^= A = singleton_=^=.asInstanceOf[A =^= A]
}

class Myclass[TFoo, TBar, TBuz] private(){
  def foo(implicit e: TFoo =^= TFalse) = new Myclass[TTrue, TBar, TBuz]
  def bar(implicit e: TBar =^= TFalse) = new Myclass[TFoo, TTrue, TBuz]
  def buz(implicit e: TBuz =^= TFalse) = new Myclass[TFoo, TBar, TTrue]
}

object Myclass{
  def apply() = new Myclass[TFalse, TFalse, TFalse]
}

to be used like this

scala> Myclass().foo.bar.buz
res0: Myclass[TTrue,TTrue,TTrue] = Myclass@12ac706a

scala> Myclass().bar.buz.foo
res1: Myclass[TTrue,TTrue,TTrue] = Myclass@1e69dff6

scala> Myclass().foo.buz.foo
<console>:12: error: Cannot call same method twice.
              Myclass().foo.buz.foo
                                ^
like image 150
senia Avatar answered Nov 04 '22 07:11

senia