repeatLoop { command } until ( condition ) implementation

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

repeatLoop { command } until ( condition ) implementation

Geoffrey Lane-2
 From Scala by Example (exercise 11.2.1)

This is the solution I came up with. It's a hybrid Object/Functional  
solution:

class Repeater(command: => Unit){
     def until(condition: => Boolean)  {
         command
         if (condition) until(condition)
     }
}

def repeatLoop(command: => Unit): Repeater = {
     new Repeater(command)
}

var x = 0
repeatLoop {
     x += 1;
     println(x)
} until (x < 10)


I was interested in feedback from other Scala people. In particular I  
was curious if there was a way to do this in a "pure functional" way  
which was the first thing I tried, but wasn't successful.

Thanks for the feedback everyone.

--
Geoff Lane <[hidden email]>




Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Eastsun
        def repeatLoop(com: => Unit)(con: => Boolean){
                com
                if(con) repeatLoop(com)(con)
        }
       
        var x = 0
        repeatLoop{
                x += 1
                println(x)
        }(x<10)
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Jan Lohre
In reply to this post by Geoffrey Lane-2
You should make the until method final, otherwise your implementation will run into a stack overflow.
A subclass of Repeater could override it, hence tail call optimization does not take place.

Kind regards,
Jan

2009/4/26 Geoffrey Lane <[hidden email]>
From Scala by Example (exercise 11.2.1)

This is the solution I came up with. It's a hybrid Object/Functional solution:

class Repeater(command: => Unit){
   def until(condition: => Boolean)  {
       command
       if (condition) until(condition)
   }
}

def repeatLoop(command: => Unit): Repeater = {
   new Repeater(command)
}

var x = 0
repeatLoop {
   x += 1;
   println(x)
} until (x < 10)


I was interested in feedback from other Scala people. In particular I was curious if there was a way to do this in a "pure functional" way which was the first thing I tried, but wasn't successful.

Thanks for the feedback everyone.

--
Geoff Lane <[hidden email]>





Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Paul Phillips-3
In reply to this post by Geoffrey Lane-2
On Sun, Apr 26, 2009 at 10:20:38AM -0500, Geoffrey Lane wrote:
> I was interested in feedback from other Scala people. In particular I
> was curious if there was a way to do this in a "pure functional" way
> which was the first thing I tried, but wasn't successful.

Without asserting this is purely functional, and using the earlier
syntax (so it's like a while loop, not a do/while loop.)

scala>   def repeatLoop[T](command: => T)(condition: => Boolean) =
  Stream.const(() => command).map(_.apply()).takeWhile(_ => condition).force
repeatLoop: [T](=> T)(=> Boolean)List[T]

scala> var x = 0
x: Int = 0

scala> repeatLoop {
     |     x += 1;
     |     println(x)
     | } (x < 10)
1
2
3
4
5
6
7
8
9
10

--
Paul Phillips      | Every normal man must be tempted at times
Future Perfect     | to spit on his hands, hoist the black flag,
Empiricist         | and begin to slit throats.
i'll ship a pulp   |     -- H. L. Mencken
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Landei
In reply to this post by Geoffrey Lane-2

Geoffrey Lane-2 wrote
 From Scala by Example (exercise 11.2.1)

This is the solution I came up with. It's a hybrid Object/Functional  
solution:

class Repeater(command: => Unit){
     def until(condition: => Boolean)  {
         command
         if (condition) until(condition)
     }
}

def repeatLoop(command: => Unit): Repeater = {
     new Repeater(command)
}

var x = 0
repeatLoop {
     x += 1;
     println(x)
} until (x < 10)


I was interested in feedback from other Scala people. In particular I  
was curious if there was a way to do this in a "pure functional" way  
which was the first thing I tried, but wasn't successful.

Thanks for the feedback everyone.

--
Geoff Lane <geoff@zorched.net>
Hi Geoffrey,

if you want to have the "until", you need an object. How about this slightly less verbose version:

def repeat(body: => Unit) = new {
   def until(condition: => Boolean) {
       body
       while(! condition) body
   }
}

BTW: There is nothing wrong with while, and (as already pointed out) it can be tricky to get tail recursion right. (There is a new annotation "@tailrec" for checking this)

Cheers,
Daniel
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Geoffrey Lane-2
Ok, that was the answer I wanted.
The until could be thought of as "flavor" syntax, but the example  
asked to implement that until syntax. It sort of gets into the DSL  
mode of extending the syntax of the language, so I thought it was a  
good exercise.


On Apr 26, 2009, at 11:35 AM, Landei wrote:

>
>
>
> Geoffrey Lane-2 wrote:
>>
>> From Scala by Example (exercise 11.2.1)
>>
>> This is the solution I came up with. It's a hybrid Object/Functional
>> solution:
>>
>> class Repeater(command: => Unit){
>>     def until(condition: => Boolean)  {
>>         command
>>         if (condition) until(condition)
>>     }
>> }
>>
>> def repeatLoop(command: => Unit): Repeater = {
>>     new Repeater(command)
>> }
>>
>> var x = 0
>> repeatLoop {
>>     x += 1;
>>     println(x)
>> } until (x < 10)
>>
>>
>> I was interested in feedback from other Scala people. In particular I
>> was curious if there was a way to do this in a "pure functional" way
>> which was the first thing I tried, but wasn't successful.
>>
>> Thanks for the feedback everyone.
>>
>> --
>> Geoff Lane <[hidden email]>
>>
>
> Hi Geoffrey,
>
> if you want to have the "until", you need an object. How about this  
> slightly
> less verbose version:
>
> def repeat(body: => Unit) = new {
>   def until(condition: => Boolean) {
>       body
>       while(! condition) body
>   }
> }
>
> BTW: There is nothing wrong with while, and (as already pointed out)  
> it can
> be tricky to get tail recursion right. (There is a new annotation  
> "@tailrec"
> for checking this)
>
> Cheers,
> Daniel
> --
> View this message in context: http://www.nabble.com/repeatLoop-%7B-command-%7D-until-%28-condition-%29--implementation-tp23243207p23243875.html
> Sent from the Scala - User mailing list archive at Nabble.com.
>

--
Geoff Lane <[hidden email]>




Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Geoffrey Lane-2
In reply to this post by Jan Lohre
Is the final part (for tail calls) only relevant to methods and not standalone functions I assume?


On Apr 26, 2009, at 11:16 AM, Jan Lohre wrote:

You should make the until method final, otherwise your implementation will run into a stack overflow.
A subclass of Repeater could override it, hence tail call optimization does not take place.

Kind regards,
Jan

2009/4/26 Geoffrey Lane <[hidden email]>
>From Scala by Example (exercise 11.2.1)

This is the solution I came up with. It's a hybrid Object/Functional solution:

class Repeater(command: => Unit){
   def until(condition: => Boolean)  {
       command
       if (condition) until(condition)
   }
}

def repeatLoop(command: => Unit): Repeater = {
   new Repeater(command)
}

var x = 0
repeatLoop {
   x += 1;
   println(x)
} until (x < 10)


I was interested in feedback from other Scala people. In particular I was curious if there was a way to do this in a "pure functional" way which was the first thing I tried, but wasn't successful.

Thanks for the feedback everyone.

--
Geoff Lane <[hidden email]>






-- 
Geoff Lane <[hidden email]>




Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Grant Rettke
In reply to this post by Geoffrey Lane-2
On Sun, Apr 26, 2009 at 10:20 AM, Geoffrey Lane <[hidden email]> wrote:
> class Repeater(command: => Unit){
>    def until(condition: => Boolean)  {
>        command
>        if (condition) until(condition)
>    }
> }

This isn't a tail call though is it?
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Rich Dougherty
In reply to this post by Geoffrey Lane-2
Yes, only to methods. To do tail-call optimisation, the compiler needs
to rewrite the code and it's not safe to do that if the code could be
overridden. Neither final methods nor (any) standalone function can be
overridden.

Rich

On Mon, Apr 27, 2009 at 5:03 AM, Geoffrey Lane <[hidden email]> wrote:

> Is the final part (for tail calls) only relevant to methods and not
> standalone functions I assume?
>
> On Apr 26, 2009, at 11:16 AM, Jan Lohre wrote:
>
> You should make the until method final, otherwise your implementation will
> run into a stack overflow.
> A subclass of Repeater could override it, hence tail call optimization does
> not take place.
>
> Kind regards,
> Jan
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Rich Dougherty
In reply to this post by Grant Rettke
On Mon, Apr 27, 2009 at 6:40 AM, Grant Rettke <[hidden email]> wrote:
> On Sun, Apr 26, 2009 at 10:20 AM, Geoffrey Lane <[hidden email]> wrote:
>> class Repeater(command: => Unit){
>>    def until(condition: => Boolean)  {
>>        command
>>        if (condition) until(condition)
>>    }
>> }
>
> This isn't a tail call though is it?

I think it is. You could check by (1) executing the code 10000 times,
(2) inspecting the bytecode or (3) putting @tailrec before the def to
assert that tail-call optimisation occurs. (But you'd need a 2.8
nightly build to do the last.)

Rich
--
http://blog.richdougherty.com/
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Grant Rettke
On Sun, Apr 26, 2009 at 2:21 PM, Rich Dougherty <[hidden email]> wrote:
> On Mon, Apr 27, 2009 at 6:40 AM, Grant Rettke <[hidden email]> wrote:
>> This isn't a tail call though is it?
>
> I think it is. You could check by (1) executing the code 10000 times,

On my machine with Scala 2.7.3 it took 10586 stacks to blow it up.
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Paul Phillips-3
On Sun, Apr 26, 2009 at 02:57:13PM -0500, Grant Rettke wrote:
> On my machine with Scala 2.7.3 it took 10586 stacks to blow it up.

I think we must have different definitions of blow up.  Do you perhaps
mean it literally, like your machine actually exploded? Scala may well
boast that sort of power but I don't think it's to blame in this case.

--
Paul Phillips      | A Sunday school is a prison in which children do
Imperfectionist    | penance for the evil conscience of their parents.
Empiricist         |     -- H. L. Mencken
pal, i pill push   |----------* http://www.improving.org/paulp/ *----------
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

David MacIver
2009/4/26 Paul Phillips <[hidden email]>:
> On Sun, Apr 26, 2009 at 02:57:13PM -0500, Grant Rettke wrote:
>> On my machine with Scala 2.7.3 it took 10586 stacks to blow it up.
>
> I think we must have different definitions of blow up.  Do you perhaps
> mean it literally, like your machine actually exploded? Scala may well
> boast that sort of power but I don't think it's to blame in this case.

Note that the behaviour here is different between trunk and 2.7.x.
This will be recognised as a tail call in trunk, but it won't in 2.7.3
Reply | Threaded
Open this post in threaded view
|

Re: repeatLoop { command } until ( condition ) implementation

Paul Phillips-3
On Sun, Apr 26, 2009 at 09:44:00PM +0100, David MacIver wrote:
> Note that the behaviour here is different between trunk and 2.7.x.
> This will be recognised as a tail call in trunk, but it won't in 2.7.3

That'd normally be the right conclusion about where I went off the beam,
but I tested this in 2.7.3 before I emailed.  Turns out it takes 347070
recursions to blow the stack on my wimpy laptop.  That's what you get
for overdoing JAVA_OPTS.

--
Paul Phillips      | It is hard to believe that a man is
Protagonist        | telling the truth when you know that you
Empiricist         | would lie if you were in his place.
all hip pupils!    |     -- H. L. Mencken