-
Notifications
You must be signed in to change notification settings - Fork 62
switch on tuple #4127
Comments
[@akberc] +1 |
[@gavinking] In light of #3626, this feature amounts to a sort of pattern matching, for example: switch (pair)
case ([0.0,y]) { .... }
case ([x, 0.0]) { .... }
else case ([x,y]) { .... } |
[@guai] mixing destructuring with values is awful. |
[@gavinking] switch (pair)
case ([x,y]) when x=0 {...}
case ([x,y]) when x>y {...} is better than this: switch(pair)
case ([x,y]) {
if (x==0) { ... }
else if (x>y) { ... }
} The second way has fewer tokens and less repetition. Indeed, it seems to me that arbitrary boolean conditions like |
[@guai] SomeObj z = SomeObj(); |
[@guai] and also if condition check is part of switch statement, then compiler can require else statement [in cases other then someCheck(a) along with !someCheck(a) for pure functions] |
[@gavinking] @guai Well, y'know, I've also often questioned the value of pattern matching, but people keep telling me it's the greatest thing ever. It doesn't seem quite that great to me, but I feel like I must be missing something... |
[@guai] Gavin, do you plan to make switch an "assert that intersection of all cases always true" statement or live it like in java just kinda alias for if-elseif-elseif? |
[@gavinking] In Ceylon, |
In 909a74e I have partially implemented this. That is, I have implemented support for the kind of destructuring we already allow in other syntactic locations. I have not implemented what is described in the original issue description where patterns are allowed to contain literals. Of course that's an obvious and pretty natural extension to this. Anyway, it's enough to make stuff like the following work: Person|Org whatever = ... ;
switch (tuple = whatever.destructured)
case ([String name, Person[] employees]) {
...
}
case ([String name, Integer age]) {
...
} That's still not "true" pattern matching, but boy is it ever close! |
Just to be sure: the |
@quintesse you need this useful interface: interface Struct<T>
satisfies Identifiable
given T satisfies Anything[] {
shared formal T destructured;
shared actual default Boolean equals(Object that) {
if (is Struct<out Anything[]> that) {
return
//type(that).declaration==type(this).declaration
className(this)==className(that)
&& destructured==that.destructured;
}
else {
return false;
}
}
shared actual default Integer hash => destructured.hash;
shared actual default String string =>
"``className(this)``(``destructured``)";
} And then class Person(shared String name, Integer age)
satisfies Struct<[String,Integer]> {
destructured = [name, age];
}
class Org(String name, Person* employees)
satisfies Struct<[String,Person[]]> {
destructured = [name, employees];
} |
I plan to work on this for 1.3.1. Supporting purely-literal tuples is trivial, so we should at least implement that. Mixing literals with pattern variables is a bit more complicated but we can take a look at that, too, and see how hard it is. |
When mixing literals with typed variables in patterns, types will depend on values. It is certainly possible to implement flow sensitive type narrowing that takes values into account. But does it help the user? Flow sensitive typing is meant to reduce cognitive complexity. But when in a multi-dimensional tuple types depend on values this might be harder to unterstand than the present implementation: First match on types, then on each value dimension of a tuple using nested switches. Why not implementing different flavors of pattern matching and unification like clojure' s core.logic as library exploiting meta language features of ceylon. Then it would be desirable to have symbol literals instead of enumerated objects. |
@welopino TBH, it's not really a feature I even miss, but it is one that languages with pattern matching offer, and that people seem to like. Anyway, I don't think we'll do it immediately. For now I think we should just support literal tuples and entries as switch |
I've made a good start on the typechecker side of this. |
I assume the program below should print "fallback", but it might be confusing. (Or, is the intention to match any shared void run() {
void process([String*] strings) {
switch (strings)
case (["a", "b"]) {
print("matched");
}
else {
print("fallback");
}
}
process({"a", "b"}.sequence());
} |
Wow, @jvasileff, that's a great point, and unbelievably it simply had not occurred to me to consider plain
Yeah, now that you mention it, that would probably be best. It's what this syntax means in all other languages, and value case matching is certainly supposed to align with |
I don’t understand, why would that print “fallback”? I don’t see the catch. Is it that |
A gotcha here is that for |
@chochos I noticed this test fails on the JS backend due to the shared void run() {
function f([String*] strings)
=> switch(strings)
case ([]) "empty"
case (["a", "b"]) "ab"
else "other";
assert (f([]) == "empty"); // this one
assert (f(["a", "b"]) == "ab");
assert (f(["c", "d"]) == "other");
} |
I think it would be weird and irregular to not allow |
so what should |
@chochos |
@chochos @tombentley can I merge this branch now? |
fine by me |
Can I implement it first? On 18 Oct 2016 3:42 a.m., "Enrique Zamudio" notifications@github.com
|
Please :-) |
Struggling to see exactly what I need to do here.
Is that right? |
Right.
Right (for now).
No: use
Right. |
This should now be working on the JVM |
Excellent, lets merge it! Sent from my iPhone
|
Alright, let's close this for now, I will open little issues if I run into bugs. Thanks everyone! |
@tombentley I didn't test it, but it looks like the |
Depends how precisely it's written. If it's written as |
OMG, that's total nonsense. Then we should do it as a type test instead, @chochos, being equivalent to |
I had implemented it with |
I now do an |
|
[@gavinking] We still don't have any real plans to support genuine pattern matching, however one small thing that could I guess make some sense would be to allow tuple expressions in a
case
, for example:This would only be for tuples of types that we already allow in
case
s.[Migrated from ceylon/ceylon-spec#1021]
The text was updated successfully, but these errors were encountered: