Why is java.util.UUID.randomUUID not accepted as a parameter

3,137 views
Skip to first unread message

Cecil Westerhof

unread,
Sep 9, 2012, 6:26:59 AM9/9/12
to scala...@googlegroups.com
I have the following function definition:

def testGenerateUuids(name: String,
uuidFn: () => String,
repeats: Int,
iterations: Int) {

When I call this with:
testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
I get:
/home/cecil/scala/test.scala:111: error: type mismatch;
found : java.util.UUID
required: String
testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
^
What am I doing wrong?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

√iktor Ҡlang

unread,
Sep 9, 2012, 6:34:08 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
On Sun, Sep 9, 2012 at 12:26 PM, Cecil Westerhof <cldwes...@gmail.com> wrote:
I have the following function definition:

    def testGenerateUuids(name:       String,
                          uuidFn:     () => String,
                          repeats:    Int,
                          iterations: Int) {

When I call this with:
    testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
I get:
    /home/cecil/scala/test.scala:111: error: type mismatch;
     found   : java.util.UUID
     required: String
    testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
                                             ^
What am I doing wrong?


What the compiler tells you: you are giving it a java.util.UUID and it wants a String.

Cheers,
 
--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Lukas Rytz

unread,
Sep 9, 2012, 6:34:38 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
functions with an empty param list can be called without argument list "()".

so "java.util.UUID.randomUUID" is an application, you need
"() => java.util.UUID.randomUUID"
"java.util.UUID.randomUUID _"

On Sun, Sep 9, 2012 at 12:26 PM, Cecil Westerhof <cldwes...@gmail.com> wrote:

Lukas Rytz

unread,
Sep 9, 2012, 6:36:59 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
oh, victor is right of course, you need .toString, and ignore my answer, the
compiler will do the eta expansion for you based on the parameter type.

Cecil Westerhof

unread,
Sep 9, 2012, 6:42:14 AM9/9/12
to scala...@googlegroups.com
Op zondag 9 sep 2012 12:34 CEST schreef √iktor Ҡlang:

> On Sun, Sep 9, 2012 at 12:26 PM, Cecil Westerhof <cldwes...@gmail.com> wrote:
>
> I have the following function definition:
>
>     def testGenerateUuids(name:       String,
>                           uuidFn:     () => String,
>                           repeats:    Int,
>                           iterations: Int) {
>
> When I call this with:
>     testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
> I get:
>     /home/cecil/scala/test.scala:111: error: type mismatch;
>      found   : java.util.UUID
>      required: String
>     testGenerateUuids("uuid", java.util.UUID.randomUUID, 5, 1000000)
>                                              ^
> What am I doing wrong?
>
> What the compiler tells you: you are giving it a java.util.UUID and it wants a
> String.

But why does it wants a String? I would think that with:
uuidFn: () => String,
it wants a function without parameters that returns a String.

Cecil Westerhof

unread,
Sep 9, 2012, 7:36:02 AM9/9/12
to scala...@googlegroups.com
Op zondag 9 sep 2012 12:42 CEST schreef Cecil Westerhof:
Even more weird. The following works:

def nano() = {
println("Getting nano")
System.nanoTime
}

def delayed(t: => Long) = {
println("In delayed method")
println("Param: "+t)
t
}

delayed(nano)

But this does not:

def uuid() = {
println("Getting uuid")
java.util.UUID.randomUUID
}

def delayed(t: => String) = {
println("In delayed method")
println("Param: "+t)
t
}

delayed(uuid)

For my inexperienced eye it is the same. So why does the first work,
and the second not?

AGYNAMIX Torsten Uhlmann

unread,
Sep 9, 2012, 7:50:46 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
You uuid() method returns a java.util.UUID, not a String.

You can make it return a String though: java.util.UUID.randomUUID.toString

scala> def uuid2() = {
     | java.util.UUID.randomUUID.toString
     | }
uuid2: ()java.lang.String

scala> delayed(uuid2)
In delayed method
Param: fc535715-3f72-469e-83a1-6827e4ed5ec0
res3: String = 198668e5-d367-4782-9af2-208ae87bcd41

Does that help?

Torsten.


-- 
AGYNAMIX(R). Passionate Software.
Inh. Torsten Uhlmann | Buchenweg 5 | 09380 Thalheim
Phone:       +49 3721 273445
Fax:             +49 3721 273446
Mobile:       +49 151 12412427
Web:           http://www.agynamix.de

Cecil Westerhof

unread,
Sep 9, 2012, 9:02:10 AM9/9/12
to scala...@googlegroups.com
Op zondag 9 sep 2012 13:50 CEST schreef AGYNAMIX Torsten Uhlmann:

> You uuid() method returns a java.util.UUID, not a String.
>
> You can make it return a String though: java.util.UUID.randomUUID.toString

Stupid mistake. I now changed it to:

def testGenerateUuids(name: String,
uuidFn: => java.util.UUID,
repeats: Int,
iterations: Int) {

By the way
uuidFn: () => java.util.UUID,
what I had seen somewhere does not work.


> Does that help?

It certainly did. Thanks.

AGYNAMIX Torsten Uhlmann

unread,
Sep 9, 2012, 9:11:49 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
Glad I could help.

Now when you use param: => String its a call-by-name parameter which is evaluated each time it is accessed, 

if you use ()=>String then it's a function that gets no input parameter and returns a String.

To do the code below with a function, you could write:

def uuid() = {
       println("Getting uuid")
       java.util.UUID.randomUUID
}

def delayed(func: ()=>java.util.UUID) = {

       println("In delayed method")
       func()
}

delayed(()=>uuid()), or 

delayed(uuid _)

In the first "delayed" call you create a function that calls, when executed, the uuid() method (it's executed with the func() call in def delayed).
The second version lifts the "uuid" method into a function. In the case above you could omit the underscore, I'm not quiet sure about the rules when it's needed and when not.

Does that help even more? :)

Torsten.


-- 
AGYNAMIX(R). Passionate Software.
Inh. Torsten Uhlmann | Buchenweg 5 | 09380 Thalheim
Phone:       +49 3721 273445
Fax:             +49 3721 273446
Mobile:       +49 151 12412427
Web:           http://www.agynamix.de

Cecil Westerhof

unread,
Sep 9, 2012, 9:49:18 AM9/9/12
to scala...@googlegroups.com
Op zondag 9 sep 2012 15:11 CEST schreef AGYNAMIX Torsten Uhlmann:

> Glad I could help.
>
> Now when you use param: => String its a call-by-name parameter which is
> evaluated each time it is accessed,
>
> if you use ()=>String then it's a function that gets no input parameter and
> returns a String.

I used the previous version, but the function was just called as I
wanted. Why (if at all) should I switch to this notation?


> Does that help even more? :)

My head starts to hurt. :-D

AGYNAMIX Torsten Uhlmann

unread,
Sep 9, 2012, 10:37:54 AM9/9/12
to Cecil Westerhof, scala...@googlegroups.com
Am 09.09.2012 um 15:49 schrieb Cecil Westerhof <cldwes...@gmail.com>:

> Op zondag 9 sep 2012 15:11 CEST schreef AGYNAMIX Torsten Uhlmann:
>
>> Glad I could help.
>>
>> Now when you use param: => String its a call-by-name parameter which is
>> evaluated each time it is accessed,
>>
>> if you use ()=>String then it's a function that gets no input parameter and
>> returns a String.
>
> I used the previous version, but the function was just called as I
> wanted. Why (if at all) should I switch to this notation?

The different notations are for different purposes. A call-by-name parameter is a parameter to a function that's evaluated on every access.
If you write a log method for instance, these parameters come in handy:

def log(msg: => String): Unit = {
if (isLogEnabled) println(msg)
}

If you call it like log("%s has the value of %s".format(valueA, valueB)) then the string is only assembled if "isLogEnabled" is true.

The other notation ()=>String is for passing blocks of code (functions) into objects, classes, methods, etc. You can pass parameters:

String=>String for instance which you can not do with a call-by-name parameter.

Now, I would guess, that a call-by-name parameter and a function with no parameters will both be compiled into a Function0 (that's a Trait that has an apply method that returns what your function would return or what your parameter type is), but I don't know if there are internal differences.

So using call-by-name conveys a different message than using a function block.

Here's an example with a function that takes a parameter:

scala> def uuid(prefix: String)={
| println("Getting uuid")
| prefix+java.util.UUID.randomUUID
| }
uuid: (prefix: String)java.lang.String

scala> def delayed(prefix: String, func: String=>String)={
| println("In delayed method")
| func(prefix)
| }
delayed: (prefix: String, func: String => String)String

scala> delayed("Hi_", uuid)
In delayed method
Getting uuid
res1: String = Hi_d40649f1-c417-43dd-87e4-35bd2121fc47

Hope I could clear up the head spinning :)

Torsten.
Reply all
Reply to author
Forward
0 new messages