Okay. I've spent a bit of time mulling this over and trying out some stuff. Here's what I came up with.
How about a language that's like Haskell/Shen: currying everywhere. This language would be based heavily on functions, of course, which are expressed with "->" as follows:
foo %x -> %x + 2
The above is equivalent to this in Arc:
(def foo (x) (+ x 2))
Now, how this works is... everything to the left of the "->" is a pattern. Everything to the right is the function's body. If a variable starts with % it's local to the function, if not, it's global.
class Duck:
def quack(self):
print("Quack")
def fly(self):
print("Flap, Flap")
class Person:
def __init__(self, name):
self.name = name
def quack(self):
print("{} walks in the forest and imitates ducks to draw them".format(self.name))
def fly(self):
print("{} takes an airplane".format(self.name))
def quack_and_fly(duck):
duck.quack()
duck.fly()
quack_and_fly(Duck())
quack_and_fly(Person("Jules Verne"))
And here it is in this hypothetical currying-pattern-matching language:
duck ->
[ quack -> prn "Quack"
fly -> prn "Flap, Flap" ]
person %n ->
[ quack -> prn "@%n walks in the forest and imitates ducks to draw them"
fly -> prn "@%n takes an airplane" ]
quack-and-fly [ quack %q fly %f ] -> %q; %f
quack-and-fly duck
quack-and-fly person "Jules Verne"
Wooow that is short! It also means that (except for % variables which are local) the pattern matching to the left of -> matches the function call.
If you wanted to, you could use parens like Shen instead of no-parens like Haskell.
Some downsides? Well, since it's using currying, there could be some issues with that. In particular, variable argument functions wouldn't be possible. There's also potentially some scoping issues and such.
Overall though, I think this idea is cool enough to actually try and implement it in a simple interpreter, to figure out all the kinks.
Okay, I was able to solve a couple problems with my object pattern-matching...
[ foo = 5 | bar = 10 ]
The above is a collection of patterns. Specifically, it has a "foo" pattern that maps to 5, and a "bar" pattern that maps to 10. Now, let's put this object into a variable:
pattern = [ foo = 5 | bar = 10 ]
Now how do we extract the subpatterns? Like so:
pattern [ foo ]
pattern [ bar ]
The above returns 5, and then 10. And we can extract multiple patterns at once:
pattern [ foo | bar ]
The above returns 10. This largely removes the need for "as" patterns, which is something I found cumbersome to use. You can think of | as being kinda like "do". It will first call the foo pattern, then the bar pattern.