News for hackers. Stuff that matters.
Re:Lambdas and Functions in Python by chriswarbo on Saturday June 16, 2018 @04:11PM (#17329124)
It's interesting to note that a dictionary ("catalog") of values is essentially the same concept as an object. This is clearer in Javascript, where `{...}` notation is called an "object" rather than a "dictionary" and the `.foo` and `["foo"]` notations are mostly interchangable.

Storing functions in a dictionary is very close to storing methods in an object. The only differences are sharing state via a `self` (or `this`) argument, and inheritance chains (either from classes or prototypes).

Also interesting to note that many of the author's functions, like `lambda x, y: x + y`, only make sense because the underlying language (Python) thought that constructs like `+` shouldn't be functions for some reason. Many languages seem to do this, e.g. here's a bug report I raised for PHP https://bugs.php.net/bug.php?id=66368

When we introduce arbitrary distinctions, like dictionary vs object, named vs anonymous functions, functions vs operators, etc. then we end up with all of the choices and complications like those shown in this article.

One of the principles I try to follow when programming is to avoid making distinctions, or breaking symmetries, unless my hand is forced by the underlying dynamics. Experience has taught me that introducing distinctions in one place just introduces complication elsewhere (e.g. more cases to handle when metaprogramming).

Re:Lambdas and Functions in Python by coldtea on Saturday June 16, 2018 @04:46PM (#17329315)
>Also interesting to note that many of the author's functions, like `lambda x, y: x + y`, only make sense because the underlying language (Python) thought that constructs like `+` shouldn't be functions for some reason

Actually python's + (and most operators) are available as functions, and allow for overloading as well:

  >>> import operator
  >>> operator.__add__(1,2)
  3
>Many languages seem to do this

"Many"? Unless you ever only touched Smalltalk, Lisp or some fringe languages, this is the norm for most languages -- operators are distinct from functions (same as expressions are different than statements). Whether this is a good idea or not, I wont go into, but it's not like this is something surprising, or something that merely "many" languages seem to do. Not just many, but almost ALL mainstream languages (C, C++, Java, C#, etc) do it.

Re:Lambdas and Functions in Python by kazinator on Sunday June 17, 2018 @12:30AM (#17330877)
Lisp operators are distinct from functions. It's just that arithmetic operations are functions; Lisp dialects use operators for various other constructs that cannot follow the function call evaluation rules.

C++ sort of makes operators functions. Any overloaded operator is a function. If a is a class object then a + b can be spelled otherwise as a.operator+(b). This doesn't work for the built-in definitions of the operator, as in 2.operator+(2).

The built-in + operator in C++ can also do things that used to be impossible in C++ until its template system became more powerful. Namely, the result type of the built-in + is deduced from both operands and can be different from both of them. If C++ were being redesigned clean-slate, it would likely be that operator overloading is allowed for the non-class types like int, and all the built-in operators are defined in terms of templates, whose deduction/instantiation reproduces all the rules.

Re:Lambdas and Functions in Python by cup-of-tea on Sunday June 17, 2018 @03:49AM (#17331355)
The thing that makes it beautiful in Lisp is multiple dispatch. In higher order functions, + is still just +, not some function that's already bound to the left hand side.
Re:Lambdas and Functions in Python by annabellish on Saturday June 16, 2018 @05:22PM (#17329501)
>operators are distinct from functions

>c#

As python, C#'s operators are backed by functions - they're just static ones on the class.

Re:Lambdas and Functions in Python by agumonkey on Saturday June 16, 2018 @05:53PM (#17329679)
personally I always always hated operation segregation
Re:Lambdas and Functions in Python by chriswarbo on Monday June 18, 2018 @09:32AM (#17338072)
> Actually python's + (and most operators) are available as functions, and allow for overloading as well

Yes, operators like `x + y` desugar to method calls like `x.__add__(y)`, which is yet another somewhat-arbitrary distinction (operators, functions and methods). The fact that `operator.__add__`, etc. are available doesn't remove the distinction between operators and functions; we can do `operator.__add__(x, y)` but we still can't do `+(x, y)`. Those `operator` functions are just a way to avoid defining our own `lambda`s, but even then it doesn't save very many keystrokes.

> Not just many, but almost ALL mainstream languages

In other words, "many" ;)

I don't think it's useful to group languages into "popular" and "fringe", since the cost/benefit of a language construct depends more on the paradigm than the popularity. For example, you mention C, and one way to think of C is as a (mostly) "portable assembly"; in which case it can make sense to distinguish operators like `+` (which are essentially machine instructions) from functions (which are more complicated subroutines involving jumps, stack manipulation, etc.).

Highly dynamic languages like Python don't emit machine instructions so that argument doesn't hold (they do emit opcodes for the interpreter, but the language designers get to choose what those are); other arguments can be made either way, but they depend on the paradigm. The indirection given by `__foo__` methods fits the language quite well, but it doesn't preclude those symbols being used as functions as well.

I don't hold much opinion on the use of operators in Java and C#: on one hand they allow high-level OOP with dynamic dispatch, first-class functions, etc. but on the other hand the body of a function/method mostly harks back to structured programming (if/else, for/while, etc.).

You also mention distinguishing between expressions and statements. That's another thing that seems to make (a little) more sense in something C-like, but less so in a high level language. Python suffers for this, since it makes `lambda` much less useful. On the other hand PHP gets this right by simply making statements a type of expression, although it shoots itself in the foot when it comes to precedence, e.g. `$x = $y xor $z;` is the expression `($x = $y) xor $z`.

> it's not like this is something surprising

I never said it was. Although I do like to view common things from new perspectives: in this case that operators are distinct from functions and methods, which we often take for granted, but (a) doesn't have to be that way (b) can cause unnecessary work (like this whole article) without us necessarily realising where it stems from and (c) has no real reason to be so widespread, and mostly comes down to self-reinforcing logic like "others are doing it, so we'll do it too".

> Unless you ever only touched Smalltalk, Lisp or some fringe languages

I wouldn't say people who've only used such languages would think in this way; rather, I'd say that even brief exposure to different ways of doing things can permanently alter the way one thinks about programming, and this is usually for the better (e.g. it's probably a bad idea to program in Python as if it had backtracking, or return-type polymorphism, or delimited continuations, or whatever; yet it can be invaluable for gaining a big-picture perspective and avoiding "everything looks like a nail")

Re:Lambdas and Functions in Python by Felk on Saturday June 16, 2018 @04:21PM (#17329172)
I don't know why operators are the way they are in Python, but to me it looks like an oversight, which ultimately let to the "operator" module, exposing all operators as functions
Re:Lambdas and Functions in Python by guitarbill on Saturday June 16, 2018 @06:02PM (#17329709)
At the risk of oversimplifying/getting the subtleties wrong, operators are syntactic sugar to call magic methods. You could still call the magic method itself:

  >>> a = 1
  >>> a.__add__(2)
  3
  >>> b = []
  >>> b.__len__()
  0
It's rare I have to use the "operator" module, and I find Python pretty well thought out w.r.t. consistency. All in all, seems fine to me.
Re:Lambdas and Functions in Python by chriswarbo on Monday June 18, 2018 @12:57PM (#17339729)
> You could still call the magic method itself

Only if you have the first argument available. As a silly example, we might want to do the following (in analogy to the built-in `sum` function):

    product = lambda vals: reduce(operators.__mult__, vals, 1)
We can't use a bound `__mult__` method for situations like this.

More generally, looking up methods from particular objects forces our code to be "first order", i.e. we have to explicitly deal with intermediate results which don't appear in higher-order programming. For the `product` case we could do:

    def product(vals):
      result = 1
      for val in vals:
        result *= val
      return result
3/5 of these lines deal with `result`, which doesn't appear at all in the `reduce` version. The same thing happens with stuff like composition too, e.g. the `x` in `lambda x: foo(bar(x))` when we could just `compose(foo, bar)`.

When code is bound up in methods, we're often forced to expose these intermediate values, in order to call their methods. Of course, we can abstract over such boilerplate too, with functions like `lambda o, m: o.__getattribute__(m)`, etc. but at that point we're fighting against the language.

PS: Yes, I know Guido doesn't like `reduce` and moved it out into `functools` for Python 3.