- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: 5 times println
Sat, 2009-08-29, 13:28
On Sat, Aug 29, 2009 at 10:09:40AM +0200, Martin Odersky wrote:
> So far I resister putting times into richint, mainly because it is
> imperative and not that much shorter than
>
> for (_ <- 1 to 3) println()
It isn't that it's shorter (although that's nice) but that it's much
faster.
I will polish the benchmark and send the numbers today. I am sure we'd
all like to reduce the number of places where we're forced to choose
between clean code and performance.
Sat, 2009-08-29, 14:37
#2
Re: 5 times println
On Sat, Aug 29, 2009 at 2:19 PM, Paul Phillips wrote:
> As things are now every time the need to do this arises it feels like I
> have to make an unnecessary compromise, because none of the available
> options have a comparable speed+clarity+convenience sum. If it's not in
> Predef or a conversion from Int, the import tax dominates the cost.
I have no particularly strong opinions on this either way. Still, I
can't shift the feeling that the occasions where I need to loop
imperatively and fast are all ones where I need the loop counter
available in the body ... what are the compelling examples of
scenarios where that's not the case?
Cheers,
Miles
Sat, 2009-08-29, 16:27
#3
Re: 5 times println
Hi Paul,
On Sat, Aug 29, 2009 at 6:19 AM, Paul Phillips wrote:
> OK, I'm no professional benchmarker so I trust someone will let me know
> if there's some huge flaw here. Every way I tried out yielded about the
> same results, summarized in these:
>
> Accumulated time after 100 iterations:
> iterator: 6709
> range: 5856
> while loop: 4611
> rich int: 4845
>
> So looking at these two approaches:
>
> 5 times println
> for (_ <- 1 to 5) println
>
> Here are the advantages for 1:
>
> 1) About 20% faster.
> 2) Less accidental complexity. Is it "to" or "until" ? Why do
> I have to explicitly discard the counter? Why am I naming
> two numbers when my intention is fully expressed by one?
> 3) Shorter.
>
> The arguments against seem much less convincing to me. It's imperative,
> and so is everything else which returns Unit.
>
> If not a method on RichInt, then I would be equally happy with a method
> in Predef, like
>
> def repeat(n: Int)(body: => Unit)
>
> As things are now every time the need to do this arises it feels like I
> have to make an unnecessary compromise, because none of the available
> options have a comparable speed+clarity+convenience sum. If it's not in
> Predef or a conversion from Int, the import tax dominates the cost.
>
Isn't the import tax pretty cheap these days? And that way everyone
can have whatever syntax they want for this. Stick it in a Utils.scala
and import and use whatever syntax you want.
By the way, as far as 20% faster goes, even if that's true this will
only matter if that loop happens to be in a time critical part of your
program. Most code is not, and if there were ever a performance
bottleneck, people could switch to a while loop to speed it up if that
helped. I do like that it is shorter to type and look at. But unless
I'm forgetting I only very rarely need to do some side effect N times
where I don't need indexes. Lastly, I certainly would rather it not be
called "times", because that is already going to break code in two
libraries that are getting used by people, and seems like a useful
word to keep available for DSL designers to let people add to Ints. I
had thought of the same "repeat" form you suggested, but that's also
not very satisfying. One other idea is loop or loops:
5 loops { println("hi") }
Instead of a for loop its a 5 loop. However, if most people are luke
warm to the idea, it is probably best to just leave anything of this
form out of 2.8. I can always be added later, but can't easily be
subtracted.
Bill
> The benchmark I used is here: http://paste.pocoo.org/show/136941/
>
> --
> Paul Phillips | Before a man speaks it is always safe to assume
> Everyman | that he is a fool. After he speaks, it is seldom
> Empiricist | necessary to assume it.
> pull his pi pal! | -- H. L. Mencken
>
Sat, 2009-08-29, 17:37
#4
Re: 5 times println
On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
> Isn't the import tax pretty cheap these days? And that way everyone
> can have whatever syntax they want for this. Stick it in a Utils.scala
> and import and use whatever syntax you want.
I am working only on the standard library and compiler, and developing
accordingly. I realize everyone can write their own tools and import
them everywhere, but the point of having a good standard library is that
they don't have to. I'm not checking in my suite of private tools here,
I'm checking in things I have every reason to believe are in demand.
Your argument above is unconvincing to me because you could say it about
anything. The impact of the import tax is basically a function of how
the fixed cost of the import compares to the savings. In situations
like this, the import tax dominates, just as it does when you're trying
to decide whether a method should take "Seq" or "collection.Traversable".
I can tell you that I hear about people wanting times all the time, near
the absolute top of the list for simple additions. But if nobody cares
enough to chip in here with their specific use cases, I have plenty of
other stuff to worry about.
Sat, 2009-08-29, 18:17
#5
Re: 5 times println
On Sat, Aug 29, 2009 at 5:31 PM, Paul Phillips wrote:
> I can tell you that I hear about people wanting times all the time, near
> the absolute top of the list for simple additions.
Maybe we need to port this from Haskell,
http://sc.tri-bit.com/images/2/23/pony.jpg
Cheers,
Miles
Sat, 2009-08-29, 18:27
#6
Re: 5 times println
Hi Paul,
On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips wrote:
> On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> Isn't the import tax pretty cheap these days? And that way everyone
>> can have whatever syntax they want for this. Stick it in a Utils.scala
>> and import and use whatever syntax you want.
>
> I am working only on the standard library and compiler, and developing
> accordingly. I realize everyone can write their own tools and import
> them everywhere, but the point of having a good standard library is that
> they don't have to. I'm not checking in my suite of private tools here,
> I'm checking in things I have every reason to believe are in demand.
>
> Your argument above is unconvincing to me because you could say it about
> anything. The impact of the import tax is basically a function of how
> the fixed cost of the import compares to the savings. In situations
> like this, the import tax dominates, just as it does when you're trying
> to decide whether a method should take "Seq" or "collection.Traversable".
>
> I can tell you that I hear about people wanting times all the time, near
> the absolute top of the list for simple additions. But if nobody cares
> enough to chip in here with their specific use cases, I have plenty of
> other stuff to worry about.
>
Where are these requests coming from? I just searched my codebase for
ScalaTest and there isn't a single place where I have needed it.
To Vlad's comment I'd agree in general that the standard library
should get first shot at the best syntax. But I'd balance that with
the need to avoid code breakage. I don't know that there's much code
that would break at this point with "times," but it is already in use
by a library that Scala programmers use. Search for "times" on this
page and you'll see it:
http://code.google.com/p/specs/wiki/UsingMockito
My use of times isn't released yet, so it wouldn't break code of
ScalaTest users because I still have time to adjust.
Neverthless, the attitude that the standard library is the only thing
you need to consider when adding things to the standard library
neglects that you need to consider the extent to which each addition
will break code. Today there few enough users of Scala that breaking
changes that will be big improvements should still be added. Moreover,
everyone using Scala today is aware that 2.8 will likely break their
code, and everyone seems to want the language and library to be
improved as much as possible now while Scala is still at the early
adopter stage. But even now I think it is important to be
conservative. Things that are added that may break code, and that
includes any addition to Predef, must really be carefully considered
and carry their weight.
You're not done when you can't think of anything else to add. You're
done when you can't think of anything else to take out.
Bill
> --
> Paul Phillips | Every election is a sort of advance auction sale
> Stickler | of stolen goods.
> Empiricist | -- H. L. Mencken
> i pull his palp! |----------* http://www.improving.org/paulp/ *----------
>
Sat, 2009-08-29, 18:57
#7
Re: 5 times println
Bill,
I'd be interested to see your intended use of `times`.
Ricky.
2009/8/29 Bill Venners :
> Hi Paul,
>
> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips wrote:
>> On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>>> Isn't the import tax pretty cheap these days? And that way everyone
>>> can have whatever syntax they want for this. Stick it in a Utils.scala
>>> and import and use whatever syntax you want.
>>
>> I am working only on the standard library and compiler, and developing
>> accordingly. I realize everyone can write their own tools and import
>> them everywhere, but the point of having a good standard library is that
>> they don't have to. I'm not checking in my suite of private tools here,
>> I'm checking in things I have every reason to believe are in demand.
>>
>> Your argument above is unconvincing to me because you could say it about
>> anything. The impact of the import tax is basically a function of how
>> the fixed cost of the import compares to the savings. In situations
>> like this, the import tax dominates, just as it does when you're trying
>> to decide whether a method should take "Seq" or "collection.Traversable".
>>
>> I can tell you that I hear about people wanting times all the time, near
>> the absolute top of the list for simple additions. But if nobody cares
>> enough to chip in here with their specific use cases, I have plenty of
>> other stuff to worry about.
>>
> Where are these requests coming from? I just searched my codebase for
> ScalaTest and there isn't a single place where I have needed it.
>
> To Vlad's comment I'd agree in general that the standard library
> should get first shot at the best syntax. But I'd balance that with
> the need to avoid code breakage. I don't know that there's much code
> that would break at this point with "times," but it is already in use
> by a library that Scala programmers use. Search for "times" on this
> page and you'll see it:
>
> http://code.google.com/p/specs/wiki/UsingMockito
>
> My use of times isn't released yet, so it wouldn't break code of
> ScalaTest users because I still have time to adjust.
>
> Neverthless, the attitude that the standard library is the only thing
> you need to consider when adding things to the standard library
> neglects that you need to consider the extent to which each addition
> will break code. Today there few enough users of Scala that breaking
> changes that will be big improvements should still be added. Moreover,
> everyone using Scala today is aware that 2.8 will likely break their
> code, and everyone seems to want the language and library to be
> improved as much as possible now while Scala is still at the early
> adopter stage. But even now I think it is important to be
> conservative. Things that are added that may break code, and that
> includes any addition to Predef, must really be carefully considered
> and carry their weight.
>
> You're not done when you can't think of anything else to add. You're
> done when you can't think of anything else to take out.
>
> Bill
>
>> --
>> Paul Phillips | Every election is a sort of advance auction sale
>> Stickler | of stolen goods.
>> Empiricist | -- H. L. Mencken
>> i pull his palp! |----------* http://www.improving.org/paulp/ *----------
>>
>
>
>
> --
> Bill Venners
> Artima, Inc.
> http://www.artima.com
>
Sat, 2009-08-29, 19:07
#8
Re: 5 times println
I'm on the fence here. I think the scala standard library should be as good as possible, and I can't wait to use a lot of the things Paul has been adding. I'm on the fence about times however as it's not amazing to me either way. I think it could help swing groovy people over when they (meaning my coworker) ask "Where's your times method? Groovy has that!". To which I want to respond "What production code do you use times in?". My coworker has no response, perhaps neither do many people? You see, these amps go to 11.
On general principles, I think the scala library should be cautious about what methods it places on globaly used things (like primitives), but I also think it takes precedence over third-party libraries (including my own!).
I'd rather see Specs and Scalatest help define the times method on the scala-library such that their use still makes sense (or they can co-exist). I believe you can somewhat get around these issues by places the DSL language before integer (and therefore not rely on integer implicit conversions).
e.g.
The Specs use of times could be combined with the standard library, or prefixed with e.g. "mock it"
scala> object mock {
| def it(n : Int) = new {
| def times[A](f : Int => A) {
| var i = 0 //This would be a real implementation
| while(i < n) {
| f(i + 1)
| i += 1
| }
| }
| }
| }
defined module mock
scala> mock it 5 times { i => println(i) }
1
2
3
4
5
Anyway, I don't mind the times function being added either way. I think it may be useful if in scala, it takes a (Int => A) and ( => A), so users who want to know what iteration they are on can find out.
- Josh
On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners <bill@artima.com> wrote:
On general principles, I think the scala library should be cautious about what methods it places on globaly used things (like primitives), but I also think it takes precedence over third-party libraries (including my own!).
I'd rather see Specs and Scalatest help define the times method on the scala-library such that their use still makes sense (or they can co-exist). I believe you can somewhat get around these issues by places the DSL language before integer (and therefore not rely on integer implicit conversions).
e.g.
The Specs use of times could be combined with the standard library, or prefixed with e.g. "mock it"
scala> object mock {
| def it(n : Int) = new {
| def times[A](f : Int => A) {
| var i = 0 //This would be a real implementation
| while(i < n) {
| f(i + 1)
| i += 1
| }
| }
| }
| }
defined module mock
scala> mock it 5 times { i => println(i) }
1
2
3
4
5
Anyway, I don't mind the times function being added either way. I think it may be useful if in scala, it takes a (Int => A) and ( => A), so users who want to know what iteration they are on can find out.
- Josh
On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners <bill@artima.com> wrote:
Hi Paul,
On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips<paulp@improving.org> wrote:
> On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> Isn't the import tax pretty cheap these days? And that way everyone
>> can have whatever syntax they want for this. Stick it in a Utils.scala
>> and import and use whatever syntax you want.
>
> I am working only on the standard library and compiler, and developing
> accordingly. I realize everyone can write their own tools and import
> them everywhere, but the point of having a good standard library is that
> they don't have to. I'm not checking in my suite of private tools here,
> I'm checking in things I have every reason to believe are in demand.
>
> Your argument above is unconvincing to me because you could say it about
> anything. The impact of the import tax is basically a function of how
> the fixed cost of the import compares to the savings. In situations
> like this, the import tax dominates, just as it does when you're trying
> to decide whether a method should take "Seq" or "collection.Traversable".
>
> I can tell you that I hear about people wanting times all the time, near
> the absolute top of the list for simple additions. But if nobody cares
> enough to chip in here with their specific use cases, I have plenty of
> other stuff to worry about.
>
Where are these requests coming from? I just searched my codebase for
ScalaTest and there isn't a single place where I have needed it.
To Vlad's comment I'd agree in general that the standard library
should get first shot at the best syntax. But I'd balance that with
the need to avoid code breakage. I don't know that there's much code
that would break at this point with "times," but it is already in use
by a library that Scala programmers use. Search for "times" on this
page and you'll see it:
http://code.google.com/p/specs/wiki/UsingMockito
My use of times isn't released yet, so it wouldn't break code of
ScalaTest users because I still have time to adjust.
Neverthless, the attitude that the standard library is the only thing
you need to consider when adding things to the standard library
neglects that you need to consider the extent to which each addition
will break code. Today there few enough users of Scala that breaking
changes that will be big improvements should still be added. Moreover,
everyone using Scala today is aware that 2.8 will likely break their
code, and everyone seems to want the language and library to be
improved as much as possible now while Scala is still at the early
adopter stage. But even now I think it is important to be
conservative. Things that are added that may break code, and that
includes any addition to Predef, must really be carefully considered
and carry their weight.
You're not done when you can't think of anything else to add. You're
done when you can't think of anything else to take out.
Bill
> --
> Paul Phillips | Every election is a sort of advance auction sale
> Stickler | of stolen goods.
> Empiricist | -- H. L. Mencken
> i pull his palp! |----------* http://www.improving.org/paulp/ *----------
>
--
Bill Venners
Artima, Inc.
http://www.artima.com
Sat, 2009-08-29, 19:17
#9
Re: 5 times println
Hi Ricky,
This is how you verify that a method was called exactly three times
when using the Mockito API directly:
verify(mockClown, times(3)).hasBigRedNose
My hope was to be able to offer this syntax in a MockitoSugar trait:
mockClown.hasBigRedNose was invoked (3 times)
If a times method is added to RichInt, then this code would no longer
compile in 2.8.
Bill
On Sat, Aug 29, 2009 at 10:52 AM, Ricky
Clarkson wrote:
> Bill,
>
> I'd be interested to see your intended use of `times`.
>
> Ricky.
>
> 2009/8/29 Bill Venners :
>> Hi Paul,
>>
>> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips wrote:
>>> On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>>>> Isn't the import tax pretty cheap these days? And that way everyone
>>>> can have whatever syntax they want for this. Stick it in a Utils.scala
>>>> and import and use whatever syntax you want.
>>>
>>> I am working only on the standard library and compiler, and developing
>>> accordingly. I realize everyone can write their own tools and import
>>> them everywhere, but the point of having a good standard library is that
>>> they don't have to. I'm not checking in my suite of private tools here,
>>> I'm checking in things I have every reason to believe are in demand.
>>>
>>> Your argument above is unconvincing to me because you could say it about
>>> anything. The impact of the import tax is basically a function of how
>>> the fixed cost of the import compares to the savings. In situations
>>> like this, the import tax dominates, just as it does when you're trying
>>> to decide whether a method should take "Seq" or "collection.Traversable".
>>>
>>> I can tell you that I hear about people wanting times all the time, near
>>> the absolute top of the list for simple additions. But if nobody cares
>>> enough to chip in here with their specific use cases, I have plenty of
>>> other stuff to worry about.
>>>
>> Where are these requests coming from? I just searched my codebase for
>> ScalaTest and there isn't a single place where I have needed it.
>>
>> To Vlad's comment I'd agree in general that the standard library
>> should get first shot at the best syntax. But I'd balance that with
>> the need to avoid code breakage. I don't know that there's much code
>> that would break at this point with "times," but it is already in use
>> by a library that Scala programmers use. Search for "times" on this
>> page and you'll see it:
>>
>> http://code.google.com/p/specs/wiki/UsingMockito
>>
>> My use of times isn't released yet, so it wouldn't break code of
>> ScalaTest users because I still have time to adjust.
>>
>> Neverthless, the attitude that the standard library is the only thing
>> you need to consider when adding things to the standard library
>> neglects that you need to consider the extent to which each addition
>> will break code. Today there few enough users of Scala that breaking
>> changes that will be big improvements should still be added. Moreover,
>> everyone using Scala today is aware that 2.8 will likely break their
>> code, and everyone seems to want the language and library to be
>> improved as much as possible now while Scala is still at the early
>> adopter stage. But even now I think it is important to be
>> conservative. Things that are added that may break code, and that
>> includes any addition to Predef, must really be carefully considered
>> and carry their weight.
>>
>> You're not done when you can't think of anything else to add. You're
>> done when you can't think of anything else to take out.
>>
>> Bill
>>
>>> --
>>> Paul Phillips | Every election is a sort of advance auction sale
>>> Stickler | of stolen goods.
>>> Empiricist | -- H. L. Mencken
>>> i pull his palp! |----------* http://www.improving.org/paulp/ *----------
>>>
>>
>>
>>
>> --
>> Bill Venners
>> Artima, Inc.
>> http://www.artima.com
>>
>
>
>
> --
> Ricky Clarkson
> Java Programmer, AD Holdings
> +44 1565 770804
> Skype: ricky_clarkson
> Google Talk: ricky.clarkson@gmail.com
>
Sat, 2009-08-29, 19:27
#10
Re: 5 times println
On Sat, Aug 29, 2009 at 3:19 PM, Paul Phillips wrote:
> OK, I'm no professional benchmarker so I trust someone will let me know
> if there's some huge flaw here. Every way I tried out yielded about the
> same results, summarized in these:
>
> Accumulated time after 100 iterations:
> iterator: 6709
> range: 5856
> while loop: 4611
> rich int: 4845
>
> So looking at these two approaches:
>
> 5 times println
> for (_ <- 1 to 5) println
>
> Here are the advantages for 1:
>
> 1) About 20% faster.
Did you try to compile with -optimise? I would say if you did and it's
still 20% slower than that's a bug which should be fixed. Unless
Iulian says that it can't be fixed; in that case we can reconsider
times.
> 2) Less accidental complexity. Is it "to" or "until" ? Why do
> I have to explicitly discard the counter? Why am I naming
> two numbers when my intention is fully expressed by one?
I don't buy that. You have just introduced more accidental complexity
by throwing in a third possiblility.
> 3) Shorter.
>
Yes, but really not by much.
> The arguments against seem much less convincing to me. It's imperative,
> and so is everything else which returns Unit.
My point here is that I feel no strong compulsion to throw in special
forms that make imperative programming more concise.
> If not a method on RichInt, then I would be equally happy with a method
> in Predef, like
>
> def repeat(n: Int)(body: => Unit)
>
> As things are now every time the need to do this arises it feels like I
> have to make an unnecessary compromise, because none of the available
> options have a comparable speed+clarity+convenience sum. If it's not in
> Predef or a conversion from Int, the import tax dominates the cost.
>
Like I said, the for loop needs to have at least the speed of times.
If it does not, it's a bug that needs to be fixed. Working around that
now by throwing in more special forms is premature optimization, IMO.
Cheers
Sat, 2009-08-29, 20:07
#11
Re: 5 times println
Hi All,
On Sat, Aug 29, 2009 at 11:12 AM, martin odersky wrote:
>> The arguments against seem much less convincing to me. It's imperative,
>> and so is everything else which returns Unit.
>
> My point here is that I feel no strong compulsion to throw in special
> forms that make imperative programming more concise.
>
I realized the reason I haven't felt much need for this kind of
construct is I "went over" to the functional style side. I don't
program this way anymore. Many people, especially newcomers to Scala,
may program this way. But the absence of a method like times method on
RichInt is a gentle nudge to the functional style, something that Ruby
and Groovy don't really encourage. I doubt people would do this much:
scala> 2 times println("hi")
hi
hi
More likely, they'd want to use it for something like:
scala> var list = List.range(1, 10)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> 5 times { list = list.tail }
scala> list
res2: List[Int] = List(6, 7, 8, 9)
Here's a more functional approach:
scala> val list = List.range(1, 10)
list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> list drop 5
res4: List[Int] = List(6, 7, 8, 9)
This is a made up example, but my experience has been that the
functional style is usually more clear and concise. So I think it is
misleading to only compare:
5 times { println("hi") }
with:
for (_ <- 1 to 5) println("hi"
When comparing a real scenario, which is likely going to involve
mutating an object or reassiging a var external to the block passed to
time, with an equivalent functional approach, the functional approach
might be better still.
Bill
----
Bill Venners
Artima, Inc.
http://www.artima.com
Sat, 2009-08-29, 20:17
#12
Re: 5 times println
Hi Josh,
I think I misinterpreted how Eric was using this. I thought he was
using it to assert that a method was invoked N number of times, but he
was actually just invoking it N times prior to doing assertions. So I
think Eric actually just implemented the imerative Ruby/Groovy-like
times method inside specs. If so then adding it to the standard
library would not break specs users code so long as he removed it from
specs.
No, I found the code and it is slightly different. It takes a function
that takes the index instead of a by-name. So the times in the 2.8
trunk would still break specs users code. Here's his definition:
/**
* This implicit definition allows to write short loops, ruby-style:
*
*
3.times { i => doThis() }
.
* Warning: an integer variable i must be declared otherwise there
will be a runtime exception
*/
implicit def integerToRange(n: Int): RangeInt = new RangeInt(n)
case class RangeInt(n: Int) {
def times[T](f: (Int) => T) = for (i <- 1 to n) f(i)
def times = this
}
}
By the way, the example in the specs documentation is a use case for
times on Ints. Testing might be a case where you want to do things
with side effects repeatedly without having a counter, but I'll have
to think whether this has come up for me before. I can't remember ever
needing to invoke a method multiple times like that. Of course, if
testing is a good use case, then testing libraries can simply provide
it even if it is not in the standard library. I'd also point out there
is no "import tax" for using this times method in specs, because you
are already going to import Specification, which inherits this
implicit conversion.
Bill
On Sat, Aug 29, 2009 at 11:01 AM, Josh Suereth wrote:
> I'm on the fence here. I think the scala standard library should be as good
> as possible, and I can't wait to use a lot of the things Paul has been
> adding. I'm on the fence about times however as it's not amazing to me
> either way. I think it could help swing groovy people over when they
> (meaning my coworker) ask "Where's your times method? Groovy has that!".
> To which I want to respond "What production code do you use times in?". My
> coworker has no response, perhaps neither do many people? You see, these
> amps go to 11.
>
> On general principles, I think the scala library should be cautious about
> what methods it places on globaly used things (like primitives), but I also
> think it takes precedence over third-party libraries (including my own!).
>
> I'd rather see Specs and Scalatest help define the times method on the
> scala-library such that their use still makes sense (or they can co-exist).
> I believe you can somewhat get around these issues by places the DSL
> language before integer (and therefore not rely on integer implicit
> conversions).
>
> e.g.
>
> The Specs use of times could be combined with the standard library, or
> prefixed with e.g. "mock it"
>
>
> scala> object mock {
> | def it(n : Int) = new {
> | def times[A](f : Int => A) {
> | var i = 0 //This would be a real
> implementation
> | while(i < n) {
> | f(i + 1)
> | i += 1
> | }
> | }
> | }
> | }
> defined module mock
>
> scala> mock it 5 times { i => println(i) }
> 1
> 2
> 3
> 4
> 5
>
>
>
> Anyway, I don't mind the times function being added either way. I think it
> may be useful if in scala, it takes a (Int => A) and ( => A), so users who
> want to know what iteration they are on can find out.
>
>
> - Josh
>
>
> On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners wrote:
>>
>> Hi Paul,
>>
>> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips wrote:
>> > On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> >> Isn't the import tax pretty cheap these days? And that way everyone
>> >> can have whatever syntax they want for this. Stick it in a Utils.scala
>> >> and import and use whatever syntax you want.
>> >
>> > I am working only on the standard library and compiler, and developing
>> > accordingly. I realize everyone can write their own tools and import
>> > them everywhere, but the point of having a good standard library is that
>> > they don't have to. I'm not checking in my suite of private tools here,
>> > I'm checking in things I have every reason to believe are in demand.
>> >
>> > Your argument above is unconvincing to me because you could say it about
>> > anything. The impact of the import tax is basically a function of how
>> > the fixed cost of the import compares to the savings. In situations
>> > like this, the import tax dominates, just as it does when you're trying
>> > to decide whether a method should take "Seq" or
>> > "collection.Traversable".
>> >
>> > I can tell you that I hear about people wanting times all the time, near
>> > the absolute top of the list for simple additions. But if nobody cares
>> > enough to chip in here with their specific use cases, I have plenty of
>> > other stuff to worry about.
>> >
>> Where are these requests coming from? I just searched my codebase for
>> ScalaTest and there isn't a single place where I have needed it.
>>
>> To Vlad's comment I'd agree in general that the standard library
>> should get first shot at the best syntax. But I'd balance that with
>> the need to avoid code breakage. I don't know that there's much code
>> that would break at this point with "times," but it is already in use
>> by a library that Scala programmers use. Search for "times" on this
>> page and you'll see it:
>>
>> http://code.google.com/p/specs/wiki/UsingMockito
>>
>> My use of times isn't released yet, so it wouldn't break code of
>> ScalaTest users because I still have time to adjust.
>>
>> Neverthless, the attitude that the standard library is the only thing
>> you need to consider when adding things to the standard library
>> neglects that you need to consider the extent to which each addition
>> will break code. Today there few enough users of Scala that breaking
>> changes that will be big improvements should still be added. Moreover,
>> everyone using Scala today is aware that 2.8 will likely break their
>> code, and everyone seems to want the language and library to be
>> improved as much as possible now while Scala is still at the early
>> adopter stage. But even now I think it is important to be
>> conservative. Things that are added that may break code, and that
>> includes any addition to Predef, must really be carefully considered
>> and carry their weight.
>>
>> You're not done when you can't think of anything else to add. You're
>> done when you can't think of anything else to take out.
>>
>> Bill
>>
>> > --
>> > Paul Phillips | Every election is a sort of advance auction sale
>> > Stickler | of stolen goods.
>> > Empiricist | -- H. L. Mencken
>> > i pull his palp! |----------* http://www.improving.org/paulp/
>> > *----------
>> >
>>
>>
>>
>> --
>> Bill Venners
>> Artima, Inc.
>> http://www.artima.com
>
>
Sat, 2009-08-29, 20:27
#13
Re: 5 times println
Bill,
I think you're right in that the biggest difference between Specs' times and the one in trunk is the => A and Int => A (which I believe was my last point).
It also appears like testing and benchmarking are valid cases where times could be useful...
//Simple Benchmark calculation
def benchmark[A](f : =>A) : Long = {
10000 times f //Seed hotspot
val start = System.currentTimeInMillis
10000 times f
val end = System.currentTimeInMillis
end - start
}
val timesSpeed = benchmark { 5 times println }
val rangeSpeed = benchmark { (1 to 5).foreach(println) }
...
Anyway, like I said, I'm on the fence over this particular method, but I'd prefer to have a strong standard library that meets the needs of consumers without resorting to the same utility method defined everywhere. Perhaps the times method belongs on some sort of Benchmarking test utility class implict that gets used when Scala performs its own benchmarks?
- Josh
On Sat, Aug 29, 2009 at 3:11 PM, Bill Venners <bill@artima.com> wrote:
I think you're right in that the biggest difference between Specs' times and the one in trunk is the => A and Int => A (which I believe was my last point).
It also appears like testing and benchmarking are valid cases where times could be useful...
//Simple Benchmark calculation
def benchmark[A](f : =>A) : Long = {
10000 times f //Seed hotspot
val start = System.currentTimeInMillis
10000 times f
val end = System.currentTimeInMillis
end - start
}
val timesSpeed = benchmark { 5 times println }
val rangeSpeed = benchmark { (1 to 5).foreach(println) }
...
Anyway, like I said, I'm on the fence over this particular method, but I'd prefer to have a strong standard library that meets the needs of consumers without resorting to the same utility method defined everywhere. Perhaps the times method belongs on some sort of Benchmarking test utility class implict that gets used when Scala performs its own benchmarks?
- Josh
On Sat, Aug 29, 2009 at 3:11 PM, Bill Venners <bill@artima.com> wrote:
Hi Josh,
I think I misinterpreted how Eric was using this. I thought he was
using it to assert that a method was invoked N number of times, but he
was actually just invoking it N times prior to doing assertions. So I
think Eric actually just implemented the imerative Ruby/Groovy-like
times method inside specs. If so then adding it to the standard
library would not break specs users code so long as he removed it from
specs.
No, I found the code and it is slightly different. It takes a function
that takes the index instead of a by-name. So the times in the 2.8
trunk would still break specs users code. Here's his definition:
/**
* This implicit definition allows to write short loops, ruby-style:<br/>
* <code> 3.times { i => doThis() } </code>.
* Warning: an integer variable i must be declared otherwise there
will be a runtime exception
*/
implicit def integerToRange(n: Int): RangeInt = new RangeInt(n)
case class RangeInt(n: Int) {
def times[T](f: (Int) => T) = for (i <- 1 to n) f(i)
def times = this
}
}
By the way, the example in the specs documentation is a use case for
times on Ints. Testing might be a case where you want to do things
with side effects repeatedly without having a counter, but I'll have
to think whether this has come up for me before. I can't remember ever
needing to invoke a method multiple times like that. Of course, if
testing is a good use case, then testing libraries can simply provide
it even if it is not in the standard library. I'd also point out there
is no "import tax" for using this times method in specs, because you
are already going to import Specification, which inherits this
implicit conversion.
Bill
On Sat, Aug 29, 2009 at 11:01 AM, Josh Suereth<joshua.suereth@gmail.com> wrote:
> I'm on the fence here. I think the scala standard library should be as good
> as possible, and I can't wait to use a lot of the things Paul has been
> adding. I'm on the fence about times however as it's not amazing to me
> either way. I think it could help swing groovy people over when they
> (meaning my coworker) ask "Where's your times method? Groovy has that!".
> To which I want to respond "What production code do you use times in?". My
> coworker has no response, perhaps neither do many people? You see, these
> amps go to 11.
>
> On general principles, I think the scala library should be cautious about
> what methods it places on globaly used things (like primitives), but I also
> think it takes precedence over third-party libraries (including my own!).
>
> I'd rather see Specs and Scalatest help define the times method on the
> scala-library such that their use still makes sense (or they can co-exist).
> I believe you can somewhat get around these issues by places the DSL
> language before integer (and therefore not rely on integer implicit
> conversions).
>
> e.g.
>
> The Specs use of times could be combined with the standard library, or
> prefixed with e.g. "mock it"
>
>
> scala> object mock {
> | def it(n : Int) = new {
> | def times[A](f : Int => A) {
> | var i = 0 //This would be a real
> implementation
> | while(i < n) {
> | f(i + 1)
> | i += 1
> | }
> | }
> | }
> | }
> defined module mock
>
> scala> mock it 5 times { i => println(i) }
> 1
> 2
> 3
> 4
> 5
>
>
>
> Anyway, I don't mind the times function being added either way. I think it
> may be useful if in scala, it takes a (Int => A) and ( => A), so users who
> want to know what iteration they are on can find out.
>
>
> - Josh
>
>
> On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners <bill@artima.com> wrote:
>>
>> Hi Paul,
>>
>> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips<paulp@improving.org> wrote:
>> > On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> >> Isn't the import tax pretty cheap these days? And that way everyone
>> >> can have whatever syntax they want for this. Stick it in a Utils.scala
>> >> and import and use whatever syntax you want.
>> >
>> > I am working only on the standard library and compiler, and developing
>> > accordingly. I realize everyone can write their own tools and import
>> > them everywhere, but the point of having a good standard library is that
>> > they don't have to. I'm not checking in my suite of private tools here,
>> > I'm checking in things I have every reason to believe are in demand.
>> >
>> > Your argument above is unconvincing to me because you could say it about
>> > anything. The impact of the import tax is basically a function of how
>> > the fixed cost of the import compares to the savings. In situations
>> > like this, the import tax dominates, just as it does when you're trying
>> > to decide whether a method should take "Seq" or
>> > "collection.Traversable".
>> >
>> > I can tell you that I hear about people wanting times all the time, near
>> > the absolute top of the list for simple additions. But if nobody cares
>> > enough to chip in here with their specific use cases, I have plenty of
>> > other stuff to worry about.
>> >
>> Where are these requests coming from? I just searched my codebase for
>> ScalaTest and there isn't a single place where I have needed it.
>>
>> To Vlad's comment I'd agree in general that the standard library
>> should get first shot at the best syntax. But I'd balance that with
>> the need to avoid code breakage. I don't know that there's much code
>> that would break at this point with "times," but it is already in use
>> by a library that Scala programmers use. Search for "times" on this
>> page and you'll see it:
>>
>> http://code.google.com/p/specs/wiki/UsingMockito
>>
>> My use of times isn't released yet, so it wouldn't break code of
>> ScalaTest users because I still have time to adjust.
>>
>> Neverthless, the attitude that the standard library is the only thing
>> you need to consider when adding things to the standard library
>> neglects that you need to consider the extent to which each addition
>> will break code. Today there few enough users of Scala that breaking
>> changes that will be big improvements should still be added. Moreover,
>> everyone using Scala today is aware that 2.8 will likely break their
>> code, and everyone seems to want the language and library to be
>> improved as much as possible now while Scala is still at the early
>> adopter stage. But even now I think it is important to be
>> conservative. Things that are added that may break code, and that
>> includes any addition to Predef, must really be carefully considered
>> and carry their weight.
>>
>> You're not done when you can't think of anything else to add. You're
>> done when you can't think of anything else to take out.
>>
>> Bill
>>
>> > --
>> > Paul Phillips | Every election is a sort of advance auction sale
>> > Stickler | of stolen goods.
>> > Empiricist | -- H. L. Mencken
>> > i pull his palp! |----------* http://www.improving.org/paulp/
>> > *----------
>> >
>>
>>
>>
>> --
>> Bill Venners
>> Artima, Inc.
>> http://www.artima.com
>
>
--
Bill Venners
Artima, Inc.
http://www.artima.com
Sat, 2009-08-29, 20:57
#14
Re: 5 times println
I think the fact that Specs felt the need to add pretty much the same method that Paul added argues in favor of it's inclusion in the standard library. I can't even begin the count the number of times I've implemented this method myself. If people are truly implementing the same method over and over again, that's the strongest reason I can think of to include it in the standard library.
It's true that the Specs version provides the Int being iterated over, but no where in Specs is this Int ever used. It's always discarded. (Except in the spec fo the "times" method itself. And even there the test there is just trying to add the numbers 0 until 3, in which case using "0 until 3" would be preferable... if the point weren't to test the "times" method.)
And as for -optimize, having never used it, I'm not very clear on what it's supposed to do. So I asked someone who would know, and his response was "All I know is that -optimize breaks things". If this is indeed the case, it's not really an acceptable alternative to "times".
Finally, a compromise might be the following:
case class repeat(n: Int) {
def apply(body: => Unit): Unit = {
var i = 0
while(i < n) {
body
i += 1
}
}
}
class RichInt(start: Int) {
...
def times = repeat(start)
}
Then libraries that wish to use "3.times" as a standalone (no block) can do so, but "3.times doStuff()" still works. And we also get "repeat(3) { doStuff() }".
I don't know if this ruins the performance argument. And frankly I'd prefer the straightforward implementation of "times".
--j
On Sat, Aug 29, 2009 at 12:11 PM, Bill Venners <bill@artima.com> wrote:
It's true that the Specs version provides the Int being iterated over, but no where in Specs is this Int ever used. It's always discarded. (Except in the spec fo the "times" method itself. And even there the test there is just trying to add the numbers 0 until 3, in which case using "0 until 3" would be preferable... if the point weren't to test the "times" method.)
And as for -optimize, having never used it, I'm not very clear on what it's supposed to do. So I asked someone who would know, and his response was "All I know is that -optimize breaks things". If this is indeed the case, it's not really an acceptable alternative to "times".
Finally, a compromise might be the following:
case class repeat(n: Int) {
def apply(body: => Unit): Unit = {
var i = 0
while(i < n) {
body
i += 1
}
}
}
class RichInt(start: Int) {
...
def times = repeat(start)
}
Then libraries that wish to use "3.times" as a standalone (no block) can do so, but "3.times doStuff()" still works. And we also get "repeat(3) { doStuff() }".
I don't know if this ruins the performance argument. And frankly I'd prefer the straightforward implementation of "times".
--j
On Sat, Aug 29, 2009 at 12:11 PM, Bill Venners <bill@artima.com> wrote:
Hi Josh,
I think I misinterpreted how Eric was using this. I thought he was
using it to assert that a method was invoked N number of times, but he
was actually just invoking it N times prior to doing assertions. So I
think Eric actually just implemented the imerative Ruby/Groovy-like
times method inside specs. If so then adding it to the standard
library would not break specs users code so long as he removed it from
specs.
No, I found the code and it is slightly different. It takes a function
that takes the index instead of a by-name. So the times in the 2.8
trunk would still break specs users code. Here's his definition:
/**
* This implicit definition allows to write short loops, ruby-style:<br/>
* <code> 3.times { i => doThis() } </code>.
* Warning: an integer variable i must be declared otherwise there
will be a runtime exception
*/
implicit def integerToRange(n: Int): RangeInt = new RangeInt(n)
case class RangeInt(n: Int) {
def times[T](f: (Int) => T) = for (i <- 1 to n) f(i)
def times = this
}
}
By the way, the example in the specs documentation is a use case for
times on Ints. Testing might be a case where you want to do things
with side effects repeatedly without having a counter, but I'll have
to think whether this has come up for me before. I can't remember ever
needing to invoke a method multiple times like that. Of course, if
testing is a good use case, then testing libraries can simply provide
it even if it is not in the standard library. I'd also point out there
is no "import tax" for using this times method in specs, because you
are already going to import Specification, which inherits this
implicit conversion.
Bill
On Sat, Aug 29, 2009 at 11:01 AM, Josh Suereth<joshua.suereth@gmail.com> wrote:
> I'm on the fence here. I think the scala standard library should be as good
> as possible, and I can't wait to use a lot of the things Paul has been
> adding. I'm on the fence about times however as it's not amazing to me
> either way. I think it could help swing groovy people over when they
> (meaning my coworker) ask "Where's your times method? Groovy has that!".
> To which I want to respond "What production code do you use times in?". My
> coworker has no response, perhaps neither do many people? You see, these
> amps go to 11.
>
> On general principles, I think the scala library should be cautious about
> what methods it places on globaly used things (like primitives), but I also
> think it takes precedence over third-party libraries (including my own!).
>
> I'd rather see Specs and Scalatest help define the times method on the
> scala-library such that their use still makes sense (or they can co-exist).
> I believe you can somewhat get around these issues by places the DSL
> language before integer (and therefore not rely on integer implicit
> conversions).
>
> e.g.
>
> The Specs use of times could be combined with the standard library, or
> prefixed with e.g. "mock it"
>
>
> scala> object mock {
> | def it(n : Int) = new {
> | def times[A](f : Int => A) {
> | var i = 0 //This would be a real
> implementation
> | while(i < n) {
> | f(i + 1)
> | i += 1
> | }
> | }
> | }
> | }
> defined module mock
>
> scala> mock it 5 times { i => println(i) }
> 1
> 2
> 3
> 4
> 5
>
>
>
> Anyway, I don't mind the times function being added either way. I think it
> may be useful if in scala, it takes a (Int => A) and ( => A), so users who
> want to know what iteration they are on can find out.
>
>
> - Josh
>
>
> On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners <bill@artima.com> wrote:
>>
>> Hi Paul,
>>
>> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips<paulp@improving.org> wrote:
>> > On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> >> Isn't the import tax pretty cheap these days? And that way everyone
>> >> can have whatever syntax they want for this. Stick it in a Utils.scala
>> >> and import and use whatever syntax you want.
>> >
>> > I am working only on the standard library and compiler, and developing
>> > accordingly. I realize everyone can write their own tools and import
>> > them everywhere, but the point of having a good standard library is that
>> > they don't have to. I'm not checking in my suite of private tools here,
>> > I'm checking in things I have every reason to believe are in demand.
>> >
>> > Your argument above is unconvincing to me because you could say it about
>> > anything. The impact of the import tax is basically a function of how
>> > the fixed cost of the import compares to the savings. In situations
>> > like this, the import tax dominates, just as it does when you're trying
>> > to decide whether a method should take "Seq" or
>> > "collection.Traversable".
>> >
>> > I can tell you that I hear about people wanting times all the time, near
>> > the absolute top of the list for simple additions. But if nobody cares
>> > enough to chip in here with their specific use cases, I have plenty of
>> > other stuff to worry about.
>> >
>> Where are these requests coming from? I just searched my codebase for
>> ScalaTest and there isn't a single place where I have needed it.
>>
>> To Vlad's comment I'd agree in general that the standard library
>> should get first shot at the best syntax. But I'd balance that with
>> the need to avoid code breakage. I don't know that there's much code
>> that would break at this point with "times," but it is already in use
>> by a library that Scala programmers use. Search for "times" on this
>> page and you'll see it:
>>
>> http://code.google.com/p/specs/wiki/UsingMockito
>>
>> My use of times isn't released yet, so it wouldn't break code of
>> ScalaTest users because I still have time to adjust.
>>
>> Neverthless, the attitude that the standard library is the only thing
>> you need to consider when adding things to the standard library
>> neglects that you need to consider the extent to which each addition
>> will break code. Today there few enough users of Scala that breaking
>> changes that will be big improvements should still be added. Moreover,
>> everyone using Scala today is aware that 2.8 will likely break their
>> code, and everyone seems to want the language and library to be
>> improved as much as possible now while Scala is still at the early
>> adopter stage. But even now I think it is important to be
>> conservative. Things that are added that may break code, and that
>> includes any addition to Predef, must really be carefully considered
>> and carry their weight.
>>
>> You're not done when you can't think of anything else to add. You're
>> done when you can't think of anything else to take out.
>>
>> Bill
>>
>> > --
>> > Paul Phillips | Every election is a sort of advance auction sale
>> > Stickler | of stolen goods.
>> > Empiricist | -- H. L. Mencken
>> > i pull his palp! |----------* http://www.improving.org/paulp/
>> > *----------
>> >
>>
>>
>>
>> --
>> Bill Venners
>> Artima, Inc.
>> http://www.artima.com
>
>
--
Bill Venners
Artima, Inc.
http://www.artima.com
Sat, 2009-08-29, 21:07
#15
Re: 5 times println
On Sat, Aug 29, 2009 at 8:46 PM, Jorge Ortiz wrote:
> I can't even begin the count the number of times I've implemented this method
> myself.
Really? Can you give us a couple of examples? Of uses, that is, not
the implementations.
Cheers,
Miles
Sat, 2009-08-29, 21:07
#16
Re: 5 times println
And in the few hours after Paul made his commit, at least half a dozen people on #scala IRC channel thanked him. Clearly I'm not the only one that finds times useful.
--j
On Sat, Aug 29, 2009 at 12:57 PM, Jorge Ortiz <jorge.ortiz@gmail.com> wrote:
--j
On Sat, Aug 29, 2009 at 12:57 PM, Jorge Ortiz <jorge.ortiz@gmail.com> wrote:
When I'm scripting stuff, when I'm benchmarking stuff, when I'm testing stuff...
It just reads much better than the equivalent for-comprehension.
--j
On Sat, Aug 29, 2009 at 12:51 PM, Miles Sabin <miles@milessabin.com> wrote:
On Sat, Aug 29, 2009 at 8:46 PM, Jorge Ortiz<jorge.ortiz@gmail.com> wrote:
> I can't even begin the count the number of times I've implemented this method
> myself.
Really? Can you give us a couple of examples? Of uses, that is, not
the implementations.
Cheers,
Miles
--
Miles Sabin
tel: +44 (0)7813 944 528
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Sat, 2009-08-29, 21:17
#17
Re: 5 times println
When I'm scripting stuff, when I'm benchmarking stuff, when I'm testing stuff...
It just reads much better than the equivalent for-comprehension.
--j
On Sat, Aug 29, 2009 at 12:51 PM, Miles Sabin <miles@milessabin.com> wrote:
It just reads much better than the equivalent for-comprehension.
--j
On Sat, Aug 29, 2009 at 12:51 PM, Miles Sabin <miles@milessabin.com> wrote:
On Sat, Aug 29, 2009 at 8:46 PM, Jorge Ortiz<jorge.ortiz@gmail.com> wrote:
> I can't even begin the count the number of times I've implemented this method
> myself.
Really? Can you give us a couple of examples? Of uses, that is, not
the implementations.
Cheers,
Miles
--
Miles Sabin
tel: +44 (0)7813 944 528
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Sat, 2009-08-29, 21:27
#18
Re: 5 times println
On Sat, Aug 29, 2009 at 8:57 PM, Jorge Ortiz wrote:
> When I'm scripting stuff, when I'm benchmarking stuff, when I'm testing
> stuff...
>
> It just reads much better than the equivalent for-comprehension.
No, I mean can you show us some code ...
Cheers,
Miles
Sat, 2009-08-29, 21:47
#19
Re: 5 times println
With just a quick grep through my ~/Code directory:
From a private project:
def repeat[T](n: Int)(what: => T): Unit = ...
def repeatParallel[T](n: Int)(what: => T): Unit = ...
From the Scala compiler's PickleBuffer.scala (granted, slightly different):
def times[T](n: Int, op: ()=>T): List[T] =
From the mada project's (http://github.com/okomok/mada/tree/master) Control.scala:
def repeat[R](body: => R, n: Int): Unit = {
From the scala-commons project's (http://assorted.sourceforge.net/scala-commons/) Collections.scala (granted, also slightly different):
def replicate[a](n: Int, gen: => a): Stream[a] = ...
From the actord project's (http://code.google.com/p/actord/) ServerSpec.scala (granted, also slightly different):
def benchMark(repeat: Int, f: => Unit): List[Long] = ...
def benchMarkAvgMillis(repeat: Int, f: => Unit) = ...
def benchMarkAvgSecs(repeat: Int, f: => Unit) = ...
--j
On Sat, Aug 29, 2009 at 12:59 PM, Miles Sabin <miles@milessabin.com> wrote:
From a private project:
def repeat[T](n: Int)(what: => T): Unit = ...
def repeatParallel[T](n: Int)(what: => T): Unit = ...
From the Scala compiler's PickleBuffer.scala (granted, slightly different):
def times[T](n: Int, op: ()=>T): List[T] =
From the mada project's (http://github.com/okomok/mada/tree/master) Control.scala:
def repeat[R](body: => R, n: Int): Unit = {
From the scala-commons project's (http://assorted.sourceforge.net/scala-commons/) Collections.scala (granted, also slightly different):
def replicate[a](n: Int, gen: => a): Stream[a] = ...
From the actord project's (http://code.google.com/p/actord/) ServerSpec.scala (granted, also slightly different):
def benchMark(repeat: Int, f: => Unit): List[Long] = ...
def benchMarkAvgMillis(repeat: Int, f: => Unit) = ...
def benchMarkAvgSecs(repeat: Int, f: => Unit) = ...
--j
On Sat, Aug 29, 2009 at 12:59 PM, Miles Sabin <miles@milessabin.com> wrote:
On Sat, Aug 29, 2009 at 8:57 PM, Jorge Ortiz<jorge.ortiz@gmail.com> wrote:
> When I'm scripting stuff, when I'm benchmarking stuff, when I'm testing
> stuff...
>
> It just reads much better than the equivalent for-comprehension.
No, I mean can you show us some code ...
Cheers,
Miles
--
Miles Sabin
tel: +44 (0)7813 944 528
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
Sat, 2009-08-29, 21:57
#20
Re: 5 times println
On Sat, Aug 29, 2009 at 9:38 PM, Jorge Ortiz wrote:
> With just a quick grep through my ~/Code directory:
Umm ... those are all signatures, it's uses that I wanted to see.
The reason I'm being so persistent in asking is that my hunch is that
almost all actual examples of use will be at best unpersuasive, at
worst inadvisable. The fact that nobody seems to be willing to post
any examples at all is only deepening my hunch ;-)
But TBH this is far too close to bikeshedding for me ...
Cheers,
Miles
Sat, 2009-08-29, 21:57
#21
Re: 5 times println
On Sat, Aug 29, 2009 at 10:50 PM, martin odersky wrote:
> That's the point. Slighty different does not count. The problem is
> that times gives only minor improvement in conciseness, and that only
> for the most trivial imperative cases. In my mind, that's not enough
> to warrant a space in the standard Scala toolbox. It takes effort to
> learn the times idiom and you have to unlearn it immediately once you
> do something remotely interesting such as return a result or access
> the index.
>
I guess Miles expressed it better than I did: How often do you want to
repeat something blindly a fixed number of times, without varying with
the index? I find very few use cases for that in my code.
Cheers
Sat, 2009-08-29, 22:07
#22
Re: 5 times println
That's the point. Slighty different does not count. The problem is
that times gives only minor improvement in conciseness, and that only
for the most trivial imperative cases. In my mind, that's not enough
to warrant a space in the standard Scala toolbox. It takes effort to
learn the times idiom and you have to unlearn it immediately once you
do something remotely interesting such as return a result or access
the index.
Cheers
Sat, 2009-08-29, 22:17
#23
Re: 5 times println
Consider a conversation in IRC, or your favourite other forum:
How do I write 5.times println("hello") in Scala?
What do you really want to do?
An action, 5 times.
No, step back. What is it you actually want to do? times
doesn't exist, but there's probably a better way.
I'm writing a test case where I execute x() 5 times then
check the value of y, a variable that it modifies.
Ok, well, def times(n: Int)(body: => Unit) = for (i <- 1 to n) body
That's not the same. I really want the n on the left.
Ok, case class Times(n: Int) { def times(body: => Unit) = for
(i <- 1 to n) body }; implicit def int2Times(n: Int) = Times(n)
Why can't it just be in the standard library?
Because it's useless. Martin Odersky says that having times in
the standard lib wouldn't be a significant improvement over for (i <-
1 to 5) println("hello").
So why is he the 5th person to ask for it today?
It is trivial, it is inflexible (perhaps that can be improved upon by
overloading it for the no-index and index cases), but it's also a
perfectly reasonable thing to want to do with the language, and the
alternative requires you to write something quite different to what
you were thinking. In my opinion, anyhoo.
2009/8/29 martin odersky :
> On Sat, Aug 29, 2009 at 10:50 PM, martin odersky wrote:
>> That's the point. Slighty different does not count. The problem is
>> that times gives only minor improvement in conciseness, and that only
>> for the most trivial imperative cases. In my mind, that's not enough
>> to warrant a space in the standard Scala toolbox. It takes effort to
>> learn the times idiom and you have to unlearn it immediately once you
>> do something remotely interesting such as return a result or access
>> the index.
>>
> I guess Miles expressed it better than I did: How often do you want to
> repeat something blindly a fixed number of times, without varying with
> the index? I find very few use cases for that in my code.
>
> Cheers
>
> -- Martin
>
Sat, 2009-08-29, 22:17
#24
Re: 5 times println
On Aug 29, 2009, at 12:46 PM, Jorge Ortiz wrote:
> I think the fact that Specs felt the need to add pretty much the
> same method that Paul added argues in favor of it's inclusion in the
> standard library. I can't even begin the count the number of times
> I've implemented this method myself. If people are truly
> implementing the same method over and over again, that's the
> strongest reason I can think of to include it in the standard library.
>
> It's true that the Specs version provides the Int being iterated
> over, but no where in Specs is this Int ever used. It's always
> discarded. (Except in the spec fo the "times" method itself. And
> even there the test there is just trying to add the numbers 0 until
> 3, in which case using "0 until 3" would be preferable... if the
> point weren't to test the "times" method.)
>
> And as for -optimize, having never used it, I'm not very clear on
> what it's supposed to do. So I asked someone who would know, and his
> response was "All I know is that -optimize breaks things". If this
> is indeed the case, it's not really an acceptable alternative to
> "times".
I run our middle-tier Scala code with -optimise and haven't had any
issues. Maybe 2.8 is different?
Regards,
Blair
Sat, 2009-08-29, 22:27
#25
Re: 5 times println
Miles,
In my private project, I was stress-testing a web service. The code looks something like:
repeat(numRequests)(doRequest)
Usually also wrapped in a block to measure the time that took.
For the others, you can look up their uses yourself. I provided enough links.
Martin,
I agree that slightly different is slightly cheating. (But not entirely. In the actord case, for example, benchMark returns a List[Long] of times taken. But benchMark is only called from benchMarkAvgMillis and benchMarkAvgSecs, which could be implemented directly with a "n times foo" idiom and no need to construct intermediate lsits.) In any case, the examples all demonstrate that the need for doing something n times is quite pervasive. In 2.8 collections, the new [Collection].fill and [Collection].tabulate address this need fairly well, but there's currently no way to do the same actions N times and throw away the results without a penalty in performance.
Anecdotally, at least three independent projects (my private project, the mada project listed above, and Specs) have implemented exactly this behavior. A few more were within striking distance. Paul felt it was worth adding. Several people thanked Paul for the addition on IRC (I wasn't keeping logs, perhaps someone else can corroborate).
I agree the benefit is merely minor, but the burden on the standard library is also minor, and frankly the effort needed to learn or unlearn the idiom is trivial.
--j
On Sat, Aug 29, 2009 at 1:52 PM, martin odersky <martin.odersky@epfl.ch> wrote:
In my private project, I was stress-testing a web service. The code looks something like:
repeat(numRequests)(doRequest)
Usually also wrapped in a block to measure the time that took.
For the others, you can look up their uses yourself. I provided enough links.
Martin,
I agree that slightly different is slightly cheating. (But not entirely. In the actord case, for example, benchMark returns a List[Long] of times taken. But benchMark is only called from benchMarkAvgMillis and benchMarkAvgSecs, which could be implemented directly with a "n times foo" idiom and no need to construct intermediate lsits.) In any case, the examples all demonstrate that the need for doing something n times is quite pervasive. In 2.8 collections, the new [Collection].fill and [Collection].tabulate address this need fairly well, but there's currently no way to do the same actions N times and throw away the results without a penalty in performance.
Anecdotally, at least three independent projects (my private project, the mada project listed above, and Specs) have implemented exactly this behavior. A few more were within striking distance. Paul felt it was worth adding. Several people thanked Paul for the addition on IRC (I wasn't keeping logs, perhaps someone else can corroborate).
I agree the benefit is merely minor, but the burden on the standard library is also minor, and frankly the effort needed to learn or unlearn the idiom is trivial.
--j
On Sat, Aug 29, 2009 at 1:52 PM, martin odersky <martin.odersky@epfl.ch> wrote:
On Sat, Aug 29, 2009 at 10:50 PM, martin odersky<martin.odersky@epfl.ch> wrote:
> That's the point. Slighty different does not count. The problem is
> that times gives only minor improvement in conciseness, and that only
> for the most trivial imperative cases. In my mind, that's not enough
> to warrant a space in the standard Scala toolbox. It takes effort to
> learn the times idiom and you have to unlearn it immediately once you
> do something remotely interesting such as return a result or access
> the index.
>
I guess Miles expressed it better than I did: How often do you want to
repeat something blindly a fixed number of times, without varying with
the index? I find very few use cases for that in my code.
Cheers
Sat, 2009-08-29, 22:37
#26
Re: 5 times println
On Sat, Aug 29, 2009 at 10:10 PM, Jorge Ortiz wrote:
> In my private project, I was stress-testing a web service. The code looks
> something like:
> repeat(numRequests)(doRequest)
> Usually also wrapped in a block to measure the time that took.
Fine, but that's not been pimped onto Int and stuffed into the global space ...
Cheers,
Miles
Sat, 2009-08-29, 22:37
#27
Re: 5 times println
Hi Jorge,
On Sat, Aug 29, 2009 at 12:46 PM, Jorge Ortiz wrote:
> I think the fact that Specs felt the need to add pretty much the same method
> that Paul added argues in favor of it's inclusion in the standard library.
>
Yes, you're probably right about that. What's more, in that same specs
Sugar trait Eric also defined ok as an alias for Boolean true and ko
as an alias for Boolean false. We should probably add those to Predef
as well. Clearly true and false are not sufficient. They are at least
twice as verbose!
I do think Josh's use of times for benchmarking is a compelling use
case, but so far that's the only one I've seen from anyone. Just
because Eric added times to Sugar doesn't necessarily mean many users
were asking for it. I doubt many users asked for ko. We'd have to ask
Eric and see what his motivations were, and what use cases users
presented to him in requests. I cc'd him in case he's not on this
list.
> can't even begin the count the number of times I've implemented this method
> myself. If people are truly implementing the same method over and over
> again, that's the strongest reason I can think of to include it in the
> standard library.
>
I have never implemented or felt the need for it. Were I doing
benchmarking I think it might be nice, but I wouldn't mind adding it
to the project that needed it. As you demonstrated, many
implementations of this idea have subtle variations. I don't know what
form I'd need for real until I got to that situation, and it might end
up being slightly different from whatever form might have ended up in
the standard library by that point.
Josh, sorry I was a bit slow on the uptake. Your earlier email did
indeed point out the difference between Eric's and Paul's times method
being the index parameter.
Bill
> It's true that the Specs version provides the Int being iterated over, but
> no where in Specs is this Int ever used. It's always discarded. (Except in
> the spec fo the "times" method itself. And even there the test there is just
> trying to add the numbers 0 until 3, in which case using "0 until 3" would
> be preferable... if the point weren't to test the "times" method.)
>
> And as for -optimize, having never used it, I'm not very clear on what it's
> supposed to do. So I asked someone who would know, and his response was "All
> I know is that -optimize breaks things". If this is indeed the case, it's
> not really an acceptable alternative to "times".
>
> Finally, a compromise might be the following:
>
> case class repeat(n: Int) {
> def apply(body: => Unit): Unit = {
> var i = 0
> while(i < n) {
> body
> i += 1
> }
> }
> }
>
> class RichInt(start: Int) {
> ...
> def times = repeat(start)
> }
>
> Then libraries that wish to use "3.times" as a standalone (no block) can do
> so, but "3.times doStuff()" still works. And we also get "repeat(3) {
> doStuff() }".
>
> I don't know if this ruins the performance argument. And frankly I'd prefer
> the straightforward implementation of "times".
>
> --j
>
> On Sat, Aug 29, 2009 at 12:11 PM, Bill Venners wrote:
>>
>> Hi Josh,
>>
>> I think I misinterpreted how Eric was using this. I thought he was
>> using it to assert that a method was invoked N number of times, but he
>> was actually just invoking it N times prior to doing assertions. So I
>> think Eric actually just implemented the imerative Ruby/Groovy-like
>> times method inside specs. If so then adding it to the standard
>> library would not break specs users code so long as he removed it from
>> specs.
>>
>> No, I found the code and it is slightly different. It takes a function
>> that takes the index instead of a by-name. So the times in the 2.8
>> trunk would still break specs users code. Here's his definition:
>>
>> /**
>> * This implicit definition allows to write short loops, ruby-style:
>> *
>> *
3.times { i => doThis() }
.
>> * Warning: an integer variable i must be declared otherwise there
>> will be a runtime exception
>> */
>> implicit def integerToRange(n: Int): RangeInt = new RangeInt(n)
>> case class RangeInt(n: Int) {
>> def times[T](f: (Int) => T) = for (i <- 1 to n) f(i)
>> def times = this
>> }
>> }
>>
>> By the way, the example in the specs documentation is a use case for
>> times on Ints. Testing might be a case where you want to do things
>> with side effects repeatedly without having a counter, but I'll have
>> to think whether this has come up for me before. I can't remember ever
>> needing to invoke a method multiple times like that. Of course, if
>> testing is a good use case, then testing libraries can simply provide
>> it even if it is not in the standard library. I'd also point out there
>> is no "import tax" for using this times method in specs, because you
>> are already going to import Specification, which inherits this
>> implicit conversion.
>>
>> Bill
>>
>> On Sat, Aug 29, 2009 at 11:01 AM, Josh Suereth
>> wrote:
>> > I'm on the fence here. I think the scala standard library should be as
>> > good
>> > as possible, and I can't wait to use a lot of the things Paul has been
>> > adding. I'm on the fence about times however as it's not amazing to me
>> > either way. I think it could help swing groovy people over when they
>> > (meaning my coworker) ask "Where's your times method? Groovy has
>> > that!".
>> > To which I want to respond "What production code do you use times in?".
>> > My
>> > coworker has no response, perhaps neither do many people? You see,
>> > these
>> > amps go to 11.
>> >
>> > On general principles, I think the scala library should be cautious
>> > about
>> > what methods it places on globaly used things (like primitives), but I
>> > also
>> > think it takes precedence over third-party libraries (including my
>> > own!).
>> >
>> > I'd rather see Specs and Scalatest help define the times method on the
>> > scala-library such that their use still makes sense (or they can
>> > co-exist).
>> > I believe you can somewhat get around these issues by places the DSL
>> > language before integer (and therefore not rely on integer implicit
>> > conversions).
>> >
>> > e.g.
>> >
>> > The Specs use of times could be combined with the standard library, or
>> > prefixed with e.g. "mock it"
>> >
>> >
>> > scala> object mock {
>> > | def it(n : Int) = new {
>> > | def times[A](f : Int => A) {
>> > | var i = 0 //This would be a real
>> > implementation
>> > | while(i < n) {
>> > | f(i + 1)
>> > | i += 1
>> > | }
>> > | }
>> > | }
>> > | }
>> > defined module mock
>> >
>> > scala> mock it 5 times { i => println(i) }
>> > 1
>> > 2
>> > 3
>> > 4
>> > 5
>> >
>> >
>> >
>> > Anyway, I don't mind the times function being added either way. I
>> > think it
>> > may be useful if in scala, it takes a (Int => A) and ( => A), so users
>> > who
>> > want to know what iteration they are on can find out.
>> >
>> >
>> > - Josh
>> >
>> >
>> > On Sat, Aug 29, 2009 at 1:14 PM, Bill Venners wrote:
>> >>
>> >> Hi Paul,
>> >>
>> >> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips
>> >> wrote:
>> >> > On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>> >> >> Isn't the import tax pretty cheap these days? And that way everyone
>> >> >> can have whatever syntax they want for this. Stick it in a
>> >> >> Utils.scala
>> >> >> and import and use whatever syntax you want.
>> >> >
>> >> > I am working only on the standard library and compiler, and
>> >> > developing
>> >> > accordingly. I realize everyone can write their own tools and import
>> >> > them everywhere, but the point of having a good standard library is
>> >> > that
>> >> > they don't have to. I'm not checking in my suite of private tools
>> >> > here,
>> >> > I'm checking in things I have every reason to believe are in demand.
>> >> >
>> >> > Your argument above is unconvincing to me because you could say it
>> >> > about
>> >> > anything. The impact of the import tax is basically a function of
>> >> > how
>> >> > the fixed cost of the import compares to the savings. In situations
>> >> > like this, the import tax dominates, just as it does when you're
>> >> > trying
>> >> > to decide whether a method should take "Seq" or
>> >> > "collection.Traversable".
>> >> >
>> >> > I can tell you that I hear about people wanting times all the time,
>> >> > near
>> >> > the absolute top of the list for simple additions. But if nobody
>> >> > cares
>> >> > enough to chip in here with their specific use cases, I have plenty
>> >> > of
>> >> > other stuff to worry about.
>> >> >
>> >> Where are these requests coming from? I just searched my codebase for
>> >> ScalaTest and there isn't a single place where I have needed it.
>> >>
>> >> To Vlad's comment I'd agree in general that the standard library
>> >> should get first shot at the best syntax. But I'd balance that with
>> >> the need to avoid code breakage. I don't know that there's much code
>> >> that would break at this point with "times," but it is already in use
>> >> by a library that Scala programmers use. Search for "times" on this
>> >> page and you'll see it:
>> >>
>> >> http://code.google.com/p/specs/wiki/UsingMockito
>> >>
>> >> My use of times isn't released yet, so it wouldn't break code of
>> >> ScalaTest users because I still have time to adjust.
>> >>
>> >> Neverthless, the attitude that the standard library is the only thing
>> >> you need to consider when adding things to the standard library
>> >> neglects that you need to consider the extent to which each addition
>> >> will break code. Today there few enough users of Scala that breaking
>> >> changes that will be big improvements should still be added. Moreover,
>> >> everyone using Scala today is aware that 2.8 will likely break their
>> >> code, and everyone seems to want the language and library to be
>> >> improved as much as possible now while Scala is still at the early
>> >> adopter stage. But even now I think it is important to be
>> >> conservative. Things that are added that may break code, and that
>> >> includes any addition to Predef, must really be carefully considered
>> >> and carry their weight.
>> >>
>> >> You're not done when you can't think of anything else to add. You're
>> >> done when you can't think of anything else to take out.
>> >>
>> >> Bill
>> >>
>> >> > --
>> >> > Paul Phillips | Every election is a sort of advance auction sale
>> >> > Stickler | of stolen goods.
>> >> > Empiricist | -- H. L. Mencken
>> >> > i pull his palp! |----------* http://www.improving.org/paulp/
>> >> > *----------
>> >> >
>> >>
>> >>
>> >>
>> >> --
>> >> Bill Venners
>> >> Artima, Inc.
>> >> http://www.artima.com
>> >
>> >
>>
>>
>>
>> --
>> Bill Venners
>> Artima, Inc.
>> http://www.artima.com
>
>
Sat, 2009-08-29, 22:47
#28
Re: 5 times println
On Sat, Aug 29, 2009 at 11:13 PM, Blair Zajac wrote:
>
> On Aug 29, 2009, at 12:46 PM, Jorge Ortiz wrote:
>
>> I think the fact that Specs felt the need to add pretty much the same
>> method that Paul added argues in favor of it's inclusion in the standard
>> library. I can't even begin the count the number of times I've implemented
>> this method myself. If people are truly implementing the same method over
>> and over again, that's the strongest reason I can think of to include it in
>> the standard library.
>>
>> It's true that the Specs version provides the Int being iterated over, but
>> no where in Specs is this Int ever used. It's always discarded. (Except in
>> the spec fo the "times" method itself. And even there the test there is just
>> trying to add the numbers 0 until 3, in which case using "0 until 3" would
>> be preferable... if the point weren't to test the "times" method.)
>>
>> And as for -optimize, having never used it, I'm not very clear on what
>> it's supposed to do. So I asked someone who would know, and his response was
>> "All I know is that -optimize breaks things". If this is indeed the case,
>> it's not really an acceptable alternative to "times".
>
My conclusion is exactly the opposite. We should embrace -optimise and
demand that it works. There are a number of places in the libraries
where I intentionally refrained from doing micro-optimizations because
I felt that this should be optimized away. The current state is: Few
people use -optimise and people work around it. That's why it's less
reliable than it could be. We need to change that!
Having or not having times is no big deal. But I feel it goes the
wrong way. Scala the language consciously refrains from having special
syntax for particular situations which are not generalizable. It makes
it easy for the libraries to do that, but that does not mean that we
should do it. So, I really feel that times is not "Scala-like" (what's
the analogue of ``Pythonic" in Scala?) Ruby-like yes, but not
Scala-like.
And let's not forget there is a cost to this: More forms of imperative
loops to remember. Maybe worse,
times is already taken as multiplication in the new Numeric trait. I
believe this trait is going to be very important in the future because
it lets us abstract from concrete number types. Do we really want to
confuse notation by something as trivial as repeating the same thing a
fixed number of times?
Cheers
Sat, 2009-08-29, 22:57
#29
Re: 5 times println
Hi Martin,
On Sat, Aug 29, 2009 at 2:27 PM, martin odersky wrote:
> ... So, I really feel that times is not "Scala-like" (what's
> the analogue of ``Pythonic" in Scala?) Ruby-like yes, but not
> Scala-like.
>
Scalactic?
Bill
> And let's not forget there is a cost to this: More forms of imperative
> loops to remember. Maybe worse,
> times is already taken as multiplication in the new Numeric trait. I
> believe this trait is going to be very important in the future because
> it lets us abstract from concrete number types. Do we really want to
> confuse notation by something as trivial as repeating the same thing a
> fixed number of times?
>
> Cheers
>
> -- Martin
>
Sun, 2009-08-30, 00:37
#30
Re: 5 times println
On Sat, Aug 29, 2009 at 5:37 PM, Bill Venners <bill@artima.com> wrote:
Hi Martin,
On Sat, Aug 29, 2009 at 2:27 PM, martin odersky<martin.odersky@epfl.ch> wrote:
> ... So, I really feel that times is not "Scala-like" (what's
> the analogue of ``Pythonic" in Scala?) Ruby-like yes, but not
> Scala-like.
>
Scalactic?
+12
(other worse ideas... Scalastic Scaltastic Scalatious Scalartic Scalable)
- Josh
Sun, 2009-08-30, 00:47
#31
Re: 5 times println
Scalasmic?
On Sun, Aug 30, 2009 at 12:30 AM, Josh Suereth <joshua.suereth@gmail.com> wrote:
On Sun, Aug 30, 2009 at 12:30 AM, Josh Suereth <joshua.suereth@gmail.com> wrote:
On Sat, Aug 29, 2009 at 5:37 PM, Bill Venners <bill@artima.com> wrote:Hi Martin,
On Sat, Aug 29, 2009 at 2:27 PM, martin odersky<martin.odersky@epfl.ch> wrote:
> ... So, I really feel that times is not "Scala-like" (what's
> the analogue of ``Pythonic" in Scala?) Ruby-like yes, but not
> Scala-like.
>
Scalactic?
+12
(other worse ideas... Scalastic Scaltastic Scalatious Scalartic Scalable)
- Josh
Sun, 2009-08-30, 00:57
#32
Re: 5 times println
On Saturday August 29 2009, martin odersky wrote:
> ... So, I really feel that times is not "Scala-like"
> (what's the analogue of ``Pythonic" in Scala?) ...
Scalastic
> ...
>
Sun, 2009-08-30, 04:37
#33
Re: 5 times println
Hi All,
I decided to go this route instead for my DSL:
mockClown.hasBigRedNose was invoked (3) times
This way I don't have to add an implicit conversion to Int, which is
better regardless of whether times stays added to RichInt.
So I don't have a conflict anymore, and it turned out Eric never did.
Nevertheless, I think the only two compelling use cases so far
presented was the benchmarking one and the from-Ruby-or-Groovy nuby. I
think the latter one has some merit because it smoothes the out of box
experience for people familiar with Ruby and Groovy. We do expect
people coming from most other mainstream languages will start out in
an imperative style and to some extent migrate to a more functional
style over time. Both Ruby and Groovy call this times, so it is sort
of the defacto name, even though it makes me think a bit of
multiplication. One other naming suggestion I'd throw out is simply
loop. As someone suggested, you could overload one form that takes a
by-name parameter and one that takes the int index (probably 0 to n -
1). So that would give you:
class LoopyInt(times: Int) {
def loop(f: => Unit) {
var i = 0
while (i < times) {
f
i = i + 1
}
}
def loop(f: Int => Unit) {
var i = 0
while (i < times) {
f(i)
i = i + 1
}
}
}
implicit def convert(i: Int) = new LoopyInt(i)
3 loop println("hi")
prints:
hi
hi
hi
3 loop { i => println(i) }
prints:
0
1
2
At least "loop" doesn't look like multiplication, as times does, and
it could be called an N-loop. I would still rather see more real use
cases that justify such an addition before it were to get added to
RichInt.
Bill
On Sat, Aug 29, 2009 at 11:14 AM, Bill Venners wrote:
> Hi Ricky,
>
> This is how you verify that a method was called exactly three times
> when using the Mockito API directly:
>
> verify(mockClown, times(3)).hasBigRedNose
>
> My hope was to be able to offer this syntax in a MockitoSugar trait:
>
> mockClown.hasBigRedNose was invoked (3 times)
>
> If a times method is added to RichInt, then this code would no longer
> compile in 2.8.
>
> Bill
>
> On Sat, Aug 29, 2009 at 10:52 AM, Ricky
> Clarkson wrote:
>> Bill,
>>
>> I'd be interested to see your intended use of `times`.
>>
>> Ricky.
>>
>> 2009/8/29 Bill Venners :
>>> Hi Paul,
>>>
>>> On Sat, Aug 29, 2009 at 9:31 AM, Paul Phillips wrote:
>>>> On Sat, Aug 29, 2009 at 08:18:19AM -0700, Bill Venners wrote:
>>>>> Isn't the import tax pretty cheap these days? And that way everyone
>>>>> can have whatever syntax they want for this. Stick it in a Utils.scala
>>>>> and import and use whatever syntax you want.
>>>>
>>>> I am working only on the standard library and compiler, and developing
>>>> accordingly. I realize everyone can write their own tools and import
>>>> them everywhere, but the point of having a good standard library is that
>>>> they don't have to. I'm not checking in my suite of private tools here,
>>>> I'm checking in things I have every reason to believe are in demand.
>>>>
>>>> Your argument above is unconvincing to me because you could say it about
>>>> anything. The impact of the import tax is basically a function of how
>>>> the fixed cost of the import compares to the savings. In situations
>>>> like this, the import tax dominates, just as it does when you're trying
>>>> to decide whether a method should take "Seq" or "collection.Traversable".
>>>>
>>>> I can tell you that I hear about people wanting times all the time, near
>>>> the absolute top of the list for simple additions. But if nobody cares
>>>> enough to chip in here with their specific use cases, I have plenty of
>>>> other stuff to worry about.
>>>>
>>> Where are these requests coming from? I just searched my codebase for
>>> ScalaTest and there isn't a single place where I have needed it.
>>>
>>> To Vlad's comment I'd agree in general that the standard library
>>> should get first shot at the best syntax. But I'd balance that with
>>> the need to avoid code breakage. I don't know that there's much code
>>> that would break at this point with "times," but it is already in use
>>> by a library that Scala programmers use. Search for "times" on this
>>> page and you'll see it:
>>>
>>> http://code.google.com/p/specs/wiki/UsingMockito
>>>
>>> My use of times isn't released yet, so it wouldn't break code of
>>> ScalaTest users because I still have time to adjust.
>>>
>>> Neverthless, the attitude that the standard library is the only thing
>>> you need to consider when adding things to the standard library
>>> neglects that you need to consider the extent to which each addition
>>> will break code. Today there few enough users of Scala that breaking
>>> changes that will be big improvements should still be added. Moreover,
>>> everyone using Scala today is aware that 2.8 will likely break their
>>> code, and everyone seems to want the language and library to be
>>> improved as much as possible now while Scala is still at the early
>>> adopter stage. But even now I think it is important to be
>>> conservative. Things that are added that may break code, and that
>>> includes any addition to Predef, must really be carefully considered
>>> and carry their weight.
>>>
>>> You're not done when you can't think of anything else to add. You're
>>> done when you can't think of anything else to take out.
>>>
>>> Bill
>>>
>>>> --
>>>> Paul Phillips | Every election is a sort of advance auction sale
>>>> Stickler | of stolen goods.
>>>> Empiricist | -- H. L. Mencken
>>>> i pull his palp! |----------* http://www.improving.org/paulp/ *----------
>>>>
>>>
>>>
>>>
>>> --
>>> Bill Venners
>>> Artima, Inc.
>>> http://www.artima.com
>>>
>>
>>
>>
>> --
>> Ricky Clarkson
>> Java Programmer, AD Holdings
>> +44 1565 770804
>> Skype: ricky_clarkson
>> Google Talk: ricky.clarkson@gmail.com
>>
>
>
>
> --
> Bill Venners
> Artima, Inc.
> http://www.artima.com
>
Sun, 2009-08-30, 17:17
#34
Re : 5 times println
Eric Torreborre was having trouble getting on this list, so he asked
me to forward his reply about his motivations for times on Ints:
Hi Bill,
Thanks for including me in the discussion. I've sent a request for
membership on the scala-internals mailing-list but I haven't yet
received an anwer, so please post this answer for me.
Some background on why I added the times method:
- this was for me an easy way to repeat a behavior a fixed number of times
- I used it to specify mocks where you want to show what happens if
the same action is repeated a certain number of times
- I was coming from the Groovy / Ruby world so the syntax was natural to me
- I don't remember why I provided a parameter only version. I think I
didn't know how to provide both versions at that time.
- I added that in a Sugar trait because I had the feeling that this
would be like "invading" the Int class and that other people may want
to do something else with "times" on Int
That being said:
- I like to have that method at hand, because I think that my use case
is a valid one (mock specifications) and I can imagine other use cases
in testing or scripting.
- I like to have a language with "batteries included". Actually, if
you put aside methods using closures, I was very happy to discover all
the methods of the Array class in Ruby coming from the Java world.
Having to re-develop Utils this and that is not a good sign IMHO.
- A great part of Scala success comes from its sound foundations. I
don't get the same feeling of soundness with Groovy or Ruby.
So my overall opinion on the matter is that this would be beneficial
to add "times" to the standard library but this should necessitate an
import. And I dream of an IDE capable of auto-importing this (Miles,
wink, wink,...).
And about "ok" and "ko", that's pure sugar, bad for health! I just
wanted to use them for matchers with pattern matching:
List(1, 2, 3) must be like { case List(_, 2, _) => ok } // instead of
=> true. I find it shorter and nicer in that case.
Cheers,
Eric
Sun, 2009-08-30, 19:07
#35
Re: Re : 5 times println
On Sun, Aug 30, 2009 at 5:10 PM, Bill Venners wrote:
> So my overall opinion on the matter is that this would be beneficial
> to add "times" to the standard library but this should necessitate an
> import. And I dream of an IDE capable of auto-importing this (Miles,
> wink, wink,...).
Noted ... I think that's an excellent suggestion and ought to reduce
the pressure to add endless nice-to-haves to the global namespace.
Cheers,
Miles
Mon, 2009-08-31, 01:47
#36
Re: Re : 5 times println
Have anyone considered this instead:
{ () => println("hi") } * 5
--
Daniel C. Sobral
Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
{ () => println("hi") } * 5
--
Daniel C. Sobral
Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
OK, I'm no professional benchmarker so I trust someone will let me know
if there's some huge flaw here. Every way I tried out yielded about the
same results, summarized in these:
Accumulated time after 100 iterations:
iterator: 6709
range: 5856
while loop: 4611
rich int: 4845
So looking at these two approaches:
5 times println
for (_ <- 1 to 5) println
Here are the advantages for 1:
1) About 20% faster.
2) Less accidental complexity. Is it "to" or "until" ? Why do
I have to explicitly discard the counter? Why am I naming
two numbers when my intention is fully expressed by one?
3) Shorter.
The arguments against seem much less convincing to me. It's imperative,
and so is everything else which returns Unit.
If not a method on RichInt, then I would be equally happy with a method
in Predef, like
def repeat(n: Int)(body: => Unit)
As things are now every time the need to do this arises it feels like I
have to make an unnecessary compromise, because none of the available
options have a comparable speed+clarity+convenience sum. If it's not in
Predef or a conversion from Int, the import tax dominates the cost.
The benchmark I used is here: http://paste.pocoo.org/show/136941/