8 ms·
Another interesting way to think about it is as "match". That is try to match the stuff on the right with the stuff on the left. Take Erlang for example:
by rdtsc 9y ago
Another interesting way to think about it is as "match". That is try to match the stuff on the right with the stuff on the left.
Take Erlang for example:
1> X = 1.
1
2> X = 2.
** exception error: no match of right hand side value 2
Notice variables are immutable (not just values themselves). Once X becomes 1, it can only match with 1 after that. You might think this is silly or annoying, why not just allow reassignment and instead have to sprinkle X1, X2 everywhere. But it turns out is can be nice because it makes state updates very explicit. In complicated applications that helps understand what is happening. And it behaves like you'd expect in math, in the sense that X = X + 1 doesn't make sense here either:
1> X = 1.
1
2> X = X + 1.
** exception error: no match of right hand side value 2
3>
It does pattern matching very well too, that is, it matches based on the shape of data:
1> {X,Y} = {1,2}.
{1,2}
2> X.
1
3> Y.
2
4>
In other languages we might say we have assignment and destructuring but here it is rather simple it's just pattern matching.
- icebraining 9y agoProlog's unification: X = Y, X = 5, %% Y = 5 now as well -- ?- append([1,2], Y, [1,2,3]). Y = [3].
- OskarS 9y agoYeah, Prolog's unification operator really blows your mind the first few times you experience it. You left the best part out of that last example: ?- append(X, Y, [1,2,3]). X = [], Y = [1, 2, 3] ; X = [1], Y = [2, 3] ; X = [1, 2], Y = [3] ; X = [1, 2, 3], Y = [] ; false. (a few newlines added for clarity)
- macintux 9y agoI'm sure I've mentioned it here before, but in my favorite Erlang talk I design the language with the equal sign as my core construct. Since the equal sign is an assertion of truth, and since assertions cause a crash on failure, you can pretty much derive the rest of the language/BEAM characteristics from that.
- hwayne 9y agoI don't think I've heard of this before; I'd love to watch it if you have a link!
- rdtsc 9y agoThanks for sharing. Enjoyed watching (from the link below). Well done! I like the '=' as an assertion idea. That is, it's like running code with assertions turned on. Never thought about it that way but it makes good sense. Also stealing your idea of "rebootable code" :-)
- macintux 9y agoI'm sure I stole the idea of rebootable code from someone else, but I'll be happy to take credit for it. I almost submitted the talk to That Conference this year. I should start shopping it around more.
- rcharles 9y agoSome(all?) compilers transform your code into something like this internally. Its called static single assignment form. https://en.wikipedia.org/wiki/Static_single_assignment_form https://en.wikipedia.org/wiki/Static_single_assignment_form
- njitbew 9y agoThough it's true that compilers usually turn assignments into SSA, that's not really the same as what parent was referring to. Static single assignment has the same semantics as normal C-style assignments. The parent was referring to assignments that have (Erlang's) pattern match semantics. Also, there's a simple counterexample. You can have static single assignment that has dynamic multiple assignment (e.g. within a loop construct). Under the pattern-matching semantics, evaluating the assignment (or rather the pattern match) a second time could fail, whereas an assignment always succeeds.
- aprao 9y agoElixir has borrowed the pattern matching approach from Erlang, but allows rebinds which makes code refactoring easier. iex(1)> x = 1 1 iex(2)> x = 2 2 iex(3)> ^x = 3 (MatchError) no match of right hand side value: 3 Notice the pin operator (^) to achieve the same effect.
- dxhdr 9y agoI've used Erlang but not Elixir. Having an additional optional "pin" operator sounds like a bad idea, just piling on complexity. You can't mess up with the Erlang syntax.
- glorioustao 9y agoThe creator of elixir had a blog on this: http://blog.plataformatec.com.br/2016/01/comparing-elixir-and-erlang-variables/ http://blog.plataformatec.com.br/2016/01/comparing-elixir-an...
- gcb0 9y agoonly the case argument there is any good. when it get to numbered vars, you know they are grasping for anything
- derefr 9y agoAlso valid in Erlang: 2 = X. {ok, Y} = X = foo(). Oh, and here's a fun one: 1> {X, X} = {1, 1}. {1, 1}. 2> {Y, Y} = {1, 2}. ** exception error: no match of right hand side value {1,2} If you're wondering what the use of that is, here's an Erlang "drop all occurrences of an element X from a list" function. (Prerequisite knowledge for this: Erlang functions have several clause-heads; which one is executed on each call depends on which one is able to successfully bind to—i.e. = with—the arguments.) drop(X, List) -> drop(X, List, []). drop(X, [], Acc) -> lists:reverse(Acc); drop(X, [X|Rest], Acc) -> drop(X, Rest, Acc); drop(X, [Y|Rest], Acc) -> drop(X, Rest, [Y|Acc]). In other words—first, set up an accumulator. Then, go through the list, and if X can bind in both positions, skip the element; otherwise (i.e. if Y != X) then shift Y into the accumulator. At the end, reverse the accumulator (because you were shifting.)
- triska 9y agoTo illustrate how close Erlang syntax is to Prolog, here is drop/3 in Prolog: drop(X, List, Result) :- drop(X, List, [], Result). drop(_, [], Acc, Result) :- reverse(Acc, Result). drop(X, [X|Rest], Acc, Result) :- drop(X, Rest, Acc, Result). drop(X, [Y|Rest], Acc, Result) :- dif(X, Y), drop(X, Rest, [Y|Acc], Result). I only had to make a few syntactic changes to the original program to obtain a Prolog predicate from it. The most significant change is that I use an additional argument to hold the original function's return value. An important consequence of the resulting relational nature is that this can answer quite general queries. For example, we can ask: What are possible solutions Ls that arise when we drop X from the single-element list [A] ? ?- drop(X, [A], Ls). X = A, Ls = [] ; dif(X, A), Ls = [A]. We see that there are two possible answers: One where X is A, and hence the result is the empty list []. And the other where X is different from A, as indicated by dif(X, A). Even more generally, we can systematically enumerate all conceivable solutions for all list lengths: ?- length(Ls0, _), drop(X, Ls0, Ls). Ls0 = Ls, Ls = [] ; Ls0 = [X], Ls = [] ; Ls0 = Ls, Ls = [_586], dif(X, _586) ; Ls0 = [X, X], Ls = [] ; Ls0 = [X, _598], Ls = [_598], dif(X, _598) ; etc. This uses iterative deepening to generate all possible answers.
- kqr 9y ago
- bogomipz 9y ago>"In other languages we might say we have assignment and destructuring ..." I'm not familiar with this term "destructuring." Can you elaborate on the concept? Might you have an example of a destructure operation and a language where its's used?
- mazesc 9y agoI could imagine by destructuring he means e.g. unapply in Scala: https://docs.scala-lang.org/tour/extractor-objects.html https://docs.scala-lang.org/tour/extractor-objects.html
- bogomipz 9y agoAh OK its a functional construct, this make sense. I have seen this in my brief exposure to Clojure. Thanks for the examples and links.
- fiddlerwoaroof 9y agoRecent JS versions have it too: > let {a,b} = {a: 1, b: 2} > a 1 > b 2
- ajuc 9y agohttps://clojure.org/guides/destructuring https://clojure.org/guides/destructuring Basically it means that you can assign several variables at once, by asssigning a complex value to an aproprietly structured literal with variables as placeholders. In pseudojavascript, let's say you got this from some API: var someList = [1, 2, 3, 4]; var someMap = { name: "John Smith", age: 20, cars: [{ id: "AAA-1111", model: "Ford T"}, { id: "AAA-1112", model: "Mercedes Benz"}] } And you want to extract useful data for your code quickly. In languages with destructuring you can do sth like this: var [x, y & rest] = someList; //x==1, y==2, rest == [3, 4] var { "name": name, "age": age, "cars": [ {"id": firstCarId, "model": firstCarModel} & restOfTheCars ] } = someMap; And the language will put the correct values in your variables name, age, firstCarId, firstCarModl, restOfTheCars.
- ninjakeyboard 9y agoYa +1 I've been working with elixir lately and the `=` operator in erlang/elixir is the first thing that came to mind when I saw this.