我已经和Scala一起工作了一段时间,并且用它编写了10,000多行程序,但我仍然对一些内部工作感到困惑.我已经熟悉Java,C和Lisp后从Python来到Scala,但即使如此,它也很慢,而且一个巨大的问题是我在尝试研究对象/类型的内部工作时经常遇到的令人沮丧的困难/类/等.与Python相比,使用Scala REPL.在Python中,您可以查看任何对象foo(类型,全局变量中的对象,内置函数等),foo以查看事物的评估结果,type(foo)显示其类型,dir(foo)告诉您可以调用它的方法,以及help(foo)获取内置文档.你甚至可以做一些事情,比如help("re")查找名为re(包含正则表达式对象和方法)的包的文档,即使没有与之关联的对象.
在Scala中,您可以尝试在线阅读文档,查看库中的源代码等,但对于您不知道在哪里甚至是什么的事情来说,这通常很难(而且经常是这样的)一大块咬掉,考虑到庞大的类型层次) -东西在不同的地方(包左右浮动scala,Predef各种隐式转换,像符号::是几乎不可能谷歌).REPL应该是直接探索的方式,但实际上,事情更加神秘.说我看过foo某个地方的引用,但我不知道它是什么.显然没有"使用REPL系统地调查Scala事物的指南",但以下是经过大量试验和错误后我拼凑起来的内容:
foo是一个值(可能包括存储在变量中的内容以及伴随对象和其他Scala object),您可以foo直接进行评估.这应该告诉你结果的类型和价值.有时结果很有帮助,有时候不是.foo是值,则可以使用它:type foo来获取其类型.(不一定具有启发性.)如果在函数调用中使用它,则可以获得返回值的类型,而无需调用函数.foo是值,则可以使用它foo.getClass来获取其类.(通常比以前更有启发性,但对象的类与其类型有何不同?)foo,你可以使用classOf[foo],虽然结果的含义并不明显.:javap foo用来反汇编一个类 - 它应该是最有用的类,但对我来说完全失败.使用失败的示例:javap:
scala> :javap List
Failed: Could not find class bytes for 'List'
Run Code Online (Sandbox Code Playgroud)
启发错误消息的示例:
scala> assert
<console>:8: error: ambiguous reference to overloaded definition, …Run Code Online (Sandbox Code Playgroud) 从2.10开始,-Xlint抱怨在包对象中定义的类.但为什么?在包对象中定义一个类应该完全等同于在具有相同名称的单独包中定义类,除了更方便.
在我看来,Scala中一个严重的设计缺陷是无法在文件的顶层放置除类类实体之外的任何东西(例如变量声明,函数定义).相反,您被迫将它们放入一个单独的"包对象"(通常在package.scala)中,与它们所属的其余代码分开并违反基本的编程规则,即概念上相关的代码应该是物理相关的同样.我没有看到任何理由为什么Scala在概念上不允许在较低级别允许的任何顶层级别,并且任何类非类似的东西都会自动放入包对象中,这样用户就不必担心它.
例如,在我的情况下,我有一个util包,并在其下我有一个号码的子包(util.io,util.text,util.time,util.os,util.math,util.distances,等等),该组的在语义上相关的函数,类,有时变量异质集合.我目前将所有各种函数,类等存储package object在目录中名为io.scala或等的文件text.scala中util.这很好用,因为函数和类可以混合的方式非常方便,例如我可以做类似的事情:
package object math {
// Coordinates on a sphere
case class SphereCoord(lat: Double, long: Double) { ... }
// great-circle distance between two points
def spheredist(a: SphereCoord, b: SphereCoord) = ...
// Area of rectangle running along latitude/longitude lines
def rectArea(topleft: SphereCoord, botright: SphereCoord) = ...
// ...
// ... …Run Code Online (Sandbox Code Playgroud) 我正在为博士研究编写代码并开始使用Scala.我经常要做文字处理.我已经习惯了Python,其'yield'语句对于在大型(通常是不规则结构化的)文本文件上实现复杂的迭代器非常有用.类似的结构存在于其他语言(例如C#)中,这是有充分理由的.
是的我知道之前有过这样的线索.但它们看起来像是黑客攻击(或至少解释得很糟糕)的解决方案,这些解决方案并不能很好地运作并且通常具有不明确的局限性.我想编写这样的代码:
import generator._
def yield_values(file:String) = {
generate {
for (x <- Source.fromFile(file).getLines()) {
# Scala is already using the 'yield' keyword.
give("something")
for (field <- ":".r.split(x)) {
if (field contains "/") {
for (subfield <- "/".r.split(field)) { give(subfield) }
} else {
// Scala has no 'continue'. IMO that should be considered
// a bug in Scala.
// Preferred: if (field.startsWith("#")) continue
// Actual: Need to indent all following code
if (!field.startsWith("#")) {
val some_calculation = { ... …Run Code Online (Sandbox Code Playgroud) 在进入Scala 2.10的所有各种不完整的功能列表中,Scaladoc有各种改进提及.但目前还不清楚有哪些,以及哪些实际进入 - 例如,其中一个改进列表称"修复Scaladoc"链接到各种拉取请求,其中一些被拒绝.
任何人都可以总结一下Scala 2.9和2.10里程碑4之间实际发生了什么变化,也许可以说明2.10本身还有什么计划?
另外,他们最终是否会解决无法链接到方法的问题?例如,在我的代码中散落着我有这样的事情:
/**
* Reverse the encoding computed using `encode_ngram`.
*/
def decode_ngram(ngram: String): Iterable[String] = {
DistDocument.decode_ngram_for_counts_field(ngram)
}
Run Code Online (Sandbox Code Playgroud)
我想在同一个类中引用另一个方法,但是AFAIK根本就没办法做到这一点.IMO它应该是显而易见的东西[[encode_ngram]]- 也就是说我绝对不需要给出一个绝对的类(一旦我拿出一个类并将其粘贴在其他地方就会使一切都中断),我不应该给如果方法名称本身是明确的(即非多态的),则为参数类型.
在Java中,有没有办法查看完整的,未截断的堆栈跟踪(例如,通过增加记录的帧数),或以其他方式获取堆栈跟踪的底部?通常情况下,堆栈跟踪在1024帧的情况下从顶部被截断,但是对于堆栈溢出问题,这实际上是毫无价值的,因为您确实需要查看是谁进行了触发递归的调用,靠近底部.更好的是在堆栈中间截断,但显然Sun的JVM不够聪明,无法做到这一点.
甚至可能是一些特殊的Sun特定标志?我尝试将堆栈大小减小到允许的最小值(-Xss1000),但仍然超过1024帧.
就我而言,我正在尝试调试Hadoop映射器中发生的堆栈溢出,但仅限于在非常大的输入上运行时.我假设问题来了,因为递归操作(Scala foldRight)正在一个非常大的链表上完成,我需要非递归地重写它...但我需要知道是谁调用了它foldRight.这是一个直接和间接在很多地方调用的基本例程,我正在使用很多很多代码,所以这是非常不明显的.
我正在使用sbt 0.12 RC2.
我的项目有一堆库依赖项,其中一些触发其他依赖项.其中一些依赖项是非托管的(in lib/),一些位于我的本地.ivy2存储库中,一些位于各种远程存储库中.
我正在寻找一个sbt update-verbose或类似的东西,它会告诉我sbt找到每个JAR文件的确切位置:
[info] Resolving com.nicta#sbt-scoobi;0.0.1 ...
[info] Resolving org.scala-lang#scala-library;2.9.2 ...
[info] Resolving org.apache.opennlp#opennlp-maxent;3.0.1-incubating ...
[info] Resolving jwnl#jwnl;1.3.3 ...
Run Code Online (Sandbox Code Playgroud) 对于如何在没有过多样板的情况下在Scala中高效序列化的问题,Twitter-chill看起来是一个很好的解决方案.
但是,我没有看到他们如何处理案例类的任何证据.这是自动工作还是需要做某些事情(例如创建一个零参数构造函数)?
我对WireFormatScoobi内置的序列化机制有一些经验,这是一个类似于Scalding的Scala Hadoop包装器.它们具有最多22个参数的case类的序列化程序,这些参数使用apply和unapply方法,并对这些函数的参数进行类型匹配以检索类型.(这在Kryo/chill中可能没有必要.)
使用Scala 2.10和SBT 0.13.2构建时,我想拥有-language:_,但Scala 2.9无法识别.有一个关于scalacOptions交叉编译设置不同的问题(带有SBT的条件scalacOptions),但它是关于build.sbt.我正在使用,Build.scala因为我正在进行多项目构建.
我试过这个:
def scalacOptionsVersion(v: String) = {
Seq(
"-unchecked",
"-deprecation",
"-Xlint",
"-Xfatal-warnings",
"-Ywarn-dead-code",
"-target:jvm-1.7",
"-encoding", "UTF-8") ++ (
if (v.startsWith("2.9")) Seq() else Seq("-language:_"))
}
override val settings = super.settings ++ Seq(
...,
scalaVersion := "2.10.4",
scalacOptions <++= scalaVersion(scalacOptionsVersion),
crossScalaVersions := Seq("2.9.2", "2.10.4", "2.11.4"),
...
)
Run Code Online (Sandbox Code Playgroud)
但是我收到一个错误:
[error] /Users/benwing/devel/lemkit/scala/project/build.scala:29: type mismatch;
[error] found : sbt.Def.Initialize[Equals]
[error] required: sbt.Def.Initialize[sbt.Task[?]]
[error] Note: Equals >: sbt.Task[?], but trait Initialize is invariant …Run Code Online (Sandbox Code Playgroud) 我现在看到有一个相关的问题,询问这些运算符(<:<,<%<,=:=)在这里做什么:
Scala 2.8中<:<,<%<和=:=的含义是什么?它们在哪里记录?
但我仍然对他们的实施感到困惑.特别是,我假设一旦你放置了一个断言特定关系的隐式参数,那么你可以使用变量,好像它们已经自动被正确地转换,例如这将编译:
class Foo[T](a: T) {
def splitit(implicit ev: T <:< String) = a split " "
}
Run Code Online (Sandbox Code Playgroud)
但是这在编译器中实际上是如何工作的呢?是否有一些神奇的编译器支持这些运算符,如果没有,它的底层机制是什么允许它从定义中推断出这种关系?(这个机制是否专门用于允许这些运算符工作,以及它对这些特定运算符的具体程度如何?)您可以放置一个额外的隐式参数,这样会以某种方式更改编译器对类型的解释,这似乎有点神奇.
C#和Scala都采用了框架来简化异步/并行计算,但方式不同.最新的C#(5.0,仍然处于测试阶段)已决定使用async/await框架(使用延续传递,但使用方式更简单),而Scala则使用"actors"的概念,最近在Akka中采用了演员实现并将其合并到基础库中.
这是一个需要考虑的任务:我们收到一系列请求来执行各种操作 - 例如,从用户输入,到服务器的请求等.某些操作很快,但有些操作需要一段时间.对于慢速的,我们想异步地执行操作(在另一个线程中)并在线程完成时处理它,同时仍然可以自由地处理新请求.
一个简单的同步循环可能是(伪代码):
while (1) {
val request = waitForAnything(user_request, server_request)
val result = do_request(request)
if (result needs to be sent back)
send_back_result(result)
}
Run Code Online (Sandbox Code Playgroud)
在基本的fork/join框架中,您可能会执行以下操作(伪代码):
val threads: Set[Thread]
while (1) {
val request = waitForAnything(user_request, server_request, termination of thread)
if (request is thread_terminate) {
threads.delete(request.terminated_thread)
val result = request.thread_result
if (result needs to be sent back)
send_back_result(result)
} else if (request is slow) {
val thread = new Thread(() => do_request(request))
Threads.add(thread)
thread.start()
} else {
val result …Run Code Online (Sandbox Code Playgroud) scala ×10
sbt ×2
actor ×1
async-await ×1
c# ×1
case-class ×1
class ×1
debugging ×1
deprecated ×1
exploratory ×1
generator ×1
java ×1
kryo ×1
object ×1
operators ×1
package ×1
python ×1
scaladoc ×1
stack-frame ×1
twitter ×1
yield ×1