Hacker Newsnew | comments | show | ask | jobs | submit login

Why's that, dons? They are playing a bit fast and loose with what 'higher order functions' means, but, for example, one of Ruby's best features is blocks. The details of higher order stuff in Ruby is certainly... messy, but blocks are a great introduction to the concept for people who haven't used them before. I've taught the concept to high school kids on their first day of programming, (mostly through a physical metaphor involving a list of chores on a piece of paper) and they picked it up easily enough.



I can't speak of Ruby (or for Dons :), but I'm not sure Python's use of hof's is a good example to learn from when it's lambda scoping rules produce such "interesting" results.

>>> monomials = [lambda x: x(star)(star)i for i in [1,2,3]] #(not sure how to escape stars for exponentiation properly, whatever)

OK, what will these functions evaluate to at the point 2.0?

>>> monomials[0](2.0), monomials[1](2.0), monomials[2](2.0)

(8.0, 8.0, 8.0)

The i variable was captured as an address which all the lambdas share. For an integer. Ouch.

You can do "lambda x,i=i: x(star)(star)i" and capture the value properly, but to me this is a landmine waiting to be stumbled upon every time I write a lambda. I for one will often forget to do this, at least so long as I also keep using other languages which can capture integers as values without hijinks.

-----


Every language with mutable variables and closures that I've used works the same way (other than ones like C++ where you have to explicitly capture by either reference or value). The behavior can be a bit confusing, but it makes perfect sense once you realize that closures are capturing variables, not values.

-----


I wonder if anyone knows why subtlety exists in Python. Is it because reference semantics and HOF are fundamentally incompatible, or could it have been avoided somehow but still retaining reference semantics. The most common complain about lambda in Python is that it is restricted to expressions, which is a conscious design decision that could have gone the opposite direction.

-----


The subtlety sixbrx mentions used to be present in C#, but it has been mostly fixed by moving the declaration of the foreach loop variable inside of the loop [1]. Like Python, C# has reference semantics. I'm surprised that Guido van Rossum didn't make a similar change when he broke backwards compatibility in Python 3.

[1]http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closi...

-----


Lexical scopes capturing variables is more powerful than capturing values.

If you want to capture values, that's easy too, with:

  lambda x, i=i: ...

-----


Yeah. Makes sense. Ruby also has a few of these kinds of weirdness, especially around the multiple kinds of hof, (lambdas, Procs, and blocks) and their limited utility compared to a truly functional language.

-----


Fair enough. I'd say they provide more of a flavor of "higher orderness" rather than a true implementation, as the semantics are so limited and ad hoc in Ruby.

-----


Seems fair. I highly respect your opinion on the topic, and that makes a lot of sense. There's a reason that I moonlight Haskell and Rust. :)

-----




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: