This page is no longer maintained — Please continue to the home page at www.scala-lang.org

reading from console

6 replies
Ishaaq Chandy
Joined: 2009-02-16,
User offline. Last seen 42 years 45 weeks ago.
Hi guys,
After a number of false starts - I've decided to learn scala the best way I know - write a real application with it.

Perhaps foolishly, I've also decided to try and wean myself off of mutable types - as far as possible I want to avoid vars and only deal in vals.

Unsurprisingly enough, I've hit a brick wall at the first step.

It is a simple enough problem if I could use vars: in my app I need to have a loop that reads a line of user-input from the console and does something with it. I've implemented the loop as a for loop over an Iterator[String]. The iterator is an instance of a class I've written that reads from the console. My problem is that my iterator must have two significant methods:
next(): String
and
hasNext(): Boolean

I can figure out how to write the next() method without resorting to using vars but am stumped as to how to implement hasNext(). hasNext() has to be implemented in such a way as to terminate the session if the user types in CTRL-D, CTRL-C or "quit".

I peeked into the source code for the scala interpreter to see how they did it - but it looks like they've cheated (or more realisticly - they didn't care about making it immutable) - they are using vars.

Any ideas? I have a feeling I need to understand monads to be able to do this - but I have no idea where to start.

Regards,
Ishaaq
sadie
Joined: 2008-12-21,
User offline. Last seen 42 years 45 weeks ago.
Re: re ading from console

Are you sure that Iterator[String] is the right approach? Does your code need
to interact with Java code? If not, you may get better results by using a
more Scala-esque Seq[String] or Stream[String]. Streams are a little fiddly
to use, but let you lazily produce values.

def getStuff: Seq[String] = {
val firstItem = getItem(...)
Stream.cons(firstItem, getItem(...))
}

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: reading from console
Perhaps you'd be better implementing a foreach method instead of actually extending Iterator.

ricky@ricky-desktop:~$ scala
Welcome to Scala version 2.8.0.r17079-b20090210164824 (Java HotSpot(TM) Client VM, Java 1.6.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.io._
import java.io._

scala> case class NoVar(reader: BufferedReader) {
       def foreach(action: String => Unit) { reader.readLine match { case null =>
                                                                     case s => action(s)
                                                                               foreach(action) } }
}
defined class NoVar

scala> for (line <- NoVar(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(List('a', 'b', '\n', 'c', 'd') map (_ toByte) toArray), "ASCII")))) println(line)
ab
cd

scala>

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>:
> Hi guys,
> After a number of false starts - I've decided to learn scala the best way I
> know - write a real application with it.
>
> Perhaps foolishly, I've also decided to try and wean myself off of mutable
> types - as far as possible I want to avoid vars and only deal in vals.
>
> Unsurprisingly enough, I've hit a brick wall at the first step.
>
> It is a simple enough problem if I could use vars: in my app I need to have
> a loop that reads a line of user-input from the console and does something
> with it. I've implemented the loop as a for loop over an Iterator[String].
> The iterator is an instance of a class I've written that reads from the
> console. My problem is that my iterator must have two significant methods:
> next(): String
> and
> hasNext(): Boolean
>
> I can figure out how to write the next() method without resorting to using
> vars but am stumped as to how to implement hasNext(). hasNext() has to be
> implemented in such a way as to terminate the session if the user types in
> CTRL-D, CTRL-C or "quit".
>
> I peeked into the source code for the scala interpreter to see how they did
> it - but it looks like they've cheated (or more realisticly - they didn't
> care about making it immutable) - they are using vars.
>
> Any ideas? I have a feeling I need to understand monads to be able to do
> this - but I have no idea where to start.
>
> Regards,
> Ishaaq
>

Ishaaq Chandy
Joined: 2009-02-16,
User offline. Last seen 42 years 45 weeks ago.
Re: reading from console
Perfect! Didn't realise that simply declaring a foreach method like that makes any arbitrary class available for iterating via a for-expression. Very cool.

Thanks for that.

Ishaaq

2009/2/16 Ricky Clarkson <ricky.clarkson@gmail.com>
Perhaps you'd be better implementing a foreach method instead of actually extending Iterator.

ricky@ricky-desktop:~$ scala
Welcome to Scala version 2.8.0.r17079-b20090210164824 (Java HotSpot(TM) Client VM, Java 1.6.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.io._
import java.io._

scala> case class NoVar(reader: BufferedReader) {
       def foreach(action: String => Unit) { reader.readLine match { case null =>
                                                                     case s => action(s)
                                                                               foreach(action) } }
}
defined class NoVar

scala> for (line <- NoVar(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(List('a', 'b', '\n', 'c', 'd') map (_ toByte) toArray), "ASCII")))) println(line)
ab
cd

