*On `where`*

History: This debate is on-going since May 2014.

The aggregate claim: `where` clauses are superior to `let-in` both 
technically
and aesthetically. It was a mistake from the beginning to choose `let` over
`where`. They should, at the very least, coexist.

Below I've summarized arguments made both for and against adding `where` to
Elm. A topic tagged with "For" means it argues in favour of adding `where`.
"Against" means the opposite.

*Technical Arguments*

***For: Intent First***

Elm is FP, and therefore lends itself to declarative programming. The
following is easier for devs to read, thus increasing code 
comprehensibility,
thus reducing dev time, thus saving companies money:

foo : (List A, Int)                                                         
                              
foo = (my ++ intent, goes - here)                                           
                              
  where my = ...                                                           
                               
        intent = ...                                                       
                               
        goes = ...                                                         
                               
        here = ...                                                         
                               

Post by Yashaka detailing why `where` is better for declarative programming:
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-207841658

Downside-up breaks logical flow:
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-221263715

There have also been multiple copy-cat issues opened on Github, detailing
this as the primary reason to add `where`.

***For: Intent-to-return-type Distance***

Minimizing the distance between your "intent" and your return type increases
the ability to understand a function.

foo : (List A, Int)                                                         
                              
foo = (my ++ intent, goes - here)                                           
                              
  where ...                                                                 
                              

Our eyes move very little when confirming the type of our intent. To 
contrast:

foo : (List A, Int)                                                         
                              
foo =                                                                       
                              
  let my = ...                                                             
                               
      intent = ...                                                         
                               
      goes = ...                                                           
                               
      here = ...                                                           
                               
  in (my ++ intent, goes - here)                                           
                               

This causes the "zig-zag" reading as mentioned elsewhere.

***For: "let" goes against Elm's own style guide***

`let` causes "dirtier" git diffs after changing a function:
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-269137011

***Against: `let` can be used in lambdas, `where` can't***

Claim: `let` is more general than `where`.
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-103122010

My thought: Never use `let` in a lambda. Combining local definitions and
anonymous functions is always an anti-pattern. If your lambda gets to the
point where you need bound names to simplify things, factor all of it out
into a `where` below the function:

-- | Haskell
bar :: [a] -> b                                                             
                              
bar = foldl f someAccVal                                                   
                               
  where f acc x = ... -- complicated lambda                                 
                              

A real example: 
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-103349671

***Against: Use "let" more cleverly***

>From Joey Eremondi:

> Use:
 let
   ret = some_expresssion_with_p1_to_pk
   p1 = e1
   ...
   pk = ek
 in
   ret

The idea being that you gain the advantage of declaring "intent first" using
existing syntax. Yet this pattern could be called unidiomatic by Elm's own
standards. Also, as mentioned by Oliver, you need to "zig-zag read" anyway
to make sure `ret` was used correctly in the "in" section.

*Philosophical Arguments*

***Against: `let` "resonates" with JS devs more***

>From Evan:

> Is this something that registers at all for a JS programmer?

>From Max:

> I think let-clauses are much more natural coming from imperative 
languages,
> and Elm's target audience is JS devs, not Haskell devs.

This argument has never been a strong one to me. You're already asking JS
devs to learn an entirely new language with radically different syntax and
concepts. Yet "let" is supposed to make them feel at home somehow? No, if
they're already learning new syntax and a new paradigm, it is not a stretch
to ask them to get used to "intent first".

It doesn't matter what is intuitive to imperative programmers. Elm is not
imperative. If Evan didn't think FP was the superior paradigm, he wouldn't
have written an FP language, or used Haskell to write it.

***Against: There should be only one way to do things in Elm***

>From Max:

> Elm's philosophy has been "there's only one way to do it" ...

This is brought up often in these discussions and in the Elm guide. It's a
well-intentioned idea, but I don't think it matches the reality of
programming. Particularly, please explain why there are multiple ways to
call record fields in Elm:

foo.bar                                                                     
                              
                                                                            
                              
.bar foo                                                                   
                               

or why anonymous functions can semantically collide with `let` statements:

let x = a in b                                                             
                               
                                                                            
                              
(\x -> b) a                                                                 
                              


Yes, any `let` expression can be replaced by a series of lambdas using the Y
combinator. Should we do that instead? No, of course not.

***Against: Elm is not Haskell***

>From Janis:
> All I was arguing against was claims that Elm must add where, "because 
Haskell".

Is Evan obligated to implement every aspect of Haskell into Elm? No, of
course not. However, taking a wider view of things, Elm *is* Haskell. The
syntax and concepts are so heavily inspired by Haskell that apart from:

- `::` becoming `:` in function signatures
- slightly different `import` syntax

that I'd argue 99% of Elm code in the wild today is parsable as legal
Haskell. If it's already mostly Haskell, why choose to cut `where`? I
understand the motivation for cutting typeclasses, but it makes no sense to
"draw the line" for borrowed features at `where` when so many people are
asking for it.

*Meta Arguments*

***Medical condition***

One dev admitted to a medical condition such that `let`'s "intent last"
style makes it extremely physically difficult for him to read Elm code:
https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-269231195

***On Alienating Haskellers***

> Haskellers are not Elm's target audience, JS programmers are.

My original comment from the thread:

> Given that Haskellers were the initial adopters, Evan and the rest of the
> Elm core team have to realize they alienate their original users by taking
> this attitude.

> All power to Elm if its goal is to "win" the frontend stack race. I really
> hope that happens. It's unfortunate that Elm thinks it has to be "easy" 
and
> must avoid advanced concepts at all costs in order to be useful/adoptable.

We're trying to help you (re: `where` and polymorphism/typeclasses).
Alienating us while infantalizing your target audience will leave you as the
smartest kid in the room.

https://github.com/elm-lang/elm-compiler/issues/621#issuecomment-221053554

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to