From 177857b987ff2ad3932849875f35ca95a0f57135 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Thu, 21 Nov 2024 15:46:36 +0000 Subject: [PATCH] build based on fcbea00 --- previews/PR117/.documenter-siteinfo.json | 2 +- previews/PR117/index.html | 14 +++++++------- previews/PR117/search_index.js | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/previews/PR117/.documenter-siteinfo.json b/previews/PR117/.documenter-siteinfo.json index 3193359..98678b2 100644 --- a/previews/PR117/.documenter-siteinfo.json +++ b/previews/PR117/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-21T15:39:13","documenter_version":"1.8.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.11.1","generation_timestamp":"2024-11-21T15:46:30","documenter_version":"1.8.0"}} \ No newline at end of file diff --git a/previews/PR117/index.html b/previews/PR117/index.html index 0b65b19..7525305 100644 --- a/previews/PR117/index.html +++ b/previews/PR117/index.html @@ -206,11 +206,11 @@ expr_type, " expression:\n", " $e\n") end -end

Inspiration

The following pages on pattern matching in scala provided inspiration for the library:

The following paper on pattern-matching inspired the automaton approach to code generation:

API Documentation

Match.MatchFailureType
MatchFailure(value)

Construct an exception to be thrown when a value fails to match a pattern in the @match macro.

source
Match.match_fieldnamesMethod
match_fieldnames(type::Type)

Return a tuple containing the ordered list of the names (as Symbols) of fields that can be matched either nominally or positionally. This list should exclude synthetic fields that are produced by packages such as Mutts and AutoHashEqualsCached. This function may be overridden by the client to hide fields that should not be matched.

source
Match.@__match__Macro

Usage:

    @__match__ value begin
+end

Inspiration

The following pages on pattern matching in scala provided inspiration for the library:

The following paper on pattern-matching inspired the automaton approach to code generation:

API Documentation

Match.MatchFailureType
MatchFailure(value)

Construct an exception to be thrown when a value fails to match a pattern in the @match macro.

source
Match.match_fieldnamesMethod
match_fieldnames(type::Type)

Return a tuple containing the ordered list of the names (as Symbols) of fields that can be matched either nominally or positionally. This list should exclude synthetic fields that are produced by packages such as Mutts and AutoHashEqualsCached. This function may be overridden by the client to hide fields that should not be matched.

source
Match.@__match__Macro

Usage:

    @__match__ value begin
         pattern1 => result1
         pattern2 => result2
         ...
-    end

Return result for the first matching pattern. If there are no matches, throw MatchFailure. This uses a brute-force code gen strategy, essentially a series of if-else statements. It is used for testing purposes, as a reference for correct semantics. Because it is so simple, we have confidence about its correctness.

source
Match.@ismatchMacro
@ismatch value pattern

Return true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.

See also @match for the syntax of patterns

Examples

julia> struct Point
+    end

Return result for the first matching pattern. If there are no matches, throw MatchFailure. This uses a brute-force code gen strategy, essentially a series of if-else statements. It is used for testing purposes, as a reference for correct semantics. Because it is so simple, we have confidence about its correctness.

source
Match.@ismatchMacro
@ismatch value pattern

Return true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.

See also @match for the syntax of patterns

Examples

julia> struct Point
             x
             y
         end
@@ -224,7 +224,7 @@
 On the y axis at y = 3

Guarded patterns ought not be used with @ismatch, as you can just use && instead:

julia> if (@ismatch p Point(x, y)) && x < y
             println("The point (", x, ", ", y, ") is in the upper left semiplane")
         end
-The point (0, 3) is in the upper left semiplane
source
Match.@matchMacro
@match pattern = value
+The point (0, 3) is in the upper left semiplane
source
Match.@matchMacro
@match pattern = value
 @match value begin
     pattern1 => result1
     pattern2 => result2
@@ -233,7 +233,7 @@
     pattern1 => result1
     pattern2 => result2
     ...
-end

Return result for the first matching pattern. If there are no matches, throw MatchFailure.

To avoid a MatchFailure exception, write the @match to handle every possible input. One way to do that is to add a final case with the wildcard pattern _.

See Also

See also

  • @match_fail
  • @match_return
  • @ismatch

Patterns:

The following syntactic forms can be used in patterns:

  • _ matches any value
  • x (an identifier) matches any value and binds it to the variable x
  • 1 (a literal value) matches that value
  • T(x,y,z) matches structs of type T with fields matching patterns x,y,z
  • T(y=p) matches structs of type T whose y field matches pattern p
  • (;x,y,z) matches values with fields x,y,z binding to variables x,y,z
  • (;x=p) matches values with field x matching pattern p; also binds the field to x
  • (;x::T) matches values with field x matching pattern ::T; also binds the field to x
  • [x,y,z] matches AbstractArrays with 3 entries matching x,y,z
  • (x,y,z) matches Tuples with 3 entries matching x,y,z
  • [x,y...,z] matches AbstractArrays with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.
  • (x,y...,z) matches Tuples with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.
  • ::T matches any subtype (isa) of type T
  • x::T matches any subtype (isa) of T that also matches pattern x
  • x || y matches values which match either pattern x or y (only variables which exist in both branches will be bound)
  • x && y matches values which match both patterns x and y
  • x, if condition end matches only if condition is true (condition may use any variables that occur earlier in the pattern eg (x, y, z where x + y > z))
  • x where condition An alternative form for x, if condition end
  • if condition end A boolean computed pattern. x && if condition end is another way of writing x where condition.
  • Anything else is treated as a constant and tested for equality
  • Expressions can be interpolated in as constants via standard interpolation syntax $(x). Interpolations may use previously bound variables.

Patterns can be nested arbitrarily.

Repeated variables only match if they are equal (isequal). For example (x,x) matches (1,1) but not (1,2).

Examples

julia> value=(1, 2, 3, 4)
+end

Return result for the first matching pattern. If there are no matches, throw MatchFailure.

To avoid a MatchFailure exception, write the @match to handle every possible input. One way to do that is to add a final case with the wildcard pattern _.

See Also

See also

  • @match_fail
  • @match_return
  • @ismatch

Patterns:

The following syntactic forms can be used in patterns:

  • _ matches any value
  • x (an identifier) matches any value and binds it to the variable x
  • T(x,y,z) matches structs of type T with fields matching patterns x,y,z
  • T(y=p) matches structs of type T whose y field matches pattern p
  • (;x,y,z) matches values with fields x,y,z binding to variables x,y,z
  • (;x=p) matches values with field x matching pattern p; also binds the field to x
  • (;x::T) matches values with field x matching pattern ::T; also binds the field to x
  • [x,y,z] matches AbstractArrays with 3 entries matching x,y,z
  • (x,y,z) matches Tuples with 3 entries matching x,y,z
  • [x,y...,z] matches AbstractArrays with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.
  • (x,y...,z) matches Tuples with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.
  • ::T matches any subtype (isa) of type T
  • x::T matches any subtype (isa) of T that also matches pattern x
  • x || y matches values which match either pattern x or y (only variables which exist in both branches will be bound)
  • x && y matches values which match both patterns x and y
  • x, if condition end matches only if condition is true (condition may use any variables that occur earlier in the pattern eg (x, y, z where x + y > z))
  • x where condition An alternative form for x, if condition end
  • if condition end A boolean computed pattern. x && if condition end is another way of writing x where condition.
  • 1 (a literal value) matches that value using isequal
  • r"[a-z]*" (a regular expression) matches strings that match the regular expression
  • 1:10 (a constant range) matches values in that range
  • Expressions can be interpolated in as constants via standard interpolation syntax $(x). Interpolations may use previously bound variables.

