Listing using yield in Ruby and Python

I am trying to create an elegant way to create a list from a function that gives values ​​in both Python and Ruby.

In Python:

def foo(x):
    for i in range(x):
        if bar(i): yield i 
result = list(foo(100))

In Ruby:

def foo(x)
  x.times {|i| yield i if bar(i)}
end
result = []
foo(100) {|x| result << x}

Despite the fact that I like working in both languages, I was always a little worried about the version of Ruby that was supposed to initialize the list and then fill it. Python yieldleads to a simple iteration, which is great. Ruby yieldcalls the block, which is also great, but when I just want to populate the list, it looks a little awkward.

Is there a more elegant Ruby way?

UPDATE Reworked the example to show that the number of values ​​received from the function is not necessarily x.

+3
7

, :

def foo(x)
  (0..x).select { |i| bar(i) }
end

, , yield Ruby. , , , Python Ruby.

+10

Python , :

(i for i in range(x) if bar(i))

,

itertools.ifilter(bar,range(x))
+7

Python ( Ruby Generators) :

def foo(x)
    Enumerator.new do |yielder|
        (0..x).each { |v| yielder.yield(v) if bar(v) }
    end
end

result = Array(foo(100))

( Python); :

def bar(v); v % 2 == 0; end

f = foo(100)
f.next #=> 0
f.next #=> 2
+5

, , , :

result = Array.new(100) {|x| x*x}
+1
def squares(x)
  (0..x).map { |i| i * i }
end

, , , , , times .

+1
source

For the version of Python list comprehension published by stbuton, use xrange instead of range if you want a generator. range will create the entire list in memory.

+1
source

yieldmean different things ruby ​​and python. In ruby, you should specify a callback block, if I remember correctly, while generators in python can be passed in and give way to the one who holds them.

+1
source

Source: https://habr.com/ru/post/1704174/


All Articles