Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the core rules of Scala

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail how to understand the core rules of Scala. The content of the article is of high quality, so the editor will share it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.

Read Eval Print Loop (REPL)

REPL in Scala refers to the interactive command line mode entered by running scala.exe directly. In a broad sense, it also refers to those online programming tools.

Core rule 1: use REPL to familiarize yourself with the Scala language.

One advantage of Scala's REPL is the ability to give feedback on the internal representation of each line of code we enter. For example:

Scala > def add (a:Int, b:Int): Int = a + b

Add: (a: Int, b: Int) Int

We define a function to complete the addition of two numbers. What Scala echoes back to us can help us write code.

Expressions and statements

The difference between expressions and statements is that statements are used to execute, while expressions are used to evaluate. In the programmer's world, expressions are return values, and languages simply do not return values to execute programs.

Scala is an expression-oriented programming language. But not 100%, there are still control chunks in the Scala code. After all, we write programs to control various entities to serve us.

Core rule 2: use expressions instead of statements.

The main purpose of this rule is to help us simplify the code. As in the previous addition example, abuttb is an expression. Compared with the same implementation written in C language, simplicity is not good. There must be a lot of examples like this in the code.

Do not use Return

When we use expressions, we don't need Return. Because the expression itself is used to evaluate, we need to say explicitly what I'm going to return now. The Scala compiler automatically uses the return value of an expression as the return value of the function.

We should remember that a programming guideline is that the function returns in the same place. If we don't have Return statements now, like in Scala, is there a similar programming guide? Look at an example:

Object NoReturn extends scala.App {def createErrorMessage1 (errorCode: Int): String = {val result = errorCode match {case 1 = > "Network Failure" case 2 = > "I Failure" case 3 = > "Unknown Error"} return result} def createErrorMessage2 (errorCode: Int): String = {var result: String = null / / not val errorCode match {case 1 = > Result = "Network Failure" case 2 = > result = "I Failure O Failure" case _ = > result = "Unknown Error"} return result } def createErrorMessage3 (errorCode: Int): String = {errorCode match {case 1 = > "Network Failure" case 2 = > "case O Failure" case 3 = > "Unknown Error"}} println (createErrorMessage1 (1)) println (createErrorMessage2 (2)) println (createErrorMessage3 (3) println (1 match {case 1 = > "Network Failure" case 2 = > 3}) println (2 match {case 1 = > "Network Failure" case 2 = > 3})}

CreateErrorMessage2 should be the way we used to write it. Define a local variable, then match the errorCode, and assign it. CreateErrorMessage1 is recommended by Scala (though not succinct enough) and uses val instead of var to declare temporary variables. Val represents a value, which cannot be changed after assignment; var is a variable and can be assigned repeatedly. The result of createErrorMessage1 is followed by an expression. After the evaluation, the value is assigned directly. CreateErrorMessage3 is even more concise, almost in the form of *. The function returns an expression directly, without temporary objects.

Note: match case supports different types returned by each branch. This feature is very useful in functional programming.

Although Scala supports all 3 writing methods, one of them is recommended. Because it helps simplify the complexity of the code and increase the immutability of the program. Immutability means that during the execution of a program, all states (variables) are constant. Immutable code is easier to understand, debug, and maintain than mutable code.

The tendency of expression-oriented language and the use of immutable objects can reduce the number of mutable objects in programs.

Use immutable objects

Core rule 3: using immutable objects can significantly reduce runtime failures. When faced with variable and immutable choices, it is undoubtedly the safest to choose immutable objects.

Object equivalence

Scala provides # # and = = to determine whether an object is equivalent, which can act on AnyRef (reference) and AnyVal (value).

The hash and equal of the object should appear in pairs. Hash values are often used because of equivalence.

Import collection.immutable.HashMap class Point2 (var x: Int, var y: Int) extends Equals {def move (mx: Int) My: Int): Unit = {x = x + mx y = y + my} override def hashCode (): Int = y + (31cm x) def canEqual (that: Any): Boolean = that match {case p: Point2 = > true case _ = > false} override def equals (that: Any): Boolean = {def strictEquals (other: Point2) = this.x = = other.x & & this.y = = other.y That match {case a: AnyRef if this eq a = > true case p: Point2 = > (p canEqual this) & & strictEquals (p) case _ = > false}} object ObjecteEquality extends scala.App {val x = new Point2 (1) val y = new Point2 (1) val z = new Point2 (1) println (x = y) / false println (x = = z) / / trueval map = HashMap (x-> "HAI") Y-> "ZOMG") println (map (x)) / / HAI println (map (y)) / / ZOMG println (map (z)) / / HAI, if we remove hashCode, there will be an exception x.move (1Power1) / / println (map (x)) / / Exception in thread "main" java.util.NoSuchElementException: key not found: Point2@40 println (map.find (_. _ 1 = = x))}

