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

Any interest in adding a format string function? #1970

Closed
yosbelms opened this issue Nov 11, 2016 · 5 comments
Closed

Any interest in adding a format string function? #1970

yosbelms opened this issue Nov 11, 2016 · 5 comments

Comments

@yosbelms
Copy link

It takes a string and an object, and returns a formatted string:

String -> Object -> String

// basic
R.format('Hello {0}!', ['World'])

// curried
var hello = R.format('Hello {0}!')
hello(['World'])

// with objects
R.format('Welcome {name}', {name: john})

String placeholders are also an alternative, something like % or ? but I see the micro-template style {key} more flexible because values can be repeated, example:

var msg = 'Error in "{0}" function, read more at http://project.com/docs/api/{0}.html'
R.format(msg, ['createComponet'])

//Error in "createComponet" function, read more at http://project.com/docs/api/createComponet.html

Another advantage of the micro-template style is that allows to select both, object properties and numeric indexes.

Any thought on this?

@buzzdecafe
Copy link
Member

This is essentially simplified sprintf? I can see the utility of it, but I am doubtful that it belongs in the core lib.

@yosbelms
Copy link
Author

A real life example, the code in https://github.com/ramda/ramda/blob/master/scripts/build#L125-L143 The lambda used as transformer in R.cond:

function(ast) {
    abort('Dependency declared with different variable name: `' +
      ast.id.name + '` & `' +
      ast.init.arguments[0].value +
      '` in ' + ast.loc.source
    );
  }

could be refactored using R.format like:

R.pipe(
    R.juxt([
        R.path(['id', 'name']),
        R.path(['init', 'arguments', '0', 'name']),
        R.path(['loc', 'source']),
    ]),
    R.format('Dependency declared with different variable name: `{0}` & `{1}` in {2}'),
    abort
)

@uzantnomo
Copy link

For these simple cases using ES6 template literals wrapped in a function is enough.
If you want to add custom formatting for different types and common formats for numbers, I think it will be outside of Ramda's scope.

@yosbelms
Copy link
Author

For these simple cases using ES6 template literals wrapped in a function is enough.

ES6 template literals are not reusable outside of a function, because the are literals, hence statically evaluated. It is possible to use it with a dynamic context but needs to wrap it inside a function as you refer above.

R.format or R.sprintf makes it possible to evaluate it lazily, which looks more useful in cases when the template is treated as data, example:

// formated strings as data, from file system, db, config, networking, etc..
var mails = {
    candidate: 'Hello {0}, We liked your application and we want to see you in action....',
    rejected : 'Hello {0}, We are not interested in your skill set for now. Thank you very....',
}

// some data to iterate over
var candidates = [
    {
        fullName: 'John Doe',
        email: 'johndoe@gmail.com'
    },
    {
        fullName: 'Peter Pan',
        email: 'peterpan@gmail.com'
    },
]

// mock, just log
var sendMail = (email, msg) => console.log(email, msg)

// example usage
var mailCandidates = R.forEach(R.converge(
        sendMail, [
            R.prop('email'),
            R.pipe(R.prop('fullName'), R.format(mails.candidate)) ]))


// run
mailCandidates(candidates)

The only way ES6 template literals can be treated as data is by using eval but is hacky.

@davidchambers
Copy link
Member

I favour leaving this to string-format and other similar libraries.

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

No branches or pull requests

5 participants