MLStyle.jl

repository·main·Indexed 19 days ago

https://github.com/thautwarm/mlstyle.jl

A Julia library providing functional programming infrastructure and metaprogramming facilities. It focuses on intuitive and fast pattern matching via the `@match` macro, algebraic data type (ADT) definitions using `@data`, and support for Generalized Algebraic Data Types (GADTs). The library includes specialized tools such as `@matchast` and `@capture` for AST manipulation, `@cond` for Lisp-flavored conditional branching, and active patterns via `@active` for custom matching logic.

Tokens
10.4K
Snippets
53
Records
60
Agent score
65%

What's inside MLStyle.jl

  1. Overview of MLStyle.jl

    main

    MLStyle.jl is a Julia package designed to bring advanced functional programming idioms to the Julia language. It provides productivity tools inspired by ML (Meta Language) to make functional programming patterns more convenient, efficient, and extensible within Julia's ecosystem.

    Key features include:

    • Pattern Matching: Statically generated and extensible pattern matching.
    • ADTs/GADTs: Support for Algebraic Data Types and Generalized Algebraic Data Types.
    • Active Patterns: Implementation of Active Patterns (similar to those found in F#).
  2. Understand MLStyle.jl benchmark results

    main

    Benchmark results are presented as relative time costs.

    • X-axis: Represents the test-case name followed by the index of the least time-consuming run in nanoseconds (ns).
    • Y-axis: Represents the ratio of the implementation's time cost relative to the least time-consuming implementation (where 1.0 is the fastest).

    Raw benchmark results in DataFrames format can be found in the stats/ directory of the repository.

  3. Use MLStyle.jl for AST manipulation and extraction

    main

    MLStyle.jl provides a syntactic way to validate or extract components from Julia Abstract Syntax Trees (ASTs) using Symbol and Expr. It is significantly faster than MacroTools.jl for extracting sub-structures from a given AST.

    You can use the @match macro to match against an expression and extract specific values using the same syntax used to construct the expression.

    f = some_thing
    ex = :($f(a, b))
    
    f == @match ex begin
        :($f(a, b)) => f
    end # => true
  4. Pattern match on Julia ASTs (Homoiconic matching)

    main

    Because Julia is homoiconic, you can use @match to deconstruct and manipulate Julia expressions (Expr). This is useful for writing macros or tools that transform code. You can match against quote ... end blocks to represent the structure of the code you are inspecting.

    @match expr begin
        quote
            struct $name{$tvar}
                $f1 :: $t1
                $f2 :: $t2
            end
        end => some_result
    end
  5. Create singleton instances with @data

    main

    If a subtype in an @data block is defined without any fields, MLStyle creates a singleton instance for it. This means the name provided becomes a constant value representing the sole instance of that subtype.

    @data T begin
      a
      b
    end
    
    # This effectively creates:
    # const a = _A()
    # const b = _B()
  6. How MQuery implements `@groupby` and `@having`

    main

    The @groupby clause is used to group data based on a predicate or mapping. The @having clause acts as a sub-clause of @groupby; it cannot exist independently and must co-appear with a @groupby clause to filter the resulting groups.

    Example usage:

    df |
    @groupby startswith(_.name, "Ruby") => is_ruby
    @having is_ruby || count(_.is_rose) > 5
  7. Use Capture to peek at the matching scope

    main

    In pattern matching, Capture is a special pattern that allows you to inspect the scope (represented as a Dict{Symbol, T}) at a specific point during the matching process.

    Important constraints:

    • The scope only contains variables that MLStyle is aware of.
    • Outer local variables and global variables are not included in the returned dictionary.
    @switch (1, 2, 3) begin
               @case (Capture(s1), Capture(s2), Capture(s3))
                   println(s1)
                   println(s2)
                   println(s3)
           end       
  8. Deploy code without MLStyle.jl runtime dependency

    main
    MLStyle.jl supports referential transparency. Because the macros expand into enclosed code that requires no runtime support, the generated code can run in production environments without having MLStyle.jl installed. This allows you to use MLStyle during development time to generate high-performance code that remains standalone.
  9. Enable pattern-matching deconstruction for structs with @as_record

    main

    By default, standard Julia structs do not support deconstruction via pattern matching. To enable this, use the @as_record macro on a struct type. Once applied, you can use the @match macro to deconstruct instances of that struct using the same syntax as its constructor (e.g., A(a, b, c)).

    You can either invoke @as_record A after the struct is defined, or wrap the entire struct definition with the macro.

    struct A
        a
        b
        c
    end
    
    @as_record A
    
    # Now you can deconstruct in @match
    @match A(1, 2, 3) begin
        A(a, b, c) => a + b + c
    end
  10. Basic Syntax of Pattern Matching with @match

    main

    MLStyle uses the @match macro to perform pattern matching. The basic syntax involves a data object followed by a block of patterns and results. MLStyle tests patterns sequentially; the first match returns its corresponding result. If no pattern matches, an error is thrown.

    In version 0.4.1 and newer, you can use a single-line syntax for a single pattern without the begin...end block.

    @match data begin
        pattern1 => result1
        pattern2 => result2
        ...
        patternn => resultn
    end
    
    # Single pattern syntax (v0.4.1+)
    @match data pattern => result