Following on from the Do you make use of term_to_binary? thread, do you know of any other lesser known tips or tricks you think others might be interested in?
If so please share! ![]()
Following on from the Do you make use of term_to_binary? thread, do you know of any other lesser known tips or tricks you think others might be interested in?
If so please share! ![]()
There’s a compact way to do a one-line conditional (ab)using list comprehensions:
[do_thing() || BooleanValue, check_stuff()]
It works because you can have both list generators and filters, but the generators are optional.
It even works with conditions not allowed in guards. But be aware of readability concerns ![]()
Oh, here’s another one: there’s a built-in function in the shell—rp(Term)—that pretty-prints terms to infinite depth. That way you don’t have to type io:format(“~p~n”, [Term]) all the time! ![]()
If you want to learn more about this, you can check the article(s) I wrote a while back…
As a matter of fact, the whole Erlang Battleground blog is full of articles that would be proper responses to the topic of this thread.
In Erlang/OTP 26, we have documented some previously undocumented details about list comprehensions, including what happens when filters fail:
(to be included in the second release candidate, which will be released this week)
The right-hand operands of andalso and orelse can be any term, it doesn’t have to be true or false.
As a (contrived) example, if maps:get/3 didn’t exist, it could be written like this:
maps_get_with_default(Key, Map, Default) ->
case maps:is_key(Key, Map) andalso {value, maps:get(Key, Map)} of
false -> Default;
{value, Value} -> Value
end.
I got the feeling that I’ll be doing this a lot in this thread. When you folks get tired of this, let me know… ![]()
But… I also wrote an article about that semantically questionable technique…
I was a bit reluctant to share this “trick”, TBH, and I’m definitely not encouraging it ![]()
Maybe all posts in this thread should flash a warning like “Don’t do this at home!” ![]()
Those lesser know tricks are lesser known not so much because they are secret magic but because they are dirty tricks ![]()
IMHO:
andalso and orelse” is not a trick.bc(B) when byte_size(B) > 64 -> binary:copy(B);
bc(B) -> B.
I use this to store values is process state when such values are received from an external large BLOB (like a JSON) after jsone:decode/1.
I like to write it that way, Mainly to avoid multiple case
I also defined some macros
Blockquote
-define(IF(IFTure, DoThat), (IFTure) andalso (DoThat)).
-define(IIF(Cond, Then, That), case Cond of true → Then; _ → That end).
-define(IIF(Expr, Expect, Then, ExprRet, That), case Expr of Expect → Then; ExprRet → That end).
this is just to make the code look like it’s on one line
That is why I put “trick” in quotes ![]()
Using ets:match_spec_run/2 over lists for dynamic filtering at runtime.
Meant I could avoid erl_parse/erl_eval/runtime-module-compilation.
I vaguely remember it being ‘fast enough’ for a small-time advertising auction hot path when I last used it (5+ years ago), no idea if it still is the best option. The need here was to take the request, turn it into a match_spec and run it over targeting rules.
On a related note, merl was helpful for my RADIUS encoder/decoder. I parsed the dictionaries and emitted code directly…in a similar vain to using ASN.1 but for RADIUS.
(Disclaimer: This is not a trick and definitely not a tip. Do this only at home, not in public
)
A while ago, @juhlig told me about a presentation from a conference he attended, where somebody created a fun project for an obfuscation library that turns Clojure code into Morse code which is still valid Clojure code, and I was like “Haha, yeah, whatever serves to waste your time
”.
But just lately, I realized what fun stuff you can do, also in Erlang.
The below is valid, working Erlang code
(sane versions in comments):
-module(hugger).
-export(['🤗'/1]).
% -export([hug/1]).
'🤗'('😢') -> '🙁';
% hug(crying_person) -> sad_person;
'🤗'('🙁') -> '😐';
% hug(sad_person) -> ok_person;
'🤗'('😐') -> '🙂';
% hug(ok_person) -> happy_person;
'🤗'(Other) -> Other.
% hug(Other) -> Other.
(The module name must not contain non-latin1 characters though, so we can’t go all the way and use Emojis there. Bummer…
)
Trying it out in the shell:
1> hugger:'🤗'('😢').
'🙁'
2> hugger:'🤗'('🙁').
'😐'
3> hugger:'🤗'('😐').
'🙂'
4> hugger:'🤗'('🌳').
'🌳'
5> lists:map(fun hugger:'🤗'/1, ['😢', '🙁', '😐', '🙂', '🌳']).
['🙁','😐','🙂','🙂','🌳']
You. Are. Evil. ![]()
Much as I like you, the day I see something like this used, I swear I’ll sue you for putting crazy ideas in peoples heads ![]()
That said, this was the presentation I attended, last year at ClojureD/ClojureU: :clojureU 2022: "Use of Macros Leads to Remorse" by Paula Gearon - YouTube
Something like this can be done out of the box in Clojure as well btw:
user=> (defn 🤗
[x]
(case x
:😢 :🙁,
:🙁 :😐,
:😐 :🙂,
x))
#'user/🤗
user=> (🤗 :😢)
:🙁
user=> (map 🤗 [:😢 :🙁 :😐 :🙂 :🌳])
(:🙁 :😐 :🙂 :🙂 :🌳)
Sometimes i find block expressions useful especially with list comprehensions
[ begin
do_something(X),
do_something_else(X),
...
end || X <- ...]
This sounds somewhat familiar to me… I wonder why that may be? ![]()
You can implement a rather efficient single-shot “pub/sub” via monitors, and pass data in a ‘DOWN’ messages:
In this vain, plenty of tricks in:
One of the really interesting tricks to come of it was to raise the process priority of the dispatcher.