Navigation Menu

Skip to content

Commit

Permalink
Change permissions.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jens Li committed Apr 12, 2013
1 parent 029fa7f commit 9435acf
Show file tree
Hide file tree
Showing 31 changed files with 89 additions and 0 deletions.
Empty file modified .gitignore 100755 → 100644
Empty file.
Empty file modified Doc/Build instructions.txt 100755 → 100644
Empty file.
Empty file modified Doc/Compiling Pattern Matching to Good Decision Trees.pdf 100755 → 100644
Empty file.
87 changes: 87 additions & 0 deletions Doc/Copy of Pattern matching in switch proposal.txt
@@ -0,0 +1,87 @@

Pattern matching in switch proposal

Intro
=====

A very useful feature in many functional languages is pattern matching. This makes it very easy and concise to write some kind of logic that can be pretty hairy to express with normal if:s and switch:s.

I propose adding pattern matching capabilities to the Fantom switch statement in a way that resemble how it looks in Scala.

UPDATE: This proposal tries to introduce a unified way of switching on the type and contents of objects, instead of making smaller and more directed changes.

For a description of the Scala model have a look at the [Programming in Scala]`http://www.artima.com/pins1ed/case-classes-and-pattern-matching.html` book.

Pattern matching would be added for lists, maps, and the type and fields of objects using the it-block style constructor syntax.

Example
=======

This is an example of how it might look in Fantom:

pre>
class Animal{Animal? parent := null}

class Turtle : Animal{Int field1 := 1}

class Frog : Animal{Int field2 := 2}

Void patternExample(Animal o)
{
switch (o) {
case Turtle{field2 = 2; parent = Frog{} as par}:
echo("Object pattern. Parent: " + par)
case [1, _ as snd]:
echo("List pattern. Second list elem: " + snd)
case ["key1": 1, "key2": _ as val2] if (val2 > 7):
echo("Map pattern. key2: " + key2)
case 17:
echo("Simple literal")
default:
echo("Default")
}
}
<pre

The first 'case' branch is chosen if 'o' is a object of type 'Turtle', its 'field2' has value '2', and its field 'parent' has an object of type 'Frog' as its value. The 'par' variable introduced with the 'as' keyword can be used only in that branch.

If that pattern doesn't match, the list patterns in the second 'case' is tried. It matches if 'o' is a two elem list, with '1' as its first elem and any second elem. '_' is the wildcard, "don't care" pattern. It is bound to the variable 'snd'.

The third 'case' is a map pattern, checking for the presence of keys '"key1"' and '"key2"' in 'o', that '"key1"' is mapped to '1', and binding the value of '"key2"' to the variable 'key2'.

The fourth 'case' is a simple expression pattern, which is compared to 'o' with 'equals'.


Details of proposal
===================

The current switch works by comparing the value of an expression in each 'case' with the objects 'equals' method. This would change so that after each 'case' a pattern is expected instead of an expression. The object that is switched on will be checked for a match against each pattern in turn.

Simple expressions are valid patterns. They will get evaluated and their value compared with 'equals' in the switch.

But after the 'case' keyword, list literals, map literals and it-block constructors will be interpreted as patterns, not as expressions creating objects.

The value that is switched on is checked to see if it matches the structure of the pattern. The 'case' branch associated with the first matching pattern is executed.

A pattern can be either:

- A normal expression. This will work like the current switch, the value will be compared by 'equals'.

- A literal object, it-block constructor style. This will be checked for a matching type, and can check the value of fields of that type with nested patterns.

- A literal list, with nested patterns for the elements.

- A literal map, with expressions for the keys and nested patterns for values.

- The wildcard identifier, '_', which matches all values. This is useful when one wants to introduce new variables without checking their value.

A pattern can also introduce new variables. That is done with the 'as' keyword followed by a free identifier, written after the pattern.

A top level pattern can have a guard. It consists of an 'if' followed by a boolean expression. The pattern match if the expression evaluates to 'true'.


Scala
=====
The Scala match statement is extendible in a very flexible way with custom extractors. This rimes well with Scalas goal of being extendible with new syntax, but it is complex and potentially bad for readability. The Fantom solution should probably aim for something simpler which solves the large majority of cases.


Empty file modified Doc/Fantom - Pattern match.txt 100755 → 100644
Empty file.
Empty file modified Doc/Fantom switch proposal description_ OLD.txt 100755 → 100644
Empty file.
Empty file modified Doc/Fantom variance proposal.txt 100755 → 100644
Empty file.
2 changes: 2 additions & 0 deletions Doc/Pattern matching in switch proposal.txt
Expand Up @@ -125,6 +125,8 @@ Further development
- Matching on more types, such as 'Range' and 'Time'
- Statically check that switches cover all possible cases
- Patterns in more places, e.g. for destructive assignments
- Translating branches with mulitiple 'case' lables


Prototype
=========
Expand Down
Empty file modified Doc/Pattern notes.txt 100755 → 100644
Empty file.
Empty file modified Doc/When Do Match-Compilation Heuristics Matter.pdf 100755 → 100644
Empty file.
Empty file modified F4_Projects/Build/.buildpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Build/.classpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Build/.project 100755 → 100644
Empty file.
Empty file modified F4_Projects/Compiler/.buildpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Compiler/.classpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Compiler/.project 100755 → 100644
Empty file.
Empty file modified F4_Projects/Compiler/build.fan 100755 → 100644
Empty file.
Empty file modified F4_Projects/CompilerJava/.buildpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/CompilerJava/.classpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/CompilerJava/.project 100755 → 100644
Empty file.
Empty file modified F4_Projects/FantomPatternMatching/src/ExprSimpl.fan 100755 → 100644
Empty file.
Empty file modified F4_Projects/FantomPatternMatching/src/PatternsExample.fan 100755 → 100644
Empty file.
Empty file modified F4_Projects/FantomPatternMatching/src/PatternsTest.fan 100755 → 100644
Empty file.
Empty file modified F4_Projects/FantomPatternMatching/src/PatternsTranslation.fan 100755 → 100644
Empty file.
Empty file modified F4_Projects/Sys/.buildpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Sys/.classpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/Sys/.project 100755 → 100644
Empty file.
Empty file modified F4_Projects/TestCompiler/.buildpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/TestCompiler/.classpath 100755 → 100644
Empty file.
Empty file modified F4_Projects/TestCompiler/.project 100755 → 100644
Empty file.
Empty file modified README.md 100755 → 100644
Empty file.

0 comments on commit 9435acf

Please sign in to comment.