Patterns can be nested arbitrarily.

Repeated variables only match if they are equal (isequal). For example (x,x) matches (1,1) but not (1,2).

Examples

julia> value=(1, 2, 3, 4)
 (1, 2, 3, 4)
 
 julia> @match (x, y..., z) = value
@@ -286,7 +286,7 @@
 
 julia> f(Foo(2, "not a foo"))
 ERROR: MatchFailure(Foo(2, "not a foo"))
-...
source
Match.@match_failMacro
@match_fail

Inside the result part of a @match case, you can cause the pattern to fail (as if the pattern did not match).

Examples

julia> struct Vect
+...
source
Match.@match_failMacro
@match_fail

Inside the result part of a @match case, you can cause the pattern to fail (as if the pattern did not match).

Examples

julia> struct Vect
            x
            y
        end
@@ -309,7 +309,7 @@
 Vect(0.5547001962252291, 0.8320502943378437)
 
 julia> norm(Vect(0, 0))
-Vect(0, 0)
source
Match.@match_failMacro
@match_fail

This statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write

@match_fail

to cause the case to terminate as if its pattern had failed. This permits cases to perform some computation before deciding if the rule "really" matched.

source
Match.@match_returnMacro
@match_return value

Inside the result part of a @match case, you can return a given value early.

Examples

julia> struct Vect
+Vect(0, 0)
source
Match.@match_failMacro
@match_fail

This statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write

@match_fail

to cause the case to terminate as if its pattern had failed. This permits cases to perform some computation before deciding if the rule "really" matched.

source
Match.@match_returnMacro
@match_return value

Inside the result part of a @match case, you can return a given value early.

Examples

julia> struct Vect
            x
            y
        end
@@ -332,4 +332,4 @@
 Vect(0.5547001962252291, 0.8320502943378437)
 
 julia> norm(Vect(0, 0))
-Vect(0, 0)
source
Match.@match_returnMacro
@match_return value

This statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write

@match_return value

to terminate the value expression early with success, with the given value.

source
+Vect(0, 0)source
Match.@match_returnMacro
@match_return value

This statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write

@match_return value

to terminate the value expression early with success, with the given value.

