This page is no longer maintained — Please continue to the home page at www.scala-lang.org

A function with two parameters that are both optional

5 replies
wrburdick
Joined: 2009-09-21,
User offline. Last seen 3 years 3 weeks ago.
I would like a function with two parameters that are both optional, with the second parameter being a function, so that all four of these calls work:
foofoo(a)foo {...}foo(a) {...}
Is there a better way to do it than this?  It's a bit, er, cumbersome...

object ITest { class Fred
implicit val f = new Fred implicit val str: String = "default" implicit val conforms: String => Any = {s => println("default func")}
def foo(implicit s: String, func: String => Any, f: Fred) = {print("first: " + s + ", "); func(s)} def foo(s: String)(implicit func: String => Any) = {print("second: " + s + ", "); func(s)} def foo(func: String => Any)(implicit s: String) = {print("third: " + s + ", "); func(s)} def main(args: Array[String]) { foo foo("a") foo("b") {s =>  println("func 1") } foo {s =>  println("func 2") } }}

-- Bill
Todd Vierling
Joined: 2011-04-27,
User offline. Last seen 42 years 45 weeks ago.
Re: A function with two parameters that are both optional
On Saturday, October 29, 2011 1:30:17 AM UTC-4, Bill Burdick wrote:
I would like a function with two parameters that are both optional, with the second parameter being a function, so that all four of these calls work:
foofoo(a)foo {...}foo(a) {...}

def foo(s: String = "default", func: String => Any = {s => println("default func")}) = { ... }
Plain ol' default arguments. Yep, it works for functions too, though it's probably better visually to stash the default func value in a val and use it that way:
val defaultFunc = {s: String => println("default func")}
def foo(s: String = "default", func: String => Any = defaultFunc) = { ... }
wrburdick
Joined: 2009-09-21,
User offline. Last seen 3 years 3 weeks ago.
Re: Re: A function with two parameters that are both optional
On Sat, Oct 29, 2011 at 12:47 AM, Todd Vierling <tv [at] duh [dot] org> wrote:
On Saturday, October 29, 2011 1:30:17 AM UTC-4, Bill Burdick wrote:
I would like a function with two parameters that are both optional, with the second parameter being a function, so that all four of these calls work:
foofoo(a)foo {...}foo(a) {...}

def foo(s: String = "default", func: String => Any = {s => println("default func")}) = { ... }
Plain ol' default arguments. Yep, it works for functions too, though it's probably better visually to stash the default func value in a val and use it that way:
val defaultFunc = {s: String => println("default func")}
def foo(s: String = "default", func: String => Any = defaultFunc) = { ... }

Doesn't work for foo (works for foo(), though) or the ones that take functions.
This is close:
def foo(s: String = "default")(implicit func: String => Any = conforms): Unit = {print("first: " + s + ", "); func(s)}
but foo still doesn't work (I like it better than foo(), especially with lambdas) and s isn't implicit.  I thought, maybe (s: String = implicitly) would work, but it doesn't, it just uses the scope of the foo declaration.

Bill
wrburdick
Joined: 2009-09-21,
User offline. Last seen 3 years 3 weeks ago.
Re: Re: A function with two parameters that are both optional
On Sat, Oct 29, 2011 at 11:20 AM, Bill Burdick <bill [dot] burdick [at] gmail [dot] com> wrote:
On Sat, Oct 29, 2011 at 12:47 AM, Todd Vierling <tv [at] duh [dot] org> wrote:
On Saturday, October 29, 2011 1:30:17 AM UTC-4, Bill Burdick wrote:
I would like a function with two parameters that are both optional, with the second parameter being a function, so that all four of these calls work:
foofoo(a)foo {...}foo(a) {...}

def foo(s: String = "default", func: String => Any = {s => println("default func")}) = { ... }
Plain ol' default arguments. Yep, it works for functions too, though it's probably better visually to stash the default func value in a val and use it that way:
val defaultFunc = {s: String => println("default func")}
def foo(s: String = "default", func: String => Any = defaultFunc) = { ... }

Doesn't work for foo (works for foo(), though) or the ones that take functions.
This is close:
def foo(s: String = "default")(implicit func: String => Any = conforms): Unit = {print("first: " + s + ", "); func(s)}
but foo still doesn't work (I like it better than foo(), especially with lambdas) and s isn't implicit.  I thought, maybe (s: String = implicitly) would work, but it doesn't, it just uses the scope of the foo declaration.

OK, this works for all cases except for foo (instead of foo()) and you can provide a second definition for that one:
class Defaults(val s: String, val func: String=>Any) implicit val defaultDefaults = new Defaults("default string", {s => println("default func: " + s)})implicit def func2Defaults(f: String=>Any)(implicit defaults: Defaults) = new Defaults(defaults.s, f)
def foo(implicit f: Defaults): Unit = foo(f.s)(f)  // optional, if you want foo in addition to foo()def foo(s: String = null)(implicit f: Defaults) = {f.func(if (s == null) f.s else s)}

Bill
Todd Vierling
Joined: 2011-04-27,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: A function with two parameters that are both optional
On Saturday, October 29, 2011 12:20:22 PM UTC-4, Bill Burdick wrote:
def foo(s: String = "default", func: String => Any = {s => println("default func")}) = { ... }
 
Doesn't work for foo (works for foo(), though) or the ones that take functions.

Yes, I probably should have tested those; I didn't notice the String-plus-function was curried rather than having the function as a second arg.
I try Hard not to declare implicit args and implicit vals because they can have unexpected side effects, and are a little more difficult for those unfamiliar with Scala to understand. An uncurried definition could use traditional delegation-style default overloading, but the curried form has issues with ambiguous method overloads.
wrburdick
Joined: 2009-09-21,
User offline. Last seen 3 years 3 weeks ago.
Re: Re: A function with two parameters that are both optional
On Sat, Oct 29, 2011 at 1:08 PM, Todd Vierling <tv [at] duh [dot] org> wrote:
On Saturday, October 29, 2011 12:20:22 PM UTC-4, Bill Burdick wrote:
def foo(s: String = "default", func: String => Any = {s => println("default func")}) = { ... }
 
Doesn't work for foo (works for foo(), though) or the ones that take functions.

Yes, I probably should have tested those; I didn't notice the String-plus-function was curried rather than having the function as a second arg.
I try Hard not to declare implicit args and implicit vals because they can have unexpected side effects, and are a little more difficult for those unfamiliar with Scala to understand. An uncurried definition could use traditional delegation-style default overloading, but the curried form has issues with ambiguous method overloads.

I'm working on a DSL that uses actors and policies that people need to be able to override piece wise, temporarily, and conveniently.  Implicits seem like a good fit for that, to me.  Really, there are at least 3 items in the policy, but the latest technique I'm using, combining optional parameters with an implicit policy object seems like it's providing the right amount of control and ease of use.  It seems to me like the implicits ought to behave well, since they're based on the policy class, which is only used for these DSL methods, as opposed to a commonly used type, like String or Int.

Bill

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland