- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
reading from console
Mon, 2009-02-16, 02:03
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
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
Mon, 2009-02-16, 09:47
#2
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
>
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
>
Mon, 2009-02-16, 15:07
#3
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>
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
>
Mon, 2009-02-16, 15:17
#4
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>
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
>
Mon, 2009-02-16, 15:57
#5
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:
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
>
Mon, 2009-02-16, 16:17
#6
Re: reading from console
This gives some flexibility in implementation. LINQ does the same thing.
2009/2/16 Szymon Jachim <sjachim@gmail.com>
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
>
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(...))
}