Quick quiz time! Given these two transforms:

```let translation = CGAffineTransform(translationX: 5, y: 10)
let rotation = CGAffineTransform(rotationAngle: CGFloat(Double.pi) / 6)```

Consider the following assignments.

```let a = rotation.concatenating(translation)
let b = translation.concatenating(rotation)
let c = rotation.translatedBy(x: 5, y: 10)
let d = translation.rotated(byDegrees: CGFloat(Double.pi) / 6)```

Can you tell me which of these outcomes match each other before scrolling down to the answer? (No cheating!) To provide a little buffer between here and there, let me remind you about what a basic affine transform looks like: For translation, the tx and ty entries specify the offsets for x and y:

```translation:
┌                       ┐
│  1.000   0.000   0.000│ translation: (5.0, 10.0)
│                       │ scale:       (1.00, 1.00)
│  0.000   1.000   0.000│ rotation:    0.00°
│                       │ rotation:    0.00 π
│  5.000  10.000   1.000│ rotation:    0.00 radians
└                       ┘
```

When rotating, the abcd slots are filled by cos(????), sin(????), -sin(????), and cos(????):

```rotation:
┌                       ┐
│  0.866   0.500   0.000│ translation: (0.0, 0.0)
│                       │ scale:       (1.00, 1.00)
│ -0.500   0.866   0.000│ rotation:    30.00°
│                       │ rotation:    0.16 π
│  0.000   0.000   1.000│ rotation:    0.52 radians
└                       ┘```

Multiplying translation by  rotation gives you this: And multiplying rotation by translation gives you this: The results are identical except in the (tx, ty) offset slots.

Okay, ready with your answers? If you guessed a/d and b/c, you’re right. As a basic rule of thumb, `x.concatenating(y)` is going to be the same as `y.performing(x)`, where the performing call is rotated(by:), translatedBy(x:,y:), or scaledBy(x, y).

Concatenating a transform simply multiplies one transform by another: T1 x T2. However, performing a transformation (rotated, translated, scaled) gives you T2 x T1. If you hop into the module declarations, the answers are there to see in the hipster retro documentation:

```/* Translate `t' by `(tx, ty)' and return the result:
t' = [ 1 0 0 1 tx ty ] * t */

@available(iOS 2.0, *)
public func translatedBy(x tx: CGFloat, y ty: CGFloat) -> CGAffineTransform

/* Scale `t' by `(sx, sy)' and return the result:
t' = [ sx 0 0 sy 0 0 ] * t */

@available(iOS 2.0, *)
public func scaledBy(x sx: CGFloat, y sy: CGFloat) -> CGAffineTransform

/* Rotate `t' by `angle' radians and return the result:
t' =  [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t */

@available(iOS 2.0, *)
public func rotated(by angle: CGFloat) -> CGAffineTransform
```

Here are the results, printed from a Swift playground, just to confirm that the behavior is, in fact, exactly as documented:

```a
CGAffineTransform(a: 0.866025403784439, b: 0.5, c: -0.5, d: 0.866025403784439, tx: 5.0, ty: 10.0)
b
CGAffineTransform(a: 0.866025403784439, b: 0.5, c: -0.5, d: 0.866025403784439, tx: -0.669872981077805, ty: 11.1602540378444)
c
CGAffineTransform(a: 0.866025403784439, b: 0.5, c: -0.5, d: 0.866025403784439, tx: -0.669872981077805, ty: 11.1602540378444)
d
CGAffineTransform(a: 0.866025403784439, b: 0.5, c: -0.5, d: 0.866025403784439, tx: 5.0, ty: 10.0)
```

I will leave my rants about the absurd and inconsistent naming, caps, argument labels, and initializers for another day.