scala>

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>:
> Hi guys,
> After a number of false starts - I've decided to learn scala the best way I
> know - write a real application with it.
>
> Perhaps foolishly, I've also decided to try and wean myself off of mutable
> types - as far as possible I want to avoid vars and only deal in vals.
>
> Unsurprisingly enough, I've hit a brick wall at the first step.
>
> It is a simple enough problem if I could use vars: in my app I need to have
> a loop that reads a line of user-input from the console and does something
> with it. I've implemented the loop as a for loop over an Iterator[String].
> The iterator is an instance of a class I've written that reads from the
> console. My problem is that my iterator must have two significant methods:
> next(): String
> and
> hasNext(): Boolean
>
> I can figure out how to write the next() method without resorting to using
> vars but am stumped as to how to implement hasNext(). hasNext() has to be
> implemented in such a way as to terminate the session if the user types in
> CTRL-D, CTRL-C or "quit".
>
> I peeked into the source code for the scala interpreter to see how they did
> it - but it looks like they've cheated (or more realisticly - they didn't
> care about making it immutable) - they are using vars.
>
> Any ideas? I have a feeling I need to understand monads to be able to do
> this - but I have no idea where to start.
>
> Regards,
> Ishaaq
>


Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: reading from console
No problem.  Note that you'll need flatMap and filter (and map?) to be implemented for more interesting features of for-comprehensions.

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>
Perfect! Didn't realise that simply declaring a foreach method like that makes any arbitrary class available for iterating via a for-expression. Very cool.

Thanks for that.

Ishaaq

2009/2/16 Ricky Clarkson <ricky.clarkson@gmail.com>
Perhaps you'd be better implementing a foreach method instead of actually extending Iterator.

ricky@ricky-desktop:~$ scala
Welcome to Scala version 2.8.0.r17079-b20090210164824 (Java HotSpot(TM) Client VM, Java 1.6.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.io._
import java.io._

scala> case class NoVar(reader: BufferedReader) {
       def foreach(action: String => Unit) { reader.readLine match { case null =>
                                                                     case s => action(s)
                                                                               foreach(action) } }
}
defined class NoVar

scala> for (line <- NoVar(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(List('a', 'b', '\n', 'c', 'd') map (_ toByte) toArray), "ASCII")))) println(line)
ab
cd

scala>

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>:
> Hi guys,
> After a number of false starts - I've decided to learn scala the best way I
> know - write a real application with it.
>
> Perhaps foolishly, I've also decided to try and wean myself off of mutable
> types - as far as possible I want to avoid vars and only deal in vals.
>
> Unsurprisingly enough, I've hit a brick wall at the first step.
>
> It is a simple enough problem if I could use vars: in my app I need to have
> a loop that reads a line of user-input from the console and does something
> with it. I've implemented the loop as a for loop over an Iterator[String].
> The iterator is an instance of a class I've written that reads from the
> console. My problem is that my iterator must have two significant methods:
> next(): String
> and
> hasNext(): Boolean
>
> I can figure out how to write the next() method without resorting to using
> vars but am stumped as to how to implement hasNext(). hasNext() has to be
> implemented in such a way as to terminate the session if the user types in
> CTRL-D, CTRL-C or "quit".
>
> I peeked into the source code for the scala interpreter to see how they did
> it - but it looks like they've cheated (or more realisticly - they didn't
> care about making it immutable) - they are using vars.
>
> Any ideas? I have a feeling I need to understand monads to be able to do
> this - but I have no idea where to start.
>
> Regards,
> Ishaaq
>



Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: reading from console
Interesting that Scala frequently uses structural typing to support language contructs instead of requiring the user to implement e.g. special kinds of traits. That's great becouse even in reallife "what is it?" is more important than "what is it's label?"
Obviously it doesn't apply to politics... ;-)

Szymon

On Mon, Feb 16, 2009 at 2:56 PM, Ishaaq Chandy <ishaaq@gmail.com> wrote:
Perfect! Didn't realise that simply declaring a foreach method like that makes any arbitrary class available for iterating via a for-expression. Very cool.

Thanks for that.

Ishaaq

2009/2/16 Ricky Clarkson <ricky.clarkson@gmail.com>
Perhaps you'd be better implementing a foreach method instead of actually extending Iterator.

