Can someone please explain the following output from the REPL?
I'm defining 2 (infinite) Streams that are otherwise identical in their definition except that map is preceded by . (period) in one definition and a _ _ (space) in the other.
I can see that this would cause map to bind differently, but what happens to the 1 in the output from the second definition?
Thanks.
scala> lazy val infinite: Stream[Int] = 1 #:: infinite.map(_+1)
infinite: Stream[Int] = <lazy>
scala> val l = infinite.take(10).toList.mkString(",")
l: String = 1,2,3,4,5,6,7,8,9,10
scala> lazy val infinite2: Stream[Int] = 1 #:: infinite2 map(_+1)
infinite2: Stream[Int] = <lazy>
scala> val l2 = infinite2.take(10).toList.mkString(",")
l2: String = 2,3,4,5,6,7,8,9,10,11
It's about method associativity. This:
1 #:: infinite.map(_+1)
is quite straightforward while this:
1 #:: infinite2 map(_+1)
is interpreted by the compiler as:
(1 #:: infinite2) map(_+1)
1 #:: infinite2 is your desired stream, but before you return it, you apply lazy transformation adding one to every item. This explains why 1 never appears as a result - after transformation it becomes 2.
For more details see: Operator precedence in Scala. Since # is not a special character, it is treated equally with map, thus methods are evaluated from left to right.
In the infinite2 case, what you've expressed is equivalent to the following:
lazy val infinite2: Stream[Int] = (1 #:: infinite2) map(_ + 1)
Since the stream starts with 1, the map will add 1 to the first element.
Related
I'm trying to come up with an endless Fibonacci sequence of numbers function, that passes two parameters. The parameters will set the first 2 elements in the sequence.
def fib(i: Int, j: Int): Stream[Int] = {
case 0 | 1 => current
case _ => Fib( current-1 ) + Fib( current -2 )
}
This is very easy to do, however, you have to recurs in the other direction. You do not define the current element based on previous elements but your function receives the current arguments and calls itself with the arguments of the next value:
def fib(i: Int, j: Int): Stream[Int] = i #:: fib(j, i + j)
println(fib(0,1).take(10))
In contrast to the typical recursive definition, this is not quaratic but just linear, so it is quite efficient. (Streams are of course more complex than a simple while loop).
For efficiency, this kind of thing is usually done with a Stream to avoid recalculating the same values over and over. The straightforward way to create a Stream of Fibonacci numbers is
val fibs: Stream[BigInt] = 0 #:: 1 #:: ( fibs zip fibs.tail map ( n => n._1 + n._2 ) )
But you can make a more efficient version of this kind of Stream by avoiding the zip, like so:
val fibs: Stream[BigInt] = {
def loop( h:BigInt, n:BigInt ): Stream[BigInt] = h #:: loop(n, h+n)
loop(0,1)
}
Notice that these use val; you generally DO NOT want to use def to define a stream!
I understand the basic of diff between val and lazy val .
but while I run across this example, I 'm confused.
The following code is right one. It is a recursion on stream type lazy value.
def recursive(): {
lazy val recurseValue: Stream[Int] = 1 #:: recurseValue.map(_+1)
recurseValue
}
If I change lazy val to val. It reports error.
def recursive(): {
//error forward reference failed.
val recurseValue: Stream[Int] = 1 #:: recurseValue.map(func)
recurseValue
}
My trace of thought in 2th example by substitution model/evaluation strategy is :
the right hand sight of #:: is call by name with that the value shall be of the form :
1 #:: ?,
and if 2th element being accessed afterward, it refer to current recurseValue value and rewriting it to :
1 :: ((1 #:: ?) map func) =
1 :: (func(1) #:: (? map func))
.... and so on and so on such that the compiler should success.
I don't see any error when I rewriting it ,is there somthing wrong?
EDIT:
CONCLUSION:I found it work fine if the val defined as a field. And I also noticed this post about implement of val. The conclusion is that the val has different implementation in method or field or REPL. That's confusing really.
That substitution model works for recursion if you are defining functions, but you can't define a variable in terms of itself unless it is lazy. All of the info needed to compute the right-hand side must be available for the assignment to take place, so a bit of laziness is required in order to recursively define a variable.
You probably don't really want to do this, but just to show that it works for functions:
scala> def r = { def x:Stream[Int] = 1#::( x map (_+1) ); x }
r: Stream[Int]
scala> r take 3 foreach println
1
2
3
I have a:
val a : Stream[Boolean] = ...
When I foldLeft it as follows
val b = a.foldLeft(false)(_||_)
Will it terminate when it finds the first true value in the stream? If not, how do I make it to?
It would not terminate on the first true. You can use exists instead:
val b = a.exists(identity)
No it won't terminate early. This is easy to illustrate:
val a : Stream[Boolean] = Stream.continually(true)
// won't terminate because the strea
val b = a.foldLeft(false)(_||_)
stew showed that a simple solution to terminate early, in your specific case, is
val b = a.exists(identity).
Even simpler, this is equivalent to:
val b = a.contains(true)
A more general solution which unlike the above is also applicable if you actually need a fold, is to use recursion (note that here I am assuming the stream is non-empty, for simplicity):
def myReduce( s: Stream[Boolean] ): Boolean = s.head || myReduce( s.tail )
val b = myReduce(a)
Now the interesting thing of the recursive solution is how it can be used in a more general use case where you actually need to accumulate the values in some way (which is what fold is for) and still terminate early. Say that you want to add the values of a stream of ints using an add method that will "terminate" early in a way similar to || (in this case, it does not evaluate its right hand side if the left hand side is > 100):
def add(x: Int, y: => Int) = if ( x >= 100 ) x else x + y
val a : Stream[Int] = Stream.range(0, Int.MaxValue)
val b = a.foldLeft(0)(add(_, _))
The last line won't terminate, much like in your example. But you can fix it like this:
def myReduce( s: Stream[Int] ): Int = add( s.head, myReduce( s.tail ) )
val b = myReduce(a)
WARNING: there is a significant downside to this approach though: myReduce here is not tail recursive, meaning that it will blow your stack if iterating over too many elements of the stream.
Yet another solution, which does nto blow the stack, is this:
val b = a.takeWhile(_ <= 100).foldLeft(0)(_ + _)
But I fear I have gone really too far on the off topic side, so I'd better stop now.
You could use takeWhile to extract the prefix of the Stream on which you want to operate and then apply foldLeft to that.
Does anyone know how to create a lazy iterator in scala?
For example, I want to iterate through instantiating each element. After passing, I want the instance to die / be removed from memory.
If I declare an iterator like so:
val xs = Iterator(
(0 to 10000).toArray,
(0 to 10).toArray,
(0 to 10000000000).toArray)
It creates the arrays when xs is declared. This can be proven like so:
def f(name: String) = {
val x = (0 to 10000).toArray
println("f: " + name)
x
}
val xs = Iterator(f("1"),f("2"),f("3"))
which prints:
scala> val xs = Iterator(f("1"),f("2"),f("3"))
f: 1
f: 2
f: 3
xs: Iterator[Array[Int]] = non-empty iterator
Anyone have any ideas?
Streams are not suitable because elements remain in memory.
Note: I am using an Array as an example, but I want it to work with any type.
Scala collections have a view method which produces a lazy equivalent of the collection. So instead of (0 to 10000).toArray, use (0 to 10000).view. This way, there will be no array created in the memory. See also https://stackoverflow.com/a/6996166/90874, https://stackoverflow.com/a/4799832/90874, https://stackoverflow.com/a/4511365/90874 etc.
Use one of Iterator factory methods which accepts call-by-name parameter.
For your first example you can do one of this:
val xs1 = Iterator.fill(3)((0 to 10000).toArray)
val xs2 = Iterator.tabulate(3)(_ => (0 to 10000).toArray)
val xs3 = Iterator.continually((0 to 10000).toArray).take(3)
Arrays won't be allocated until you need them.
In case you need different expressions for each element, you can create separate iterators and concatenate them:
val iter = Iterator.fill(1)(f("1")) ++
Iterator.fill(1)(f("2")) ++
Iterator.fill(1)(f("3"))
I found this issue of scala: https://issues.scala-lang.org/browse/SI-4939
Seems we can define a method whose name is a number:
scala> object Foo { val 1 = 2 }
defined module Foo
But we can't invoke it:
scala> Foo.1
<console>:1: error: ';' expected but double literal found.
Foo.1
And we can invoke it inside the object:
scala> object O { val 1 = 1; def x = 1 }
defined module O
scala> O.x
res1: Int = 1
And follow will throw error:
scala> object O { val 1 = 2; def x = 1 }
defined module O
scala> O.x
scala.MatchError: 2
at O$.<init>(<console>:5)
at O$.<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
I use scalac -Xprint:typer to see the code, the val 1 = 2 part is:
<synthetic> private[this] val x$1: Unit = (2: Int(2) #unchecked) match {
case 1 => ()
}
From it, we can see the method name changed to x$1, and only can be invoked inside that object.
And the resolution of that issue is: Won't Fix
I want to know is there any reason to allow a number to be the name of a method? Is there any case we need to use a "number" method?
There is no name "1" being bound here. val 1 = 2 is a pattern-matching expression, in much the same way val (x,2) = (1,2) binds x to 1 (and would throw a MatchError if the second element were not thet same). It's allowed because there's no real reason to add a special case to forbid it; this way val pattern matching works (almost) exactly the same way as match pattern-matching.
There are usually two factors in this kind of decision:
There are many bugs in Scalac that are much higher priority, and bug fixing resources are limited. This behavior is benign and therefore low priority.
There's a long term cost to any increases in the complexity of the language specification, and the current behavior is consistent with the spec. Once things start getting special cased, there can be an avalanche effect.
It's some combination of these two.
Update. Here's what seems strange to me:
val pair = (1, 2)
object Foo
object Bar
val (1, 2) = pair // Pattern matching on constants 1 and 2
val (Foo, Bar) = pair // Pattern matching on stable ids Foo and Bar
val (foo, bar) = pair // Binds foo and bar because they are lowercase
val 1 = 1 // Pattern matching on constant 1
val Foo = 1 // *Not* pattern matching; binds Foo
If val 1 = 1 is pattern matching, then why should val Foo = 1 bind Foo rather than pattern match?
Update 2. Daniel Sobral pointed out that this is a special exception, and Martin Odersky recently wrote the same.
Here's a few examples to show how the LHS of an assignment is more than just a name:
val pair = (1, 2)
val (a1, b1) = pair // LHS of the = is a pattern
val (1, b2) = pair // okay, b2 is bound the the value 2
val (0, b3) = pair // MatchError, as 0 != 1
val a4 = 1 // okay, a4 is bound to the value 1
val 1 = 1 // okay, but useless, no names are bound
val a # 1 = 1 // well, we can bind a name to a pattern with #
val 1 = 0 // MatchError
As always, you can use backticks to escape the name. I see no problem in supporting such names – either you use them and they work for you or they do not work for you, and you don’t use them.