source
diff --git a/previews/PR117/search_index.js b/previews/PR117/search_index.js index de5164b..a6786db 100644 --- a/previews/PR117/search_index.js +++ b/previews/PR117/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"","page":"Home","title":"Home","text":"CurrentModule = Match","category":"page"},{"location":"#[Match.jl](https://github.com/JuliaServices/Match.jl)-–-Advanced-Pattern-Matching-for-Julia","page":"Home","title":"Match.jl –- Advanced Pattern Matching for Julia","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package provides both simple and advanced pattern matching capabilities for Julia. Features include:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Matching against almost any data type with a first-match policy\nDeep matching within data types, tuples, and vectors\nVariable binding within matches\nEfficient code generation via a decision automaton.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Use the Julia package manager. Within Julia, do:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Pkg.add(\"Match\")","category":"page"},{"location":"#Usage","page":"Home","title":"Usage","text":"","category":"section"},{"location":"#Simple-pattern-@ismatch-macro","page":"Home","title":"Simple-pattern @ismatch macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @ismatch macro tests if a value patches a given pattern, returning either true if it matches, or false if it does not. When the pattern matches, the variables named in the pattern are bound and can be used.","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> using Match\n\njulia> @ismatch (1, 2) (x, y)\ntrue\n\njulia> x\n1\n\njulia> y\n2","category":"page"},{"location":"#Multi-case-@match-macro","page":"Home","title":"Multi-case @match macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @match macro acts as a pattern-matching switch statement, in which each case has a pattern and a result for when that pattern matches. The first case that matches is the one that computes the result for the @match.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Match\n@match item begin\n pattern1 => result1\n pattern2 where cond => result2\n pattern3 || pattern4 => result3\n _ => default_result\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Patterns can be values, regular expressions, type checks or constructors, tuples, or arrays. It is possible to supply variables inside a pattern, which will be bound to corresponding values. This and other features are best seen with examples.","category":"page"},{"location":"#Match-Values","page":"Home","title":"Match Values","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The easiest kind of matching to use is simply to match against values:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@match item begin\n 1 => \"one\"\n 2 => \"two\"\n _ => \"Something else...\"\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Values can be computed expressions by using interpolation. That is how to use @match with @enums:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@enum Color Red Blue Greed\n@match item begin\n $Red => \"Red\"\n $Blue => \"Blue\"\n $Greed => \"Greed is the color of money\"\n _ => \"Something else...\"\nend","category":"page"},{"location":"#Match-Types","page":"Home","title":"Match Types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Julia already does a great job of this with functions and multiple dispatch, and it is generally be better to use those mechanisms when possible. But it can be done here:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> matchtype(item) = @match item begin\n ::Int => println(\"Integers are awesome!\")\n ::String => println(\"Strings are the best\")\n ::Dict{Int, String} => println(\"Ints for Strings?\")\n ::Dict => println(\"A Dict! Looking up a word?\")\n _ => println(\"Something unexpected\")\n end\n\njulia> matchtype(66)\nIntegers are awesome!\n\njulia> matchtype(\"abc\")\nStrings are the best\n\njulia> matchtype(Dict{Int, String}(1=>\"a\",2=>\"b\"))\nInts for Strings?\n\njulia> matchtype(Dict())\nA Dict! Looking up a word?\n\njulia> matchtype(2.0)\nSomething unexpected","category":"page"},{"location":"#Deep-Matching-of-Composite-Types","page":"Home","title":"Deep Matching of Composite Types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"One nice feature is the ability to match embedded types, as well as bind variables to components of those types:","category":"page"},{"location":"","page":"Home","title":"Home","text":"struct Address\n street::String\n city::String\n zip::String\nend\n\nstruct Person\n firstname::String\n lastname::String\n address::Address\nend\n\npersoninfo(person) = @match person begin\n Person(\"Julia\", lname, _) => \"Found Julia $lname\"\n Person(fname, \"Julia\", _) => \"$fname Julia was here!\"\n Person(fname, lname,\n Address(_, \"Cambridge\", zip)) => \"$fname $lname lives in zip $zip\"\n Person(_...) => \"Unknown person!\"\nend\n\njulia> personinfo(Person(\"Julia\", \"Robinson\",\n Address(\"450 Serra Mall\", \"Stanford\", \"94305\")))\n\"Found Julia Robinson\"\n\njulia> personinfo(Person(\"Gaston\", \"Julia\",\n Address(\"1 rue Victor Cousin\", \"Paris\", \"75005\")))\n\"Gaston Julia was here!\"\n\njulia> personinfo(Person(\"Edwin\", \"Aldrin\",\n Address(\"350 Memorial Dr\", \"Cambridge\", \"02139\")))\n\"Edwin Aldrin lives in zip 02139\"\n\njulia> personinfo(Person(\"Linus\", \"Pauling\",\n Address(\"1200 E California Blvd\", \"Pasadena\", \"91125\")))\n\"Unknown person!\"","category":"page"},{"location":"#Alternatives-and-Guards","page":"Home","title":"Alternatives and Guards","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Alternatives allow a match against multiple patterns.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Guards allow a conditional match. They are not a standard part of Julia yet, so to get the parser to accept them requires that they are preceded by a comma and end with \"end\":","category":"page"},{"location":"","page":"Home","title":"Home","text":"function parse_arg(arg::String, value::Any=nothing)\n @match (arg, value) begin\n (\"-l\", lang) => println(\"Language set to $lang\")\n (\"-o\" || \"--optim\", n::Int),\n if 0 < n <= 5 end => println(\"Optimization level set to $n\")\n (\"-o\" || \"--optim\", n::Int) => println(\"Illegal optimization level $(n)!\")\n (\"-h\" || \"--help\", nothing) => println(\"Help!\")\n bad => println(\"Unknown argument: $bad\")\n end\nend\n\njulia> parse_arg(\"-l\", \"eng\")\nLanguage set to eng\n\njulia> parse_arg(\"-l\")\nUnknown argument: (\"-l\",nothing)\n\njulia> parse_arg(\"-o\", 4)\nOptimization level set to 4\n\njulia> parse_arg(\"--optim\", 5)\nOptimization level set to 5\n\njulia> parse_arg(\"-o\", 0)\nIllegal optimization level 0!\n\njulia> parse_arg(\"-o\", 1.0)\nUnknown argument: (\"-o\",1.0)\n\njulia> parse_arg(\"-h\")\nHelp!\n\njulia> parse_arg(\"--help\")\nHelp!","category":"page"},{"location":"","page":"Home","title":"Home","text":"The alternative guard syntax pattern where expression can sometimes be easier to use.","category":"page"},{"location":"","page":"Home","title":"Home","text":"function parse_arg(arg::String, value::Any=nothing)\n @match (arg, value) begin\n (\"-l\", lang) => println(\"Language set to $lang\")\n (\"-o\" || \"--optim\", n::Int) where 0 < n <= 5 =>\n println(\"Optimization level set to $n\")\n (\"-o\" || \"--optim\", n::Int) => println(\"Illegal optimization level $(n)!\")\n (\"-h\" || \"--help\", nothing) => println(\"Help!\")\n bad => println(\"Unknown argument: $bad\")\n end\nend","category":"page"},{"location":"#Match-Ranges","page":"Home","title":"Match Ranges","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Borrowing a nice idea from pattern matching in Rust, pattern matching against ranges is also supported:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> function num_match(n)\n @match n begin\n 0 => \"zero\"\n 1 || 2 => \"one or two\"\n 3:10 => \"three to ten\"\n _ => \"something else\"\n end\n end\nnum_match (generic function with 1 method)\n\njulia> num_match(0)\n\"zero\"\n\njulia> num_match(2)\n\"one or two\"\n\njulia> num_match(12)\n\"something else\"\n\njulia> num_match('c')\n\"something else\"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Note that a range can still match another range exactly:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> num_match(3:10)\n\"three to ten\"","category":"page"},{"location":"#Regular-Expressions","page":"Home","title":"Regular Expressions","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"A regular expression can be used as a pattern, and will match any string that satisfies the pattern.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Match.jl used to have complex regular expression handling, permitting the capturing of matched subpatterns. We are considering adding that back again.","category":"page"},{"location":"#Deep-Matching-Against-Arrays","page":"Home","title":"Deep Matching Against Arrays","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Arrays are intrinsic components of Julia. Match allows deep matching against single-dimensional vectors.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Match previously supported multidimensional arrays. If there is sufficient demand, we'll add support for that again.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following examples also demonstrate how Match can be used strictly for its extraction/binding capabilities, by only matching against one pattern.","category":"page"},{"location":"#Extract-first-element,-rest-of-vector","page":"Home","title":"Extract first element, rest of vector","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> @ismatch 1:4 [a,b...]\ntrue\n\njulia> a\n1\n\njulia> b\n2:4","category":"page"},{"location":"#Match-values-at-the-beginning-of-a-vector","page":"Home","title":"Match values at the beginning of a vector","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> @ismatch 1:5 [1,2,a...]\ntrue\n\njulia> a\n3:5","category":"page"},{"location":"#Notes/Gotchas","page":"Home","title":"Notes/Gotchas","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are a few useful things to be aware of when using Match.","category":"page"},{"location":"","page":"Home","title":"Home","text":"if guards need a comma and an `end`:","category":"page"},{"location":"#Bad","page":"Home","title":"Bad","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int if n%2 == 0 end => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\nERROR: syntax: extra token \"if\" after end of expression\n\njulia> _iseven(a) = @match a begin\n n::Int, if n%2 == 0 => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\nERROR: syntax: invalid identifier name =>","category":"page"},{"location":"#Good","page":"Home","title":"Good","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int, if n%2 == 0 end => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\n# methods for generic function _iseven\n_iseven(a) at none:1","category":"page"},{"location":"","page":"Home","title":"Home","text":"It is sometimes easier to use the where syntax for guards:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int where n%2 == 0 => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\n# methods for generic function _iseven\n_iseven(a) at none:1","category":"page"},{"location":"#@match_return-macro","page":"Home","title":"@match_return macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match_return value","category":"page"},{"location":"","page":"Home","title":"Home","text":"Within the result value (to the right of the =>) part of a @match case, you can use the @match_return macro to return a result early, before the end of the block. This is useful if you have a shortcut for computing the result in some cases. You can think of it as a return statement for the @match macro.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Use of this macro anywhere else will result in an error.","category":"page"},{"location":"#@match_fail-macros","page":"Home","title":"@match_fail macros","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match_fail","category":"page"},{"location":"","page":"Home","title":"Home","text":"Inside the result part of a @match case, you can cause the case to fail as if the corresponding pattern did not match. The @match statement will resume attempting to match the following cases. This is useful if you want to write some complex code that would be awkward to express as a guard.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Use of this macro anywhere else will result in an error.","category":"page"},{"location":"#single-case-@match-macro","page":"Home","title":"single-case @match macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match pattern = value","category":"page"},{"location":"","page":"Home","title":"Home","text":"Returns the value if it matches the pattern, and binds any pattern variables. Otherwise, throws MatchFailure.","category":"page"},{"location":"#ismatch-macro","page":"Home","title":"ismatch macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@ismatch value pattern","category":"page"},{"location":"","page":"Home","title":"Home","text":"Returns true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.","category":"page"},{"location":"#Examples","page":"Home","title":"Examples","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Here are a couple of additional examples.","category":"page"},{"location":"#Mathematica-Inspired-Sparse-Array-Constructor","page":"Home","title":"Mathematica-Inspired Sparse Array Constructor","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Contributed by @benkj","category":"page"},{"location":"","page":"Home","title":"Home","text":"I've realized that Match.jl is perfect for creating in Julia an equivalent of SparseArray which I find quite useful in Mathematica.My basic implementation is this:macro sparsearray(size, rule)\n return quote\n _A = spzeros($size...)\n $(push!(rule.args, :(_ => 0)))\n\n for _itr in eachindex(_A)\n _A[_itr] = @match(_itr.I, $rule)\n end\n _A\n end\nendExample:julia> A = @sparsearray (5,5) begin\n (n,m), if n==m+1 end => m\n (n,m), if n==m-1 end => n+10\n (1,5) => 1\n endwhich creates the matrix:julia> full(A)\n5x5 Array{Float64,2}:\n 0.0 11.0 0.0 0.0 1.0\n 1.0 0.0 12.0 0.0 0.0\n 0.0 2.0 0.0 13.0 0.0\n 0.0 0.0 3.0 0.0 14.0\n 0.0 0.0 0.0 4.0 0.0","category":"page"},{"location":"#Matching-Exprs","page":"Home","title":"Matching Exprs","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @match macro can be used to match Julia expressions (Expr objects). One issue is that the internal structure of Expr objects doesn't match their constructor exactly, so one has to put arguments in brackets, as well as capture the typ field of macros.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following function is a nice example of matching expressions. It is used in VideoIO.jl to extract the names of expressions generated by Clang.jl, for later filtering and rewriting.:","category":"page"},{"location":"","page":"Home","title":"Home","text":"extract_name(x) = string(x)\nfunction extract_name(e::Expr)\n @match e begin\n Expr(:type, [_, name, _]) => name\n Expr(:typealias, [name, _]) => name\n Expr(:call, [name, _...]) => name\n Expr(:function, [sig, _...]) => extract_name(sig)\n Expr(:const, [assn, _...]) => extract_name(assn)\n Expr(:(=), [fn, body, _...]) => extract_name(fn)\n Expr(expr_type, _...) => error(\"Can't extract name from \",\n expr_type, \" expression:\\n\",\n \" $e\\n\")\n end\nend","category":"page"},{"location":"#Inspiration","page":"Home","title":"Inspiration","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The following pages on pattern matching in scala provided inspiration for the library:","category":"page"},{"location":"","page":"Home","title":"Home","text":"http://thecodegeneral.wordpress.com/2012/03/25/switch-statements-on-steroids-scala-pattern-matching/\nhttp://java.dzone.com/articles/scala-pattern-matching-case\nhttp://kerflyn.wordpress.com/2011/02/14/playing-with-scalas-pattern-matching/\nhttp://docs.scala-lang.org/tutorials/tour/case-classes.html","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following paper on pattern-matching inspired the automaton approach to code generation:","category":"page"},{"location":"","page":"Home","title":"Home","text":"https://www.cs.tufts.edu/~nr/cs257/archive/norman-ramsey/match.pdf","category":"page"},{"location":"#API-Documentation","page":"Home","title":"API Documentation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Modules = [Match]","category":"page"},{"location":"#Match.MatchFailure","page":"Home","title":"Match.MatchFailure","text":"MatchFailure(value)\n\nConstruct an exception to be thrown when a value fails to match a pattern in the @match macro.\n\n\n\n\n\n","category":"type"},{"location":"#Match.match_fieldnames-Tuple{Type}","page":"Home","title":"Match.match_fieldnames","text":"match_fieldnames(type::Type)\n\nReturn a tuple containing the ordered list of the names (as Symbols) of fields that can be matched either nominally or positionally. This list should exclude synthetic fields that are produced by packages such as Mutts and AutoHashEqualsCached. This function may be overridden by the client to hide fields that should not be matched.\n\n\n\n\n\n","category":"method"},{"location":"#Match.@__match__-Tuple{Any, Any}","page":"Home","title":"Match.@__match__","text":"Usage:\n\n @__match__ value begin\n pattern1 => result1\n pattern2 => result2\n ...\n end\n\nReturn result for the first matching pattern. If there are no matches, throw MatchFailure. This uses a brute-force code gen strategy, essentially a series of if-else statements. It is used for testing purposes, as a reference for correct semantics. Because it is so simple, we have confidence about its correctness.\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@ismatch","page":"Home","title":"Match.@ismatch","text":"@ismatch value pattern\n\nReturn true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.\n\nSee also @match for the syntax of patterns\n\nExamples\n\njulia> struct Point\n x\n y\n end\n\njulia> p = Point(0, 3)\nPoint(0, 3)\n\njulia> if @ismatch p Point(0, y)\n println(\"On the y axis at y = \", y)\n end\nOn the y axis at y = 3\n\nGuarded patterns ought not be used with @ismatch, as you can just use && instead:\n\njulia> if (@ismatch p Point(x, y)) && x < y\n println(\"The point (\", x, \", \", y, \") is in the upper left semiplane\")\n end\nThe point (0, 3) is in the upper left semiplane\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match","page":"Home","title":"Match.@match","text":"@match pattern = value\n@match value begin\n pattern1 => result1\n pattern2 => result2\n ...\nend\n\nMatch a given value to a pattern or series of patterns.\n\nThis macro has two forms. In the first form\n\n@match pattern = value\n\nReturn the value if it matches the pattern, and bind any pattern variables. Otherwise, throw MatchFailure.\n\nIn the second form\n\n@match value begin\n pattern1 => result1\n pattern2 => result2\n ...\nend\n\nReturn result for the first matching pattern. If there are no matches, throw MatchFailure.\n\nTo avoid a MatchFailure exception, write the @match to handle every possible input. One way to do that is to add a final case with the wildcard pattern _.\n\nSee Also\n\nSee also\n\n@match_fail\n@match_return\n@ismatch\n\nPatterns:\n\nThe following syntactic forms can be used in patterns:\n\n_ matches any value\nx (an identifier) matches any value and binds it to the variable x\n1 (a literal value) matches that value\nT(x,y,z) matches structs of type T with fields matching patterns x,y,z\nT(y=p) matches structs of type T whose y field matches pattern p\n(;x,y,z) matches values with fields x,y,z binding to variables x,y,z\n(;x=p) matches values with field x matching pattern p; also binds the field to x\n(;x::T) matches values with field x matching pattern ::T; also binds the field to x\n[x,y,z] matches AbstractArrays with 3 entries matching x,y,z\n(x,y,z) matches Tuples with 3 entries matching x,y,z\n[x,y...,z] matches AbstractArrays with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.\n(x,y...,z) matches Tuples with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.\n::T matches any subtype (isa) of type T\nx::T matches any subtype (isa) of T that also matches pattern x\nx || y matches values which match either pattern x or y (only variables which exist in both branches will be bound)\nx && y matches values which match both patterns x and y\nx, if condition end matches only if condition is true (condition may use any variables that occur earlier in the pattern eg (x, y, z where x + y > z))\nx where condition An alternative form for x, if condition end\nif condition end A boolean computed pattern. x && if condition end is another way of writing x where condition.\nAnything else is treated as a constant and tested for equality\nExpressions can be interpolated in as constants via standard interpolation syntax $(x). Interpolations may use previously bound variables.\n\nPatterns can be nested arbitrarily.\n\nRepeated variables only match if they are equal (isequal). For example (x,x) matches (1,1) but not (1,2).\n\nExamples\n\njulia> value=(1, 2, 3, 4)\n(1, 2, 3, 4)\n\njulia> @match (x, y..., z) = value\n(1, 2, 3, 4)\n\njulia> x\n1\n\njulia> y\n(2, 3)\n\njulia> z\n4\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> f(x) = @match x begin\n _::String => :string\n [a,a,a] => (:all_the_same, a)\n [a,bs...,c] => (:at_least_2, a, bs, c)\n Foo(x, \"foo\") where x > 1 => :foo\n end\nf (generic function with 1 method)\n\njulia> f(\"foo\")\n:string\n\njulia> f([1,1,1])\n(:all_the_same, 1)\n\njulia> f([1,1])\n(:at_least_2, 1, Int64[], 1)\n\njulia> f([1,2,3,4])\n(:at_least_2, 1, [2, 3], 4)\n\njulia> f([1])\nERROR: MatchFailure([1])\n...\n\njulia> f(Foo(2, \"foo\"))\n:foo\n\njulia> f(Foo(0, \"foo\"))\nERROR: MatchFailure(Foo(0, \"foo\"))\n...\n\njulia> f(Foo(2, \"not a foo\"))\nERROR: MatchFailure(Foo(2, \"not a foo\"))\n...\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_fail","page":"Home","title":"Match.@match_fail","text":"@match_fail\n\nInside the result part of a @match case, you can cause the pattern to fail (as if the pattern did not match).\n\nExamples\n\njulia> struct Vect\n x\n y\n end\n\njulia> function norm(v)\n @match v begin\n Vect(x, y) => begin\n if x==0 && y==0\n @match_fail\n end\n l = sqrt(x^2 + y^2)\n Vect(x/l, y/l)\n end\n _ => v\n end\n end\nnorm (generic function with 1 method)\n\njulia> norm(Vect(2, 3))\nVect(0.5547001962252291, 0.8320502943378437)\n\njulia> norm(Vect(0, 0))\nVect(0, 0)\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_fail-Tuple{}","page":"Home","title":"Match.@match_fail","text":"@match_fail\n\nThis statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write\n\n@match_fail\n\nto cause the case to terminate as if its pattern had failed. This permits cases to perform some computation before deciding if the rule \"really\" matched.\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_return","page":"Home","title":"Match.@match_return","text":"@match_return value\n\nInside the result part of a @match case, you can return a given value early.\n\nExamples\n\njulia> struct Vect\n x\n y\n end\n\njulia> function norm(v)\n @match v begin\n Vect(x, y) => begin\n if x==0 && y==0\n @match_return v\n end\n l = sqrt(x^2 + y^2)\n Vect(x/l, y/l)\n end\n _ => v\n end\n end\nnorm (generic function with 1 method)\n\njulia> norm(Vect(2, 3))\nVect(0.5547001962252291, 0.8320502943378437)\n\njulia> norm(Vect(0, 0))\nVect(0, 0)\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_return-Tuple{Any}","page":"Home","title":"Match.@match_return","text":"@match_return value\n\nThis statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write\n\n@match_return value\n\nto terminate the value expression early with success, with the given value.\n\n\n\n\n\n","category":"macro"}] +[{"location":"","page":"Home","title":"Home","text":"CurrentModule = Match","category":"page"},{"location":"#[Match.jl](https://github.com/JuliaServices/Match.jl)-–-Advanced-Pattern-Matching-for-Julia","page":"Home","title":"Match.jl –- Advanced Pattern Matching for Julia","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"This package provides both simple and advanced pattern matching capabilities for Julia. Features include:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Matching against almost any data type with a first-match policy\nDeep matching within data types, tuples, and vectors\nVariable binding within matches\nEfficient code generation via a decision automaton.","category":"page"},{"location":"#Installation","page":"Home","title":"Installation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Use the Julia package manager. Within Julia, do:","category":"page"},{"location":"","page":"Home","title":"Home","text":"Pkg.add(\"Match\")","category":"page"},{"location":"#Usage","page":"Home","title":"Usage","text":"","category":"section"},{"location":"#Simple-pattern-@ismatch-macro","page":"Home","title":"Simple-pattern @ismatch macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @ismatch macro tests if a value patches a given pattern, returning either true if it matches, or false if it does not. When the pattern matches, the variables named in the pattern are bound and can be used.","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> using Match\n\njulia> @ismatch (1, 2) (x, y)\ntrue\n\njulia> x\n1\n\njulia> y\n2","category":"page"},{"location":"#Multi-case-@match-macro","page":"Home","title":"Multi-case @match macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @match macro acts as a pattern-matching switch statement, in which each case has a pattern and a result for when that pattern matches. The first case that matches is the one that computes the result for the @match.","category":"page"},{"location":"","page":"Home","title":"Home","text":"using Match\n@match item begin\n pattern1 => result1\n pattern2 where cond => result2\n pattern3 || pattern4 => result3\n _ => default_result\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Patterns can be values, regular expressions, type checks or constructors, tuples, or arrays. It is possible to supply variables inside a pattern, which will be bound to corresponding values. This and other features are best seen with examples.","category":"page"},{"location":"#Match-Values","page":"Home","title":"Match Values","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The easiest kind of matching to use is simply to match against values:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@match item begin\n 1 => \"one\"\n 2 => \"two\"\n _ => \"Something else...\"\nend","category":"page"},{"location":"","page":"Home","title":"Home","text":"Values can be computed expressions by using interpolation. That is how to use @match with @enums:","category":"page"},{"location":"","page":"Home","title":"Home","text":"@enum Color Red Blue Greed\n@match item begin\n $Red => \"Red\"\n $Blue => \"Blue\"\n $Greed => \"Greed is the color of money\"\n _ => \"Something else...\"\nend","category":"page"},{"location":"#Match-Types","page":"Home","title":"Match Types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Julia already does a great job of this with functions and multiple dispatch, and it is generally be better to use those mechanisms when possible. But it can be done here:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> matchtype(item) = @match item begin\n ::Int => println(\"Integers are awesome!\")\n ::String => println(\"Strings are the best\")\n ::Dict{Int, String} => println(\"Ints for Strings?\")\n ::Dict => println(\"A Dict! Looking up a word?\")\n _ => println(\"Something unexpected\")\n end\n\njulia> matchtype(66)\nIntegers are awesome!\n\njulia> matchtype(\"abc\")\nStrings are the best\n\njulia> matchtype(Dict{Int, String}(1=>\"a\",2=>\"b\"))\nInts for Strings?\n\njulia> matchtype(Dict())\nA Dict! Looking up a word?\n\njulia> matchtype(2.0)\nSomething unexpected","category":"page"},{"location":"#Deep-Matching-of-Composite-Types","page":"Home","title":"Deep Matching of Composite Types","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"One nice feature is the ability to match embedded types, as well as bind variables to components of those types:","category":"page"},{"location":"","page":"Home","title":"Home","text":"struct Address\n street::String\n city::String\n zip::String\nend\n\nstruct Person\n firstname::String\n lastname::String\n address::Address\nend\n\npersoninfo(person) = @match person begin\n Person(\"Julia\", lname, _) => \"Found Julia $lname\"\n Person(fname, \"Julia\", _) => \"$fname Julia was here!\"\n Person(fname, lname,\n Address(_, \"Cambridge\", zip)) => \"$fname $lname lives in zip $zip\"\n Person(_...) => \"Unknown person!\"\nend\n\njulia> personinfo(Person(\"Julia\", \"Robinson\",\n Address(\"450 Serra Mall\", \"Stanford\", \"94305\")))\n\"Found Julia Robinson\"\n\njulia> personinfo(Person(\"Gaston\", \"Julia\",\n Address(\"1 rue Victor Cousin\", \"Paris\", \"75005\")))\n\"Gaston Julia was here!\"\n\njulia> personinfo(Person(\"Edwin\", \"Aldrin\",\n Address(\"350 Memorial Dr\", \"Cambridge\", \"02139\")))\n\"Edwin Aldrin lives in zip 02139\"\n\njulia> personinfo(Person(\"Linus\", \"Pauling\",\n Address(\"1200 E California Blvd\", \"Pasadena\", \"91125\")))\n\"Unknown person!\"","category":"page"},{"location":"#Alternatives-and-Guards","page":"Home","title":"Alternatives and Guards","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Alternatives allow a match against multiple patterns.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Guards allow a conditional match. They are not a standard part of Julia yet, so to get the parser to accept them requires that they are preceded by a comma and end with \"end\":","category":"page"},{"location":"","page":"Home","title":"Home","text":"function parse_arg(arg::String, value::Any=nothing)\n @match (arg, value) begin\n (\"-l\", lang) => println(\"Language set to $lang\")\n (\"-o\" || \"--optim\", n::Int),\n if 0 < n <= 5 end => println(\"Optimization level set to $n\")\n (\"-o\" || \"--optim\", n::Int) => println(\"Illegal optimization level $(n)!\")\n (\"-h\" || \"--help\", nothing) => println(\"Help!\")\n bad => println(\"Unknown argument: $bad\")\n end\nend\n\njulia> parse_arg(\"-l\", \"eng\")\nLanguage set to eng\n\njulia> parse_arg(\"-l\")\nUnknown argument: (\"-l\",nothing)\n\njulia> parse_arg(\"-o\", 4)\nOptimization level set to 4\n\njulia> parse_arg(\"--optim\", 5)\nOptimization level set to 5\n\njulia> parse_arg(\"-o\", 0)\nIllegal optimization level 0!\n\njulia> parse_arg(\"-o\", 1.0)\nUnknown argument: (\"-o\",1.0)\n\njulia> parse_arg(\"-h\")\nHelp!\n\njulia> parse_arg(\"--help\")\nHelp!","category":"page"},{"location":"","page":"Home","title":"Home","text":"The alternative guard syntax pattern where expression can sometimes be easier to use.","category":"page"},{"location":"","page":"Home","title":"Home","text":"function parse_arg(arg::String, value::Any=nothing)\n @match (arg, value) begin\n (\"-l\", lang) => println(\"Language set to $lang\")\n (\"-o\" || \"--optim\", n::Int) where 0 < n <= 5 =>\n println(\"Optimization level set to $n\")\n (\"-o\" || \"--optim\", n::Int) => println(\"Illegal optimization level $(n)!\")\n (\"-h\" || \"--help\", nothing) => println(\"Help!\")\n bad => println(\"Unknown argument: $bad\")\n end\nend","category":"page"},{"location":"#Match-Ranges","page":"Home","title":"Match Ranges","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Borrowing a nice idea from pattern matching in Rust, pattern matching against ranges is also supported:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> function num_match(n)\n @match n begin\n 0 => \"zero\"\n 1 || 2 => \"one or two\"\n 3:10 => \"three to ten\"\n _ => \"something else\"\n end\n end\nnum_match (generic function with 1 method)\n\njulia> num_match(0)\n\"zero\"\n\njulia> num_match(2)\n\"one or two\"\n\njulia> num_match(12)\n\"something else\"\n\njulia> num_match('c')\n\"something else\"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Note that a range can still match another range exactly:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> num_match(3:10)\n\"three to ten\"","category":"page"},{"location":"#Regular-Expressions","page":"Home","title":"Regular Expressions","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"A regular expression can be used as a pattern, and will match any string that satisfies the pattern.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Match.jl used to have complex regular expression handling, permitting the capturing of matched subpatterns. We are considering adding that back again.","category":"page"},{"location":"#Deep-Matching-Against-Arrays","page":"Home","title":"Deep Matching Against Arrays","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Arrays are intrinsic components of Julia. Match allows deep matching against single-dimensional vectors.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Match previously supported multidimensional arrays. If there is sufficient demand, we'll add support for that again.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following examples also demonstrate how Match can be used strictly for its extraction/binding capabilities, by only matching against one pattern.","category":"page"},{"location":"#Extract-first-element,-rest-of-vector","page":"Home","title":"Extract first element, rest of vector","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> @ismatch 1:4 [a,b...]\ntrue\n\njulia> a\n1\n\njulia> b\n2:4","category":"page"},{"location":"#Match-values-at-the-beginning-of-a-vector","page":"Home","title":"Match values at the beginning of a vector","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> @ismatch 1:5 [1,2,a...]\ntrue\n\njulia> a\n3:5","category":"page"},{"location":"#Notes/Gotchas","page":"Home","title":"Notes/Gotchas","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"There are a few useful things to be aware of when using Match.","category":"page"},{"location":"","page":"Home","title":"Home","text":"if guards need a comma and an `end`:","category":"page"},{"location":"#Bad","page":"Home","title":"Bad","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int if n%2 == 0 end => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\nERROR: syntax: extra token \"if\" after end of expression\n\njulia> _iseven(a) = @match a begin\n n::Int, if n%2 == 0 => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\nERROR: syntax: invalid identifier name =>","category":"page"},{"location":"#Good","page":"Home","title":"Good","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int, if n%2 == 0 end => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\n# methods for generic function _iseven\n_iseven(a) at none:1","category":"page"},{"location":"","page":"Home","title":"Home","text":"It is sometimes easier to use the where syntax for guards:","category":"page"},{"location":"","page":"Home","title":"Home","text":"julia> _iseven(a) = @match a begin\n n::Int where n%2 == 0 => println(\"$n is even\")\n m::Int => println(\"$m is odd\")\n end\n# methods for generic function _iseven\n_iseven(a) at none:1","category":"page"},{"location":"#@match_return-macro","page":"Home","title":"@match_return macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match_return value","category":"page"},{"location":"","page":"Home","title":"Home","text":"Within the result value (to the right of the =>) part of a @match case, you can use the @match_return macro to return a result early, before the end of the block. This is useful if you have a shortcut for computing the result in some cases. You can think of it as a return statement for the @match macro.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Use of this macro anywhere else will result in an error.","category":"page"},{"location":"#@match_fail-macros","page":"Home","title":"@match_fail macros","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match_fail","category":"page"},{"location":"","page":"Home","title":"Home","text":"Inside the result part of a @match case, you can cause the case to fail as if the corresponding pattern did not match. The @match statement will resume attempting to match the following cases. This is useful if you want to write some complex code that would be awkward to express as a guard.","category":"page"},{"location":"","page":"Home","title":"Home","text":"Use of this macro anywhere else will result in an error.","category":"page"},{"location":"#single-case-@match-macro","page":"Home","title":"single-case @match macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@match pattern = value","category":"page"},{"location":"","page":"Home","title":"Home","text":"Returns the value if it matches the pattern, and binds any pattern variables. Otherwise, throws MatchFailure.","category":"page"},{"location":"#ismatch-macro","page":"Home","title":"ismatch macro","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"@ismatch value pattern","category":"page"},{"location":"","page":"Home","title":"Home","text":"Returns true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.","category":"page"},{"location":"#Examples","page":"Home","title":"Examples","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Here are a couple of additional examples.","category":"page"},{"location":"#Mathematica-Inspired-Sparse-Array-Constructor","page":"Home","title":"Mathematica-Inspired Sparse Array Constructor","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"Contributed by @benkj","category":"page"},{"location":"","page":"Home","title":"Home","text":"I've realized that Match.jl is perfect for creating in Julia an equivalent of SparseArray which I find quite useful in Mathematica.My basic implementation is this:macro sparsearray(size, rule)\n return quote\n _A = spzeros($size...)\n $(push!(rule.args, :(_ => 0)))\n\n for _itr in eachindex(_A)\n _A[_itr] = @match(_itr.I, $rule)\n end\n _A\n end\nendExample:julia> A = @sparsearray (5,5) begin\n (n,m), if n==m+1 end => m\n (n,m), if n==m-1 end => n+10\n (1,5) => 1\n endwhich creates the matrix:julia> full(A)\n5x5 Array{Float64,2}:\n 0.0 11.0 0.0 0.0 1.0\n 1.0 0.0 12.0 0.0 0.0\n 0.0 2.0 0.0 13.0 0.0\n 0.0 0.0 3.0 0.0 14.0\n 0.0 0.0 0.0 4.0 0.0","category":"page"},{"location":"#Matching-Exprs","page":"Home","title":"Matching Exprs","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The @match macro can be used to match Julia expressions (Expr objects). One issue is that the internal structure of Expr objects doesn't match their constructor exactly, so one has to put arguments in brackets, as well as capture the typ field of macros.","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following function is a nice example of matching expressions. It is used in VideoIO.jl to extract the names of expressions generated by Clang.jl, for later filtering and rewriting.:","category":"page"},{"location":"","page":"Home","title":"Home","text":"extract_name(x) = string(x)\nfunction extract_name(e::Expr)\n @match e begin\n Expr(:type, [_, name, _]) => name\n Expr(:typealias, [name, _]) => name\n Expr(:call, [name, _...]) => name\n Expr(:function, [sig, _...]) => extract_name(sig)\n Expr(:const, [assn, _...]) => extract_name(assn)\n Expr(:(=), [fn, body, _...]) => extract_name(fn)\n Expr(expr_type, _...) => error(\"Can't extract name from \",\n expr_type, \" expression:\\n\",\n \" $e\\n\")\n end\nend","category":"page"},{"location":"#Inspiration","page":"Home","title":"Inspiration","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"The following pages on pattern matching in scala provided inspiration for the library:","category":"page"},{"location":"","page":"Home","title":"Home","text":"http://thecodegeneral.wordpress.com/2012/03/25/switch-statements-on-steroids-scala-pattern-matching/\nhttp://java.dzone.com/articles/scala-pattern-matching-case\nhttp://kerflyn.wordpress.com/2011/02/14/playing-with-scalas-pattern-matching/\nhttp://docs.scala-lang.org/tutorials/tour/case-classes.html","category":"page"},{"location":"","page":"Home","title":"Home","text":"The following paper on pattern-matching inspired the automaton approach to code generation:","category":"page"},{"location":"","page":"Home","title":"Home","text":"https://www.cs.tufts.edu/~nr/cs257/archive/norman-ramsey/match.pdf","category":"page"},{"location":"#API-Documentation","page":"Home","title":"API Documentation","text":"","category":"section"},{"location":"","page":"Home","title":"Home","text":"","category":"page"},{"location":"","page":"Home","title":"Home","text":"Modules = [Match]","category":"page"},{"location":"#Match.MatchFailure","page":"Home","title":"Match.MatchFailure","text":"MatchFailure(value)\n\nConstruct an exception to be thrown when a value fails to match a pattern in the @match macro.\n\n\n\n\n\n","category":"type"},{"location":"#Match.match_fieldnames-Tuple{Type}","page":"Home","title":"Match.match_fieldnames","text":"match_fieldnames(type::Type)\n\nReturn a tuple containing the ordered list of the names (as Symbols) of fields that can be matched either nominally or positionally. This list should exclude synthetic fields that are produced by packages such as Mutts and AutoHashEqualsCached. This function may be overridden by the client to hide fields that should not be matched.\n\n\n\n\n\n","category":"method"},{"location":"#Match.@__match__-Tuple{Any, Any}","page":"Home","title":"Match.@__match__","text":"Usage:\n\n @__match__ value begin\n pattern1 => result1\n pattern2 => result2\n ...\n end\n\nReturn result for the first matching pattern. If there are no matches, throw MatchFailure. This uses a brute-force code gen strategy, essentially a series of if-else statements. It is used for testing purposes, as a reference for correct semantics. Because it is so simple, we have confidence about its correctness.\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@ismatch","page":"Home","title":"Match.@ismatch","text":"@ismatch value pattern\n\nReturn true if value matches pattern, false otherwise. When returning true, binds the pattern variables in the enclosing scope.\n\nSee also @match for the syntax of patterns\n\nExamples\n\njulia> struct Point\n x\n y\n end\n\njulia> p = Point(0, 3)\nPoint(0, 3)\n\njulia> if @ismatch p Point(0, y)\n println(\"On the y axis at y = \", y)\n end\nOn the y axis at y = 3\n\nGuarded patterns ought not be used with @ismatch, as you can just use && instead:\n\njulia> if (@ismatch p Point(x, y)) && x < y\n println(\"The point (\", x, \", \", y, \") is in the upper left semiplane\")\n end\nThe point (0, 3) is in the upper left semiplane\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match","page":"Home","title":"Match.@match","text":"@match pattern = value\n@match value begin\n pattern1 => result1\n pattern2 => result2\n ...\nend\n\nMatch a given value to a pattern or series of patterns.\n\nThis macro has two forms. In the first form\n\n@match pattern = value\n\nReturn the value if it matches the pattern, and bind any pattern variables. Otherwise, throw MatchFailure.\n\nIn the second form\n\n@match value begin\n pattern1 => result1\n pattern2 => result2\n ...\nend\n\nReturn result for the first matching pattern. If there are no matches, throw MatchFailure.\n\nTo avoid a MatchFailure exception, write the @match to handle every possible input. One way to do that is to add a final case with the wildcard pattern _.\n\nSee Also\n\nSee also\n\n@match_fail\n@match_return\n@ismatch\n\nPatterns:\n\nThe following syntactic forms can be used in patterns:\n\n_ matches any value\nx (an identifier) matches any value and binds it to the variable x\nT(x,y,z) matches structs of type T with fields matching patterns x,y,z\nT(y=p) matches structs of type T whose y field matches pattern p\n(;x,y,z) matches values with fields x,y,z binding to variables x,y,z\n(;x=p) matches values with field x matching pattern p; also binds the field to x\n(;x::T) matches values with field x matching pattern ::T; also binds the field to x\n[x,y,z] matches AbstractArrays with 3 entries matching x,y,z\n(x,y,z) matches Tuples with 3 entries matching x,y,z\n[x,y...,z] matches AbstractArrays with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.\n(x,y...,z) matches Tuples with at least 2 entries, where x matches the first entry, z matches the last entry and y matches the remaining entries.\n::T matches any subtype (isa) of type T\nx::T matches any subtype (isa) of T that also matches pattern x\nx || y matches values which match either pattern x or y (only variables which exist in both branches will be bound)\nx && y matches values which match both patterns x and y\nx, if condition end matches only if condition is true (condition may use any variables that occur earlier in the pattern eg (x, y, z where x + y > z))\nx where condition An alternative form for x, if condition end\nif condition end A boolean computed pattern. x && if condition end is another way of writing x where condition.\n1 (a literal value) matches that value using isequal\nr\"[a-z]*\" (a regular expression) matches strings that match the regular expression\n1:10 (a constant range) matches values in that range\nExpressions can be interpolated in as constants via standard interpolation syntax $(x). Interpolations may use previously bound variables.\n\nPatterns can be nested arbitrarily.\n\nRepeated variables only match if they are equal (isequal). For example (x,x) matches (1,1) but not (1,2).\n\nExamples\n\njulia> value=(1, 2, 3, 4)\n(1, 2, 3, 4)\n\njulia> @match (x, y..., z) = value\n(1, 2, 3, 4)\n\njulia> x\n1\n\njulia> y\n(2, 3)\n\njulia> z\n4\n\njulia> struct Foo\n x::Int64\n y::String\n end\n\njulia> f(x) = @match x begin\n _::String => :string\n [a,a,a] => (:all_the_same, a)\n [a,bs...,c] => (:at_least_2, a, bs, c)\n Foo(x, \"foo\") where x > 1 => :foo\n end\nf (generic function with 1 method)\n\njulia> f(\"foo\")\n:string\n\njulia> f([1,1,1])\n(:all_the_same, 1)\n\njulia> f([1,1])\n(:at_least_2, 1, Int64[], 1)\n\njulia> f([1,2,3,4])\n(:at_least_2, 1, [2, 3], 4)\n\njulia> f([1])\nERROR: MatchFailure([1])\n...\n\njulia> f(Foo(2, \"foo\"))\n:foo\n\njulia> f(Foo(0, \"foo\"))\nERROR: MatchFailure(Foo(0, \"foo\"))\n...\n\njulia> f(Foo(2, \"not a foo\"))\nERROR: MatchFailure(Foo(2, \"not a foo\"))\n...\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_fail","page":"Home","title":"Match.@match_fail","text":"@match_fail\n\nInside the result part of a @match case, you can cause the pattern to fail (as if the pattern did not match).\n\nExamples\n\njulia> struct Vect\n x\n y\n end\n\njulia> function norm(v)\n @match v begin\n Vect(x, y) => begin\n if x==0 && y==0\n @match_fail\n end\n l = sqrt(x^2 + y^2)\n Vect(x/l, y/l)\n end\n _ => v\n end\n end\nnorm (generic function with 1 method)\n\njulia> norm(Vect(2, 3))\nVect(0.5547001962252291, 0.8320502943378437)\n\njulia> norm(Vect(0, 0))\nVect(0, 0)\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_fail-Tuple{}","page":"Home","title":"Match.@match_fail","text":"@match_fail\n\nThis statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write\n\n@match_fail\n\nto cause the case to terminate as if its pattern had failed. This permits cases to perform some computation before deciding if the rule \"really\" matched.\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_return","page":"Home","title":"Match.@match_return","text":"@match_return value\n\nInside the result part of a @match case, you can return a given value early.\n\nExamples\n\njulia> struct Vect\n x\n y\n end\n\njulia> function norm(v)\n @match v begin\n Vect(x, y) => begin\n if x==0 && y==0\n @match_return v\n end\n l = sqrt(x^2 + y^2)\n Vect(x/l, y/l)\n end\n _ => v\n end\n end\nnorm (generic function with 1 method)\n\njulia> norm(Vect(2, 3))\nVect(0.5547001962252291, 0.8320502943378437)\n\njulia> norm(Vect(0, 0))\nVect(0, 0)\n\n\n\n\n\n","category":"macro"},{"location":"#Match.@match_return-Tuple{Any}","page":"Home","title":"Match.@match_return","text":"@match_return value\n\nThis statement permits early-exit from the value of a @match case. The programmer may write the value as a begin ... end and then, within the value, the programmer may write\n\n@match_return value\n\nto terminate the value expression early with success, with the given value.\n\n\n\n\n\n","category":"macro"}] }