Saturday, May 18, 2024

Using MathML to Embed Mathematical Equations in Webpages

MathML (Mathematical Markup Language), a markup language developed by the World Wide Web Consortium (W3C), serves as the standard for representing mathematical notation on the web. Integrating MathML into webpages involves encapsulating mathematical expressions within <math> tags and utilising a variety of MathML elements to represent different components of equations.

For example, the following snippet represents the quadratic formula: x = - b ± b2 - 4 a c 2 a

<math>
  <mrow>
    <mi>x</mi>
    <mo>=</mo>
    <mfrac>
      <mrow>
        <mo>-</mo>
        <mi>b</mi>
        <mo>±</mo>
        <msqrt>
          <mrow>
            <msup><mi>b</mi><mn>2</mn></msup>
            <mo>-</mo>
            <mn>4</mn>
            <mi>a</mi>
            <mi>c</mi>
          </mrow>
        </msqrt>
      </mrow>
      <mrow>
        <mn>2</mn>
        <mi>a</mi>
      </mrow>
    </mfrac>
  </mrow>
</math>

While alternatives like LaTeX exist, MathML emerges as the superior choice for the web because it is supported natively by modern web browsers, without the need for additional libraries or plugins. Also, search engines can parse MathML-encoded equations, enhancing the discoverability of mathematical content on the web. LaTeX requires additional processing and rendering engines like MathJax or KaTeX to display equations in webpages, introducing complexities and potential compatibility issues.

Saturday, May 11, 2024

Java 22: Stream Gatherers

Java 22 introduces Stream Gatherers, a preview language feature, that allows you to build complex stream pipelines using custom intermediate operations, such as grouping elements based on specific criteria, selecting elements with intricate conditions, or performing sophisticated transformations. Furthermore, Stream Gatherers offer seamless integration with parallel stream processing, ensuring optimal performance even in parallel execution scenarios.

There are built-in gatherers like fold, mapConcurrent, scan, windowFixed, and windowSliding, but you can also define your own custom gatherers.

Here is an example using the windowFixed gatherer to group elements in a stream into sliding windows of a specified size:

IntStream.range(0,10)
  .boxed()
  .gather(Gatherers.windowFixed(2))
  .forEach(System.out::println);

// Result:
[0, 1]
[2, 3]
[4, 5]
[6, 7]
[8, 9]

Sunday, May 05, 2024

Java 22: Statements Before super(...)

Java 22 brings forth a new preview language feature: the ability to include statements before the super() call in constructors.

Traditionally, Java constructors have had a strict rule: the super() call, which invokes the superclass constructor, must always be the first statement in a subclass constructor. This rule, while ensuring proper initialisation order, sometimes led to verbose or convoluted constructor implementations, especially when additional setup was required before invoking the superclass constructor.

With the introduction of JDK 22, this limitation has been relaxed with the introduction of pre-super statements, which allow you to validate and prepare arguments before the super() call. This also facilitates fail-fast scenarios, because you can perform rigorous argument validation or exception handling before superclass instantiation.

Here is an example:

class Shape {
  private final String color;

  Shape(String color) {
    this.color = color;
  }
}

class Rectangle extends Shape {
  private final double length;
  private final double width;

  Rectangle(String color, double length, double width) {
    if (length <= 0 || width <= 0) {
      throw new IllegalArgumentException("Dimensions must be positive");
    }
    super(color);
    this.length = length;
    this.width = width;
  }
}

In this example, before invoking the superclass constructor, a pre-super statement validates the dimensions of the rectangle, ensuring they are positive.

Saturday, May 04, 2024

Java 22: Unnamed Variables and Patterns

Java 22 introduces Unnamed Variables & Patterns. Unnamed variables are placeholders denoted by the underscore character (_) that stand in for variable names, particularly in situations where the variable's identifier is insignificant or redundant. They can be declared in several contexts, including local variable declarations, catch clauses, lambda expressions, and more. By omitting explicit variable names in scenarios where the variable name serves no functional purpose, code becomes more succinct, reducing unnecessary verbosity and aiding readability.

Here are a few examples of unnamed variables in action:

For-loop:

for (Order _ : orders) {
  doSomething();
}

Assignment statement:

Queue<Integer> q = ... // x1, y1, z1, x2, y2, z2, ...
var x = q.remove();
var y = q.remove();
var _ = q.remove();

Lambda expressions:

list.stream().mapToInt(_ -> 1).sum();

Exception handling:

String s = ...
try {
  int i = Integer.parseInt(s);
} catch (NumberFormatException _) {
  System.out.println("Invalid number: " + s);
}

Try-with-resources:

try (BufferedReader _ = new BufferedReader(...)) {
  System.out.println("File opened successfully.");
} catch (IOException _) {
  System.err.println("An error occurred while opening the file.");
}

Unnamed pattern variables:

switch (shape) {
  case Circle _ -> process(shape, 0);
  case Triangle _ -> process(shape, 3);
  case Rectangle _ -> process(shape, 4);
  case var _ -> System.out.println("Unknown shape");
}

Unnamed Patterns

Unnamed Patterns provide an elegant solution when you need to match a pattern without extracting specific components. If you have nested data structures, such as records within records, with unnamed patterns, you can focus on extracting the necessary components without cluttering your code with unnecessary variable assignments.

record Address(String city, String country) {}
record Person(String name, int age, Address address) {}

if (person instanceof Person(var name, _, Address(var city, _))) {
  System.out.println(name + " lives in " + city);
}

So, the next time you encounter a situation where the variable name seems inconsequential, consider using an unnamed variable to streamline your code.