Lines 3-22 define a Point2 class that inherits from Equals.

Trait Equals extends Any {def canEqual (that: Any): Boolean def equals (that: Any): Boolean}

Define your own move method and hashCode method. CanEqual is used to determine whether the equal method can be applied to an object, just to check whether the type matches. Equal contains an internal function strictEquals to determine whether the members of an object are equal. Equal first checks whether the same Point2 object is referenced, and if so, returns true directly. Otherwise, check whether the type matches, and if so, use strictEquals to determine whether the members of the object are equal.

Line 36: println (map (z)), whose correct execution depends on whether the hashCode is defined or not. Map calls key.## when it looks for the value of the specified key.

In line 38, because move changes the internal state of x, the new value calculated by hashCode is used as key to look in Map, and if you cannot find the corresponding value, a NoSuchElementException exception will be reported.

Line 40, quite peculiar. Look at the definition of find:

Trait IterableLike:

Override / * TraversableLike*/ def find (p: a = > Boolean): Option [A] = iterator.find (p)

Object Iterator:

Def find (p: a = > Boolean): Option [A] = {var res: Option [A] = None while (res.isEmpty & & hasNext) {val e = next () if (p (e)) res = Some (e)} res}

Passed on to find is a predicate. The iterator iterates through each element in the collection and passes that element as a parameter to predicate. All the parameters we pass to predicate here are a key-value pair [A _ Magi B]. _ is the parameter passed to predicate. _ 1 refers to the * elements in the key-value pair (actually the * elements in the tuple), that is, A, that is, the Point2 as key. It's easy to understand what this means now, which is the same element as the hashCode of x. The definition of _ 1 is located at:

Trait Product2:

/ * A projection of element 1 of this Product. * @ return A projection of element 1. * / def _ 1: T1

When we implement the equivalence judgment of an object, please follow:

If two objects are equal, they should have the same hashCode.

The hashCode of an object does not change during its life cycle.

If you send an object to another JVM, you should ensure that the equivalent judgment depends on the properties of the object that are available on both JVM. Mainly used for serialization.

If our object is immutable, then condition 2 above satisfies itself, which simplifies the equivalence judgment. In addition, immutability not only simplifies equivalence judgment, but also simplifies access to parallel data because there is no synchronous mutex.

Use None instead of null

The use of null has been criticized by everyone. Null forces people to add extra processing code. Scala uses Option to wrap null processing, so we no longer need to determine whether the variable is empty. We can think of Option as a general-purpose container, containing some object containers (Some), or empty containers (None). The container needs the type of object for the past two weeks.

Similarly, Scala also has an empty list Nil.

Core rule 4: use None instead of null

In Java, we often encounter null exceptions. If we learn to use Option correctly, we can avoid null exceptions.

Scala's Option concomitant object (companion object) contains a factory method that automatically converts Java's null to None:var x: Option [String] = Option (null). Equivalent to var x: Option [String] = Null.

A more advanced use of Scala is to treat it as a collection. This means that you can use map, flatMap, foreach, or even for expressions on Option.

Some advanced examples of using Null:

Class HttpSession class Connection object DriverManager {def getConnection (url: String, user: String, pw: String): Connection = {println ("getConnection") new Connection}} object AdvancedNull extends scala.App {/ / CREATE AN OBJECT OR RETURN A DEFAULT def getTemporaryDirectory (tmpArg: Option [String]): java.io.File = {tmpArg.map (name = > new java.io.File (name)) Filter (_ .isDirectory). GetOrElse (new java.io.File (System.getProperty ("java.io.tmpdir"))} / / EXECUTE BLOCK OF CODE IF VARIABLE IS INITIALIZED val username1: Option [String] = Option ("Sulliy") for (uname

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report