> 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

Reply via email to