Hacker News new | past | comments | ask | show | jobs | submit login

More importantly (and annoyingly), if I define a top-level method with def—let’s call those top-level def methods (TLDMs)—Ruby won’t let me pass it as a block to any other method. (TLDMs actually belong to an object, so strictly speaking, this makes sense. It’s still annoying.) In Python, we can pass lambdas and TLDMs like they’re identical.

...

This is a problem because Python treats methods and functions differently. You can pass functions to other functions. But you can’t pass instance methods.

In Ruby, you can pass "TLDMs" by passing the symbol corresponding to their name, and calling send() on the symbol to call the method. Likewise, you can pass the object and the symbol in order to pass a method around.

Ruby lacks list comprehensions

Ruby does have the select method, which is semantically equivalent. List comprehensions are syntactic sugar for select (and I'll freely admit that Ruby can have a pretty bitter syntax at times, so maybe the sugar is justified).




> This is a problem because Python treats methods and functions differently. You can pass functions to other functions. But you can’t pass instance methods.

I should also mention that this is false:

    >>> x = 'a'
    >>> def call(f): return f()
    ... 
    >>> call(x.capitalize)
    'A'


I stand corrected. However, I do think that in order to use this like I want ...

map(str.capitalize, ['a', 'b', 'c'])

... you have to understand far too much of Python's implementation (for example, that str is not a function, but a class that kindof acts like a function) to program. I still think that methods + functions = a pain point in Python.


Well... to make it easier you can think of classes as normal functions returning instances. For almost any practical purpose, that's true. Also, str.capitalize is (for any practical purpose again :) ) a one-argument function that takes a string and returns a capitalised string.


In Python, str is a class. And all classes act as function. If there is ever any doubt, you can tell like this:

    >>> type(str)
    <type 'type'>
You can tell that str is a class because it inherits from type type.


also to access TLDMs ruby gives us Object#method, but it's kind of gross.

  class Foo
    def bar
      p 'baz'
    end
  end

  bar = Foo.new.method(:bar).to_proc

  3.times &bar
This can also be used if you have a function such as puts where the object is passed in so you can do things such as...

  [1,2,3].each(&method(:puts))
  #instead of
  [1,2,3].each {|i| puts i }
but that's ALSO pretty gross, and usually considered poor form.


I don't think so, select is just a filter. List comprehensions map and select at the same time.

Regarding TLDMs, how do you propose mapping a TLDM over an array? For example:

  def transform(x)
    # implementation ...
  end

  list = [1, 2, 3]

  # doesn't work ...
  list.map &transform
Edit: &method(:transform) is way too verbose compared with Python's solution


    def transform(x)
      x * 2
    end
    
    list = [1, 2, 3]
    
    p list.map &method(:transform)
<3 <3 <3 <3


You wouldn't use a named Ruby method for something like this. You'd typically use a Proc or block.

    [1,2,3].map{ |x| x * 2 }
or if you wanted to reuse the block for other things

    transform = lambda { |x| x * 2 }
    [1,2,3].map(&transform)


Exactly, but there should be an easier syntax that declaring a lambda for each algorithm I want to map over.


That's probably why explicitly calling transform inside the block, or making transform a method of the objects you're trying to transform, is more idiomatic Ruby.

You're right in that list comprehensions are semantically equivalent to combining map and select, not just select.


    alias :m :method
<3 <3 <3




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: