Skip to content

Commit e6e7a0e

Browse files
committed
[GR-20446] Implement Enumerator::Lazy#with_index
PullRequest: truffleruby/2669
2 parents e76da03 + 68db106 commit e6e7a0e

File tree

6 files changed

+83
-1
lines changed

6 files changed

+83
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Compatibility:
3232
* Fix `ObjectSpace._id2ref` for Symbols and frozen String literals (#2358).
3333
* Implemented `Enumerator::Lazy#filter_map` (#2356).
3434
* Fix LLVM toolchain issue on macOS 10.13 (#2352, [oracle/graal#3383](https://github.com/oracle/graal/issues/3383)).
35+
* Implemented `Enumerator::Lazy#with_index` (#2356).
3536

3637
Performance:
3738

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# -*- encoding: us-ascii -*-
2+
3+
require_relative '../../../spec_helper'
4+
require_relative 'fixtures/classes'
5+
6+
ruby_version_is "2.7" do
7+
describe "Enumerator::Lazy#with_index" do
8+
it "enumerates with an index" do
9+
(0..Float::INFINITY).lazy.with_index.map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
10+
end
11+
12+
it "enumerates with an index starting at a given offset" do
13+
(0..Float::INFINITY).lazy.with_index(3).map { |i, idx| [i, idx] }.first(3).should == [[0, 3], [1, 4], [2, 5]]
14+
end
15+
16+
it "enumerates with an index starting at 0 when offset is nil" do
17+
(0..Float::INFINITY).lazy.with_index(nil).map { |i, idx| [i, idx] }.first(3).should == [[0, 0], [1, 1], [2, 2]]
18+
end
19+
20+
it "raises TypeError when offset does not convert to Integer" do
21+
-> { (0..Float::INFINITY).lazy.with_index(false).map { |i, idx| i }.first(3) }.should raise_error(TypeError)
22+
end
23+
24+
it "enumerates with a given block" do
25+
result = []
26+
(0..Float::INFINITY).lazy.with_index { |i, idx| result << [i * 2, idx] }.first(3)
27+
result.should == [[0,0],[2,1],[4,2]]
28+
end
29+
end
30+
end
31+

spec/tags/truffle/methods_tags.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ fails:Public methods on TracePoint should include parameters
5757
fails:Public methods on TracePoint should include raised_exception
5858
fails:Public methods on TracePoint should include return_value
5959
fails:Public methods on ENV.singleton_class should include freeze
60-
fails:Public methods on Enumerator::Lazy should include with_index
6160
fails:Public methods on IO should include set_encoding_by_bom
6261
fails:Public methods on BasicSocket should include read_nonblock
6362
fails:Public methods on BasicSocket should include write_nonblock

src/main/java/org/truffleruby/core/CoreLibrary.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,7 @@ public boolean isTruffleBootMainMethod(SharedMethodInfo info) {
979979
"/core/truffle/debug.rb",
980980
"/core/truffle/diggable.rb",
981981
"/core/truffle/encoding_operations.rb",
982+
"/core/truffle/enumerator_operations.rb",
982983
"/core/truffle/hash_operations.rb",
983984
"/core/truffle/interop_operations.rb",
984985
"/core/truffle/numeric_operations.rb",

src/main/ruby/truffleruby/core/enumerator.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,14 @@ def each(*args, &block)
275275
end
276276

277277
class Lazy < Enumerator
278+
279+
aliases = Truffle::EnumeratorOperations::LAZY_OVERRIDE_METHODS.map do |m|
280+
name = :"_enumerable_#{m}"
281+
alias_method name, :"#{m}"
282+
name
283+
end
284+
private(*aliases)
285+
278286
class StopLazyError < Exception # rubocop:disable Lint/InheritException
279287
end
280288

@@ -299,6 +307,7 @@ def initialize(receiver, size=nil)
299307
def to_enum(method_name=:each, *method_args, &block)
300308
size = block_given? ? block : nil
301309
ret = Lazy.allocate
310+
method_name = Truffle::EnumeratorOperations.lazy_method(method_name)
302311

303312
ret.__send__ :initialize_enumerator, self, size, method_name, *method_args
304313

@@ -492,6 +501,23 @@ def flat_map
492501
end
493502
alias_method :collect_concat, :flat_map
494503

504+
def with_index(offset=0, &block)
505+
offset = if Primitive.nil?(offset)
506+
0
507+
else
508+
Truffle::Type.coerce_to offset, Integer, :to_int
509+
end
510+
511+
Lazy.new(self, enumerator_size) do |yielder, *args|
512+
if block
513+
yielder.yield yield(*args, offset)
514+
else
515+
yielder.yield(*args, offset)
516+
end
517+
offset += 1
518+
end
519+
end
520+
495521
def zip(*lists)
496522
return super(*lists) { |entry| yield entry } if block_given?
497523

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright (c) 2021, 2021 Oracle and/or its affiliates. All rights reserved. This
4+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
5+
# redistribute it and/or modify it under the terms of the:
6+
#
7+
# Eclipse Public License version 2.0, or
8+
# GNU General Public License version 2, or
9+
# GNU Lesser General Public License version 2.1.
10+
11+
module Truffle
12+
module EnumeratorOperations
13+
LAZY_OVERRIDE_METHODS = %i[map collect flat_map collect_concat select find_all filter filter_map reject grep grep_v
14+
zip take take_while drop drop_while uniq with_index]
15+
16+
def self.lazy_method(meth)
17+
if LAZY_OVERRIDE_METHODS.include?(meth)
18+
:"_enumerable_#{meth}"
19+
else
20+
meth
21+
end
22+
end
23+
end
24+
end

0 commit comments

Comments
 (0)