the feel of scala - dewapurnama | just another wordpress ... · pdf file the feel of scala...
Post on 28-Mar-2018
224 Views
Preview:
TRANSCRIPT
www.devoxx.com
The Feel of Scala
Bill VennersPresidentArtima, Inc.www.artima.com
www.devoxx.com
Overall Presentation Goal
Give you a feel for what Scala programming is like, by showing Scala solutions to real problems.
www.devoxx.com
Run the Artima Developer website
An old Java guy, who chose Scala for Artima's next language
Coauthored Programming in Scala
Primary developer of ScalaTest
Enough about me
3
www.devoxx.com
The verbosity of Java code addsaccidental complexity to my software.
My Problem
www.devoxx.com
Scala lets me...
use and design libraries that enableclearer, more concise code.
www.devoxx.com
Can enhance Java
But can only add; can't subtract
Scala adds to and subtracts from Java
Not source compatible with Java language
But has seamless binary compatibility with JVM
What about Java?
6
www.devoxx.com
More concise; no type annotations
Can add new methods to existing classes
Can pass objects that share no common supertype to a method, which treats them uniformly
What about JRuby, Jython, and Groovy?
7
www.devoxx.com
More concise; no type annotations
Can add new methods to existing classes
Can pass objects that share no common supertype to a method, which treats them uniformly
Dynamic
8
Staticvs.deterministic refactoring
fewer tests needed
documentation
code completion
performance, on JVM
www.devoxx.com
More concise; fewer type annotations
Can effectively add new methods to existing classes
Can pass objects that share no common supertype to a method, which treats them uniformly
Scala gives me...
9
deterministic refactoring
fewer tests needed
documentation
code completion
performance, on JVM
www.devoxx.com
import scala.io.Source
def widthOfLength(s: String) = s.length.toString.length
if (args.length > 0)
val lines = Source.fromFile(args(0)).getLines.toList
val longestLine = lines.reduceLeft( (a, b) => if (a.length > b.length) a else b ) val maxWidth = widthOfLength(longestLine)
for (line <- lines) val numSpaces = maxWidth - widthOfLength(line) val padding = " " * numSpaces print(padding + line.length +" | "+ line) else Console.err.println("Please enter filename")
www.devoxx.com
DEMO
Type inference
www.devoxx.com
if (x == BigInteger.ZERO) BigInteger.ONEelse x.multiply(factorial(x.subtract(BigInteger.ONE)))
if (x == 0) 1 else x * factorial(x - 1) def factorial(x: BigInt): BigInt =
def factorial(x: BigInteger): BigInteger =
versus
www.devoxx.com
Every value is an object;Every operation a method call
map.containsKey('a') map containsKey 'a'
factorial(x - 1)factorial(x.-(1))
www.devoxx.com
map.should have_key('a')
Hamcrest matchers (Java)
RSpec matchers (Ruby)
assertThat(map, hasKey('a'));
In dynamic languages, open classes let you add new methods to existing classes and objects.
www.devoxx.com
Scala's implicit conversions lets you appear to add new methods to existing classes.
map should have key ('a')
ScalaTest matchers (Scala)
www.devoxx.com
map should have
map.should(have)
map should have key ('a')
map.should(have).key('a')
1 + 2 - 3
(1).+(2).-(3)
www.devoxx.com17
A wrapper class (in Java)
public class Wrapper private Object payload; public Wrapper(Object payload) this.payload = payload; public void should(HaveWord c) // ...
should(HaveWord)
Wrapper
Object
www.devoxx.com18
A conversion method (in Java)
public static Wrapper wrap(Object obj) return new Wrapper(obj);
should(HaveWord)
map.should(have) // ERROR
wrap(map).should(have)
www.devoxx.com19
An implicit conversion method (in Scala)
implicit def wrap(o: Any) = new Wrapper(o)
class Wrapper(payload: Any) def should(HaveWord c) // ...
www.devoxx.com
map should have key ('a')
map.should(have).key('a')
wrap(map).should(have).key('a')
1
2
3
www.devoxx.com21
ScalaTest matchers
map should have key ('a')
collection should contain element (1.0)
collection should have size (17)
string must equal ("done")
array must have length (9)
www.devoxx.com
Scala:
assert(result == 17)
www.devoxx.com
Scala:
assert(result == 17)
JUnit:
assertEquals(17, result);
www.devoxx.com
Scala:
assert(result == 17)
JUnit:
assertEquals(17, result);
ScalaTest:
assert(result === 17)
www.devoxx.com
DEMO
The === operator
www.devoxx.com26
Which is actual? Which is expected?
assertEquals(animalShelter.getCat(), myKitty);
www.devoxx.com27
A trick question
JUnit:
assertEquals(expected, actual);
TestNG:
assertEquals(actual, expected);
www.devoxx.com28
A basic control abstraction in Scala
JUnit:
assertEquals(expected, actual);
TestNG:
assertEquals(expected, actual);
ScalaTest:
expect(myKitty) animalShelter.getCat()
www.devoxx.com
DEMO
Curly braces and parens
Currying
By-name parameters
Expect in action
www.devoxx.com30
Testing for thrown exceptions (JUnit)
JUnit 3:String s = "hi”;try s.charAt(-1); fail();catch (StringIndexOutOfBoundsException e) // Expected, so continue
JUnit 4:@Test(expected=StringIndexOutOfBoundsException.class)public void testPassingANegativeToCharAt() s.charAt(-1);
www.devoxx.com31
Testing for thrown exceptions (ScalaTest)
intercept[StringIndexOutOfBoundsException] s.charAt(-1)
www.devoxx.com
DEMO
Intercept in action
Test methods with Suite and TestNGSuite
Test functions with FunSuite
BDD with Spec
www.devoxx.com33
The need to test private methods
expect("'c'") FailureMessages.decorateToStringValue('c')
www.devoxx.com34
Symbol literals in Scala
'decorateToStringValue
"'decorateToStringValue"
Symbol
www.devoxx.com35
Testing with invokePrivate (ScalaTest)
val decorateToStringValue = PrivateMethod[String]('decorateToStringValue)
expect("\"Howdy!\"") FailureMessages invokePrivate decorateToStringValue("Howdy!")expect("'c'") FailureMessages invokePrivate decorateToStringValue('c')expect("1") FailureMessages invokePrivate decorateToStringValue(1)expect("true") FailureMessages invokePrivate decorateToStringValue(true)
www.devoxx.com
DEMO
invokePrivate in action
www.devoxx.com37
Type checking in matchers
Map("hi" -> 1) should have key ("hi")
Map(1 -> "hi") should have key ("hi")
MatcherSpec.scala:1089: error: type mismatch; found : java.lang.String("hi") required: Int Map(1 -> "hi") should have key ("hi") ^
www.devoxx.com38
What should I require about the type of object?
object should have length (7)
www.devoxx.com39
object should have length (7)
Duck typing lets you pass objects that have the same structure, but no common supertypes.
www.devoxx.com40
object should have length (7)
Duck typing lets you pass objects that have the same structure, but no common supertypes.
public final int length;
public int length();
public int getLength();
Array:
String:
Document:
www.devoxx.com41
View bounds and the can-be-treated-as relationship
LengthWrapper« trait »
TextArrayLengthWrapper StringLengthWrapper DocumentLengthWrapper
Array String Document
def length: Int
can be treated ascan be treated ascan be treated as
is a is a is a
www.devoxx.com42
string should have length (7)
Object can be any type that can be treated as a LengthWrapper
array should have length (7)
document should have length (7)
www.devoxx.com
length() - Method in class java.io.FileReturns the length of the file denoted by this abstract pathname.length - Variable in exception java.io.OptionalDataExceptionThe number of bytes of primitive data available to be read in the current buffer.length() - Method in class java.io.RandomAccessFileReturns the length of this file.length() - Method in interface java.lang.CharSequenceReturns the length of this character sequence.length() - Method in class java.lang.StringReturns the length of this string.length() - Method in class java.lang.StringBufferlength() - Method in class java.nio.CharBufferReturns the length of this character buffer.length() - Method in class java.nio.charset.CoderResultReturns the length of the erroneous input described by this object (optional operation).length() - Method in interface java.sql.BlobReturns the number of bytes in the BLOB value designated by this Blob object.length() - Method in interface java.sql.ClobRetrieves the number of characters in the CLOB value designated by this Clob object.length() - Method in class java.util.BitSeReturns the "logical size" of this BitSet: the index of the highest set bit in the BitSetplus one.length() - Method in class java.util.concurrent.atomic.AtomicIntegerArrayReturns the length of the array.length() - Method in class java.util.concurrent.atomic.AtomicLongArrayReturns the length of the array.length() - Method in class java.util.concurrent.atomic.AtomicReferenceArrayReturns the length of the array.length() - Method in class javax.imageio.stream.FileCacheImageOutputStreamlength() - Method in class javax.swing.text.GapContentReturns the length of the content.length() - Method in class javax.swing.text.StringContentReturns the length of the content.length() - Method in class org.omg.CORBA.TypeCodeReturns the number of elements in the type described by this TypeCode object.length() - Method in class javax.imageio.stream.FileImageInputStreamReturns the length of the underlying file, or -1 if it is unknown.length() - Method in class javax.imageio.stream.FileImageOutputStreamlength() - Method in interface javax.imageio.stream.ImageInputStreamReturns the total length of the stream, if known.length() - Method in class javax.imageio.stream.ImageInputStreamImplReturns -1L to indicate that the stream has unknown length.length() - Method in class javax.imageio.stream.MemoryCacheImageOutputStreamlength - Variable in class javax.sound.midi.MidiMessageThe number of bytes in the MIDI message, including the status byte and any data bytes.
length() - Method in class javax.sql.rowset.serial.SerialBlobRetrieves the number of bytes in this SerialBlob object's array of bytes.length() - Method in class javax.sql.rowset.serial.SerialClobRetrieves the number of characters in this SerialClob object's array of characters.length() - Method in interface javax.swing.text.AbstractDocument.ContentCurrent length of the sequence of character content.length() - Method in class javax.swing.text.GapContentReturns the length of the content.length() - Method in class javax.swing.text.StringContentReturns the length of the content.length() - Method in class org.omg.CORBA.TypeCodeReturns the number of elements in the type described by this TypeCode object.getLength() - Method in class java.net.DatagramPacketReturns the length of the data to be sent or the length of the data received.getLength() - Method in class java.text.BidiReturn the length of text in the line.getLength() - Method in class javax.imageio.metadata.IIOMetadataNodegetLength() - Method in class javax.imageio.stream.IIOByteBufferReturns the length of the data of interest within the byte array returned by getData.getLength() - Method in class javax.sound.midi.MidiMessageObtains the total length of the MIDI message in bytes.getLength() - Method in interface javax.swing.event.DocumentEventReturns the length of the change.getLength() - Method in class javax.swing.text.AbstractDocument.DefaultDocumentEventReturns the length of the change.getLength() - Method in class javax.swing.text.AbstractDocumentReturns the length of the data.getLength() - Method in class javax.swing.text.DefaultStyledDocument.ElementSpecGets the length.getLength() - Method in interface javax.swing.text.DocumentReturns number of characters of content currently in the document.getLength() - Method in interface org.w3c.dom.CharacterDataThe number of 16-bit units that are available through data and the substringData method below.getLength() - Method in interface org.w3c.dom.DOMImplementationListThe number of DOMImplementations in the list.getLength() - Method in interface org.w3c.dom.DOMStringListThe number of DOMStrings in the list.getLength() - Method in interface org.w3c.dom.NamedNodeMapThe number of nodes in this map.getLength() - Method in interface org.w3c.dom.NameListThe number of pairs (name and namespaceURI) in the list.getLength() - Method in interface org.w3c.dom.NodeListThe number of nodes in the list.getLength() - Method in interface org.xml.sax.AttributesReturn the number of attributes in the list.getLength() - Method in class org.xml.sax.helpers.AttributeListImpl
www.devoxx.com44
Structural types in Scala
LengthWrapper« trait »
TextLengthFieldWrapper LengthMethodWrapper GetLengthMethodWrapper
def getLength(): Int
def length: Int
can be treated ascan be treated ascan be treated as
def length(): Int val length: Int
is a is a is a
www.devoxx.com45
string should have length (7)array should have length (7)document should have length (7)file should have length (7)blob should have length (7)atomicIntegerArray should have length (7)gapContent should have length (7)midiMessage should have length (7)datagramPacket should have length (7)iioByteBuffer should have length (7)documentEvent should have length (7)characterData should have length (7)nodeList should have length (7)attributes should have length (7)yourNewClass should have length (7)
Object can be any type that can be treated as a LengthWrapper
www.devoxx.com
DEMO
testing length
optional type systems
www.devoxx.com
More concise; fewer type annotations
Can effectively add new methods to existing classes
Can pass objects that share no common supertype to a method, which treats them uniformly
47
deterministic refactoring
fewer tests needed
documentation
code completion
performance, on JVM
Summary: Scala decreases the cost and increases the benefit of static typing.
www.devoxx.com
Programming in Scala is available in the Devoxx bookstore.
top related