Reactive Programming - An Introduction With Swift - Part 1

This post is part of a series of articles on Reactive Programming Part 1 | Part 2 | ...

Prerequisites

This is a very high level and basic intro to reactive programming. From a reader perspective, it assumes:

  • You are at an intermediate level in programming (you are not an absolute beginner and know the difference between a variable and a function and a closure)
  • You are comfortable with Swift (you know what extensions are and how to constrain them at your will; although 80% of the code should be easy to follow even if you don't know what Swift is)
  • You know something about functional programming (just enough though...)
  • Monads do not scare you (don't worry, you won't find them here)

Introduction

Reactive programming is a paradigm to writing code in a way that concentrates data flow and propagating change across variables.

Well...

Reactive Variables

Consider we have two integer variables, a and b.

If we state that the value of b is one plus a, we could write this out as:

var a = 42
var b = a + 1

Seems straightforward. Now what if we modify our initial statement to state that the value of b is always a plus one?

var a = 42
var b = a + 1
a = 100
b // still 43 :-/

Specifying this sort of constraint is not directly possible in Swift at a language level. We could imagine we would be able to write code similar to the following:

var a = 42
var b <= a + 1 // special operator '<='
a = 100
print(b) // prints 101 magically

In the above example, <= data-preserve-html-node="true" is a magical operator that allows us to specify that the value of b depends on the value of a. Specifying this dependency allows us to change the value of a later on, and we can be assured that the value of b will get updated accordingly, and will always be a plus one.

So how can we accomplish this style of programming with Swift?

Observing Changes

The fundamental thing to note is that changes to a should be notified to external interested parties, and these notifications should be capable of being observed somehow, and all dependent variables should be notified of this change, so that they can react accordingly. This can be accomplished using the Observer Pattern.

NOTE The terminology out there is quite varied - Observer, Listener / Producer, Signal, Event / Subscribe, Bind, Listen and many more. There are slight nuances about how these differ.

For this article, we use the term bindto denote the act of an observer subscribing to a change produced by an observable.

Consider a type Observable<T> that wraps its type T as follows:

class Observable<T> {

    // a list of observers that should be notified
    // of changes to the underlying value
    var observers = [(T)->()]()

    init(_ value: T) {
        self.value = value
    }

    var value: T {
        didSet {
            // whenever the value changes notify
            // all observers with the updated value
            observers.forEach { $0(value) }
        }
    }

    // add a new observer binding
    func bind(_ f: @escaping (T)->()) {
        observers.append(f)
    }
}

With Observable<T> we can now write the following:

var a = Observable<Int>(10)
a.bind { print("a:", $0) }

a.value = 1001         // will print 'a: 1001'
a.value = 7         // will print 'a: 7'
a.value = 233         // will print 'a: 233'

This is the observer pattern at its most basic level, changes to a value are being notified to its observers. Now, whenever the underlying of a.value changes, it will automatically print out the new value.

Alright, so what happens if we write code like:

var a = Observable<Int>.init(0)
var b = a.value + 1 // we just set b once

a.value = 100
print(b) // prints '1'

Well, nothing much, actually. We still do not have a mechanism to tell how b is always dependent on a. Let's try to bind a closure that updates b:

var a = Observable<Int>.init(0)
var b = a.value + 1 // as before, set initial value

a.bind { b = $0 + 1 } // binding such that b is updated to a + 1, when a changes

print(a.value, b) // prints 0, 1

a.value = 100
print(a.value, b) // prints 100, 101!

Notice that in the last two lines, we first update a.value to 100 and later we print b, its value is now 101 as expected. We now have a very very basic implementation of a reactive variable. We can do much better.

In the previous examples, we were dealing with integer values. What if we want the value of b to be a string representation of a instead. We could write this out as:

var a = Observable<Int>.init(0)
var b = "\(a.value)"

a.bind { b = "\($0)" }

A Practical Example: Reactive UI

To show a more practical use-case, consider we have a label UI element, and a variable name that is used to populate the .text property of the label. From a reactive context, we want the label to always display the value in the name variable.

The class for our demo label looks like:

class Label {
    var text: String = "" {
        didSet {
            print("will layout with text: \(text)")
        }
    }
    init() { } 
}

The label as such has no notion of reactive-ness.; we can extend the Label class to become reactive:

// Reactive acts as a container for a Base type
class Reactive<Base> where Base: AnyObject {
    weak var base: Base? = nil
    init(_ base: Base) { 
        self.base = base 
    }
}

// If the Base is a Label, add in a text function
// Notice the function signature: (String) -> ()
extension Reactive where Base: Label {
    func text(_ text: String) {
        base?.text = text
    }
}

// Extend Label to provide an instance of a Reactive container
extension Label {
    var rx: Reactive<Label> { return Reactive<Label>.init(self) }
}

With the above code in place, we can write something like:

var name = Observable<String>.init("")
var label = Label()

// binds name to the label's text
// this works because the bind function
// simply expects a parameter of type (String)->()
// which the text() function of the Reactive 
// container of a Label will match

name.bind(label.rx.text) 

// now, whenever we set the name variable
// the label will automatically update it's
// appearance

name.value = "John Doe" // label will print 'will layout with text: John Doe'

assert(name.value == label.text) // succeeds

Functional Extensions

Our basic Observable class seems to be capable of quite a feat at this moment. But we can do more. Time to look at some functional programming.

Consider the map function. When defined over a type T, map is a function that takes in as input another function of type (T)->U and returns U.

For an observable, we do something similar, except that the types get wrapped in an Observable.

extension Observable {

    // maps an Observable<T> to Observable<U>
    func map(_ f: @escaping (T) -> U) -> Observable<U> {

        // create a new observable
        // and bind chages to self to it

        var r = Observable<U>.init(f(value)) 
        bind { value in
            r.value = f(value)
        }

        return r
    }
}

Having a map allows us to write the following:

var a = Observable<Int>.init(0)
var b = a.map { $0 + 1 }

print(a.value, b.value) // prints 0, 1

a.value = 100
print(a.value, b.value) // prints 100, 101

Interesting isn't it? Both a and b are now Observables, and b's value depends on a.

Since we have a map function, let's see if we can pull in more functional methods. Let's implement filter and see what happens.

extension Observable {
    func filter(_ f: @escaping (T) -> Bool) -> Observable<T> {
        let r = Observable(self.value)
        bind { value in
            if f(value) {
                r.value = value
            }
        }
        return r
    }
}

And now with code like the following, we have a mechanism to filter out even numbers and print a message whenever the value of a changes.

var a = Observable<Int>.init(0)
a.filter { $0 % 2 == 0 }
 .map { "\($0) is even" }
 .bind { print($0) }

If you consider a to be a stream of values, the above three lines is able to filter, map and process that stream. To solidify this stream concept of an observable, you can easily write a function that can convert a stream of values to a group of values.

Consider the following:

extension Observable {

    // buffers values until a certain count is reached
    func buffer(count: Int) -> Observable<[T]> {
        let r = Observable<[T]>.init([])
        var b = [T]()
        bind { value in
            if b.count == count {
                r.value = b
                b = []
            }
            b.append(value)
        }
        return r
    }

}

And now, if we write:

var a = Observable<Int>(0)

// buffer values and then print them

a.buffer(count: 3)
 .bind { print($0) }

for i in 0..<10 {
    a.value = i
}

// prints:
// [0, 1, 2]
// [3, 4, 5]
// [6, 7, 8]

We have created a stream that buffers values from its input stream until a certain count (3 in this case) of them are received, and then outputs the buffered values.

Note that we wait until the current buffer is full before triggering the configured observers (printing out the buffer in this case).

Conclusion

So there you have it, a very short intro into high level aspects of reactive programming. Give a shout out at @benziahamed on Twitter.

Exercises

The design we have come up with until now has some limitations:

  1. In our first set of examples when we created b as an Observable, reading the value of b would always give us a.value + 1. However, there was nothing stopping us from write a line like b.value = 10000000, even when a.value was 10. This actually would break the constraint we set out initially. What fundamental design change would be needed to ensure this will not happen? What do you think are the benefits of removing implicit storage of state?

  2. The Observable<T> implementation outlined in this article requires initialization with a known value of T. Implement an Observable<T> that does not require this, and has no value property. The only way to get a value out of an Observable would then be to strictly observe it.

  3. Now implement flatMap on our modified version of Observable. Did you face any problems in creating this function? I know I said you won't encounter a monad here, but if you implemented flatMap, well, you just created your own monad type.

  4. Would implementing reduce on an Observable make sense?

  5. Design and implement a throttle function that works similar to buffer, except that it is dependent of a time threshold and not a count threshold. The timer starts the moment the input stream produces a value. As long as the timer is running, new values are buffered, and when the timer finishes, all buffered values are passed on to the downstream observers.

    • The signature would look like func threshold(interval: Double) -> Observable<[T]>.
    • You can use this function to detect double taps; double taps are taps that occur within a short interval of one another. If we had an observable over a tap that is generated: tap event observable => threshold 250ms => map to count => filter by count of two => bind double tap handler

In part 2 [ coming soon-ish :-) ], we will look at re-designing Observable and try to its limitations.

