[swift-evolution] Stdlib closure argument labels and parameter names

Charlie Monroe charlie at charliemonroe.net
Mon Jun 27 00:10:24 CDT 2016


> I like `predicate`. I endorse `predicate`. Does this mean the rule of "must
> read like a sentence" can be overturned for things like "comparison" and
> "order"? If so, woo!

I've suggested that a few emails back as well, but I've asked myself if it's not a bit confusing when you have (NS)Predicate - if it doesn't seem like something taking the Predicate object argument instead of a block.

> 
>> 
>>> I get the `is` desire but it's being tossed away in a lot of other
>>> places in this diff. and `suchThat` feels out of place.
>> 
>> I think I'm pretty strongly sold on “soEach” as a label for closures in
>> all the filtering components.
> 
> To quote greatness:, "I personally find `soEach` repulsive".
> (cite: http://article.gmane.org/gmane.comp.lang.swift.evolution/16998/match=repulsive <http://article.gmane.org/gmane.comp.lang.swift.evolution/16998/match=repulsive>)
> 
>> 
>>> -      || u16.contains({ $0 > 127 || _isspace_clocale($0) }) {
>>> +    || u16.contains(elementWhere: { $0 > 127 || _isspace_clocale($0) }) {
>>> 
>>> I assume the challenge here is differentiating contains(element) from contains(closure).
>>> This feels predicate-y, which is why I put it near the predicates. But I think something
>>> like `containsElement(where:)` works better.
>> 
>> I understand your motivation for suggesting it.  The downside is that it
>> severs the strong basename relationship between algorithms that do
>> effectively the same things, one using a default comparison and the
>> other using an explicitly-specified one.  I'm truly not sure where we
>> ought to land on this one.
> 
> May I recommend `predicate:` then since it looks like that's actually a possibility?
> 
>> 
>>> -    let result = try base._withUnsafeMutableBufferPointerIfSupported(body)
>>> +    let result = try base._withUnsafeMutableBufferPointerIfSupported(invoke: body)
>>> 
>>> I hate "ifSupported" 
>> 
>> Me too.
>> 
>>> but that's another discussion
>> 
>> Quite.  It's also an internal API so it's not an evolution issue.  The
>> point of having that change as part of the diff (as with all the other
>> use sites), is to observe how the changes affect real usage.
> 
> Woody Allen: "The heart wants what it wants"
> Me: "The spleen vents what it vents"
> 
>> 
>>> (withSupportedUnsafeMutableBufferPointer,
>>> withAvailableUnsafeMutableBufferPointer, it's all lipstick)
>>> 
>>> This is procedural, so `do` or `perform` rather than `invoke`
>>> 
>>> -      for test in removeFirstTests.filter({ $0.numberToRemove == 1 }) {
>>> +      for test in removeFirstTests.filter(
>>> +        suchThat: { $0.numberToRemove == 1 }
>>> 
>>> The difference between `filter` and `forEach` is that `forEach` is explicitly 
>>> procedural while `filter` is functional.  I do not like functional chainable
>>> calls being modified to use explicit external labels in this way. 
>>> 
>>> I'd prefer no label here.
>> 
>> Can you provide rationale for treating functional methods differently,
>> or is it just personal taste?
> 
> Functional programming flow. I follow Kevin Ballard's rule of parens around
> functional elements and naked braces for trailing closures that do not return
> values. This ensures the compiler is never confused at places like:
> 
> for x in foo when y.f{...} {
>     ...
> }
> 
> and instantly identifies to the reader when there's a non-returning scope, as
> in forEach or GCD dispatch.
> 
> However, if you use chaining and if the language insists on external label 
> preambles, which would not be seen when using the call with a trailing closure,
> it becomes far less readable and encourages people  to use trailing closures to 
> avoid the label, i.e. an attractive nuisance. Simple selectors encourage better fp:
> 
> let x = myStream.f1({...}).f2({...})
> 
>> 
>>> public func split(
>>>      maxSplits: Int = Int.max,
>>>      omittingEmptySubsequences: Bool = true,
>>> -    isSeparator: @noescape (Base.Iterator.Element) throws -> Bool
>>> +    separatedWhere isSeparator: @noescape (Base.Iterator.Element) throws -> Bool
>>> 
>>> I'm torn on this one. It's not the worst ever but something more like where/at/when
>>> makes more sense to me than
>>> "separatedWhere/separatedAt/separatedWhen".
>> 
>> The biggest reason to keep “separate” in the name is the connection with
>> the semantics of the other `split` method, that takes a single element
>> that is tested for equality.  I think this is very similar to the
>> `contains(elementWhere` vs `containsElement(where` discussion.  If you
>> leave “separate” out of the name it fails to imply that those elements
>> for which the predicate returns true are not present in the result.
> 
> `predicate` ftw.
> 
>> 
>>> 
>>> +      count: __manager._headerPointer.pointee.count)
>>> 
>>> For the sake of Zippy the Pinhead, surely there has to be something better than `pointee`.
>>> Like...`reference`?
>> 
>> It's not a reference; it's a value.  But that, my friend, is an
>> *entirely* different discussion. Let's try to stick to the scope of the
>> proposal: names and labels for parameters of function type, OK?
> 
> It was humor. It was at the end. I assumed the joke would lighten the
> previous complaints and bookend the positive support at the start of
> my message.
> 
>> 
>> -- 
>> -Dave
> 
> -- E
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160627/acf05890/attachment.html>


More information about the swift-evolution mailing list