Proposal: switch expressions

David Koblas david at koblas.com
Sun Feb 24 16:42:41 UTC 2019


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;
     }





More information about the es-discuss mailing list