I am new to scala. Currently I am trying to develop a calculator as scala project.
But while trying to find the sum I am getting problem. The following code doesn't compile.
def add [T](values :List[T]) : Option[T]={
if (values.isInstanceOf[String]) {
None
}
else if(values.isInstanceOf[Int] || values.isInstanceOf[Long] || values.isInstanceOf[Double]) {
Some(values.sum)
}
}
When you're new to a language, it is important to start slow and discover the abstractions rather than impose them right away without the experience to make it work. I also think it is a bad idea to just rely on standard library functions (unless you are in a hurry) like sum or to look at third-party libraries until you fully understand what the standard library offers.
So in other words, first let's look at ways to solve the problem just for Int:
def add(values: List[Int]) = values.reduce((a, b) => a + b)
The reduce function works because the type of the result matches the type of what is in the list. The contents are Ints, and the sum is an Int. You will also find this can be simplified with some syntactic sugar:
def add(values: List[Int]) = values.reduce(_ + _)
Wait until you see all the ways underscores get used in Scala.
As you keep studying, you will find that in order to accumulate a value that is a different type than what's in the list, you can use one of the fold* methods. But they can work here too, so for example you could also do this:
def add(values: List[Int]) = values.foldLeft(0)(_ + _)
Now try to define the same function for Long, Double, or even String. You will find the implementations will be almost identical.
It's only when you see implementations that look really similar if not identical that you should even think about abstractions. One option to solve this problem is with type classes. They aren't easy for beginners though. Daniel Westheide wrote a great post on the topic, and frankly you would do well to read the whole series as you learn Scala.
I've really simplified things and glossed over a lot of topics (like why foldLeft has two parameter lists with the first one being 0 or what those crazy implicit things are in Daniel's type classes post), but my advice is to be patient and move slowly. Scala isn't easy, but you'll get it.
(But if you are in a hurry and you are a beginner, I think you are better off just using sum and then writing separate functions for each type. This would be an example of what agile author Kenny Rubin would call "necessary" or "unavoidable" technical debt, and that's to be expected from beginners. Just refactor later.)
Or more generic (example with amm):
# import $ivy.`org.typelevel:cats_2.12:0.8.1`
import $ivy.$
# import cats._, cats.implicits._
import cats._, cats.implicits._
# List(1, 2, 3).combineAll
res2: Int = 6
# List("1", "2", "3").combineAll
res3: String = "123"
# List(List(1, 2), List(), List(3)).combineAll
res5: List[Int] = List(1, 2, 3)
Or via fiddle. It works by using the Monoid and Traversable typeclass.
Related
I am new to Scala and now I went through a construct like the following:
scala> var a = List(('a',1),('b',2))
I googled this one and it turned out to be a Scala tuple2. My question is:
Is this a special Scala constructs i.e whenever I use ('a',3), scala creates a Tuple2 or there is something configured that I can change to make scala create MyTuple2 instead of Tuple2?
Can I create my own class that makes scala use it whenever I use its constructor?
As pointed out in the comments, Tuple2 is just a class like any other. You can create your own like this:
case class MyTuple2[A, B](a: A, b: B)
val myTuples: List[MyTuple2[String, Int]] = List(MyTuple2("a", 1), MyTuple2("b", 2))
As for the syntax, you cannot override the syntax-sugar of normal tuples (afaik). There are certainly things you could do with implicits or macros to fake it, but I'd strongly encourage you not to do that as it's highly surprising to anyone else if something looks like a standard Tuple2, but doesn't behave like one.
I'm using the Reader monad in Scala as provided by the scalaz library. I'm familiar with this monad as defined in Haskell. The problem is that I cannot find the functions equivalent to return, local, and sequence (among others).
Currently I use constructs that I do not like since I'm repeating myself or making my code a bit obscure.
Regarding return, I'm currently using:
Reader{_ => someValue}
I'd rather just use a construct like unit(someValue), but I could not find anything on the internet. There are tutorials like this one that use the approach above, and which I consider not optimal.
Regarding local I also have to do something similar: instead of typing something like: local f myReader I have to unfold its definition:
Reader{env => myReader.run(f(env))
Finally, sequence is a bit closer to what I would expect (being a Haskell refugee doing Scala):
readers: List[Reader[Env, T]]
readerTs: Reader[Env, List[T]] = readers.sequenceU
My problem with this implementation is that, being relatively new to Scala, the type of sequenceU
final class TraverseOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Traverse[F]) extends Ops[F[A]] {
//...
def sequenceU(implicit G: Unapply[Applicative, A]): G.M[F[G.A]]
appears like rather obscure, and seems like black magic. Ideally I would like to use a sequence operations on Monads.
Is there a better translation of these constructs to Scala available on scalaz or similar library? I'm not married to any Functional library for Scala, so any solution using other libraries will do, although I'd rather have an answer using scalaz, since I already implemented my code using it.
To make the things simpler, I fill in some types. Changing them to defs with generic types should still work.
Also I extracted the ReaderInt type, to avoid confusion with type lambdas.
return / pure / point
Scala does not have automatic typeclass resolution, so you need to provide them implicitly. For Kleisli (being a monad transformer for reader),
Kleisli[Id, ?, ?] is enough
implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]
type ReaderInt[A] = Kleisli[Id.Id, Int, A]
val alwaysHello = KA.point("hello")
or with imported syntax:
import scalaz.syntax.applicative._
val alwaysHello = "hello".point[ReaderInt]
So as a general rule, you
1) import the applicative intance, which usually located in scalaz.std.something.somethingInstance
2) import scalaz.syntax.something._
3) then you can write x.point[F], where F is your applicative.
local
Not sure, that it answers your question, but Kleisli has a local method.
val f: String ⇒ Int = _.length
val alwaysEleven = alwaysHello local f
sequencing
The same way, you are free to choose to use syntax for or to specify type classes explicitly.
import scalaz.std.list.listInstance
val initial: List[ReaderInt[String]] = ???
val sequenced: ReaderInt[List[String]] = Traverse[List].sequence[ReaderInt, String](initial)
import scalaz.syntax.traverse._
val z = x.sequence[ReaderInt, String]
I prefer not to use sequenceU, which uses Unapply typelcass to infer the G type, because sometimes scala has troubles of figuring out the right one.
And I personally do not find it messy to put in some types myself.
It may worth to look into cats, though it does not have much yet.
I've been working with Scala for a while now and have written a 10,000+ line program with it, but I'm still confused by some of the inner workings. I came to Scala from Python after already having intimate familiarity with Java, C and Lisp, but even so it's been slow going, and a huge problem is the frustrating difficulty I've often found when trying to investigate the inner workings of objects/types/classes/etc. using the Scala REPL as compared with Python. In Python you can investigate any object foo (type, object in a global variable, built-in function, etc.) using foo to see what the thing evaluates to, type(foo) to show its type, dir(foo) to tell you the methods you can call on it, and help(foo) to get the built-in documentation. You can even do things like help("re") to find out the documentation on the package named re (which holds regular-expression objects and methods), even though there isn't an object associated with it.
In Scala, you can try and read the documentation online, go look up the source code to the library, etc., but this can often be very difficult for things where you don't know where or even what they are (and it's often a big chunk to bite off, given the voluminous type hierarchy) -- stuff is floating around in various places (package scala, Predef, various implicit conversions, symbols like :: that are nearly impossible to Google). The REPL should be the way to explore directly, but in reality, things are far more mysterious. Say that I've seen a reference to foo somewhere, but I have no idea what it is. There's apparently no such thing as a "guide to systematically investigating Scala thingies with the REPL", but the following is what I've pieced together after a great deal of trial and error:
If foo is a value (which presumably includes things stored in variables plus companion objects and other Scala objects), you can evaluate foo directly. This ought to tell you the type and value of the result. Sometimes the result is helpful, sometimes not.
If foo is a value, you can use :type foo to get its type. (Not necessarily enlightening.) If you use this on a function call, you get the type of the return value, without calling the function.
If foo is a value, you can use foo.getClass to get its class. (Often more enlightening than the previous, but how does an object's class differ from its type?)
For a class foo, you can use classOf[foo], although it's not obvious what the result means.
Theoretically, you can use :javap foo to disassemble a class -- which should be the most useful of all, but fails entirely and uniformly for me.
Sometimes you have to piece things together from error messages.
Example of failure using :javap:
scala> :javap List
Failed: Could not find class bytes for 'List'
Example of enlightening error message:
scala> assert
<console>:8: error: ambiguous reference to overloaded definition,
both method assert in object Predef of type (assertion: Boolean, message: => Any)Unit
and method assert in object Predef of type (assertion: Boolean)Unit
match expected type ?
assert
^
OK, now let's try a simple example.
scala> 5
res63: Int = 5
scala> :type 5
Int
scala> 5.getClass
res64: java.lang.Class[Int] = int
Simple enough ...
Now, let's try some real cases, where it's not so obvious:
scala> Predef
res65: type = scala.Predef$#3cd41115
scala> :type Predef
type
scala> Predef.getClass
res66: java.lang.Class[_ <: object Predef] = class scala.Predef$
What does this mean? Why is the type of Predef simply type, whereas the class is scala.Predef$? I gather that the $ is the way that companion objects are shoehorned into Java ... but Scala docs on Google tell me that Predef is object Predef extends LowPriorityImplicits -- how can I deduce this from the REPL? And how can I look into what's in it?
OK, let's try another confusing thing:
scala> `::`
res77: collection.immutable.::.type = ::
scala> :type `::`
collection.immutable.::.type
scala> `::`.getClass
res79: java.lang.Class[_ <: object scala.collection.immutable.::] = class scala.collection.immutable.$colon$colon$
scala> classOf[`::`]
<console>:8: error: type :: takes type parameters
classOf[`::`]
^
scala> classOf[`::`[Int]]
res81: java.lang.Class[::[Int]] = class scala.collection.immutable.$colon$colon
OK, this left me hopelessly confused, and eventually I had to go read the source code to make sense of this all.
So, my questions are:
What's the recommended best way from the true Scala experts of using the REPL to make sense of Scala objects, classes, methods, etc., or at least investigate them as best as can be done from the REPL?
How do I get :javap working from the REPL for built-in stuff? (Shouldn't it work by default?)
Thanks for any enlightenment.
You mentioned an important point which Scala lacks a bit: the documentation.
The REPL is a fantastic tool, but it is not as fantastic at it can be. There are too much missing features and features which can be improved - some of them are mentioned in your post. Scaladoc is a nice tool, too, but is far away to be perfect. Furthermore lots of code in the API is not yet or too less documented and code examples are often missing. The IDEs are full ob bugs and compared to the possibilities Java IDEs show us they look like some kindergarten toys.
Nevertheless there is a gigantic difference of Scalas current tools compared to the tools available as I started to learn Scala 2-3 years ago. At that time IDEs compiled permanently some trash in the background, the compiler crashed every few minutes and some documentation was absolutely nonexistent. Frequently I got rage attacks and wished death and corruption to Scala authors.
And now? I do not have any of these rage attacks any more. Because the tools we currently have are great although the are not perfect!
There is docs.scala-lang.org, which summarizes a lot of great documentation. There are Tutorials, Cheat-sheets, Glossaries, Guides and a lot of more great stuff. Another great tools is Scalex, which can find even the weirdest operator one can think of. It is Scalas Hoogle and even though it is not yet as good as his great ideal, it is very useful.
Great improvements are coming with Scala2.10 in form of Scalas own Reflection library:
// needs Scala2.10M4
scala> import scala.reflect.runtime.{universe => u}
import scala.reflect.runtime.{universe=>u}
scala> val t = u.typeOf[List[_]]
t: reflect.runtime.universe.Type = List[Any]
scala> t.declarations
res10: Iterable[reflect.runtime.universe.Symbol] = SynchronizedOps(constructor List, method companion, method isEmpty, method head, method tail, method ::, method :::, method reverse_:::, method mapConserve, method ++, method +:, method toList, method take, method drop, method slice, method takeRight, method splitAt, method takeWhile, method dropWhile, method span, method reverse, method stringPrefix, method toStream, method removeDuplicates)
Documentation for the new Reflection library is still missing, but in progress. It allows one to use scalac in an easy way inside of the REPL:
scala> u reify { List(1,2,3) map (_+1) }
res14: reflect.runtime.universe.Expr[List[Int]] = Expr[List[Int]](immutable.this.List.apply(1, 2, 3).map(((x$1) => x$1.$plus(1)))(immutable.this.List.canBuildFrom))
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> import scala.reflect.runtime.{currentMirror => m}
import scala.reflect.runtime.{currentMirror=>m}
scala> val tb = m.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl#32f7fa37
scala> tb.parseExpr("List(1,2,3) map (_+1)")
res16: tb.u.Tree = List(1, 2, 3).map(((x$1) => x$1.$plus(1)))
scala> tb.runExpr(res16)
res18: Any = List(2, 3, 4)
This is even greater when we want to know how Scala code is translated internally. Formerly wen need to type scala -Xprint:typer -e "List(1,2,3) map (_+1)"
to get the internally representation. Furthermore some small improvements found there way to the new release, for example:
scala> :type Predef
scala.Predef.type
Scaladoc will gain some type-hierarchy graph (click on type-hierarchy).
With Macros it is possible now, to improve error messages in a great way. There is a library called expecty, which does this:
// copied from GitHub page
import org.expecty.Expecty
case class Person(name: String = "Fred", age: Int = 42) {
def say(words: String*) = words.mkString(" ")
}
val person = Person()
val expect = new Expecty()
// Passing expectations
expect {
person.name == "Fred"
person.age * 2 == 84
person.say("Hi", "from", "Expecty!") == "Hi from Expecty!"
}
// Failing expectation
val word1 = "ping"
val word2 = "pong"
expect {
person.say(word1, word2) == "pong pong"
}
/*
Output:
java.lang.AssertionError:
person.say(word1, word2) == "pong pong"
| | | | |
| | ping pong false
| ping pong
Person(Fred,42)
*/
There is a tool which allows one to find libraries hosted on GitHub, called ls.implicit.ly.
The IDEs now have some semantic highlighting, to show if a member is a object/type/method/whatever. The semantic highlighting feature of ScalaIDE.
The javap feature of the REPL is only a call to the native javap, therefore it is not a very featue-rich tool. You have to fully qualify the name of a module:
scala> :javap scala.collection.immutable.List
Compiled from "List.scala"
public abstract class scala.collection.immutable.List extends scala.collection.AbstractSeq implements scala.collection.immutable.LinearSeq,scala.Product,scala.collection.LinearSeqOptimized{
...
Some time ago I have written a summary of how Scala code is compiled to Bytecode, which offers a lot of things to know.
And the best: This is all done in the last few months!
So, how to use all of these things inside of the REPL? Well, it is not possible ... not yet. ;)
But I can tell you that one day we will have such a REPL. A REPL which shows us documentation if we want to see it. A REPL which let us communicate with it (maybe like lambdabot). A REPL which let us do cool things we still cannot imagine. I don't know when this will be the case, but I know that a lot of stuff was done in the last years and I know even greater stuff will be done in the next years.
Javap works, but you are pointing it to scala.Predef.List, which is a type, not a class. Point it instead to scala.collection.immutable.List.
Now, for the most part just entering a value and seeing what the result's type is is enough. Using :type can be helpful sometimes. I find that use getClass is a really bad way of going about it, though.
Also, you are sometimes mixing types and values. For example, here you refer to the object :::
scala> `::`.getClass res79: java.lang.Class[_ <: object
scala.collection.immutable.::] = class
scala.collection.immutable.$colon$colon$
And here you refer to the class :::
scala> classOf[`::`[Int]] res81: java.lang.Class[::[Int]] = class
scala.collection.immutable.$colon$colon
Objects and classes are not the same thing, and, in fact, there's a common pattern of objects and classes by the same name, with a specific name for their relationship: companions.
Instead of dir, just use tab completion:
scala> "abc".
+ asInstanceOf charAt codePointAt codePointBefore codePointCount
compareTo compareToIgnoreCase concat contains contentEquals endsWith
equalsIgnoreCase getBytes getChars indexOf intern isEmpty
isInstanceOf lastIndexOf length matches offsetByCodePoints regionMatches
replace replaceAll replaceFirst split startsWith subSequence
substring toCharArray toLowerCase toString toUpperCase trim
scala> "abc".compareTo
compareTo compareToIgnoreCase
scala> "abc".compareTo
def compareTo(String): Int
If you enter the power mode, you'll get way more information, but that's hardly for beginners. The above shows types, methods, and method signatures. Javap will decompile stuff, though that requires you to have a good handle on bytecode.
There's other stuff in there -- be sure to look up :help, and see what's available.
Docs are only available through the scaladoc API. Keep it open on the browser, and use its search capability to quickly find classes and methods. Also, note that, as opposed to Java, you don't need to navigate through the inheritance list to get the description of the method.
And they do search perfectly fine for symbols. I suspect you haven't spent much time on scaladoc because other doc tools out there just aren't up to it. Javadoc comes to mind -- it's awful browsing through packages and classes.
If you have specific questions Stack Overflow style, use Symbol Hound to search with symbols.
Use the nightly Scaladocs: they'll diverge from whatever version you are using, but they'll always be the most complete. Besides, right now they are far better in many respects: you can use TAB to alternate between frames, with auto-focus on the search boxes, you can use arrows to navigate on the left frame after filtering, and ENTER to have the selected element appear on the right frame. They have the list of implicit methods, and have class diagrams.
I've made do with a far less powerful REPL, and a far poorer Scaladoc -- they do work, together. Granted, I skipped to trunk (now HEAD) just to get my hands on tab-completion.
Note that scala 2.11.8 New tab-completion in the Scala REPL can facilitate the type exploration/discovery.
It now includes:
CamelCase completion:
try:
(l: List[Int]).rroTAB,
it expands to:
(l: List[Int]).reduceRightOption
Find members by typing any CamelCased part of the name:
try:
classOf[String].typTAB,
to get getAnnotationsByType, getComponentType and others
Complete bean getters without typing get:
try:
(d: java.util.Date).dayTAB
Press TAB twice to see the method signature:
try:
List(1,2,3).partTAB,
which completes to:
List(1,2,3).partition;
press TAB again to display:
def partition(p: Int => Boolean): (List[Int], List[Int])
You need to pass fully qualified class name to javap.
First take it using classOf:
scala> classOf[List[_]]
res2: java.lang.Class[List[_]] = class scala.collection.immutable.List
Then use javap (doesn't work from repl for me: ":javap unavailable on this platform.") so example is from a command line, in repl, I believe, you don't need to specify classpath:
d:\bin\scala\scala-2.9.1-1\lib>javap -classpath scala-library.jar "scala.collection.immutable.List"
But I doubt this will help you. Probably you're trying to use techniques you used to use in dynamic languages. I extremely rarely use repl in scala (while use it often in javascript). An IDE and sources are my all.
Array programming languages (also known as vector or multidimensional languages) generalize operations on scalars to apply transparently to vectors, matrices, and higher dimensional arrays.
Is it possible to achieve this kind of code reuse in Scala?
It's entirely possible (I've done so myself) with appropriate implicits, though the result is not always as utterly seamless as a language that has been designed from the ground up that way.
For example, suppose you want to treat arrays of integers as vectors and want to be able to add them to each other and to scalars. You have to define the operation yourself--Scala can't guess what + should mean on an array. (Good thing, too, because * doesn't usually have the obvious element-by-element meaning on matrices, and it means something else again when it comes to convolution!) You can
class ArraysAdd(a: Array[Int]) {
def +(i: Int) = a.map(_ + i)
def +(b: Array[Int]) = {
if (b.length==a.length) (a,b).zipped.map(_ + _).toArray
else throw new IllegalArgumentException
}
}
class ScalarAddsToArray(i: Int) {
def +(a: Array[Int]) = a.map(_ + i)
}
implicit def array2addable(a: Array[Int]) = new ArraysAdd(a)
implicit def scalar2arrayaddable(i: Int) = new ScalarAddsToArray(i)
and then you can do math on arrays of integers:
scala> Array(1,2,3) + 5
res2: Array[Int] = Array(6, 7, 8)
scala> Array(1,7) + Array(3,2)
res3: Array[Int] = Array(4, 9)
scala> 4 + Array(-2,-3,-1)
res4: Array[Int] = Array(2, 1, 3)
If you want to cover all data types it gets trickier (you need to use generics and Numeric at least--or write a code generator to cover the cases you need), and for efficiency you might want to create a custom "matrix" class instead of sticking with raw arrays that you keep wrapping with extra functionality.
This covers basic operations. For mathematical functions like math.sqrt, if you don't mind typing a map sqrt instead of sqrt(a) then you don't need to do anything. Otherwise, you can overload them all yourself; tedious, but it then lets you use them transparently.
Or you could use a library that has already done much of this for you. (Scalala is the best candidate I know of for matrices.)
There isn't any real way to auto-lift Scala operations, as would you would need to to support array programming languages like APL and J. The closest thing to array auto-lifting in Scala is implicit conversions, and that's not quite right. Scala implicit conversions go the opposite way, converting the targets of the operations, rather than the operations themselves. Even then, Scala implicit conversions don't chain, so even if you could lift a scalar operation to a vector (which you can't), that wouldn't automatically lift it to a 2-D or higher array.
In short, doing APL/J-ish calculation in Scala is going to involve seeing the "map" and "flatMap" methods a lot, explicitly called (as well as fold, reduce, scan, and all the other usual suspects). One benefit is that you can code those operations as for-comprehensions in Scala, which can give some admirable clarity for these sort of batch operations over collections.
Is something like scalala what you're looking for?
I want to give a Scala presentation and I want to do it by taking an application and evolve it from something which uses java idioms to something that uses the power of scala (traits, pattern matching, implicit convertions, functional programming).
I'm especially interested in something that demonstrates a design change, rather than syntactic sugar. Something where the end scala code is evidently easier to maintain and extend.
So any ideas? (I'm not asking for code examples, just the rough ideas of what example to use and what design principles can be demonstrated).
A wonderful example is developing a little interpreter for a dynamic mini-language.
The basic java implementation requires the classical interpreter design pattern, whereas a functional scala-approach can use many wonderful functional idioms like
case classes
pattern matching
higher-order functions
or maybe even monads in order to produce very clean and easily understandable code.
Just compare
class Number implements Expression {
private int number;
public Number(int number) { this.number = number; }
public int interpret(HashMap<String,Integer> variables) { return number; }
}
with
case NumberLiteral(i) => Integer(i)
See the interpreter examples at the scala page.
To help you choose among the features and build some nice code examples, here are some ideas:
try to stick on your audience business domain. Try to take example (even basics) from their usual applications.
try to guess your audience main language (java, perl, C++) and make syntax comparisons in your examples.
have a look at: A tour of scala and Scala snippets and pick features to preasent, which you like and you are comfortable with.
try to remember your early steps with scala and situations where you were impressed (or puzzled).
I think you may be being too ambitious in your scope. Just showing people a new and unfamiliar syntax is likely to "lose" them a little, so adding in yet more drastic changes may be a step too far. Don't forget: you can always do a second presentation if the first is popular!
I did pretty much this at my company a while back; it was only as I was giving the presentation that I suddenly grasped how strange and incomprehensible some scala syntax was appearing to the audience (or perhaps it was my delivery style!). I found that the following went down well:
An iterative approach - take a single Java method (not a whole program) and then convert to really dumb like-for-like Scala (type declarations and all). Now apply one set of scala substitutions (e.g. type inference), followed by another (e.g. type aliases) followed by another (e.g. closures) etc. The end result of this would probably be about a third of the Java code, much more readable and concise, which can be contrasted as people are now familiar with what is going on. It's amazing to what extent Java is just a jumbled bunch of types and keywords when viewed in comparison with something like scala.
Take a while to explain all the asides - for example, go through pattern-matching in some detail and how it works. Don't skim over extractors or case x :: xs. I found people were really interested in this and what was so great about it!
Functional programming style takes a while to sink in. It's not reasonable to get people to start understanding this stuff straight away. I've been programming in Scala for over a year and I'm still confused by some of it.
Using the REPL is really cool for some low-level things like showing how everything in scala (including synchronized, try-catch etc) is an expression with a type.
When you've justified the awesomeness of the lower-level stuff, hopefully you'll have whetted people's appetite for more. (I was looking at the implementations of the ternary operator with a - scala-familiar - colleague just last week and he found it slightly confusing. Attempting to introduce an entire app to a bunch of newbies is way too much!)
The spelling corrector example was used to explain Python in the Stackoverflow Devdays. A short scala implementation may be a start:
import util.matching.Regex.MatchIterator
val alphabet = 'a' to 'z' toArray
def train(features : MatchIterator) = (Map[String, Int]() /: features)((m, f) => m + ((f, m.getOrElse(f, 0) + 1)))
def words(text : String) = ("[%s]+" format alphabet.mkString).r.findAllIn(text.toLowerCase)
val dict = train(words(io.Source.fromFile("big.txt").mkString))
def edits(s : Seq[(String, String)]) = (for((a,b) <- s; if b.length > 0) yield a + b.substring(1)) ++
(for((a,b) <- s; if b.length > 1) yield a + b(1) + b(0) + b.substring(2)) ++
(for((a,b) <- s; c <- alphabet if b.length > 0) yield a + c + b.substring(1)) ++
(for((a,b) <- s; c <- alphabet) yield a + c + b)
def edits1(word : String) = edits(for(i <- 0 to word.length) yield (word take i, word drop i))
def edits2(word : String) = for(e1 <- edits1(word); e2 <-edits1(e1)) yield e2
def known(words : Seq[String]) = for(w <- words; found <- dict.get(w)) yield w
def or[T](candidates : Seq[T], other : => Seq[T]) = if(candidates.isEmpty) other else candidates
def candidates(word: String) = or(known(List(word)), or(known(edits1(word)), known(edits2(word))))
def correct(word : String) = ((-1, word) /: candidates(word))(
(max, word) => if(dict(word) > max._1) (dict(word), word) else max)._2
List("osters", "musters", "mixters") map correct foreach println
It demonstrates higher order functions, tuple support, regex support, call by name, for expressions. OO features (type system, traits, objects, packages and visibility) are missing. (I aimed at a short implementation.) But you can these to get to a OO implementation. For example you can add some traits like Dictionary, Corrector etc.