Proposal: switch expressions
David Koblas
david at koblas.com
Tue Feb 26 18:34:17 UTC 2019
Jordan,
Thanks for taking time to read and provide thoughts.
I just back and re-read the pattern matching proposal and it still fails
on the basic requirement of being an Expression not a Statement. The
problem that I see and want to address is the need to have something
that removes the need to chain trinary expressions together to have an
Expression.
This is unmaintainable --
const x = v === 'foo' ? 1 : v === 'bar' ? 3 : v === 'baz' ? 6 : 99;
This is maintainable, but is less than ideal:
let x;
switch (v) {
case "foo":
x = 1;
break;
case "bar":
x = 3;
break;
case "baz":
x = 6;
break;
default:
x = 99;
break;
}
Pattern matching does shorten the code, but you have a weird default
case and also still end up with a loose variable and since pattern
matching is a statement you still have a initially undefined variable.
let x;
case (v) {
when "foo" -> x = 1;
when "bar" -> x = 3;
when "baz" -> x = 6;
when v -> x = 99;
}
Let's try do expressions, I'll leave people's thoughts to themselves.
const x = do {
if (v === "foo") { 1; }
else if (v === "bar") { 3; }
else if (v === "baz") { 6; }
else { 99; }
}
Or as another do expression variant:
const x = do {
switch (v) {
case "foo": 1; break;
case "bar": 3; break;
case "baz": 6; break;
default: 99; break;
}
}
And as I'm thinking about switch expressions:
const x = switch (v) {
case "foo" => 1;
case "bar" => 3;
case "baz" => 6;
default => 99;
}
What I really like is that it preserves all of the normal JavaScript
syntax with the small change that a switch is allowed in an expression
provided that all of the cases evaluate to expressions hence the use of
the '=>' as an indicator. Fundamentally this is a very basic concept
where you have a state machine and need it switch based on the current
state and evaluate to the new state.
const nextState = switch (currentState) {
case ... =>
}
On 2/25/19 4:00 PM, Jordan Harband wrote:
> Pattern Matching is still at stage 1; so there's not really any
> permanent decisions that have been made - the repo theoretically
> should contain rationales for decisions up to this point.
>
> I can speak for myself (as "not a champion" of that proposal, just a
> fan) that any similarity to the reviled and terrible `switch` is
> something I'll be pushing back against - I want a replacement that
> lacks the footguns and pitfalls of `switch`, and that is easily
> teachable and googleable as a different, distinct thing.
>
> On Mon, Feb 25, 2019 at 12:42 PM David Koblas <david at koblas.com
> <mailto:david at koblas.com>> wrote:
>
> Jordan,
>
> One question that I have lingering from pattern matching is why is
> the syntax so different? IMHO it is still a switch statement with
> a variation of the match on the case rather than a whole new
> construct.
>
> Is there somewhere I can find a bit of discussion about the
> history of the syntax decisions?
>
> --David
>
>
> On Feb 25, 2019, at 12:33 PM, Jordan Harband <ljharb at gmail.com
> <mailto:ljharb at gmail.com>> wrote:
>
>> Additionally, https://github.com/tc39/proposal-pattern-matching -
>> switch statements are something I hope we'll soon be able to
>> relegate to the dustbin of history.
>>
>> On Mon, Feb 25, 2019 at 6:01 AM David Koblas <david at koblas.com
>> <mailto:david at koblas.com>> wrote:
>>
>> I quite aware that it’s covered in do expressions. Personally
>> I find do expressions non-JavaScript in style and it’s also
>> not necessarily going to make it into the language.
>>
>> Hence why I wanted to put out there the idea of switch
>> expressions.
>>
>> --David
>>
>>
>> On Feb 25, 2019, at 5:28 AM, N. Oxer <blueshuk2 at gmail.com
>> <mailto:blueshuk2 at gmail.com>> wrote:
>>
>>> Hi,
>>>
>>> This would be covered by do expressions
>>> <https://github.com/tc39/proposal-do-expressions>. You could
>>> just do:
>>>
>>> ```js
>>> const category = do {
>>> switch (...) {
>>> ...
>>> };
>>> };
>>> ```
>>>
>>> On Sun, Feb 24, 2019 at 10:42 AM David Koblas
>>> <david at koblas.com <mailto:david at koblas.com>> wrote:
>>>
>>> After looking at a bunch of code in our system noted
>>> that there are many
>>> cases where our code base has a pattern similar to this:
>>>
>>> let category = data.category;
>>>
>>> if (category === undefined) {
>>> // Even if Tax is not enabled, we have defaults
>>> for incomeCode
>>> switch (session.merchant.settings.tax.incomeCode) {
>>> case TaxIncomeCode.RENTS_14:
>>> category = PaymentCategory.RENT;
>>> break;
>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17:
>>> category = PaymentCategory.SERVICES;
>>> break;
>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17:
>>> category = PaymentCategory.SERVICES;
>>> break;
>>> }
>>> }
>>>
>>> I also bumped into a block of go code that also
>>> implemented similar
>>> patterns, which really demonstrated to me that there
>>> while you could go
>>> crazy with triary nesting there should be a better way.
>>> Looked at the
>>> pattern matching proposal and while could possibly help
>>> looked like it
>>> was overkill for the typical use case that I'm seeing.
>>> The most relevant
>>> example I noted was switch expressions from Java. When
>>> applied to this
>>> problem really create a simple result:
>>>
>>> const category = data.category || switch
>>> (setting.incomeCode) {
>>> case TaxIncomeCode.RENTS_14 => PaymentCategory.RENT;
>>> case TaxIncomeCode.ROYALTIES_COPYRIGHTS_12 =>
>>> PaymentCategory.ROYALTIES;
>>> case
>>> TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17 =>
>>> PaymentCategory.SERVICES;
>>> default => PaymentCategory.OTHER;
>>> }
>>>
>>> Note; the instead of using the '->' as Java, continue to
>>> use => and with
>>> the understanding that the right hand side is
>>> fundamentally function.
>>> So similar things to this are natural, note this
>>> proposal should remove
>>> "fall through" breaks and allow for multiple cases as such.
>>>
>>> const quarter = switch (foo) {
>>> case "Jan", "Feb", "Mar" => "Q1";
>>> case "Apr", "May", "Jun" => "Q2";
>>> case "Jul", "Aug", "Sep" => "Q3";
>>> case "Oct", "Nov", "Dec" => { return "Q4" };
>>> default => { throw new Error("Invalid Month") };
>>> }
>>>
>>> Also compared this to the do expression proposal, it
>>> also provides a
>>> substantial simplification, but in a way that is more
>>> consistent with
>>> the existing language. In one of their examples they
>>> provide an example
>>> of the Redux reducer
>>> https://redux.js.org/basics/reducers#splitting-reducers
>>> -- this would be
>>> a switch expression implementation.
>>>
>>> function todoApp(state = initialState, action) =>
>>> switch
>>> (action.type) {
>>> case SET_VISIBILITY_FILTER => { ...state,
>>> visibilityFilter:
>>> action.filter };
>>> case ADD_TODO => {
>>> ...state, todos: [
>>> ...state.todos,
>>> {
>>> text: action.text,
>>> completed: false
>>> }
>>> ]
>>> };
>>> case TOGGLE_TODO => {
>>> ...state,
>>> todos: state.todos.map((todo, index) =>
>>> (index ===
>>> action.index) ? { ...todo, completed: !todo.completed }
>>> : todo)
>>> };
>>> default => state;
>>> }
>>>
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss
>>
On 2/25/19 3:42 PM, David Koblas wrote:
> Jordan,
>
> One question that I have lingering from pattern matching is why is the
> syntax so different? IMHO it is still a switch statement with a
> variation of the match on the case rather than a whole new construct.
>
> Is there somewhere I can find a bit of discussion about the history of
> the syntax decisions?
>
> --David
>
>
> On Feb 25, 2019, at 12:33 PM, Jordan Harband <ljharb at gmail.com
> <mailto:ljharb at gmail.com>> wrote:
>
>> Additionally, https://github.com/tc39/proposal-pattern-matching -
>> switch statements are something I hope we'll soon be able to relegate
>> to the dustbin of history.
>>
>> On Mon, Feb 25, 2019 at 6:01 AM David Koblas <david at koblas.com
>> <mailto:david at koblas.com>> wrote:
>>
>> I quite aware that it’s covered in do expressions. Personally I
>> find do expressions non-JavaScript in style and it’s also not
>> necessarily going to make it into the language.
>>
>> Hence why I wanted to put out there the idea of switch expressions.
>>
>> --David
>>
>>
>> On Feb 25, 2019, at 5:28 AM, N. Oxer <blueshuk2 at gmail.com
>> <mailto:blueshuk2 at gmail.com>> wrote:
>>
>>> Hi,
>>>
>>> This would be covered by do expressions
>>> <https://github.com/tc39/proposal-do-expressions>. You could
>>> just do:
>>>
>>> ```js
>>> const category = do {
>>> switch (...) {
>>> ...
>>> };
>>> };
>>> ```
>>>
>>> On Sun, Feb 24, 2019 at 10:42 AM David Koblas <david at koblas.com
>>> <mailto:david at koblas.com>> wrote:
>>>
>>> After looking at a bunch of code in our system noted that
>>> there are many
>>> cases where our code base has a pattern similar to this:
>>>
>>> let category = data.category;
>>>
>>> if (category === undefined) {
>>> // Even if Tax is not enabled, we have defaults for
>>> incomeCode
>>> switch (session.merchant.settings.tax.incomeCode) {
>>> case TaxIncomeCode.RENTS_14:
>>> category = PaymentCategory.RENT;
>>> break;
>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17:
>>> category = PaymentCategory.SERVICES;
>>> break;
>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17:
>>> category = PaymentCategory.SERVICES;
>>> break;
>>> }
>>> }
>>>
>>> I also bumped into a block of go code that also implemented
>>> similar
>>> patterns, which really demonstrated to me that there while
>>> you could go
>>> crazy with triary nesting there should be a better way.
>>> Looked at the
>>> pattern matching proposal and while could possibly help
>>> looked like it
>>> was overkill for the typical use case that I'm seeing. The
>>> most relevant
>>> example I noted was switch expressions from Java. When
>>> applied to this
>>> problem really create a simple result:
>>>
>>> const category = data.category || switch
>>> (setting.incomeCode) {
>>> case TaxIncomeCode.RENTS_14 => PaymentCategory.RENT;
>>> case TaxIncomeCode.ROYALTIES_COPYRIGHTS_12 =>
>>> PaymentCategory.ROYALTIES;
>>> case TaxIncomeCode.INDEPENDENT_PERSONAL_SERVICE_17 =>
>>> PaymentCategory.SERVICES;
>>> default => PaymentCategory.OTHER;
>>> }
>>>
>>> Note; the instead of using the '->' as Java, continue to use
>>> => and with
>>> the understanding that the right hand side is fundamentally
>>> function.
>>> So similar things to this are natural, note this proposal
>>> should remove
>>> "fall through" breaks and allow for multiple cases as such.
>>>
>>> const quarter = switch (foo) {
>>> case "Jan", "Feb", "Mar" => "Q1";
>>> case "Apr", "May", "Jun" => "Q2";
>>> case "Jul", "Aug", "Sep" => "Q3";
>>> case "Oct", "Nov", "Dec" => { return "Q4" };
>>> default => { throw new Error("Invalid Month") };
>>> }
>>>
>>> Also compared this to the do expression proposal, it also
>>> provides a
>>> substantial simplification, but in a way that is more
>>> consistent with
>>> the existing language. In one of their examples they
>>> provide an example
>>> of the Redux reducer
>>> https://redux.js.org/basics/reducers#splitting-reducers --
>>> this would be
>>> a switch expression implementation.
>>>
>>> function todoApp(state = initialState, action) => switch
>>> (action.type) {
>>> case SET_VISIBILITY_FILTER => { ...state,
>>> visibilityFilter:
>>> action.filter };
>>> case ADD_TODO => {
>>> ...state, todos: [
>>> ...state.todos,
>>> {
>>> text: action.text,
>>> completed: false
>>> }
>>> ]
>>> };
>>> case TOGGLE_TODO => {
>>> ...state,
>>> todos: state.todos.map((todo, index) => (index ===
>>> action.index) ? { ...todo, completed: !todo.completed } : todo)
>>> };
>>> default => state;
>>> }
>>>
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org <mailto:es-discuss at mozilla.org>
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20190226/89412436/attachment-0001.html>
More information about the es-discuss
mailing list