Скрытые возможности Erlang
В духе:
- Скрытые возможности C#
- Скрытые возможности Java
- Скрытые возможности ASP.NET
- Скрытые возможности Python
- Скрытые возможности HTML
- и другие вопросы о скрытых функциях
О каких скрытых особенностях Erlang должен знать каждый разработчик Erlang?
Одна скрытая функция в ответе, пожалуйста.
17 ответов
Магические команды в оболочке. Полный список приведен в руководстве, но больше всего я использую:
- f () - забыть все переменные
- f(X) - забыть X
- v (42) - вызвать результат из строки 42
- v (-1) - вызвать результат из предыдущей строки
- e(-1) - повторно выполнить выражение в предыдущей строке
- rr (foo) - читать определения записей из модуля foo
- rr ("* / *") - читать определения записей из каждого модуля в каждом подкаталоге
- rp (выражение) - вывести полное выражение с форматированием записи
Наследование! http://www.erlang.se/euc/07/papers/1700Carlsson.pdf
родитель
-module(parent).
-export([foo/0, bar/0]).
foo() ->
io:format("parent:foo/0 ~n", []).
bar() ->
io:format("parent:bar/0 ~n", []).
ребенок
-module(child).
-extends(parent).
-export([foo/0]).
foo() ->
io:format("child:foo/0 ~n", []).
Приставка
23> parent:foo().
parent:foo/0
ok
24> parent:bar().
parent:bar/0
ok
25> child:foo().
child:foo/0
ok
26> child:bar().
parent:bar/0
ok
Параметризованные модули! От http://www.lshift.net/blog/2008/05/18/late-binding-with-erlang и http://www.erlang.se/euc/07/papers/1700Carlsson.pdf
-module(myclass, [Instvar1, Instvar2]).
-export([getInstvar1/0, getInstvar2/0]).
getInstvar1() -> Instvar1.
getInstvar2() -> Instvar2.
А также
Eshell V5.6 (abort with ^G)
1> Handle = myclass:new(123, 234).
{myclass,123,234}
2> Handle:getInstvar1().
123
3> Handle:getInstvar2().
234
user_default.erl - вы можете создавать свои собственные встроенные оболочки, имея скомпилированный user_default.beam на своем пути, который может быть довольно изящным
beam_lib: чанки могут получить исходный код от луча, который был скомпилирован с отладкой, что может быть действительно полезным
{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(Beam,[abstract_code]).
io:fwrite("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
Порты, внешние или связанные, принимают так называемые списки io-списков для отправки им данных. Io-list - это двоичный или (возможно, глубокий) список двоичных файлов или целых чисел в диапазоне 0..255.
Это означает, что вместо объединения двух списков перед отправкой их в порт можно просто отправить их как два элемента в списке. Так что вместо
"foo" ++ "bar"
один делать
["foo", "bar"]
В этом примере это, конечно, незначительная разница. Но сам по себе iolist обеспечивает удобное программирование при создании выходных данных. Например, io_lib:format/2,3 возвращает список io.
Функция erlang:list_to_binary/1 принимает списки io, но теперь у нас есть erlang:iolist_to_binary/1, который лучше передает намерение. Существует также erlang:iolist_size/1.
Лучше всего, поскольку файлы и сокеты реализованы в виде портов, вы можете отправлять в них iolist. Нет необходимости выравнивать или добавлять.
Спецификации соответствия могут быть построены с использованием ets:fun2ms(...), где используется синтаксис Erlang fun и преобразован в спецификацию соответствия с преобразованием синтаксического анализа.
1> ets:fun2ms(fun({Foo, _, Bar}) when Foo > 0 -> {Foo, Bar} end).
[{{'$1','_','$2'},[{'>','$1',0}],[{{'$1','$2'}}]}]
Так что никакой забавной ценности никогда не создается, выражение заменяется на match-spec во время компиляции. Веселье может делать только то, что может делать выражение соответствия.
Кроме того, ets: fun2ms доступен для использования в оболочке, поэтому выражения-выражения можно легко протестировать.
.erlang_hosts дает хороший способ обмениваться именами между компьютерами
Не обязательно "скрытый", но я не вижу этого часто. Анонимные функции могут иметь несколько предложений, как и функции модуля, т.е.
-module(foo).
-compile(export_all).
foo(0) -> "zero";
foo(1) -> "one";
foo(_) -> "many".
anon() ->
fun(0) ->
"zero";
(1) ->
"one";
(_) ->
"many"
end.
1> foo:foo(0).
"zero"
2> foo:foo(1).
"one"
3> foo:foo(2).
"many"
4> (foo:anon())(0).
"zero"
5> (foo:anon())(1).
"one"
6> (foo:anon())(2).
"many"
В сокетах gen___tcp и ssl есть опция сокета {package, Type}, помогающая декодировать несколько протоколов. Функция erlang:decode_packet/3 имеет хорошее описание того, что могут быть различные значения типа и что они делают.
Вместе с настройкой {active, once} или {active, true} каждое значение в рамке будет доставлено как одно сообщение.
Примеры: режим http пакета интенсивно используется для iserve и режим fcgi пакета для ifastcgi. Я могу представить, что многие другие http-серверы также используют пакетный http.
.erlang может предварительно загружать библиотеки и запускать команды при запуске оболочки, вы также можете выполнять определенные команды для определенных узлов, выполняя инструкцию case для имени узла.
Если вы хотите выполнить более одного выражения в понимании списка, вы можете использовать блок. Например:
> [begin erlang:display(N), N*10 end || N <- lists:seq(1,3)].
1
2
3
[10,20,30]
Не такой скрытый, но один из самых важных аспектов при выборе Erlang в качестве платформы для разработки:
- Возможность улучшенной трассировки на живых узлах (в рабочем состоянии) и быть одним из лучших в отладке!
Можно определить свой собственный итератор для использования QLC. Например, набор результатов из запроса SQL может быть преобразован в таблицу QLC и, таким образом, использовать преимущества запросов QLC.
Помимо таблиц mnesia, dets и ets имеют функции table/1,2, которые возвращают им такой "дескриптор запроса".
Вы можете скрыть узел Erlang, запустив его с:
erl -sname foo -hidden
Вы все еще можете подключиться к узлу, но он не появится в списке, возвращаемом nodes/0
,
Соответствие с оператором добавления:
"pajamas:" ++ Color = "pajamas:blue"
Цвет теперь имеет значение "синий". Имейте в виду, что у этого трюка есть свои ограничения - насколько я знаю, он работает только с одной переменной и одной константой в указанном выше порядке.
Горячая загрузка кода. Из вики.
Код загружается и управляется как "модульные" модули, модуль является модулем компиляции. Система может хранить две версии модуля в памяти одновременно, и процессы могут одновременно запускать код из каждой.
Версии относятся к "новой" и "старой" версии. Процесс не переместится в новую версию, пока не выполнит внешний вызов своего модуля.