SlideShare ist ein Scribd-Unternehmen logo
1 von 222
Downloaden Sie, um offline zu lesen
F#in the
Real World
F# in the real world (NDC)
agenda
Domain Modelling
Infrastructure
Game Logic
Algorithms
DSLs
1MILLION USERS
ACTIVE
DAILY
250MILLION DAY
PER
REQUEST
2MONTH
TB
P E R
sec
ops
25,000
C#
why F#?
time to market
correctness
efficient
tame complexity
F# in the real world (NDC)
Collectables
Wager Size
Special Symbol
Avg Wager Size
Web Server call
• Line Win
– X number of matching symbols on adjacent columns
– Positions have to be a ‘line’
– Wild symbols substitute for other symbols
• Scatter Win
– X number of matching symbols anywhere
– Triggers bonus game
What symbols should land?
Any special symbol wins?
Did the player win anything?
What the player’s new
average wager?
Should the player receive
collectables?
type Symbol = Standard of string
| Wild
type Symbol = Standard of string
| Wild
e.g. Standard “hat”
Standard “shoe”
Standard “bonus”
…
type Symbol = Standard of string
| Wild
i.e. Wild
type Win = LineWin of int * Symbol * int
| ScatterWin of Symbol * int
type Win = LineWin of int * Symbol * int
| ScatterWin of Symbol * int
e.g. LineWin (5, Standard “shoe”, 4)
type Win = LineWin of int * Symbol * int
| ScatterWin of Symbol * int
e.g. ScatterWin (Standard “bonus”, 3)
type LineNum = int
type Count = int
type Win = LineWin of LineNum * Symbol * Count
| ScatterWin of Symbol * Count
closed hierarchy
no Nulls
“Make illegal states unrepresentable”
- Yaron Minsky
[<Measure>]
type Pence
e.g. 42<Pence>
153<Pence>
…
10<Meter> / 2<Second> = 5<Meter/Second>
10<Meter> * 2<Second> = 20<Meter Second>
10<Meter> + 10<Meter> = 20<Meter>
10<Meter> * 10 = 100<Meter>
10<Meter> * 10<Meter> = 100<Meter2>
10<Meter> + 2<Second> // error
10<Meter> + 2 // error
10<Meter> / 2<Second> = 5<Meter/Second>
10<Meter> * 2<Second> = 20<Meter Second>
10<Meter> + 10<Meter> = 20<Meter>
10<Meter> * 10 = 100<Meter>
10<Meter> * 10<Meter> = 100<Meter2>
10<Meter> + 2<Second> // error
10<Meter> + 2 // error
type Wager = int64<Pence>
type Multiplier = int
type Payout = Coins of Wager
| MultipliedCoins of Multiplier * Wager
| Multi of Payout list
| BonusGame
type Wager = int64<Pence>
type Multiplier = int
type Payout = Coins of Wager
| MultipliedCoins of Multiplier * Wager
| Multi of Payout list
| BonusGame
type Wager = int64<Pence>
type Multiplier = int
type Payout = Coins of Wager
| MultipliedCoins of Multiplier * Wager
| Multi of Payout list
| BonusGame
type State =
{
AvgWager : Wager
SpecialSymbol : Symbol
Collectables : Map<Collectable, Count>
}
immutable by default
F# in the real world (NDC)
Recap
lightweight syntax
for types &
hierarchies
great for domain
modelling
make invalid states
unrepresentable
better correctness
order of magnitude
increase in productivity
F# in the real world (NDC)
F# in the real world (NDC)
player states are big
Stateless Server DatabaseClient
1:1 read-write ratio
F# in the real world (NDC)
ServerClient
Session 1
Session 2
ServerClient Database
Elastic Load Balancer
S3
Auto scaling Group
Server A Server B
...
EC2
CloudFront
Stateful Server
Stateful Server
Game Logic
Stateless Middle-tier
Infrastructure
logging
circuit
breaker
perf
tracking
retry …
Stateful Server
Game Logic
Stateless Middle-tier
Infrastructure
logging
circuit
breaker
perf
tracking
retry …
Stateful Server
Game Logic
Stateful Middle-tier
Infrastructure
logging
circuit
breaker
perf
tracking
retry …
The Actor Model
An actor is the fundamental unit of computation
which embodies the 3 things
• Processing
• Storage
• Communication
that are essential to computation.
-Carl Hewitt*
* http://bit.ly/HoNHbG
The Actor Model
• Everything is an actor
• An actor has a mailbox
• When an actor receives a message it can:
– Create new actors
– Send messages to actors
– Designate how to handle the next message
Stateful Server
• Gatekeeper
– Manages the local list of active workers
– Spawns new workers
• Worker
– Manages the states for a player
– Optimistic locking
– Persist state after period of inactivity
Stateful Server
Game Server
Player A
Player B
S3
Worker C
Worker B
Gatekeeper
RequestHandlers
Asynchronous
Stateful Server
Game Server
Worker C
Worker B
Gatekeeper
Worker A
ok
RequestHandlers
Player A
Player B
Asynchronous
S3
Stateful Server
Game Server
S3
Worker C
Worker B
Gatekeeper
Worker A
RequestHandlers
Player A
Player B
Asynchronous
Stateful Server
Game Server
S3
Worker C
Gatekeeper
Worker A
RequestHandlers
Player A
Player B
Asynchronous
Stateful Server
Game Server
Worker C
Worker A
Gatekeeper
error
RequestHandlers
Player A
Player B
S3
Asynchronous
type Agent<‘T> = MailboxProcessor<‘T>
type Agent<‘T> = MailboxProcessor<‘T>
type Message =
| Get of AsyncReplyChannel<…>
| Put of State * Version * AsyncReplyChannel<…>
type Agent<‘T> = MailboxProcessor<‘T>
type Message =
| Get of AsyncReplyChannel<…>
| Put of State * Version * AsyncReplyChannel<…>
type Result<‘T> =
| Success of ’T
| Failure of Exception
type Result<‘T> =
| Success of ’T
| Failure of Exception
type GetResult = Result<State * Version>
type PutResult = Result<unit>
type Agent<‘T> = MailboxProcessor<‘T>
type Message =
| Get of AsyncReplyChannel<GetResult>
| Put of State * Version * AsyncReplyChannel<PutResult>
type Agent<‘T> = MailboxProcessor<‘T>
type Message =
| Get of AsyncReplyChannel<GetResult>
| Put of State * Version * AsyncReplyChannel<PutResult>
type Worker (playerId) =
let agent = Agent<Message>.Start(fun inbox ->
let state = getCurrentState playerId
let rec workingState (state, version) =
async { … }
and closedState () =
async { … }
workingState (state, 1))
type Worker (playerId) =
let agent = Agent<Message>.Start(fun inbox ->
let state = getCurrentState playerId
let rec workingState (state, version) =
async { … }
and closedState () =
async { … }
workingState (state, 1))
type Worker (playerId) =
let agent = Agent<Message>.Start(fun inbox ->
let state = getCurrentState playerId
let rec workingState (state, version) =
async { … }
and closedState () =
async { … }
workingState (state, 1))
type Worker (playerId) =
let agent = Agent<Message>.Start(fun inbox ->
let state = getCurrentState playerId
let rec workingState (state, version) =
async { … }
and closedState () =
async { … }
workingState (state, 1))
type Worker (playerId) =
let agent = Agent<Message>.Start(fun inbox ->
let state = getCurrentState playerId
let rec workingState (state, version) =
async { … }
and closedState () =
async { … }
workingState (state, 1))
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None ->
do! persist state
return! closedState()
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None ->
do! persist state
return! closedState()
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None ->
do! persist state
return! closedState()
…
}
non-blocking I/O
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None ->
do! persist state
return! closedState()
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None ->
do! persist state
return! closedState()
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Get(reply)) ->
reply.Reply <| Success(state, version)
return! workingState(state, version)
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Get(reply)) ->
reply.Reply <| Success(state, version)
return! workingState(state, version)
…
}
type Message =
| Get of AsyncReplyChannel<GetResult>
| Put of State * Version * AsyncReplyChannel<PutResult>
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Get(reply)) ->
reply.Reply <| Success(state, version)
return! workingState(state, version)
…
}
type GetResult = Result<State * Version>
type PutResult = Result<unit>
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Get(reply)) ->
reply.Reply <| Success(state, version)
return! workingState(state, version)
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(newState, v, reply)) when version = v ->
reply.Reply <| Success()
return! workingState(newState, version+1)
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(newState, v, reply)) when version = v ->
reply.Reply <| Success()
return! workingState(newState, version+1)
…
}
type Message =
| Get of AsyncReplyChannel<GetResult>
| Put of State * Version * AsyncReplyChannel<PutResult>
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(newState, v, reply)) when version = v ->
reply.Reply <| Success()
return! workingState(newState, version+1)
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(newState, v, reply)) when version = v ->
reply.Reply <| Success()
return! workingState(newState, version+1)
…
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(_, v, reply)) ->
reply.Reply <| Failure(VersionMismatch(version, v))
return! workingState(state, version)
}
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
…
| Some(Put(_, v, reply)) ->
reply.Reply <| Failure(VersionMismatch(version, v))
return! workingState(state, version)
} type Result<‘T> =
| Success of ’T
| Failure of Exception
let rec workingState (state, version) =
async {
let! msg = inbox.TryReceive(60000)
match msg with
| None -> …
| Some(Get(reply)) -> …
| Some(Put(newState, v, reply)) when version = v -> …
| Some(Put(_, v, reply)) -> …
}
and closedState () =
async {
let! msg = inbox.Receive()
match msg with
| Get(reply) ->
reply.Reply <| Failure(WorkerStopped)
return! closedState()
| Put(_, _, reply) ->
reply.Reply <| Failure(WorkerStopped)
return! closedState()
}
and closedState () =
async {
let! msg = inbox.Receive()
match msg with
| Get(reply) ->
reply.Reply <| Failure(WorkerStopped)
return! closedState()
| Put(_, _, reply) ->
reply.Reply <| Failure(WorkerStopped)
return! closedState()
}
5x efficient
improvement
60% latency drop
no databases
90% cost saving
F# in the real world (NDC)
akka.Net
Orleans
F# in the real world (NDC)
F# in the real world (NDC)
Caught a Gnome
EXP Item Gold
Quest Progress
Caught a Gnome
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
New Quest
Quest Complete
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Level Up
Quest Progress
New Quest
Achievement
Progress
EXP Item Gold
Quest Complete
Level Up
Caught a Gnome
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Achievement
Progress
Achievement
Complete
Level Up
Quest Progress
EXP Item Gold
Caught a Gnome
Quest Complete
New Quest
Achievement
Progress
Achievement
Complete
100+ actions
F# in the real world (NDC)
triggered by different
abstraction layers
non-functional
requirements
F# in the real world (NDC)
message-broker
pattern
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
Ignore
Process
Process
Process
Process
Ignore
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Process
Ignore
Ignore
Ignore
Process
Ignore
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Level Up
Caught Gnome Trapping
Queue
Levelling
Quests
Achievements
Analytics
Partner
Reporting
EXP
Item
Gold
Level Up
need lots of facts
type Fact =
| GotExp of Exp
| GotGold of Gold
| GotItem of Item * Count
| CaughtMonster of Monster * Bait * Location
| LevelUp of OldLevel * NewLevel
…
type Reward =
| GotExp of Exp
| GotGold of Gold
| GotItem of Item * Count
type StateChange =
| LevelUp of OldLevel * NewLevel
…
type Fact =
| StateChange of StateChange
| Reward of Reward
| Trapping of Trapping
| Fishing of Fishing
…
let process fact =
match fact with
| StateChange(stateChange) -> …
| Reward(reward) -> …
| Trapping(trapping) -> …
…
C# interop
…
var fact = Fact.NewStateChange(
StateChange.NewLevelUp(oldLvl, newLvl));
…
type IFact = interface end
type Reward =
| GotExp of Exp
| GotGold of Gold
| GotItem of Item * Count
interface IFact
type IFact = interface end
type Reward =
| GotExp of Exp
| GotGold of Gold
| GotItem of Item * Count
interface IFact
let process (fact : IFact) =
match fact with
| :? StateChange as stateChange -> …
| :? Reward as reward -> …
| :? Trapping as trapping -> …
…
| _ -> raise <| NotSupportedFact fact
let process (fact : IFact) =
match fact with
| :? StateChange as stateChange -> …
| :? Reward as reward -> …
| :? Trapping as trapping -> …
…
| _ -> raise <| NotSupportedFact fact
let process (fact : IFact) =
match fact with
| :? StateChange as stateChange -> …
| :? Reward as reward -> …
| :? Trapping as trapping -> …
…
| _ -> raise <| NotSupportedFact fact
simple
flexible
saver
F# in the real world (NDC)
location bait
attraction rate
catch rate
auto-tuning
trapping stats
Monster
strength
speed
intelligence
Trap
strength
speed
technology
Monster
strength
speed
intelligence
Trap
strength
speed
technology
Catch Rate %
trial-and-error
F# in the real world (NDC)
“…if you require constant diligence you’re
setting everyone up for failure and hurt”
F# in the real world (NDC)
genetic algorithms
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F#-powered DSLs.
Awesome!
F# in the real world (NDC)
F# in the real world (NDC)
wanna find
correlations?
wanna find
correlations?
you can DIY it!
;-)
why was
payment service
slow last night?
F# in the real world (NDC)
F# in the real world (NDC)
Pain Driven Development
Amazon
.CloudWatch
.Selector
github.com/fsprojects/Amazon.CloudWatch.Selector
Find metrics whose 5
min average exceeded
1 second during last
12 hours
cloudWatch.Select(
unitIs “milliseconds” +
average (>) 1000.0
@ last 12 hours
|> intervalOf 5 minutes)
cloudWatch.Select(“
unitIs ‘milliseconds’ and
average > 1000.0
duringLast 12 hours
at intervalOf 5 minutes”)
did any cache
nodes’ CPU spike
yesterday?
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
cloudWatch.Select(
namespaceLike “elasticache” +
nameLike “cpu” +
max (>) 80.0
@ last 24 hours
|> intervalOf 15 minutes)
regex support
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
Amazing
F#
=
usable from anywhere you
can run F# code
e.g. F# REPL, executable, ..
Internal DSL
useful for building tools
e.g. CLI, …
External DSL
F# in the real world (NDC)
Recap
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
managed
key-value store
redundancy
9-9s guarantee
great performance
name your
throughput
F# in the real world (NDC)
F# in the real world (NDC)
F# in the real world (NDC)
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
DynamoDB.SQL
github.com/fsprojects/DynamoDb.SQL
GOAL
Disguise
complexity
GOAL
SELECT UserId, TopScore
FROM GameScore
WHERE GameTitle CONTAINS “Zelda”
ORDER DESC
LIMIT 3
WITH (NoConsistentRead)
Query
AST
Execution
F# & FParsec*
*www.quanttec.com/fparsec
External DSL
via
F# in the real world (NDC)
SELECT * FROM GameScore
Abstract Syntax Tree (AST)
FParsec
F# in the real world (NDC)
select GameTitle, UserId, TopScore
from GameScores
where GameTitle = “Starship X”
and TopScore >= 1000
order desc
limit 3
with (NoConsistentRead, Index(GameTitleIndex, true))
F# in the real world (NDC)
< 50 LOC
S3 Provider
github.com/fsprojects/S3Provider
F# type provider for Amazon S3
F# in the real world (NDC)
F# in the real world (NDC)
intellisense over S3
compile time validation
no code generation
Domain Modelling
Infrastructure
Game Logic
Algorithms
DSLs
why F#?
time to market
correctness
efficient
tame complexity
also on the Functional Track this year :-)
Today
REPL
Driven Dev
FP Lab Hour
Tomorrow
Parser
Combinators
FP Lab Hour
@theburningmonk
theburningmonk.com
github.com/theburningmonk

Weitere ähnliche Inhalte

Was ist angesagt?

Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadiesAlicia Pérez
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to SwiftGiordano Scalzo
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactOdessaJS Conf
 
The Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsThe Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsMiguel Angel Horna
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsDavid Golden
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFabio Collini
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented ProgrammingScott Wlaschin
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift OverviewKaz Yoshikawa
 
Haskell in the Real World
Haskell in the Real WorldHaskell in the Real World
Haskell in the Real Worldosfameron
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and InferenceRichard Fox
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinFabio Collini
 
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesTo be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesArtur Skowroński
 
Exhibition of Atrocity
Exhibition of AtrocityExhibition of Atrocity
Exhibition of AtrocityMichael Pirnat
 
Ruby Meetup Balabit
Ruby Meetup BalabitRuby Meetup Balabit
Ruby Meetup BalabitPapp Laszlo
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of CodeJoe Morgan
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsMichael Pirnat
 

Was ist angesagt? (20)

Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Beautiful python - PyLadies
Beautiful python - PyLadiesBeautiful python - PyLadies
Beautiful python - PyLadies
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
Nik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReactNik Graf - Get started with Reason and ReasonReact
Nik Graf - Get started with Reason and ReasonReact
 
The Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation PlatformsThe Challenge of Bringing FEZ to PlayStation Platforms
The Challenge of Bringing FEZ to PlayStation Platforms
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
1 the ruby way
1   the ruby way1   the ruby way
1 the ruby way
 
