小编shj*_*shj的帖子

含有隐含的Scala函数文字

请原谅我,如果已经在别处问过这个问题.我有一个涉及函数值和隐式参数的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 function implicit currying literals

25
推荐指数
3
解决办法
4667
查看次数

斯卡拉蛋糕模式鼓励硬编码的依赖?

我还在尝试学习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)

dependency-injection scala traits cake-pattern

18
推荐指数
1
解决办法
2289
查看次数

Scala属性问题

我还在学习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)

scala properties javabeans named-parameters scala-2.8

11
推荐指数
1
解决办法
2665
查看次数

Haskell - 严格与非严格的foldl

我有一个关于严格与非严格定义的问题.Haskell wiki-laziness(http://en.wikibooks.org/wiki/Haskell/Laziness)在"黑盒严格性分析"一节中做出以下断言:

[假设函数f采用单个参数.]当且仅当f未定义导致打印错误并停止我们的程序时,函数f才是严格函数.

维基对比constid,分别表示一个非严格和严格的功能.

我的问题是,我认为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)

有人可以解释一下我缺少的东西吗?

谢谢!

haskell strict lazy-evaluation fold

11
推荐指数
1
解决办法
1440
查看次数

Lift Framework无法反序列化JSON数据

我正在尝试使用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)

json scala list lift seq

9
推荐指数
1
解决办法
2639
查看次数

Scala Copy()奇怪的行为

当我使用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 named-parameters scala-2.8

9
推荐指数
1
解决办法
775
查看次数

类型构造函数的Scala类型推断

我有一个关于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)

generics scala type-inference higher-kinded-types gadt

8
推荐指数
1
解决办法
434
查看次数

Scala 2.9 Bridge-Method

我正在使用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.

有没有人遇到过这个问题?有任何修复或解决方法吗?

java reflection spring scala scala-2.9

6
推荐指数
1
解决办法
602
查看次数

Scala中的方法级高级绑定类型

我刚刚开始在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 higher-kinded-types

4
推荐指数
1
解决办法
770
查看次数

Scala Infinite Iterator OutOfMemory

我正在玩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)

iterator functional-programming scala lazy-evaluation

4
推荐指数
1
解决办法
863
查看次数

Spring Boot Kafka 配置 DefaultErrorHandler?

我按照 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)

spring apache-kafka spring-boot spring-kafka

4
推荐指数
1
解决办法
9919
查看次数