God Created Integers Pdf

0 views
Skip to first unread message

Jacinto Man

unread,
Aug 5, 2024, 10:34:56 AM8/5/24
to usalbuffolk
Im a student and have been attempting to create a program in JavaScript to create a function and generate a random integer (whole number) between 1 and 9. I have created two different programs for this in my testing but while using Visual Studio Code it doesn't print the generated number.

I found out that the first snippet will end up giving a number between 1 and 9 which is the exact thing you wanted but the problem is that you are not calling the function itself. So this should help.


As others have already pointed out, you need to be outputting your result somewhere, no? Online scripting environments have spoiled us a bit in recent years, but when you're doing thins locally, never assume your build assumes implicit return.


@mwielen @Johnny

I saw your questions when I was researching this topic, and I thought I would add some color, and mention why I believe that auto-incremented generated columns will also not work as a substitute for an idempotent surrogate key:


I suspect that is because the human act of creating a table is time-consuming SQL to write and execute, so naturally the idea that we would drop and re-create a table for any reason whatsoever is hard to embrace as a task we would humanly want to manage, and also likely feels familiar in larger organizations where a dbadmin often had to get involved to create a new table.


The answer is that you want to be able to put a human-readable identifier for rows in the BI tool if possible (maybe there is an account ID that is an integer created at the source for example), but behind the scenes, every row has a unique and idempotent surrogate key that joins and other functions are performed against, and that follows that fact or dim throughout the data journey.


Before Databricks introduced generated IDs I did have a work around for this that involved using row_number that worked ok. I may try and rework that to work with dbt and will report back if I have any success.


I've learned enough now to start working on the "ElixirLargeSort" project. This project is a fun exercise in sorting a very large number of integers while keeping only a subset of integers in memory at any particular time, and I've been using it as a way to practice or improve my skills in various programming languages.


I originally saw this listed somewhere as an interview question: "How do you sort a large number of integers without being able to load all of them into memory at once?" I quickly realized that the solution would be to sort chunks of integers and write them to files. Then I would merge multiple sorted integer files in to a single sorted integer file, solving the problem without ever having them all in memory at once.


I was learning Node.js at the time, so I wanted to go and implement the solution in Node.js to get some experience using it. The Node.js project is called NodeLargeSort, which is on my GitHub page. It also uses Bacon.js, a functional reactive programming library that is very much like working with streams in Elixir.


Later on I implemented the solution in C# in the LargeSortCSharp project, also on my Github page. I already knew C# really well, but I thought it would be interesting to get to know .NET Core better, so I implemented the soution using .NET Core 2.1. It was an interesting exercise and I was able to compare it to the Node.js solution.


Now it's time to implement this solution in Elixir. So I created a project on my Github page called ElixirLargeSort. This project will accomplish the same thing that the other two projects did, but using Elixir. Like the other projects, I plan to create a full suite of unit tests to test the parts of the code.


Like the other projects, there are two runnable programs in ElixirLargeSort: IntGen and IntSort. IntGen is the simpler of the two: its job is to create an integer file of randomly-generated integers. This provides us a collection of random integers to sort in chunks. The IntSort program will then read in the randomly-generated integers and provide the sorting functionality, spitting out a final sorted integer file.


When I talk about "integer file" in the context of this project, I mean a text file with an integer on each line. Having each integer on its own line makes it easy for code to read the file and easy to people to view the file in a text editor. The line numbers in the editor can easily tell us how many integers are in an integer file.


First, I created the IntGen project (known to Elixir by the :int_gen atom) by running mix new int_gen. That created a nice project for me. Since Elixir is a functional language, I'm trying to create simpler, more composable functions, so I started work on a function that creates a random integer stream. Anyone who's been reading along knows that I love streams, so I'm going to try to use streams as much as I can (the Node.js implementation used Bacon.js streams).


So I created a module called IntGen, which will contain the main functions for the IntGen application. After I'm finished with this module, I'll put an interface layer (to the command line) on top of it. Back in lwm 43, where I talked about streams, I had already implemented a stream that generates random integers. So I'll just use that code here as well.


Most of the contents of this module are actually documentation. The code is quite small. The random_integer_stream/1 function takes a range that defines the range of the random integers to be generated and then returns a stream (created using Stream.repeatedly/1) that will generate those random integers. Note that this is an infinite stream, so it will generate as many random numbers as we need.


Once I finished with that code, I compiled it by running mix on the command line. Once it compiled, I loaded the application into iex by running iex -S mix. Then I tested the function manually to see how it works, piping the resulting stream into a list to see the randomly-generated integers.


It's important to use Enum.take/1 here because the stream is infinite. The first time I did this, I mistakenly used Enum.to_list/1 and was then puzzled when it never finished, until I realized what I had done.


I grouped all the tests for this function using describe. I tested that the stream only generates integers (and not some other type of data) and then tried testing with different ranges of values to verify that the stream still functions as expected. While writing these tests, I saw that they would mostly be the same, with the only variation being the range of integers that were being generated. So I created a function that contains the logic for all the tests, with the test variables passed in as parameters. So all I had to do for each test is to call test_range/2, passing the range I want to test. I typically structure my unit tests this way when I see a chance for reusability. It's a lot more maintainable and readable than copying and pasting code between the tests.


As I was writing the tests, I wanted to see the tests start off failing and go from failing to passing as I wrote the tests. In the past when I failed to do this, I occasionally found that I forgot to implement some tests, since they we're all passing due to not containing any code. I call these sort of tests false positives, so I like to insert something that deliberately causes them to fail until they are implemented.


In past implementations of this project, I found that there was some common integer file functionality that was shared between IntGen and IntSort. I had no reason to doubt that this project implementation would be any different. I then had to figure out how to share code between Elixir projects without having to publish a package to hex.


Here's what I ended up doing. I created a separate project called ElixirLargeSort.Shared (located in the largesort_shared) directory that contains any functionality that will be shared between IntGen and IntSort. This is where I will put the generic integer file functionality. For the IntGen project, I wanted a function that will create a file stream for an integer file, and then keeping in the spirit of functional composition, I wanted a separate function that will take an enumerable containing integers (which could be another stream) and write it to a stream. The plan was to create the random integer stream, an integer file stream, and then write the integers in the random integer stream to the file stream.


I also kept in mind that when I was doing unit testing, I want to mock out dependencies that produce side effects in order to make testing simpler. That requires decoupling the interface from the implementation and mocking out a test implementation during unit tests. In C#, I did that using interfaces and implementations and in Elixir, I do that using behaviours and behaviour implementations. If you want to review those subjects, I talked about unit tests and mocking in lwm 65 and I talked about behaviours in lwm 71.


That defines the integer file functionality using typespecs. Ideally, I want to specify a stream of integers in the typepsec, but typespecs cannot currently get that specific. I can define a list of integers in a typespec, but streams are enumerables, not lists. So the best I could do was to specify an enumerable (Enumerable.t()) for streams that will be read from and a collectable (Collectable.t()) for streams that will be written to. Streams are both enumerables and collectables, so I can use either typespec depending on the primary role of the stream.


The alias statement at the top of the module allows me just write IntegerFileBehavior instead of having to include the full namespace. The @behaviour IntegerFileBehavior statement tells the module that it's implementing IntegerFileBehavior.


Again, most of the content of the module is documentation. The code is relatively simple and brief, which is my goal. Notice that when writing integers to a stream, which will mostly be an integer file stream, I need to convert each integer to a string and then add a newline character to the end of each integer string before I write it to the stream. That's necessary to write to a text file in the proper format.

3a8082e126
Reply all
Reply to author
Forward
0 new messages