Scala Learning (1)

Source: Internet
Author: User
Tags traits uppercase character

I. Scala conclusion

Scala helps you manage complexity by increasing the Abstraction Level of the interfaces you design and use. For example, if you have a string variable name, you want to determine whether the string contains an uppercase character.

Val namehasuppercase = Name. exists (_. isuppercase)

The Java code regards the string as a low-level entity that step by character in a loop. Scala code treats the same string as usableConclusion:PredicateThe character high-level sequence to query. Obviously scala code is shorter and-for well-trained eyes-easier to understand than Java code. Therefore, scala code is greatly reduced in the overall complexity budget. It also gives you fewer chances to make mistakes.

Conclusion: _. isuppercase is an example of functional text in Scala. [1] It describes a function with a character parameter (represented by an underline) and tests whether it is an uppercase letter. [2]

[1] function text with a return type of Boolean is called an argument.

[2] This approach of using underscores as parameter placeholders is described in Section 8.5.

Ii. Scala Variables

Scala has two variables: Val and var.

Val is similar to the final variable in Java. Once initialized, Val can no longer be assigned a value.

In contrast, VaR is like a non-final variable in Java. VaR can be assigned multiple times in its lifecycle.

Iii. Functions

Now that you have used Scala variables, you may want to write some functions. The following is the practice in scala:

Scala> def max (X: int, Y: INT): Int = {

If (x> Y) x

Else y

}

MAX: (INT, INT) int

Function Definition starts with Def. Function name. In this example, It is Max, followed by a list of parameters separated by colons in parentheses. Each function parameter must be followed by a type Annotation with the prefix colon, because the scala Compiler (and interpreter, but we will only talk about the compiler later) cannot deduce the function parameter type. In this example, the function named Max has two parameters, X and Y, both of which are of the int type. After the brackets in the max parameter list, you will see another ": int" type annotation. This defines the maxcompute FunctionResult type:Result type. [1] What follows the function result type is an equal sign and a pair of braces containing the function body. In this example, there is only one if expression in the function body. If X or Y is selected, the result of the Max function is used. As demonstrated here, Scala's if expression can generate a value like Java's ternary operator. For example, the scala expression "If (x> Y) x else y" is different from the "(x> Y)" in Java )? X: Y "is very similar. The equal sign before the function body prompts us that in the world of functional programming, the function defines an expression that can generate values. The basic structure of the function is shown in figure 2.1.

Illustration 2.1 Basic Components of scala Functions

Sometimes the scala compiler requires you to define the function result type. For example, if a function is recursive, [2] You must explicitly define the function result type. However, in the max example, you can infer the result type by the compiler without writing the result type. [3] Similarly, if a function is composed of only one sentence, you can choose not to write braces. In this way, you can write the max function as follows:

Scala> def max2 (X: int, Y: INT) = If (x> Y) x else y

[1] in Java, the type of the value returned from the method is called the return type. In Scala, the same concept is calledResult type.

[2] If a method calls itself, it is called recursion.

[3] Despite this, even if the compiler does not need it, it is often a good idea to explicitly describe the function result type. This type annotation can make the code easier to read, because the reader does not need to study the function body and then guess the result type.

There are also function definitions that do not contain parameters or return useful results:

Scala> def greet () = println ("Hello, world! ")

Greet: () Unit

When you define the GREET () function, the interpreter will respond to a greet: () unit. "Greet" is of course the function name. The blank brackets indicate that the function does not contain parameters.Unit is the result type of greet. The result type of unit indicates that the function does not return useful values. Scala's unit type is similar to Java's void type. In fact, every method in Java that returns void is mapped to the method that returns unit in Scala.. Therefore, the result type is unit and only runs for their side effects. In the GREET () example, the side effect is to print a polite word on the standard output.

Next, you will put scala code in a file and execute it as a script. If you want to leave the interpreter, enter quit or Q.

Scala>: Quit

$

Iv. Function text

var i = 0while (i < args.length) {  println(args(i))  i += 1}

Note that the boolean expressions of while or if must be placed in brackets like Scala and Java. (In other words, it cannot be written in Scala like in ruby: If I <10. In Scala, it must be written as if (I <10 ).) Another point similar to Java is that if the code block has only one sentence, braces are optional.

One of the main features of functional language is that functions are the first type of structure, which is absolutely true in Scala. For example, another (more concise) method for printing each command line parameter is:

Args. foreach (ARG => println (ARG ))

In this line of code, you call the foreach Method on ARGs and pass it into the function. In this example,You passed in the function text with a parameter named Arg:Function literal. The function body is println (ARG ). If you input the above Code to the new file Pa. Scala and run the following command:

$ Scala Pa. Scala concise is nice

You will see:

Concise

Is

Nice

In parser, the scala interpreter inferred that the ARG type is string, because string is the element type of the array you call foreach. You can add the type name if you like it to be more explicit, but in this case, you need to wrap the parameter section in brackets (in short, this is the normal syntax form ):

Args. foreach (Arg: string) => println (ARG ))

The result of running this script is the same as that of the previous one.

If you prefer a concise style instead of an explicit style, you can fully appreciate the advantages of scala.If the function text is composed of a sentence with a parameter, you do not need to explicitly name or specify the Parameter. [1] the following code is also valid:

Args. foreach (println)

All in all, the syntax of the function text is the name parameter list in brackets, the right arrow, and then the function body. The syntax is shown in Figure 2.2.

Illustration 2.2 Scala function text syntax

Now, you may want to know where the for loop that you trust in a script language such as Java or C goes. In order to guide you to the functional direction, scala has only one directive for (calledExpression:Expression. At present, you still don't see all their power and expressions until you read (or take a look at it first) section 7.3. We just want to show you here. Create a new file forargs. Scala and enter the following code:

For (ARG <-ARGs)

Println (ARG)

The parentheses after "for" in this expression include Arg <-args. [2] <-the right side is the familiar ARGs array. <-The left side is "Arg" and the Val name (not var ). (Because it is always Val, you only need to write Arg. Do not write it as Val Arg .) Although Arg may feel like var, because it will get a new value in each enumeration, it is true that Val: Arg cannot be re-assigned in the function body of the for expression.Instead, for each element in the ARGs array, a new Arg Val will be created and initialized as the element value, and then the for function body will be executed.

If you execute the forargs. Scala script:

$ Scala forargs. Scala for ARG in ARGs

You can see:

For

ARG

In

ARGs

[1] This short form is calledPartial application functions:Partially applied Function, Which is described in section 8.6.

[2] You can think of the <-symbol as "in it ".If you want to read for (ARG <-ARGs), read "for ARG in ARGs ".

When you use parentheses outside one or more values or variables, scala converts them to a method call named apply.. Therefore, greetstrings (I) is converted to greetstrings. Apply (I ). Therefore, elements accessing arrays in Scala are just the same method calls as others. This principle is not limited to Arrays: any application to some objects with parameters in parentheses will be converted to calls to the apply method. Of course, the premise is that this type actually defines the apply method. Therefore, this is not a special case, but a general rule.

When a value is assigned to a variable with parentheses and includes one or more parameters,The compiler converts it to a call to the update method for objects with parameters and equal signs in parentheses.. For example,

Greetstrings (0) = "hello"

Will be converted

Greetstrings. Update (0, "hello ")

Therefore, the following scala code is consistent with the Code semantics in Code 3.1:

Val greetstrings = new array [String] (3)

Greetstrings. Update (0, "hello ")

Greetstrings. Update (1 ,",")

Greetstrings. Update (2, "World! \ N ")

For (I <-0.to( 2 ))

Print (greetstrings. Apply (I ))

5. Use tuple, set or map

Another useful container object isTuples:Tuple. Like a list, tuples are also immutable, but unlike a list, tuples can contain different types of elements. The list should look like list [int] or list [String]. tuples can have both int and string. Tuples are useful. For example, if you need to return multiple objects in a method. In Java, you will often create a JavaBean class to hold multiple return values. In Scala, you can simply return a tuple. In addition, this is indeed simple: to instantiate a new Meta Group containing some objects, you just need to put these objects in brackets and separate them with commas. Once you have instantiated A tuples, you can access them with dots, underscores, and a 1-based element index. Code 3.4 shows an example:

Val pair = (99, "luftballons ")

Println (pair. _ 1)

Println (pair. _ 2)

Code 3.4 creates and uses tuples

In the first line of code 3.4, you have created a tuples. The first element of the tuples is an int with The 99 value, and the second is a string with the "luftballons" value. Scala deduce that the type of the tuples is tuple2 [int, string] and assigns it to the variable pair. In the second line, you access the _ 1 field to output the first element, 99. The "." In the second line is no different from the points you use to access fields or call methods. In this example, you are accessing a field named _ 1. If you execute this script, you can see:

99

Luftballons

The actual type of a tuple depends on the number of elements it contains and the type of these elements. Therefore, the type of (99, "luftballons") is tuple2 [int, string]. ('U', 'R', 'the', 1, 4, "me") is tuple6 [char, Char, String, Int, Int, string]. [1]

Elements accessing tuples

You may want to know why you cannot access tuples as you access elements in the list, just like pair (0 ). That is because the apply method of list always returns the same type, but the types in the tuples may be different. _ 1 can have a result type, and _ 2 is another one, and so on. These _ n numbers are based on 1 rather than 0, because for other languages that have static type tuples, such as Haskell and ML, they are traditionally set from 1.

[1] Although theoretically you can create tuples of any length, the scala library currently only supports tupe22.

Val romannumeral = map (

1-> "I", 2-> "II", 3-> "III", 4-> "IV", 5-> "V"

)

Println (romannumeral (4 ))

6. Learning and Recognizing Functional styles

As mentioned in chapter 1st, scala allows you to useDirectiveStyle programming, but you are encouraged to adopt a moreFunction Type. If you are switching from the script background to Scala-for example, if you are a Java programmer-then learning Scala is the main challenge you may face.Understand how to use functional style Programming. We understand that this kind of change will be very difficult, and in this book we will do everything we can to guide you in this regard. However, this also requires some work in this area. We encourage you to work hard. If you come from the script background, we believe that learning functional programming will not only make you a better Scala programmer, in addition, it can expand your horizons and make you a programmer of the general sense.

The first step on the way to a more functional style is to identify the differences between the two styles in code. One of the clues is,If the Code contains any var variable, it is probably the script style..If the Code does not have VaR at all -- that is, it only contains Val -- it is probably a functional style. Therefore, one way to push to the functional style is to try not to use any var programming..

If you come from a directive background, such as Java, C ++, or C #, you may think that VaR is an orthodox variable, and Val is a special type of variable. On the contrary, if you are from a functional background, such as Haskell, ocamel, or Erlang, you may think that Val is an orthodox variable, and VaR has a vulgar lineage. In Scala, Val and VaR are just two different tools in your toolbox. They are all very useful, and none of them are born demons. Scala encourages you to learn Val, but it does not blame you for choosing the most effective tool for your given job. Although you may agree with this balance philosophy, you may still find it challenging to understand how to remove var from your code for the first time.

Consider the example of the while loop from Chapter 1 below. It uses VaR and therefore belongs to the directive style:

def printArgs(args: Array[String]): Unit = {var i = 0while (i < args.length) {println(args(i))i += 1}}

You can remove VaR to make the code more functional, such:

Def printargs (ARGs: array [String]): unit = {for (ARG <-ARGs) println (ARG)} Or: def printargs (ARGs: array [String]): unit = {args. foreach (println )}

This example demonstrates the benefit of reducing the use of var. After reconstruction (more functional), the code is simpler, clearer, and fewer likely to make mistakes than the original (more directive) code.Scala encourages functional style because it helps you write code that is easier to understand and make mistakes.

Of course, you can go further. The reconstructed printargs method is notPureFunction, because it has side effects-in this example, the side effect is printed to the standard output stream. The result type is unit. If a function does not return any useful values, that is, the result type is unit, the only way that function can make the world change is through some side effects. The more functional method should be to define the method for formatting the ARG to be printed, but only the formatted strings will be returned, as shown in code 3.9:

Def formatargs (ARGs: array [String]) = args. mkstring ("\ n ")

Code 3.9 has no side effects or var Functions

Now is the real functional style: no side effects or VaR are visible. The mkstring method called on any enumerated set types (including arrays, lists, sets, and ing) returns a string consisting of the results produced by calling tostring for each array element to pass in the string interval. Therefore, if ARGs contains three elements, "zero", "one", and "two", formatargs returns "zero \ none \ ntwo ". Of course, this function does not actually print the output like the printargs method, but it can be simply passed to println for implementation:

Println (formatargs (ARGs ))

Every useful program may have some form of side effects, because otherwise it is impossible to provide any value to the outside world. Preference for methods without side effects can encourage you to design programs with minimal side effects code. One of the advantages of this approach is that it can help make your program easier to test. For example, to test any of the three printargs methods provided earlier in this section, you will need to redefine println, capture the output passed to it, and be sure this is what you want. On the contrary, you can test formatargs by checking the results:

Val res = formatargs (Array ("zero", "one", "two "))

Assert (RES = "zero \ none \ ntwo ")

Scala's assert method checks the passed Boolean and if it is false, an assertionerror is thrown. If the input Boolean is true, assert only returns it quietly. You will learn more about assertions and testing in Chapter 2.

Even so, keep in mind that neither var nor side effects are inherently evil. Scala is not a pure functional language that forces you to compile anything in a functional style. It is a mixed language of commands and functions. In some cases, you may find that the directive style is more suitable for your problems. At this time, you should not hesitate to use it. However, to help you learn how to avoid using VAR programming, Chapter 7th shows you many special code examples with VAR and how to convert these VaR values to Val.

An important feature of method parameters in Scala is that they are all Val, Not var. [1] If you want to assign a value to a parameter in the method, the result is a compilation failure:

Def add (B: byte): unit = {

B + = 1 // compilation failed, because B is Val

Sum + = B

}

[1] The reason for the parameter Val is that Val is easier to clarify. You don't need to read more code to determine whether Val is assigned again, but VaR is not.

If no explicit Return Statement is found,The Scala method returns the last calculated value of the method..

If a method only calculates a single result expression, you can remove the braces.. If the result expression is short, you can even put it in the same row of def. After this change, the checksumaccumulator class looks like this:

class ChecksumAccumulator {private var sum = 0def add(b: Byte): Unit = sum += bdef checksum(): Int = ~(sum & 0xFF) + 1}

The result type of a method like the add method of checksumaccumulator is unit. The purpose of execution is its side effects. We usually define a side effect as changing the status or executing an I/O activity somewhere outside the method. For example, in the Add example, sum is assigned a value again. Another way to express this method is to remove the result type and equal sign and put the method body in braces. In this form, the method looks likeProcess:Procedure, A method that is executed only for side effects. This style is demonstrated in the add method of code 4.1:

// File checksumaccumulator. Scala

Class checksumaccumulator {

Private var sum = 0

Def add (B: byte) {sum + = B}

Def checksum (): Int = ~ (Sum & 0xff) + 1

}

Final Version of code 4.1 class checksumaccumulator

What is confusing?When you remove the equal sign before the method body, the result type is destined to be unit.. No matter what the method body containsScala compiler can convert any type to Unit. For example, if the final result of a method is string but the result type of the method is declared as unit, the string will be converted to unit and its value will be lost. The following is an example:

Scala> def F (): unit = "this string gets lost"

F: () Unit

In this example, string is converted to unit because unit is the result type declared by function f.The Scala compiler defines a process-style method, that is, a method with braces but no equals signs, essentially as a method that explicitly defines the result type as unit.. For example:

Scala> def g () {"this string gets lost too "}

G: () Unit

Therefore,If you want to return a non-unit valueWhen you forget the equal sign, the confusion arises. So to get the expected results,You need to insert the equal sign:

Scala> def H () = {"this string gets returned! "}

H: () Java. Lang. String

Scala> H

Res0: Java. Lang. String = This string gets returned!

VII,Semicolon Inference

In Scala, the semicolon at the end of a statement is usually optional.. You can enter one statement if you want, but you cannot write only one statement in a row. On the other hand, if multiple statements are written in one row, the semicolon is required:

Val S = "hello"; println (s)

If you want to enter a statement that spans multiple rows, most of the time you only need to input the statement, scala will separate the statement in the correct position. For example, the following code is considered to be a statement that spans four rows:

If (x <2)

Println ("too small ")

Else

Println ("OK ")

However, occasionally Scala may not split the sentence into two parts as you wish:

X

+ Y

This statement is divided into two statements X and + Y. If you want to use it as a statement X + Y, you can wrap it in brackets:

(X

+ Y)

Alternatively, you can put + at the end of the row. For this reason, when you concatenate an infix operator similar to +, placing the operator at the end of the line rather than the line header is a common Scala style:

X +

Y +

Z

8,SingletonObject

As mentioned in chapter 1st, one of the more object-oriented aspects of scala than Java is that Scala does not have static members. The alternative is that Scala hasSingleton object:Singleton object. In addition to replacing the class keyword with the object keyword, the definition of a singleton object looks like a class definition. Code 4.2 shows an example:

// File checksumaccumulator. scalaimport Scala. collection. mutable. mapObject checksumaccumulator {private Val cache = map [String, int] () def calculate (S: string): Int = If (cache. contains (s) cache (s) else {Val ACC = new checksumaccumulatorfor (C <-S) ACC. add (C. tobyte) Val cs = ACC. checksum () cache + = (S-> CS) CS} code 4.2 class checksumaccumulator companion object

The singleton object in the table is called checksumaccumulator and has the same name as the class in the previous example.When a singleton object shares the same name with a class, it is called the companion object of the class:Companion object. You must define the class and its associated objects in the same source file. Class is called the companion class of this singleton object:Companion class. Class and its associated objects can access each other's private members.

The checksumaccumulator singleton object has a method, calculate, used to calculate the character checksum in the string parameter. It also has a private field, cache, a variable ing of the checksum calculated before caching. [1] the first line of the method, "If (Cache. Contains (s)", checks the cache to see if the passed string already exists as a key in the ing. If yes, only the ing value "cache (s)" is returned )". Otherwise, run the else clause to calculate the checksum. The first line of the else clause defines a Val called ACC and initializes it with the new checksumaccumulator instance. [2] The next line is a for expression that loops every character in the input string once and calls tobyte to convert the character to byte, then, it is passed to the Add method of the checksumaccumulator instance referred to by ACC. After the for expression is complete, the next line of the method calls checksum on ACC to obtain the checksum of the input string, and stores the Val called CS. Next line, "Cache + = (S-> CS)", the incoming string key maps to the integer verification value and value, and adds this key-value pair to the cache ing. The last expression of the method, "Cs", ensures the checksum and the result of this method..

