List

Joyful Polyglot: Beautiful insights from many languages

Joyful Polyglot: Beautiful insights from many languages

by Nick Barone

In the talk "Joyful Polyglot: Beautiful Insights from Many Languages," presented by Nick Barone at RubyConf 2021, the speaker explores how insights from various programming languages can enrich the understanding of Ruby and improve programming practices. Barone emphasizes that each programming language approaches coding differently, guiding developers in unique ways to structure their thoughts and code.

Key Points Discussed:

- Importance of Language Diversity: Barone shares his experience of learning from multiple languages, suggesting that exposure to different programming paradigms enhances problem-solving skills and coding style.

- Currying in JavaScript: He illustrates currying functions, a concept in JavaScript, by demonstrating how to transform code for image processing into a more legible structure using curried functions, which can be directly translated to Ruby.

- Scala’s Companion Objects: Barone discusses companion objects in Scala and their ability to access private members, showcasing how similar patterns can be applied in Ruby using modules to effectively separate data and state in code.

- Java Interfaces: He examines Java interfaces and how they can be leveraged in Ruby by creating wrappers around dependencies, enabling clearer interaction with external libraries.

- Spring Framework Beans: Barone highlights the Spring Framework's ability to wire components together automatically, suggesting ways to achieve similar dependency injection techniques in Ruby, ultimately promoting separation of logic and the timing of execution.

Significant examples:

- Throughout the talk, Barone provides coding examples, transitioning from JavaScript to Ruby to demonstrate concepts like currying and dependency injection, emphasizing legibility and maintainability of code.

- He shares insights from a real-world chatbot project, illustrating how incorporating these principles led to clearer, more beautiful code.

Conclusions/Takeaways:

- The talk concludes with a reminder that learning from various programming languages enriches Ruby programming and enhances the clarity and maintainability of code. Barone encourages experimentation with functional patterns and novel implementations within Ruby, advocating for continued exploration of code aesthetics and effective structuring.

- He stresses the significance of writing code that is not only functional but also beautiful, as this contributes to deeper satisfaction and understanding in programming work.

Every language teaches you something beautiful, leading new and experienced programmers alike to novel and joyful ways to think about code. Would you benefit from a broader bag of programming concepts, or are you just curious about what can be learned when venturing outside your current box? From C++'s template metaprogramming to Scala's companion objects and more, this talk will explore a multitude of different programming languages and how the ideas and principles exemplified by each can be used by any other - but specifically, Ruby.

RubyConf 2021

