Summarized using AI

Let's write an esoteric language in Ruby!

Thomas E Enebo • November 13, 2024 • Chicago, IL • Talk

In this talk at RubyConf 2024, Thomas Enebo dives into the intriguing world of esoteric programming languages, specifically focusing on creating a Ruby implementation of the image-based language Piet. The session explores the definition and features of Piet, an unconventional language that represents programs as images.

Key Points Discussed:
- Introduction to Esoteric Languages:
- An esoteric programming language is characterized by being difficult to understand or use, often viewed as weird compared to traditional languages.

  • Overview of Piet:

    • Piet allows programming through an image, with execution starting in the upper left corner and moving based on color transitions identified through a coordinate system.
    • Programs in Piet are visually represented in colors (six colors and three shades) that dictate operations and how a program flows.
  • Initial Implementation:

    • Enebo presents his initial naive port of Piet, dubbed Rpiet, from Python to Ruby, highlighting challenges such as the absence of tests leading to potential mistakes.
  • Graphical Debugger:

    • A graphical debugger was developed to visualize and troubleshoot the interpretation process of Piet, which supports developing an understanding of how the programs flow.
  • Optimizing the Implementation:

    • Techniques like converting the interpreter to a graph-based implementation are discussed, enabling improved execution speed. The original interpreter was improved significantly, showcasing optimized parsing of the Piet structure into executable instructions.
  • Transpilation to Ruby:

    • Further improvements included converting the graph of instructions directly into Ruby code, which eliminated interpreter overhead and increased speed significantly, achieving a performance boost of over 70 times.

Examples Presented:
- Example Programs in P:
- Simple programs like a cow saying input text and a program that computes the value of Pi were demonstrated, showcasing Piet's capabilities in a fun and engaging manner.

Conclusions and Takeaways:
- Exploring different programming languages, especially esoteric ones, can provide valuable insights into programming concepts and paradigms.
- The process of developing the interpreter illustrated the importance of robust debugging tools and optimization methodologies in programming.
- Enebo encourages programmers to experiment and learn from challenging languages as they can lead to innovative development techniques and approaches.

As a unique instance in programming, Piet serves as a reminder of the creativity and exploration possible in software development, pushing the boundaries of traditional programming paradigms.

In summary, learning about and implementing esoteric languages like Piet not only broadens understanding but also enhances practical programming skills in more established languages like Ruby.

Let's write an esoteric language in Ruby!
Thomas E Enebo • November 13, 2024 • Chicago, IL • Talk

Ever wondered if some programming languages are weird by design? Welcome to the wild and wacky world of esoteric programming languages! The main focus of this talk will be to create a Ruby implementation of the image-based (gif/png/jpeg) language Piet. Can you imagine your source code as a picture of a cow?

Rpiet starts as a naive port of one of the other language implementations of Piet. From there, we consider what is special about this language versus traditional programming languages. We then distill our initial implementation into a lean and mean version which verges on ROFLScale. It even includes a working graphical debugger!

RubyConf 2024

00:00:15.360 okay um thanks for
00:00:17.840 coming my name's Tom anabo I'm normally
00:00:20.640 known as Tom and not Thomas but I always
00:00:22.680 feel I need to be formal um as Sarah
00:00:26.119 said I'm J molad and I'll also point out
00:00:29.519 that uh Charlie and I are doing a j Ruby
00:00:32.960 talk after lunch I don't have the
00:00:35.320 details on the screen but I should have
00:00:37.320 put that there uh I've been using Ruby
00:00:39.840 and Java a very long time I'm also kind
00:00:42.600 of a fan of rust now and if you're an
00:00:46.440 employer looking to hire me um I'm
00:00:49.920 looking for a job so there's my LinkedIn
00:00:53.719 link all right so what's an esoteric
00:00:56.120 programming language Wikipedia has a lot
00:00:58.920 to say but we're not going to read that
00:01:02.320 all right I'm going to break it down to
00:01:03.800 two sentences it's a programming
00:01:05.840 language that's typically hard to use or
00:01:08.960 understand and you're going to consider
00:01:11.600 the language weird in comparison to a
00:01:13.840 traditional programming
00:01:17.520 language the language we're going to be
00:01:19.439 looking at today is
00:01:21.280 p it's known it's named after this guy
00:01:25.119 uh there's one of his more famous pieces
00:01:28.040 on the right he unfortunately um didn't
00:01:32.479 have a great fashion sense later in life
00:01:36.119 uh so we'll remember him by this photo
00:01:39.399 he's pretty cool he's somewhere between
00:01:42.360 George Clinton and time traveling
00:01:45.040 hipster and if you want to go and waste
00:01:47.960 five or 10 minutes of your life but be
00:01:50.079 somewhat entertained look up time
00:01:52.079 traveling
00:01:53.360 hipster narrator he's not a time
00:01:58.159 traveler so uh
00:02:00.360 P it's an image-based language just like
00:02:02.399 small
00:02:03.759 talk well no not really it's literally
00:02:06.799 an image so uh if you run P it on this
00:02:10.720 image it's going to display P it to the
00:02:15.040 screen it's also a funge Fung is just
00:02:17.920 languages that involve coordinate
00:02:22.120 systems it's stack
00:02:26.959 based uh the unit the primary unit of
00:02:30.800 things is a codal this is a n byn set of
00:02:34.120 pixels this one is 10
00:02:38.519 by1 uh adjacent colas are made into
00:02:41.840 groups so in the upper Le hand corner we
00:02:44.239 have a 3X3
00:02:50.319 group there's a direction pointer this
00:02:52.800 indicates the flow of the program as it
00:02:55.319 moves through the image uh it's all P
00:02:59.120 programs start by by executing in the
00:03:00.519 upper left hand corner of the image and
00:03:03.080 it uh is set to right
00:03:08.400 initially uh there's another concept
00:03:10.640 called a codal Chooser where it's either
00:03:14.040 set to left or
00:03:15.560 right and so the navigation is the
00:03:18.879 direction pointer will move through a
00:03:20.640 group and try to enter the next group
00:03:23.319 and at the most extreme Edge the codal
00:03:25.519 Chooser will say should I go at the left
00:03:28.560 side or the right side of the that
00:03:32.200 edge so uh here's Just A visual
00:03:35.680 representation if the direction pointer
00:03:37.640 is right and the col choosers left we're
00:03:40.040 going to go from the blue to the dark
00:03:41.840 blue square or
00:03:44.840 group at
00:03:46.599 a but if the Cal choosers is right we're
00:03:49.760 just going to go in at B it's pretty
00:03:52.599 simple okay harder
00:03:56.239 example if the direction pointer is
00:03:58.239 right and the C choosers is left
00:04:00.720 uh we're going to go and enter into this
00:04:02.720 green group but had it been right it's
00:04:06.120 going to go into this dark blue
00:04:09.959 group uh P programs have six different
00:04:13.000 colors and each of those colors have
00:04:15.200 three different shades light normal and
00:04:19.759 dark and when you transition from one
00:04:22.919 group to the next group you go and
00:04:25.080 reference this table to figure out what
00:04:26.759 operation to
00:04:28.560 perform uh we have some stack
00:04:31.720 operations we have
00:04:34.080 math
00:04:36.680 inequalities input and
00:04:38.840 output and then we have two Special
00:04:41.320 Operations one is pointer which allows
00:04:44.240 you to programmatically change the
00:04:45.759 direction pointer and switches the same
00:04:48.360 thing for the codal
00:04:51.520 Chooser so when I say one shade darker
00:04:54.160 and this is how it's written in the pet
00:04:55.919 speec uh it makes sense that light blue
00:04:58.800 to Blue is one shade darker and blue to
00:05:02.639 dark blue is one shade but it also is
00:05:05.199 that a dark blue to light blue is one
00:05:06.720 shade darker so don't get too hung up on
00:05:10.360 the word it's just a
00:05:14.880 circle similarly for uh Hue changes
00:05:19.639 again it's just a circle all these are
00:05:21.960 examples of the Divide operation um but
00:05:25.560 if you go to Red you just go around the
00:05:27.000 circle too and that's it that's green
00:05:31.440 okay so now we're just going to go
00:05:32.520 through a program to get an
00:05:34.840 idea of uh how it works in practice so
00:05:38.720 as I said we start in the upper leftand
00:05:41.000 corner because the direction pointers
00:05:43.319 and the direction pointer is Right C
00:05:45.000 choos is left so we enter into the dark
00:05:47.880 blue uh group at that upper point where
00:05:51.319 the arrow
00:05:52.360 is and we look it up oh it's one shade
00:05:55.160 darker so we're going to do a push and
00:05:57.720 we're going to end up pushing nine
00:05:59.199 because
00:06:00.280 we use the size of the group that we're
00:06:02.479 leaving as the value to
00:06:07.360 push okay so now at step two we run into
00:06:10.280 black it's not one of the six colors
00:06:12.720 it's an impassible color in fact if you
00:06:16.360 actually exit off the side of the image
00:06:18.639 it's equivalent to running into black so
00:06:20.440 you can just kind of pretend to all pit
00:06:23.240 programs are just lined with a black
00:06:26.319 border and so when this happens you do
00:06:29.280 this
00:06:30.800 algorithm so for up to eight times you
00:06:33.440 flip between the codal Chooser and you
00:06:36.000 just rotate the direction pointer
00:06:37.880 clockwise and try to find another place
00:06:40.120 to
00:06:41.680 go um if you can find it in eight moves
00:06:44.880 that's how a p program
00:06:48.080 terminates okay so Cal choos it goes
00:06:50.120 from left to right and we move in and
00:06:53.039 We're Off to the Races we're still
00:06:56.639 executing okay uh we'll go to the next
00:06:59.240 special
00:07:00.280 thing we're now in this uh little
00:07:02.879 L-shaped green group and uh we're moving
00:07:06.720 down and I promise you that is white it
00:07:11.440 does not look white but for the sake of
00:07:13.440 this talk it is really
00:07:15.400 white um in the case of white though you
00:07:17.879 just kind of slide through to the next
00:07:21.599 thing all right so that's the basic
00:07:24.960 rules of
00:07:26.120 PE and I'm sure everyone's going to run
00:07:28.440 off and make their own program
00:07:30.960 if you want to run them you can go and
00:07:32.879 install R pit this is my implementation
00:07:35.160 of the pit language it will run in C
00:07:38.039 Ruby or J Ruby but if you want to use
00:07:40.960 the uh graphical
00:07:43.280 debugger then you have to use J Ruby and
00:07:46.159 that's using a j j Ruby Library called
00:07:49.120 Java FX which is pretty
00:07:52.560 sweet okay so a few example programs to
00:07:55.240 kind of wet the appetite for writing
00:07:56.800 your own P programs the first one is cow
00:08:00.159 say I am just executing this off the
00:08:04.520 internet and when you run it uh it
00:08:07.240 prompts you for some text and then the
00:08:10.319 cow goes and repeats it it's pretty
00:08:14.159 cute this one's kind of mind-blowing
00:08:17.080 someone figured out how to go and uh
00:08:20.080 make two programs in one image by
00:08:22.479 changing the codal size so it just
00:08:24.840 prints two different things
00:08:30.720 this is my favorite um as I say you
00:08:34.000 enter a p program by going to the upper
00:08:35.839 lefthand corner the first thing you hit
00:08:37.320 is this red line which is half the
00:08:41.399 image's size so you push that onto the
00:08:43.800 stack then you go and find the circle
00:08:46.680 and you push that and that's the area of
00:08:48.480 the
00:08:49.160 circle area
00:08:51.160 over R 2 right and you get this perfect
00:08:54.800 Pi
00:08:56.320 number so I should I should point out
00:08:59.160 that
00:09:00.279 there are no floating point in P so
00:09:03.440 pretend there's a period there um but
00:09:06.079 this is actually a better approximation
00:09:07.839 than at least one States legal
00:09:09.800 definition of Pi so there's
00:09:14.680 that okay so now I'm done talking about
00:09:17.040 P at the language I'm going to talk
00:09:18.640 about
00:09:21.079 um implementing it
00:09:23.839 myself I just ported it from
00:09:28.120 python yeah so uh porting is hard uh
00:09:32.519 Python and Ruby are not identical
00:09:33.959 languages so there's different
00:09:36.360 idms porting code you make lots of like
00:09:39.040 stupid mistakes where you just do the
00:09:40.959 wrong thing and there were no tests I
00:09:43.320 say few tests but there were none
00:09:47.079 so what you do is you generate a
00:09:49.959 debugging uh output that's similar to
00:09:52.000 another P implementation figure out
00:09:54.440 what's wrong and then and then fix it I
00:09:57.120 was comparing against npit which is
00:10:00.200 kind of the the best P implementation at
00:10:03.480 least for
00:10:05.760 now okay so I I made a graphical
00:10:08.399 debugger so let's take a look at
00:10:10.920 that all right so I'm going to start by
00:10:13.480 hitting step oh wait I got to start it
00:10:16.000 though all
00:10:17.320 right so I hit step once I hit step
00:10:20.839 again now I'm going to go and set a
00:10:24.839 breakpoint then I'll resume it gets
00:10:27.800 there pretty quickly then I look at the
00:10:30.040 stack yeah that's what I expected then I
00:10:32.920 keep running
00:10:35.120 it you can see it bouncing
00:10:38.399 around so uh the fun thing about this
00:10:41.079 video is it gives you the illustration
00:10:42.920 of that that I'm going to try to move
00:10:45.600 stuff eight times and then terminate so
00:10:47.959 if you look at that green upside down T
00:10:50.320 it's surrounded by black and so it did
00:10:53.480 the eight different changes and then
00:10:55.279 said I'm out of here
00:11:01.079 okay so I quite literally ported The
00:11:04.040 Interpreter I don't expect you to read
00:11:06.360 that um or I'm not sure if you can even
00:11:08.639 read it um but it's almost all in one
00:11:12.360 method it's kind of what I call code
00:11:14.760 shouter there's just way too much stuff
00:11:16.600 in a
00:11:17.839 method
00:11:20.160 so it has a mixture of concerns it's
00:11:23.360 continuously reparsing and changing that
00:11:26.880 direction pointer and Cal Chooser uh
00:11:30.920 and that's
00:11:32.600 invariant logic so we need to fix that
00:11:37.440 uh like the shortlived mcdlt we have to
00:11:39.920 keep the hot side hot and the cold side
00:11:42.519 cold does anyone remember
00:11:45.959 mcdlt all right all right we got a few
00:11:48.320 people I thought you know sometimes they
00:11:50.880 put this stuff in for me
00:11:55.160 so um but in all programming languages
00:11:59.279 you translate the text of your language
00:12:01.160 I shouldn't say all nearly all languages
00:12:03.279 you translate the text into a data
00:12:05.440 structure it's almost universally uh an
00:12:08.519 abstract syntax tree so here's a snippet
00:12:11.560 of Ruby uh when this gets parsed it'll
00:12:14.519 construct a wild node and then there'll
00:12:17.480 be a Boolean node for the test and then
00:12:19.480 there will be a call node with the puts
00:12:21.079 in it and so forth now most languages
00:12:24.360 and matz even mentioned this in his
00:12:25.839 keynote this morning uh the interpreter
00:12:29.600 that you make will actually be attached
00:12:31.079 to this tree so every one of these nodes
00:12:33.279 will have their own execute method so
00:12:35.800 when you're actually execute a while
00:12:38.040 node you'll just call execute on the
00:12:39.639 wild node it'll do the test it'll
00:12:41.800 execute the body and so
00:12:43.920 forth so that's what we're going to do
00:12:46.240 now and and RP
00:12:48.160 it but uh it has all sorts of weird
00:12:52.279 abilities to like fold back in on itself
00:12:55.199 so we can't really do a tree so we're
00:12:57.760 going to make an abstract syntax group
00:12:59.199 graph
00:13:00.720 instead every note is going to be the
00:13:03.399 operation we perform so if you
00:13:05.720 remember in the early examples where we
00:13:08.120 went from Blue to dark blue it was a
00:13:09.920 push so we' create a push node and
00:13:14.160 pretty much every operation that was in
00:13:16.199 that table will become its own
00:13:18.160 node uh we have to create some new nodes
00:13:21.079 to keep track of when the direction
00:13:22.480 pointer and coer changes so that'll go
00:13:25.360 into the graph as
00:13:27.880 well and then and then the algorithm is
00:13:30.120 we're going to just strip out the
00:13:31.320 execution from the original code shouter
00:13:33.920 and make it into a
00:13:35.360 visitor and for every possible
00:13:37.519 transition from one group to the next
00:13:39.199 group we're going to add it to a work
00:13:40.880 list so uh for the pointer
00:13:44.160 operation that can potentially go four
00:13:46.720 different transitions so we just add
00:13:48.360 them in there and we just process this
00:13:50.519 thing until we have a complete
00:13:55.000 graph and now here's what the graph
00:13:57.440 interpreter looks like uh we start at
00:13:59.279 the entry part of the graph and then
00:14:02.320 I'll just bring the push up again for
00:14:04.480 that example program the first thing we
00:14:06.160 had execute is is push and then when it
00:14:09.480 finishes it Returns the next node to
00:14:11.639 execute and if it returns nil program's
00:14:15.000 done
00:14:17.079 simple ah okay
00:14:19.440 so uh The Benchmark for the rest of this
00:14:22.199 is going to be a prime number
00:14:24.079 detector when you run at a prompts for a
00:14:26.360 number and it tells you whether it's a
00:14:27.680 prime or not and it's got a nice little
00:14:29.880 face on
00:14:32.279 it and I couldn't think of a number to
00:14:34.519 use so I'm going back I'm going way back
00:14:38.360 uh
00:14:39.680 8675309 does anyone use this number
00:14:42.480 whenever you have to do a fake phone
00:14:44.480 number okay more people than knew the
00:14:46.800 mcdlt reference that's good uh this is
00:14:50.120 from the song Jenny it's her phone
00:14:52.519 number and it's forever etched in my
00:14:57.480 brain Okay so when I run the original
00:15:00.320 interpreter it takes about 147 seconds
00:15:02.959 and now with the new graph interpreter
00:15:05.279 it doubled in speed effectively getting
00:15:08.000 rid of that constantly reparsing the
00:15:09.959 image to navigate is a pretty good
00:15:13.240 payback so
00:15:14.880 good but we want to make it faster now
00:15:17.680 so let's get away from the abstra syntax
00:15:20.240 graph and go to a list of
00:15:23.440 instructions and these list of
00:15:25.279 instructions will mostly be the same
00:15:27.040 that the operations in the original
00:15:29.720 table but because we have these weird
00:15:33.120 jumps and flow control changes we need
00:15:35.240 to actually add branches and
00:15:38.639 jumps uh and so now what we're getting
00:15:41.160 to at this point is we're going to
00:15:43.399 convert this graph into a single
00:15:45.519 sequence of text with instructions so
00:15:49.160 I'm effectively making a simple
00:15:51.440 programming
00:15:55.000 language uh here's a translation from uh
00:15:58.800 the dupe operation in the graph where we
00:16:02.399 just take the top element of the stack
00:16:04.319 and duplicate it and now for uh the new
00:16:09.399 IR instructions I'm going to actually
00:16:11.000 make three instructions where I pop the
00:16:13.920 top element and I just push it
00:16:15.920 twice for
00:16:18.920 reasons and so now we end up with a
00:16:21.079 single list of instructions and this is
00:16:22.959 pretty easy to read and it's a lot
00:16:24.680 easier than reading a gif image so if we
00:16:28.440 look at the GRE green underline here uh
00:16:31.399 jump to test end towards the bottom what
00:16:34.480 that will do is it'll look for the label
00:16:36.319 test to end and execute that instruction
00:16:42.240 next and if we look at our new
00:16:44.360 interpreter uh we now have this
00:16:46.360 instructions list that's indexed with
00:16:49.240 this program
00:16:50.680 counter and it gets the instruction it
00:16:53.720 executes it and if flow control changes
00:16:57.360 it uh return something that we can then
00:17:00.519 use to look up in a jump table for the
00:17:02.800 next index that we should execute from
00:17:05.880 and if not it Just increments the
00:17:07.480 program counter and does the next
00:17:11.559 instruction uh
00:17:14.240 oh well I did actually add more
00:17:17.439 instructions than their originally nodes
00:17:19.520 so I think this is sort of to be
00:17:21.720 expected and I'm actually trying to
00:17:24.199 massage this in a way where I can
00:17:26.559 do common well-known optimization ations
00:17:29.919 uh things that if youd taken a
00:17:31.840 compiler's class uh you would have it in
00:17:34.880 your textbook or you look up on
00:17:38.400 Wikipedia uh
00:17:40.400 and I did the dupe thing for a reason
00:17:43.799 for the first
00:17:45.480 optimization which is to do a simple
00:17:47.600 pull
00:17:48.679 optimization so with the pull
00:17:52.280 optimizations you take one set of
00:17:54.440 instructions and you look for a pattern
00:17:57.120 that makes it better generally faster in
00:18:01.000 this case I'm using a very specific one
00:18:03.240 uh if you see a push followed by a pop
00:18:05.720 you can eliminate both of those and just
00:18:08.240 make it into an
00:18:11.880 assignment and uh you can see here if
00:18:15.320 there's multiple of them it's almost
00:18:16.919 kind of like
00:18:17.840 a Russian nesting doll where the push
00:18:22.320 one V1 equals pop will just become an
00:18:25.679 assignment but then once you do that
00:18:27.320 then you can all already see that but
00:18:29.120 you can do it again for push two and
00:18:32.240 V2 and so now if you can imagine that
00:18:35.679 the next instruction after this is going
00:18:37.240 to be an arithmetic
00:18:39.559 operation uh we can do another
00:18:41.400 optimization called constant propagation
00:18:44.120 where we can just get rid of V1 and V2
00:18:47.159 and make that math 1 plus
00:18:49.120 two and now you're looking at that and
00:18:51.280 you're thinking H why would I do 1 plus
00:18:54.440 two I can just constant fold that into a
00:18:57.480 single assignment because I know 1 plus
00:18:59.840 2 equals
00:19:03.400 3 and all these optimizations keep
00:19:05.919 stacking on each other and luckily P
00:19:09.280 uses tons of pushes and
00:19:11.200 Pops so I was able to reduce the number
00:19:13.880 of instructions from 197 down to
00:19:17.120 76 now it's four time four and a half
00:19:19.559 times faster than the original it's more
00:19:22.120 than twice as fast as the graph
00:19:23.640 interpreter
00:19:25.120 so hooray me
00:19:31.080 anyone remember Slap
00:19:32.880 Chop okay that's more
00:19:35.919 modern all right so the last thing that
00:19:38.280 I'm going to do is I'm going to try to
00:19:39.440 get rid of most of The Interpreter
00:19:41.480 overhead uh as I said we're constantly
00:19:45.640 accessing stuff out of an
00:19:47.520 array uh we're incrementing this program
00:19:51.559 counter and recalling execute I mean
00:19:54.679 what we're doing here is
00:19:56.679 we're simulating a machine
00:20:00.000 and that's not very
00:20:02.679 fast and we're going to solve this by
00:20:04.840 transpiling to
00:20:06.520 Ruby uh we still unfortunately because
00:20:09.000 of the complexity of the language have
00:20:10.559 branches and jumps so we will still have
00:20:13.679 to emulate the machine a little bit but
00:20:16.960 everything else can just become
00:20:18.640 transpiled lines of Ruby and then we get
00:20:21.159 rid of the overhead of
00:20:24.120 that so I don't expect anyone to read
00:20:27.120 that at all um but for the both the
00:20:30.880 optimizations and for uh this
00:20:34.360 transpiling I made a control flow graph
00:20:37.080 the important thing here is you can see
00:20:38.799 all these little lines pointing between
00:20:40.679 boxes this is all the places where flow
00:20:44.559 changes and if we zoom in a little bit
00:20:47.080 on one uh I gave each one a somewhat
00:20:51.440 random name I think that 4012 is its
00:20:54.480 object
00:20:55.520 ID but um if we look at how we trans
00:20:58.960 pilot uh V1 equals NN for numeric
00:21:04.240 input uh we just print out prompting for
00:21:06.960 the number and then we get it from the
00:21:09.039 io and convert it to an integer the
00:21:11.600 pushes are pretty obvious what's
00:21:13.039 happening here and then the very last
00:21:15.679 line is the next method that we have to
00:21:19.840 execute so now if we look at this
00:21:21.919 version of The Interpreter uh we're
00:21:24.720 basically just sending to all these
00:21:26.159 generated
00:21:27.360 methods and and they just uh um return
00:21:30.640 the next method to
00:21:31.960 execute so some people might be
00:21:35.559 wondering why don't you just call re 404
00:21:39.600 in this method instead of returning it
00:21:42.000 and it's because we don't have an
00:21:44.039 infinite stack in Ruby but that would
00:21:46.480 have been way faster if that would have
00:21:48.159 worked and probably would have worked
00:21:49.960 for a small number of P programs
00:21:53.120 but uh this was kind of an unexpected
00:21:56.000 thing for me uh once I they started
00:21:59.080 transpiling into Ruby I started getting
00:22:00.679 all these ideas and like duh I've been
00:22:04.279 using Ruby for a couple decades I know
00:22:06.559 Ruby really well and uh I also got to
00:22:09.760 use profiler and I was
00:22:11.799 like really surprised that something I
00:22:14.200 thought was fast wasn't fast so this
00:22:17.480 this was an unexpected joy in
00:22:20.360 this okay so now when I did that now
00:22:23.679 it's 70 times faster there's other
00:22:26.400 things that I could have done but I
00:22:27.880 already spent way way too much time
00:22:30.960 doing this
00:22:33.279 so I'm gonna declare Victory right
00:22:37.799 here uh but I want to do uh a couple of
00:22:41.600 conclusions uh the first one is I think
00:22:44.480 it's really important to study different
00:22:46.760 languages so if you're someone who's
00:22:49.640 learning a language and you decide to
00:22:51.240 use a language that isn't very different
00:22:52.720 from yours you're not going to get a lot
00:22:55.080 of insights so I recommend like learning
00:22:59.080 a radically different language I'm not
00:23:01.039 saying you should learn pit although you
00:23:02.960 all know pit now but um you know learn
00:23:07.159 something like prologue prologue is a
00:23:09.240 declarative logic based language it was
00:23:11.880 pretty transformative to me in college
00:23:14.400 when I learned it because I thought
00:23:16.240 everything was going to be like Pascal
00:23:17.960 or
00:23:19.080 C Pascal might date me a little bit but
00:23:22.360 um but yeah get away from something
00:23:24.480 familiar and don't even don't even spend
00:23:27.480 a ton of time on it just spend a few
00:23:29.120 days on it just get some appreciation
00:23:30.880 that there's different ways of doing
00:23:32.400 things I think as time goes on all the
00:23:35.039 programming languages are starting to
00:23:36.200 look more and more
00:23:38.840 alike uh I think this is a pretty good
00:23:41.440 example that uh when you're an uncertain
00:23:44.799 ground you just need to translate what
00:23:46.679 you're doing into something
00:23:48.440 familiar once I
00:23:50.520 actually made the abstract syntax graph
00:23:53.640 then I'm like well naturally I can make
00:23:55.320 this into instructions and then once I
00:23:57.039 made it into instructions there's just
00:23:58.760 tons of things I could do but when I was
00:24:00.880 looking at that original interpreter I'm
00:24:03.240 like there was I had no ideas on how to
00:24:05.960 improve it if I would have made it nice
00:24:08.240 and clean it would have ran way slower
00:24:11.600 so Ruby and rails we have tons of tools
00:24:16.000 so this this
00:24:17.520 isn't as applicable but P had no tools
00:24:21.720 for me so I had to make
00:24:23.440 everything so graph fiz was the most
00:24:25.919 useful thing that control flow graph
00:24:28.159 that I showed I was constantly looking
00:24:30.480 at those seeing how my results had
00:24:32.360 changed and that was super useful had I
00:24:35.120 not had that tool I would have been
00:24:37.000 pretty lost the graphical debugger I
00:24:41.399 made it was a total waste of time but I
00:24:45.960 had a lot of fun writing it so you know
00:24:49.039 take what you can get right I had to
00:24:51.480 make an assembler for the IR so I could
00:24:53.360 actually test
00:24:54.880 it I made an asky image format so that I
00:24:57.880 could actually use a text editor to make
00:24:59.559 my my P programs because who wants to
00:25:02.640 use paint or you know some program like
00:25:06.679 that uh but there were many others and
00:25:10.399 the last and possibly uh best thing to
00:25:14.200 know is 8675309 is not just a phone
00:25:17.799 number it's also a prime
00:25:23.240 number so thank you
00:25:33.799 again looking for
00:25:35.559 work and uh I think I have like four
00:25:39.320 minutes for
00:25:42.279 questions if anyone wants to ask
00:25:44.399 questions I'll answer can p do anything
00:25:47.480 like change the colors of the of the
00:25:49.919 program now there are a bunch of people
00:25:52.760 who have extended p in weird ways
00:25:55.080 they've added more colors so they could
00:25:56.480 add more operations I I think someone
00:25:58.919 made like uh some TCP server
00:26:03.520 somehow
00:26:05.480 so I wouldn't be surprised if someone
00:26:07.760 made a self-modifying program so that
00:26:10.480 would be like the ultimate and lispy
00:26:13.039 right data is the code but I'm not aware
00:26:17.320 of that
00:26:19.799 specifically can QR codes be P programs
00:26:24.320 well it's not one of the six colors that
00:26:26.760 do anything so you could do something
00:26:30.360 with it but it would just instantly
00:26:32.360 terminate cuz if it's black and white
00:26:36.000 it'll make well let's just pretend that
00:26:38.600 the there's no border it would just move
00:26:41.320 around the white do the eight thing and
00:26:42.720 then eventually stop might run a very
00:26:44.960 long it might run
00:26:46.240 infinitely because oh no it's gonna it's
00:26:48.720 gonna
00:26:49.520 stop because white just slides through
00:26:51.640 and Black's gonna go nope it's going to
00:26:53.760 rotate yeah
00:26:57.240 yep man we could really go places with P
00:27:04.559 it there should be and another problem I
00:27:08.480 ran into with pet as an implementation
00:27:10.760 is there's
00:27:12.240 like 20 P programs on the planet and and
00:27:17.200 about eight of them don't do it
00:27:19.600 right there there was a rata and then
00:27:22.000 they updated the pet
00:27:23.960 speec for something where there's 20
00:27:26.120 programs on the planet and uh um so half
00:27:30.320 the programs don't
00:27:32.000 work and and if you use npit which is
00:27:35.679 the implementation I was talking about
00:27:37.279 earlier they actually have a flag to
00:27:39.399 specify I wanted to use 1.1 of pit so
00:27:43.279 yeah there's there's at least three
00:27:45.039 different versions of P
00:27:46.880 now okay well thank you thank you Tom
Explore all talks recorded at RubyConf 2024
+64