Register to get access to free programming courses with interactive exercises

Parametric polymorphism JS: Polymorphism

The word polymorphism can mean different things depending on the context. When programmers in imperative languages talk about polymorphism, they usually mean polymorphism of subtypes. At the same time, programmers in functional languages have parametric polymorphism in mind. Let us talk about the latter.

We will see Java code in this lesson. Do not worry if you don't fully understand it. Our goal is to deal with concepts, not Java itself.

The lodash library has the _.concat() function, which combines arrays passed to it:

_.concat([1], [2, 3, 1]); // [1, 2, 3, 1]
_.concat(['one'], ['two', 'three']); // ['one', 'two', 'three']
_.concat([true], [false, false, true]); // [true, false, false, true]

This function joins any array, regardless of the type of data contained within. Let's try to implement it ourselves.

It is a slightly stripped-down version of the concat function. It only works with two arguments, each of them is an array. The function creates a new array, then traverses the passed arrays one by one, and adds their values to the newly created array.Then, it returns the result:


const concat = (coll1, coll2) => {
    const result = [];
    coll1.forEach((value) => result.push(value));
    coll2.forEach((value) => result.push(value));
    return result;
};

Take a close look at this code. Does it perform any operations on the data inside the array? The correct answer is no. This data moves from one array to another, but we do not act on it. Our new concat() function, like the original _.concat() function, can handle arrays containing any data type.

This behavior seems natural for developers who've only written in dynamic languages. But in static languages, it's not so simple. Below is an example of the definition of arrays in Java:

int numbers[] = {3, 1, 2, 5, 4};
String words[] = {"one", "two", "three"};

The first thing you might notice is the need to specify the type. For the first array, it is int. For the second one, it is String. You can't create an array without specifying what type its values will have. The same applies to functions that process arrays:

class Main {
    public static void main(String[] args) {
        // Declaring array `a`
        int[] a = {1, 2, 3, 4};
        // Declaring array `b`
        int[] b = {4, 16, 1, 2, 3, 22};

        // Merging arrays
        concat(a, b);
    }

    // Arrays are containing only int can be input
    public static int[] concat(int[] arr1, int[] arr2) {
        // Create a resulting array whose length is equal to the sum of the lengths of the original arrays
        int[] result = new int[arr1.length + arr2.length];

        // Transfer all values from the first array to result
        for (int i = 0; i < arr1.length; i++) {
           result[i] = arr1[i];
        }

        // Transfer all values from the second array to result
        for (int j = 0; j < arr2.length; j++) {
           result[arr1.length + j] = arr2[j];
        }

        return result;
    }
}

Note the signature of the concat() method: concat(): int[] concat(int[] arr1, int[] arr2). In contrast to the JavaScript variant, the input parameters here are arrays of numbers. I.e., this function won't work for an array of strings. Nor will it work for all other data types.

What does this mean in practice? Something simple but sad. We have to implement a similar function for each type even though the algorithm inside is identical.

It is where parametric polymorphism comes in handy. Static languages have to introduce special constructions into the language. They help us describe these algorithms without regard to the type of parameter. In some languages, they're called templates (C++) or generics (Java, C#):

class Main {
  public static void main(String[] args) {
    Integer[] a = {1, 2, 3, 4};
    Integer[] b = {4, 16, 1, 2, 3, 22};
    concat(a, b);
  }

  public static<T> T[] concat(T[] arr1, T[] arr2) {
      T[] result = (T[]) new Object[arr1.length + arr2.length];

      for (int i = 0; i < arr1.length; i++) {
         result[i] = arr1[i];
      }

      for (int j = 0; j < arr2.length; j++) {
         result[arr1.length + j] = arr2[j];
      }

      return result;
  }
}

In this code, we see a type called T. It simply means we can use it within an array with any type. The concat() method now works like its JavaScript counterpart.

Parametric polymorphism makes it possible to write generalized algorithms for composite types. In some cases, it reduces the amount of code. Sometimes, this comes at the expense of having a simple solution. But you won't see an increase in complexity for most typical operations. You can see that in the code above.

Dynamic languages don't need parametric polymorphism to implement generalized algorithms. Any collection can contain any data type at any time. It eliminates the need to introduce additional language constructs and learn new concepts.

In the literature, the usage of parametric polymorphism is often called generalized programming.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.