我写了一个函数,使用流无限期地生成质数(维基百科:Erastothenes的增量筛).它返回一个流,但它也在内部合并素数倍流以标记即将到来的复合.如果我自己这样说,这个定义简洁,实用,优雅且易于理解:
def primes(): Stream[Int] = {
def merge(a: Stream[Int], b: Stream[Int]): Stream[Int] = {
def next = a.head min b.head
Stream.cons(next, merge(if (a.head == next) a.tail else a,
if (b.head == next) b.tail else b))
}
def test(n: Int, compositeStream: Stream[Int]): Stream[Int] = {
if (n == compositeStream.head) test(n+1, compositeStream.tail)
else Stream.cons(n, test(n+1, merge(compositeStream, Stream.from(n*n, n))))
}
test(2, Stream.from(4, 2))
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试生成第1000个素数时,我得到了"java.lang.OutOfMemoryError:超出GC开销限制".
我有一个替代解决方案,它在primes上返回一个迭代器,并在内部使用元组的优先级队列(multiple,prime用于生成多个)来标记即将到来的复合.它运行良好,但它需要大约两倍的代码,我基本上不得不从头重新开始:
import scala.collection.mutable.PriorityQueue
def primes(): Iterator[Int] = {
// Tuple (composite, prime) is used to generate …
Run Code Online (Sandbox Code Playgroud) 我可以使用调试隐式的建议:
我想使用隐含的,x
:
type T
trait HasT {
implicit def x: T = ...
}
Run Code Online (Sandbox Code Playgroud)
但我还需要从某个包中导入通配符foo
.我尝试了两种不同的方式来介绍两者:
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
Run Code Online (Sandbox Code Playgroud)
和
class UseT {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
Run Code Online (Sandbox Code Playgroud)
两者都失败了"找不到"(不是"模糊的含义值").
当x: T
通过继承或导入在方法调用点访问隐式标识符时会发生这种情况.
我的解决方法是在导入之前将x重新绑定到隐式val.以下两项工作:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
Run Code Online (Sandbox Code Playgroud)
和
implicit val …
Run Code Online (Sandbox Code Playgroud) 假设我们有以下内容:
args = (4,7,5)
def foo(a,b,c): return a*b%c
Run Code Online (Sandbox Code Playgroud)
Python方便地允许元组解包:
foo(4,7,5) # returns 3
foo(*args) # returns foo(4,7,5), i.e. 3
Run Code Online (Sandbox Code Playgroud)
所以我们不必这样做:
foo(t[0], t[1], t[2]) # a repulsive, verbose, and error-prone synonym
Run Code Online (Sandbox Code Playgroud)
现在假设我们有一个类似的3元组列表,并希望列出foo(t)
每个元组的列表t
.有"一种明显的方法":
list(map(lambda t: foo(*t), listoftuples))
Run Code Online (Sandbox Code Playgroud)
但现在假设foo
只是一个扔掉的功能.我们不希望垃圾污染我们的命名空间.让我们在匿名的地毯下扫一扫!:
list(map(lambda t: (lambda a, b, c: a*b%c)(*t), listoftuples))
Run Code Online (Sandbox Code Playgroud)
好吧,我们现在有嵌套的lambda.当然,我们可以解析它.但是我们冒着被误认为是一个阴谋家的风险,这个阴谋家喜欢构造神秘的法术,其唯一目的就是为那些冒昧的人重新审视我们的代码.
此外,对于这样一个简单的想法,这有点冗长.这似乎不是pythonic.(在scala中,相当于内部lambda (_*_%_)
,假设上下文允许类型推断.如果这是 pythonic,它不会同样简洁吗?).
我们可以这样删除内部lambda:
list(map((lambda t: t[0] * t[1] % t[2]), listoftuples))
Run Code Online (Sandbox Code Playgroud)
那更短,但令人厌恶.我发现使用幻数(而不是名称)来引用参数往往会导致错误.
如果它看起来更像这样会很棒:
list(map((lambda a, b, c: a*b%c), listoftuples))
Run Code Online (Sandbox Code Playgroud)
当然,它不可能.这就像打电话一样foo(args)
.我们需要一个星号,可以这么说.这是一个可能的星号:
def unpackInto(func): return lambda …
Run Code Online (Sandbox Code Playgroud) python lambda coding-style language-design iterable-unpacking