- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Confused noob question about functions as objects
Mon, 2011-04-04, 18:32
because in a function, the default implementation of hashcode is used
(inherited from object).
Am 04.04.2011 19:26, schrieb Donald McLean:
> In this code, the values printed for the hash code of bob1 and bob2
> are not the same. Why is that?
>
> @Test
> def trySomethingElse() {
> val bob1: ()=>Unit = bob
> println(bob1.hashCode)
> val bob2: ()=>Unit = bob
> println(bob2.hashCode)
> }
>
> def bob() {
> println("Hello, world.")
> }
>
Mon, 2011-04-04, 18:57
#2
Re: Confused noob question about functions as objects
On 4/4/11 10:26 AM, Donald McLean wrote:
> In this code, the values printed for the hash code of bob1 and bob2
> are not the same. Why is that?
Because they're different objects. Eta expansions aren't cached.
Tue, 2011-04-05, 05:17
#3
Re: Confused noob question about functions as objects
Any reason for them to be not equal? Whatever the wrapper is, it could
preserve equality of the wrapped - it is natural to expect it to be a
function, no?
Thanks,
-Vlad
On Mon, Apr 4, 2011 at 10:30 AM, Paul Phillips wrote:
> On 4/4/11 10:26 AM, Donald McLean wrote:
>>
>> In this code, the values printed for the hash code of bob1 and bob2
>> are not the same. Why is that?
>
> Because they're different objects. Eta expansions aren't cached.
>
Tue, 2011-04-05, 05:37
#4
Re: Confused noob question about functions as objects
On 4/4/11 9:04 PM, Vlad Patryshev wrote:
> Any reason for them to be not equal? Whatever the wrapper is, it could
> preserve equality of the wrapped - it is natural to expect it to be a
> function, no?
It can't preserve the equality of the wrapped, because the thing it is
wrapping is incomparable. A method is equal to nothing (not even
itself, I imagine) because it is not a value.
That aside, there's no point in making them equal. There would be a
point in saving an object and reusing the first one, and then they would
be equal as a consequence. But anyone who wants their program to do
different things based on whether this function object is equal to that
function object is in trouble no matter what we do, and I'd feel bad
tempting them by making this one narrow case work.
Tue, 2011-04-05, 14:47
#5
Re: Confused noob question about functions as objects
On Tue, Apr 5, 2011 at 12:30 AM, Paul Phillips wrote:
> On 4/4/11 9:04 PM, Vlad Patryshev wrote:
>>
>> Any reason for them to be not equal? Whatever the wrapper is, it could
>> preserve equality of the wrapped - it is natural to expect it to be a
>> function, no?
>
> It can't preserve the equality of the wrapped, because the thing it is
> wrapping is incomparable. A method is equal to nothing (not even itself, I
> imagine) because it is not a value.
>
> That aside, there's no point in making them equal. There would be a point
> in saving an object and reusing the first one, and then they would be equal
> as a consequence. But anyone who wants their program to do different things
> based on whether this function object is equal to that function object is in
> trouble no matter what we do, and I'd feel bad tempting them by making this
> one narrow case work.
"in trouble" based on what, exactly? A statement like that must have
some kind of theoretical principle behind it. I'm kinda new to some of
this functional stuff and would appreciate being enlightened.
Thank you,
Donald
Tue, 2011-04-05, 15:07
#6
Re: Confused noob question about functions as objects
On Tuesday April 5 2011, Donald McLean wrote:
> On Tue, Apr 5, 2011 at 12:30 AM, Paul Phillips wrote:
> > ...
> >
> > That aside, there's no point in making them equal. There would be
> > a point in saving an object and reusing the first one, and then
> > they would be equal as a consequence. But anyone who wants their
> > program to do different things based on whether this function
> > object is equal to that function object is in trouble no matter
> > what we do, and I'd feel bad tempting them by making this one
> > narrow case work.
>
> "in trouble" based on what, exactly? A statement like that must have
> some kind of theoretical principle behind it. I'm kinda new to some
> of this functional stuff and would appreciate being enlightened.
As I understand it, it is a metatheorem of logic and the mathematics of
functions that there is no intensional way to determine whether two
functions compute the same thing.
I'm only echoing vaguely, imprecisely and probably not too correctly
what has been written in these forums already.
Why do you want to test Function instances for equality?
> Thank you,
>
> Donald
Randall Schulz
Tue, 2011-04-05, 15:27
#7
Re: Confused noob question about functions as objects
So that I can remove a callback from a structure.
Donald
On Tue, Apr 5, 2011 at 9:52 AM, Randall R Schulz wrote:
> Why do you want to test Function instances for equality?
Tue, 2011-04-05, 15:37
#8
Re: Confused noob question about functions as objects
On Tuesday April 5 2011, Donald McLean wrote:
> So that I can remove a callback from a structure.
>
> Donald
>
> On Tue, Apr 5, 2011 at 9:52 AM, Randall R Schulz wrote:
> > Why do you want to test Function instances for equality?
Then you'll have to remember the precise instance you registered.
Randall Schulz
Tue, 2011-04-05, 15:47
#9
Re: Confused noob question about functions as objects
On Tuesday April 5 2011, Donald McLean wrote:
> So that I can remove a callback from a structure.
>
> Donald
>
> On Tue, Apr 5, 2011 at 9:52 AM, Randall R Schulz wrote:
> > Why do you want to test Function instances for equality?
Is this a Java API or a Scala API? 'Cause if it's Scala, you should
probably define it to avoid these problems.
Randall Schulz
Tue, 2011-04-05, 16:07
#10
Re: Confused noob question about functions as objects
On Tue, Apr 5, 2011 at 10:27 AM, Randall R Schulz wrote:
> On Tuesday April 5 2011, Donald McLean wrote:
>> So that I can remove a callback from a structure.
>>
>> On Tue, Apr 5, 2011 at 9:52 AM, Randall R Schulz wrote:
>> > Why do you want to test Function instances for equality?
>
> Is this a Java API or a Scala API? 'Cause if it's Scala, you should
> probably define it to avoid these problems.
I would be happy to entertain suggestions. I don't pretend to be
anything but a neophyte with Scala so mostly I just look for solutions
that work without necessarily worrying about whether or not they fit
somebody's notion of "proper Scala".
Donald
Tue, 2011-04-05, 16:07
#11
Re: Confused noob question about functions as objects
The last message was meant as a reply to Randall not Donald.
On Tue, Apr 5, 2011 at 11:03 AM, Lex wrote:
> I actually stumbled upon the issue of comparing function objects as well.
> While there is no computable way to verify that ANY two functions are
> equivalent, it is perfectly logical and reasonable to verify that SOME
> functions are equivalent. Basically true if we know they are the same
> object or share exactly the same source code or false otherwise. Maybe
> not call it == but something along the lines of
> "verifiablyEquivalent". The main contract would be that you get false
> negatives, but never false positives.
>
> This is more useful than you think. Especially when dealing objects
> that have callbacks or higher-order functions.
Tue, 2011-04-05, 16:17
#12
Re: Confused noob question about functions as objects
I actually stumbled upon the issue of comparing function objects as well.
While there is no computable way to verify that ANY two functions are
equivalent, it is perfectly logical and reasonable to verify that SOME
functions are equivalent. Basically true if we know they are the same
object or share exactly the same source code or false otherwise. Maybe
not call it == but something along the lines of
"verifiablyEquivalent". The main contract would be that you get false
negatives, but never false positives.
This is more useful than you think. Especially when dealing objects
that have callbacks or higher-order functions.
On Tue, Apr 5, 2011 at 10:48 AM, Donald McLean wrote:
> On Tue, Apr 5, 2011 at 10:27 AM, Randall R Schulz wrote:
>> On Tuesday April 5 2011, Donald McLean wrote:
>>> So that I can remove a callback from a structure.
>>>
>>> On Tue, Apr 5, 2011 at 9:52 AM, Randall R Schulz wrote:
>>> > Why do you want to test Function instances for equality?
>>
>> Is this a Java API or a Scala API? 'Cause if it's Scala, you should
>> probably define it to avoid these problems.
>
> I would be happy to entertain suggestions. I don't pretend to be
> anything but a neophyte with Scala so mostly I just look for solutions
> that work without necessarily worrying about whether or not they fit
> somebody's notion of "proper Scala".
>
> Donald
>
Tue, 2011-04-05, 18:07
#13
Re: Confused noob question about functions as objects
In this particular case you could define 'bob' as a function object (and not as a method that gets
converted to function objects in assignments):
val bob = () => println("Hello, world.")
Sorry, if this is obvious to you.
On 2011-04-04 19:26, Donald McLean wrote:
> In this code, the values printed for the hash code of bob1 and bob2
> are not the same. Why is that?
>
> @Test
> def trySomethingElse() {
> val bob1: ()=>Unit = bob
> println(bob1.hashCode)
> val bob2: ()=>Unit = bob
> println(bob2.hashCode)
> }
>
> def bob() {
> println("Hello, world.")
> }
>
Tue, 2011-04-05, 18:37
#14
Re: Confused noob question about functions as objects
No, that wasn't obvious. I'm still pretty new with Scala and very
little is obvious, yet.
Thank you for the suggestion. It's simple and effective - I like it.
Donald
On Tue, Apr 5, 2011 at 1:05 PM, Eugen Labun wrote:
> In this particular case you could define 'bob' as a function object (and not as a method that gets
> converted to function objects in assignments):
>
> val bob = () => println("Hello, world.")
>
> Sorry, if this is obvious to you.
>
> On 2011-04-04 19:26, Donald McLean wrote:
>> In this code, the values printed for the hash code of bob1 and bob2
>> are not the same. Why is that?
>>
>> @Test
>> def trySomethingElse() {
>> val bob1: ()=>Unit = bob
>> println(bob1.hashCode)
>> val bob2: ()=>Unit = bob
>> println(bob2.hashCode)
>> }
>>
>> def bob() {
>> println("Hello, world.")
>> }
Tue, 2011-04-05, 19:17
#15
Re: Confused noob question about functions as objects
True, the objects are different, but they have the same class.
For some purposes, using their class as, for instance, a hash
key does the trick.
On 04/04/2011 10:30 AM, Paul Phillips wrote:
> On 4/4/11 10:26 AM, Donald McLean wrote:
>> In this code, the values printed for the hash code of bob1 and bob2
>> are not the same. Why is that?
>
> Because they're different objects. Eta expansions aren't cached.
>
Tue, 2011-04-05, 19:27
#16
Re: Confused noob question about functions as objects
Not that I can see. The following test fails.
@Test
def trySomethingElse() {
val bob1: ()=>Unit = bob
println(bob1.hashCode)
println(bob1.getClass.getName)
val bob2: ()=>Unit = bob
println(bob2.hashCode)
println(bob2.getClass.getName)
bob1.getClass should be {bob2.getClass}
}
def bob() {
println("Hello, world.")
}
On Tue, Apr 5, 2011 at 1:56 PM, richard emberson
wrote:
> True, the objects are different, but they have the same class.
> For some purposes, using their class as, for instance, a hash
> key does the trick.
>
> On 04/04/2011 10:30 AM, Paul Phillips wrote:
>>
>> On 4/4/11 10:26 AM, Donald McLean wrote:
>>>
>>> In this code, the values printed for the hash code of bob1 and bob2
>>> are not the same. Why is that?
>>
>> Because they're different objects. Eta expansions aren't cached.
>>
>
> --
> Quis custodiet ipsos custodes
>
Tue, 2011-04-05, 19:47
#17
Re: Confused noob question about functions as objects
On 4/5/11 11:21 AM, Donald McLean wrote:
> Not that I can see. The following test fails.
You are correct, they don't have the same class. You can count the
classfiles.
class A {
def foo() = "bar"
val x1 = foo _
val x2 = foo _
}
% ls -l
-rw-r--r-- 1 paulp wheel 735 Apr 5 11:40 A$$anonfun$1.class
-rw-r--r-- 1 paulp wheel 735 Apr 5 11:40 A$$anonfun$2.class
-rw-r--r-- 1 paulp wheel 1089 Apr 5 11:40 A.class
Tue, 2011-04-05, 19:57
#18
Re: Confused noob question about functions as objects
The difference between methods and functions wasn't obvious to me, too as I learned Scala basics.
(In fact, I'm still learning!)
In short:
Essentially, we have only classes and instances (i.e. objects) of classes in Scala. Classes can have
methods (and other members).
Now, a "function" aka "function object" aka "function value" is nothing else as an *instance* of a
class that has one or more methods 'apply(...)'. That's all!
It's simply a syntactic sugar that expressions like 'f(x)' get translated by compiler into
'f.apply(x)'.
Since functions are instances of classes, they can have methods, but not vice versa.
Points of confusion:
1) you can pass a method name where a function value is expected (as in your initial code). The
compiler generates and inserts a function value that calls our initial method from its own
'apply'-method. This is called Eta-expansion.
2) some/many articles and books use the term "function" for both: function values and methods.
Best regards,
Eugen
On 2011-04-05 19:17, Donald McLean wrote:
> No, that wasn't obvious. I'm still pretty new with Scala and very
> little is obvious, yet.
>
> Thank you for the suggestion. It's simple and effective - I like it.
>
> Donald
>
> On Tue, Apr 5, 2011 at 1:05 PM, Eugen Labun wrote:
>> In this particular case you could define 'bob' as a function object (and not as a method that gets
>> converted to function objects in assignments):
>>
>> val bob = () => println("Hello, world.")
>>
>> Sorry, if this is obvious to you.
>>
>> On 2011-04-04 19:26, Donald McLean wrote:
>>> In this code, the values printed for the hash code of bob1 and bob2
>>> are not the same. Why is that?
>>>
>>> @Test
>>> def trySomethingElse() {
>>> val bob1: ()=>Unit = bob
>>> println(bob1.hashCode)
>>> val bob2: ()=>Unit = bob
>>> println(bob2.hashCode)
>>> }
>>>
>>> def bob() {
>>> println("Hello, world.")
>>> }
>
Tue, 2011-04-05, 20:17
#19
Re: Confused noob question about functions as objects
Am Dienstag, 5. April 2011, 19:17:06 schrieb Donald McLean:
> No, that wasn't obvious. I'm still pretty new with Scala and very
> little is obvious, yet.
>
> Thank you for the suggestion. It's simple and effective - I like it.
>
> Donald
>
> On Tue, Apr 5, 2011 at 1:05 PM, Eugen Labun wrote:
> > In this particular case you could define 'bob' as a function object (and
> > not as a method that gets converted to function objects in assignments):
> >
> > val bob = () => println("Hello, world.")
> >
> > Sorry, if this is obvious to you.
> >
> > On 2011-04-04 19:26, Donald McLean wrote:
> >> In this code, the values printed for the hash code of bob1 and bob2
> >> are not the same. Why is that?
> >>
> >> @Test
> >> def trySomethingElse() {
> >> val bob1: ()=>Unit = bob
> >> println(bob1.hashCode)
> >> val bob2: ()=>Unit = bob
> >> println(bob2.hashCode)
> >> }
> >>
> >> def bob() {
> >> println("Hello, world.")
> >> }
Hi Donald,
you've got always the possibility to extend FunctionN to suit your needs. This
is a bit clumsy - but may be an option for your use case:
-------------
Welcome to Scala version 2.9.0.RC1 (Java HotSpot(TM) 64-Bit Server VM, Java
1.6.0_24).
Type in expressions to have them evaluated.
Type :help for more information.
// thats a "normal" function instance
scala> val a: (Int) => Int = x => x+1
a: (Int) => Int =
// the same thing with an additional ident marker that can be used
// to identify functions or group kinds of functions as you require
scala> val b = new Function1[Int, Int] {
| def apply (x: Int): Int = x+1
| val ident = "whatever it takes to identify me"
| }
b: java.lang.Object with (Int) => Int{val ident: java.lang.String} =
scala> println(a(1))
2
scala> println(b(1))
2
scala> println(b.ident)
whatever it takes to identify me
------------
...or you wait until Paul has managed to bring parts of the AST as identifying
marker into the function instance and provides some utility analyzers to
compare functions based on plugable flow analytics ;-)
Hope that helps...
Greetings
Bernd
Tue, 2011-04-05, 20:57
#20
Re: Confused noob question about functions as objects
In this code, one can use their classes as a key for a hash.
import scala.collection.mutable.HashMap
import java.lang.management._
object Body {
object MethodNameFinder {
val map = new HashMap[Int, String]
val STACK_DEPTH = 5
class HandleDeref {
def getHandle(b: Function0[_]): AnyRef = b
}
type Deref = {
def getHandle[R](b: => R): AnyRef
}
val deref = (new HandleDeref).asInstanceOf[Deref]
def apply[R](body: => R): String = {
val hash = deref.getHandle(body).getClass.getName.hashCode
map.get(hash) match {
case Some(callingName) =>
println("In Cache: "+callingName)
callingName
case None =>
val n = getCallingFunctionName(2)
map += (hash -> n)
println("Was not in Cache: "+n)
n
}
}
def getCallingFunctionName(depth: Int): String = {
val mxBean = ManagementFactory.getThreadMXBean
val threadInfo = mxBean.getThreadInfo(Thread.currentThread.getId,
depth+STACK_DEPTH)
val elements = threadInfo.getStackTrace
// for (el <- elements) println("el="+el.getMethodName)
elements(depth+STACK_DEPTH-1).getMethodName
}
}
def monitor[R](body: => R): R = {
val methodName = MethodNameFinder(body)
println(" calling function="+methodName)
try {
body
} finally {
println(" monitor: BOTTOM")
}
}
def toad: String = monitor {
println(" toad inside")
return "MyToad"
} def bar(prefix: String): String = monitor {
println(" bar inside")
return prefix+" hi"
}
}
import Body._
object Main {
def main(args: Array[String]) {
println(" bar="+bar("one"))
println(" toad="+toad)
println(" bar="+bar("two"))
println(" bar="+bar("three"))
}
}
Output:
Was not in Cache: bar
calling function=bar
bar inside
monitor: BOTTOM
bar=one hi
Was not in Cache: toad
calling function=toad
toad inside
monitor: BOTTOM
toad=MyToad
In Cache: bar
calling function=bar
bar inside
monitor: BOTTOM
bar=two hi
In Cache: bar
calling function=bar
bar inside
monitor: BOTTOM
bar=three hi
In the previous example, REPL mislead me:
scala> bob1.getClass
res0: java.lang.Class[_] = class $anonfun$1
scala> bob2.getClass
res1: java.lang.Class[_] = class $anonfun$1
but:
scala> bob2.getClass == bob1.getClass
res2: Boolean = false
On 04/05/2011 11:42 AM, Paul Phillips wrote:
> On 4/5/11 11:21 AM, Donald McLean wrote:
>> Not that I can see. The following test fails.
>
> You are correct, they don't have the same class. You can count the
> classfiles.
>
> class A {
> def foo() = "bar"
> val x1 = foo _
> val x2 = foo _
> }
>
> % ls -l
> -rw-r--r-- 1 paulp wheel 735 Apr 5 11:40 A$$anonfun$1.class
> -rw-r--r-- 1 paulp wheel 735 Apr 5 11:40 A$$anonfun$2.class
> -rw-r--r-- 1 paulp wheel 1089 Apr 5 11:40 A.class
>
Tue, 2011-04-05, 21:27
#21
Re: Confused noob question about functions as objects
On 4/5/11 12:49 PM, richard emberson wrote:
> In the previous example, REPL mislead me:
>
> scala> bob1.getClass
> res0: java.lang.Class[_] = class $anonfun$1
> scala> bob2.getClass
> res1: java.lang.Class[_] = class $anonfun$1
Ah. Sorry about that. Not so easy to do anything about the occasional
repl misleading without introducing a ton of noise. In the future, if
you would like to see what things really are, you can print them rather
than letting the repl handle the stringifying.
scala> def f() = ""
f: ()java.lang.String
scala> val bob1 = f _
bob1: () => java.lang.String =
scala> bob1.getClass
res3: java.lang.Class[_] = class $anonfun$1
scala> println(bob1.getClass)
class $line6.$read$$iw$$iw$$anonfun$1
scala> val bob2 = f _
bob2: () => java.lang.String =
scala> println(bob2.getClass)
class $line9.$read$$iw$$iw$$anonfun$1
In this code, the values printed for the hash code of bob1 and bob2
are not the same. Why is that?
@Test
def trySomethingElse() {
val bob1: ()=>Unit = bob
println(bob1.hashCode)
val bob2: ()=>Unit = bob
println(bob2.hashCode)
}
def bob() {
println("Hello, world.")
}