Further Material

Event class for Swift

Say we want to implement the event/message pattern in Swift to decouple our objects. The event should be generic so that we can specify a type argument.

let start = Event<Int>()

start is an event that can be fired passing an integer; listeners must having a function that takes in an Int value and returns Void can subscribe to this event

Iteration 1

Let's target an API like the following.

var object_1 = SomeClass()
var object_2 = AnotherClass()

// NOTE: handleEvent is a function defined as
// func handleEvent(arg:Int) { ... }
// in the respective classes
start.add(object_1.handleEvent)
start.add(object_2.handleEvent)

To get this in place, we would need to specify our Event class as follows.

class Event<T> {
    // this will be the signature of handler functions
    // that can respond to this event, it should take in
    // a single parameter of type T and return Void
    typealias EventHandler = (T)->()

    // the list of handlers this event knows about
    var handlers = [EventHandler]()

    // given a handler, add it to the list of handlers
    func add(handler:EventHandler) {
        handlers.append(handler)
    }

    // to raise the event, we need to pass in the args parameter
    // of type T which will then be forwarded to all the handlers
    func fire(arg:T) {
        for handler in handlers {
            handler(arg)
        }
    }
}

So once start has been configured, we can fire it using start.fire(100) and all the listeners associated with start will get called; in our example, that means the handleEvent functions of both object_1 and object_2 will be called, being passed an argument value of 100.

This means that once all listeners are added to start, later firing start will in turn notify the listeners. It looks all fine except thar if the following situation happens, we may have a problem:

// initially
var object_1 = SomeClass() // the initial instance
start.add(object_1.handleEvent)
start.fire(100) // the initial object will get notified

// later on
object_1 = SomeClass() // re-initialize new instance
start.fire(200)

The problem is that the second call to start.fire will invoke the handleEvent function of the initial instance, which means that even though the variable object_1 now references a new instance, the Event class has held a strong reference internally to the old instance. This is as it is - since we are passing in a Function to the add method, the handlers array inside Event will hold a strong reference to that, and in-turn, a strong reference to the initial instance of object_1.

This could lead to problems - for example, what if we really intended to remove the old instance object_1 referenced and replace it with a new instance, and did not expect any unwanted side effects just because we added it to the Event class. We are in a situation where we cannot event identify which handler in the handlers array to remove, because Function types are not equatable.

What we need is a mechanism for Event to hold weak references to the handler objects. A weak reference to an object will not cause a retain in ARC when the referenced object can be otherwise deallocated.

Iteration 2

To allow for weak references, we need to allow for weak Function references. This is not possible in Swift (as of up to 2.0).

This means we need to start thinking outside (T)->() type handlers. First off, we need to pass on the object so that we can create a weak reference to it, and also the handler function. Swift instance methods are curried functions. Which means calling object_1.handleEvent(100) is the same as calling SomeClass.handleEvent(object_1)(100). In the second version we specify the type of object_1, which is SomeClass in our example. This will have a signature like (SomeClass)->(Int)->(), which means a function that takes in an argument of SomeClass and returns another function of type (Int)->().

Now we are getting somewhere; if we could generalize the above, we could say that all Event handlers are of AnyObject type and the function to handle the event should be of type (AnyObject)->(T)->().

// perhaps something like this in the event class?

// handlers have a new type now
var handlers = [(AnyObject)->(T)->()] ()

func add(listener:AnyObject, handler:(AnyObject)->(T)->()) {
    // now what to do?
}

What do we do inside the add method?

First of all, we need a mechanism to capture the listener argument in a weak reference. We need this in order to invoke handler in fire() (it would be something like handler(listener)(arg) ).

We need to approach this in a slightly roundabout fashion; the modified add method is as follows.

public typealias EventCallback = (T)->(Bool)

    var callbacks = [EventCallback]()

    public func add(
        target:H, 
        _ handler:(H)->(T)->()
    ) {
        callbacks.append(createWeakCallback(target, handler))
    }

We modify the handlers variable and call it callbacks, and it has a different type (T)->Bool - more on that later. In the add method, we create a callback from the arguments passed in. The createWeakCallback is the crux of our new solution.

func createWeakCallback(
        target:H, 
        _ handler:(H)->(T)->()
    ) -> EventCallback {
        return {
            [weak target]
            (args:T) in
            if let t = target {
                let f = handler(t)
                f(args)
                return true
            }
            return false
        }
    }


This function does a couple of things. First of all, this returns another function of type (T)->Bool which gets stored in the callbacks array. The returned function works as follows:

  • It captures a weak reference to the target object that needs to be notified on the event. The line [weak target] does this.
  • The function then checks if the captured variable is not nil. If it is it returns false; else it will invoke the handler function with the args variable which is of type T.

So essentially the function returned by createWeakCallback can be used to (1) notify the listener, and (2) understand if the callback itself is referencing a handler that is not deallocated.

We can use this information to modify the fire method.

// loops through all the callbacks
    // invokes them, and if they returned
    // false, it means that the callback
    // is referencing a weak variable that
    // is now nil
    public func fire(args:T) {
        var i = 0
        while i != callbacks.count {

            let callback = callbacks[i]

            if callback(args) {
                // since this callback succeeded, move
                // on to the next callback in the list
                i++
            }
            else {
                // housekeeping - since the callback
                // did not actually notify anything
                // no point in having it around, so
                // let's remove it from our list
                // to avoid future processing

                // we need to save it to a temp
                // variable because removeAtIndex returns
                // the item that was removed, and since
                // the item in our case is a function
                // we cannot have a statement in Swift
                // that is a unused function reference

                let removed = callbacks.removeAtIndex(i)
            }
        }
    }

Of course, if we do not wish to perform housekeeping to remove unwanted callbacks, we can simply use the following version instead.

public func fire(arg:T) {
        for callback in callbacks {
            callback(arg)
        }       
    }

Its simply a tradeoff between space and time; and solely depends on the use case. In fact, we could event create another function that returns whether a weak reference is nil or not similar to the createWeakCallback method, and use that in a separate housekeeping function that can be called separately outside the event processing cycle. This is left as an exercise to the reader.

The final Event class in its entirety.

public class Event<T> {

    public init() {}

    typealias EventCallback = (T)->(Bool)
    var callbacks = [EventCallback]()

    func createWeakCallback(target:H, _ handler:(H)->(T)->()) -> EventCallback {
        return {
            [weak target]
            (args:T) in
            if let t = target {
                let f = handler(t)
                f(args)
                return true
            }
            return false
        }
    }

    public func add(target:H, _ handler:(H)->(T)->()) {
        callbacks.append(createWeakCallback(target, handler))
    }

    public func fire(args:T) {
        var i = 0
        while i != callbacks.count {
            let callback = callbacks[i]
            if callback(args) {
                i++
            }
            else {
                let removed = callbacks.removeAtIndex(i)
            }
        }
    }

}

Forcing SpriteKit Texture Atlas Generation to honour tile sizes

SpriteKit's texture atlas creation will try to efficiently pack in all images, finding out transparent areas in individual images that can be ignored while packing. This obviously will allow more images to be packed into a single texture.

In some cases, this is not desirable - while laying out a pixel perfect 16x16 tile based scene, I noticed glitches and gaps along tile boundaries. This stemmed to some of the 16x16 containing transparent regions which the texture atlas generation process took advantage of. While being unpacked behind the scenes and rendered onto the SKScene, gaps across tiles would surface.

 

I checked if forcing a 16x16 tiling on SpriteKit would resolve the issue - and it did. So, for creating texture atlases bound to a specific tile size, I opt to now modify images and write a black pixel with alpha of 0.004 (1/255) on all four corners of the image using ImageMagick's convert command line tool.

convert inputTile.png -fill 'rgba(0,0,0,0.004)' -draw 'point 0,0' -draw 'point 15,0' -draw 'point 0,15' -draw 'point 15,15' outputTile.png

I have a custom Run Script in Xcode that will run the above command on all my image files as a pre-processing step before texture atlas creation. This thankfully solved the weird gaps for good.

Let's build a timer and scheduler for Sprite Kit using Swift

This post assumes you have some know how working with Sprite Kit and Swift, and are fairly confident about what a game loop's timestep is.

The demo project in GitHub provides a Scheduler class that allows you to write code like the following in your Scene:

scheduler
  .every(1.0) // every one second
  .perform( self=>GameScene.updateElapsedTimeLabel ) // update the elapsed time label
  .end()
        
scheduler
  .every(0.5) // every half second
  .perform( self=>GameScene.createRandomSprite ) // randomly place a sprite on the scene
  .end()

 

But first, some ramblings about time step and Sprite Kit

To make a time based scheduler, we need to know the elapsed time in the system. At any point in time, we need to know exactly how much seconds has passed.

In a game, the update loop is called once per frame. The timestep or delta time (dt) is the time it takes between frames. Sprite Kit tried to maintain a 60FPS mark, so the update loop gets called every 1/60th of a second, making dt = .016666667 (well, theoretically anyway).

The default signature of Sprite Kit's update method is as follows:

func update(_ currentTime: NSTimeInterval)

The currentTime parameter is the current system time. So you could measure dt by keeping track on the previous system time and subtract that from the current time every frame. Hold on to that thought, because we need to define another aspect of measuring time in relation to a game.

Game Time vs Real World Time

Real world time is just that, the time you see when you look at a watch, or clock, or... you get the idea. Game Time may be the same as real world time - 5 mins in the real world is 5 mins of elapsed gameplay time. If you have slow motion effects, you may need to slow down time; if your game has controlling time as a core mechanic (like Braid) - well things can get complicated. So you see, game time does not always map directly to the real world time. Another aspect is how should game time elapse when you pause the game? Should it proceed ahead in the background? Or should time be paused as well? E.g. if it takes 30 seconds to make a resource, if you pause the game midway after 15 seconds, and get back to the game after an hour, should the resource be made already (as real world time an hour has passed) or should the resource take the remaining 15 seconds to finish making the resource? The answer to this question depends very much on the kind of game you want to make.

Now, using Sprite Kit's currentTime method to calculate dt every frame has slight problem - if you pause, wait an hour and then resume the game, the dt in the very first update loop after unpausing will be very very large. (It would equal 3600 seconds rather than 1/60th of a second, give or take a few).

 // just print currentTime in update
...
...
spritekit time:545123.830644708
// pause the game for some time / press the home button
// and then get back to the game after a while
// notice how the time jumps ahead in relation
// to real world time. If we use currentTime
// to calculate the timestep, then dt=10.666769 seconds
spritekit time:545134.497413708
...
...


So we need a better way to calculate dt - something that is flexible in taking into account the paused state of a game when required, and ignoring it when it is not required (depending on the nature of game you are trying to make).

We need a timer component that can advance time in the correct increment and calculate dt reliably. If we need game time to halt when the game is paused, dt should be zero; when the game is unpaused, we need to dt to again be set correctly to the difference between two frames.

The following function in the Timer class achieves this:

    private func advance(currentTime:CFTimeInterval, paused:Bool) {
        if paused {
            shouldCorrectAfterPause = true
            dt = 0
        }
        else  {
            if shouldCorrectAfterPause {
                dt = 0
                shouldCorrectAfterPause = false
            }
            else {
                dt = currentTime - previousTime
            }
            previousTime = currentTime
        }
    }

If you need game time to pause when your game is paused, the paused parameter value should reflect the state of your game scene. If game time progresses independently of whether the game scene is paused or not, always set the paused parameter in the advance function to false. Have a look at Timer.swift in the demo project for the full implementation.


 

UPDATE AUG 15  Another approach to is to limit the time step.

dt = currentTime - previousTime
if dt > 0.02 { 
    dt = 0.02 // something convenient
}

This way you can ignore pausing the timer.


Ok, time step sorted, now how about that scheduler?

A time based scheduler is actually easy to make. If you know the elapsed time (which is the accumulated value of dt), you know exactly how much time has elapsed.

Think of scheduled events as pieces of code that needs to be executed at a specific time. We need to abstract away the piece of code that needs to be executed, and the time at which the code's execution needs to be triggered. Pieces of code can be abstracted in terms of blocks, closures etc. (By having code abstracted away I mean we need to store a reference to a piece of executable code in a variable that can be invoked later on).

In the very least, a scheduled event should look like:

final class SchedulerEvent {
    var trigger:Double = 0.0
    var callback:TargetAction? = nil
    func fire() {
        if let c = callback {
            c.performAction()
        }
    }
}

We have the the time at which the event should be triggered, and something called a TargetAction. A TargetAction is a technique you can represent a block of code based on the fact that instance methods are curried functions in Swift. Seriously, read that post. So rather than use blocks or closures, we will use TargetActions.

When you create a scheduled event and pass it on to the scheduler, it gets inserted into a priority queue.  

In every frame update, the scheduler will update the elapsed time by adding dt to it, and then scan the priority queue for matching events that need to be run. If the top item in the queue has a trigger time that is less than the current elapsed time, it means that that item needs to be run. The item is popped off the queue, and its corresponding TargetAction is invoked.

If you want recurring events, we just update the trigger time and re-insert the event back to the queue; it will get picked up by the scheduler in the next appropriate update loop.

The demo project

Over at GitHub, you will find a demo implementation of a game scene that does two things:

  • Show how many seconds the game scene has been displayed; updates every second
  • Twice a second, a sprite is placed on a random position on the scene 

It uses the scheduler and timer components outlined above.

 

 

 

Audiogrep

Audiogrep is a python script that transcribes audio files and then creates audio “supercuts” based on search phrases. It uses CMU Pocketsphinx for speech-to-text, and pydub to splice audio segments together.

Coding like a girl

In an advertisement campaign by Always, when adult women and men are asked to run/hit/throw like a girl they do those things wispily and terribly. On the other hand, when young girls are asked to run/hit/throw like a girl, they do those things with lots of enthusiasm and effort. When asked what doing things like a girl means to them, a young girl responds “Do them as best as you can.”

Heartbreakingly, at some age, we become convinced that doing anything like a girl means that you are doing it ineffectively, wimpily, and in a way that can’t be taken seriously at all. What then, does this mean for women and non-binary people who work in technology and present as feminine? What does it mean for those of us who code like girls?
— Sailor Mercury

Light's duality captured

Quantum mechanics tells us that light can behave simultaneously as a particle or a wave. However, there has never been an experiment able to capture both natures of light at the same time; the closest we have come is seeing either wave or particle, but always at different times. Taking a radically different experimental approach, EPFL scientists have now been able to take the first ever snapshot of light behaving both as a wave and as a particle. The breakthrough work is published in Nature Communications.

Curiosity rover sends a message for Leonard Nimoy

I’m part of the engineering operations team for the Mars Curiosity rover. When we heard about Leonard Nimoy’s death, I happened to be on shift for operations and so I decided to have Curiosity execute a command that would echo a message for him:

ECHO “SOL-0914M10:26:01.537”,”\’RIP Leonard Nimoy.\’.”

This is just an abbreviated version of the record that Curiosity logged when the command executed. I’ve stripped out the junk.

It took us a few days to turn this around once we had heard, so it’s a little late to the game... :/

In any case, Curiosity misses him too.

LLAP

We have a planet inhabited by robots.

Source: http://www.reddit.com/r/space/comments/2y1...

One-way binding in Swift

In a fight for great software architecture, our hands are often tied by the shortcomings of frameworks or languages we work with. Simple tasks like downloading a photo and presenting it in a view, updating a view when underlying data changes, or propagating user input to a model tend to introduce unnecessary complexity to our code.

Two-way binding; that's next.

Swatch to release "smartwatch"

Swatch will launch a new generation of its Swatch smartwatch in the next two to three months. Functions will include communication, mobile payments at stores such as Migros and Coop, and applications that work with Windows and Android – without having to be charged. Separately, Swatch will present its new Swatch Touch at the end of the month.
— Swatch Spokesperson

Wonder if it will be Andriod-based.

I suppose Tissot will soon announce its upcoming watches for the year (and possibly other mid-to-high range watchmakers) and the luxury segment might just pass this off as a fad.

I don't like the term "smartwatch" - it should just be a watch. Like how many people actually call their mobile phones/mobiles smartphones these days?