Algebraic data types: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
Line 14: Line 14:
=={{header|Bracmat}}==
=={{header|Bracmat}}==


<lang bracmat>( ( balance
<syntaxhighlight lang=bracmat>( ( balance
= a x b y c zd
= a x b y c zd
. !arg
. !arg
Line 60: Line 60:
| insert$!arg
| insert$!arg
)
)
);</lang>
);</syntaxhighlight>


Test:
Test:
<lang bracmat>( ( it allows for terse code which is easy to read
<syntaxhighlight lang=bracmat>( ( it allows for terse code which is easy to read
, and can represent the algorithm directly
, and can represent the algorithm directly
.
.
Line 71: Line 71:
& lst$tree
& lst$tree
& done
& done
);</lang>
);</syntaxhighlight>


Output:
Output:
<lang bracmat>(tree=
<syntaxhighlight lang=bracmat>(tree=
B
B
. ( B
. ( B
Line 95: Line 95:
)
)
)
)
);</lang>
);</syntaxhighlight>


=={{header|C++}}==
=={{header|C++}}==
Line 102: Line 102:
C++ templates have a robust pattern matching facility, with some warts - for example, nested templates cannot be fully specialized, so we must use a dummy template parameter. This implementation uses C++17 deduced template parameters for genericity.
C++ templates have a robust pattern matching facility, with some warts - for example, nested templates cannot be fully specialized, so we must use a dummy template parameter. This implementation uses C++17 deduced template parameters for genericity.


<lang cpp>enum Color { R, B };
<syntaxhighlight lang=cpp>enum Color { R, B };
template<Color, class, auto, class> struct T;
template<Color, class, auto, class> struct T;
struct E;
struct E;
Line 146: Line 146:
int main() {
int main() {
print<insert_t<1, insert_t<2, insert_t<0, insert_t<4, E>>>>>();
print<insert_t<1, insert_t<2, insert_t<0, insert_t<4, E>>>>>();
}</lang>
}</syntaxhighlight>


===Run time===
===Run time===
Although C++ has structured bindings and pattern matching through function overloading, it is not yet possible to use them together so we must match the structure of the tree being rebalanced separately from decomposing it into its elements. A further issue is that function overloads are not ordered, so to avoid ambiguity we must explicitly reject any (ill-formed) trees that would match more than one case during rebalance.
Although C++ has structured bindings and pattern matching through function overloading, it is not yet possible to use them together so we must match the structure of the tree being rebalanced separately from decomposing it into its elements. A further issue is that function overloads are not ordered, so to avoid ambiguity we must explicitly reject any (ill-formed) trees that would match more than one case during rebalance.


<lang cpp>#include <memory>
<syntaxhighlight lang=cpp>#include <memory>
#include <variant>
#include <variant>


Line 253: Line 253:
t = insert(std::string{argv[i]}, std::move(t));
t = insert(std::string{argv[i]}, std::move(t));
print(t);
print(t);
}</lang>
}</syntaxhighlight>


=={{header|C sharp}}==
=={{header|C sharp}}==
Translation of several
Translation of several
{{works with|C sharp|8}}
{{works with|C sharp|8}}
<lang csharp>using System;
<syntaxhighlight lang=csharp>using System;


class Tree
class Tree
Line 306: Line 306:
_ => this
_ => this
};
};
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 356: Line 356:
{{libheader|toadstool}}
{{libheader|toadstool}}