00:00:10.080 i'm nick
00:00:11.280 and i'm a first time speaker so let's
00:00:13.040 all collectively pretend like i know
00:00:14.400 what i'm about to do and i'm going to
00:00:16.800 talk about things i've learned from
00:00:18.000 other programming languages
00:00:19.680 because in my career i've learned a lot
00:00:23.279 i've worked in a lot of different
00:00:24.880 languages i think this is all of them
00:00:26.960 but don't quote me on that
00:00:29.679 and the first thing to note is just that
00:00:31.840 each
00:00:32.719 language has a different way that it
00:00:35.280 approaches thinking about code and this
00:00:37.280 comes from both the structure of the
00:00:38.480 language itself as well as the way that
00:00:40.399 communities have created the libraries
00:00:42.879 that you then end up using when you are
00:00:44.800 working in that language and so
00:00:48.480 it guides your thinking it helps you to
00:00:50.000 explore different ways to contemplate
00:00:53.039 how to write code how to organize your
00:00:54.800 thinking and all of that learning is
00:00:57.039 expressible in any other language i mean
00:00:59.440 that's part of what makes during
00:01:00.719 complete right
00:01:02.559 so
00:01:03.520 this is really about hey we can look at
00:01:05.600 some feature of another language some
00:01:07.280 way that some other language likes to
00:01:09.040 think and then how can we apply that
00:01:11.360 thinking either directly or as
00:01:12.960 inspiration for something to do in ruby
00:01:16.240 so i'm going to talk about four specific
00:01:18.320 things uh current functions in
00:01:20.159 javascript companion objects from scala
00:01:22.960 interfaces from java and beans from
00:01:25.759 javaspring framework unless you think
00:01:27.439 i'm a java fan going no
00:01:31.280 so current functions
00:01:33.920 i'm glad you got that
00:01:35.920 so canonically current functions are
00:01:37.920 just a function that returns a function
00:01:39.360 this is a very straightforward
00:01:40.640 javascript example where we're rewriting
00:01:43.280 the addition operation as create
00:01:45.600 functions
00:01:47.200 this can very directly be translated to
00:01:49.040 ruby using procedures
00:01:50.880 but we also have this neat little thing
00:01:53.119 called dot curry
00:01:54.960 all this is saying is hey i'm a function
00:01:56.560 that takes two parameters and you have
00:01:58.320 one and then later you can give another
00:02:01.680 so i first learned about curried
00:02:03.920 functions when i need to detain callback
00:02:05.759 hell i'm gonna blaze through the
00:02:06.960 javascript because we're here for the
00:02:08.319 ruby
00:02:09.280 uh so this is a big chunk of javascript
00:02:11.840 that goes through a directory and
00:02:14.000 creates a bunch of uh different images
00:02:16.959 preserving aspect ratio
00:02:19.040 and we're gonna recompose it into a much
00:02:21.120 prettier current function setup so the
00:02:23.680 first thing that i did is i pulled out
00:02:25.920 the
00:02:26.800 the bit that gets the aspect ratio
00:02:29.280 into its own function
00:02:31.599 placed it there
00:02:33.440 then i pulled out the bit that does the
00:02:35.200 image resizing
00:02:40.160 placed it there and now at the bottom
00:02:41.840 i've got this really handy little block
00:02:43.440 of code that really eloquently describes
00:02:45.200 everything that i'm doing all of my code
00:02:47.040 blocks are named right read directly for
00:02:49.680 each file get the aspect ratio for each
00:02:52.319 width resize
00:02:53.840 much more
00:02:55.280 legible than before so now for the ruby
00:02:57.920 example that you're all here for
00:02:59.920 uh so this is before currying we're
00:03:01.920 going to move a bunch of objects from
00:03:03.680 one location to another in s3 now
00:03:06.080 ironically
00:03:07.519 when i carry it it gets a lot bigger so
00:03:09.840 what do we get from this and don't worry
00:03:12.000 if you can't read all the stuff i'm
00:03:13.200 going to go through each piece of this
00:03:14.640 code
00:03:15.760 so the first thing that this lets us do
00:03:17.280 is let's let's let's us slice up our
00:03:20.159 code in a really novel way we can kind
00:03:22.000 of pull out little steps so what i'm
00:03:24.480 doing here is i'm building a couple of
00:03:25.920 different iterators that i can then pick
00:03:28.000 up and carry around and do anything with
00:03:30.560 so that's what i mean by pull out the
00:03:32.000 middle slice
00:03:34.560 and then that lets me recompose
00:03:37.360 my code in terms of functions right
00:03:39.040 we're all used to dot chains or mixins
00:03:41.360 but this kind of lets me do it with
00:03:42.879 functions as well i can do this
00:03:44.319 composition step right so i can take my
00:03:46.400 iterator from before and i combine it
00:03:48.640 with a little slice of computation to do
00:03:50.640 the copying and i get my resulting
00:03:53.439 code
00:03:55.519 one of the things that i really value
00:03:57.360 from doing this is when i stick to a
00:03:59.599 very functional style
00:04:01.840 i have a very clear description of all
00:04:04.480 of the dependencies that my code has
00:04:07.040 both in terms of literally the client
00:04:08.959 but also in the information that i'm
00:04:10.640 going to need to use to do what i'm
00:04:12.319 about to do because i can just look at
00:04:14.000 the function signature there's nothing
00:04:16.160 in there that doesn't come from those
00:04:18.479 two
00:04:19.440 parameter lists
00:04:22.079 this then of course makes it really easy
00:04:23.759 to do dependency injection because all
00:04:25.280 my dependencies are parameters
00:04:28.800 and that then has the further on effects
00:04:30.880 that it's really easy to test each
00:04:32.400 function because we have no need for
00:04:33.840 state
00:04:35.280 and i found that when i go to write my
00:04:37.759 tests i just go down my library file
00:04:40.560 write a function or two write a test for
00:04:42.560 test or two for each function by the end
00:04:44.240 of it i've got 90 to 95 percent test
00:04:46.400 coverage without ever having to think
00:04:48.160 about it
00:04:49.600 right so just to right we slice up the
00:04:52.720 code in a different way we can compose
00:04:54.560 my functions we can clear we have very
00:04:56.960 clear dependencies which makes it easy
00:04:58.639 to do dependency injection which makes
00:05:00.479 it easy to do tests uh and it makes it
00:05:02.960 easy to get full test coverage
00:05:05.440 uh any quick questions about complaint
00:05:08.240 about code functions
00:05:10.400 all good sweet all right companion
00:05:12.720 objects
00:05:14.400 this is a concept from scala so we have
00:05:16.560 kind of a singleton object that's the
00:05:18.639 same name as a class
00:05:20.960 and this is a core language feature in
00:05:23.199 scala
00:05:24.479 and they have a bunch of special
00:05:25.759 relationships and the one i'm going to
00:05:27.120 point out here is that they can access
00:05:29.600 each other's private aspects be those
00:05:32.080 member functions or variables
00:05:35.039 so we can kind of pull this off into
00:05:36.720 ruby using introspection
00:05:39.199 but that's not great
00:05:42.160 so instead what i ended up doing when i
00:05:44.080 beat my head against the wall for a
00:05:45.199 while i was like how can i take
00:05:46.240 inspiration from this what can i do i
00:05:47.680 really like this pattern it feels good
00:05:49.280 what am i going to do with it i end up
00:05:50.880 doing this kind of stuff uh so i've got
00:05:52.960 some module and i've got some
00:05:54.160 boilerplate at the bottom lets me handle
00:05:55.919 the new while having the names be the
00:05:58.080 same uh and then i've got this struct
00:06:01.120 and i'm extending with the module
00:06:04.960 so what does this let us do uh so this
00:06:07.280 is again an example of moving around
00:06:09.280 files on s3 and again i'm going to go
00:06:11.440 through each block of code in this so
00:06:13.600 don't worry if
00:06:15.840 right so the first thing and it's
00:06:17.840 fitting that i learned scala within the
00:06:19.759 context of apache spark which is a
00:06:21.360 distributing computing thing because the
00:06:23.360 first thing i think this lets us do is
00:06:25.039 really cleanly separate the data that
00:06:27.120 we're going to use to do our computation
00:06:29.520 from the state of that computation right
00:06:32.240 so the struct between the prefix the
00:06:34.319 toke the bucket the prefix and the
00:06:36.080 continuation token for the pagination
00:06:38.800 uh that's all the information that we
00:06:40.319 need to actually do the computation but
00:06:42.880 independent of that is the state of the
00:06:44.639 iterator and because i've got them
00:06:46.319 separated
00:06:47.520 it's really easy to hand that around and
00:06:49.120 get along with my clones
00:06:52.080 so the next thing it lets us do is this
00:06:53.680 really appealing to me at least split
00:06:56.639 for my statics and my methods where i
00:06:58.639 can put all of my transformations in one
00:07:00.960 place and i can put all my actions in
00:07:03.120 another
00:07:04.160 so i've got on the left here under
00:07:05.520 transformations the pagination action
00:07:07.919 right i'm transforming my iterator into
00:07:10.000 the next page but then the action of
00:07:12.319 each iterator is the classic each
00:07:16.479 uh the next thing that i've been calling
00:07:18.479 it dependency application because in my
00:07:20.160 mind it feels sort of like the inverse
00:07:22.000 of dependency injection but i can take
00:07:24.319 any data structure that represents this
00:07:26.479 computation that has these little bits
00:07:28.479 of data and i can apply these functions
00:07:30.800 and run with it so it kind of feels like
00:07:32.960 i'm applying the dependencies to some
00:07:36.319 data
00:07:37.599 so again what this lets us do
00:07:40.000 we can distribute our computing easier
00:07:42.000 because we can separate the data that
00:07:44.000 we're using to compute from the state of
00:07:46.160 that computation we can separate our
00:07:48.479 actions and our transformations
00:07:50.800 and we can
00:07:52.000 apply our code to any piece of data and
00:07:55.120 that last one has been particularly
00:07:56.639 useful again in testing
00:07:58.479 because i can just write down the state
00:08:00.160 that i want to start from and go from
00:08:02.000 there
00:08:04.080 right interfaces
00:08:08.000 some of you are older like me
00:08:10.479 all right so uh interfaces do show up in
00:08:12.800 other places i think canonically they
00:08:14.800 started as abstract classes in c plus
00:08:16.720 plus but whoopty do all we're doing is
00:08:18.720 we're describing all the things you're
00:08:19.919 going to use
00:08:21.360 uh
00:08:22.479 descendants of the class to do
00:08:25.120 in one place but we're not actually
00:08:26.639 going to describe any of the code that
00:08:28.479 does it
00:08:29.680 so in ruby we can pull that off by
00:08:31.840 raising exceptions but again
00:08:33.919 not very satisfying
00:08:35.599 so what i've ended up doing is i've
00:08:37.519 started wrapping all of my dependencies
00:08:40.640 and this is inspired by the interface
00:08:42.320 pattern even if it's not directly the
00:08:44.080 interface pattern so here's a snippet of
00:08:46.080 an s3 wrapper again
00:08:48.320 gives us an iterator for the bucket
00:08:49.680 items gives us a function for moving
00:08:52.320 and
00:08:53.600 here's a real world example uh from a
00:08:55.839 chatbot hobby project i've got where i'm
00:08:58.160 interacting with dialogflow and
00:08:59.680 dialogflow for a lot of valid reasons
00:09:02.240 but still painful reasons has these
00:09:04.240 deeply nested complex data structures
00:09:06.399 that it thinks in and so in order to do
00:09:08.240 the request i have to build all this
00:09:10.240 data structure when really all i want to
00:09:12.640 do is say how do i respond when a
00:09:14.720 stranger says hello
00:09:17.680 so
00:09:18.560 what does this pattern let us do
00:09:20.959 it lets us write our own domain specific
00:09:22.640 language because i can say the action
00:09:24.800 that i care about instead of
00:09:27.120 what the library code likes to think in
00:09:31.120 uh it makes it easy to list every action
00:09:34.720 every interaction that i'm having with
00:09:36.320 my dependency because it's only in one
00:09:38.399 file in one class so i can just search
00:09:40.560 through that class for every instance of
00:09:42.560 my client and i can mock that
00:09:46.240 it also means that i can easily think in
00:09:48.640 the data structures that i want to think
00:09:50.480 in this is a sort of same thing but
00:09:52.399 different for
00:09:53.760 the
00:09:55.040 domain specific language except of
00:09:56.720 course it's about the data instead of
00:09:58.080 the functions right so instead of
00:09:59.600 thinking in the detect intent request i
00:10:01.200 can think in terms of a string and it
00:10:02.560 makes the rest of my code a lot simpler
00:10:06.560 uh so like i said
00:10:09.279 we get to write our own domain specific
00:10:10.959 language we get to clearly list every
00:10:12.959 action that the code performs we get to
00:10:14.880 easy that lets it makes it a lot easier
00:10:17.120 for us to mock our tests and then the
00:10:18.959 rest of our code gets to think how we
00:10:20.800 like to think instead of how the library
00:10:22.240 we're working with
00:10:24.000 any quick questions
00:10:27.040 blazing through my talk
00:10:29.200 all right object graph uh so this one's
00:10:31.279 a little wacky uh it's one of the harder
00:10:33.680 ones to think about because it's a
00:10:35.360 framework
00:10:36.480 not a core language thing so the spring
00:10:39.680 boot framework lets us do this wacky
00:10:42.000 thing where we can define components we
00:10:43.760 can define configurations and then what
00:10:45.839 the framework's going to do is it's
00:10:47.680 going to stitch these two together and
00:10:49.440 it is kind of rails-like in that sense
00:10:51.600 so what i've got here on the left is
00:10:52.959 i've got these functions that define the
00:10:54.800 various dependencies and on the right
00:10:57.040 yeah
00:10:57.920 i've got the place where those
00:10:59.120 dependencies get used and the spring
00:11:01.040 boot framework will actually take each
00:11:02.800 of those beans and it'll inject it into
00:11:06.079 the parameter list for that and just
00:11:08.320 call it uh it's kind of wacky to think
00:11:10.480 about and it turns into a graph
00:11:13.440 so theoretically
00:11:15.519 we could create some sort of auto wire
00:11:18.320 system using the new type system
00:11:21.279 because it is available at runtime we
00:11:23.680 can use any of our classic ruby
00:11:25.680 introspection tricks uh and of course
00:11:27.839 this is very similar to the rail style
00:11:29.920 naming conventions even if it is forking
00:11:31.920 off of a fundamentally different set of
00:11:33.839 operations
00:11:35.279 and what this really lets us do this is
00:11:37.360 the thing i'm a big fan of is separating
00:11:40.000 the what from the web so i've got one
00:11:42.880 place where i'm defining all of my
00:11:44.399 actions right in this case the wrapper
00:11:46.079 that's why i presented these two
00:11:47.200 together because they really work hand
00:11:48.560 in hand so each of my wrappers defines
00:11:50.720 the different things i might do with
00:11:52.480 this stuff
00:11:53.760 but
00:11:54.560 uh my top level code defines when all of
00:11:57.680 those things happen
00:12:00.079 similarly
00:12:01.360 i've now got a graph of how all my
00:12:03.440 pieces connect
00:12:04.800 of course drawing that graph with pencil
00:12:06.959 and paper might be challenging but
00:12:08.160 that's why we have code
00:12:10.959 uh so just to repeat
00:12:13.600 when we think in terms of an object
00:12:14.880 graph we're really thinking in terms of
00:12:16.399 separating what we're doing from when
00:12:18.639 we're doing it right you can think of a
00:12:20.079 graph with the nodes and little things
00:12:21.680 that step in
00:12:23.279 and then we've got one place or more
00:12:25.120 than one if you've got script code here
00:12:26.639 and there
00:12:27.519 where our top level code shows how
00:12:29.279 everything connects
00:12:32.000 so here's a real world example putting
00:12:34.240 everything together so this is a hobby
00:12:35.839 project by the way i highly recommend
00:12:37.519 hobby projects because it's the only
00:12:38.800 time you get to write perfect code and
00:12:40.240 once you know what perfect code looks
00:12:41.600 like
00:12:42.560 of course it's in the ibb holder once
00:12:44.000 you know what perfect code looks like
00:12:45.360 it's a lot easier to do it anywhere else
00:12:47.920 so this is a hobby project that connects
00:12:50.320 air table is a contact list transcribes
00:12:52.800 a conversation with a bot to slack and
00:12:54.880 of course it's a chat bot uh we can see
00:12:57.360 i'm using a bunch of the different
00:12:58.639 features in here
00:13:00.720 and all of this code is a lot easier to
00:13:02.639 read than trying to cram everything that
00:13:04.560 each of these steps does into
00:13:07.040 the endpoint handler right
00:13:09.839 uh yeah
00:13:12.399 so
00:13:14.480 what i told you we talked about carried
00:13:16.079 functions and how they let us slice up
00:13:18.320 computation steps in novel ways and i
00:13:20.560 really am a big fan of that thing that i
00:13:22.079 talked about where you slice out the
00:13:23.440 middle because usually it's pretty hard
00:13:25.279 to
00:13:26.079 pull apart your code when it's nested
00:13:28.399 like that because like how do you how do
00:13:29.839 you get the middle out well curried
00:13:31.360 functions is a great way to do that
00:13:33.360 companion objects which give us a lot of
00:13:35.200 inspiration for separating
00:13:37.360 our data and our state our actions and
00:13:39.440 our transformations
00:13:41.279 which is just i don't know it's an
00:13:42.800 easier way to think about to communicate
00:13:44.720 the code that we're working with
00:13:46.320 interfaces and all the advantages that
00:13:47.920 wrapping things uh gives us and beams
00:13:50.880 the separation of what and when
00:13:54.480 so we have a lot of time for q a
00:13:57.360 so
00:13:59.120 who's got questions
00:14:07.519 um
00:14:09.760 thanks this is uh interesting talk but
00:14:11.760 the thing that um i'm a little worried
00:14:13.440 about is it's not very idiomatic ruby uh
00:14:15.920 what you're showing up there um i think
00:14:18.079 you have a mix of ideas from different
00:14:19.440 languages
00:14:20.959 um but you can do a lot of things like
00:14:22.959 what you're saying in ruby
00:14:25.519 without all the complexity you have in
00:14:27.040 there for for instance on some of those
00:14:28.880 slides right you're using class
00:14:30.079 variables
00:14:31.839 which are really dangerous right because
00:14:33.519 if you get into inheritance right and
00:14:34.959 you have subclasses right if that
00:14:36.240 subclass changes that class variable
00:14:37.760 it's going to it's going to mutate the
00:14:39.120 variable in the superclass so there's a
00:14:41.279 lot of dangers in that code
00:14:43.199 yeah well so one of the things to note
00:14:45.040 is it's challenging to find toy examples
00:14:47.680 that will fit on a slide
00:14:50.320 okay that's that's fair
00:14:52.560 um
00:14:53.839 the other thing i was a little worried
00:14:54.959 about too is you're talking about how
00:14:57.360 you're trying to compose things right
00:14:58.639 using dependency injection
00:15:00.480 but in the classes that you're showing
00:15:02.079 in the code there
00:15:03.360 you don't actually inject anything
00:15:04.800 through the object itself so you have
00:15:06.079 like a class
00:15:07.519 and you have a method
00:15:09.199 and you're just putting methods within
00:15:10.639 the class but there's no state or any
00:15:12.959 kind of constructor that you're
00:15:13.920 constructing the object on and so in
00:15:15.680 object-oriented programming right you
00:15:17.120 want to have an object has a constructor
00:15:18.800 you inject your dependencies right and
00:15:20.240 you call those so
00:15:22.560 kind of feels like what you're asking
00:15:23.600 about is
00:15:25.120 how does this relate to
00:15:27.279 when we should do object-oriented versus
00:15:29.360 functional programming
00:15:31.360 and ironically or interestingly that's
00:15:33.360 one of my favorite interview questions
00:15:35.120 whenever i'm interviewing anybody
00:15:36.399 regardless of which side of the aisle
00:15:37.839 i'm on i will ask what is your
00:15:40.000 understanding of these two things and
00:15:41.120 when you should you use either so
00:15:42.959 interestingly uh
00:15:45.279 this top pattern which is actually just
00:15:47.120 the builder pattern right where i've got
00:15:48.560 the incoming message and i'm
00:15:49.600 constructing other things that's what
00:15:51.279 happened when i spent a while trying to
00:15:53.440 figure out how to use curried functions
00:15:56.079 in my project so that goes back to the
00:15:58.399 thinking that regardless of whether or
00:16:00.480 not we actually take the construct from
00:16:03.360 another language
00:16:04.880 the encouragement to think in this
00:16:06.880 different way can give us new insight
00:16:08.720 into how to write our own code
00:16:10.720 there's also a few places where
00:16:13.120 trying to apply one thing from one
00:16:15.199 language to ruby never resulted in a
00:16:17.519 useful pattern but did result in a
00:16:19.360 deeper insight for how ruby itself
00:16:21.680 functions and that sort of goes back to
00:16:23.680 the i know there's a number of talks
00:16:25.120 here that are about things you really
00:16:26.880 shouldn't do with ruby but you can and
00:16:30.240 again playing around with a language in
00:16:32.320 that way does a
00:16:33.839 huge benefit for your understanding of
00:16:36.880 the deeper ways that language works as
00:16:38.720 well as may yield some useful patterns
00:16:41.199 for how to organize your code
00:16:43.680 yeah that makes sense oh i asked one
00:16:45.279 more question i promise not to hug
00:16:47.279 the time
00:16:49.120 the one thing i want to ask you
00:16:50.720 have you looked at dry rb because some
00:16:52.639 of the functional set uh aspects that
00:16:54.720 you're trying to do here um is great i
00:16:57.040 like where you're going with this but
00:16:58.480 you might want to reach for dry rb
00:17:00.000 actually to give you some of that
00:17:01.839 like dependency injection uh being able
00:17:04.160 to have like a monadic pattern right so
00:17:05.760 you can have just a success or a result
00:17:07.280 type thing like
00:17:08.559 you're kind of scratching the surface
00:17:09.760 here uh but if you bring in dry rb you
00:17:11.679 would actually get a lot of super power
00:17:13.360 with that so what i'm hearing is
00:17:14.559 encouragement to check out dry.rb which
00:17:17.120 i haven't checked out before uh
00:17:19.439 one of the reasons why i've worked in a
00:17:20.720 lot of different languages is i keep
00:17:22.319 trying to work for ruby shops and not
00:17:24.079 succeeding
00:17:25.199 uh how has learning ruby affected you
00:17:27.679 the way you write other programming
00:17:28.960 languages
00:17:30.000 yeah thank you for asking that uh i had
00:17:32.480 a like a list of ten things
00:17:34.720 in the talk proposals when they said
00:17:36.000 pick three
00:17:37.600 uh but it turned out two of them were
00:17:39.120 linked uh so ruby i feel like
00:17:42.160 really what ruby taught me is the code
00:17:43.679 can be beautiful which is really sappy
00:17:45.919 but then what happens is i write code
00:17:47.760 that i'm really deeply unsatisfied with
00:17:49.440 like uh this is third or fourth rewrite
00:17:52.080 of the same code base and i kept being
00:17:53.840 unsatisfied with it because it didn't
00:17:55.600 feel beautiful and then once i got it to
00:17:58.160 the point that it was beautiful
00:17:59.919 everything made so much more sense and
00:18:02.000 so ruby kind of taught me on a deep
00:18:03.919 level that if it's not aesthetically
00:18:06.080 pleasing there's a better way to do it
00:18:07.600 and once i get to the better way i'm
00:18:08.799 like yeah yeah this makes way more sense
00:18:11.520 yeah i'm curious what are your
00:18:13.120 experiences um you know on a larger team
00:18:16.080 getting them on board with some of these
00:18:18.240 new patterns and really novel ways of
00:18:20.640 thinking through ruby or another code
00:18:23.360 yeah so
00:18:25.600 one of the big things that happens is
00:18:26.799 just people have inertia
00:18:28.400 and that inertia comes from
00:18:30.480 hey i've already got a plan for how i'm
00:18:31.919 doing this next step uh i've got
00:18:34.000 pressure from my manager to accomplish
00:18:35.919 this thing i've got pressure from
00:18:37.039 product on the timeline
00:18:38.720 uh so it generally ends up being more
00:18:40.720 like planting seeds that then come to
00:18:42.320 fruition later that said um this
00:18:45.280 particular bit the what from the when
00:18:47.520 so my current gig is i'm doing a lot of
00:18:49.679 support engineering and we have to do a
00:18:51.440 lot of fixing our systems when they
00:18:53.440 break so we've got a lot of utility
00:18:55.039 scripts and it was really useful and was
00:18:58.080 really easy to get a bunch of my more
00:19:00.240 junior programmers
00:19:02.320 on board and contributing to these tools
00:19:04.799 when i separated the library code from
00:19:07.120 the script code and then the script code
00:19:09.200 which is breaking all the time because
00:19:10.640 we're not the core engineering teams the
00:19:12.320 core engineering team changed the system
00:19:14.080 the script breaks but the script then
00:19:16.240 functions like documentation in fact the
00:19:18.799 first generations of the script were
00:19:20.320 literally taking the run books
00:19:22.640 and turning them into code
00:19:24.480 and so i took you know this step this
00:19:26.000 step this step and i define that step in
00:19:27.600 the library and then i put it in the
00:19:28.960 thing now you can just
00:19:30.480 read the code and say okay i got to do
00:19:32.640 this step then this step then this step
00:19:34.240 then this step
00:19:35.679 without having to get into the weeds or
00:19:37.760 getting distracted by the weeds of how
00:19:39.520 each of those steps are accomplished
00:19:41.679 so just by way of encouragement i've
00:19:44.000 done a lot of bad things for
00:19:45.200 reprogramming language over the years
00:19:47.039 you can probably find that all over the
00:19:48.320 place but a lot of the things that have
00:19:50.400 been done that you say these are
00:19:51.919 anti-patterns these don't make sense
00:19:53.760 eventually those ended up getting merged
00:19:55.280 language so by way of encouragement
00:19:57.280 please do experiment please do try new
00:19:59.440 things give those ruby bug tracker a lot
00:20:01.600 of times you'd be surprised in the
00:20:02.960 language i'll say it one time this is
00:20:04.799 all magic and then matt's merges it and
00:20:06.480 i had to recant my entire talk like i
00:20:08.159 don't have any magic anymore quit
00:20:09.440 stealing all my thunder here but
00:20:12.000 as far as functional patterns i'd be
00:20:13.840 very interested in this kind of my
00:20:15.600 question what you think of stuff like
00:20:17.440 raptors a lot of this isolate object
00:20:19.360 space and what that might kind of evolve
00:20:20.799 ruby into over the years to be honest i
00:20:23.280 don't really know what rector means the
00:20:24.720 word i kind of want to crack a joke
00:20:26.159 about monads and endo functors without
00:20:28.159 knowing what any of the words mean so
00:20:29.919 racter is ruby actor model kind of based
00:20:32.159 on erlang where you have isolate state
00:20:34.960 you can't really do anything with it and
00:20:37.360 there's a very real chance where we end
00:20:38.880 up going into deep functional land
00:20:40.400 because of that because there's no way
00:20:41.760 to use object-oriented kind of stateful
00:20:43.679 stuff in there
00:20:45.200 so my understanding is
00:20:47.440 basically one of the major advantages of
00:20:49.280 functional programming is the ease with
00:20:50.880 which it does concurrency because of its
00:20:53.120 restrictions on how you're modifying
00:20:55.039 state
00:20:56.000 um
00:20:56.960 and so
00:20:58.400 but also some of the the experience that
00:21:00.080 i've had trying to build larger
00:21:01.679 functional programming
00:21:03.840 projects
00:21:06.480 some things don't fit
00:21:08.640 into the functional programming
00:21:11.440 idiom
00:21:12.559 well and it can get really confusing
00:21:14.480 trying to think about certain things
00:21:16.400 when you're trying to wedge them into
00:21:17.760 that so that's where the diversity of
00:21:19.440 thought patterns i think really comes in
00:21:21.600 in handy
00:21:23.360 my brain's poking at me and saying go
00:21:24.880 back to the scala companion object with
00:21:26.720 that sort of novel combination of
00:21:29.760 i've got my pure functions but then i've
00:21:32.000 also got my data in my state
00:21:34.799 and how that interacts with the
00:21:36.559 distributed computing
00:21:38.480 so
00:21:39.520 hi there
00:21:40.480 i just have one question so being a
00:21:42.559 polyglot have you found another language
00:21:44.640 that's as ergonomic as ruby scala
00:21:48.880 it's the only one that feels like ruby
00:21:51.440 um
00:21:53.120 it's got a lot of
00:21:54.480 a lot of things that i i didn't realize
00:21:56.080 that i loved about ruby until i noticed
00:21:58.159 that they were also in scala like um one
00:22:00.880 of the novel things
00:22:02.960 the
00:22:04.159 code
00:22:05.200 like when you're in a class definition
00:22:07.600 the code that you're writing is the same
00:22:09.280 kind of code as the code that's inside
00:22:11.280 of a function definition
00:22:12.880 contrast that with like c plus when
00:22:14.960 they're very different kinds of code uh
00:22:17.200 and scala is one of the few other
00:22:18.480 languages that i've noticed i mean i
00:22:20.159 know java is the same way it's not java
00:22:22.640 javascript's the same way python's the
00:22:24.159 same way but scala is one of the other
00:22:25.520 languages that i've noticed that
00:22:28.240 is also the case and is actually used by
00:22:30.559 the community
00:22:32.720 um i'm new to ruby and one of the things
00:22:34.720 i've been very impressed by is pry
00:22:37.520 i was curious if you your thoughts on
00:22:40.960 like debugging and all these other
00:22:42.799 languages and how they compare
00:22:44.720 to movie
00:22:46.960 yeah uh
00:22:48.720 compiling languages do have a bit of a
00:22:50.960 advantage with your debugging tools
00:22:55.520 but
00:22:57.280 then you don't get things like your
00:22:59.280 rebel console
00:23:00.559 so one of the
00:23:01.760 one of the things that i like about some
00:23:02.799 of the patterns that i've used here is
00:23:05.679 when i want to debug what i generally
00:23:07.520 find myself doing is rather than putting
00:23:09.440 in like a price statement somewhere in
00:23:11.120 my codebase
00:23:12.400 i'll actually
00:23:13.760 use the code to set up an environment
00:23:15.600 and just play around with the grapple
00:23:16.799 console
00:23:20.240 in terms of i mean so like javascript
00:23:23.919 all the scripting languages kind of have
00:23:25.280 the same kind of tooling for their
00:23:27.919 debuggers you'll stick some statement in
00:23:29.919 somewhere that drops you into rebel
00:23:31.200 console in your local uh scope
00:23:33.679 uh and then all the kapow languages have
00:23:36.240 something that's a more formalized set
00:23:37.679 of tools for debugger where you can put
00:23:40.000 in the the breakpoint statements and the
00:23:41.840 like uh and then of course they they
00:23:44.159 cross
00:23:45.600 so there are there's tooling in
00:23:48.880 scripting languages that lets you drop
00:23:50.320 in break points and then in recent years
00:23:53.919 uh particularly with the advent of
00:23:55.919 jupiter notebooks people have started
00:23:57.840 adding in rapple consoles so you can do
00:24:00.559 c plus from
00:24:02.799 the same sort of thing as irb
00:24:05.279 uh instead of having to compile your
00:24:07.279 whole thing you can write a chunk of
00:24:08.720 code compile and link it write a chunk
00:24:10.720 of code compile and link it well um we
00:24:13.120 can call it there
00:24:16.720 thank you for coming to my talk