Recursion

Summarized using AI

A World Without Assignment

Aja Hammerly • March 17, 2014 • Earth

In the presentation "A World Without Assignment," Aja Hammerly explores the principles of functional programming contrasted with object-oriented programming (OOP), highlighting how to accomplish programming tasks without using assignment or mutable state. This talk, delivered at the MountainWest RubyConf 2014, underscores the compatibility of Ruby with functional programming techniques, demonstrating that developers can leverage these principles within an OOP context.

Key Points Discussed:
- Functional Programming Definition: The definition includes treating computation as the evaluation of mathematical functions, avoiding mutable state and data. A more practical definition emphasizes the creation of doing functions.
- Significance of Non-Assignment: The talk particularly focuses on avoiding assignment in programming, which simplifies testing and enhances code readability.
- Advantages of Functional Programming:
- Easier testing due to a known state.
- Enhanced concurrency by eliminating mutable state.
- Safe reuse of functions across projects.
- Brevity of code in functional languages like Scheme and Haskell.
- Ruby and Functional Concepts: Ruby allows integration of functional programming techniques without deviating from its OOP principles, providing practical examples, such as passing blocks and using methods from Enumerable.
- Introduction to Scheme: A brief explanation of Scheme as a functional programming language, particularly its prefix notation, function definitions, and recursion techniques were provided. Specific examples include calculating the absolute value and demonstrating recursion using factorials and Fibonacci sequences.
- Complex Problem Solving: Hammerly tackles a complex problem of making change for a dollar using recursion, illustrating the power of functional programming with concise code implementations.
- Key Resources for Learning: Recommended resources include "The Little Schemer" and "Structure and Interpretation of Computer Programs," alongside online lectures and events for deeper understanding.

Conclusions:
- Functional programming can enhance Ruby development through access to functional concepts, making programming tasks more manageable and maintainable. The importance of not using assignment can lead to increased code clarity and efficiency. Hammerly encourages attendees to explore these concepts further and utilize available resources for better comprehension of functional programming.

A World Without Assignment
Aja Hammerly • March 17, 2014 • Earth

In OO, assignment is one of our main tools. Most developers learn how to store values in variables shortly after learning "Hello World". By contrast, functional programming makes much less use of assignment and mutation. Instead techniques like function composition, recursion, and anonymous functions are used to produce the same results that OO programmers produce with side effects.
Despite being object oriented, Ruby easily accommodates pure functional approaches. This talk will demonstrate how common programming tasks can be accomplished without assignment or mutation. Ruby and Scheme (a Lisp dialect) will be used for examples. I'll also discuss some of the great resources available for those interested in digging deeper into functional programming.

Help us caption & translate this video!

http://amara.org/v/FG2H/

MountainWest RubyConf 2014

