I've read here about the difference between functions and methods in scala. It says that methods can be slightly faster than functions. But when passing a method m as an argument using m _, m is implicitly converted to a function.
Is the performance difference significant enough to ponder avoiding Functions when it is going to be a bottleneck in my program?
Is there a way to pass a method as an argument without converting it to a Function?
Kind of irrelevant to by 2. But in general, forget about performance, methods are more readable than function declarations. They might be a little faster in some situations from compiler optimizations, but:
You cannot pass a method as an argument without converting it to a function. A method is a special language construct, and not an object itself. You must use eta-expansion to convert it to one if you want to use it as an object.
No.
No. In the extremely rare case where this kind of microperformance was important, you'd want to pass the object that the method is on, and either modify the receiving function to accept that, or make the object implement one of the FunctionN interfaces so that it can be used as a function.
It makes just as much sense avoiding functions as it does avoiding other object allocations. There's nothing particularly special about them.
It's possible to pass and invoke methods directly using reflection, but the performance is going to be much worse than passing functions in the similar situation.
Related
I am not sure the keywords for this pattern, sorry if the question is not clear.
If you have:
case class MyFancyWrapper(
somethingElse: Any,
heavyComplexObject: CrazyThing
)
val w = MyFancyWrapper(???, complexThing)
I want to be able to call w.method with the method coming from complexThing. I tried to extends CrazyThing but it is a trait and I don't want to implement all the method that would be very tedious. I also don't want to have to do:
def method1 = heavyComplexObject.method1
...
for all of them.
Any solution ?
Thanks.
You can do this with macros but I agree with Luis that this is an overkill. Macros are intended to repetitive boring things, not one time boring things. Also this is not as trivial as it sounds, because you probably don't want to pass through all the methods (you probably still want your own hashCode and equals). Finally macros have bad IDE support so most probably no auto-completion for all those methods. On the other hand if you do use a good IDE (like IDEA) there is most probably an action like "Delegate methods" that will generate most of the code for you. You still will have to change the return type from Unit to MyFancyWrapper and add returning this at the end of each method but this can easily be done with mass replace operations (hint: replace "}" with "this }" and the automatically re-formatting code should do the trick)
Here are some screenshots of the process from JetBrains IDEA:
You can use an implicit conversion to make all the methods of heavyComplexThing directly available on MyFancyWrapper:
implicit def toHeavy(fancy: MyFancyWrapper): CrazyThing = fancy.heavyComplexObject
This needs to be in scope when the method is called.
In the comments you indicate that you want to return this so that you can chain multiple calls on the same object:
w.method1.method2.method3
Don't do this
While this is a common pattern in non-functional languages, it is bad practice is Scala for two reasons:
This pattern inherently relies on side-effects, which is the antithesis of functional programming.
It is confusing, because in Scala chaining calls in this way is used to implement a data pipeline, where the output of one function is passed as the input to the next.
It is much clearer to write separate statements so that it is obvious that the methods are being called on the same object:
w.method1()
w.method2()
w.method3()
(It is also conventional to use () when calling methods with side effects)
It's a rather general purpose question and not specific to any one language. I don't quite understand the point behind passing a function as an argument to another function. I understand that if a function, say, foo1() needs to use some result returned by another function foo2(), why can't the values returned/updated by foo2() be passed to foo1() as is? Or in another scenario, why can't the foo2() be called within foo1() with its results being used therein?
Also what happens under the hood when a foo2() is passed as an argument to foo1()? Is foo2() executed prior to foo1()?
Generally speaking, you pass a function foo2 to a function foo1 in cases where multiple evaluations of foo2 will be necessary - and you perhaps don't know in advance what parameters will be used for each call of foo2, so you couldn't possibly perform the calls yourself in advance.
I think that a sort() function/method on lists might be the best concrete example. Consider a list of People - you might reasonably want to sort them alphabetically by name, or numerically by age, or by geographical distance from a given point, or many other possible orders. It would hardly be practical to include every such ordering as built-in options to sort(): the usual approach taken by languages is to allow the caller to provide a function as a parameter, that defines the ordering between items of the list.
There are many reasons:
Dependency injection: if you pass a method that in production will use a database call, and you use it with different parameters, you could substitute it with some mock when unit testing.
Map, filter, reduce: you could apply the same method to a list of parameters, to map it, filter it or reduce it.
Usually to provide callbacks, or to separate interface from implementation. Look up the following:
1. Dependency Injection,
2. Callbacks,
3. Anonymous Functions (aka Lambdas),
4. PIMPL
etc
Take a look at this book where it is used extensively in developing TDD with C:
https://www.amazon.co.uk/Driven-Development-Embedded-Pragmatic-Programmers/dp/193435662X
I have been reading about methods and functions in Scala. Jim's post and Daniel's complement to it do a good job of explaining what the differences between these are. Here is what I took with me:
functions are objects, methods are not;
as a consequence functions can be passed as argument, but methods can not;
methods can be type-parametrised, functions can not;
methods are faster.
I also understand the difference between def, val and var.
Now I have actually two questions:
Why can't we parametrise the apply method of a function to parametrise the function? And
Why can't the method be called by the function object to run faster? Or the caller of the function be made calling the original method directly?
Looking forward to your answers and many thanks in advance!
1 - Parameterizing functions.
It is theoretically possible for a compiler to parameterize the type of a function; one could add that as a feature. It isn't entirely trivial, though, because functions are contravariant in their argument and covariant in their return value:
trait Function1[+T,-R] { ... }
which means that another function that can take more arguments counts as a subclass (since it can process anything that the superclass can process), and if it produces a smaller set of results, that's okay (since it will also obey the superclass construct that way). But how do you encode
def fn[A](a: A) = a
in that framework? The whole point is that the return type is equal to the type passed in, whatever that type has to be. You'd need
Function1[ ThisCanBeAnything, ThisHasToMatch ]
as your function type. "This can be anything" is well-represented by Any if you want a single type, but then you could return anything as the original type is lost. This isn't to say that there is no way to implement it, but it doesn't fit nicely into the existing framework.
2 - Speed of functions.
This is really simple: a function is the apply method on another object. You have to have that object in order to call its method. This will always be slower (or at least no faster) than calling your own method, since you already have yourself.
As a practical matter, JVMs can do a very good job inlining functions these days; there is often no difference in performance as long as you're mostly using your method or function, not creating the function object over and over. If you're deeply nesting very short loops, you may find yourself creating way too many functions; moving them out into vals outside of the nested loops may save time. But don't bother until you've benchmarked and know that there's a bottleneck there; typically the JVM does the right thing.
Think about the type signature of a function. It explicitly says what types it takes. So then type-parameterizing apply() would be inconsistent.
A function is an object, which must be created, initialized, and then garbage-collected. When apply() is called, it has to grab the function object in addition to the parent.
I mean if there's some declarative way to prevent an object from changing any of it's members.
In the following example
class student(var name:String)
val s = new student("John")
"s" has been declared as a val, so it will always point to the same student.
But is there some way to prevent s.name from being changed by just declaring it like immutable???
Or the only solution is to declare everything as val, and manually force immutability?
No, it's not possible to declare something immutable. You have to enforce immutability yourself, by not allowing anyone to change it, that is remove all ways of modifying the class.
Someone can still modify it using reflection, but that's another story.
Scala doesn't enforce that, so there is no way to know. There is, however, an interesting compiler-plugin project named pusca (I guess it stands for Pure-Scala). Pure is defined there as not mutating a non-local variable and being side-effect free (e.g. not printing to the console)—so that calling a pure method repeatedly will always yield the same result (what is called referentially transparent).
I haven't tried out that plug-in myself, so I can't say if it's any stable or usable already.
There is no way that Scala could do this generally.
Consider the following hypothetical example:
class Student(var name : String, var course : Course)
def stuff(course : Course) {
magically_pure_val s = new Student("Fredzilla", course)
someFunctionOfStudent(s)
genericHigherOrderFunction(s, someFunctionOfStudent)
course.someMethod()
}
The pitfalls for any attempt to actually implement that magically_pure_val keyword are:
someFunctionOfStudent takes an arbitrary student, and isn't implemented in this compilation unit. It was written/compiled knowing that Student consists of two mutable fields. How do we know it doesn't actually mutate them?
genericHigherOrderFunction is even worse; it's going to take our Student and a function of Student, but it's written polymorphically. Whether or not it actually mutates s depends on what its other arguments are; determining that at compile time with full generality requires solving the Halting Problem.
Let's assume we could get around that (maybe we could set some secret flags that mean exceptions get raised if the s object is actually mutated, though personally I wouldn't find that good enough). What about that course field? Does course.someMethod() mutate it? That method call isn't invoked from s directly.
Worse than that, we only know that we'll have passed in an instance of Course or some subclass of Course. So even if we are able to analyze a particular implementation of Course and Course.someMethod and conclude that this is safe, someone can always add a new subclass of Course whose implementation of someMethod mutates the Course.
There's simply no way for the compiler to check that a given object cannot be mutated. The pusca plugin mentioned by 0__ appears to detect purity the same way Mercury does; by ensuring that every method is known from its signature to be either pure or impure, and by raising a compiler error if the implementation of anything declared to be pure does anything that could cause impurity (unless the programmer promises that the method is pure anyway).[1]
This is quite a different from simply declaring a value to be completely (and deeply) immutable and expecting the compiler to notice if any of the code that could touch it could mutate it. It's also not a perfect inference, just a conservative one
[1]The pusca README claims that it can infer impurity of methods whose last expression is a call to an impure method. I'm not quite sure how it can do this, as checking if that last expression is an impure call requires checking if it's calling a not-declared-impure method that should be declared impure by this rule, and the implementation might not be available to the compiler at that point (and indeed could be changed later even if it is). But all I've done is look at the README and think about it for a few minutes, so I might be missing something.
I'd like this thread to be some kind of summary of pros/cons for overriding and calling toString with or without empty parentheses, because this thing still confuses me sometimes, even though I've been into Scala for quite a while.
So which one is preferable over another? Comments from Scala geeks, officials and OCD paranoids are highly appreciated.
Pros to toString:
seems to be an obvious and natural choice at the first glance;
most cases are trivial and just construct Strings on the fly without ever modifying internal state;
another common case is to delegate method call to the wrapped abstraction:
override def toString = underlying.toString
Pros to toString():
definitely not "accessor-like" name (that's how IntelliJ IDEA inspector complains every once in a while);
might imply some CPU or I/O work (in cases where counting every System.arrayCopy call is crucial to performance);
even might imply some mutable state changing (consider an example when first toString call is expensive, so it is cached internally to yield quicker calls in future).
So what's the best practice? Am I still missing something?
Update: this question is related specifically to toString which is defined on every JVM object, so I was hoping to find the best practice, if it ever exists.
Here's what Programming In Scala (section 10.3) has to say:
The recommended convention is to use a parameterless method whenever
there are no parameters and the method accesses mutable state only by
reading fields of the containing object (in particular, it does not
change mutable state). This convention supports the uniform access
principle,1 which says that client code should not be affected by a
decision to implement an attribute as a field or method.
Here's what the (unofficial) Scala Style Guide (page 18) has to say:
Scala allows the omission of parentheses on methods of arity-0 (no
arguments):
reply()
// is the same as
reply
However, this syntax
should only be used when the method in question has no side-effects
(purely-functional). In other words, it would be acceptable to omit
parentheses when calling queue.size, but not when calling println().
This convention mirrors the method declaration convention given above.
The latter does not mention the Uniform Access Principle.
If your toString method can be implemented as a val, it implies the field is immutable. If, however, your class is mutable, toString might not always yield the same result (e.g. for StringBuffer). So Programming In Scala implies that we should use toString() in two different situations:
1) When its value is mutable
2) When there are side-effects
Personally I think it's more common and more consistent to ignore the first of these. In practice toString will almost never have side-effects. So (unless it does), always use toString and ignore the Uniform Access Principle (following the Style Guide): keep parentheses to denote side-effects, rather than mutability.
Yes, you are missing something: Semantics.
If you have a method that simply gives back a value, you shouldn't use parens. The reason is that this blurs the line between vals and defs, satisfying the Uniform Access Principle. E.g. consider the size method for collections. For fixed-sized vectors or arrays this can be just a val, other collections may need to calculate it.
The usage of empty parens should be limited to methods which perform some kind of side effect, e.g. println(), or a method that increases an internal counter, or a method that resets a connection etc.
I would recommend always using toString. Regarding your third "pro" to toString():
Might imply some mutable state changing (consider an example when first toString call is expensive, so it is cached internally to yield quicker calls in future).
First of all, toString generally shouldn't be an expensive operation. But suppose it is expensive, and suppose you do choose to cache the result internally. Even in that case, I'd say use toString, as long as the result of toString is always the same for a given state of the object (disregarding the state of the toString cache).
The only reason I would not recommend using toString without parens is if you have a code profiler/analyzer that makes assumptions based on the presence or absence of parens. In that case, follow the conventions set forth by said profiler. Also, if your toString is that complicated, consider renaming it to something else, like expensiveToString. It is unofficially expected that toString be a straightforward, simple function in most cases.
Not much argumentation in this answer but GenTraversableOnce alone declares the following defs without parentheses:
toArray
toBuffer
toIndexedSeq
toIterable
toIterator
toList
toMap
toSeq
toSet
toStream
toTraversable