Pass a reference to a no-argument method in scala - scala

How can I pass a reference to a no-argument method reference in scala?
For example:
class Foo {
def foo: String = computeSomethingAndReturnIt
}
object Foo extends App {
def acceptSupplier(???) { doSomethingWithFooSupplier }
val f = new Foo
acceptSupplier(f.foo ???)
}
I know I can define foo to accept Unit by declaring def foo()... and this will work, but is there a way to pass foo and have it accept zero arguments as shown above in the code snippet?

You can use a by-name argument:
def acceptSupplier(f: => String) { ... }
val f = new Foo
acceptSupplier(f.foo)

Or more explicitly:
def acceptSupplier(f: () => String) { ... }
val f = new Foo
acceptSupplier(f.foo _)

Related

Pass Scala.js class instance to JavaScript that will invoke the function call method

I have a simple Scala.js class (Scala-2.12.10 and Scala-js 0.6.31):
class Foo extends js.Object {
def apply() = { println("apply") }
def bar() = { println("bar") }
}
val myfoo = new Foo()
An instance of Foo will be passed to a JavaScript library which will in turn attempt to invoke the following two methods:
myfoo()
myfoo.bar()
Of course, this will not work because I cannot define the apply method on Foo since it derives from js.Object and that will not translate to calling () on the object.
How does one construct an appropriate class for this scenario?
Update:
Here is some example code based on #sjrd's answer that provides for strong typing while encapsulating the js.Dynamic complexity.
trait FooTrait extends js.Object {
def own()
def bar()
}
class Foo extends FooTrait {
def own() = { println("apply") }
def bar() = { println("bar") }
}
def makeFoo(foo: FooTrait]) = {
val jsFoo = ({ () =>
foo.own()
}: js.Function0[Unit]).asInstanceOf[js.Dynamic]
jsFoo.bar = ({ () =>
foo.bar()
}: js.Function0[Unit])
jsFoo
}
val myFoo = makeFoo(new Foo())
Now myFoo is ready to be passed to the JavaScript library.
In JavaScript, the only way that a call like myfoo() can be valid is if myfoo was created as a function value. To make myfoo.bar() work in addition, that must be patched on the function value after it's created. There is no way (except proxies, which are another beast entirely) to create myfoo as an object first, from a class or not, and make it answer to myfoo().
Therefore, this is also what you have to do in Scala.js:
val myfoo = ({ () =>
println("apply")
}: js.Function0[Unit]).asInstanceOf[js.Dynamic]
myfoo.bar = ({ () =>
println("bar")
}: js.Function0[Unit])
After that, you can pass myfoo to the JavaScript code.

Scala - explicitly refer to parameter

Given this awesome piece of totally pro Scala:
trait SomethingCool {
def foo: Int => String
}
def makeSomethingCool(foo: Int => String = i => i.toString): SomethingCool = {
new SomethingCool {
override def foo = foo // method foo does nothing other than call itself recursively
}
}
where I have a factory method for a trait that has a default implementation, how can I refer to the parameter name from within the new SomethingCool { }? It seems to get masked by the trait's function name.
You can't. But here is one workaround:
def makeSomethingCool(foo: Int => String = i => i.toString): SomethingCool = {
val _foo = foo
new SomethingCool {
override def foo = _foo
}
}

More aesthetic way to instantiate an anonymous implementation of a trait