00:00:25.199 Good morning, everyone! People are actually awake at this conference in the morning. It's weird.
00:00:32.880 My first tech conference was Golden Gate RubyConf 2010, where Jim Wyrick gave the keynote.
00:00:39.200 He covered a wide variety of topics, including physical chemistry, which is one of my favorite subjects. He mentioned a book called 'The Structure and Interpretation of Computer Programs', which he said had been recommended more than any other book to help professional programmers improve their craft.
00:00:51.520 As a result, he started a study group, and his keynote was about what his group had learned from the first two chapters of the book.
00:01:03.440 The book contains five chapters, and you can imagine the depth of content covered in just the first two chapters. About 50 to 60 minutes into his 90-minute keynote, he mentioned that everything he had covered so far did not use assignment.
00:01:16.320 In fact, this book doesn’t introduce assignment until chapter three, which is more than forty percent of the way through. That little nugget stuck with me, and that's kind of where this talk started.
00:01:28.479 A little bit about me: I'm Aja Hammerly, and I tweet under the handle @thagomizer_rb. I enjoy when people tweet at me during my talk since my phone is over there, and I will read all your comments later. Just make sure they're nice! I'm also on GitHub as @thagomizer and occasionally blog at thagomizer.com, mostly sharing my talk slides. These slides would be posted there, but I had a technical issue with rsync about an hour ago.
00:01:46.640 I work at a company called Substantial, a digital product studio in Seattle, Washington. If you're ever in Seattle, check out our website, substantial.com, where we host many events for nerds of varying kinds.
00:02:06.719 What qualifies me to give this talk? Quite frankly, not much. However, based on Jim's keynote, a few of us in the Seattle Ruby community started a study group through SICP, which took us about nine months to complete.
00:02:20.239 Ryan is going to talk about that later. I also conducted a study group on functional programming last fall using a different book. If you've seen me speak before, you know that I have a deep fascination with esoteric programming languages like Prolog.
00:02:39.120 Once I started exploring that, I began noticing functional programming concepts everywhere. So, what is functional programming?
00:02:50.800 According to Wikipedia, functional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids mutable state and data. While that definition isn’t particularly insightful, one of my coworkers remarked that the concept of mutable state is suspicious and easy to mess up.
00:03:10.480 Jim provided a more practical definition in his talk: a functional language is about creating functions that do things, not just calling functions. For this talk, I will focus on a core aspect of functional programming: not using assignment.
00:03:29.680 There will not be a single equals sign in Ruby anywhere in this presentation. In Scheme, assignment is done using 'set!', but there won’t be any 'set!' operations in this talk either. I will also avoid modifying objects.
00:03:41.680 Setting expectations: I have 114 slides packed with code. I don't give fluffy talks, so be prepared for lots of parentheses! And no ponies... sorry, Mike.
00:03:55.760 Now, why should you care about functional programming? First of all, it's easier to test. There's significantly less setup and very little stubbing and mocking involved. Many times, on projects with functional aspects, we start from a known state.
00:04:13.360 This means your tests won't pollute your data across runs, and you avoid dependencies that might trip you up. Concurrency is also much easier in functional paradigms, where there’s no mutable state for threads to interfere with. It’s fantastic.
00:04:31.840 Functional programming advocates often talk about safe reuse—you can take a function from one project and move it wholesale into another, owing to the absence of mutable state. You also benefit from brevity, as functional programming languages like Scheme and Haskell are typically concise.
00:04:58.000 This brevity can be a double-edged sword, however, as some find it appealing while others might get frustrated by it. Ultimately, I think two of the biggest reasons to care about functional programming are that many of you are already using it and that Ruby makes it easy.
00:05:26.800 Raise your hand if you’ve ever passed a block to a method from Enumerable. That practice is heavily influenced by functional programming concepts. Since many of you are already doing it, you might as well learn the basics and utilize its strengths.
00:05:51.440 Moreover, Ruby natively supports many basic functional concepts, allowing easy integration of functional techniques without complex contortions. For instance, if you have a service in your Rails app that could benefit from functional ideas, you can implement them whilekeeping your rest of the Rails app in an object-oriented paradigm.
00:06:09.680 The functional language I know best, which also has real-world use, is Scheme. Let’s cover some basics of Scheme quickly.
00:06:27.919 The most important thing to know is that Scheme uses prefix notation, meaning that the function name appears before the arguments. In my slides, Ruby will be in red on the right, while Scheme will be in blue on the left.
00:06:46.240 For example, '5 + 3' in Ruby translates to '(+ 5 3)' in Scheme. Prefix notation allows for a variable number of arguments, so you can add or multiply multiple numbers in a single expression using the same method.
00:07:09.520 To define a function in Scheme, you use 'define' followed by the function name, arguments, and the method body. Instead of 'end', you just close with a parenthesis. Invocation is again straightforward—just the method name followed by the argument in parentheses.
00:07:29.520 For conditionals, functional programmers often use 'cond', which maps well to Ruby's 'case' statements. For example, an absolute value function can be built using 'cond' to evaluate cases based on the number's value.
00:07:53.039 In the first case, if the number is greater than zero, we simply return that number. If it’s zero, we return zero. Otherwise, we return the mathematical opposite using Scheme's unary minus.
00:08:12.400 Just as in Ruby, Scheme has an implicit return value for the last expression evaluated. However, this isn't how a true Schemer would write it, as brevity is preferred among them, leading to more condensed code.
00:08:30.640 Another conditional construct in Scheme is 'if'. A predicate function returns a boolean, and the structure leverages this by executing different branches based on the true or false evaluation of the condition.
00:08:54.000 The temperature example demonstrates this effectively: If it's above 65 degrees, it’s considered balmy, otherwise it is not.
00:09:13.280 Additionally, lists are fundamental in functional programming languages. In Scheme, you define a list using a single quote followed by parentheses and elements separated by spaces.
00:09:28.560 In Ruby, we use arrays like [1, 2, 3], whereas in Scheme and Lisp, the 'car' and 'cdr' functions are used to access the first element and the rest of the list, respectively.
00:09:43.440 Finally, the concept of checking whether lists are empty and utilizing 'null?' in Scheme corresponds to 'empty?' in Ruby. Scheme denotes true as '#t' and false as '#f'.
00:10:02.960 Now, let’s dive into recursion, one of my favorite topics, starting with a factorial definition in both Scheme and Ruby. If the number we're calculating is one, we return one; otherwise, we multiply the number by the factorial of the number minus one.
00:10:22.960 We've been calculating the factorial of five recursively: 5 times the factorial of 4, and so on, down to factorial of 1.
00:10:41.680 Recursion is fascinating and powerful in functional programming languages. Allow me to show you a Scheme implementation of the Fibonacci sequence next.
00:11:01.600 In this implementation, if n is zero, we return zero; if n is one, we return one. Otherwise, the nth Fibonacci is the sum of the Fibonacci numbers for (n-1) and (n-2). This closely mirrors Ruby's definition as well.
00:11:20.240 While these examples are fantastic, tail call optimization further enhances the performance of recursive functions. For example, let’s look at exponentiation.
00:11:38.000 In the basic exponentiation function, we compute b to the power of n by repeatedly multiplying b times b raised to the n-1.
00:11:56.280 However, the depth of the call stack can become excessive with this version if we raise very large powers. Regardless, we can optimize this using tail call optimization.
00:12:14.400 The alternative involves defining an accumulator that takes in our current product. We reduce the counter and increase the product with each recursive call until we reach zero.
00:12:36.720 Thus, we still make the same number of calls, but because all calculations are done immediately, we reduce the stack workload significantly.
00:12:56.240 Now, I want to present a classic functional programming example: making change. The task is to figure out how many ways you can make change for a dollar using half dollars, quarters, dimes, and nickels.
00:13:20.000 Initially, I thought the task was too challenging, so I opted to simplify it and determine how many ways I could make some amounts using various coin denominations.
00:13:43.760 As before, I defined a function called 'count_change', in which the amount is represented in cents. I'm assuming an infinite supply of coins for simplicity.
00:14:02.560 First, let's handle the case where there are no coins; in that instance, making any amount is impossible, so the function returns zero ways.
00:14:21.440 Next, we look at a base case: if the amount equals the first denomination, we return one way; if we have a penny and we want to make change for one cent, we can use exactly one penny.
00:14:41.760 In cases where the amount does not correspond to one denomination, we must invoke recursion to explore remaining values. Starting with a penny, we calculate how many ways we can make the amount with the remaining coins.
00:15:03.520 If we try using nickels and pennies, we discover that we can make five cents using either one nickel or five pennies, leading to some recursive exploration.
00:15:26.880 My testing revealed that, while my implementation was working, I needed to ensure each denomination's availability during recursion to accurately gauge change possibilities.
00:15:49.200 By reconstructing the recursive calls based on the denominations array, I could evaluate both scenarios: making the amount using a nominal value or not.
00:16:07.600 We can apply the 'no penny' case and sum it with the 'penny' option to derive the final outcomes. After refining my code through testing iterations, I could confirm these results.
00:16:29.920 Finally, I went back to the primary challenge: making one dollar worth of change. After implementing this with effective recursion, the answer was ideally calculated to be 292 possible combinations.
00:16:47.760 This solution, appearing much cleaner in Scheme, indicates how powerful concise functional expressions can be in handling complex problems.
00:17:06.640 To summarize, we explored different functional techniques and their advantages such as list operations, predicate behavior, and exhaustive enumeration within Ruby and Scheme, emphasizing their versatility across languages.
00:17:27.120 In particular, Ruby supports functional programming intuitively, enabling us to apply these concepts seamlessly in our code.
00:17:46.000 To deepen your understanding, I highly suggest further exploration into functional programming concepts, as they can greatly enhance your programming repertoire, particularly in Ruby.
00:18:05.200 I encourage those interested in functional programming to check out resources like 'The Little Schemer', which is concise and engaging, or 'Structure and Interpretation of Computer Programs', also known as the wizard book.
00:18:25.200 Both books dive deep into various concepts, promoting a better understanding of functional language theory and application.
00:18:43.200 You can also find numerous lectures online focusing on the intersection of functional programming and Ruby, which could greatly benefit your journey into this paradigm.
00:19:03.680 Events like Ruby Midwest and Goruco often feature talks on functional programming, and watching speakers like Pat Shaughnessy and Jessica Care can offer you diverse insights into the topic.
00:19:25.760 In particular, I highly recommend Jessica's presentation on functional principles in object-oriented development, which provides excellent perspectives.
00:19:47.840 Lastly, Jim Wyrick's 'Adventures in Functional Programming' is a fantastic resource, delivering dense information that made the subject enlightening while still challenging.
00:20:11.840 The need to cite images in presentations is important. I had one this time: the boring board pony. Thank you very much for your attention.
00:20:32.240 I have a moment for just one quick question.
00:20:40.840 Someone asked about my opinion on the Closure programming language. Though I haven't personally used it, those I know who have really enjoyed it, so it seems promising.
00:21:00.159 Okay, thank you all!
Explore all talks recorded at MountainWest RubyConf 2014
+12