Why copy the `lambda` naming? Just use `def`! (also change `closure` naming?)

Just sharing my thoughts on the newly added lambda expressions.

Mojo already deviates from python in lots of smaller or bigger details which I really appreciate!!

Copying the lambda naming is IMO not ideal:

  • name
  • syntax

Name

The word “lambda” does not provide any meaningful description.
Programmers only learned that the term “lambda” means something special in programming.

Suggestion

  • Lambda Expression → Anonymous function

Anonymous function is immediately super clear and easy to remember

Syntax

We already have:

# (standard) function
def add_one(x: Int) -> Int: return x + 1

# closure -> Capturing function
def add_one(x: Int) {} -> Int: return x + 1

Suggestions
Why not be consistent and just keep the existing syntax with lambda/anonymous functions?

# Instead of
lambda(x: Int) {} -> Int: x + 1

# use existing syntax
def(x: Int) {} -> Int: x + 1

Summary / Conclusion: Keep It Simple

3 Functions

  • (standard) function = Base :white_check_mark:
  • closure capturing function = Base + capture list {} → rename
  • lambda anonymous function = Base + capture list {} - function name - return keyword ==> remove lambda keyword use plain def

Any thoughts on this? :nerd_face: :fire:

Require (or at least allow) a space between def and (x: Int)?

(otherwise I like it, this is already the familiar idiom in JS, Go, etc.)

FWIW, def() -> Int (etc) syntax is already valid mojo code, it is used for function types.

:+1:

Example here:

def __wrap_and_execute_main[
main_func: def() thin -> None
](
argc: Int32,
argv: __mlir_type[!kgen.pointer<!kgen.pointer<scalar<ui8>>>],
) -> Int32: ...

In the syntax def(x: Int) {} -> Int: x + 1, the : followed by the function body would not be enough information to distinguish a function type and an function (typed) implementation?

The word “lambda” references Lambda calculus which dates back to the 1930s. It has nearly a century of meaning associated with it.

“What is easy for beginners” is not the only bar to measure by. “Anonymous function” is not the only or most relevant aspect of lambda functions, and what is “clear” to you is not clear for others. Clarity obtained through hiding behind abstract concepts is sweeping critical differences under the proverbial rug - it would introduce ambiguity that is clearly wrong in this case (IMHO)

The word “lambda” references Lambda calculus which dates back to the 1930s. It has nearly a century of meaning associated with it.

The thing is that 99.9% of developers do not know that and have no relation at all to the name lambda. They learned it like vocabulary without having any background knowledge. So for all of them it’s just a learned name and nothing with inherent meaning.

Also, already now but even more with AI the most important skill in the (programming) world(!) will IMO be clear and precise communication. And this across all domains and experience levels. Communication is king.

We already have AWS Lambda which is another point people might confuse.

“What is easy for beginners” is not the only bar to measure by.

Absolutely! But no one said that.
It is not like beginners just need to put in the effort to learn those names and in return there is a huge benefit as an experienced senior developer in having “fancy names”.

In the future there will be more and more (unexperienced) people across all domains using AI to get things done. AI narrows the gap between pure developers and business, requiring more business knowledge and understanding of devs and bringing more technical power to the business. If we try to keep the language clear, precise and simple we can communicate much better and more efficient.

One of my leading principle is always: Keep it simple.
Having just the one concept of “function” with different variants seems very clean and intuitive.
Often the best name needs to consider more context (like read+mut :cross_mark: , imm+mut :white_check_mark: )

The core issue with overloading def here is that def(T) -> R already occupies a non-terminal slot in the type grammar.

If def(...) is reused to instantiate anonymous function values inline, it creates immediate parsing ambiguity between type signatures and value expressions—especially in variable declarations and higher-order argument slots.

Keeping lambda as a distinct production rule keeps the expression AST cleanly separated from function type declarations without requiring heavier lookahead or grammar hacks.

In this case, “simple” would create unnecessary complications for the compiler. As expressed by H. L. Mencken: “For every complex problem there is an answer that is clear, simple, and wrong.”

I generally lean towards sticking with Python when there is no safety, performance, or semantic reason to change. If your proposal is to do exactly the same thing with a different syntax, then it probably (imo) adds more confusion than clarity - at least for anybody with familiarity with Python. It is yet another muscle memory that can not be used.