请原谅我,如果已经在别处问过这个问题.我有一个涉及函数值和隐式参数的Scala语法问题.
我很自在地使用Scala的currying功能.例如,如果我有一个sum函数,并希望使第二个参数隐含:
scala> def sum(a: Int)(implicit b: Int) = a + b
sum: (a: Int)(implicit b: Int)Int
Run Code Online (Sandbox Code Playgroud)
有没有办法使用函数值语法执行此操作?忽略隐含片刻,我通常会写出如下的curried函数值:
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
Run Code Online (Sandbox Code Playgroud)
但是,第二种方法中的函数签名是非常不同的(currying正在明确表达).只是将隐式关键字添加到b中没有多大意义,编译器也会抱怨:
scala> val sum2 = (a: Int) => (implicit b: Int) => a + b
<console>:1: error: '=>' expected but ')' found.
val sum2 = (a: Int) => (implicit b: Int) => a + b
^
Run Code Online (Sandbox Code Playgroud)
此外,从第一种获取函数值的方法中部分应用总和也会导致问题:
scala> val sumFunction = …Run Code Online (Sandbox Code Playgroud) 我还在尝试学习Scala的蛋糕模式.在我看来,它为您提供了集中"组件"配置的优势,以及为这些组件提供默认实现的能力(当然这些组件是可覆盖的).
然而,使用自我类型特征来描述依赖关系似乎混合了关注领域.Component(我认为)的目的是抽象出该组件的不同实现.但是Component中描述的依赖列表本身就是一个实现问题.
例如,假设我有一个装满小部件的数据库,一个允许我查找特定种类小部件的注册表,以及一些使用注册表处理小部件的算法:
case class Widget(id: Int, name:String)
trait DatabaseComponent {
def database: (Int => Widget) = new DefaultDatabase()
class DefaultDatabase extends (Int => Widget) {
// silly impl
def apply(x: Int) = new Person(x, "Bob")
}
}
trait RegistryComponent {
this: DatabaseComponent => // registry depends on the database
def registry: (List[Int] => List[Widget]) = new DefaultRegistry()
class DefaultRegistry extends (List[Int] => List[Widget]) {
def apply(xs: List[Int]) = xs.map(database(_))
}
}
trait AlgorithmComponent {
this: RegistryComponent => …Run Code Online (Sandbox Code Playgroud) 我还在学习Scala,但我认为有趣的一点是Scala模糊了方法和字段之间的界限.例如,我可以建立一个这样的类......
class MutableNumber(var value: Int)
Run Code Online (Sandbox Code Playgroud)
这里的关键是constructor-argument中的var自动允许我像java中的getter/setter一样使用'value'字段.
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Run Code Online (Sandbox Code Playgroud)
如果我想添加约束,我可以通过切换到使用方法代替实例字段来实现:
// require all mutable numbers to be >= 0
class MutableNumber(private var _value: Int) {
require(_value >= 0)
def value: Int = _value
def value_=(other: Int) {
require(other >=0)
_value = other
}
}
Run Code Online (Sandbox Code Playgroud)
由于API不会更改,因此客户端代码不会中断:
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
Run Code Online (Sandbox Code Playgroud)
我的挂机是添加到Scala-2.8的命名参数功能.如果我使用命名参数,我的API 确实会改变,它确实打破了api.
val num = new MutableNumber(value=5) // old API
val …Run Code Online (Sandbox Code Playgroud) 我有一个关于严格与非严格定义的问题.Haskell wiki-laziness(http://en.wikibooks.org/wiki/Haskell/Laziness)在"黑盒严格性分析"一节中做出以下断言:
[假设函数f采用单个参数.]当且仅当f未定义导致打印错误并停止我们的程序时,函数f才是严格函数.
维基对比const用id,分别表示一个非严格和严格的功能.
我的问题是,我认为foldl是以非严格的方式进行评估,造成不良的空间泄漏,而foldl'则是严格的.
然而,上述测试似乎断言foldl和foldl'都是严格的.如果它们的任何参数未定义,那么两个函数都会生成undefined:
> Data.List.foldl (+) undefined [1,2,3,4]
Prelude.undefined
> Data.List.foldl' (+) 0 undefined
Prelude.undefined
> Data.List.foldl' (+) undefined [1,2,3,4]
Prelude.undefined
> Data.List.foldl (+) 0 undefined
Prelude.undefined
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下我缺少的东西吗?
谢谢!
我正在尝试使用Lift框架反序列化JSON文本,并且它们似乎不支持Seq特征(尽管支持List).举个例子...
一些代表员工的JSON数据(名字和姓氏)......
{"employees":[{"fname":"Bob","lname":"Hope"},{"fname":"Bob","lname":"Smith"}]}
Run Code Online (Sandbox Code Playgroud)
这是员工域对象:
case class Employee(fname: String, lname: String) { }
case class Employees(employees: Seq[Employee]) { }
Run Code Online (Sandbox Code Playgroud)
这是我的JSON反序列化代码......
class EmployeeTest {
@Test def test() {
val jsonText: String = ....
val e = deserialize(jsonText)
}
def deserialize(in: String): Employees = {
implicit val formats = net.liftweb.json.DefaultFormats
net.liftweb.json.Serialization.read[Employees](in)
}
}
Run Code Online (Sandbox Code Playgroud)
如果我将Employees域对象更改为使用List而不是Seq,那么它可以工作.但是如果可以的话,我真的很想使用Seq.
这是我在运行上面的代码时看到的异常(使用Seq):我能做些什么来让它工作吗?谢谢你的帮助!
net.liftweb.json.MappingException: unknown error
at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:288)
at net.liftweb.json.Serialization$.read(Serialization.scala:50)
at EmployeeTest.deserialize(EmployeeTest.scala:20)
at EmployeeTest.test(EmployeeTest.scala:13)
Caused by: java.lang.UnsupportedOperationException: tail of empty list
at scala.collection.immutable.Nil$.tail(List.scala:388)
at scala.collection.immutable.Nil$.tail(List.scala:383)
at net.liftweb.json.Meta$Constructor.bestMatching(Meta.scala:60)
at net.liftweb.json.Extraction$.findBestConstructor$1(Extraction.scala:187) …Run Code Online (Sandbox Code Playgroud) 当我使用Scala-2.8中添加的自动生成的copy()方法时,我遇到了一些奇怪的行为.
从我读过的内容来看,当你将一个给定的类声明为一个case-class时,你会自动生成很多东西,其中一个就是copy()方法.所以你可以做以下......
case class Number(value: Int)
val m = Number(6)
println(m) // prints 6
println( m.copy(value=7) ) // works fine, prints 7
println( m.copy(value=-7) ) // produces: error: not found: value value
println( m.copy(value=(-7)) ) // works fine, prints -7
Run Code Online (Sandbox Code Playgroud)
如果已经问过这个问题,我很抱歉,但这里发生了什么?
我有一个关于Scala的类型构造函数的类型推理的问题.我正在运行Scala 2.9.1 ...
假设我定义了Tree:
sealed trait Tree[C[_], A]
case class Leaf[C[_], A](a: A) extends Tree[C, A]
case class Node[C[_], A](a: A, c: C[Tree[C, A]]) extends Tree[C, A]
Run Code Online (Sandbox Code Playgroud)
并根据我的Tree定义定义了BinaryTree:
type Pair[A] = (A, A)
type BinaryTree[A] = Tree[Pair, A]
Run Code Online (Sandbox Code Playgroud)
我现在可以定义一个BinaryTree整数:
val tree: BinaryTree[Int] = Node[Pair, Int](1, (Leaf(2), Leaf(3)))
Run Code Online (Sandbox Code Playgroud)
这个问题是我必须在实例化时提供类型参数Node.
所以,如果这样做:
val tree: BinaryTree[Int] = Node(1, (Leaf(2), Leaf(3)))
Run Code Online (Sandbox Code Playgroud)
我收到错误:
error: no type parameters for method apply: (a: A, c: C[Tree[C,A]])Node[C,A] in
object Node exist so that it can be applied …Run Code Online (Sandbox Code Playgroud) 我正在使用Scala 2.9.1
我已经定义了一个Logging特性:
trait Logging {
def debug(msg: String, throwables: Throwable*) = ....
....
}
Run Code Online (Sandbox Code Playgroud)
我有一个JMSPublisher类混合了Logging特性:
class JMSPublisher extends Publisher with Logging {
def publishProducts(list: List[_ <: Product]) = ....
def publish(list: Seq[Product]) = ....
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好.我的问题是我有一个用户想要将我的JMSPublisher加载到Spring中.他正在使用Spring 2.5.6.
在启动期间加载ApplicationContext时,应用程序崩溃并出现IllegalStateException,抱怨它无法找到与我的Logging特征相关的桥接方法.
Initialization of bean failed; nested exception is java.lang.IllegalStateException: Unable to locate bridged method for bridge method 'public void com.app.messaging.JmsPublisher.debug(java.lang.String, scala.collection.Seq)'
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
.....stack trace follows.......
Run Code Online (Sandbox Code Playgroud)
这段代码在Scala-2.8下运行,我听说Scala标记的特性有一些方法,如2.9中所述.我认为这是导致Spring失败的原因.如果我的类无法被Spring加载,我无法升级到Scala-2.9.
有没有人遇到过这个问题?有任何修复或解决方法吗?
我刚刚开始在Scala中使用更高级的类型,我遇到了我不理解的行为.我在Scala 2.9.0.1的REPL中做了所有这些.
首先,我创建一个mapper特征,以便我可以映射任何类型M的元素:
trait Mapper {
def mapper[M[_], A, B](m: M[A], f: A => B): M[B]
}
Run Code Online (Sandbox Code Playgroud)
这是我对mapper的实现:
val mymapper = new Mapper {
def mapper[List, Int, Double](m: List[Int], f: Int => Double): List[Double] = m.map(f)
}
Run Code Online (Sandbox Code Playgroud)
但REPL抱怨......
<console>:9: error: List does not take type parameters
def mapper[List, Int, Double](m: List[Int], f: Int => Double): List[Double] = m.map(f)
^
<console>:9: error: List does not take type parameters
def mapper[List, Int, Double](m: List[Int], f: Int => Double): List[Double] = m.map(f)
^ …Run Code Online (Sandbox Code Playgroud) 我正在玩Scala的懒惰迭代器,我遇到了一个问题.我要做的是读取一个大文件,进行转换,然后写出结果:
object FileProcessor {
def main(args: Array[String]) {
val inSource = Source.fromFile("in.txt")
val outSource = new PrintWriter("out.txt")
try {
// this "basic" lazy iterator works fine
// val iterator = inSource.getLines
// ...but this one, which incorporates my process method,
// throws OutOfMemoryExceptions
val iterator = process(inSource.getLines.toSeq).iterator
while(iterator.hasNext) outSource.println(iterator.next)
} finally {
inSource.close()
outSource.close()
}
}
// processing in this case just means upper-cases every line
private def process(contents: Seq[String]) = contents.map(_.toUpperCase)
}
Run Code Online (Sandbox Code Playgroud)
所以我在大文件上得到一个OutOfMemoryException.我知道如果你保持对流的头部的引用,你可以与Scala的懒惰流相遇.所以在这种情况下,我小心翼翼地将process()的结果转换为迭代器并抛弃最初返回的Seq.
有谁知道为什么这仍会导致O(n)内存消耗?谢谢!
为了回应fge和huynhjl,似乎Seq可能是罪魁祸首,但我不知道为什么.作为一个例子,以下代码工作正常(我在整个地方使用Seq).此代码并不会产生一个OutOfMemoryException:
object …Run Code Online (Sandbox Code Playgroud) 我按照 Spring Kafka 文档创建了一个批处理消费者:
@SpringBootApplication
public class ApplicationConsumer {
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationConsumer.class);
private static final String TOPIC = "foo";
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ApplicationConsumer.class, args);
}
@Bean
public RecordMessageConverter converter() {
return new JsonMessageConverter();
}
@Bean
public BatchMessagingMessageConverter batchConverter() {
return new BatchMessagingMessageConverter(converter());
}
@KafkaListener(topics = TOPIC)
public void listen(List<Name> ps) {
LOGGER.info("received name beans: {}", Arrays.toString(ps.toArray()));
}
}
Run Code Online (Sandbox Code Playgroud)
我能够通过定义 Spring 自动选取的以下附加配置环境变量来成功让使用者运行:
export SPRING_KAFKA_BOOTSTRAP-SERVERS=...
export SPRING_KAFKA_CONSUMER_GROUP-ID=...
Run Code Online (Sandbox Code Playgroud)
所以上面的代码有效。但现在我想自定义默认错误处理程序以使用指数退避。从参考文档中,我尝试将以下内容添加到 ApplicationConsumer 类中:
@Bean
public …Run Code Online (Sandbox Code Playgroud) scala ×9
scala-2.8 ×2
spring ×2
apache-kafka ×1
cake-pattern ×1
currying ×1
fold ×1
function ×1
gadt ×1
generics ×1
haskell ×1
implicit ×1
iterator ×1
java ×1
javabeans ×1
json ×1
lift ×1
list ×1
literals ×1
properties ×1
reflection ×1
scala-2.9 ×1
seq ×1
spring-boot ×1
spring-kafka ×1
strict ×1
traits ×1