All Projects → inamiy → FunRouter

inamiy / FunRouter

Licence: MIT license
Functional & type-safe URL routing example for http://2016.funswiftconf.com

Programming Languages

swift
15916 projects
objective c
16641 projects - #2 most used programming language

FunRouter

Functional & type-safe URL routing example for Functional Swift Conference 2016.

There are following route types available.

  • Route1 (struct, function-based)
  • Route2 (enum, optimizable)

Example

Assume typealias Route<Value> = RouteN<Value> (N = 1, 2).

/// Parses "/Hello/{city}/{year}".
let route: Route<(String, Int)> =
    curry { ($1, $2) } <^> match("Hello") <*> string() <*> int()
    
// or, more fancy flipped way:
// let route =
//    /"Hello" </> string() </> int() <&!> flipCurry { ($1, $2) }

let value1 = route.run(["Hello", "Budapest", "2016"])
expect(value1?.0) == "Budapest"
expect(value1?.1) == 2016

let value2 = route.run(["Ya", "tu", "sabes"])
expect(value2).to(beNil())

More complex routing

enum Sitemap {
    case foo(Int)       // "/R/foo/{Int}"
    case bar(Double)    // "/R/bar/{Double}"
    case baz(String)    // "/R/baz/{String}"
    case fooBar         // "/R/foo/bar"
    case notFound
}

let route: Route<Sitemap> =
    match("R")
        *> choice([
            match("foo") *> int() <&> Sitemap.foo,
            match("bar") *> double() <&> Sitemap.bar,
            match("baz") *> string() <&> Sitemap.baz,
            match("foo") *> match("bar") *> pure(Sitemap.fooBar),
        ])
    <|> pure(Sitemap.notFound)
    
expect(route.run(["R", "foo", "123"])) == .foo(123)
expect(route.run(["R", "bar", "4.5"])) == .bar(4.5)
expect(route.run(["R", "baz", "xyz"])) == .baz("xyz")
expect(route.run(["R", "foo", "bar"])) == .fooBar
expect(route.run(["R", "foo", "xxx"])) == .notFound

Optimization

For Route2<Value>, you can call optimize() so that:

// Before optimization (duplicated `match("foo")`)
let naiveRoute: Route<Sitemap> =
    match("R")
        *> choice([
            match("foo") *> int() <&> Sitemap.foo,
            match("bar") *> double() <&> Sitemap.bar,
            match("baz") *> string() <&> Sitemap.baz,
            match("foo") *> match("bar") *> pure(Sitemap.fooBar)
        ])

// After optimization
let optimizedRoute = optimize(naiveRoute)

will have an optimized structure as:

naiveRoute = .match("R", .choice([
    .match("foo", .capture(int)),
    .match("bar", .capture(double)),
    .match("baz", .capture(string)),
    .match("foo", .match("bar", .term(fooBar)))
]))

optimizedRoute = .match("R", .choice([
    .match("bar", .capture(double)),
    .match("baz", .capture(string)),
    .match("foo", .choice([
        .capture(int),
        .match("bar", .term(fooBar))
    ]))
]))

References

License

MIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].