> On 14. Jan 2018, at 06:04, BJ Homer via swift-evolution > <swift-evolution@swift.org> wrote: > > An Angle type already exists in Foundation; see Measurement<UnitAngle>. You > could add some convenience methods in an extension pretty easily. > > import Foundation > > typealias Angle = Measurement<UnitAngle> > > extension Measurement where UnitType == UnitAngle { > var sine: Double { > let radians = self.converted(to: .radians).value > return sin(radians) > } > > static var threeQuarterTurn: Angle { > return Angle(value: 0.75, unit: .revolutions) > } > } > > let x = Angle.threeQuarterTurn > x.sine // -1 > > -BJ
Maybe it would be good to pitch such improvements to the Foundation API? “Angle” is certainly a lot more discoverable and convenient to type than “Measurement<UnitAngle>”. That said, I tend not to use Foundation’s Measurement API. It’s pretty heavyweight. test.swift: import Foundation @available(macOS 10.12, *) func a() { let a = Measurement(value: 20, unit: UnitDuration.minutes).converted(to: .seconds) } Generated IR: define hidden swiftcc void @_T04test1ayyF() #0 { entry: %0 = call %swift.type* @_T0So12UnitDurationCMa() #3 %1 = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0 %.kind = load i64, i64* %1, align 8 %isObjCClassWrapper = icmp eq i64 %.kind, 14 br i1 %isObjCClassWrapper, label %isWrapper, label %metadataForClass.cont isWrapper: ; preds = %entry %2 = bitcast %swift.type* %0 to %swift.type** %3 = getelementptr inbounds %swift.type*, %swift.type** %2, i64 1 %4 = load %swift.type*, %swift.type** %3, align 8, !invariant.load !31 br label %metadataForClass.cont metadataForClass.cont: ; preds = %isWrapper, %entry %.class = phi %swift.type* [ %0, %entry ], [ %4, %isWrapper ] %5 = bitcast %swift.type* %.class to %objc_class* %6 = load i8*, i8** @"\01L_selector(minutes)", align 8 %7 = bitcast %objc_class* %5 to i8* %8 = call %0* bitcast (void ()* @objc_msgSend to %0* (i8*, i8*)*)(i8* %7, i8* %6) %9 = bitcast %0* %8 to i8* %10 = call i8* @objc_retainAutoreleasedReturnValue(i8* %9) #4 %11 = bitcast i8* %10 to %0* %12 = bitcast %0* %11 to %TSo12UnitDurationC* %.asUnsubstituted = bitcast %TSo12UnitDurationC* %12 to %TSo4UnitC* %13 = call swiftcc { %TSo4UnitC*, double } @_T010Foundation11MeasurementVACyxGSd5value_x4unittcfC(double 2.000000e+01, %TSo4UnitC* %.asUnsubstituted, %swift.type* %0) %14 = extractvalue { %TSo4UnitC*, double } %13, 0 %15 = extractvalue { %TSo4UnitC*, double } %13, 1 %.asSubstituted = bitcast %TSo4UnitC* %14 to %TSo12UnitDurationC* %16 = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0 %.kind1 = load i64, i64* %16, align 8 %isObjCClassWrapper2 = icmp eq i64 %.kind1, 14 br i1 %isObjCClassWrapper2, label %isWrapper3, label %metadataForClass.cont4 isWrapper3: ; preds = %metadataForClass.cont %17 = bitcast %swift.type* %0 to %swift.type** %18 = getelementptr inbounds %swift.type*, %swift.type** %17, i64 1 %19 = load %swift.type*, %swift.type** %18, align 8, !invariant.load !31 br label %metadataForClass.cont4 metadataForClass.cont4: ; preds = %isWrapper3, %metadataForClass.cont %.class5 = phi %swift.type* [ %0, %metadataForClass.cont ], [ %19, %isWrapper3 ] %20 = bitcast %swift.type* %.class5 to %objc_class* %21 = load i8*, i8** @"\01L_selector(seconds)", align 8 %22 = bitcast %objc_class* %20 to i8* %23 = call %0* bitcast (void ()* @objc_msgSend to %0* (i8*, i8*)*)(i8* %22, i8* %21) %24 = bitcast %0* %23 to i8* %25 = call i8* @objc_retainAutoreleasedReturnValue(i8* %24) #4 %26 = bitcast i8* %25 to %0* %27 = bitcast %0* %26 to %TSo12UnitDurationC* %.asUnsubstituted6 = bitcast %TSo12UnitDurationC* %27 to %TSo9DimensionC* %.asSubstituted.asUnsubstituted = bitcast %TSo12UnitDurationC* %.asSubstituted to %TSo9DimensionC* %28 = call swiftcc { %TSo9DimensionC*, double } @_T010Foundation11MeasurementVAASo9DimensionCRbzlE9convertedACyxGx2to_tF(%TSo9DimensionC* %.asUnsubstituted6, %TSo9DimensionC* %.asSubstituted.asUnsubstituted, double %15, %swift.type* %0) %29 = extractvalue { %TSo9DimensionC*, double } %28, 0 %30 = extractvalue { %TSo9DimensionC*, double } %28, 1 %.asSubstituted7 = bitcast %TSo9DimensionC* %29 to %TSo12UnitDurationC* call void bitcast (void (%objc_object*)* @objc_release to void (%TSo12UnitDurationC*)*)(%TSo12UnitDurationC* %.asSubstituted) #4 call void bitcast (void (%objc_object*)* @objc_release to void (%TSo12UnitDurationC*)*)(%TSo12UnitDurationC* %.asSubstituted7) #4 ret void } declare swiftcc { %TSo9DimensionC*, double } @_T010Foundation11MeasurementVAASo9DimensionCRbzlE9convertedACyxGx2to_tF(%TSo9DimensionC*, %TSo9DimensionC*, double, %swift.type*) #0 declare swiftcc { %TSo4UnitC*, double } @_T010Foundation11MeasurementVACyxGSd5value_x4unittcfC(double, %TSo4UnitC*, %swift.type*) #0 ; Function Attrs: nounwind readnone define linkonce_odr hidden %swift.type* @_T0So12UnitDurationCMa() #1 { entry: %0 = load %swift.type*, %swift.type** @_T0So12UnitDurationCML, align 8 %1 = icmp eq %swift.type* %0, null br i1 %1, label %cacheIsNull, label %cont cacheIsNull: ; preds = %entry %2 = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_NSUnitDuration", align 8 %3 = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* %2) %4 = call %swift.type* @swift_getObjCClassMetadata(%objc_class* %3) #3 store atomic %swift.type* %4, %swift.type** @_T0So12UnitDurationCML release, align 8 br label %cont cont: ; preds = %cacheIsNull, %entry %5 = phi %swift.type* [ %0, %entry ], [ %4, %cacheIsNull ] ret %swift.type* %5 } ; Function Attrs: noinline nounwind define linkonce_odr hidden %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class*) #2 { entry: %load = load %objc_class* (%objc_class*)*, %objc_class* (%objc_class*)** @_swift_getInitializedObjCClass %1 = tail call %objc_class* %load(%objc_class* %0) ret %objc_class* %1 } declare %swift.type* @swift_getObjCClassMetadata(%objc_class*) declare void @objc_msgSend() declare i8* @objc_retainAutoreleasedReturnValue(i8*) declare void @objc_release(%objc_object*) … which, personally, I think is just excessive. Maybe for complex conversions it’s worth it, but I’m not sure it is for simple conversions. - Karl > > >> On Jan 13, 2018, at 9:31 PM, Erica Sadun via swift-evolution >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >> >> I would like to see a full Geometry implementation but I don't think it >> should be part of the standard library. >> >> I've kicked around some ideas here: >> >> * https://gist.github.com/erica/8cb4b21cf0c429828fad1d8ad459b71b >> <https://gist.github.com/erica/8cb4b21cf0c429828fad1d8ad459b71b> >> * https://gist.github.com/erica/ee06008202c9fed699bfa6254c42c721 >> <https://gist.github.com/erica/ee06008202c9fed699bfa6254c42c721> >> >> and >> >> * https://github.com/erica/SwiftGeometry >> <https://github.com/erica/SwiftGeometry> >> >>> On Jan 13, 2018, at 7:49 PM, Jonathan Hull via swift-evolution >>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>> Hi Evolution, >>> >>> I would really like to see Swift gain an Angle type in the standard >>> library. Every time I have to deal with an angle in an api, I have to go >>> figure out the conventions for that call. Is it in degrees? Is it in >>> radians? What if it is in radians, but I want to think about it in degrees? >>> >>> I ended up writing an Angle type for my own code a few years back, and I >>> have to say it is really wonderful. It has greatly simplified my graphics >>> work. It takes a lot of mental load off of my brain when dealing with >>> Angles. >>> >>> I can of course initialize it either as degrees or radians (or >>> revolutions), but I can also just say things like ‘.threeQuarterTurn’, and >>> then I can get the value back out in whatever format I like. There are >>> also useful additions that let me normalize the angle to different ranges >>> and which let me snap to the nearest multiple of an angle. Both of these >>> are enormously useful for user facing features. I can also do math on >>> angles in a way that makes geometric sense for angles. It is also really >>> useful for interacting with CGVectors in intelligent ways. >>> >>> Using Doubles or CGFloats to represent angles everywhere is just >>> semantically wrong IMHO, and it stops us from adding all of these >>> angle-specific niceties. >>> >>> Happy to provide code if there is interest… >>> >>> Thanks, >>> Jon >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution