Better Tuple Syntactic Sugar

436 views
Skip to first unread message

wookietreiber

unread,
May 26, 2012, 6:38:34 AM5/26/12
to scala-...@googlegroups.com
Hi there,

I'd like Scala to better support tuple syntax, consider the following
example:

> $ scala
> Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_03-icedtea).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
> <console>:8: error: wrong number of parameters; expected = 1
> (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
> ^

Instead of being able to that, currently I have to go the long way:

> scala> (0 to 5).zipWithIndex map { ab => val (a,b) = ab ; a*b } foreach println
> 0
> 1
> 4
> 9
> 16
> 25

It is already possible with for expressions:

> scala> for { i <- 0 to 5 ; ps = (i,i) ; (a,b) = ps } println(a*b)
> 0
> 1
> 4
> 9
> 16
> 25

So why not with e.g. functions like in the example above?


--

Beste Gr��e / Best Regards
Christian Krause aka wookietreiber

-----------------------------------------------------------------------

Egal wie dicht du bist, Goethe war Dichter.

Jason Zaugg

unread,
May 26, 2012, 6:42:44 AM5/26/12
to scala-...@googlegroups.com
On Sat, May 26, 2012 at 12:38 PM, wookietreiber
<kizkizz...@googlemail.com> wrote:
> Hi there,
>
> I'd like Scala to better support tuple syntax, consider the following
> example:
>
>> $ scala
>> Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_03-icedtea).
>> Type in expressions to have them evaluated.
>> Type :help for more information.
>>
>> scala> (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
>> <console>:8: error: wrong number of parameters; expected = 1
>>               (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println

You can destructure function arguments with a pattern matching
anonymous function:

scala> (0 to 5).zipWithIndex map { case (a,b) => a*b }
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4, 9, 16, 25)

-jason

wookietreiber

unread,
May 26, 2012, 6:55:36 AM5/26/12
to scala-...@googlegroups.com
Doesn't this introduce some performance overhead, that goes along with
pattern matching or will that get optimized away?

>
> -jason

Dave

unread,
May 26, 2012, 7:17:10 AM5/26/12
to scala-debate
Instead of map you can also collect.
Isn't this a redundancy in the scala api?


scala> (0 to 5).zipWithIndex map { case (a,b) => a*b }
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4, 9,
16, 25)

scala>

scala> (0 to 5).zipWithIndex collect { case (a,b) => a*b }

Tony Sloane

unread,
May 26, 2012, 7:21:29 AM5/26/12
to Dave, scala-debate
Not really. collect allows its argument to be undefined.

scala> (0 to 5).zipWithIndex map { case (a,b) if a % 2 == 0 => a*b }
scala.MatchError: (1,1) (of class scala.Tuple2)
...

scala> (0 to 5).zipWithIndex collect { case (a,b) if a % 2 == 0 => a*b }
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 4, 16)

Nikita Volkov

unread,
May 26, 2012, 7:30:50 AM5/26/12
to scala-...@googlegroups.com
@wookietreiber No, there's no overhead, nor are any optimizations needed. All the code that partial functions add (that's how the {case ...} construct is named) is just some specific if-conditions and a throw-statement when they are not met. In your case it will probably just check the tuple on not being null.

2012/5/26 wookietreiber <kizkizz...@googlemail.com>
On Sat, May 26, 2012 at 12:42:44PM +0200, Jason Zaugg wrote:
> On Sat, May 26, 2012 at 12:38 PM, wookietreiber
> <kizkizz...@googlemail.com> wrote:
> > Hi there,
> >
> > I'd like Scala to better support tuple syntax, consider the following
> > example:
> >
> >> $ scala
> >> Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_03-icedtea).
> >> Type in expressions to have them evaluated.
> >> Type :help for more information.
> >>
> >> scala> (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
> >> <console>:8: error: wrong number of parameters; expected = 1
> >>               (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
>
> You can destructure function arguments with a pattern matching
> anonymous function:
>
> scala> (0 to 5).zipWithIndex map { case (a,b) => a*b }
> res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4, 9, 16, 25)

Doesn't this introduce some performance overhead, that goes along with
pattern matching or will that get optimized away?

>
> -jason

--

Beste Grüße / Best Regards

Jason Zaugg

unread,
May 26, 2012, 7:44:45 AM5/26/12
to Nikita Volkov, scala-...@googlegroups.com
On Sat, May 26, 2012 at 1:30 PM, Nikita Volkov
<nikita....@gmail.com> wrote:
> @wookietreiber No, there's no overhead, nor are any optimizations needed.
> All the code that partial functions add (that's how the {case ...} construct
> is named) is just some specific if-conditions and a throw-statement when
> they are not met. In your case it will probably just check the tuple on not
> being null.

To nitpick: `{ case pat => expr; ... }` is a pattern matching
anonymous function. It must be defined in a context where the expected
type is `FunctionN[A1,...,AN, ?]` or `PartialFunction1[A, ?]`, and
that expected type will determine what it compiles to.

If you want to be sure what code is emitted:

~/code/scala scala -print -e "(0 to 5).zipWithIndex map { case (a,b) => a*b }"

final <synthetic> class Main$$anon$1$$anonfun$1 extends
scala.runtime.AbstractFunction1 with Serializable {
final def apply(x0$1: Tuple2): Int = {
<synthetic> val temp1: Tuple2 = x0$1;
if (temp1.ne(null))
{
scala.Int.unbox(temp1._1()).*(scala.Int.unbox(temp1._2()))
}
else
throw new MatchError(temp1)
};
///
};


-jason

wookietreiber

unread,
May 26, 2012, 8:21:46 AM5/26/12
to scala-...@googlegroups.com
Ah, thanks for the explanation.
--

Beste Gr��e / Best Regards

Naftoli Gugenheim

unread,
Jun 10, 2012, 10:24:11 PM6/10/12
to scala-...@googlegroups.com
The same overhead exists in

> scala> (0 to 5).zipWithIndex map { ab => val (a,b) = ab ; a*b } foreach println

val (a,b) = ... is also a pattern match.


On Sat, May 26, 2012 at 6:55 AM, wookietreiber <kizkizz...@googlemail.com> wrote:
On Sat, May 26, 2012 at 12:42:44PM +0200, Jason Zaugg wrote:
> On Sat, May 26, 2012 at 12:38 PM, wookietreiber
> <kizkizz...@googlemail.com> wrote:
> > Hi there,
> >
> > I'd like Scala to better support tuple syntax, consider the following
> > example:
> >
> >> $ scala
> >> Welcome to Scala version 2.9.2 (OpenJDK 64-Bit Server VM, Java 1.7.0_03-icedtea).
> >> Type in expressions to have them evaluated.
> >> Type :help for more information.
> >>
> >> scala> (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
> >> <console>:8: error: wrong number of parameters; expected = 1
> >>               (0 to 5).zipWithIndex map { (a,b) => a*b } foreach println
>
> You can destructure function arguments with a pattern matching
> anonymous function:
>
> scala> (0 to 5).zipWithIndex map { case (a,b) => a*b }
> res1: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4, 9, 16, 25)

Doesn't this introduce some performance overhead, that goes along with
pattern matching or will that get optimized away?

>
> -jason

--

Beste Grüße / Best Regards

Pedro Furlanetto

unread,
Jun 12, 2012, 11:01:17 PM6/12/12
to scala-...@googlegroups.com
There is also pattern match in the for: 

scala> for ( (a,b) <-  (0 to 5).zipWithIndex ) yield a*b
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 4, 9, 16, 25)
Reply all
Reply to author
Forward
0 new messages