2014-12-25 3 views
1

При использовании списка он работает правильно, но когда я создаю бесконечный потокпоток вызывает OutOfMemoryError в Scala

def foo = { 
    val s = Stream.from(1) 
    s.flatMap(x => 
       s.flatMap(y => 
        s.flatMap(z => f(x, y, z)))) 
} 

Я получаю java.lang.OutOfMemoryError, когда я звоню

foo.take(10) 

В отношении f

def f(x: Int, y: Int, z: Int) = { 
     if(Math.pow(x, 2) + Math.pow(y, 2) == Math.pow(z, 2)) 
     else None 
    } 

Первоначально я думал, что он будет оцениваться только тогда, когда я бы назвал его f или эти 10 элементов, но знаю, что я не уверен. Я получаю ту же самую проблему с Iterator.from(1) Любая помощь пожалуйста. Заранее спасибо!

+0

Что делать? – Dici

+0

Как вы можете сгруппировать по каждому элементу в потоке. Его бесконечно! У вас не хватит памяти. Что вы на самом деле пытаетесь сделать? –

+0

Код для меня работает. Пожалуйста, разместите код _exact_, который вы используете, включая определение 'f'. Примечание 'foo.take (10)' возвращает поток, поэтому нам также нужно знать, что вы делаете с этим значением. –

ответ

2

Похоже, вы пытаетесь создать тройки, в которых первый член больше второго. Для начала создадим несколько таких пар:

scala> def natNums = Iterator from 1 
natNums: Iterator[Int] 

scala> def foo = for { x <- natNums; y <- 1 until x } yield (x,y) 
foo: Iterator[(Int, Int)] 

scala> (foo take 15).toList 
res4: List[(Int, Int)] = List((2,1), (3,1), (3,2), (4,1), (4,2), (4,3), (5,1), (5,2), (5,3), (5,4), (6,1), (6,2), (6,3), (6,4), (6,5)) 

Есть ли я на правильном пути?

ОК, теперь вы хотите добавить третьего члена к кортежу. Ну, если мы так же ограничить г будет меньше, чем у, она отлично работает:

scala> def foo = for { x <- natNums; y <- 1 until x; z <- 1 until y } yield (x,y,z) 
foo: Iterator[(Int, Int, Int)] 

scala> (foo take 15).toList 
res1: List[(Int, Int, Int)] = List((3,2,1), (4,2,1), (4,3,1), (4,3,2), (5,2,1), (5,3,1), (5,3,2), (5,4,1), (5,4,2), (5,4,3), (6,2,1), (6,3,1), (6,3,2), (6,4,1), (6,4,2)) 

Но если г непринужденный, я не понимаю, что вы хотите, чтобы программа делать. Просто рисунок из г natNums превращает процессор в тостере:

scala> def foo = for { x <- natNums; y <- 1 until x; z <- natNums } yield (x,y,z) 
foo: Iterator[(Int, Int, Int)] 

scala> (foo take 15).toList 
^C 

Можете ли вы дать нам выход вы ожидаете?

ОБНОВЛЕНИЕ: Ах! Пифагорейские троицы - как весело!

Вот простой генератор для того, что я буду называть «сырыми» пифагорейскими троек, потому что он включает в себя кратные, которые нужно отфильтровать. Например, (6,8,10) не следует считать пифагорейской тройкой, так как она кратно (3,4,5). Я оставлю это для вас, так как я думаю, что блокирование вас было всего лишь частью создания чисел в первую очередь. Не стесняйтесь обращаться за помощью к этому в другой вопрос StackOverflow, если вам это нужно.

scala> def rawPythagTriples = 
    for { c <- Iterator from 1; a <- 1 until c; b <- a until c if a*a + b*b == c*c } 
    yield (a,b,c) 
rawPythagTriples: Iterator[(Int, Int, Int)] 

scala> (rawPythagTriples take 10).toList 
res2: List[(Int, Int, Int)] = List((3,4,5), (6,8,10), (5,12,13), (9,12,15), (8,15,17), (12,16,20), (7,24,25), (15,20,25), (10,24,26), (20,21,29)) 

Обратите внимание, что мы начинаем с гипотенузой, тем самым сдерживая a и b. Кстати, вы можете сделать некоторые небольшие оптимизации, например. начиная с c по 5, a по 2, и b по адресу: a+1.

+0

Спасибо AmigoNico. Результат, который я ожидаю, это троицы Пифагора. Извините, я не уточнил это с самого начала. – jimakos17

0

Это работает в РЕПЛ:

def foo = { 
    val s = Stream.from(1) 
    s.flatMap(x => 
    s.flatMap(y => 
     s.flatMap(z => List(x,y,z)))) 
} 

scala> foo.take(15) mkString ", " 
res24: String = 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1, 5 

Ваш е (х, у, г) должен возвращать тип, который расширяет подкласс GenTraversableOnce [?].

+0

Да, это так, но определение 'f' в обновленном вопросе не делает. –

Смежные вопросы