If you are a Java programmer, one way to consider a singleton object is to treat it as a home of any static methods you may have written in Java. You can use similar syntax to call a method on a singleton object: singleton object name, vertex, and method name. For example, you can call the calculate method of the checksumaccumulator singleton object as follows:

Checksumaccumulator. Calculate ("every value is an object .")

However, the singleton object is not just a static site. It is also the first class object. Therefore, you can regard the name of a singleton object as a "name tag" on the object ":

Defining a singleton object is not a definition type (in Scala's abstract hierarchy ). If you only define the checksumaccumulator object, you cannot create a variable of the checksumaccumulator type. In this case, the checksumaccumulator type is defined by the companion class of the singleton object. However, the singleton object extends the superclass and can be mixed into the traits. Because each singleton object is a super-class instance and contains characteristics, you can use these types to call its methods and use these types of variables to refer to it, and pass it to the methods that require these types. In Chapter 12th, we will show examples of Singleton objects that inherit from classes and traits.

One difference between a class and a singleton object is that a singleton object does not contain parameters, while a class can. Because you cannot use the new keyword to instantiate a singleton object, you have no chance to pass it parameters. Each singleton object is pointed to by a static variable.Virtual Libraries:Synthetic classSo they have the same initialization syntax as Java static classes. [3] in particular, the singleton object will be initialized when it is accessed for the first time.

A singleton object that does not share a name with the associated class is calledIsolated object:Standalone object. You may use it for many reasons, including collecting related functional methods or defining the entry point of a Scala application. This example is described in the next section.

[1] Here we use a cache example to describe a singleton object with a domain. The cache is optimized by memory-for-computing time. In general, this example can be used only when a performance problem can be solved by the cache, and weak map, such as Scala, should be used. collection. weakhashmap of jcl, so that if the memory is scarce, the entries in the cache will be reclaimed by the garbage collection mechanism.

[2] Because the new keyword is only used to instantiate a class, the new object created here is an instance of the checksumaccumulator class, rather than a singleton object with the same name.

[3] The Name Of The imaginary class is the object name plus a dollar sign. Therefore, the virtual class of the single-instance object checksumaccumulator is checksumaccumulator $.

IX,ApplicationCharacteristics

Scala provides a feature, scala. application, which can save some of your finger input work. Although we haven't provided you with everything you need to know how it works, we still think you might want to know it. Code 4.4 shows an example:

import ChecksumAccumulator.calculateobject FallWinterSpringSummer extends Application {for (season <- List("fall", "winter", "spring"))println(season +": "+ calculate(season))}

Code 4.4 use application characteristics

To use this feature, first write "extends application" after your singleton object name ".Instead, you can place the code that you want to put in the main method directly between the braces of the singleton object.. That's simple. Then you can compile and run the program as you would for other programs.

This method works because the property application declares the main method with the appropriate signature and is inherited from your singleton object so that it can be used as a Scala program. The code between braces is collected intoMaster constructor:Primary ConstructorAnd executed when the class is initialized. You don't have to worry about anything you don't understand. The subsequent sections will explain these issues, which can be left blank for the moment.

Inheriting from an application is shorter than writing an explicit main method, but it also has some disadvantages.First, if you want to access the command line parameter, you cannot use it because the ARGs array is not accessible.. For example, because the summer program uses the command line parameter, it must have an explicit main method, as shown in code 4.3.Second, because of the limitations in some JVM thread models, if your program is multi-threaded, you need an explicit main method.. Finally, some JVM implementations do not optimize the initialization code of objects executed by application characteristics. Therefore, you can inherit the application characteristics only when your program is relatively simple and single-threaded.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.