how to define Operator for {Double * myType}?

View: New views
12 Messages — Rating Filter:   Alert me  

how to define Operator for {Double * myType}?

by Kubitz, Jörg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.

  casflow*2

does work, but how to get

  2*cashflow

done?

 

Its not possible to wrap the scalar value 2 to a cashflow.

 

Is there a trait for adding Commutativity? Can such a trait be implemented in general?

 

import scala.collection.mutable.Map

class cashflow(currency:String){

  val flow = Map[Int, Double]()

  def add(date: Int,cash:Double)=flow+= date -> cash

  def *=(scalar:Double)=flow.transform((date: Int,cash:Double) => cash*scalar)

  def *(scalar:Double):cashflow={var c=this.clone;c*=scalar; return c}

  def print()= flow foreach {case (key, value) => println (key + "-->" + value)}

  override def clone():cashflow={

    val c= new cashflow(currency)

    flow foreach  {case (key, value) => c.add(key+0,value+0)}

    return c

  }

}

 

 

object t1 extends Application {

 

  var cf= new cashflow("EUR")

  cf.add (1,2)

  cf.add (3,5.4)

  var d=cf*2

  println("d")

  d.print

}


Re: how to define Operator for {Double * myType}?

by Kevin Wright-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sounds like a classic case for the "pimp my library" pattern!

You need an implicit conversion from Double (or Int, or Whatever) to
some anonymous class that CAN bet multiplied by a cashflow.

inlining here will mean that it's not as expensive as it might first seem

On Mon, Nov 9, 2009 at 3:20 PM, Kubitz, Jörg <jkubitz@...> wrote:

>   casflow*2
>
> does work, but how to get
>
>   2*cashflow
>
> done?
>
>
>
> Its not possible to wrap the scalar value 2 to a cashflow.
>
>
>
> Is there a trait for adding Commutativity? Can such a trait be implemented
> in general?
>
>
>
> import scala.collection.mutable.Map
>
> class cashflow(currency:String){
>
>   val flow = Map[Int, Double]()
>
>   def add(date: Int,cash:Double)=flow+= date -> cash
>
>   def *=(scalar:Double)=flow.transform((date: Int,cash:Double) =>
> cash*scalar)
>
>   def *(scalar:Double):cashflow={var c=this.clone;c*=scalar; return c}
>
>   def print()= flow foreach {case (key, value) => println (key + "-->" +
> value)}
>
>   override def clone():cashflow={
>
>     val c= new cashflow(currency)
>
>     flow foreach  {case (key, value) => c.add(key+0,value+0)}
>
>     return c
>
>   }
>
> }
>
>
>
>
>
> object t1 extends Application {
>
>
>
>   var cf= new cashflow("EUR")
>
>   cf.add (1,2)
>
>   cf.add (3,5.4)
>
>   var d=cf*2
>
>   println("d")
>
>   d.print
>
> }

Re: how to define Operator for {Double * myType}?

by Paul Phillips-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
> Is there a trait for adding Commutativity? Can such a trait be
> implemented in general?

In general? No.  Your problem is that * already exists on Double, and
the error of calling that with the wrong type trumps an implicit
conversion (maybe that could change, but it feels unlikely.) If you pick
a fresh operator you can do this, or a more efficient equivalent.

implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2 }

--
Paul Phillips      | Every normal man must be tempted at times
Stickler           | to spit on his hands, hoist the black flag,
Empiricist         | and begin to slit throats.
i pull his palp!   |     -- H. L. Mencken

Re: how to define Operator for {Double * myType}?

by Kevin Wright-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
>> Is there a trait for adding Commutativity? Can such a trait be
>> implemented in general?
>
> In general? No.  Your problem is that * already exists on Double, and
> the error of calling that with the wrong type trumps an implicit
> conversion (maybe that could change, but it feels unlikely.)


Ouch! Looks like we have another candidate for Scala puzzlers...
We live and learn :)


> If you pick a fresh operator you can do this, or a more efficient equivalent.
>
> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2 }
>
> --
> Paul Phillips      | Every normal man must be tempted at times
> Stickler           | to spit on his hands, hoist the black flag,
> Empiricist         | and begin to slit throats.
> i pull his palp!   |     -- H. L. Mencken
>

AW: how to define Operator for {Double * myType}?

by Kubitz, Jörg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thanks, but the compiler does not allow a "implicit" outside a (class)body.
So I would have to put the line

implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x }

in every method that uses a Multiplication? I hope you are kidding me ;)


-----Ursprüngliche Nachricht-----
Von: Kevin Wright [mailto:kev.lee.wright@...]
Gesendet: Montag, 9. November 2009 16:57
An: Paul Phillips
Cc: Kubitz, Jörg; scala-user@...
Betreff: Re: [scala-user] how to define Operator for {Double * myType}?

On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
>> Is there a trait for adding Commutativity? Can such a trait be
>> implemented in general?
>
> In general? No.  Your problem is that * already exists on Double, and
> the error of calling that with the wrong type trumps an implicit
> conversion (maybe that could change, but it feels unlikely.)


Ouch! Looks like we have another candidate for Scala puzzlers...
We live and learn :)


> If you pick a fresh operator you can do this, or a more efficient equivalent.
>
> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2 }
>
> --
> Paul Phillips      | Every normal man must be tempted at times
> Stickler           | to spit on his hands, hoist the black flag,
> Empiricist         | and begin to slit throats.
> i pull his palp!   |     -- H. L. Mencken
>

Re: how to define Operator for {Double * myType}?

by Paul Phillips-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 09, 2009 at 03:56:53PM +0000, Kevin Wright wrote:
> Ouch! Looks like we have another candidate for Scala puzzlers... We
> live and learn :)

Even more puzzling is that it's not true.  I think I managed to combine
misremembering with a quick test which mixed up Int and Double.

--
Paul Phillips      | Every election is a sort of advance auction sale
In Theory          | of stolen goods.
Empiricist         |     -- H. L. Mencken
slap pi uphill!    |----------* http://www.improving.org/paulp/ *----------

Re: how to define Operator for {Double * myType}?

by Kevin Wright-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

You can use a static import, or put the implicit in the cashflow
companion object (I think, this may not work as you're not actually
converting to a cashflow, I forget the exact spec)

I also believe that an implicit in the package object (for whatever
package contains cashflow) will do the trick under 2.8, though I
haven't actually tested this one myself...



On Mon, Nov 9, 2009 at 4:00 PM, Kubitz, Jörg <jkubitz@...> wrote:

> Thanks, but the compiler does not allow a "implicit" outside a (class)body.
> So I would have to put the line
>
> implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x }
>
> in every method that uses a Multiplication? I hope you are kidding me ;)
>
>
> -----Ursprüngliche Nachricht-----
> Von: Kevin Wright [mailto:kev.lee.wright@...]
> Gesendet: Montag, 9. November 2009 16:57
> An: Paul Phillips
> Cc: Kubitz, Jörg; scala-user@...
> Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
>
> On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
>> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
>>> Is there a trait for adding Commutativity? Can such a trait be
>>> implemented in general?
>>
>> In general? No.  Your problem is that * already exists on Double, and
>> the error of calling that with the wrong type trumps an implicit
>> conversion (maybe that could change, but it feels unlikely.)
>
>
> Ouch! Looks like we have another candidate for Scala puzzlers...
> We live and learn :)
>
>
>> If you pick a fresh operator you can do this, or a more efficient equivalent.
>>
>> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2 }
>>
>> --
>> Paul Phillips      | Every normal man must be tempted at times
>> Stickler           | to spit on his hands, hoist the black flag,
>> Empiricist         | and begin to slit throats.
>> i pull his palp!   |     -- H. L. Mencken
>>
>

right bounded infix notation (was:how to define Operator for {Double * myType}?)

by Kubitz, Jörg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi

I realy don’t like that Methods with ":" as the last character are bounded in the inverse Order (by that implicity you put a domain specific feature into the language).  Thats neither intuitive nor documented on http://www.scala-lang.org/node/118

On the other side I see the need of inverse bounding and would like to use the inverse bounding as well for my scalar-multiplication "*" to get rid of that nesty implicit type conversion import.

So my suggestion is that the inverse bounding can (and has to) be declared explicitly
Unary Operators would then become a special case (inverse bounded method without parameter)

Instead of
  def ::[U>:T](x:U):List[U]= new scala.::(x,this)
  def unary_~ : Rational = new Rational(denom, numer)

I would like a explicit definition of inverse bounding like this:
  inverse def ::[U>:T](x:U):List[U]= new scala.::(x,this)
  inverse def ~ : Rational = new Rational(denom, numer)

Furthermore it would be nice if one could define tenary (or even higher) operators in this style:
 def myif(this)then(y)else(z) : any = if x then y else z
 def select(this)from(t : table) : ...
 def insert(this)into(t : table) : ...

i.e. "(this)" defines the place of the hidden class instance parameter.

That’s why I suggest the following syntax for explicit inverse bounding:

 def [U>:T](x:U)::(this) :List[U]= new scala.::(x,this)
 def ~(this) : Rational = new Rational(denom, numer)


Jörg Kubitz
-----Ursprüngliche Nachricht-----
Von: Kevin Wright [mailto:kev.lee.wright@...]
Gesendet: Montag, 9. November 2009 17:08
An: Kubitz, Jörg
Cc: Paul Phillips; scala-user@...
Betreff: Re: [scala-user] how to define Operator for {Double * myType}?

You can use a static import, or put the implicit in the cashflow
companion object (I think, this may not work as you're not actually
converting to a cashflow, I forget the exact spec)

I also believe that an implicit in the package object (for whatever
package contains cashflow) will do the trick under 2.8, though I
haven't actually tested this one myself...



On Mon, Nov 9, 2009 at 4:00 PM, Kubitz, Jörg <jkubitz@...> wrote:

> Thanks, but the compiler does not allow a "implicit" outside a (class)body.
> So I would have to put the line
>
> implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x }
>
> in every method that uses a Multiplication? I hope you are kidding me ;)
>
>
> -----Ursprüngliche Nachricht-----
> Von: Kevin Wright [mailto:kev.lee.wright@...]
> Gesendet: Montag, 9. November 2009 16:57
> An: Paul Phillips
> Cc: Kubitz, Jörg; scala-user@...
> Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
>
> On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
>> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
>>> Is there a trait for adding Commutativity? Can such a trait be
>>> implemented in general?
>>
>> In general? No.  Your problem is that * already exists on Double, and
>> the error of calling that with the wrong type trumps an implicit
>> conversion (maybe that could change, but it feels unlikely.)
>
>
> Ouch! Looks like we have another candidate for Scala puzzlers...
> We live and learn :)
>
>
>> If you pick a fresh operator you can do this, or a more efficient equivalent.
>>
>> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2 }
>>
>> --
>> Paul Phillips      | Every normal man must be tempted at times
>> Stickler           | to spit on his hands, hoist the black flag,
>> Empiricist         | and begin to slit throats.
>> i pull his palp!   |     -- H. L. Mencken
>>
>

Re: right bounded infix notation (was:how to define Operator for {Double * myType}?)

by David Flemström :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,
First, your problem of "nasty implicit type conversion imports": You can
always put your implicits in the companion object of your class, and they will
be loaded automatically, e.g:

package example {
  object S {
    implicit def int2s(i: Int) = new {
      def method() = println("s")
    }
  }
  class S
}
object Program {
  def main(args: Array[String]) = {
    import example._
    val x = new S
    x.method()
  }
}

Secondly, your language extensions:
I see many problems with this, one being that the Scala syntax can't be
changed "just like that", and another being that your solution brings about
quite a few syntactical conflicts, like, for example:

class A {
  def and(b: B) = println("A")
}

class B {
  inverse def and(a: A) = println("B")
}

object Program {
  def main(args: Array[String]) = {
    val (a, b) = (new A, new B)
    a and b
  }
}

I like the idea of adding some mechanic that would allow you to skip implicits
for some use cases (because implicits are expensive; they require a wrapper
object to be created), but I don't think that your soultion is sustainable.

What would work, as can be seen in the CLI-language C# (some of you might have
heard about it ;-) ), would be to allow for pure extension methods to classes,
like so:

class SomeClass

object SomewhereElse {
  def newMethod(this: SomeClass, arg: String) = println(this + " says " + arg)
}

object Program {
  def main(args: Array[String]) = {
    import SomewhereElse._
    val x = new SomeClass
    x newMethod "Hello"  //Compiler transforms this to newMethod(x, "Hello")
  }
}

It would be clean and not break any current code, but I don't think that
something like that will be implemented in the near future (but maybe I should
write a compiler plugin for it anyways?)

On Wednesday 11 November 2009 14:43:15 Kubitz, Jörg wrote:

> Hi
>
> I realy don’t like that Methods with ":" as the last character are bounded
>  in the inverse Order (by that implicity you put a domain specific feature
>  into the language).  Thats neither intuitive nor documented on
>  http://www.scala-lang.org/node/118
>
> On the other side I see the need of inverse bounding and would like to use
>  the inverse bounding as well for my scalar-multiplication "*" to get rid
>  of that nesty implicit type conversion import.
>
> So my suggestion is that the inverse bounding can (and has to) be declared
>  explicitly Unary Operators would then become a special case (inverse
>  bounded method without parameter)
>
> Instead of
>   def ::[U>:T](x:U):List[U]= new scala.::(x,this)
>   def unary_~ : Rational = new Rational(denom, numer)
>
> I would like a explicit definition of inverse bounding like this:
>   inverse def ::[U>:T](x:U):List[U]= new scala.::(x,this)
>   inverse def ~ : Rational = new Rational(denom, numer)
>
> Furthermore it would be nice if one could define tenary (or even higher)
>  operators in this style: def myif(this)then(y)else(z) : any = if x then y
>  else z
>  def select(this)from(t : table) : ...
>  def insert(this)into(t : table) : ...
>
> i.e. "(this)" defines the place of the hidden class instance parameter.
>
> That’s why I suggest the following syntax for explicit inverse bounding:
>
>  def [U>:T](x:U)::(this) :List[U]= new scala.::(x,this)
>  def ~(this) : Rational = new Rational(denom, numer)
>
>
> Jörg Kubitz
> -----Ursprüngliche Nachricht-----
> Von: Kevin Wright [mailto:kev.lee.wright@...]
> Gesendet: Montag, 9. November 2009 17:08
> An: Kubitz, Jörg
> Cc: Paul Phillips; scala-user@...
> Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
>
> You can use a static import, or put the implicit in the cashflow
> companion object (I think, this may not work as you're not actually
> converting to a cashflow, I forget the exact spec)
>
> I also believe that an implicit in the package object (for whatever
> package contains cashflow) will do the trick under 2.8, though I
> haven't actually tested this one myself...
>
> On Mon, Nov 9, 2009 at 4:00 PM, Kubitz, Jörg <jkubitz@...> wrote:
> > Thanks, but the compiler does not allow a "implicit" outside a
> > (class)body. So I would have to put the line
> >
> > implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x }
> >
> > in every method that uses a Multiplication? I hope you are kidding me ;)
> >
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Kevin Wright [mailto:kev.lee.wright@...]
> > Gesendet: Montag, 9. November 2009 16:57
> > An: Paul Phillips
> > Cc: Kubitz, Jörg; scala-user@...
> > Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
> >
> > On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
> >> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
> >>> Is there a trait for adding Commutativity? Can such a trait be
> >>> implemented in general?
> >>
> >> In general? No.  Your problem is that * already exists on Double, and
> >> the error of calling that with the wrong type trumps an implicit
> >> conversion (maybe that could change, but it feels unlikely.)
> >
> > Ouch! Looks like we have another candidate for Scala puzzlers...
> > We live and learn :)
> >
> >> If you pick a fresh operator you can do this, or a more efficient
> >> equivalent.
> >>
> >> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2
> >> }
> >>
> >> --
> >> Paul Phillips      | Every normal man must be tempted at times
> >> Stickler           | to spit on his hands, hoist the black flag,
> >> Empiricist         | and begin to slit throats.
> >> i pull his palp!   |     -- H. L. Mencken
>

AW: right bounded infix notation (was:how to define Operator for {Double * myType}?)

by Kubitz, Jörg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi David,
Thanks for the detailed reply.

First, your example shows very well how nasty scala code can be: it takes realy hard brain work to understand what it does (at least for me - being a non-scla guru). And implementing such a Pattern is not intuitive. Plus it doesn’t shows how to solve the problem that I cannot add a Method to build-in types Int or Double (since x is a S).
To be downward compatible it could be possible that ":" still implies inverse as default

Second, "a and b" in your counterexample should simply result in a "ambigious definition Error" at compiletime. Its hard to believe that anybody produces such code. Justification: Suppose I am the Author of Class B. "Inverse" is only needed if I cannot extend the source of Class A. If I cannot extend the source of Class A then I am not the author of Class A. Since I am not the author of Class A the author of Class A won't know my Class B. So the Author of Class A cannot write such a method.

So I don’t see real issues with my idea.

The c# solution is also nice (there is also a Java trunk that enables such a feature) but I think the function should not need to be defined within a Class.
If I could write pure function library it would be clearer:


Package stringExtention {
  def myStringMethod(s: string)= ...
}

"hallo".myStringMethod()


Nevertheless it would not fix that method "::" arbitrarily has the inverse order.

Talking about future: How much is it to extend scalar with either mine or your idea?

Jörg


-----Ursprüngliche Nachricht-----
Von: David Flemström [mailto:david.flemstrom@...]
Gesendet: Mittwoch, 11. November 2009 16:55
An: scala-user@...; Kubitz, Jörg
Betreff: Re: [scala-user] right bounded infix notation (was:how to define Operator for {Double * myType}?)

Hello,
First, your problem of "nasty implicit type conversion imports": You can
always put your implicits in the companion object of your class, and they will
be loaded automatically, e.g:

package example {
  object S {
    implicit def int2s(i: Int) = new {
      def method() = println("s")
    }
  }
  class S
}
object Program {
  def main(args: Array[String]) = {
    import example._
    val x = new S
    x.method()
  }
}

Secondly, your language extensions:
I see many problems with this, one being that the Scala syntax can't be
changed "just like that", and another being that your solution brings about
quite a few syntactical conflicts, like, for example:

class A {
  def and(b: B) = println("A")
}

class B {
  inverse def and(a: A) = println("B")
}

object Program {
  def main(args: Array[String]) = {
    val (a, b) = (new A, new B)
    a and b
  }
}

I like the idea of adding some mechanic that would allow you to skip implicits
for some use cases (because implicits are expensive; they require a wrapper
object to be created), but I don't think that your soultion is sustainable.

What would work, as can be seen in the CLI-language C# (some of you might have
heard about it ;-) ), would be to allow for pure extension methods to classes,
like so:

class SomeClass

object SomewhereElse {
  def newMethod(this: SomeClass, arg: String) = println(this + " says " + arg)
}

object Program {
  def main(args: Array[String]) = {
    import SomewhereElse._
    val x = new SomeClass
    x newMethod "Hello"  //Compiler transforms this to newMethod(x, "Hello")
  }
}

It would be clean and not break any current code, but I don't think that
something like that will be implemented in the near future (but maybe I should
write a compiler plugin for it anyways?)

On Wednesday 11 November 2009 14:43:15 Kubitz, Jörg wrote:

> Hi
>
> I realy don’t like that Methods with ":" as the last character are bounded
>  in the inverse Order (by that implicity you put a domain specific feature
>  into the language).  Thats neither intuitive nor documented on
>  http://www.scala-lang.org/node/118
>
> On the other side I see the need of inverse bounding and would like to use
>  the inverse bounding as well for my scalar-multiplication "*" to get rid
>  of that nesty implicit type conversion import.
>
> So my suggestion is that the inverse bounding can (and has to) be declared
>  explicitly Unary Operators would then become a special case (inverse
>  bounded method without parameter)
>
> Instead of
>   def ::[U>:T](x:U):List[U]= new scala.::(x,this)
>   def unary_~ : Rational = new Rational(denom, numer)
>
> I would like a explicit definition of inverse bounding like this:
>   inverse def ::[U>:T](x:U):List[U]= new scala.::(x,this)
>   inverse def ~ : Rational = new Rational(denom, numer)
>
> Furthermore it would be nice if one could define tenary (or even higher)
>  operators in this style: def myif(this)then(y)else(z) : any = if x then y
>  else z
>  def select(this)from(t : table) : ...
>  def insert(this)into(t : table) : ...
>
> i.e. "(this)" defines the place of the hidden class instance parameter.
>
> That’s why I suggest the following syntax for explicit inverse bounding:
>
>  def [U>:T](x:U)::(this) :List[U]= new scala.::(x,this)
>  def ~(this) : Rational = new Rational(denom, numer)
>
>
> Jörg Kubitz
> -----Ursprüngliche Nachricht-----
> Von: Kevin Wright [mailto:kev.lee.wright@...]
> Gesendet: Montag, 9. November 2009 17:08
> An: Kubitz, Jörg
> Cc: Paul Phillips; scala-user@...
> Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
>
> You can use a static import, or put the implicit in the cashflow
> companion object (I think, this may not work as you're not actually
> converting to a cashflow, I forget the exact spec)
>
> I also believe that an implicit in the package object (for whatever
> package contains cashflow) will do the trick under 2.8, though I
> haven't actually tested this one myself...
>
> On Mon, Nov 9, 2009 at 4:00 PM, Kubitz, Jörg <jkubitz@...> wrote:
> > Thanks, but the compiler does not allow a "implicit" outside a
> > (class)body. So I would have to put the line
> >
> > implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x }
> >
> > in every method that uses a Multiplication? I hope you are kidding me ;)
> >
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Kevin Wright [mailto:kev.lee.wright@...]
> > Gesendet: Montag, 9. November 2009 16:57
> > An: Paul Phillips
> > Cc: Kubitz, Jörg; scala-user@...
> > Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
> >
> > On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...> wrote:
> >> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
> >>> Is there a trait for adding Commutativity? Can such a trait be
> >>> implemented in general?
> >>
> >> In general? No.  Your problem is that * already exists on Double, and
> >> the error of calling that with the wrong type trumps an implicit
> >> conversion (maybe that could change, but it feels unlikely.)
> >
> > Ouch! Looks like we have another candidate for Scala puzzlers...
> > We live and learn :)
> >
> >> If you pick a fresh operator you can do this, or a more efficient
> >> equivalent.
> >>
> >> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c ** 2
> >> }
> >>
> >> --
> >> Paul Phillips      | Every normal man must be tempted at times
> >> Stickler           | to spit on his hands, hoist the black flag,
> >> Empiricist         | and begin to slit throats.
> >> i pull his palp!   |     -- H. L. Mencken
>

Re: AW: right bounded infix notation (was:how to define Operator for {Double * myType}?)

by David Flemström :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Wednesday 11 November 2009 17:46:08 Kubitz, Jörg wrote:
> Hi David,
> Thanks for the detailed reply.
>
> First, your example shows very well how nasty scala code can be: it takes
>  realy hard brain work to understand what it does (at least for me - being
>  a non-scla guru). And implementing such a Pattern is not intuitive.
So why do you want to add yet another layer of complexity on top of that?

> Second, "a and b" in your counterexample should simply result in a
>  "ambigious definition Error" at compiletime. Its hard to believe that
>  anybody produces such code.
You think so? Imagine that there's a class with a "def +(that: AnyRef)" on it,
that does something like just calling ".toString" on "that"; quite reasonable.  
With your approach, it would not be possible to add a "+" method to that class
by means of reverse methods, since every such method would conflict with the
original "+" method.

>  Justification: Suppose I am the Author of
>  Class B. "Inverse" is only needed if I cannot extend the source of Class
>  A. If I cannot extend the source of Class A then I am not the author of
>  Class A. Since I am not the author of Class A the author of Class A won't
>  know my Class B. So the Author of Class A cannot write such a method.
Yes, I understand your problem, but there are multiple solutions for it that
don't require reverse methods, one being implicit conversions in companion
objects (that are somewhat inefficient, granted)

> The c# solution is also nice (there is also a Java trunk that enables such
>  a feature) but I think the function should not need to be defined within a
>  Class. If I could write pure function library it would be clearer:
>
>
> Package stringExtention {
>   def myStringMethod(s: string)= ...
> }
>
> "hallo".myStringMethod()
You can already do that by either using 1. companion objects for a related
class or 2. package objects (Google it). I don't think that package-level
methods are a good idea, since Scala tries to be an object-oriented language,
and unless you want such package-level methods to be instantiated as singleton
function objects, it's not a sustainable solution.

> Nevertheless it would not fix that method "::" arbitrarily has the inverse
>  order.
>
> Talking about future: How much is it to extend scalar with either mine or
>  your idea?
I think that a good place to ask that would be on the scala-discussion mailing
list. It's there that discussions about new features are supposed to be,
anyways.

>
> Jörg
>
>
> -----Ursprüngliche Nachricht-----
> Von: David Flemström [mailto:david.flemstrom@...]
> Gesendet: Mittwoch, 11. November 2009 16:55
> An: scala-user@...; Kubitz, Jörg
> Betreff: Re: [scala-user] right bounded infix notation (was:how to define
>  Operator for {Double * myType}?)
>
> Hello,
> First, your problem of "nasty implicit type conversion imports": You can
> always put your implicits in the companion object of your class, and they
>  will be loaded automatically, e.g:
>
> package example {
>   object S {
>     implicit def int2s(i: Int) = new {
>       def method() = println("s")
>     }
>   }
>   class S
> }
> object Program {
>   def main(args: Array[String]) = {
>     import example._
>     val x = new S
>     x.method()
>   }
> }
>
> Secondly, your language extensions:
> I see many problems with this, one being that the Scala syntax can't be
> changed "just like that", and another being that your solution brings about
> quite a few syntactical conflicts, like, for example:
>
> class A {
>   def and(b: B) = println("A")
> }
>
> class B {
>   inverse def and(a: A) = println("B")
> }
>
> object Program {
>   def main(args: Array[String]) = {
>     val (a, b) = (new A, new B)
>     a and b
>   }
> }
>
> I like the idea of adding some mechanic that would allow you to skip
>  implicits for some use cases (because implicits are expensive; they
>  require a wrapper object to be created), but I don't think that your
>  soultion is sustainable.
>
> What would work, as can be seen in the CLI-language C# (some of you might
>  have heard about it ;-) ), would be to allow for pure extension methods to
>  classes, like so:
>
> class SomeClass
>
> object SomewhereElse {
>   def newMethod(this: SomeClass, arg: String) = println(this + " says " +
>  arg) }
>
> object Program {
>   def main(args: Array[String]) = {
>     import SomewhereElse._
>     val x = new SomeClass
>     x newMethod "Hello"  //Compiler transforms this to newMethod(x,
>  "Hello") }
> }
>
> It would be clean and not break any current code, but I don't think that
> something like that will be implemented in the near future (but maybe I
>  should write a compiler plugin for it anyways?)
>
> On Wednesday 11 November 2009 14:43:15 Kubitz, Jörg wrote:
> > Hi
> >
> > I realy don’t like that Methods with ":" as the last character are
> > bounded in the inverse Order (by that implicity you put a domain specific
> > feature into the language).  Thats neither intuitive nor documented on
> >  http://www.scala-lang.org/node/118
> >
> > On the other side I see the need of inverse bounding and would like to
> > use the inverse bounding as well for my scalar-multiplication "*" to get
> > rid of that nesty implicit type conversion import.
> >
> > So my suggestion is that the inverse bounding can (and has to) be
> > declared explicitly Unary Operators would then become a special case
> > (inverse bounded method without parameter)
> >
> > Instead of
> >   def ::[U>:T](x:U):List[U]= new scala.::(x,this)
> >   def unary_~ : Rational = new Rational(denom, numer)
> >
> > I would like a explicit definition of inverse bounding like this:
> >   inverse def ::[U>:T](x:U):List[U]= new scala.::(x,this)
> >   inverse def ~ : Rational = new Rational(denom, numer)
> >
> > Furthermore it would be nice if one could define tenary (or even higher)
> >  operators in this style: def myif(this)then(y)else(z) : any = if x then
> > y else z
> >  def select(this)from(t : table) : ...
> >  def insert(this)into(t : table) : ...
> >
> > i.e. "(this)" defines the place of the hidden class instance parameter.
> >
> > That’s why I suggest the following syntax for explicit inverse bounding:
> >
> >  def [U>:T](x:U)::(this) :List[U]= new scala.::(x,this)
> >  def ~(this) : Rational = new Rational(denom, numer)
> >
> >
> > Jörg Kubitz
> > -----Ursprüngliche Nachricht-----
> > Von: Kevin Wright [mailto:kev.lee.wright@...]
> > Gesendet: Montag, 9. November 2009 17:08
> > An: Kubitz, Jörg
> > Cc: Paul Phillips; scala-user@...
> > Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
> >
> > You can use a static import, or put the implicit in the cashflow
> > companion object (I think, this may not work as you're not actually
> > converting to a cashflow, I forget the exact spec)
> >
> > I also believe that an implicit in the package object (for whatever
> > package contains cashflow) will do the trick under 2.8, though I
> > haven't actually tested this one myself...
> >
> > On Mon, Nov 9, 2009 at 4:00 PM, Kubitz, Jörg <jkubitz@...> wrote:
> > > Thanks, but the compiler does not allow a "implicit" outside a
> > > (class)body. So I would have to put the line
> > >
> > > implicit def num2commute(x: Double) = new { def *(c: cashflow) = c * x
> > > }
> > >
> > > in every method that uses a Multiplication? I hope you are kidding me
> > > ;)
> > >
> > >
> > > -----Ursprüngliche Nachricht-----
> > > Von: Kevin Wright [mailto:kev.lee.wright@...]
> > > Gesendet: Montag, 9. November 2009 16:57
> > > An: Paul Phillips
> > > Cc: Kubitz, Jörg; scala-user@...
> > > Betreff: Re: [scala-user] how to define Operator for {Double * myType}?
> > >
> > > On Mon, Nov 9, 2009 at 3:46 PM, Paul Phillips <paulp@...>
wrote:

> > >> On Mon, Nov 09, 2009 at 04:20:48PM +0100, Kubitz, Jörg wrote:
> > >>> Is there a trait for adding Commutativity? Can such a trait be
> > >>> implemented in general?
> > >>
> > >> In general? No.  Your problem is that * already exists on Double, and
> > >> the error of calling that with the wrong type trumps an implicit
> > >> conversion (maybe that could change, but it feels unlikely.)
> > >
> > > Ouch! Looks like we have another candidate for Scala puzzlers...
> > > We live and learn :)
> > >
> > >> If you pick a fresh operator you can do this, or a more efficient
> > >> equivalent.
> > >>
> > >> implicit def num2commute(x: Double) = new { def **(c: cashflow) = c **
> > >> 2 }
> > >>
> > >> --
> > >> Paul Phillips      | Every normal man must be tempted at times
> > >> Stickler           | to spit on his hands, hoist the black flag,
> > >> Empiricist         | and begin to slit throats.
> > >> i pull his palp!   |     -- H. L. Mencken
>

Re: AW: right bounded infix notation (was:how to define Operator for {Double * myType}?)

by Colin Bullock :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Just to add, this would also require the parser to reason about the type of your method before being able to parse it. As it is now, given "a meth b", there are effectively only two simple rules about how this parses, based only on the syntax: if meth ends in ":" it parses as "b.meth(a)", otherwise as "a.meth(b)". If it needs to know about the definition of meth before making this decision, the world becomes a much more complicated (if not undecidable) place.

- Colin