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

Allow passing a function to join #30328

Closed
wants to merge 1 commit into from
Closed

Allow passing a function to join #30328

wants to merge 1 commit into from

Conversation

ararslan
Copy link
Member

@ararslan ararslan commented Dec 9, 2018

Patterns such as join(map(uppercase, xs)) can now be written more succinctly and efficiently as join(uppercase, xs). I've found myself wanting this often lately.

I've set the !!! compat notice to 1.1, but I can change it to 1.2 or whatever as needed.

Patterns such as `join(map(uppercase, xs))` can now be written more
succinctly and efficiently as `join(uppercase, xs)`.
@ararslan ararslan added domain:strings "Strings!" kind:feature Indicates new feature / enhancement requests labels Dec 9, 2018
@vtjnash
Copy link
Sponsor Member

vtjnash commented Dec 9, 2018

Alternatively: join((uppercase(x) for x in xs), "") ?

Or as implementation:
join([io, ]f::Function, iter, vargs...) = join([io, ](f(x) for x in iter), vargs...)

@KristofferC
Copy link
Sponsor Member

KristofferC commented Dec 9, 2018

Yeah, using generators here seems more composable and general than adding function arguments to everything?

@ararslan
Copy link
Member Author

I wholeheartedly disagree. What's the point of first-class functions and other features from functional programming if you don't get to use them? This isn't Python; littering everything with generators does not improve efficiency or readability.

@fredrikekre
Copy link
Member

FWIW it is not that obvious what the function argument does, I thought it would decide how to join, with print beeing the default`.

@ararslan
Copy link
Member Author

It seems fairly obvious and consistent to me, since other places we allow function arguments, they (almost?) always mean "map this function across the input during the reduction operation."

@StefanKarpinski
Copy link
Sponsor Member

The other ones are generally reducers of some kind like maximum(transform, collection). This doesn't fit that general pattern at all. Where do we stop? Any function that iterates over anything could potentially apply a transformation first. Should we have reverse(transform, collection) to reverse a collection while also transforming each element?

@ararslan
Copy link
Member Author

This doesn't fit that general pattern at all.

I would argue that it does, as it's equivalent to prod, which accepts a function argument.

@andyferris
Copy link
Member

I've noticed a growing number of these types of "map as you go" methods for functions. I'd raise a couple points:

  • Keyword arguments might be less disruptive. (Caveat is the do syntax, but I do wonder if this may be clearer overall, such as join(itr, ""; map = uppercase))
  • I feel this pattern indicates a general desire to have lazy map operation or similar, so users can compose two or more very simple functions, e.g. join(mapped(uppercase, itr), "". Note: I'm not sure generator syntax is alwways ideal and that Generatoris always as useful as e.g. aMappedArray` could be).

Such a discussion might deserve it's own issue, I suppose. (Perhaps this has already been discussed somewhere already?)

Yeah, using generators here seems more composable and general than adding function arguments to everything?

I wholeheartedly disagree. What's the point of first-class functions and other features from functional programming if you don't get to use them?

First-class functions allow you to build lazily mapped containers efficiently, which lets us seperate the concerns of the mapping and the joining to two different operations. This seperation of concerns feels like better software engineering to me, rather than having to add the "lazy mapping" comcept to each and every function in Base.

@ararslan
Copy link
Member Author

rather than having to add the "lazy mapping" comcept to each and every function in Base.

I don't get why people seem to be taking this addition to that extreme. There is a fairly clear set of functions that should support this, namely reduction operations, which hardly constitutes "every function in Base."

@ararslan ararslan closed this May 2, 2020
@ararslan ararslan deleted the aa/join-function branch May 2, 2020 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:strings "Strings!" kind:feature Indicates new feature / enhancement requests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants