Skip to content

Instantly share code, notes, and snippets.

@iamvery
Last active August 29, 2015 14:16
Show Gist options
  • Save iamvery/e7dcad7b3e0fc071cb58 to your computer and use it in GitHub Desktop.
Save iamvery/e7dcad7b3e0fc071cb58 to your computer and use it in GitHub Desktop.

Rubyist Does Swift

The most fundamental concepts in Swift that should be presented up front:

  • variables and constants
  • type safety
  • type inference

Helpful:

  • println
  • assert

0. Variables, Constants, and Types(afty)

Variables

var name: String = "Jay"
name = "Capt. Jay"
println(name)
// Capt. Jay

var ints: [Int] = [1,2]
ints.append(3)
println(ints)
// [1, 2, 3]

Constants

let pi: Double = 3.14159
pi++
// ERRORZ

let ints: [Int] = [1,2]
ints.append(3)
// ERRORZ

Type Safety

var name: String = "Jay"
name = 42
// ERRORZ

var ints: [Int] = [1,2]
ints.append("Jay")
// ERRORZ

Type Inference

let pi = 3.14159
assert(pi is Double)

1. Short-circuiting values

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-1-short-circuit-spec-rb

Swift

new concepts

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-1-short-circuit-swift

2. kwargs

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-2-kwargs-rb

Swift

new concepts

  • functions
  • external parameters

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-2-kwargs-swift

Warning: External parameters have different semantics as "methods"

3. Symbol to Proc

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-3-sym-to-proc-rb

Swift

new concepts

  • arrays
  • function types
  • closures

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-3-sym-to-proc-swift

4. Truthy, Falsey

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-4-truthy-rb

Swift

new concepts

  • conditionals
  • Bool
  • extensions
  • protocols

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-4-truthy-swift

5. Object#tap

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-5-tap-rb

Swift

new concepts

  • generics
  • inout
  • explicit reference

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-5-tap-swift

6. Hash#fetch

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-6-fetch-rb

Swift

new concepts

  • Dictionary
  • forced-internal parameter
  • closures
  • fatalError

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-6-fetch-swift

Note: It does not pass the missing key to the closure like Ruby!

7. Memoization

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-7-memoization-rb

Swift

new concepts

  • operators
  • implicitly unwrapped optionals

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-7-memoization-swift

8. Shovel <<

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-8-shovel-rb

Swift

new concepts

  • generic typealias

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-8-shovel-swift

9. Regular Expressions

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-9-regex-rb

Swift

  • objc brigde (?)
  • enum (sort of)

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-9-regex-swift

Note: There is no formal type for regular expressions in Swift. You could do something like this to add some syntactic sugar: https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-9-regex-sugar-swift

10. Enumerable

Ruby

https://gist.github.com/iamvery/e7dcad7b3e0fc071cb58#file-10-enumerable-rb

Swift

new concepts

Running examples

Ruby

Run any Ruby example with:

$ ruby 1-short-circuit.rb

Swift

Swift any Swift example with:

$ ./1-short-circuit.swift

Some of the scripts may not produce any output when successful, but failure would produce output. Certain examples are designed to "fail" for illustration.

