Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Console Function that Returns a Value #168

Closed
easilyBaffled opened this issue Dec 19, 2019 · 3 comments
Closed

Add a Console Function that Returns a Value #168

easilyBaffled opened this issue Dec 19, 2019 · 3 comments

Comments

@easilyBaffled
Copy link

The purpose of this proposal is to introduce a console function that can fit inline with existing code rather than having to be a stand-alone statement. A function like this could simplify the developer experience and reduce the potential of human error.

The Case

Many of the commonly used features introduced since ES6 have been expression alternatives to block statements or new features that support an expressive style of writing. For example:
- map, filter, reduce
- Promise, await
- () => ({})
- Rest and Spread Operators
As a result, a lot of code is written so that one expression can feed into another with concise syntax. For Example:

const pick = (...keys) => obj =>
  Object.fromEntries(
    Object.entries(obj).filter(entry => keys.includes(entry[0]))
  );
const groupBy = groupingPropName => (groups, obj) => ({
  ...groups,
  [obj[groupingPropName]]: [...(groups[groupingPropName] || []), obj],
});

const groupped = arr.reduce(groupBy('type'), {});

console.log does not fit in these examples. While console.log is technically a CallExpression it is most often treated as a Statement because it returns undefined. As a result, anyone writing in an expressive style has to rewrite their code to accommodate for that result. It is a cumbersome and tedious process. More than that, though, all of that writing and rewriting introduces new opportunities for typos and errors.

A Solution

I want to propose a new console function. It takes in any number of values, logs all of the values, but only returns the first value. Something like:

( v, ...rest ) => { 
    console.log( v, …rest );
    return v;
}

By doing this, the logging function could be used inline with just about any expression without requiring a rewrite. It would have no functional impact on the code around it.

For the following examples I am going use this new function, and call it console.exp.

Use Cases

These examples are also available in a live sandbox.

In Function Composition

var userID = getUserId(
    JSON.parse(console.exp(localStorage.getItem( 'user' ))) 
);
With console.log
const user = localStorage.getItem( 'user' );
console.log(user)

var userID = getUserId(
    JSON.parse(user) 
);

Around Dot Chaining

const result = console.exp(['1', '2', 'zero' , 3, 4, 5]
    .map(parseNumbers)
    .filter(removeEvens)) // `exp` will log the result of map & filter
    .reduce(( acc, v ) => Math.max(acc, v));
With console.log
const filteredRes = ['1', '2', 'zero' , 3, 4, 5]
    .map(parseNumbers)
    .filter(removeEvens)
console.log(filteredRes)

const result = filteredRes
    .reduce(( acc, v ) => Math.max(acc, v));

Pass through Promise.then

fetch(url)
    .then( res => res.json() )
    .then( console.exp )
    .then( calculate )
With console.log
fetch(url)
    .then( res => res.json() )
    .then( res => ( console.log(res), res ) )
    .then( calculate )

Returning an ObjectExpression

const pickAndFormatTransaction = ( {
        amount,
        date
} ) => console.exp( {
        amount: console.exp(Number( amount ))
            ? formatCurrency( amount ) 
            : amount,
        date: console.tap(moment( date ).format( 'DD/MM/YYY' ))
} );
With console.log
const pickAndFormatTransaction = ({ amount, date }) => {
  const isNumber = Number(amount);
  console.log(isNumber);

  const formattedDate = moment(date).format('DD/MM/YYY');
  console.log(formattedDate);
  const res = {
    amount: isNumber ? formatCurrency(amount) : amount,
    date: formattedDate,
  };
  console.log(res);

  return res;
};

Additional Resources

I have a more thorough post on Dev.To about this Why (We) Make Room For console.log?
And an npm module, which includes a polyfill.

@domfarolino
Copy link
Member

Thanks for the proposal.

I want to propose a new console function. It takes in any number of values, logs all of the values, but only returns the first value. Something like:

This seems to solve a problem for very specific / certain ways of writing code, and is otherwise extremely easily poly-fillable as you've shown. I'm not sure how much of a place there is for this in the standard, as it seems like a very niche addition solving a developer ergonomic annoyance, and slightly reminds me of #155, in that I'm tempted to say this is out-of-scope.

Happy to hear other opinions from e.g., @terinjokes though.

@terinjokes
Copy link
Collaborator

I took a look at a few functional programming languages. I noticed that among them the equivalent of a console.log are treated as functions that perform side effects (or cause IO) and return an equivalent of undefined or void.

I'm not sure this is something that needs to be added to console. Collection libraries already have support for handling side effects (such as _.tap or RxJS.tap) which would be far more flexible than adding it here.

@domfarolino
Copy link
Member

Thanks for taking a look. Given that there’s not too much precedent for this and it seems slightly out-of-scope, but again, thanks so much for the easy to understand and well-formatted proposal. Feel free to let me know if you have any questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants