I mean, it's not a problem when it's just a few lines, but when you have a lot of code, and you have to scroll further down to see, what do parts of it mean, and then jump back... It just seems backwards to me.
And yes, I know there is "let ... in", and if I ever start writing in functional languages I will use it, but when reading functional programs, I see way more "where" than "let ... in".
It's the same thing you'd have to do when the code was factored out into separate functions, which is generally (though not universally) seen as good practice in those circumstances in languages that don't have `where`. You want to be able to see a high level overview of what the function is doing and then drill down into the details, rather than be overwhelmed by all the details right from the start.
Nevertheless, functions (with names) differ from 'where' clauses in precisely that: they have a name, and ideally, a function's name might tell you everything you need to know about it, though in practice, it is hard to fully and unambiguously state a function's contract in its name, especially if it has side effects.
I doubt it is possible for a language to be such that everything that matters in understanding a given part is always lexically local. I think we need to look to tools, rather than syntax, to help with that.
Huh? What's the difference in "naminess" between:
bar x = ... foo x y = bar (x + y)
foo x y = bar (x + y) where bar x = ... ?
I always think that let ... in ... can also use where. My mistake.
A brief skim over the revised definition of Standard ML indicates that it was abandoned at some point. I've no idea if Caml or OCaml kept it.
That said, I'm reasonably sure that the syntactic construct (insofar is it is used in programming languages) originated with the ISWIM introduced in this paper, which was rather influential in its day, perhaps especially in the functional programming community.
Here is a version of LCF with that first ML from 1977: https://github.com/theoremprover-museum/LCF77
> ML (Meta Language) is a general-purpose functional programming language. It has roots in Lisp, and has been characterized as "Lisp with types". It is known for its use of the polymorphic Hindley–Milner type system, which automatically assigns the types of most expressions without requiring explicit type annotations, and ensures type safety – there is a formal proof that a well-typed ML program does not cause runtime type errors.