One of the very reasons why Haskell and Rust are so safe is because pattern match checking in these languages is exhaustive. If you don't cover every possible type constructor for an enum or pattern the compiler will throw an error.
For example, the Maybe monad used with match must have Nothing and Just handled during pattern matching. Precompile time logic checking.
The below will throw a precompile time error:
handleMaybeNum :: Maybe int -> int
handleMaybeNum Just a = a
The below will not:
handleMaybeNum :: Maybe int -> int
handleMaybeNum Just a = a
handleMaybeNUm Nothing = -1
Could the same be said for this library? If so when combined with mypy type checking and functional programming this can transform python into a language with haskell level saftey.
$ cat maybe.hs
handleMaybeNum :: Maybe int -> int
handleMaybeNum Just a = a
$ ghci maybe.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( maybe.hs, interpreted )
maybe.hs:2:16:
Constructor ‘Just’ should have 1 argument, but has been given none
In the pattern: Just
In an equation for ‘handleMaybeNum’: handleMaybeNum Just a = a
Failed, modules loaded: none.
You're right about the "precompile time error", although it's not what you claim...
Let's fix the syntax error:
$ cat maybe_fixed.hs
handleMaybeNum :: Maybe int -> int
handleMaybeNum (Just a) = a
$ ghci maybe_fixed.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( maybe_fixed.hs, interpreted )
Ok, modules loaded: Main.
*Main>
No error now. You do get a warning with -Wall, but that's not quite what you claimed. (Newer versions may be more strict, I don't know.)
Author here. Pampy and Pampy.js (https://github.com/santinic/pampy.js) are more similar to Lisp-style Pattern Matching. Of course they cannot provide static analysis, but they can improve understandability, and they are useful with nested structures which are typical of how you solve problems in dynamic languages (less types, more nested dicts-and-lists).
What's the theoretical difference between this kind of pattern matching and polymorphism? Instead of encoding the logic for each branch in a switch, do we get the same kind of exhaustive static guarantees if instead we encode each branch as a polymorphic implementation on each type?
For example, Java's Optional type seems to provide the same static guarantees without pattern matching (assuming it didn't have the unsafe get() method).
Looks neat! Pattern matching is one of those features that I sorely miss when I have to program in Python.
I do feel a bit wary seeing this[1] though, given that `_` can be considered a special character in Python. I suppose you can use `ANY` instead of `_` in the pattern matches, but of course that would not look as clean.
I agree. Lots of Python programmers use "_" as a variable name to indicate (by convention) that they don't intend to use the variable yet are syntactically required to give it a name[1]. Some common examples:
for _ in range(10):
...
red, _, _ = rgb(color)
first, *_, last = some_list
This convention conflicts with the use of a global variable named "_" because the first time a programmer uses this convention and rebinds "_" to something arbitrary it will mask the "_" imported from pampy. Of course a programmer is free to give it a more conventional name:
from pampy import _ as placeholder
But for my money pampy should have given "_" a real name and left it up to the programmer to give it a short alias if so desired:
from pampy import placeholder as _
This is in line with common conventions around say, numpy, which is conventionally aliased to the shorter "np" on import:
EDIT: So it turns out that pampy already has a more explicitly named alternative to "_" called "ANY". So anybody who doesn't like the _ syntax can use "from pampy import ANY" and use that instead.
And here is an another pattern matching implementation for Python [1]. It was made for compilers construction task and may look similiar for those who has an experience with Prolog, Stratego or Refal.
This way of sharing variable names between the pattern and the associated action is pretty neat. It's much nicer than Pampy's use of '_' for all variables.
It’s neat that Python allows writing such things, but it’d be nice to see what the effect on debugging and stack traces are before writing anything with it.
Pattern matching is actually not very hard to write. There is a portable pattern matcher for scheme that uses macros to provide high quality code generation.
In guile the module (ice-9 match) generally has zero runtime cost compared to equal hand-written code.
Nice! Extending this further to support associative and commutative operations yields a functionality similar to that provided in Mathematica. This approach was taken by the MatchPy project to hopefully integrate into SymPy so that they can use the Rubi integration ruleset.
[+] [-] lou1306|7 years ago|reply
[+] [-] quietbritishjim|7 years ago|reply
[+] [-] crimsonalucard|7 years ago|reply
For example, the Maybe monad used with match must have Nothing and Just handled during pattern matching. Precompile time logic checking.
The below will throw a precompile time error:
The below will not: Could the same be said for this library? If so when combined with mypy type checking and functional programming this can transform python into a language with haskell level saftey.[+] [-] tom_mellior|7 years ago|reply
Let's fix the syntax error:
No error now. You do get a warning with -Wall, but that's not quite what you claimed. (Newer versions may be more strict, I don't know.)[+] [-] csantini|7 years ago|reply
An example:
pampy.matchAll(json, {_: {age: Number}}, (key, age) => age)
Finds any object with a Numeric age, that is value of any key in a json object we don't know the structure of.
[+] [-] freddie_mercury|7 years ago|reply
This is clearly answered on the page.
"By default match() is strict. If no pattern matches, it raises a MatchError"
[+] [-] cle|7 years ago|reply
For example, Java's Optional type seems to provide the same static guarantees without pattern matching (assuming it didn't have the unsafe get() method).
[+] [-] marmaduke|7 years ago|reply
[+] [-] bow_|7 years ago|reply
I do feel a bit wary seeing this[1] though, given that `_` can be considered a special character in Python. I suppose you can use `ANY` instead of `_` in the pattern matches, but of course that would not look as clean.
[1] https://github.com/santinic/pampy/blob/4c8e6e0cabada82a5ed79...
[+] [-] olooney|7 years ago|reply
EDIT: So it turns out that pampy already has a more explicitly named alternative to "_" called "ANY". So anybody who doesn't like the _ syntax can use "from pampy import ANY" and use that instead.
[+] [-] richard_shelton|7 years ago|reply
And here is a toy term rewriting system [2].
[1] https://github.com/true-grue/raddsl
[2] https://github.com/true-grue/code-snippets/blob/master/ttrs....
[+] [-] tom_mellior|7 years ago|reply
Oh, I like the prettier syntax:
(https://github.com/true-grue/raddsl/blob/master/examples/cal...)This way of sharing variable names between the pattern and the associated action is pretty neat. It's much nicer than Pampy's use of '_' for all variables.
[+] [-] methyl|7 years ago|reply
[+] [-] marmaduke|7 years ago|reply
[+] [-] bjoli|7 years ago|reply
In guile the module (ice-9 match) generally has zero runtime cost compared to equal hand-written code.
[+] [-] hyperopt|7 years ago|reply
[+] [-] kolinko|7 years ago|reply