Say I have a function that expects an instance of a trait:
trait MyTrait[T] {
def f1: T
def f2(t: T): Unit
}
def foo[T](t: MyTrait[T]) { ... }
Now, anywhere I call this function I need to use the following syntax:
val x = foo[String](new MyTrait[String] {
def f1 = "Hello"
def f2(str: String) = { ... }
}
I am wondering if there is another way I can achieve this to make my usages simpler and more aesthetic? Ideally I would like to have the following usage:
val x = foo() {
def f1 = "Hello"
def f2(str: String) = { ... }
}
If you use this trait anonymous everywhere like you described, throw it away!
Instead make the function look like
def foo[T](f1: T, f2: T => Unit)
so you can call it like
foo("Hello", (myString:String) => { } )
An alternative to Nabil A.'s answer, if you want to keep the trait, is to subclass it using a case class that takes f1 and (a function describing) f2 as parameters:
case class MyClass[T](f1: T, _f2: T => Unit) extends MyTrait[T] {
def f2(t: T) = _f2(t)
}
You can then instantiate it as:
foo(MyClass[String]("hello", str => {...}))

Generic type having the special constructor and calling it

Let's say I have a few classes class and all they extend Response(response), that is to say, have the same constructor:
import scalaj.http.Http
class MyClass1(response: Http.Request) extends Response(response) {
//....
}
class MyClass2(response: Http.Request) extends Response(response) {
//....
}
How do I create a generic method which accepts only a type of the classes above and call its constructor:
def myGeneric[A <: ???](r: Http.Request) = {
new A(r) // doesn't compile
}
I'd like to call it like this:
myGeneric[MyClass1](r) // r is Http.Request
I can do this:
def myGeneric[A <: ???](r: Http.Request)(f: r => A) = {
f(r) // f - is the constructor
}
myGeneric[MyClass1](r) { x =>
new MyClass1(x)
}
But is there more elegant way to achieve the same?
Maybe you could make myGeneric take a factory as the implicit parameter. For example:
def myGeneric[A](r: Request)(implicit f: Request => A) {
... val a = f(r) ...
If I remember right, bare implicit functions like that can get confusing, so maybe ...
trait MyFactory[T] {
def make(r: Request): T
}
...
def myGeneric[A](r: Request)(implicit f: MyFactory[A]) ...
// which is same as...
def myGeneric[A : MyFactory](r: Request) ...

scala: function recursively returns a function object, how to overcome illegal cyclic reference?

i have a class with a method that returns a function object. the requirements are that the method is arity 0 and its return type is an Option of a Function0 - whose return type is the original return type. for example:
class MyClass {
def f(): Option[Function[A]] = Some(g _)
def g(): Option[Function[A]] = Some(h _)
... goes on and on, eventually returns Some(z _) ...
def z(): Option[Function[A]] = None
}
Due to the recursion, the issue is that the type A is defined as:
type A = Option[Function0[A]]
but since cyclic references are not allowed, it produces the error:
illegal cyclic reference involving type A
i obviously want to avoid defining a different return type for each of the methods, but having a unified return type doesn't seem possible due to the cycle. is there any way to do this? thanks!
This is not supported by Scala type definitions. See How to define a cyclic type definition?
You can accomplish this with a class instead of a type, although you would have to define your own Option-like class. An example is below (with monadic methods omitted). Also, see this mailing list discussion: http://www.scala-lang.org/node/2541
sealed trait OptionalFunction extends (() => OptionalFunction) {
def get: (() => OptionalFunction)
}
case class SomeFunction(fn: () => OptionalFunction) extends OptionalFunction {
def apply() = fn()
def get = fn
}
case object NoFunction extends OptionalFunction {
def apply() = this
def get = throw new NoSuchElementException
}
class MyClass {
type A = OptionalFunction
def f(): A = SomeFunction(g _)
def g(): A = SomeFunction(h _)
def h(): A = SomeFunction(() => { println("At the end!"); i })
def i(): A = NoFunction
}
scala> new MyClass().f()()()()
At the end!
res0: OptionalFunction[Unit] = <function0>
I'm not sure if this is what you're looking for, but many of these edge-cases can be worked around with explicitly using objects:
abstract class F extends Function0[F]
val p = new F {
def apply() = { println("hi"); this }
}
>> defined class F
>> p: $anon forSome { type $anon <: F{def apply(): $anon} } =
p()
>> hi
>> res2: $anon =
p()()
>> hi
>> hi
>> res3: $anon =
Happy coding.