Skip to content

Scala Tuple Argumentative Essays

scala> val o = new { val number = 42; val spelling = "forty two" }
o: java.lang.Object{def number: Int; def spelling: java.lang.String} =
$anon$1@39859

scala> def gimme(n: { val number: Int; val spelling: String }) = "The
answer is "+n.number+" ("+n.spelling+")"
gimme: (AnyRef{def number: Int; def spelling: String})java.lang.String

scala> gimme(o)
res0: java.lang.String = The answer is 42 (forty two)

2009/3/20 Windemuth Andreas :
>
> I have thought for a while now that it would be nice to have named tuples,
> like this:
>
> (number=42, spelling="forty two")
>
> Then instead of "x._1" one could write "x.number", without any need for
> pattern matching. Maps could return tuples with default names such as (key=,
> value=). These look a lot like named argument lists, and also like case
> classes. Maybe there is a grand unification of sorts begging to be done to
> simplify everything and turn the three into one?  Tuples == case classes ==
> argument lists ?
>
> Andreas
>
>
> ________________________________
> From: Jorge Ortiz
> To: Robey Pointer
> Cc: Steven Shaw ; Scala list
> Sent: Friday, March 20, 2009 2:57:19 AM
> Subject: Re: [scala] breaking open tuples in an anonymous function
>
> It's not a bug, but could be an enhancement request. Function literals don't
> support pattern matching.
>
> There was at some point talk about unifying tuples and function arguments,
> but I don't know serious that talk was.
>
> --j
>
> On Thu, Mar 19, 2009 at 10:55 PM, Robey Pointer
> wrote:
>>
>> On 19 Mar 2009, at 21:13, Steven Shaw wrote:
>>
>>> 2009/3/20 Jorge Ortiz :
>>>>
>>>> x map { case (k, v) => v / 5 }
>>>
>>> I like this. An alternative is
>>>
>>>  x map (_._2 / 5)
>>
>> The _1, _2 things look like an ugly hack to me so I avoid them.
>>
>> I like the case trick, and I'll use that, but is there any reason ((k, v))
>> doesn't work? Should I file a bug?
>>
>> robey
>>
>
>
>

In Scala Tuples and function arguments look similar but they can’t be used interchangeably.

A Tuple of two Ints can be defined as:

Given a simple sum method that takes in two Ints:

you might think that you could simply pass in your tuple t2 to invoke the sum method:

Unfortunately this does not work as you can’t simply replace an argument list with a similarly-sized tuple. t2 is taken as the first argument n1, hence the error indicating that n2 has not been supplied.

One way to get this to work is to do the following:

Let’s break that incantation down step-by-step to make it more digestible.

  1. Convert the sum method into a Function:
  1. Convert the function into its tupled variant:

Tupling the sum function is merely going from to . Notice the extra parenthesis around the arguments.

  1. Apply the tupled function to the tupled input t2:

Looking back that does look very difficult but it’s not very intuitive.

Using Underscores with Currying

I had a similar problem recently where I had a contains method defined as:

And a List l1 defined as:

I tried to call the contains method using underscores for the values of the pred parameter and got the following error:

You can use underscores to represent positional arguments in an argument list where you don’t need to bind it to a name. So why did this fail?

I can get the contains method to work with:

Conversely, why did this work?

Another interesting variant is if I change the definition of contains to contains2 that takes in an uncurried pred function:

I can invoke it with the underscore syntax:

One of the main reasons for using a curried version of pred was that I could partially apply it with the exists method on List without having to use underscores to convert the method to a function. I can still achieve the same result by currying pred where it is applied:

The reason I couldn’t use underscores to represent the parameters of the contains method is that the curried function pred, represents two argument lists; One that takes an and returns another function that takes another and returns a Boolean:

Underscores can only used to represent positional arguments of a single argument list, since we have two in the curried variation of pred in contains we can’t use it.

Changing the shape of the Input Function

If I define a uncurried function isEqual as:

I can call contains2 as:

If I define an isEqual2 as:

I can call contains as:

But if I try to call contains2 with isEqual2 we get:

And we can fix that by uncurrying isEqual2:

If we define isEqual3 with a Tuple2 as:

And we try to invoke contains2 with isEqual3 we get:

And we can easily fix that by untupling the parameters to isEqual3:

Case Class Constructors

And one last example invoking a constructor of a case class:

If I try to invoke pc with nameAge I get an error as expected:

And we can solve that by tupling the constructor:

Or more succinctly:

Hopefully this has given you some insight into the various ways to invoke functions that takes tuples, curried arguments or uncurried variants.

Some references: