6 ms·
Picking up new languages is fun. I have to say things like this tickle my funny bone though: > def backlog(board_id) when is_integer(board_id) do What happ
by blindwatchmaker 9y ago
Picking up new languages is fun.
I have to say things like this tickle my funny bone though:
> def backlog(board_id) when is_integer(board_id) do
What happened to good old fashioned function foo (int bar) :)
Is there an equivalent to typescript for elixir?
- ch4s3 9y agoThere are typespec annotations. The syntax using guards allows you to have for example: def backlog(board_id) when is_integer(board_id), do: something and def backlog(board_id) when is_list(board_id), do: some_list_thing
- chickenfries 9y agoI've been reading about Erlang recently, and guards (the when clause) seem much more expressive than something like type annotations for function parameters. For example, TypeScript's annotations can't express something like this (which also shows Erlang's pattern matching): right_age(X) when X >= 16, X =< 104 -> true; right_age(_) -> false. http://learnyousomeerlang.com/syntax-in-functions#guards-guards http://learnyousomeerlang.com/syntax-in-functions#guards-gua...
- jacquesm 9y agoCan't?
- chickenfries 9y agoThat was awkwardly phrased. I was trying to say "TypeScript's annotations can't express something this Erlang example."
- always_good 9y agoUnless you're telling me Elixir has static analysis that can tell me that `right_age(18) == true` then I'm not sure how that competes with types much less is so different from any other runtime conditional.
- rdtsc 9y ago> Unless you're telling me Elixir has static analysis Sure does: http://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html http://erlang.org/doc/apps/dialyzer/dialyzer_chapter.html > I'm not sure how that competes with types much less is so different from any other runtime conditional. You can write: f(5) -> "got a 5"; f(X) when is_integer(X), X > 1000 -> "got an integer greater than 1000"; f(X) -> "not 5 and not an integer greater than 1000". Sure you can do it with an if statement in some languages. Except in Erlang can also have the same guards on process message receive expressions. There would have to process all messages then check the type and somehow re-insert it back into the message queue.
- always_good 9y agoLooking at the dialyzer docs and how you truncated my full question, I'm still not sure if Elixir has static analysis that is aware of those guards or not.
- rdtsc 9y agoSorry for being confusing. I think this might be better description of static type analysis: http://learnyousomeerlang.com/dialyzer http://learnyousomeerlang.com/dialyzer Erlang is a dynamic, strongly typed language. Dynamic means the compiler doesn't do static type checks. "Strongly typed" means once a variable has a type it usually doesn't get automatically coerced to other types. So adding a string "5" and an integer 1 doesn't return a string "6" or integer 6 but throws an exception. In addition to the compiler there is also a tool called Dialyzer. It's based on the idea of Success Types (paper on it: http://www.it.uu.se/research/group/hipe/papers/succ_types.pdf http://www.it.uu.se/research/group/hipe/papers/succ_types.pd...). It checks for type inconsistencies, violations, etc just like a compiler in a traditional statically typed language. But it doesn't emit optimized code based on it. So say it deduced that a variable can only be an integer between 1 and 10 it doesn't have a way to emit some optimized assembly code based on that information. Besides the types it automatically infers, additional typing constraints can be specified by the user. So for the guard in question, if say the second clause of right_age(_) -> wasn't there and it saw calls to the function with X=105, then Dialyzer would come back with an error with something like: your_module:105: Clause guard cannot succeed.
- jmcgough 9y agoElixir uses pattern matching for its functions. You can define multiple functions with the same name, and which function is used depends on which one "matches" first, based on the arguments. E.g ############ # no args def my_func() do: (something) end # an array arg, assigning the first to "head and the rest to "tail" def my_func([ head | tail ]) do: (something) end # two args, so you'd call this my_func/2 instead of my_func/1. def my_func([], %{key: val}) do: (something) end # definition with a guard clause, so it checks the value of the arg when determining whether it matches def my_func(val) when (val > 10) do: (something) end # wildcard matcher for any single arg passed def my_func(_) do: (something) end ############ Pattern matching was my gateway drug for getting into Elixir, and it's just the tip of the iceberg when it comes to what makes the language great to work with. It's particularly elegant when pattern matching responses from HTTP requests, using switch statements. No need to put try catch blocks around everything, just pattern match against a tuple with :ok and a tuple with :error
- mr_luc 9y agoThere are optional type annotations that are supported by docs and compile-time tools. But if you don't mind me nerd-sniping you ... someone's done something a bit crazier recently. It's called Elmchemy[1], which lets you write Elm that compiles to elixir. Recent blog post[2]. --- [1] https://github.com/wende/elmchemy https://github.com/wende/elmchemy [2] https://hackernoon.com/elmchemy-write-type-safe-elixir-code-with-elms-syntax-part-2-our-own-rpg-character-module-cedbf7da138d https://hackernoon.com/elmchemy-write-type-safe-elixir-code-...
- dqv 9y agoAn Elixir macro guru would have to verify, but you could do some funny stuff with a macro that takes a keyword list to get syntax like: function foo: [int: bar] do bar * bar end But, no the Erlang type system is not what you'd normally expect. I really like this paper on success types that kind of goes over the type system: http://user.it.uu.se/~kostis/Papers/succ_types.pdf http://user.it.uu.se/~kostis/Papers/succ_types.pdf
- rdtsc 9y ago> What happened to good old fashioned function foo (int bar) :) It doesn't let you do things like: "for (int bar) and 0 <= bar <= 3" while the "when" guard construct can do that. Moreover it lets you have multiple function heads as well. So you can defined multiple for (int bar) with different conditions. Or even a "foo" with a string bar.
- di4na 9y agoAlso something to keep in mind : so far noone has found a way to properly typed in a strong static formally proving way the erlang and elixir paradigm. Over other things, the self() construct that return the own pid of a process is so far impossible to type well.