Evolution of Programming Languages

Scripting, Web, and Domain-Specific Languages


Learning Objectives

  • You know of languages for specific tasks like scripting and automation.

Beyond the evolution of programming paradigms like structural programming, object-oriented programming, and functional programming, software development has also been shaped by languages that help in specific tasks.

Scripting and Automation

Scripting languages help in automating repetitive tasks and streamlining system administration. Scripting languages are typically interpreted, allowing developers to write and execute code rapidly without an explicit build process, and they also often provide a direct interface to functionality provided by the operating system.

For example, the following Bash script can be used to back up files in a directory:

#!/bin/bash

SOURCE_DIR="/path/to/source"
DEST_DIR="/path/to/backup/$(date +%Y-%m-%d)"

# Create the destination directory if it doesn't exist
mkdir -p "$DEST_DIR"

# Copy files from the source to the backup directory
cp -r "$SOURCE_DIR"/* "$DEST_DIR"

echo "Backup completed successfully to $DEST_DIR"

The above script demonstrates th utility of scripting for automation by using existing shell commands. The above script could be, for example, scheduled with crontab to run daily backups automatically.

Languages like Python are also widely used for automation tasks due to the standard libraries. The following Python script shows how to watch for changes in a given directory, and process the files that have been changed.

import os
import time

WATCHED_DIR = '/path/to/watched/directory'

def process_file(filename):
  print(f"Processing {filename}")
  # do something here

def watch_directory(directory):
  already_seen = set(os.listdir(directory))
  while True:
    time.sleep(5)
    current_files = set(os.listdir(directory))
    new_files = current_files - already_seen
    if new_files:
      for file in new_files:
        process_file(file)
      already_seen.update(new_files)

if __name__ == "__main__":
  watch_directory(WATCHED_DIR)

Both of the above examples highlight the utility of scripting in automating tasks that would be tedious and error-prone if done manually. Implementing the above functionality with languages like Scala would be also possible, although the syntax is more verbose and the setup more complex.

It is better to leave scripting tasks for scripting languages. However, if performance is a concern, it is possible to use languages like Rust for better performance.

Loading Exercise...

Languages Shaping the Web

When discussing the evolution of programming languages, we can’t ignore languages that have shaped the web: HTML, CSS, and JavaScript. These languages form the basis of web, and have evolved to meet the demands of modern web applications.

As an example, the following HTML page contains JavaScript that dynamically changes the content of a web page element when a button is clicked:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Interactive Web Page</title>
  <script>
    function changeContent() {
      document.getElementById('message').innerText = 'Hello, World!';
    }
  </script>
</head>
<body>
  <h1 id="message">Welcome</h1>
  <button onclick="changeContent()">Click Me</button>
</body>
</html>

On the server, languages like PHP have gained popularity by providing a straightforward way to generate dynamic content and interact with databases. A basic PHP script for displaying a greeting might look like this:

<?php
$name = "Visitor";
echo "<h1>Hello, $name! Welcome to our website.</h1>";
?>
More on evolution of web development..

For more information on the evolution of web development, check out the Web Software Development course.

Domain-Specific Languages

Domain-specific languages (DSLs) are tailored to specific problem domains, offering specialized syntax and features for particular tasks. Their focused design makes DSLs highly effective in their niche, minimizing the need for verbose or error-prone general-purpose code.

One of the most well-known DSLs is SQL (Structured Query Language), which is specifically designed for managing and querying relational databases. SQL abstracts the complexity of underlying data structures, enabling declarative commands for querying and manipulating data.

SELECT first_name, last_name, email
  FROM customers
  WHERE signup_date >= '2024-01-01'
  ORDER BY last_name ASC;

The above example would retrieve a list of customers who signed up after January 1, 2024, sorted alphabetically by their last name. SQL’s widespread adoption in database management underscores the power of DSLs to simplify complex operations by focusing on domain-specific requirements.

DSLs are not limited to web and database domains, as they also appear in configuration management (e.g., YAML and JSON), scientific computing, and even in specialized areas like build automation (e.g., Gradle uses a DSL based on Groovy or Kotlin).

As an example, the following YAML configuration file for Docker Compose is also a DSL tailored for specifying settings in a human-readable format:

services:
  server:
    build: server
    restart: unless-stopped
    volumes:
      - ./server:/app
    ports:
      - 8000:8000

  client:
    build: client
    restart: unless-stopped
    volumes:
      - ./client:/app
    ports:
      - 4321:4321
    depends_on:
      - server
Loading Exercise...