<lang lisp>(mapc #'use-package '(#:toadstool #:toadstool-system))
<syntaxhighlight lang=lisp>(mapc #'use-package '(#:toadstool #:toadstool-system))
(defstruct (red-black-tree (:constructor tree (color left val right)))
(defstruct (red-black-tree (:constructor tree (color left val right)))
color left val right)
color left val right)
Line 394: Line 394:
(defun insert (x s)
(defun insert (x s)
(toad-ecase1 (%insert x s)
(toad-ecase1 (%insert x s)
((tree t a y b) (tree 'black a y b))))</lang>
((tree t a y b) (tree 'black a y b))))</syntaxhighlight>


=={{header|E}}==
=={{header|E}}==
Line 441: Line 441:


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
<lang scheme>
<syntaxhighlight lang=scheme>
;; code adapted from Racket and Common Lisp
;; code adapted from Racket and Common Lisp
;; Illustrates matching on structures
;; Illustrates matching on structures
Line 469: Line 469:
(match (ins x s) [(N _ l v r) (N '⚫️ l v r)]))
(match (ins x s) [(N _ l v r) (N '⚫️ l v r)]))
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<lang scheme>
<syntaxhighlight lang=scheme>
(define (t-show n (depth 0))
(define (t-show n (depth 0))
(when (!eq? 'empty n)
(when (!eq? 'empty n)
Line 480: Line 480:
(define T (for/fold [t 'empty] ([i 32]) (insert (random 100) t)))
(define T (for/fold [t 'empty] ([i 32]) (insert (random 100) t)))
(t-show T)
(t-show T)
</syntaxhighlight>
</lang>
<small>
<small>
<pre>
<pre>
Line 515: Line 515:
{{trans|Erlang}}
{{trans|Erlang}}
But, it changed an API into the Elixir style.
But, it changed an API into the Elixir style.
<lang elixir>defmodule RBtree do
<syntaxhighlight lang=elixir>defmodule RBtree do
def find(nil, _), do: :not_found
def find(nil, _), do: :not_found
def find({ key, value, _, _, _ }, key), do: { :found, { key, value } }
def find({ key, value, _, _, _ }, key), do: { :found, { key, value } }
Line 557: Line 557:
|> RBtree.insert(6,-1) |> IO.inspect
|> RBtree.insert(6,-1) |> IO.inspect
|> RBtree.insert(7,0) |> IO.inspect
|> RBtree.insert(7,0) |> IO.inspect
|> RBtree.find(4) |> IO.inspect</lang>
|> RBtree.find(4) |> IO.inspect</syntaxhighlight>


{{out}}
{{out}}
Line 580: Line 580:
The <code>pcase</code> macro was added in Emacs 24.1. It's auto-loaded, so there's no need to add <code>(require 'pcase)</code> to your code.
The <code>pcase</code> macro was added in Emacs 24.1. It's auto-loaded, so there's no need to add <code>(require 'pcase)</code> to your code.


<lang lisp>(defun rbt-balance (tree)
<syntaxhighlight lang=lisp>(defun rbt-balance (tree)
(pcase tree
(pcase tree
(`(B (R (R ,a ,x ,b) ,y ,c) ,z ,d) `(R (B ,a ,x ,b) ,y (B ,c ,z ,d)))
(`(B (R (R ,a ,x ,b) ,y ,c) ,z ,d) `(R (B ,a ,x ,b) ,y (B ,c ,z ,d)))
Line 607: Line 607:
(dotimes (i 16)
(dotimes (i 16)
(setq s (rbt-insert (1+ i) s)))
(setq s (rbt-insert (1+ i) s)))
(pp s))</lang>
(pp s))</syntaxhighlight>
Output:
Output:


Line 639: Line 639:


The code used here is extracted from [https://gist.github.com/mjn/2648040 Mark Northcott's GitHubGist].
The code used here is extracted from [https://gist.github.com/mjn/2648040 Mark Northcott's GitHubGist].
<lang erlang>
<syntaxhighlight lang=erlang>
-module(rbtree).
-module(rbtree).
-export([insert/3, find/2]).
-export([insert/3, find/2]).
Line 679: Line 679:
balance(T) ->
balance(T) ->
T.
T.
</syntaxhighlight>
</lang>


Output:
Output:
Line 714: Line 714:


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
<lang fsharp>
<syntaxhighlight lang=fsharp>
// Pattern Matching. Nigel Galloway: January 15th., 2021
// Pattern Matching. Nigel Galloway: January 15th., 2021
type colour= |Red |Black
type colour= |Red |Black
Line 727: Line 727:
|N(i,g,e,l) as node->if item>l then repair(i,g,insert e,l) elif item<l then repair(i,insert g,e,l) else node
|N(i,g,e,l) as node->if item>l then repair(i,g,insert e,l) elif item<l then repair(i,insert g,e,l) else node
match insert rbt with N(_,g,e,l)->N(Black,g,e,l) |_->Empty
match insert rbt with N(_,g,e,l)->N(Black,g,e,l) |_->Empty
</syntaxhighlight>
</lang>
=={{header|Go}}==
=={{header|Go}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
Line 734: Line 734:


However, pattern matching on interfaces (via the type switch statement and type assertions) is limited to matching the implementing type and so the balance() method is not very pleasant.
However, pattern matching on interfaces (via the type switch statement and type assertions) is limited to matching the implementing type and so the balance() method is not very pleasant.
<lang go>package main
<syntaxhighlight lang=go>package main


import "fmt"
import "fmt"
Line 851: Line 851:
}
}
fmt.Println(tr)
fmt.Println(tr)
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 860: Line 860:
=={{header|Haskell}}==
=={{header|Haskell}}==


<lang haskell>data Color = R | B
<syntaxhighlight lang=haskell>data Color = R | B
data Tree a = E | T Color (Tree a) a (Tree a)
data Tree a = E | T Color (Tree a) a (Tree a)


Line 877: Line 877:
| x > y = balance col a y (ins b)
| x > y = balance col a y (ins b)
| otherwise = s
| otherwise = s
T _ a y b = ins s</lang>
T _ a y b = ins s</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==
Line 886: Line 886:
The following code represents a best effort translation of the current Haskell implementation of this task:
The following code represents a best effort translation of the current Haskell implementation of this task:


<lang J>insert=:{{
<syntaxhighlight lang=J>insert=:{{
'R';'';y;a:
'R';'';y;a:
:
:
Line 924: Line 924:
if. 'R'=wwC do. 'R';('B';e;K;<we);wK;<'B';wwe;wwK;<www return. end. end. end. end.
if. 'R'=wwC do. 'R';('B';e;K;<we);wK;<'B';wwe;wwK;<www return. end. end. end. end.
y
y
}}</lang>
}}</syntaxhighlight>


Example use:
Example use:


<lang J> 3 insert 2 insert 5
<syntaxhighlight lang=J> 3 insert 2 insert 5
┌─┬───────┬─┬───────┐
┌─┬───────┬─┬───────┐
│R│┌─┬┬─┬┐│3│┌─┬┬─┬┐│
│R│┌─┬┬─┬┐│3│┌─┬┬─┬┐│
│ ││B││2│││ ││B││5│││
│ ││B││2│││ ││B││5│││
│ │└─┴┴─┴┘│ │└─┴┴─┴┘│
│ │└─┴┴─┴┘│ │└─┴┴─┴┘│
└─┴───────┴─┴───────┘</lang>
└─┴───────┴─┴───────┘</syntaxhighlight>


Note that by convention we treat the root node as black. This approach always labels it with 'R' which we ignore. However, if we wish to validate these trees, we must account for the discrepancy.
Note that by convention we treat the root node as black. This approach always labels it with 'R' which we ignore. However, if we wish to validate these trees, we must account for the discrepancy.


<lang J>NB. always treat root of tree as black
<syntaxhighlight lang=J>NB. always treat root of tree as black
validate=: {{
validate=: {{
if. 0=#y do. 1 return. end.
if. 0=#y do. 1 return. end.
Line 954: Line 954:
b=. check w
b=. check w
(*a)*(a=b)*b+'B'=C
(*a)*(a=b)*b+'B'=C
}}</lang>
}}</syntaxhighlight>


Here, validate returns the effective "black depth" of the tree (treating the root node as black and treating empty nodes as black), or 0 if the tree is not balanced properly.
Here, validate returns the effective "black depth" of the tree (treating the root node as black and treating empty nodes as black), or 0 if the tree is not balanced properly.
Line 960: Line 960:
For example:
For example:


<lang J> ?.~20
<syntaxhighlight lang=J> ?.~20
14 18 12 16 5 1 3 0 6 13 9 8 15 17 2 10 7 4 19 11
14 18 12 16 5 1 3 0 6 13 9 8 15 17 2 10 7 4 19 11
insert/?.~20
insert/?.~20
Line 975: Line 975:
└─┴──────────────────────────────────────────────────────────────────────┴──┴────────────────────────────────────────────────────────────────────────┘
└─┴──────────────────────────────────────────────────────────────────────┴──┴────────────────────────────────────────────────────────────────────────┘
validate insert/?.~20
validate insert/?.~20
4</lang>
4</syntaxhighlight>


Finally a caution: red black trees exhibit poor cache coherency. In many (perhaps most or all) cases an amortized hierarchical linear sort mechanism will perform better than a red black tree implementation. (And that characteristic is especially true of this particular implementation.)
Finally a caution: red black trees exhibit poor cache coherency. In many (perhaps most or all) cases an amortized hierarchical linear sort mechanism will perform better than a red black tree implementation. (And that characteristic is especially true of this particular implementation.)
Line 990: Line 990:


'''bindings.jq'''
'''bindings.jq'''
<lang jq># bindings($x) attempts to match . and $x structurally on the
<syntaxhighlight lang=jq># bindings($x) attempts to match . and $x structurally on the
# assumption that . is free of JSON objects, and that any objects in
# assumption that . is free of JSON objects, and that any objects in
# $x will have distinct, singleton keys that are to be interpreted as
# $x will have distinct, singleton keys that are to be interpreted as
Line 1,017: Line 1,017:
end
end
else null
else null
end ;</lang>
end ;</syntaxhighlight>


'''pattern-matching.jq'''
'''pattern-matching.jq'''
<lang jq>include "bindings" {search: "."};
<syntaxhighlight lang=jq>include "bindings" {search: "."};


def E: []; # the empty node
def E: []; # the empty node
Line 1,061: Line 1,061:
reduce range(0; $n) as $i (E; insert($i));
reduce range(0; $n) as $i (E; insert($i));


task(16) | pp</lang>
task(16) | pp</syntaxhighlight>
{{out}}
{{out}}
For brevity and perhaps visual appeal, the output from jq has been trimmed as per the following invocation:
For brevity and perhaps visual appeal, the output from jq has been trimmed as per the following invocation:
<lang sh>jq -n -f pattern-matching.jq | grep -v '[][]' | tr -d ',"'</lang>
<syntaxhighlight lang=sh>jq -n -f pattern-matching.jq | grep -v '[][]' | tr -d ',"'</syntaxhighlight>
<pre>
<pre>
Line 1,101: Line 1,101:
=={{header|Julia}}==
=={{header|Julia}}==
Julia's multiple dispatch model is based on the types of a function's arguments, but does not look deeper into the function's array arguments for the types of their contents. Therefore we do multi-dispatch on the balance function but then use an if statement within the multiply dispatched functions to further match based on argument vector contents.
Julia's multiple dispatch model is based on the types of a function's arguments, but does not look deeper into the function's array arguments for the types of their contents. Therefore we do multi-dispatch on the balance function but then use an if statement within the multiply dispatched functions to further match based on argument vector contents.
<lang julia>import Base.length
<syntaxhighlight lang=julia>import Base.length


abstract type AbstractColoredNode end
abstract type AbstractColoredNode end
Line 1,169: Line 1,169:


testRB()
testRB()
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
[B, [R, [B, [R, E, 1, E], 2, [R, E, 3, E]], 4, [B, E, 6, E]], 14, [B, E, 18, E]]]
[B, [R, [B, [R, E, 1, E], 2, [R, E, 3, E]], 4, [B, E, 6, E]], 14, [B, E, 18, E]]]
Line 1,179: Line 1,179:
Whilst Kotlin supports algebraic data types (via 'sealed classes') and destructuring of data classes, pattern matching on them (via the 'when' expression) is currently limited to matching the type. Consequently the balance() function is not very pretty!
Whilst Kotlin supports algebraic data types (via 'sealed classes') and destructuring of data classes, pattern matching on them (via the 'when' expression) is currently limited to matching the type. Consequently the balance() function is not very pretty!
<lang scala>// version 1.1.51
<syntaxhighlight lang=scala>// version 1.1.51


import Color.*
import Color.*
Line 1,262: Line 1,262:
}
}
println(tree)
println(tree)
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,270: Line 1,270:
=={{header|Nim}}==
=={{header|Nim}}==
{{libheader|fusion/matching}}
{{libheader|fusion/matching}}
<lang nim>import fusion/matching
<syntaxhighlight lang=nim>import fusion/matching
{.experimental: "caseStmtMacros".}
{.experimental: "caseStmtMacros".}


Line 1,314: Line 1,314:
proc ins(t: var RBTree[T], x: T) = insImpl[T](t, x)
proc ins(t: var RBTree[T], x: T) = insImpl[T](t, x)
tt.ins(xx)
tt.ins(xx)
tt.colour = Black</lang>
tt.colour = Black</syntaxhighlight>


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml>
<syntaxhighlight lang=ocaml>
type color = R | B
type color = R | B
type 'a tree = E | T of color * 'a tree * 'a * 'a tree
type 'a tree = E | T of color * 'a tree * 'a * 'a tree
Line 1,342: Line 1,342:
in let T (_,a,y,b) = ins s
in let T (_,a,y,b) = ins s
in T (B,a,y,b)
in T (B,a,y,b)
</syntaxhighlight>
</lang>


=={{header|Oz}}==
=={{header|Oz}}==
Line 1,350: Line 1,350:
To match multiple variables at once, we create temporary tuples with "#".
To match multiple variables at once, we create temporary tuples with "#".


<lang oz>fun {Balance Col A X B}
<syntaxhighlight lang=oz>fun {Balance Col A X B}
case Col#A#X#B
case Col#A#X#B
of b#t(r t(r A X B) Y C )#Z#D then t(r t(b A X B) Y t(b C Z D))
of b#t(r t(r A X B) Y C )#Z#D then t(r t(b A X B) Y t(b C Z D))
Line 1,373: Line 1,373:
in
in
t(b A Y B)
t(b A Y B)
end</lang>
end</syntaxhighlight>


=={{header|Perl}}==
=={{header|Perl}}==
Line 1,386: Line 1,386:
Each of the single letter variables declared right after $balanced, match an instance of $balanced, and if they succeed, store the result into the %+ hash.
Each of the single letter variables declared right after $balanced, match an instance of $balanced, and if they succeed, store the result into the %+ hash.


<lang perl>#!perl
<syntaxhighlight lang=perl>#!perl
use 5.010;
use 5.010;
use strict;
use strict;
Line 1,451: Line 1,451:
}
}
print "Done\n";
print "Done\n";
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>Tree: <B,_,9,_>.
<pre>Tree: <B,_,9,_>.
Line 1,468: Line 1,468:
There is no formal support for this sort of thing in Phix, but that's not to say that whipping
There is no formal support for this sort of thing in Phix, but that's not to say that whipping
something up is likely to be particularly difficult, so let's give it a whirl.
something up is likely to be particularly difficult, so let's give it a whirl.
<!--<lang Phix>(phixonline)-->
<!--<syntaxhighlight lang=Phix>(phixonline)-->
<span style="color: #000080;font-style:italic;">--
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\Pattern_matching.exw
-- demo\rosetta\Pattern_matching.exw
Line 1,595: Line 1,595:
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</lang>-->
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 1,612: Line 1,612:
=={{header|Picat}}==
=={{header|Picat}}==
{{trans|Prolog}}
{{trans|Prolog}}
<lang Picat>main =>
<syntaxhighlight lang=Picat>main =>
T = e,
T = e,
foreach (X in 1..10)
foreach (X in 1..10)
Line 1,642: Line 1,642:
printf("%*w[%w]\n",Indent,C,Y),
printf("%*w[%w]\n",Indent,C,Y),
output(B,Indent+6).
output(B,Indent+6).
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,670: Line 1,670:
=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
{{trans|Prolog}}
{{trans|Prolog}}
<lang PicoLisp>(be color (R))
<syntaxhighlight lang=PicoLisp>(be color (R))
(be color (B))
(be color (B))


Line 1,704: Line 1,704:


(be insert (@X @S (T B @A @Y @B))
(be insert (@X @S (T B @A @Y @B))
(ins @X @S (T @ @A @Y @B)) )</lang>
(ins @X @S (T @ @A @Y @B)) )</syntaxhighlight>
Test:
Test:
<lang PicoLisp>: (? (insert 2 E @A) (insert 1 @A @B) (insert 3 @B @C))
<syntaxhighlight lang=PicoLisp>: (? (insert 2 E @A) (insert 1 @A @B) (insert 3 @B @C))
@A=(T B E 2 E) @B=(T B (T R E 1 E) 2 E) @C=(T B (T R E 1 E) 2 (T R E 3 E))
@A=(T B E 2 E) @B=(T B (T R E 1 E) 2 E) @C=(T B (T R E 1 E) 2 (T R E 3 E))
-> NIL</lang>
-> NIL</syntaxhighlight>


=={{header|Prolog}}==
=={{header|Prolog}}==
Line 1,739: Line 1,739:
Structural pattern matching was added to Python in version 3.10.
Structural pattern matching was added to Python in version 3.10.


<lang python>from __future__ import annotations
<syntaxhighlight lang=python>from __future__ import annotations
from enum import Enum
from enum import Enum
from typing import NamedTuple
from typing import NamedTuple
Line 1,829: Line 1,829:
if __name__ == "__main__":
if __name__ == "__main__":
main()
main()
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 1,871: Line 1,871:
{{trans|OCaml}}
{{trans|OCaml}}


<lang racket>
<syntaxhighlight lang=racket>
#lang racket
#lang racket


Line 1,904: Line 1,904:


(visualize (for/fold ([t 'empty]) ([i 16]) (insert i t)))
(visualize (for/fold ([t 'empty]) ([i 16]) (insert i t)))
</syntaxhighlight>
</lang>


<pre>
<pre>
Line 1,929: Line 1,929:
{{works with|rakudo|2016.11}}
{{works with|rakudo|2016.11}}
Raku doesn't have algebraic data types (yet), but it does have pretty good pattern matching in multi signatures.
Raku doesn't have algebraic data types (yet), but it does have pretty good pattern matching in multi signatures.
<lang perl6>enum RedBlack <R B>;
<syntaxhighlight lang=perl6>enum RedBlack <R B>;


multi balance(B,[R,[R,$a,$x,$b],$y,$c],$z,$d) { [R,[B,$a,$x,$b],$y,[B,$c,$z,$d]] }
multi balance(B,[R,[R,$a,$x,$b],$y,$c],$z,$d) { [R,[B,$a,$x,$b],$y,[B,$c,$z,$d]] }
Line 1,953: Line 1,953:
$t = insert($_, $t) for (1..10).pick(*);
$t = insert($_, $t) for (1..10).pick(*);
say $t.gist;
say $t.gist;
}</lang>
}</syntaxhighlight>
This code uses generic comparison operators <tt>before</tt> and <tt>after</tt>, so it should work on any ordered type.
This code uses generic comparison operators <tt>before</tt> and <tt>after</tt>, so it should work on any ordered type.
{{out}}
{{out}}
Line 1,965: Line 1,965:


An abstract pattern is recursively defined and may contain, among others, the following elements: Literal, VariableDeclaration, MultiVariable, Variable, List, Set, Tuple, Node, Descendant, Labelled, TypedLabelled, TypeConstrained. More explanation can be found in the [http://http://tutor.rascal-mpl.org/Courses/Rascal/Rascal.html#/Courses/Rascal/Patterns/Abstract/Abstract.html Documentation]. Some examples:
An abstract pattern is recursively defined and may contain, among others, the following elements: Literal, VariableDeclaration, MultiVariable, Variable, List, Set, Tuple, Node, Descendant, Labelled, TypedLabelled, TypeConstrained. More explanation can be found in the [http://http://tutor.rascal-mpl.org/Courses/Rascal/Rascal.html#/Courses/Rascal/Patterns/Abstract/Abstract.html Documentation]. Some examples:
<lang rascal>
<syntaxhighlight lang=rascal>
// Literal
// Literal
rascal>123 := 123
rascal>123 := 123
Line 2,030: Line 2,030:
Match black(leaf(3),leaf(4))
Match black(leaf(3),leaf(4))
Match black(leaf(5),leaf(4))
Match black(leaf(5),leaf(4))
list[void]: []</lang>
list[void]: []</syntaxhighlight>


===Concrete===
===Concrete===
Line 2,037: Line 2,037:


A concrete pattern is a quoted concrete syntax fragment that may contain variables. The syntax that is used to parse the concrete pattern may come from any module that has been imported in the module in which the concrete pattern occurs. Some examples of concrete patterns:
A concrete pattern is a quoted concrete syntax fragment that may contain variables. The syntax that is used to parse the concrete pattern may come from any module that has been imported in the module in which the concrete pattern occurs. Some examples of concrete patterns:
<lang rascal>// Quoted pattern
<syntaxhighlight lang=rascal>// Quoted pattern
` Token1 Token2 ... Tokenn `
` Token1 Token2 ... Tokenn `
// A typed quoted pattern
// A typed quoted pattern
Line 2,044: Line 2,044:
<Type Var>
<Type Var>
// A variable pattern
// A variable pattern
<Var></lang>
<Var></syntaxhighlight>


A full example of concrete patterns can be found in the [http://tutor.rascal-mpl.org/Courses/Recipes/Languages/Exp/Concrete/WithLayout/WithLayout.html Rascal Recipes].
A full example of concrete patterns can be found in the [http://tutor.rascal-mpl.org/Courses/Recipes/Languages/Exp/Concrete/WithLayout/WithLayout.html Rascal Recipes].
Line 2,052: Line 2,052:
There are two variants of the PatternsWitchAction. When the subject matches Pattern, the expression Exp is evaluated and the subject is replaced with the result. Secondly, when the subject matches Pattern, the (block of) Statement(s) is executed. See below for some ColoredTree examples:
There are two variants of the PatternsWitchAction. When the subject matches Pattern, the expression Exp is evaluated and the subject is replaced with the result. Secondly, when the subject matches Pattern, the (block of) Statement(s) is executed. See below for some ColoredTree examples:


<lang rascal>// Define ColoredTrees with red and black nodes and integer leaves
<syntaxhighlight lang=rascal>// Define ColoredTrees with red and black nodes and integer leaves
data ColoredTree = leaf(int N)
data ColoredTree = leaf(int N)
| red(ColoredTree left, ColoredTree right)
| red(ColoredTree left, ColoredTree right)
Line 2,091: Line 2,091:
case red(l, r) => green(l, r)
case red(l, r) => green(l, r)
};
};
}</lang>
}</syntaxhighlight>


===Regular Expressions===
===Regular Expressions===
Line 2,097: Line 2,097:
Regular expressions are noated between two slashes. Most normal regular expressions patterns are available, such as ., \n, \d, etc. Additionally, flags can be used to create case intensiveness.
Regular expressions are noated between two slashes. Most normal regular expressions patterns are available, such as ., \n, \d, etc. Additionally, flags can be used to create case intensiveness.


<lang rascal>rascal>/XX/i := "some xx";
<syntaxhighlight lang=rascal>rascal>/XX/i := "some xx";
bool: true
bool: true
rascal>/a.c/ := "abc";
rascal>/a.c/ := "abc";
bool: true</lang>
bool: true</syntaxhighlight>


=={{header|REXX}}==
=={{header|REXX}}==
The nodes used for this example are taken from the Wikipedia example at: &nbsp;
The nodes used for this example are taken from the Wikipedia example at: &nbsp;
[[https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#/media/File:Red-black_tree_example.svg red black tree, an example]]
[[https://en.wikipedia.org/wiki/Red%E2%80%93black_tree#/media/File:Red-black_tree_example.svg red black tree, an example]]
<lang rexx>/*REXX pgm builds a red/black tree (with verification & validation), balanced as needed.*/
<syntaxhighlight lang=rexx>/*REXX pgm builds a red/black tree (with verification & validation), balanced as needed.*/
parse arg nodes '/' insert /*obtain optional arguments from the CL*/
parse arg nodes '/' insert /*obtain optional arguments from the CL*/
if nodes='' then nodes = 13.8.17 8.1.11 17.15.25 1.6 25.22.27 /*default nodes. */
if nodes='' then nodes = 13.8.17 8.1.11 17.15.25 1.6 25.22.27 /*default nodes. */
Line 2,142: Line 2,142:
if @.y\==. & @.y\=='' then call err "node is already defined: " y
if @.y\==. & @.y\=='' then call err "node is already defined: " y
end /*v*/
end /*v*/
return</lang>
return</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
<pre>
Line 2,156: Line 2,156:
{{trans|Haskell}}
{{trans|Haskell}}
This would be a horribly inefficient way to implement a Red-Black Tree in Rust as nodes are being allocated and deallocated constantly, but it does show off Rust's pattern matching.
This would be a horribly inefficient way to implement a Red-Black Tree in Rust as nodes are being allocated and deallocated constantly, but it does show off Rust's pattern matching.
<lang rust>#![feature(box_patterns, box_syntax)]
<syntaxhighlight lang=rust>#![feature(box_patterns, box_syntax)]
use self::Color::*;
use self::Color::*;
use std::cmp::Ordering::*;
use std::cmp::Ordering::*;
Line 2,198: Line 2,198:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Scala}}==
=={{header|Scala}}==
Line 2,233: Line 2,233:
of that object.
of that object.


<lang scala>class RedBlackTree[A](implicit ord: Ordering[A]) {
<syntaxhighlight lang=scala>class RedBlackTree[A](implicit ord: Ordering[A]) {
sealed abstract class Color
sealed abstract class Color
case object R extends Color
case object R extends Color
Line 2,265: Line 2,265:
}
}
}
}
}</lang>
}</syntaxhighlight>


Usage example:
Usage example:
Line 2,282: Line 2,282:


=={{header|Standard ML}}==
=={{header|Standard ML}}==
<lang sml>
<syntaxhighlight lang=sml>
datatype color = R | B
datatype color = R | B
datatype 'a tree = E | T of color * 'a tree * 'a * 'a tree
datatype 'a tree = E | T of color * 'a tree * 'a * 'a tree
Line 2,307: Line 2,307:
T (B,a,y,b)
T (B,a,y,b)
end
end
</syntaxhighlight>
</lang>


=={{header|Swift}}==
=={{header|Swift}}==
{{works with|Swift|2+}}
{{works with|Swift|2+}}
<lang swift>enum Color { case R, B }
<syntaxhighlight lang=swift>enum Color { case R, B }
enum Tree<A> {
enum Tree<A> {
case E
case E
Line 2,347: Line 2,347:
return .E
return .E
}
}
}</lang>
}</syntaxhighlight>


=={{header|Tailspin}}==
=={{header|Tailspin}}==
Line 2,353: Line 2,353:


Tailspin doesn't have type names, so here using a tag. Neither does it have destructuring (which seems to be posited in the problem statement). Arguably, pattern matching in Tailspin is more readable while still as concise.
Tailspin doesn't have type names, so here using a tag. Neither does it have destructuring (which seems to be posited in the problem statement). Arguably, pattern matching in Tailspin is more readable while still as concise.
<lang tailspin>
<syntaxhighlight lang=tailspin>
processor RedBlackTree
processor RedBlackTree
data node <{VOID}|{colour: <='black'|='red'>, left: <node>, right: <node>, value: <> VOID}> local
data node <{VOID}|{colour: <='black'|='red'>, left: <node>, right: <node>, value: <> VOID}> local
Line 2,396: Line 2,396:
1..5 -> \('$tree::toString;$#10;' -> !OUT::write $ -> !tree::insert \) -> !VOID
1..5 -> \('$tree::toString;$#10;' -> !OUT::write $ -> !tree::insert \) -> !VOID
$tree::toString -> !OUT::write
$tree::toString -> !OUT::write
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 2,411: Line 2,411:


Tcl doesn't have algebraic types built-in, but they can be simulated using tagged lists, and a custom pattern matching control structure can be built:
Tcl doesn't have algebraic types built-in, but they can be simulated using tagged lists, and a custom pattern matching control structure can be built:
<lang tcl># From http://wiki.tcl.tk/9547
<syntaxhighlight lang=tcl># From http://wiki.tcl.tk/9547
package require Tcl 8.5
package require Tcl 8.5
package provide datatype 0.1
package provide datatype 0.1
Line 2,481: Line 2,481:
proc default body { return -code return [list {} $body] }
proc default body { return -code return [list {} $body] }
}
}
</syntaxhighlight>
</lang>
We can then code our solution similar to Haskell:
We can then code our solution similar to Haskell:


<lang tcl>datatype define Color = R | B
<syntaxhighlight lang=tcl>datatype define Color = R | B
datatype define Tree = E | T color left val right
datatype define Tree = E | T color left val right


Line 2,513: Line 2,513:
}
}
}
}
}</lang>
}</syntaxhighlight>


=={{header|Wren}}==
=={{header|Wren}}==
{{trans|Go}}
{{trans|Go}}
Wren doesn't have either algebraic data types or pattern matching though, despite that, the ''T.balance()'' method looks better than I thought it would :)
Wren doesn't have either algebraic data types or pattern matching though, despite that, the ''T.balance()'' method looks better than I thought it would :)
<lang ecmascript>var R = "R"
<syntaxhighlight lang=ecmascript>var R = "R"
var B = "B"
var B = "B"


Line 2,601: Line 2,601:
var tr = E.new()
var tr = E.new()
for (i in 1..16) tr = tr.insert(i)
for (i in 1..16) tr = tr.insert(i)
System.print(tr)</lang>
System.print(tr)</syntaxhighlight>


{{out}}
{{out}}