zoukankan      html  css  js  c++  java
  • Scala入门指南与建议

    最近在学习使用Scala语言做项目,感觉这门语言实在是太优美了!作为一个本科数学、研究生机器学习专业的混合人才(哈哈),这门语言真的是满足了普通计算机编程(告诉计算机怎么做)和函数式编程(告诉计算机做什么)的所有幻想。学了半个多月,根本停不下来!先来做个总结:

    1. 语法简洁,往往比Java少至少一半的代码量。比如:
      • 支持自动类型判断,可以省去很多类型标志。 e.g.  val x = 2
      • 用伴生对象来生成类,省去new的麻烦。e.g. val cat = Cat("Hello Ketty")
      • 不用return,直接把一个块(可以使if...else...块,for循环块等)的值返回。例如一行代码定义函数:def add(x: Int, y: Int): Int = x + y
      • 用()来统一函数的参数传递与带参类的构造。对类来说,这种写法其实是语法糖,因为中间有自动的转换机制,使得简洁的代码和底层实现可以分离。
      • 程序易读。对比C/C++、Python、Java,Scala是最符合人类理解的程序语言。
    2. 有几乎完全的函数式风格支持。
      • 函数和值一样,是第一等公民。函数也是值,值也可以作为函数。
      • 支持高阶函数、Curry化、lambda运算等函数运算概念。
      • 函数式风格要求函数尽量无副作用,这样一方面适合做单元测试来验证程序的正确性,另外很适合做并行计算!
    3. 可以满足大多数OOP编程需求。
      • 这里就不展开了。
    4. Scala兼具科学计算语言(matlab、R、Python等)的易读性与静态语言(C/C++、Java等)的高效率。

    正是由于以上优点,我觉得Scala很有潜力成为下一门普及的编程语言。

    另外,关于Scala学习曲线,我的建议是:

    1. 从网上各种博客大概了解Scala的特性,包括上面提到的几条。
    2. 看书:
      • 《Programming in Scala》和《Scala for the Impatient》交替看。前一本是Scala语言创建者写的,非常通俗易懂,包含了Scala的大多数“是什么”和“为什么”;后一本则是总结性的,把Scala的大多少“是什么”告诉你。
      • 《Scala in Depth》适合中等水平的Scala程序员阅读。(计划下一步看完)
    3. 做项目 / 开发程序。

    最后,附上《Scala for the Impatient》(中文版《快学Scala》)的所有key notes 以及我做的部分课后题参考答案地址。如果有需要相关电子书的,可以给我发email。


    《Scala for the Impatient》key notes

    Chapter 1. The Basics
    • Using the Scala interpreter
    • Defining variables with val and var
    • Numeric types
    • Using operators and functions
    • Navigating Scaladoc
     
    Chapter 2. Control Structures and Functions
    • An if expression has a value
    • A block has a value — the value of its last expression
    • The Scala for loop is like an "enhanced" Java for loop
    • Semicolons are (mostly) optional
    • The Void type is Unit
    • Avoid using return in a function
    • Beware of missing = in a function definition
    • Exceptions work just like in Java or C++, but you use a "pattern matching" syntax for catch 
    • Scala has no checked exceptions
     
    Chapter 3. Working with Arrays
    • Use an Array if the length is fixed, and an ArrayBuffer if the length can vary
    • Don’t use new when supplying initial values
    • Use () to access elements
    • Use for (elem <- arr) to traverse the elements
    • Use for (elem <- arr if …) … yield … to transform into a new array
    • Scala and Java arrays are interoperable; with ArrayBuffer, use scala.collection.JavaConversions
     
    Chapter 4. Maps and Tuples
    • Scala has a pleasant syntax for creating, querying, and traversing maps
    • You need to choose between mutable and immutable maps
    • By default, you get a hash map, but you can also get a tree map
    • You can easily convert between Scala and Java maps
    • Tuples are useful for aggregating values
     
    Chapter 5. Classes
    • Fields in classes automatically come with getters and setters
    • You can replace a field with a custom getter / setter without changing the client of a class — that is the "uniform access principle"
    • Use the @BeanProperty annotation to generate the JavaBeans getXxx / setXxx methods
    • Every class has a primary constructor that is "interwoven" with the class definition. Its parameters turn into the fields of the class. The primary constructor excuses all statements in the body of the class
    • Auxiliary constructors are optional. That are called this.
     
    Chapter 6. Objects
    • Use Objects for singletons and utility methods
    • A class can have a companion object with the same name.
    • Objects can extend classes or traits
    • The apply method of an object is usually used for constructing new instance of the companion class
    • To avoid the main method, use an object that extends that App trait
    • You can implement enumerations by extending the Enumeration object
     
    Chapter 7. Packages and imports
    • Packages nest just like inner classes
    • Package paths are not absolute
    • A chain x.y.z in a package clause leaves the intermediate packages x and x.y invisible
    • Package statements without braces at the top of the file extend to the entire file
    • A package object can hold functions and variables
    • Import statements can import packages, classes, and objects
    • Import statements can be anywhere
    • Import statements can rename and hide menbers
    • java.lang, scala, and Predef are always imported
     
    Chapter 8. Inheritance
    • The extends and final keywords are as in Java.
    • You must use override when you override a method
    • Only the primary constructors can all the primary superclass constructor
    • You can override fields
     
    Chapter 9. Files and Regular Expressions
    • Source.fromFile(…).getLines.toArray yields all lines of a file
    • Source.fromFile(…).mkString yields the file contents as a string
    • To convert a string into a number, use the toInt or toDouble method
    • Use the Java PrintWriter to write text files
    • "regex".r is a Regex object
    • Use """…""" if your regular expression contains backslashes or quotes
    • If a regex pattern has groups, you can extract their contents using the syntax for (regex(var_1,…,var_n) <- string )
     
    Chapter 10. Traits
    • A class can implement any number of traits
    • Traits can require that implementing classes have certain fields, methods, or superclasses
    • Unlike Java Interface, a Scala trait can provide implementations of methods and fields
    • When you layer multiple traits, the order matters — the trait whose methods execute first goes to the back
     
    Chapter 11. Operators
    • Identifiers contain either alphanumeric or operator characters
    • Unary and binary operators are method calls
    • Operator precedence depends on the first character, associativity on the last
    • The apply and update methods are called when evaluating expr(args)
    • Extractors extract tuples or sequences of values from an input
     
    Chapter 12. Higher-Order Functions
    • Functions are "first-class citizens" in Scala, just like numbers
    • You can create anonymous functions, usually to give them to other functions
    • A function argument specifies behavior that should be executed later
    • Many collection methods take function parameters, applying a function to the values of the collections
    • There are syntax shortcuts that allow you to express function parameters in a way that is short and easy to read
    • You can create functions that operate on the blocks of code and look much like the build-in control statement
     
    Chapter 13. Collections
    • All collections extend the Iterable trait
    • The three major categories of collections are sequences, sets, and maps.
    • Scala has mutable and immutable versions of most collections
    • A Scala list is either empty, or it has a head and a tail which is again a list
    • Sets are unordered collections
    • Use a LinkedHashSet to retain the insertion order or a SortedSet to iterate in sorted order
    • + adds an elements to an unordered collection; +: and :+ prepend or append to a sequence; ++ concatenates two collections; - and -- remove elements
    • The Iterable and Seq traits have dozens of useful methods for common operations. Check them out before writing tedious loops.
    • Mapping, folding, and zipping are useful techniques for applying a function or operation to the elements of a collection
     
    Chapter 14. Pattern Matching and Case Classes
    • The match expression is a better switch, without fall-through
    • If no pattern matches, a MatchError is thrown. Use the case _ pattern to avoid that
    • A pattern can include an arbitrary condition, called a guard
    • You can match on the type of an expression; prefer this over isInstanceOf / asInstanceOf
    • You can match patterns of arrays, tuples, and case classes, and bind parts of the pattern to variables
    • In a for expression, non matches are silently skipped
    • A case class is a class for which the compiler automatically produce the methods that are needed for pattern matching
    • The common superclass in a case class hierarchy should be sealed
    • Use the Option type for values that may or may not be present — it is safer than using null
     
    Chapter 15. Annotations
    • You can annotate classes, methods, fields, local variables, parameters, expressions, type parameters and types.
    • With expressions and types, the annotation follows the annotated item
    • Annotation have the form @Annotation, @Annotation(value), or @Annotation(name1= value1, …)
    • @volatile, @transient, @strictfp, and @native generate the equivalent Java modifiers
    • Use @throws to generate Java-compatible throws specifications
    • The @tailrec annotation lets you verify that a recursive function uses tail call optimization
    • The assert function takes advantage of the @elidable annotation. You can optionally remove assertions from your Scala program
    • Use the @deprecated annotation to mark deprecated features.
     
    Chapter 16. XML Processiong
    • XML literals <like> this </like> are of type NodeSeq
    • You can embed Scala code inside XML literals
    • The child property of a Node yield the child nodes
    • The attributes property of a Node yields a MetaData object containing the node attributes.
    • The and \ operators carry out XPath-Like matches
    • You can match mode patterns with XML literals in case clauses
    • Use the RuleTransformer with RewriteRule instance to transform descendants of a node
    • The XML object interfaces with Java XML methods for loading and saving
    • The ConstructingParser is an alternate parser that preserves comments and CDATA sections
     
    Chapter 17. Type parameters
    • Classes, traits, methods, and functions can have type parameters
    • Place the type parameters after the name, enclosed in square brackets
    • Type bounds have the form T <: UpperBound, T >: LowerBound, T <% ViewBound, T : ContextBound
    • You can restrict a method with a type constraint such as (implicit ev: T <: < UpperBound)
    • Use +T (covariance) to indicate that a generic type’s subtype relationship is in the same direction as the parameter T, or -T (contravariance) to indicate the reverse direction
    • Covariance is appropriate for parameters that denote outputs, such as elements in an immutable collection.
    • Contravariance is appropriate for parameters that denote inputs, such as function arguments.
     
    Chapter 18. Advanced types
    • Singleton types are useful for method chaining and methods with object parameters
    • A type projection includes inner class instances for all objects of an outer class.
    • A type alias gives a short name for a type.
    • Structural types are equivalent to "duck typing"
    • Existential types provide the formalism for wildcard parameters of generic types.
    • Use a self type declaration to indicate that a trait requires another type.
    • The "cake pattern" uses self types to implement a dependency injection mechanism
    • An abstract type must be made concrete in a subclass
    • A higher-kinded type has a type parameter that is itself a parameterized type.
     
    Chapter 19. Parsing
    • Alternatives, concatenation, options, and repetitions in a grammar turn into |, ~, opt, and rep in Scala combinator parsers.
    • With RegexParsers, literal strings and regular expressions match tokens.
    • Use ^^ to process parse results.
    • Use pattern matching in a function supplied to ^^ to take apart ~ result.
    • Use ~> and <~ to discard tokens that are no longer needed after matching.
    • The respell combinator handles the common case of repeated items with a seperator
    • A token-based parser is useful for paring languages with reserved words and operations. Be prepared to define your own lexer.
    • Parsers are functions that consume a reader and yield a parse result: success, failure, or error.
    • The Failure result provides the details for error reporting.
    • You may want to add failure clauses to your grammar to improve the quality of error message.
    • Thanks to operator symbols, implicit conversions, and pattern matching, the parser combinator library makes parser writing easy for anyone who understands context-free grammars. Even if you don’t feel the urge to write your own parsers, you may find this an interesting case study for an effective domain-specific language.
     
    Chapter 20. Actors
    • Extend the Actor class and provide an act method for each other.
    • To send a message to an actor, use actor ! message.
    • Message sending is asynchronous: "send and forget."
    • To receive messages, an actor calls receive or react, usually in a loop.
    • The argument to receive / react is a block of case clauses (technically, a partial function)
    • Actors should never share state. Always send data using messages.
    • Don’t invoke methods on actors. Communicating by sending messages.
    • Avoid synchronous messaging — that is, unlink sending a message and waiting for a reply.
    • Actors can share threads by using react instead of receive, provided the control flow of the message handler is simple.
    • It is OK to let actors crash, provided you have other actors that monitor their demise. Use linking to set up monitoring relationships.
     
    Chapter 21. Implicits
    • Implicit conversions are used to convert between types.
    • You must import implicit conversions so that they are in scope as single identifiers.
    • An implicit parameter list requests objects of a given type. They can be obtained from implicit objects that are defined as single identifiers in scope, or from the companion object of the desired type.
    • If an implicit parameter is a single-argument function, it is also used as an implicit conversion.
    • A context bound of a type parameter requires the existence of an implicit object of the given type.
    • If it is possible to locate an implicit object, this can serve as evidence that a type conversion is valid.
     
    Chapter 22. Delimited Continuations
    • A continuation lets you go back to a previous point in a program.
    • You can capture a continuation in a shift block.
    • A contination function extends until the end of the enclosing reset block.
    • A continuation is the "reset of the computation" from the expression containing the shift to the end of the enclosing reset, with the shift replaced by a "hole"
    • When you call a continuation with an argument, the "hole" is set to the argument.
    • Code containing shift expressions is rewritten in "continuation-passing stype", or CPS, up to the enclosing reset.
    • A method containing a shift without a reset must be annotated with a CPS annotation.
    • Continuation can be used to turn a recursive visit of a tree structure into an iteration.
    • Continuations can undo the "inversion of control" in a web or GUI application.

    部分《快学Scala》课后题答案(还在更新中):

    https://github.com/fengfu-chris/Scala-for-the-Impatient-Exercises

  • 相关阅读:
    Golang——面向对象
    Golang——排序算法
    python常用设计模式
    Golang基础——数据类型:指针
    Golang基础——数据类型:结构体
    Golang基础——数据类型:map
    css盒子模型
    css选择器以及样式优先级
    Android中finish()方法
    架构漫谈(二)认识概念是理解架构的基础
  • 原文地址:https://www.cnblogs.com/fengfu-chris/p/4763539.html
Copyright © 2011-2022 走看看