Developing iOS apps with Swift
Developing iOS apps with SwiftDeveloping iOS apps with Swift
Developing iOS apps with Swift
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift Overview
 
Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
 
Haskell in the Real World
Haskell in the Real WorldHaskell in the Real World
Haskell in the Real World
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
 
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's CoroutinesTo be Continued - multithreading with Project Loom and Kotlin's Coroutines
To be Continued - multithreading with Project Loom and Kotlin's Coroutines
 
Exhibition of Atrocity
Exhibition of AtrocityExhibition of Atrocity
Exhibition of Atrocity
 
Ruby Meetup Balabit
Ruby Meetup BalabitRuby Meetup Balabit
Ruby Meetup Balabit
 
Unbreakable: The Craft of Code
Unbreakable: The Craft of CodeUnbreakable: The Craft of Code
Unbreakable: The Craft of Code
 
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) ThingsA Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
 

Ähnlich wie F# in the real world (NDC)

F# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiF# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiCodemotion Dubai
 
F# in the Real World (DDD EA)
F# in the Real World (DDD EA)F# in the Real World (DDD EA)
F# in the Real World (DDD EA)Yan Cui
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server SideIgnacio Martín
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actorszucaritask
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++Sumant Tambe
 
import sys sys.path.append(aima-python) from search import .pdf
import sys sys.path.append(aima-python) from search import .pdfimport sys sys.path.append(aima-python) from search import .pdf
import sys sys.path.append(aima-python) from search import .pdfmaheshkumar12354
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React AlicanteIgnacio Martín
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languagesArthur Xavier
 
React-Native Rendering Performance
React-Native Rendering PerformanceReact-Native Rendering Performance
React-Native Rendering PerformanceInnerFood
 
look at the following module.import sys sys.path.append(aima-py.pdf
look at the following module.import sys sys.path.append(aima-py.pdflook at the following module.import sys sys.path.append(aima-py.pdf
look at the following module.import sys sys.path.append(aima-py.pdfbalrajashok
 
Hive function-cheat-sheet
Hive function-cheat-sheetHive function-cheat-sheet
Hive function-cheat-sheetDr. Volkan OBAN
 
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Yan Cui
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Ignacio Martín
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScriptGarth Gilmour
 
Print input-presentation
Print input-presentationPrint input-presentation
Print input-presentationMartin McBride
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Igalia
 
The Dynamic Language is not Enough
The Dynamic Language is not EnoughThe Dynamic Language is not Enough
The Dynamic Language is not EnoughLukas Renggli
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developersjessitron
 

Ähnlich wie F# in the real world (NDC) (20)

F# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion DubaiF# in social gaming by Yan Cui at Codemotion Dubai
F# in social gaming by Yan Cui at Codemotion Dubai
 
F# in the Real World (DDD EA)
F# in the Real World (DDD EA)F# in the Real World (DDD EA)
F# in the Real World (DDD EA)
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
 
Casting for not so strange actors
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++
 
import sys sys.path.append(aima-python) from search import .pdf
import sys sys.path.append(aima-python) from search import .pdfimport sys sys.path.append(aima-python) from search import .pdf
import sys sys.path.append(aima-python) from search import .pdf
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Type safe embedded domain-specific languages
Type safe embedded domain-specific languagesType safe embedded domain-specific languages
Type safe embedded domain-specific languages
 
React-Native Rendering Performance
React-Native Rendering PerformanceReact-Native Rendering Performance
React-Native Rendering Performance
 
look at the following module.import sys sys.path.append(aima-py.pdf
look at the following module.import sys sys.path.append(aima-py.pdflook at the following module.import sys sys.path.append(aima-py.pdf
look at the following module.import sys sys.path.append(aima-py.pdf
 
Hive function-cheat-sheet
Hive function-cheat-sheetHive function-cheat-sheet
Hive function-cheat-sheet
 
Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0Cassandra 2.2 & 3.0
Cassandra 2.2 & 3.0
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)Tame cloud complexity with F# powered DSLs (build stuff)
Tame cloud complexity with F# powered DSLs (build stuff)
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Type Driven Development with TypeScript
Type Driven Development with TypeScriptType Driven Development with TypeScript
Type Driven Development with TypeScript
 
Print input-presentation
Print input-presentationPrint input-presentation
Print input-presentation
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
 
The Dynamic Language is not Enough
The Dynamic Language is not EnoughThe Dynamic Language is not Enough
The Dynamic Language is not Enough
 
Functional Principles for OO Developers
Functional Principles for OO DevelopersFunctional Principles for OO Developers
Functional Principles for OO Developers
 

Mehr von Yan Cui

How to win the game of trade-offs
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offsYan Cui
 
How to choose the right messaging service
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging serviceYan Cui
 
How to choose the right messaging service for your workload
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workloadYan Cui
 
Patterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfYan Cui
 
Lambda and DynamoDB best practices
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practicesYan Cui
 
Lessons from running AppSync in prod
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prodYan Cui
 
Serverless observability - a hero's perspective
Serverless observability - a hero's perspectiveServerless observability - a hero's perspective
Serverless observability - a hero's perspectiveYan Cui
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functionsYan Cui
 
How serverless changes the cost paradigm
How serverless changes the cost paradigmHow serverless changes the cost paradigm
How serverless changes the cost paradigmYan Cui
 
Why your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncWhy your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncYan Cui
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeksYan Cui
 
Patterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsPatterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsYan Cui
 
How to bring chaos engineering to serverless
How to bring chaos engineering to serverlessHow to bring chaos engineering to serverless
How to bring chaos engineering to serverlessYan Cui
 
Migrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsMigrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsYan Cui
 
Building a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLBuilding a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLYan Cui
 
FinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyFinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyYan Cui
 
How to improve lambda cold starts
How to improve lambda cold startsHow to improve lambda cold starts
How to improve lambda cold startsYan Cui
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020Yan Cui
 
A chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayA chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayYan Cui
 
How to debug slow lambda response times
How to debug slow lambda response timesHow to debug slow lambda response times
How to debug slow lambda response timesYan Cui
 

Mehr von Yan Cui (20)

How to win the game of trade-offs
How to win the game of trade-offsHow to win the game of trade-offs
How to win the game of trade-offs
 
How to choose the right messaging service
How to choose the right messaging serviceHow to choose the right messaging service
How to choose the right messaging service
 
How to choose the right messaging service for your workload
How to choose the right messaging service for your workloadHow to choose the right messaging service for your workload
How to choose the right messaging service for your workload
 
Patterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdfPatterns and practices for building resilient serverless applications.pdf
Patterns and practices for building resilient serverless applications.pdf
 
Lambda and DynamoDB best practices
Lambda and DynamoDB best practicesLambda and DynamoDB best practices
Lambda and DynamoDB best practices
 
Lessons from running AppSync in prod
Lessons from running AppSync in prodLessons from running AppSync in prod
Lessons from running AppSync in prod
 
Serverless observability - a hero's perspective
Serverless observability - a hero's perspectiveServerless observability - a hero's perspective
Serverless observability - a hero's perspective
 
How to ship customer value faster with step functions
How to ship customer value faster with step functionsHow to ship customer value faster with step functions
How to ship customer value faster with step functions
 
How serverless changes the cost paradigm
How serverless changes the cost paradigmHow serverless changes the cost paradigm
How serverless changes the cost paradigm
 
Why your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSyncWhy your next serverless project should use AWS AppSync
Why your next serverless project should use AWS AppSync
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeks
 
Patterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applicationsPatterns and practices for building resilient serverless applications
Patterns and practices for building resilient serverless applications
 
How to bring chaos engineering to serverless
How to bring chaos engineering to serverlessHow to bring chaos engineering to serverless
How to bring chaos engineering to serverless
 
Migrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 stepsMigrating existing monolith to serverless in 8 steps
Migrating existing monolith to serverless in 8 steps
 
Building a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQLBuilding a social network in under 4 weeks with Serverless and GraphQL
Building a social network in under 4 weeks with Serverless and GraphQL
 
FinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economyFinDev as a business advantage in the post covid19 economy
FinDev as a business advantage in the post covid19 economy
 
How to improve lambda cold starts
How to improve lambda cold startsHow to improve lambda cold starts
How to improve lambda cold starts
 
What can you do with lambda in 2020
What can you do with lambda in 2020What can you do with lambda in 2020
What can you do with lambda in 2020
 
A chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage awayA chaos experiment a day, keeping the outage away
A chaos experiment a day, keeping the outage away
 
How to debug slow lambda response times
How to debug slow lambda response timesHow to debug slow lambda response times
How to debug slow lambda response times
 

Kürzlich hochgeladen

AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 

Kürzlich hochgeladen (20)

AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 

F# in the real world (NDC)