require "test/unit/assertions"
include Test::Unit::Assertions
str = nil
str || "default" # "default"
str = "so stringy"
str || "default" # "so stringy"
str = nil
assert_equal(str || "default", "default")
str = "so stringy"
assert_equal(str || "default", "so stringy")
var str: String?
str ?? "default" // "default"
str = "so stringy"
str ?? "default" // "so stringy"
str = nil
assert((str ?? "default") == "default")
str = "so stringy"
assert((str ?? "default") == "so stringy")
require "test/unit/assertions"
include Test::Unit::Assertions
[1,2,3].select { |n| n > 1 } # => [2,3]
assert_equal([1,2,3].select{|n| n>1}, [2,3])
class Foo
include Enumerable
def each
yield(1)
yield(2)
yield(3)
end
end
Foo.new.select { |n| n > 1 } # => [2,3]
assert_equal(Foo.new.select{|n| n>1}, [2,3])
var name: String?
println(name)
// ERRORZ
var name: String?
println(name)
// nil
name = "Jay"
println(name!)
// "Jay"
if let jay = name {
println(jay)
}
def foo(bar:, baz: "baz")
puts bar, baz
end
foo(bar: "bar")
foo(bar: "bar", baz: "yo")
foo(baz: "yo", bar: "dawg")
func foo (#bar: String,
baz: String = "baz") {
println("\(bar) \(baz)")
}
foo(bar: "bar")
foo(bar: "bar", baz: "yo")
foo(baz: "yo", bar: "dawg")
// ERRORZ, parameter order!
func foo (bar: String,
baz: String = "baz") {
println("\(bar) \(baz)")
}
foo("bar")
foo("bar", baz: "yo")
func foo (bar bar: String,
baz: String = "baz") {
println("\(bar) \(baz)")
}
foo(bar: "bar")
foo(bar: "bar", baz: "yo")
foo(baz: "yo", bar: "bar")
// ERRORZ, parameter order!
require "test/unit/assertions"
include Test::Unit::Assertions
a = %w(a b c)
a.map(&:upcase)
# => ["A", "B", "C"]
upcase = proc do |str|
str.public_send(:upcase)
end
a.map(&upcase)
assert_equal(a.map(&:upcase), ["A","B","C"])
assert_equal(a.map(&upcase), ["A","B","C"])
let closure = {
(name: String) in
println("Hi, \(name)!")
}
closure("ACR")
var a = ["a","b","c"]
a.map { letter in
letter.uppercaseString
}
a.map { $0.uppercaseString }
func upcase(string: String) -> String {
return string.uppercaseString
}
// String -> String
a.map(upcase) // ["A", "B", "C"]
if 0
puts "it's true"
end
extension Int: BooleanType {
public var boolValue: Bool {
return true
}
}
if true {
println("it's true")
}
if 1 {
println("it's true")
}
require "test/unit/assertions"
include Test::Unit::Assertions
Foo = Struct.new(:one, :two)
foo = Foo.new
foo.tap do |foo|
foo.one = 1
foo.two = 2
end # => <#Foo>
assert_equal(foo.one, 1)
assert_equal(foo.two, 2)
func tap <T> (inout instance: T,
doWith: inout T -> Void) -> T {
doWith(&instance)
return instance
}
struct Foo {
var one: String = "one"
var two: String = "two"
}
var foo = Foo()
tap(&foo) {
$0.one = "1"
$0.two = "2"
} // Foo(one: "1", two: "2")
println(foo.one)
println(foo.two)
require "test/unit/assertions"
include Test::Unit::Assertions
assert_raises(KeyError) do
hash = { one: 1 }
hash.fetch(:one) # => 1
hash.fetch(:two) # => KeyError
hash.fetch(:two, 2) # => 2
hash.fetch(:two) { 1 + 1 } # => 2
end
class Foo {
func bar(baz: Int, _ qux: Int) {
println(baz + qux)
}
}
Foo().bar(2,2)
extension Dictionary {
func fetch(
key: Key,
_ defaultValue: Value? = nil,
defaultValuer: (() -> Value)? = nil
) -> Value {
if let value = self[key] ?? defaultValue ?? defaultValuer?()
{ return value }
fatalError("Key \(key) not found.")
}
}
//var dict = ["one" : 1]
// Dictionary<String, Int>
// Ruby: dict = { "one" => 1 }
var dict = ["one" : 1]
dict.fetch("one") // 1
//dict.fetch("two") // ERRORZ
dict.fetch("two", 2) // 2
dict.fetch("two") { 1 + 1 } // 2
class Foo {
func bar(baz: Int, qux: Int) {
println(baz + qux)
}
}
Foo().bar(2, qux: 2)
var str: String?
println(str?.uppercaseString)
// nil
str = "ohai"
println(str?.uppercaseString)
// Optional("OHAI")
require "test/unit/assertions"
include Test::Unit::Assertions
a = nil
a ||= "foo" # "foo"
a ||= "bar" # "foo"
assert_equal(a, "foo")
infix operator ??= {}
func ??= <T>(inout base: T?,
defaultValue: T) {
base = base ?? defaultValue
}
func ??= <T>(inout base: T!,
defaultValue: T) {
base = base ?? defaultValue
}
var eh: String?
eh ??= "a" // Optional("a")
eh ??= "eh" // Optional("a")
var a: String!
a ??= "foo" // "foo"
a ??= "bar" // "foo"
var s: String!
println(s) // ERRORZ
s = "wow"
println(s) // "wow"
require "test/unit/assertions"
include Test::Unit::Assertions
a = [1,2]
a << 3 # => [1,2,3]
s = "ab"
s << "c" # => "abc"
assert_equal([1,2] << 3, [1,2,3])
assert_equal("ab" << "c", "abc")
protocol Appender {
typealias AppendageType
mutating func append(appendage: AppendageType)
}
extension Array: Appender {}
extension String: Appender {
typealias AppendageType = Character
}
infix operator << {}
func << <T: Appender> (inout collection: T, newValue: T.AppendageType) -> T {
collection.append(newValue)
return collection
}
var a = [1,2]
a << 3 // [1,2,3]
var s = "ab"
s << "c" // "abc"
var a = [1,2]
a.append(3)
var s = "ab"
s.append("c" as Character)
prefix operator / {}
prefix func / (expression: String) -> String {
return expression
}
postfix operator / {}
postfix func / (expression: String) -> String {
return expression
}
if "thing" =~ /"i.g"/ {
println("match!")
}
"thing"[/"i.g"/] // "ing"
require "test/unit/assertions"
include Test::Unit::Assertions
if "thing" =~ /i.g/
puts "match!"
end
"thing"[/i.g/] # "ing"
assert_equal("thing"[/i.g/], "ing")
import Foundation
infix operator =~ {}
func =~ (input: String,
pattern: String) -> Bool {
if let _ = input.rangeOfString(pattern,
options: .RegularExpressionSearch) {
return true
} else {
return false
}
}
extension String {
subscript (pattern: String) -> String? {
if let range = rangeOfString(pattern,
options: .RegularExpressionSearch) {
return substringWithRange(range)
} else {
return nil
}
}
}
if "thing" =~ "i.g" {
println("match!")
}
"thing"["i.g"] // Optional("ing")
@tdouce
Copy link

tdouce commented Mar 18, 2015

Personally, optionals were difficult for me to grasp. I think it will help people understand them better if you provide a use case, i.e. when and why would you want/use one.

@tdouce
Copy link

tdouce commented Mar 18, 2015

Perhaps I've overlooked some content so excuse me if you already cover this. But, I thought one very interesting aspect of Swift was the multiple initialization signatures (not sure if this is the technical term). For example, being able to initialize an object according to the number or type of argument supplied on initialization.

@tdouce
Copy link

tdouce commented Mar 18, 2015

Do you think it is possible to provide a very brief, "What is a closure?" for Closures

@tdouce
Copy link

tdouce commented Mar 18, 2015

For tap, my initial reaction is, "What is <T>, inout T -> Void, and doWith(&instance). Looks very foreign to me. In order for folks to grok this, I suspect you will need to spend some time explaining what these strange things mean.

@tdouce
Copy link

tdouce commented Mar 18, 2015

Is fetch supported in Swift or is this creating Swift functionality to make comparable Ruby's #fetch?

Expanding on that question, is the presentation about learning Swift and making it Ruby-like by implementing familiar Ruby methods in Swift?

@tdouce
Copy link

tdouce commented Mar 18, 2015

Overall, I think this concept is interesting. I think the challenge is the breadth of what you cover, everything you cover is very technical (i.e. Need to first grasp Ruby fairly/very well to understand the Swift), and the amount of what you cover.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment