Basic destructuring assignment or multiple assignment is common in many languages. ```go a, b := 1, 2 fmt.Println(a) // 1 fmt.Println(b) // 2 ``` ```ruby a, b = [1, 2] p b # 2 head, *tail = [1, 2, 3] p tail # [2, 3] ``` ```crystal a, b = [1, 2] p b # 2 head, *tail = [1, 2, 3] p tail # [2, 3] ``` ```erlang [A, B] = [1, 2]. B. % output: 2 ``` ```csharp int[] array = { 1, 2 }; var result = array is [var a, var b] ? a : 0; Console.WriteLine(result); // 1 // holy crap this language is painful, despite some cool features, and list destructuring is so limited ``` More advanced destructuring is mostly the domain of functional languages. ```clojure (def data [[1,2], [3,4]]) (let [[[_ b]] data] (println b)) ; 2 (def greeting "Hello, world!") (let [[ _ _ _ _ _ _ _ & name ] greeting] (println (apply str name))) ; world! ``` ```erlang Data = [[1, 2], [3, 4]]. [[_, B] | _] = Data. B. % output: 2 "Hello, " ++ Name = "Hello, world!". Name. % output: world! ``` Frustratingly, neither [[Clojure]] nor [[Erlang]] can operate on the ends of lists due to their very 80s insistence on treating everything like linked lists where you only operate on the "head" one at a time, and the "tail" is everything else. This paradigm is a good starting point, but it is exasperating to have to invert the lists to do simple operations and prevents the otherwise super cool destructuring and pattern matching facilities from taking into account suffixes. [[Erlang]] is an interesting case because the basic assignment and equality operators are the same. Variables, aren't variable, due to single assignment (although you can "forget" variables, or even entire vocabularies). So any variables on the left must be either empty or already the same value, otherwise it will fail. While some other languages, particularly [[3. Reference/Software/Programming Languages/Ruby]] and [[Perl]] do have more advanced pattern matching capabilities, they're not commonly used in the wild. Probably because these are add-on features which did not exist early in the language's life, are not used in any core libraries, it is not integrated seamlessly with the rest of the language, and the fragile syntax feels less refined. ```ruby hash = {a: 3, b: 4} hash => {a:} puts a # 3 # below example from https://ruby-doc.org/core-3.0.0/doc/syntax/pattern_matching_rdoc.html jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]} case jane in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match "matched. school: #{id}" else "not matched" end #=> "matched. school: 2" ``` Ruby doesn't allow keys to match with the contents of variables, pinned or not. It's just an error, severely limiting this feature. Crystal's implementation of pattern matching is less advanced in most ways than any of the others presented. It only works with tuples and cannot be used for destructuring assignment. In exchange, it can run arbitrary methods on the elements positionally within the tuple. And this is *rad as hell*. ```crystal case { 1, 2 } when { .odd?, Number } puts "match" else puts "fail" end # match ``` The simple prefix dot notation is a bit strange, since the `&.method` syntax already exists, however it is very clean. # References - https://github.com/dart-lang/language/issues/2415#issuecomment-1228318083 - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns - https://tryclojure.org/ - https://clojure.org/guides/destructuring - https://clojure.org/guides/learn/syntax - https://tryerlang.org/# - https://www.erlang.org/doc/reference_manual/expressions.html#pattern - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment