0

I am trying to do:

MyObject.myMethod(_:MyType.myAttribute)

This fails with

type myAttribute is not a member of object MyObject

which is correct. The problem is that I want to call myMethod on myAttribute of _:MyType, not ascribe MyType:myAttribute to _. Can I somehow group the type ascription _:MyType? (_:MyType).myAttribute returns type MyType => classOf(myAttribute), which is not what I want.

Edit: I changed the title and text of this post to no longer refer to this as the associativity of the dot, which I believe was not correct.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
taz
  • 1,506
  • 3
  • 15
  • 26
  • Someone with enough reputation to create new tags should replace `casting` with `ascription` or `ascribe`. – taz Dec 12 '12 at 01:24

3 Answers3

2

Are you trying to create function (m: MyType) => MyObject.myMethod(m.myAttribute) using underscore?

If so, the problem is that MyObject.myMethod((_:MyType).myAttribute) means MyObject.myMethod((m:MyType) => m.myAttribute).

You can use infix notation:

MyObject myMethod (_:MyType).myAttribute

Proof it works:

scala> case class MyType(myAttribute: Int)
defined class MyType

scala> object MyObject {
     |   def myMethod(a: Int) = a.toString
     | }
defined module MyObject

scala> MyObject myMethod (_:MyType).myAttribute
res0: MyType => java.lang.String = <function1>

scala> res0(MyType(1))
res1: java.lang.String = 1

scala> MyObject myMethod (MyType(1))
<console>:1: error: type mismatch;
 found   : MyType
 required: Int
              MyObject myMethod (_:MyType)
                                  ^
Community
  • 1
  • 1
senia
  • 37,745
  • 4
  • 88
  • 129
  • 1
    Neato. It works because while func args are Exprs, InfixExprs are not. (Responding to prev comment.) – som-snytt Dec 12 '12 at 05:05
  • This does not work for what I am trying to do. This calls `myMethod` on `_:Mytpe`; this does not call `myMethod` on `_:MyType`'s `myAttribute`. This has the same effect as `(myMethod(_:MyType)).myAttribute)` – taz Dec 12 '12 at 05:06
  • @taz It's not true. Result of `myMethod` don't have `myAttribute` member. I've added proof to my answer. – senia Dec 12 '12 at 05:10
  • No, where you got `res0: MyType => java.lang.String = `, in your example I would be expecting a `String`. – taz Dec 12 '12 at 05:13
  • Maybe @taz should post his code. I really had no idea what you were going for. – som-snytt Dec 12 '12 at 05:15
  • `TitleController get (_:Media) titleID` gives me `type mismatch: found: Media; required: Int`. I am trying to call `get` on the `titleID` attribute of `_:Media`. `titleID` is an `Int`. – taz Dec 12 '12 at 05:17
  • @taz Use `TitleController get (_:Media).titleID` as in my answer. – senia Dec 12 '12 at 05:18
  • That changed things. I might be on the way here. I'm getting a different error from the longer expression: `((TitleController get (_:Media).titleID):Option[Title]).exists(...)` gives `found: Media => Option[Title]; required: Option[Title]`. `get` returns `Option[Title]`. If I use `TitleController.get` I get the exact same error as before. – taz Dec 12 '12 at 05:25
  • @taz: It's a different question. – senia Dec 12 '12 at 05:28
  • @taz: Try `TitleController get (_:Media).titleID exists(...)`. – senia Dec 12 '12 at 05:29
  • @senia That compiled! Thanks! I realize that was a different question but I figured you probably knew the answer. Hopefully it works in testing. Thanks again. – taz Dec 12 '12 at 05:37
1

I'm not sure whether this illustrates or answers your question, but it's true.

My guess is that you expected your a.b(_.i) to be an anon func after you add an ascription (to type the parameter).

But the subexpr foils you by there is no other expression of syntactic category Expr which is properly contained in e and which itself properly contains u. (SLS 6.23)

Also, you can use scalac -Xprint:parser to see how it's taken.

object Foo {
  def m(k: Int) = 7 * k
}
class Bar {
  val i = 5
  val What = i
}
object Bar {
  type What = Int
}

object Test extends App {
  Foo.m(_:Bar.What)
  // this is not anon func placeholder syntax...
  //Foo.m((_:Bar).What)  // _ is in a subexpr
  //Foo.m(_.i)
  // ...for this
  val f = (x: Bar) => Foo.m(x.i)
  // InfixExpr is ok
  val g = Foo m (_: Bar).i
  val b = new Bar
  println(f(b))
  println(g(b))
}

Contrast, to illustrate what is being restricted:

scala> val f: (Int,Int)=>Int = _+_
f: (Int, Int) => Int = <function2>

scala> val g: Int=>Int = if (_ > 0) 1 else 2
<console>:7: error: missing parameter type for expanded function ((x$1) => x$1.$greater(0))
som-snytt
  • 39,429
  • 2
  • 47
  • 129
  • Yes, this is what I have described in my original post. I have in place the `(x: Bar) => Foo.m(x.i)` construct. I understand why `(_:Bar.What)` doesn't work. Is there no way to associate the `What` to the entire `_:Bar`? This seems like an accidental limitation of the syntax; can I not use an associativity operator somehow to cause the `Bar` to apply to the `_` and not the `What`? – taz Dec 12 '12 at 04:42
0
List(1,2,3).map((i: Int) => i * i)

EDIT

List(1,2,3).map((_: Int).unary_-)

EDIT 2

implicit class MyAttribute(i: Int) { def myMethod() = i * i }
List(1,2,3).map((_: Int).myMethod.unary_-)

Explanation

I used implicit class (Scala-2.10) to add myMethod on Int, after that unary "-" operation executed on result. You could add something like def wrap: MyAttribute to MyAttribute, and use it like (_: Int).wrap.method1.method2.method3.result.abs, for example.

idonnie
  • 1,703
  • 12
  • 11
  • I am aware of how to accomplish my goal using `=>`; I am asking specifically how to accomplish this using the underscore. The problem is not that the underscore can't be properly ascribed; the problem is the associativity of the ascription. Your example does not address this unless I missed something. – taz Dec 12 '12 at 01:48
  • I see that you edited your answer but I don't understand this at all. Can you provide some explanation? – taz Dec 12 '12 at 03:04