Предположим, что существует последовательность a[i] = f(a[i-1], a[i-2], ... a[i-k])
. Как бы вы закодировали его, используя streams
в Scala?Последовательность с потоками в Scala
ответ
Его можно будет обобщить для любого k, используя массив для a
и еще один параметр k
и имеющий функцию f.i. с параметром rest...
.
def next(a1:Any, ..., ak:Any, f: (Any, ..., Any) => Any):Stream[Any] {
val n = f(a1, ..., ak)
Stream.cons(n, next(a2, ..., n, f))
}
val myStream = next(init1, ..., initk)
для того, чтобы иметь сделать next.drop(1000)
1000.
Последняя информация, чтобы показать, как это может быть сделано с переменным числом аргументов. Помните, что нет никакой проверки Арности для пройденной функции:
object Test extends App {
def next(a:Seq[Long], f: (Long*) => Long): Stream[Long] = {
val v = f(a: _*)
Stream.cons(v, next(a.tail ++ Array(v), f))
}
def init(firsts:Seq[Long], rest:Seq[Long], f: (Long*) => Long):Stream[Long] = {
rest match {
case Nil => next(firsts, f)
case x :: xs => Stream.cons(x,init(firsts, xs, f))
}
}
def sum(a:Long*):Long = {
a.sum
}
val myStream = init(Seq[Long](1,1,1), Seq[Long](1,1,1), sum)
myStream.take(12).foreach(println)
}
Как вы получаете начальные 'k'elements? – huitseeker
Это не часть вопроса, я предположил, что они известны. Как и для Фибоначчи, вы устанавливаете первые два как 0 и 1. –
@andypetrella да, вы правы, я предполагаю, что первые элементы 'k' известны. – Michael
К сожалению, мы не можем обобщать над числом и быть типобезопасны одновременно. Таким образом, мы должны сделать все вручную:
def seq2[T, U](initials: Tuple2[T, T]) = new {
def apply(fun: Function2[T, T, T]): Stream[T] = {
initials._1 #::
initials._2 #::
(apply(fun) zip apply(fun).tail).map {
case (a, b) => fun(a, b)
}
}
}
И мы получаем def fibonacci = seq2((1, 1))(_ + _)
.
def seq3[T, U](initials: Tuple3[T, T, T]) = new {
def apply(fun: Function3[T, T, T, T]): Stream[T] = {
initials._1 #::
initials._2 #::
initials._3 #::
(apply(fun) zip apply(fun).tail zip apply(fun).tail.tail).map {
case ((a, b), c) => fun(a, b, c)
}
}
}
def tribonacci = seq3((1, 1, 1))(_ + _ + _)
... и до 22.
Я надеюсь, что картина становится ясно, каким-то образом. (Мы могли бы, конечно, улучшить и обменивать кортеж initials
с отдельными аргументами. Это поможет нам скопировать скобки позже, когда мы его используем.) Если в будущем наступит маска-язык Scala, это, надеюсь, будет легче определить.
Хм, 'def' должен быть 'lazy val'. – Debilski
В порядке? (a [i] = f (a [ik], a [i-k + 1], ... a [i-1]) вместо a [i] = f (a [i-1], a [я-2] ... а [ик]), так как я предпочитаю таким образом)
/**
Generating a Stream[T] by the given first k items and a function map k items to the next one.
*/
def getStream[T](f : T => Any,a : T*): Stream[T] = {
def invoke[T](fun: T => Any, es: T*): T = {
if(es.size == 1) fun.asInstanceOf[T=>T].apply(es.head)
else invoke(fun(es.head).asInstanceOf[T => Any],es.tail :_*)
}
Stream.iterate(a){ es => es.tail :+ invoke(f,es: _*)}.map{ _.head }
}
Например, следующий код для генерации последовательности Фибоначчи.
scala> val fn = (x: Int, y: Int) => x+y
fn: (Int, Int) => Int = <function2>
scala> val fib = getStream(fn.curried,1,1)
fib: Stream[Int] = Stream(1, ?)
scala> fib.take(10).toList
res0: List[Int] = List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
Следующий код может генерировать последовательность {ап} где a1 = 1, a2 = 2, а3 = 3, а (п + 3) = а (п) + 2а (п + 1) + 3a (п + 2).
scala> val gn = (x: Int, y: Int, z: Int) => x + 2*y + 3*z
gn: (Int, Int, Int) => Int = <function3>
scala> val seq = getStream(gn.curried,1,2,3)
seq: Stream[Int] = Stream(1, ?)
scala> seq.take(10).toList
res1: List[Int] = List(1, 2, 3, 14, 50, 181, 657, 2383, 8644, 31355)
короткий ответ, который вы, вероятно, ищете, это шаблон, чтобы определить ваш Stream
как только вы закрепили избранный k
для арности f
(т.е. у вас есть фиксированный тип для f). Следующая диаграмма дает вам Stream
, который n
-й элемент - это термин a[n]
из вашей последовательности:
def recStreamK [A](f : A ⇒ A ⇒ ... A) (x1:A) ... (xk:A):Stream[A] =
x1 #:: recStreamK (f) (x2)(x3) ... (xk) (f(x1)(x2) ... (xk))
(кредит: это очень близко к answer Энди Петрелла, за исключением того, что начальные элементы установлены правильно, и, следовательно, ранг в потоке соответствует таковому в последовательности)
Если вы хотите обобщить более k
, это возможно безопасным способом (с проверкой arity) в Scala, используя приоритетные перекрывающиеся импликации. Код (~80 строк) доступен как gist here.Боюсь, я немного увлекся и объяснил это как подробный & блог блога there.
- 1. Управление потоками актеров Scala
- 2. Составление операций с потоками в Scala
- 3. Scala проверить Последовательность Eithers
- 4. Scala Последовательность Int
- 5. Последовательность подобных функций в Scala
- 6. Перемешать последовательность List в Scala
- 7. Scala - возвращаемая геометрическая последовательность
- 8. Уникальная последовательность Scala
- 9. Преобразовать Scala последовательность в пар
- 10. идентифицировать последовательность чисел в Scala
- 11. Последовательность повторного упорядочения в Scala
- 12. Как общаться между потоками в Scala?
- 13. Последовательность очередности и таймаута Scala
- 14. параметры Scala SortBy как последовательность
- 15. Scala, Как пройти через последовательность
- 16. последовательность методов возврата функции scala
- 17. Как создать последовательность выражений Scala?
- 18. Как интерпретировать последовательность => в Scala?
- 19. Сформировать последовательность числа Фибоначчи в Scala
- 20. Wrongly реализована последовательность Фибоначчи в Scala
- 21. Decompress дельта сжимается последовательность чисел в Scala
- 22. Как слить последовательность массивов в scala
- 23. Работа с битовыми потоками
- 24. Play 2.3 с Scala, преобразование JSON массива в последовательность
- 25. Как сопоставить последовательность объектов с Картами в Scala?
- 26. Инициализация поля и последовательность конструкторов в Scala с наследованием
- 27. Как реализовать рекурсивную последовательность Фибоначчи в Scala с использованием FS2?
- 28. Scala vector splicing (поддерживая отсортированную последовательность)
- 29. Последовательность карт не работает - scala play framework
- 30. Как эффективно взаимодействовать с потоками Java из Scala?
Я пытаюсь понять правила последовательности. Что такое 'k'? Что такое 'a [0]' (первый элемент в потоке)? Что такое 'a [1]'? – toddsundsted
@toddsundsted Предположим, что я знаю первые элементы 'k' последовательности: a [0], a [1], ..., a [1]. Теперь я хочу вычислить 'a [n]' for 'n'>' k', используя функцию 'f'. – Michael