ricky@ricky-desktop:~$ scala
Welcome to Scala version 2.8.0.r17079-b20090210164824 (Java HotSpot(TM) Client VM, Java 1.6.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.io._
import java.io._

scala> case class NoVar(reader: BufferedReader) {
       def foreach(action: String => Unit) { reader.readLine match { case null =>
                                                                     case s => action(s)
                                                                               foreach(action) } }
}
defined class NoVar

scala> for (line <- NoVar(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(List('a', 'b', '\n', 'c', 'd') map (_ toByte) toArray), "ASCII")))) println(line)
ab
cd

scala>

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>:
> Hi guys,
> After a number of false starts - I've decided to learn scala the best way I
> know - write a real application with it.
>
> Perhaps foolishly, I've also decided to try and wean myself off of mutable
> types - as far as possible I want to avoid vars and only deal in vals.
>
> Unsurprisingly enough, I've hit a brick wall at the first step.
>
> It is a simple enough problem if I could use vars: in my app I need to have
> a loop that reads a line of user-input from the console and does something
> with it. I've implemented the loop as a for loop over an Iterator[String].
> The iterator is an instance of a class I've written that reads from the
> console. My problem is that my iterator must have two significant methods:
> next(): String
> and
> hasNext(): Boolean
>
> I can figure out how to write the next() method without resorting to using
> vars but am stumped as to how to implement hasNext(). hasNext() has to be
> implemented in such a way as to terminate the session if the user types in
> CTRL-D, CTRL-C or "quit".
>
> I peeked into the source code for the scala interpreter to see how they did
> it - but it looks like they've cheated (or more realisticly - they didn't
> care about making it immutable) - they are using vars.
>
> Any ideas? I have a feeling I need to understand monads to be able to do
> this - but I have no idea where to start.
>
> Regards,
> Ishaaq
>



Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: reading from console
This gives some flexibility in implementation.  LINQ does the same thing.

2009/2/16 Szymon Jachim <sjachim@gmail.com>
Interesting that Scala frequently uses structural typing to support language contructs instead of requiring the user to implement e.g. special kinds of traits. That's great becouse even in reallife "what is it?" is more important than "what is it's label?"
Obviously it doesn't apply to politics... ;-)

Szymon

On Mon, Feb 16, 2009 at 2:56 PM, Ishaaq Chandy <ishaaq@gmail.com> wrote:
Perfect! Didn't realise that simply declaring a foreach method like that makes any arbitrary class available for iterating via a for-expression. Very cool.

Thanks for that.

Ishaaq

2009/2/16 Ricky Clarkson <ricky.clarkson@gmail.com>
Perhaps you'd be better implementing a foreach method instead of actually extending Iterator.

ricky@ricky-desktop:~$ scala
Welcome to Scala version 2.8.0.r17079-b20090210164824 (Java HotSpot(TM) Client VM, Java 1.6.0_11).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import java.io._
import java.io._

scala> case class NoVar(reader: BufferedReader) {
       def foreach(action: String => Unit) { reader.readLine match { case null =>
                                                                     case s => action(s)
                                                                               foreach(action) } }
}
defined class NoVar

scala> for (line <- NoVar(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(List('a', 'b', '\n', 'c', 'd') map (_ toByte) toArray), "ASCII")))) println(line)
ab
cd

scala>

2009/2/16 Ishaaq Chandy <ishaaq@gmail.com>:
> Hi guys,
> After a number of false starts - I've decided to learn scala the best way I
> know - write a real application with it.
>
> Perhaps foolishly, I've also decided to try and wean myself off of mutable
> types - as far as possible I want to avoid vars and only deal in vals.
>
> Unsurprisingly enough, I've hit a brick wall at the first step.
>
> It is a simple enough problem if I could use vars: in my app I need to have
> a loop that reads a line of user-input from the console and does something
> with it. I've implemented the loop as a for loop over an Iterator[String].
> The iterator is an instance of a class I've written that reads from the
> console. My problem is that my iterator must have two significant methods:
> next(): String
> and
> hasNext(): Boolean
>
> I can figure out how to write the next() method without resorting to using
> vars but am stumped as to how to implement hasNext(). hasNext() has to be
> implemented in such a way as to terminate the session if the user types in
> CTRL-D, CTRL-C or "quit".
>
> I peeked into the source code for the scala interpreter to see how they did
> it - but it looks like they've cheated (or more realisticly - they didn't
> care about making it immutable) - they are using vars.
>
> Any ideas? I have a feeling I need to understand monads to be able to do
> this - but I have no idea where to start.
>
> Regards,
> Ishaaq
>




Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland