Recursion is an essential tool in functional programming (FP) – it is the canonical way (and often the only way) to represent iteration.
Being a hybrid object/functional language, Scala offers both recursion and imperative control structures (like
while, etc) to express iteration. However, imperative control statements imply using mutable state, while Scala (and FP in general) encourages data immutability. That is why you may prefer to use recursion (or higher order functions) in the first place.
To facilitate the FP approach to recursion, Scala offers:
So far so good. Yet the underlying platform (i.e. JVM) still uses up a call stack for non-tail recursive methods, so we can get a nasty stack overflow in no time while processing reasonably large amounts of data. Therefore it is a good idea to know where recursion lurks (and to easily distinguish its type).
While, in real-life code, recursion is not always obvious, new icons help us to reveal it:
Let’s (for the sake of example) rewrite our linear recursion to tail recursion:
We can use an intention (Alt + Enter) to automatically add
@tailrec annotation which guarantees that compiler will always optimize the method (or will refuse to compile it).
After we (accidentally) change the method back to the linear recursion, we can immediately notice the violation of the contract:
If you wish, you may enable an optional “No @tailrec annotation inspection” which suggests to add
@tailrec annotation when needed.
Intentions were extended with several new.
- Now you can simply switch between two different ways of writing expressions – infix and method call. Convert infix notation to method call (and vice versa) intention provides you this possibility. It appears when you put caret to the operation in your statement.
- Intention for removing unnecessary ‘apply’ simplifies your code.
But in some cases it’s impossible to do this action. So, you will see error hint, which explains you reasons of rejecting your action. For example:
- Now you are able to introduce explicit parameters in anonymous function (and vice versa). Sometimes you meet with situations, when you write function with implicit parameters, but then realize that you must add new parameters or do something else that is impossible to do with implicit parameters. This intention provides you possibility to replace your infix expression with function expression. If you put caret near the placeholder you will be able to use this intention.
After converting you can change parameters names:
Also you can perform reverse converting. But in some cases it is impossible to refactor this authomatically, because of, for example, incorrect order of parameters usages. So you will see error hint with explanations.
- Replace ‘==’ with ‘equals’ and replace ‘equals’ with ‘==’ intentions work both in infix and method call expressions. You should put your caret into ‘==’ or ‘equals’.
- Swap operands intention swaps the operands of a comparison expression. It works with all following operators: ‘<’, ‘>’, ‘<=’, ‘>=’, ‘!=’, ‘==’, ‘eq’, ‘ne’, ‘equals’ and both in infix and method call expressions.
Recently completion was improved, so I want to describe most significant changes:
- Basic completion works as Class Name completion in case if nothing found. If something is found, you can invoke second basic completion to observe classes, which you want to import.
So if you want to import for example HashMap you can just type HashMap and choose appropriate variant (in case if autopopup completion is enabled).
- Completion after ‘@’ is smarter now. Both class name and basic completions show only annotations (scala and java).
- Added false, true, this and prefixed this to smart completion. Added prefixed this and super to basic completion (so now it’s much simpler to type such code).
- String.length, String.hashCode, String.trim has no side effects, so it’s always completing without unnecessary, annoying parentheses.
- Class name completion after point tries to find possible implicit conversions (with fixing imports), for example:
- Basic completion can filter inappropriate variants after implicit conversions in case if there are two implicit conversions, which lead to two elements with same signature. It means that this is impossible to use such variant, because of implicit ambiguity. For example parameter ‘x’ in class ‘Ensuring’ and parameter ‘x’ in class ‘ArrowAssoc’, these variants are bad, so it can be filtered.
- All completion can choose variants of same name, which have the biggest priority in place, where completion was invoked, so you will see only variant, to which actually will be resolved reference after completion. So it means that shadowing is supported by completion.
- classOf completion always inserts ‘‘.
- Class name completion supports aliased imports.
- Improved completion from Java for Scala keywords like ‘Thread.yield’ (it suggests only back-ticked variant).
- Added smart completion for eta expanded functions:
- Added smart completion for enum elements (Java and Scala).
- Added smart completion for factory methods (static methods for Java classes, methods from companion object for Scala classes).
- Name completion for classes. On toplevel if there is no class matching to file name, it suggests file name as class name. For all possible companion classes it suggests name of these classes (to make creation of companion objects faster and less error-prone).
- Some completion now works on first invocation (http://blog.jetbrains.com/scala/2011/09/16/some-smart-completion/).
- Second smart completion searches chains of methods:
- Fixed many bugs and usability problems.
Last releases are coming with full scaladoc 2 support
- Go to declaration and Auto completion for entity links and @throws tags
- Go to declaration, Auto completion, Renaming and Generation by signature for @tparam and @param tags
- Highlighting and Brace matching for wiki syntax and html tags
- Some Inspections (unknown tag, missing parameter, unknown or duplicating parameter, inspections for wiki syntax, missing parameter description) and Quick fixes (delete unknown tag/parameter, quick fixes for wiki syntax)
Build 0.5.265 is coming with new cool features for ScalaTest.
First of all it shows now outdated configurations. For example you removed test class, but your configuration is still here, then you’ll see that you shouldn’t try to run this outdated configuration:
What’s next. New plugin version is coming with possibility to run single test.
Usually it’s not obvious what exact test name is, so you have possibility to run single test from context menu. Currently rules to get test name from location is hard-coded for all suites in the latest ScalaTest package. But it won’t work for your custom suites and your custom method invocations to register new tests. That will be possibly changed in future, but now you should write test name by yourself for custom suites.
Next feature is test navigation. It will work only with unreleased ScalaTest 2.0 (I’m not sure is it available in maven repository, but you can build your own ScalaTest 2.0 snapshot). So you can double click on test and navigate to exact test location. Moreover, joined with previous new feature you can use right click on test node and re-run (or debug) just this test.
Also ScalaTest 2.0 is coming with better scoping feature. It means you will see better tree in test run view:
And that is not all. New feature for ScalaTest integration is re-running failed tests. After the first run you added some fixes and you don’t need to run previously successful tests, so you can just re-run failed tests and you will see, which of them are fixed.
Last thing I want to describe is Coverage integration (for IntelliJ IDEA Ultimate users). It just works:
Thanks to Bill Venners and Chee Seng Chua (from ScalaTest team) for collaboration on doing this cool features.
Evaluate expression feature is available now in build 0.5.180.
This feature is not fully implemented (and will not be in foreseeable future) and have beta quality, however even now it’s much more usable than it was using Java language.
- Scala editor with debug context resolve/completion.
- Add import action.
- Conditional breakpoints.
- Local variables evaluation, even from inner functions/classes (you don’t need to use $ anymore).
- Local function calls.
- Implicit conversions.
- Default, named, implicit parameters for method calls.
- New instance creation.
- Boxing/unboxing of primitive values.
- Primitive values calculations.
- While/do/if statements.
- Assign statements.
- Pattern matching local value with one usage (It’s probably will be done).
- Anonymous classes (It’s will not be done as in Java Evaluate Expression)
- Anonymous functions (the same as for classes, however It’s slightly simpler than for classes, so unlikely, that it will be done, but it’s possible)
- By-name parameters (it’s anonymous function, however It’s probably will be done)
- Default, named, implicit parameters for constructors.
- Pattern matching.
- Variables/function declarations.
- Dynamic method calls (I’m sure it will be fixed soon)
Look at this feature in action:
Is it possible using Java?
This feature is available from build 0.5.142. Now you can generate Scaladoc html documentation for the entire project or custom scope from the IntelliJ IDEA.
To use it, select “Generate Scaladoc” from Tools menu. Then you will see configuration dialog:
After choosing output directory you can press OK and get documentation for your project.
I’m glad to introduce to you new feature of Scala plugin, which is coming with builds 0.4.1480 and 0.5.111 (depends on IntelliJ IDEA version).
This called “Show implicit parameters action”, however it also can be called like “Go to passed implicit value”.
As usual using of this feature is very simple. Look at the following example:
Then you probably want to know, what is actually passed to `foo` call. So you can press Ctrl+Shift+P, and then you will get the result:
After that you can choose parameter for navigation.
New scala console comes with build 0.5.89 (http://confluence.jetbrains.net/display/SCA/Scala+Plugin+Nightly+Builds+for+Nika).
Now you can use full featured editor for editing code in console (just instead of Enter, use Shift + Enter).
And after execution:
This comes only with Nika scala plugin builds (this is the first difference between Nika and IDEA X plugins).