Speaker 1: You know, usually when we think about building a massive
Speaker 1: digital platform, something that handles millions of requests a second,
Speaker 1: we picture this incredibly complex, chaotic web of moving parts.
Speaker 1: Oh absolutely, Like I always imagine a giant, sprawling restaurant kitchen.
Speaker 1: You have thousands of cooks constantly shouting tweaking recipes on
Speaker 1: the fly, grabbing ingredients out of each other's hands, you know,
Speaker 1: just to keep the whole dinner service from collapsing, right, And.
Speaker 2: That kitchen analogy highlights the exact danger developers face at scale,
Speaker 2: which is race conditions. Yeah, because when two chefs reach
Speaker 2: for the salt a millisecond apart and try to use
Speaker 2: it simultaneously, I mean, the entire system just crashes. It
Speaker 2: really feels like the bigger the architecture gets, the more
Speaker 2: inherently fragile it should be.
Speaker 1: But then you look under the hood of the apps
Speaker 1: you probably use just this morning. I mean, if you
Speaker 1: scroll through Twitter, ordered Nuber, watch Netflix, or bought something
Speaker 1: on Amazon recently, you haven't been interacting with a chaotic,
Speaker 1: fragile kitchen.
Speaker 2: No, not at all.
Speaker 1: You've been interacting with systems scaled using these remarkably stable,
Speaker 1: rigidly disciplined principles running on the Java virtual machine.
Speaker 2: And that stability. It actually came out of a painful
Speaker 2: industry wide realization because for decades the software world relied
Speaker 2: heavily on object oriented programming.
Speaker 1: Like Java or C sharp, Python exactly.
Speaker 2: Those languages established the bedrock of enterprise software. But as
Speaker 2: our digital world just exploded in scale, we hit this
Speaker 2: massive wall with concurrency.
Speaker 1: Meaning handling tons of users.
Speaker 2: At once right, handling millions of simultaneous users in traditional OOP,
Speaker 2: it required a nightmare of threadlocking and synchronization. We desperately
Speaker 2: needed a different approach.
Speaker 1: Which is the core mission of our deep dives. Today
Speaker 1: we are exploring the world of functional programming and a
Speaker 1: language called Scala, using our source material on how to
Speaker 1: build applications with it. Yeah, we're going to unpack exactly
Speaker 1: how the biggest tech companies keep the Internet running without
Speaker 1: their servers, you know, constantly catching on fire.
Speaker 2: It's a fascinating shift.
Speaker 1: So Scala enters the picture in two thousand and one,
Speaker 1: created by Martin O. Durski, and the text describes it
Speaker 1: as this post functional multi paradigm language.
Speaker 2: Yeah, it bridges a massive gap, but to understand how
Speaker 2: it solves modern concurrency problems. We actually have to look backward. Okay,
Speaker 2: functional programming's roots. They go all the way back to
Speaker 2: mathematical abstractions from the nineteen thirties, specifically this formal system
Speaker 2: called lambda calculus.
Speaker 1: Wait the nineteen thirties.
Speaker 2: Yeah, the nineteen thirties, And the very first language implementation
Speaker 2: of these ideas was Lisp back in the nineteen fifties.
Speaker 1: That's wild. I mean, I always assume functional programming was
Speaker 1: this modern, cutting edge Silicon Valley trend. But you're telling
Speaker 1: me it's practically ancient history and computer science.
Speaker 2: It is. But back in the nineteen fifties, maintaining the
Speaker 2: pure immutable state required by functional programming was incredibly expensive computationally.
Speaker 1: Like, the machines just couldn't handle it right.
Speaker 2: Computers just didn't have the memory or the processing power
Speaker 2: to do it efficiently. But today, well, hardware has finally
Speaker 2: caught up to the math. I see, those math based
Speaker 2: principles from the fifties are now what power the most
Speaker 2: modern infrastructure. We have massive big data tools like Hadoop
Speaker 2: or Spark. They're built entirely around map.
Speaker 1: Reduce, which is a functional concept.
Speaker 2: Literally, a functional programming concept. We've taken pure academic math
Speaker 2: and applied it to modern web scale traffic.
Speaker 1: Okay, so we have this beautiful nineteen thirties mathematical purity.
Speaker 1: But purity doesn't survive in the methi reality of modern
Speaker 1: web traffic unless it has an absolute workhourse of an
Speaker 1: engine to run on. That's right, and that's the compromise
Speaker 1: skull I had to make. It runs on the JVM.
Speaker 1: So it's like taking the aerodynamic ultra light chassis of
Speaker 1: a Formula one car and bolting it directly onto the
Speaker 1: undercarriage of a massive diesel freight train.
Speaker 2: I love that analogy.
Speaker 1: You get the cutting edge design, but you also get
Speaker 1: the unstoppable, heavy duty momentum of the track.
Speaker 2: Yeah, and that is the engineering pragmatism that made Skala
Speaker 2: a huge success. Tethering's Gala to the JVM provides massive
Speaker 2: immediate leverage. Also, you get native access to the entire
Speaker 2: existing Java ecosystem, all those frameworks, enterprise library, security tools
Speaker 2: that developers have spent the last twenty years building. Yeah,
Speaker 2: Scala can interact with them natively.
Speaker 1: I still have to push back a little here, though.
Speaker 1: Sure if functional programming is this massive evolution from object
Speaker 1: oriented programming. Why not just build a totally new runtime
Speaker 1: environment from scratch. Why tether this sleek f one car
Speaker 1: to legacy infrastructure.
Speaker 2: It really just comes down to operational leverage. The JVM
Speaker 2: is entirely battle tested by web scale companies. It has
Speaker 2: proven it won't break when a million people click a
Speaker 2: button at the exact same time, and more importantly, your
Speaker 2: IT and DevOps teams they already know how to deploy, monitor,
Speaker 2: and scale JVM applications.
Speaker 1: Ah, so there's no learning curve for the operation side.
Speaker 2: Exactly, if you introduce a completely new language with a
Speaker 2: completely new run time, you force a company to been
Speaker 2: millions of dollars rebuilding their entire deployment pipeline.
Speaker 1: That makes a lot of sense.
Speaker 2: With Scala, a company's operations team can run the application
Speaker 2: exactly the same way they run legacy Java apps. Plus
Speaker 2: Scala code can call Java code and vice versa.
Speaker 1: So you aren't forcing an enterprise to just throw away
Speaker 1: twenty years of legacy code just to modernize their concurrent processing.
Speaker 2: Right.
Speaker 1: Okay, that makes perfect sense. But since Scala runs on
Speaker 1: the exact same engine as Java, the difference isn't the
Speaker 1: machine itself. The transition we're talking about today is entirely
Speaker 1: about the mindset of the developer driving it, and it.
Speaker 2: Requires a radical shift. You're moving from imperative programming to
Speaker 2: declarative programming.
Speaker 1: I get the declarative mindset in theory, you know, telling
Speaker 1: the system what I want to accomplish, not how to
Speaker 1: do it. Yes, But mechanically, if I take away a
Speaker 1: developer's ability to use imperative tools like for loops and
Speaker 1: STANDARDI fel statements that mutate variables, aren't I just crippling
Speaker 1: their toolkit? How does Scala compensate for them?
Speaker 2: Well, you aren't crippling the toolkit. You're elevating the abstraction.
Speaker 1: Elevating the extraction.
Speaker 2: Yeah.
Speaker 1: Right.
Speaker 2: Imperative programming involves micromanaging the computer's state. You use statements
Speaker 2: to manually dictate the sequence of operations. Update this counter,
Speaker 2: move this pointer, check this condition, very step by step
Speaker 2: exactly declarative programming, specifically, in a functional paradigm, it focuses
Speaker 2: on composing expressions. Okay, Instead of a for loop that
Speaker 2: mutates a counter variable, you use recursive structures and higher
Speaker 2: order functions like map, filter or reduce. Those functions transform
Speaker 2: a collection of data into a new collection without ever
Speaker 2: altering the original.
Speaker 1: And a big part of that shift is tackling what
Speaker 1: the architecture documentation calls the ultimate villain in software design,
Speaker 1: shared mutable state.
Speaker 2: Oh yeah, shared mutable state is basically the root cause
Speaker 2: of almost every major concurrency bug in existence.
Speaker 1: Wow.
Speaker 2: It's essentially a global variable that multiple different functions or
Speaker 2: threads have direct access to, and they can modify it
Speaker 2: at any given moment.
Speaker 1: Returning to our restaurant kitchen, shared mutable state is having
Speaker 1: ten different chefs standing around a single pot of soup. Yes, exactly,
Speaker 1: One chef adds salt, another unexpectedly swaps out the chicken
Speaker 1: broth for beef broth. Another turns the heat up to boiling,
Speaker 1: and none of them are communicating, which is a disaster,
Speaker 1: total chaos. When the soup finally reaches the customer, it's
Speaker 1: ruined and you have absolutely no idea which chef destroyed
Speaker 1: it or at what specific millisecond the error occurred.
Speaker 2: And that lack of traceability is the true nightmare of
Speaker 2: shared mutable state. It makes systems incredibly difficult to scale.
Speaker 2: I can imagine refactoring the codebase becomes terrifying because you
Speaker 2: can never trust the local method. You have to trace
Speaker 2: every single function across the entire program that might touch
Speaker 2: that global variable. Just to understand the logic.
Speaker 1: That sounds exhausting, it is.
Speaker 2: Functional programming avoids this entirely by ensuring state is kept
Speaker 2: local and isolated.
Speaker 1: So in the ft kitchen, every chef gets their own ingredients,
Speaker 1: their own private cutting board, and a strict recipe that
Speaker 1: absolutely cannot be altered mid cook. Precisely which brings us
Speaker 1: to the actual rules of this new kitchen. The core
Speaker 1: pillars of functional programming. The biggest one, the absolute bedrock
Speaker 1: of this philosophy is immutability.
Speaker 2: Yeah, and immutability simply means that once a value is
Speaker 2: assigned to a variable, it can never ever be changed.
Speaker 2: It is locked in memory.
Speaker 1: But wait, if I can never change you variable, how
Speaker 1: does my application actually process data? Like if a user
Speaker 1: updates their profile picture and their profile object is immutable,
Speaker 1: how do they get a new picture?
Speaker 2: So you replace state mutation with discipline state discipline state right.
Speaker 2: Instead of overwriting the existing profile object with the new picture,
Speaker 2: your function creates a brand new instance of the profile
Speaker 2: object that contains the new picture while preserving the old one.
Speaker 2: You leave the original data completely alone.
Speaker 1: But wouldn't that use a massive amount of memory just
Speaker 1: constantly creating copies of everything.
Speaker 2: It would if it were literally copying everything, But Scala
Speaker 2: uses highly optimized structural sharing under the hood. Oh, when
Speaker 2: you create that new profile object, it actually shares references
Speaker 2: to all the unchanged data like the username and email
Speaker 2: from the original object.
Speaker 1: That's clever.
Speaker 2: Yeah, it only allocates new memory for the piece that changed,
Speaker 2: and the operational payoff for this is massive because there
Speaker 2: are no side effects. Your code is parallel by nature.
Speaker 1: Because multiple threads can read that data at the exact
Speaker 1: same time without locking each other out.
Speaker 2: Yes, you completely eliminate the need for thread synchronization locks.
Speaker 2: Your program can run incredibly fast concurrently across dozens of processors.
Speaker 1: Because no function is ever waiting to see if another
Speaker 1: function is currently mutating the data exactly. It mathematically eliminates
Speaker 1: the traffic jams in the system.
Speaker 2: It really does.
Speaker 1: So that brings us to how we actually manipulate this
Speaker 1: immutable data. The functions themselves. In functional programming, they get
Speaker 1: special treatment. We hear the terms first class function and
Speaker 1: higher order functions thrown around constantly.
Speaker 2: Yeah, and treating functions as first class citizens. Means the
Speaker 2: programming language treats a function exactly the same way it
Speaker 2: treats an integer or a string. Okay, you can assign
Speaker 2: a function to a variable. You can pass a function
Speaker 2: as an argument into another function. You can even return
Speaker 2: a function as the result of an operation.
Speaker 1: So they aren't just rigid script sitting on a server.
Speaker 1: They're fluid pieces of data you can pass around your architecture.
Speaker 2: Right, and that leads to higher order functions. These are
Speaker 2: functions that take other functions as parameters.
Speaker 1: Got it.
Speaker 2: This enables incredibly powerful techniques like currying and partial functions.
Speaker 1: Okay, currying, let's unpack that.
Speaker 2: Currying is a mathematical technique where you take a function
Speaker 2: that requires multiple parameters and you transform it into a
Speaker 2: sequence of chain functions where each function takes only a
Speaker 2: single argument.
Speaker 1: Okay, I need a concrete example of that. Why would
Speaker 1: I want to break a perfectly good multi parameter function
Speaker 1: into a chain of single argument functions.
Speaker 2: Well, imagine you have a function that queries a secure database.
Speaker 2: It requires three arguments, an authentication token, the database endpoint,
Speaker 2: and the actual query payload.
Speaker 1: Siple enough.
Speaker 2: Instead of passing all three arguments, every single. Time a
Speaker 2: UI component requests data, currying allows you to basically bake
Speaker 2: in the authentication token. Once that applications start up, you
Speaker 2: pass the token in and it returns a new function
Speaker 2: that only requires the endpoint and payload. Then you can
Speaker 2: bake in the end point, returning yet another new function
Speaker 2: that only needs the payload.
Speaker 1: Oh wow, So I can pass that final single argument
Speaker 1: function down to my front end UI components exactly, and
Speaker 1: the UI just passes the query payload totally unaware of
Speaker 1: the complex authentication or endpoint routing happening behind the scenes.
Speaker 1: You're building customized single purpose tools on the fly.
Speaker 2: It creates incredible modularity. It's heavily utilized in pure functional
Speaker 2: languages like Haskell and Skoalar provides native support to build
Speaker 2: these pipelines effortlessly.
Speaker 1: This is where the architecture really starts to click for me.
Speaker 1: But here's the piece of the puzzle that initially threw
Speaker 1: me off.
Speaker 2: What's up.
Speaker 1: Scalar relies on a statically type system, A strong type system.
Speaker 1: My instinct says that rigid, strict typing means more boilerplate,
Speaker 1: more rules, and inevitably more testing to make sure everything aligns.
Speaker 1: A lot of people think that, yet the documentation makes
Speaker 1: this wild claim. A strong type system actually forces you
Speaker 1: to write fewer.
Speaker 2: Tests, and it does because Skala is statically typed. You're
Speaker 2: shifting the burden of validation from run time tests back
Speaker 2: to compile time. Okay, the compiler essentially becomes your strictest
Speaker 2: editor in your first line of defense. Oh so well,
Speaker 2: in a dynamically typed language like JavaScript or Python, you
Speaker 2: might write a function that expects a user's age as
Speaker 2: an integer and a separate service accidentally passes the word
Speaker 2: thirty as a string. Right, the program will accept it,
Speaker 2: and it might not crash until it's actually running live
Speaker 2: in production and tries to run math on a word.
Speaker 1: Which is exactly why to developers in dynamic languages spend
Speaker 1: hours writing massive suites of unit tests just to verify.
Speaker 1: You know, is this number? Is this a string? Please
Speaker 1: handle this gracefully, right.
Speaker 2: But in a strong type language like Scala, you define
Speaker 2: the exact type upfront in.
Speaker 1: The function signature, so it's locked in.
Speaker 2: If that function demands an integer type and you try
Speaker 2: to pass it a string of texts, the compiler simply
Speaker 2: refuses to build the application. It won't let you make
Speaker 2: that basic routing mistake, you don't have to write a
Speaker 2: test checking if the input is an integer, because it
Speaker 2: is mathematically impossible for the wrong data type to enter
Speaker 2: that function in the first place. The compiler catches the
Speaker 2: error before the program ever executes.
Speaker 1: And that leads directly into another core concept you see
Speaker 1: constantly in functional architecture, referential transparency.
Speaker 2: Yes, referential transparency is the ultimate result of combining immutability
Speaker 2: with strict types. Okay, it means that any function call
Speaker 2: can be seamlessly replaced by its output value without changing
Speaker 2: the behavior of the program.
Speaker 1: Break that down mechanically. Why does that matter computationally?
Speaker 2: Think of it like a math equation. If x equals five,
Speaker 2: and why equals x plus two, you can confidently just
Speaker 2: replace x with five. Everywhere you know the answer is
Speaker 2: always seven. But in imperative programming, a background thread might
Speaker 2: have mutated x to equal ten right before why was calculated?
Speaker 2: You can't trust the variable unpredictable exactly because Scala enforces immutability.
Speaker 2: A function called calculate tax given the input one hundred,
Speaker 2: will always unequivocally return ten.
Speaker 1: Because nothing else can mess with it.
Speaker 2: Right, Because it relies on no external mutable state. The
Speaker 2: system can safely cache that result ten across one thousand
Speaker 2: different servers.
Speaker 1: So you don't have to waste CPU cycles constantly recalculating
Speaker 1: it or checking if the global tax rate variable changed
Speaker 1: in the background. That cuts out massive amounts of compute
Speaker 1: time at scale.
Speaker 2: Yeah, the code essentially becomes its own reliable mathematical documentation.
Speaker 2: You can parallelize and cache aggressively, which is the secret
Speaker 2: to scaling applications to millions of users.
Speaker 1: Okay, so we've established the philosophy. We have our disciplined
Speaker 1: immutable kitchen where chefs pass around first class functions and
Speaker 1: the compiler acts like a straight head chef, checking every
Speaker 1: ingredient at the door.
Speaker 2: That's a great summary, but.
Speaker 1: Let's look at the actual reality the code. Comparing Java
Speaker 1: to Scala side by side.
Speaker 2: The best place to start that comparison is in the
Speaker 2: interactive shell, the r epl.
Speaker 1: Right, the read evil, print and loop. Because if I
Speaker 1: want to write a standard Java application to test a
Speaker 1: quick piece of logic, I have to configure a whole
Speaker 1: project environment.
Speaker 2: It's a hassle.
Speaker 1: But with Scala, you just open your terminal type Scala
Speaker 1: and you drop straight into an interactive loop. You type
Speaker 1: of command, it evaluates, it prints the result, and waits
Speaker 1: for the next input.
Speaker 2: It creates an incredibly fast feedback loop for developers. You
Speaker 2: can test complex functional pipelines without compiling an entire enterprise application.
Speaker 1: In slight way.
Speaker 2: Yeah, but when we look at formal application structure, the
Speaker 2: verbosity of Java compared to the conciseness of Scala is stark.
Speaker 1: It really is. The documentation gives a great side by
Speaker 1: side Hello World showdown. In Java, printing a simple phrase
Speaker 1: to the screen requires about six lines of code. You
Speaker 1: have to define your package to find a public class,
Speaker 1: write out the incredibly formal method, signature of public static void, mainstream, brackets, arcs,
Speaker 1: and finally call system dot out dot print.
Speaker 2: In it's an immense amount of ceremony for a simple action.
Speaker 1: Right, and in Scala, achieving the exact same result takes
Speaker 1: three lines. You write object hello world, extends app, open
Speaker 1: your bracket, write print on Hello World, and close it.
Speaker 2: Yeah. By extending that app trait, Scala completely abstracts away
Speaker 2: the need for the developer to define that massive main method.
Speaker 2: It's built into the language.
Speaker 1: It's so clean, but there's a specific keyword you just used.
Speaker 1: That signifies a massive architectural difference. You said object, Hello world,
Speaker 1: not class Hello World.
Speaker 2: Ah. Yes, this is a crucial distinction in maintaining a
Speaker 2: discipline state. In Scala. Simply using the key word object
Speaker 2: instead of class automatically creates a singleton pattern at the
Speaker 2: language level.
Speaker 1: And just to clarify the mechanics for a second, a
Speaker 1: singleton is a design pattern used when you only ever
Speaker 1: want one single instance of an object to exist across
Speaker 1: the entire system, exactly, things like database connection pools or
Speaker 1: configuration managers. But doing this safely in Java is notoriously difficult.
Speaker 2: Oh, building a thread safe singleton in Java requires a
Speaker 2: nightmare of boilerplate.
Speaker 1: Really.
Speaker 2: Oh yeah, You have to write a private constructor so
Speaker 2: other classes can't instantiate it. You need a static instance variable,
Speaker 2: You have to write a get instance method. And that's
Speaker 2: just the start, right, Because if you are in a
Speaker 2: multi threaded environment, you have to implement double checked locking
Speaker 2: with synchronization blocks just to ensure two threads don't accidentally
Speaker 2: create two instances at the exact same millisecond. Wow, it
Speaker 2: takes over a dozen lines of complex, error prone code.
Speaker 1: And in Scarlight you just type the word object. That's it.
Speaker 2: The language provides the thread safe abstraction implicitly. It handles
Speaker 2: the lazy initialization safely under the hood.
Speaker 1: That's amazing.
Speaker 2: When you multiply that reduction in boiler played across a
Speaker 2: million line code base, the cognitive load on the developers
Speaker 2: drops dramatically. Writing less code mathematically means you have a
Speaker 2: smaller surface area for bugs to hide.
Speaker 1: Let's close out the code segment with the absolute basics
Speaker 1: of how variables are handled. Because we said immutability is
Speaker 1: the core of functional programming, but we also know Scala
Speaker 1: is multi paradigm. Does the language physically force you to
Speaker 1: only use immutable variables.
Speaker 2: It doesn't force you, but it's design deeply favors it.
Speaker 2: You have two options for declaring variables in scalavarn val.
Speaker 2: If you use var, you are creating a mutable reference
Speaker 2: of value you can overwrite later.
Speaker 1: The dreaded mutable state.
Speaker 2: Well, it's only dreaded if you allow it to escape
Speaker 2: your local scope.
Speaker 1: Fair point.
Speaker 2: Sometimes mutating a local counter inside a highly isolated function
Speaker 2: is just more computationally efficient. But the standard default in
Speaker 2: Scala is val, and val means when you dec fila
Speaker 2: of variable. With val, you are creating a strictly immutable reference.
Speaker 2: Once it points to an object, it can never be reassigned.
Speaker 1: Never.
Speaker 2: The compiler will literally throw an error and halt the
Speaker 2: build if you attempt to reassign it.
Speaker 1: So it's building the guardrails directly into the syntax exactly. So,
Speaker 1: looking at this entire journey from nineteen thirty's math to
Speaker 1: compiling immutable variables on the JVM, what does this all
Speaker 1: mean for you, the listener?
Speaker 2: It's a big question.
Speaker 1: This deep dive wasn't just about learning a new programming
Speaker 1: syntax or comparing the spelling of Java versus Skala. What
Speaker 1: we're really talking about is a profound philosophy of predictability.
Speaker 2: Yeah, when you eliminate shared mutable state, lock down your
Speaker 2: values with immutability, and let a strict compiler catch your
Speaker 2: logical errors before runtime, you remove the chaos from the system.
Speaker 1: You totally do.
Speaker 2: You shift from hoping your application works to mathematically proving
Speaker 2: it works.
Speaker 1: And that predictability is exactly what provides the unbelievable horsepower
Speaker 1: required to the world's biggest digital platform smoothly, absolutely, but
Speaker 1: beyond the server room, the core concepts of functional programming
Speaker 1: actually offer an incredibly interesting lens for how we process
Speaker 1: information in our own lives.
Speaker 2: It really is a fascinating parallel think about how we
Speaker 2: operate as human beings in the modern world. Okay, we
Speaker 2: have dozens of browser tabs open, our phones are constantly buzzing.
Speaker 2: We're trying to retain a thought for an upcoming meeting
Speaker 2: while actively listening to a conversation.
Speaker 1: Guilty is charged.
Speaker 2: We are constantly allowing external side effects to interrupt our
Speaker 2: local functions. We essentially live our lives as one giant, chaotic,
Speaker 2: shared mutable state.
Speaker 1: We are constantly getting our internal variables overwritten by distractions.
Speaker 2: Which leaves us with a compelling final thought, love that
Speaker 2: if enforcing strict constraints like absolute immutability and zero side
Speaker 2: effects is the exact mechanism that allows our computing systems
Speaker 2: to become infinitely more scalable, resilient, and creative, how might
Speaker 2: we apply that to our own own daily workflows. If
Speaker 2: we treated our current task as a pure function, blocking
Speaker 2: out all external inputs, refusing to let our attention be
Speaker 2: mutated by an incoming notification, could adopting a functional mindset
Speaker 2: actually free us from our own mental bugs and cognitive overload.
Speaker 1: Shutting down the chaotic kitchen in our own minds. Every
Speaker 1: chef gets their own cutting board exactly. It is definitely
Speaker 1: something to experiment with the next time you sit down
Speaker 1: to focus. Thank you so much for joining us on
Speaker 1: this deep dive today. We hope it gave you a
Speaker 1: totally new perspective on the invisible architecture running the modern world.
Speaker 1: Keep exploring, keep questioning the systems running behind the scenes,
Speaker 1: and we will catch you next time.