6 ms·
Why is `shuffled()` a function and `first` a property? Seems weird and not simple.
by romanovcode 7y ago
Why is `shuffled()` a function and `first` a property? Seems weird and not simple.
- saagarjha 7y agoWhile you are free to implement functions and properties however you like, usually it's pretty clear which one is which. shuffled performs non-trivial computation and doesn't seem like an intrinsic property of the array, so it's a function; the opposite is true for first.
- skohan 7y agoAlso on an immutable array, `first` should always return the same value where `shuffled()` may return different values each time it's called.
- ninjaoxygen 7y agoIf it anything like C#, .shuffled needs to return a new object and has some expense incurred to achieve, so is a function/method, but .first is immediately available, requires only a trivial amount of calculation and does not return a new array/list, so is a property.
- the_duke 7y agoYeah first being a property is weird to me too. Although I do believe Swift has "virtual properties" that are really a method under the hood.
- deleted 7y ago[deleted]
- skohan 7y agoThe reverse seems weird to me. Things like the first element, or the count of an array seem conceptually more like properties than functions: they're just values derived from the data structure. The fact that you need to use function call syntax for things like this in other languages seems like it is unnecessarily exposing implementation details to the API because of limitations of the language.
- romanovcode 7y agoOr maybe they just opt for it for the simplicity sake? Just like said above, the first is just a magic getter which is a function underneath anyway.
- skohan 7y agoBut why should I as the user of an interface care whether something is implemented as a function or whether it's just a reference to a pure value? For instance, let's imagine in some C++-like language I had two list implementations: one static and one dynamic: class StaticList { ... int count; // set at initialization time } class DynamicList { ... int count() { ... // compute the count dynamically return count; } } Here `count` is conceptually the same between these two implementations, but if I want to get that value, I have to access it differently: int c1 = staticList.count; int c2 = dynamicList.count(); But that difference is essentially an implementation detail which means nothing to the client. The Swift way just lets me express my interface however I decide is most fitting.
- dbaupp 7y agoThere is a useful distinction between "properties" and "functions" that appears in some languages: properties exist in memory and so can be addressed. This is particularly important for "systems"/low-level programming, where addresses are often manipulated directly and need to be stable/controlled. In languages like C, C++ and Rust, properties are things that are definitely in memory, and functions/methods are things that may not be. If you have an interface like `count` that may be dynamic, it should be uniformly expressed as a method/function (that may have a trivial "return count;" implementation). On the other, Swift has to put a non-trivial amount of infrastructure into making sure all the things with property syntax can behave as if they are backed by memory, so that an address/pointer can be generated for them (in the general case, a temporary pointer, that becomes invalid quickly).
- kibwen 7y agoThe reason that performance-oriented languages like C++ and Rust make a distinction there is to make it easier for someone reading the code to understand the performance implications of a piece of code. Accessing a field involves jumping to a statically-known offset, which is a minor and predictable cost, whereas calling a function could have any cost imaginable. It's reasonable for languages that prioritize ergonomics over extreme performance to make the decision to paper over that distinction.
- rimliu 7y agoshuffled() can accept randomness generator, this form just uses the default. Also .shuffled() returns a new array. For in-place shuffling there is .shuffle(). This pattern is consistent: verb() is for in-place actions, verbed() if for actions returning a new collection e.g. sort()/sorted(). Btw, there is also .first(where:) which accepts a predicate.
- jonhohle 7y agoContrast that to Objective C < 2, Ruby, or Smalltalk where everything is a message sent to the object and there are no exposed, public fields.
- wool_gather 7y agoYou're misremembering. Prior to ObjC 2, classes indeed exposed fields. Convention was that you should not touch them and use accessors instead, but they were most definitely there, declared in the `@interface`. @interface Foo : NSObject { NSString * name; NSInteger count; } - (NSString)name; - (void)setName:(NSString *)newName; - (NSInteger)count; @end (This is still legal, of course, but bad practice now that there's `@property` synthesis as well as ivars being declarable in either an extension or the `@implementation` block.)
- bobbylarrybobby 7y agoA couple reasons, which are used consistently throughout Swift: Shuffled may accept arguments. First does not The runtime cost of first is nearly zero, whereas shuffled is doing significant work (constant versus linear time) It sort of doesn’t matter because autocomplete won’t let you do the wrong thing.