[erlang-questions] Orelse and andalso as short-hand for case

123 views
Skip to first unread message

Viktor Söderqvist

unread,
Jul 22, 2018, 8:25:17 AM7/22/18
to erlang-q...@erlang.org
Hey everyone,

I've seen these short-circuit operators with a non-boolean second
operand, usually where the second operand is doing some side-effect and
the return value is not important. It seems to be a trend. Example:

Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),

I this good or bad style?
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Loïc Hoguin

unread,
Jul 22, 2018, 8:32:43 AM7/22/18
to Viktor Söderqvist, erlang-q...@erlang.org
Neither.

The problem with this and the list comprehension equivalent

[io:format("Message: ~s~n", [Msg]) || Msg /= undefined]

is that it will confuse people who never encountered it before.

But if one or both of these forms were teached to beginners and everyone
was using them, then there'd be no problem in using them anymore.

I'd love if they became more popular.

Cheers,

--
Loïc Hoguin
https://ninenines.eu

Robert Raschke

unread,
Jul 22, 2018, 9:24:11 AM7/22/18
to Viktor Söderqvist, Erlang Questions
I think this kind of style originated in languages like Perl, Lua and Javascript for writing shorthand code for default values. Things like "v = v or -1".

From there things spread, leading to odd combinations, like the examples you quote with side effects.

In the end it is about readability, sometimes the shortcut can read nicer than a case or if statement. And sometimes it is clearer to be a teensy bit more verbose.

Robby

Jachym Holecek

unread,
Jul 22, 2018, 3:09:27 PM7/22/18
to Viktor Söderqvist, erlang-q...@erlang.org
Hi,

# Viktor Söderqvist 2018-07-22:
> Hey everyone,
>
> I've seen these short-circuit operators with a non-boolean second
> operand, usually where the second operand is doing some side-effect and
> the return value is not important. It seems to be a trend. Example:
>
> Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
>
> I this good or bad style?

It is horrible style. Pain to read, pain to modify, pain to reason about.

Simple clear question deserves a simple clear answer. :-)

BR,
-- Jachym

Jesper Louis Andersen

unread,
Jul 23, 2018, 7:06:29 AM7/23/18
to fr...@circlewave.net, Erlang (E-mail)
On Sun, Jul 22, 2018 at 9:09 PM Jachym Holecek <fr...@circlewave.net> wrote:
# Viktor Söderqvist 2018-07-22:

>
>     Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
>
> I this good or bad style?

It is horrible style. Pain to read, pain to modify, pain to reason about.

Simple clear question deserves a simple clear answer. :-)


​I don't like the style either, mostly because it messes with the types. andalso and orelse expects boolean expressions, but the style used breaks that format. However, something like

[x || Msg /= undefined]

doesn't.​


--
J.

Dmytro Lytovchenko

unread,
Jul 23, 2018, 7:21:03 AM7/23/18
to Jesper Louis Andersen, Erlang (E-mail)
Just checked that a function is not created when you compile [X || condition] and it creates a check and a branch instruction.
Amazing.
Thanks for the tip.

黃耀賢 (Yau-Hsien Huang)

unread,
Jul 23, 2018, 7:26:04 AM7/23/18
to Erlang-Questions Questions
IMO, it's meaningful.

Think that,

Msg /= nil and io:fwrite("blah, blah, ...~n"). %% It won't build a boolean expression.

But

Msg /= nil andalso io:fwrite("blah, blah, ...~n"). %% Confirm the Msg is nothing and also say "blah, blah, ..."

I think the reason why andalso/2 was built. Though, andalso/2 won't be used for a general default value usage like what we saw in JS or Perl, because the first argument of andalso/2 must be either true or false.



_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions




--

Best Regards.

--- Y-H. H.

Dmitry Belyaev

unread,
Jul 23, 2018, 9:33:13 AM7/23/18
to erlang-q...@erlang.org, Jesper Louis Andersen, fr...@circlewave.net, Erlang (E-mail)
How does it mess with types? The andalso and orelse operators should only care about the type of the first operand and it always is boolean.

I personally don't like list comprehension as brackets create additional noise and might not be obvious to other developers.

Also dialyzer may complain about unused value in either of ways, so the cleanest is probably case or if. The latter in Elixir doesn't require else branch which reduces noise a little bit.
Kind regards,
Dmitry Belyaev

Jesper Louis Andersen

unread,
Jul 23, 2018, 9:53:56 AM7/23/18
to Dmitry Belyaev, Erlang (E-mail)
On Mon, Jul 23, 2018 at 3:32 PM Dmitry Belyaev <be.d...@gmail.com> wrote:
How does it mess with types? The andalso and orelse operators should only care about the type of the first operand and it always is boolean.


​Assume a GADT or dependently typed language. Then we have something like (forgive me the rust on the Agdaish notation used here):

data Ty where
  Bool : Ty
  Int : Ty

data Expr (t : Ty) : Set where
  andAlso : Expr Bool -> Expr Bool -> Expr Bool
  orElse : Expr Bool -> Expr Bool -> Expr Bool
  ...

​and this is the normal canonical definition most statically typed languages use. You propose

data Expr (t : Ty) : Set where
  andAlso : Expr Bool -> Expr t -> Expr ?
  orElse : Expr Bool -> Expr t -> Expr ?
  ...

but the complication is that you have to be able to tell the system what the '?' should be. It is some union type over either Bool or t for any type t, but this easily complicates the type rules of the language. This is why I say it is a "mess". You might come up with a solution, but that solution will usually lead to an acceptance of a larger body of programs in which some of the programs will be weaker from a type perspective. Or it will lead to programs which has to do more runtime checking which are slower programs.

Finally, in a dynamically typed language like Erlang, you indeed can give it a somewhat meaningful result by your proposal. But my view, as it often does, comes from 15 years of statically typed programming in Standard ML, OCaml and Haskell.


greim

unread,
Jul 23, 2018, 10:01:32 AM7/23/18
to erlang-q...@erlang.org
"Programs must not regarded as code for computers,
but as literature for humans"

Nicklaus Wirth, Turing Award 1984

.......
so whats your opinion about:

Msg /= undefined maybeornot io:format("Message: ~s~n", [Msg]),

or much more readable and clear with a well defined operator, because we
have a functional language:

Msg /= undefined F@*#! io:format("Message: ~s~n", [Msg]),

Markus Greim

Dmitry Kolesnikov

unread,
Jul 23, 2018, 10:17:10 AM7/23/18
to Dmitry Belyaev, Jesper Louis Andersen, fr...@circlewave.net, Erlang Mailing List
This is a clear case for Option data type…

I would prefer to use explicit definition of a function that is able to handle undefined values 

```
print(undefined) ->
   undefined;
print(Msg) ->
   io:format("Message: ~s~n", [Msg]).
``` 

Alternatively, there is a parse transforms for composition of maybe/option types (https://github.com/fogfish/datum/blob/master/doc/category.md#option)

Long time ago, I’ve used andalso syntax but it never stays longer at code repository due to readability. It has been refactored to function(s) with guards or pattern match.

Best Regards, 
Dmitry 


signature.asc

Danil Zagoskin

unread,
Jul 23, 2018, 11:32:52 AM7/23/18
to vik...@zuiderkwast.se, Erlang/OTP discussions
Hi!

I find this style convenient for debugging.
Sometimes you need some binding to be logged, but only under some rare conditions. After the problem is fixed the added code should be removed or commented-out.

Adding a simple if (or case) costs you 4 lines and an extra tabulation.
Removing/disabling that requires selecting several lines, then deleting/commenting them.

Adding a wrapper function invades the code in two places.
Removing that requires extra seeking to the helper function. Disabling (commenting the call) requires disabling the function too,
to avoid unused function warning. Much pain.

A single-liner with andalso/orelse is easy to write (shorter than other options) and easy to remove/disable (just jump to line + single dd or I in vim).
--
Danil Zagoskin | z...@gosk.in

黃耀賢 (Yau-Hsien Huang)

unread,
Jul 23, 2018, 11:48:19 AM7/23/18
to Erlang-Questions Questions
Though the RHS of andalso is not typed in Erlang.

On Mon, Jul 23, 2018 at 10:35 PM, Richard O'Keefe <rao...@gmail.com> wrote:
No, that is *not* why andalso/2 was added to the language.
The very spelling of the token, 'andalso', was copied from
a language, Standard ML, which is strictly typed and does
not allow <test> andalso <action>.

Ivan Uemlianin

unread,
Jul 23, 2018, 12:32:34 PM7/23/18
to erlang-q...@erlang.org
Yes, same here.  Anything clever but unreadable I would put in an informatively-named function.  I might call this print_unless_undefined/1.

Ivan
-- 
============================================================
Ivan A. Uemlianin PhD
Llaisdy

Ymchwil a Datblygu Technoleg Lleferydd
Speech Technology Research and Development

                    iv...@llaisdy.com
                        @llaisdy
                         llaisdy.wordpress.com
              github.com/llaisdy
                     www.linkedin.com/in/ivanuemlianin

                        festina lente
============================================================ 

黃耀賢 (Yau-Hsien Huang)

unread,
Jul 23, 2018, 1:41:26 PM7/23/18
to Erlang-Questions Questions
I'm not interested in so-called "it's for something but the other." By typing some code in both shell, I got an error message in SML/NJ when typing the following code,

> true andalso nil;

though I got similar code working smoothly in Erlang when typing the following code,

> is_list(true andalso []). %% The shell reported `true`.

So, what's the meaning of "being copied into?" Is it rigid that you borrow a word from a language and keep all the nature of it? I don't think so.



On Tue, Jul 24, 2018 at 12:58 AM, Richard O'Keefe <rao...@gmail.com> wrote:
Yes, I know the RHS of 'andalso' is not typed in Erlang.
So what?  The point is that when 'andalso' and 'orelse'
were copied into Erlang from Standard ML, they did not
drag the obsolete baggage of being ersatzes for WHEN and
UNLESS in with them.  They were added to provide
non-strict AND and OR for Boolean expressions, and that
is all they were added for, just as 'and' and 'or' were
added to provide strict AND and OR.

They were not added to provide a cryptic way to obfuscate
conditionals you could already easily write.



On 24 July 2018 at 03:48, 黃耀賢 (Yau-Hsien Huang) <g9414002.pccu.edu.tw@gmail.com> wrote:
Though the RHS of andalso is not typed in Erlang.
On Mon, Jul 23, 2018 at 10:35 PM, Richard O'Keefe <rao...@gmail.com> wrote:
No, that is *not* why andalso/2 was added to the language.
The very spelling of the token, 'andalso', was copied from
a language, Standard ML, which is strictly typed and does
not allow <test> andalso <action>.

zx...@zxq9.com

unread,
Jul 23, 2018, 11:42:18 PM7/23/18
to erlang-q...@erlang.org
On 2018年7月22日日曜日 14時25分00秒 JST Viktor Söderqvist wrote:
> Hey everyone,
>
> I've seen these short-circuit operators with a non-boolean second
> operand, usually where the second operand is doing some side-effect and
> the return value is not important. It seems to be a trend. Example:
>
> Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
>
> I this good or bad style?

That code should die in a fire and the author should say repent with
the chanting of 100 Hail McCarthys.

-Craig

Pierre Fenoll

unread,
Jul 24, 2018, 3:20:24 AM7/24/18
to zx...@zxq9.com, erlang-q...@erlang.org
I don’t understand the strong answers.
To me the semantics of orelse/and also are well known. They are even known as ||/&& in the mainstream. 
They have their use as the common boolean shortcut operators. They are even more than that:
case ShouldOpen andalso file:open(...) of
false ->
{error,_} ->
{ok,_} ->
end

These operators are very interesting semantics. Erlang is not exactly a pure language. Being able to express side effects in such an easy-to-comment amount of code that’s just priceless. Here’s a legit example: 

So why the big words? What’s next, the process dictionary, using list comprehensions with 1-element lists generators?
To me if you don’t like this kind of code it’s only because you have not needed / seen it much. So, read more code?
--

Cheers,
-- 
Pierre Fenoll

greim

unread,
Jul 24, 2018, 3:38:28 AM7/24/18
to erlang-q...@erlang.org
Am 23.07.2018 um 16:28 schrieb Ivan Uemlianin:
> Yes, same here.  Anything clever but unreadable I would put in an
> informatively-named function.  I might call this print_unless_undefined/1.
>

yep, now we are going in the right direction, that is self explaining!

Markus


> Ivan
>
>
> On 23/07/2018 15:16, Dmitry Kolesnikov wrote:
>> This is a clear case for Option data type…
>>
>> I would prefer to use explicit definition of a function that is able
>> to handle undefined values
>>
>> ```
>> print(undefined) ->
>>    undefined;
>> print(Msg) ->
>>    io:format("Message: ~s~n", [Msg]).
>> ```
>>
>> Alternatively, there is a parse transforms for composition of
>> maybe/option types
>> (https://github.com/fogfish/datum/blob/master/doc/category.md#option)
>>
>> Long time ago, I’ve used andalso syntax but it never stays longer at
>> code repository due to readability. It has been refactored to
>> function(s) with guards or pattern match.
>>
>> Best Regards,
>> Dmitry
>>
>>
>>> On 23 Jul 2018, at 16.32, Dmitry Belyaev <be.d...@gmail.com

>>> <mailto:be.d...@gmail.com>> wrote:
>>>
>>> How does it mess with types? The andalso and orelse operators should
>>> only care about the type of the first operand and it always is boolean.
>>>
>>> I personally don't like list comprehension as brackets create
>>> additional noise and might not be obvious to other developers.
>>>
>>> Also dialyzer may complain about unused value in either of ways, so
>>> the cleanest is probably case or if. The latter in Elixir doesn't
>>> require else branch which reduces noise a little bit.
>>>
>>> On 23 July 2018 21:05:37 GMT+10:00, Jesper Louis Andersen
>>> <jesper.lou...@gmail.com

>>> <mailto:jesper.lou...@gmail.com>> wrote:
>>>
>>> On Sun, Jul 22, 2018 at 9:09 PM Jachym Holecek
>>> <fr...@circlewave.net <mailto:fr...@circlewave.net>> wrote:
>>>
>>> # Viktor Söderqvist 2018-07-22:
>>> >
>>> >     Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
>>> >
>>> > I this good or bad style?
>>>
>>> It is horrible style. Pain to read, pain to modify, pain to
>>> reason about.
>>>
>>> Simple clear question deserves a simple clear answer. :-)
>>>
>>>
>>> ​I don't like the style either, mostly because it messes with the
>>> types. andalso and orelse expects boolean expressions, but the
>>> style used breaks that format. However, something like
>>>
>>> [x || Msg /= undefined]
>>>
>>> doesn't.​
>>>
>>>
>>> --
>>> Kind regards,
>>> Dmitry Belyaev
>>> _______________________________________________
>>> erlang-questions mailing list

>>> erlang-q...@erlang.org <mailto:erlang-q...@erlang.org>

zx...@zxq9.com

unread,
Jul 24, 2018, 4:01:49 AM7/24/18
to erlang-q...@erlang.org
On 2018年7月24日火曜日 9時19分56秒 JST Pierre Fenoll wrote:
> I don’t understand the strong answers.
> To me the semantics of orelse/and also are well known.

"To me... well known"

Says it all.

Nathaniel Waisbrot

unread,
Jul 24, 2018, 8:07:17 AM7/24/18
to zx...@zxq9.com, erlang-q...@erlang.org

> On Jul 24, 2018, at 4:00 AM, zx...@zxq9.com wrote:
>
>> On 2018年7月24日火曜日 9時19分56秒 JST Pierre Fenoll wrote:
>> I don’t understand the strong answers.
>> To me the semantics of orelse/and also are well known.
>
> "To me... well known"
>
> Says it all.


Well, it’s a pattern I’ve seen in both lisp and javascript, so I agree that it’s not a totally wild idea. A pretty wide swath of programmers should be able to recognize what’s happening.

I feel like avoiding the pattern is more on the language than the programmer, too. You don’t see this pattern in languages without side-effects and you don’t get it when both sides of && must be booleans. OTOH if the language hands me a tool and I see a convenient use for it, why should I hold back?

Led

unread,
Jul 24, 2018, 8:41:24 AM7/24/18
to erlang-q...@erlang.org
2018-07-24 10:19 GMT+03:00 Pierre Fenoll <pierre...@gmail.com>:
I don’t understand the strong answers.


Do not pay attention to ruby-influensed people :)

--
Led.

emp...@web.de

unread,
Jul 24, 2018, 8:42:07 AM7/24/18
to erlang-q...@erlang.org
Am Tue, 24 Jul 2018 09:19:56 +0200
schrieb Pierre Fenoll <pierre...@gmail.com>:

> I don’t understand the strong answers.

Then let me try to help :-)


> To me the semantics of orelse/and also are well known.

Are they? Or do you merely know of a different way to
(ab)use them?


> They are even known as ||/&& in the mainstream.

The "mainstream"? or C and bash and whatever? What about
Perl's: succeed() or die("fast")?


> They have their use as the common boolean shortcut
> operators.

Languages have their (ab)use by marketing persons and
spokespeople and lawyers; but does that make a better -
easier to learn, expressive, concise - language? a better
world for everyone (or most, actually)?


> These operators are very interesting semantics.

See? Now I have to guess whether this is merely a
(completely acceptable) mistake or something I do not (yet)
understand. Operators are no semantics, but ... It may as
well be that you confuse semantics with syntax, because you
say "easy-to-comment" below, so it might be the syntax
that appeals to you (and others, this all is not
meant to be personal :-).


> not exactly a pure language.

Off topic, this is about whether one codes for the compiler
or the programmer. No compiler has ever lamented about the
Obfuscated C Code Contest, full of things one _can_
write ... "Pure"? like 'completely and only functional'?
All programs will eventually push something to an output
device, which is inherently non-functional (or is it?)


> Being able to express side
> effects in such an easy-to-comment amount of code that’s
> just priceless.

Concise is fine, simply and only and first of all 'few
lines' is not price- but ruthless.

Is it legit? why? Why not:

if Pid =:= WorkerPid -> throw({'task', Task}) end,

? Not even now I am sure that this translation is correct,
and that after the much too long time that code forced me
to spend on understanding it. I am sure the compiler does
not complain ...


> So why the big words? What’s next, the process
> dictionary, using list comprehensions with 1-element
> lists generators?

In what better way would you express the process dict? Or
why not spawn a function and stuff all state into its
dictionary, have set/2 and get/1 to mutate and read the
attributes and call it OOerlang ... or WoeWoeErlang ...

If you want to translate/map or reduce/filter a list A to
produce a list B, it does not matter whether A happens to
have only one element or none (apart from []) or several or
many; that is what lists and list comprehension are meant
for. If one does not want to process a list, and does not
even want but create one -

[x || Msg /= undefined]

- then ... perhaps the author should die in a fire ;-)

Note: it does not matter what the compiler (writer) makes
of this.


> To me if you don’t like this kind of
> code it’s only because you have not needed / seen it
> much. So, read more code?

So if people have trouble walking on their hands they need
more practice?

Michael

P. S. All "you"s and "I"s are to be read as 'one'. This
really is not meant to be personal.

--

That, which was said, is not that, which was spoken,
but that, which was understood; and none of these
comes necessarily close to that, which was meant.

Dmitry Belyaev

unread,
Jul 24, 2018, 10:17:47 AM7/24/18
to erlang-q...@erlang.org, emp...@web.de


On 24 July 2018 20:26:57 GMT+10:00, emp...@web.de wrote:
>...
>Why not:
>
> if Pid =:= WorkerPid -> throw({'task', Task}) end,
>

Because it doesn't work for the false case. In Erlang if and case are expressions and they have to be exhaustive and return values for each case. Otherwise they will throw errors.
--
Kind regards,
Dmitry Belyaev

Raimo Niskanen

unread,
Jul 24, 2018, 11:01:40 AM7/24/18
to erlang-q...@erlang.org
On Sun, Jul 22, 2018 at 02:32:29PM +0200, Loïc Hoguin wrote:
> Neither.
>
> The problem with this and the list comprehension equivalent
>
> [io:format("Message: ~s~n", [Msg]) || Msg /= undefined]
>
> is that it will confuse people who never encountered it before.
>
> But if one or both of these forms were teached to beginners and everyone
> was using them, then there'd be no problem in using them anymore.
>
> I'd love if they became more popular.

I do not mind writing nor reading

Msg /= undefined andalso
io:format("Message: ~s~n", [Msg]),

but find

[io:format("Message: ~s~n", [Msg]) ||
Msg /= undefined]

a bit harder to read because the condition comes after the action.

I prefer in any case to use two lines with indentation to hint about
the flow control usage.

(Doesn't Dialyzer complain about the 'andalso' variant because it may
return a 'false' that is ignored?)

Erlang does not have many "ugly tricks" like these, so if it can save
me from 4 uninteresting code lines i certainly do not mind:

case Msg of
undefined ->
ok;
_ ->
io:format("Message: ~s~n", [Msg])
end


>
> Cheers,
>
> On 07/22/2018 02:25 PM, Viktor Söderqvist wrote:
> > Hey everyone,
> >
> > I've seen these short-circuit operators with a non-boolean second
> > operand, usually where the second operand is doing some side-effect and
> > the return value is not important. It seems to be a trend. Example:
> >
> > Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
> >
> > I this good or bad style?
> >
>
> --
> Loïc Hoguin
> https://ninenines.eu

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB

Led

unread,
Jul 24, 2018, 11:04:10 AM7/24/18
to erlang-q...@erlang.org
2018-07-24 13:26 GMT+03:00 <emp...@web.de>:
Why not:

  if Pid =:= WorkerPid -> throw({'task', Task}) end,

?


Are you serious?
Or is this a joke?

--
Led.

emp...@web.de

unread,
Jul 24, 2018, 4:32:38 PM7/24/18
to Led, Erlang mailing-list
Am Tue, 24 Jul 2018 17:30:46 +0300
schrieb Led <led...@gmail.com>:
Sorry! do not attribute to jest what can be explained with
simple stupidity - or so the saying goes ... :-)

Perhaps it was the mentioning of WHEN and UNLESS (that
remove the need for PROGN and the "else" in LISP), perhaps
it was seeing the use of a list comprehension without a list
producing one that was not wanted, perhaps I was
simply trying not to like the "andalso" (which is only
possible since R13A
http://erlang.org/doc/reference_manual/expressions.html#short-circuit-expressions)
or perhaps there is a reason for my "if" being nonsense and
that reason is not to be circumvented with "andalso" ...

... but I seem to be too stupid to see that (yet) :-)

Michael

--

If a bank in need of money is systematically important,
then that system is not important.

Viktor Söderqvist

unread,
Jul 26, 2018, 8:06:09 AM7/26/18
to erlang-q...@erlang.org
Thank you all for the diverse opinions!

Especially, I liked this point from Dmitry Kolesnikov:

> Long time ago, I’ve used andalso syntax but it never stays longer at
> code repository due to readability. It has been refactored to
> function(s) with guards or pattern match.

I think it is the process from prototyping to maintained code.
Refactoring involves gradually adding names to things by introducing
functions, adding specs and rewriting hacks into proper solutions. A
spec with a return type like false | ok | {error, Reason} would make me
reconsider the andalso trick. I guess this process gradually makes the
code change style from dynamically typed style (LISP, Perl) to
statically typed style (ML, Haskell). I find this interesting.

Viktor


On 2018-07-22 14:25, Viktor Söderqvist wrote:
> Hey everyone,
>
> I've seen these short-circuit operators with a non-boolean second
> operand, usually where the second operand is doing some side-effect and
> the return value is not important. It seems to be a trend. Example:
>
> Msg /= undefined andalso io:format("Message: ~s~n", [Msg]),
>
> I this good or bad style?

zx...@zxq9.com

unread,
Jul 26, 2018, 7:53:31 PM7/26/18
to Erlang Questions
For whatever reason, Richard's responses never made it into the archive.
I believe they are worthy of preservation.

-Craig

On 2018年7月25日水曜日 15時00分03秒 JST Richard O'Keefe wrote:
> Pierre Fenoli does not "understand the strong answers".
> I imagine that other people have had the experience of having to maintain
> someone else's code, and after a long struggle to disentangle unduly
> "clever"
> code found themselves shouting "Why did this offspring of an incestuous
> union between two male naked mole-rats not remove xer hands from xer
> genitals long enough to write down what xie actually meant and NOT WASTE
> MY RAPIDLY DWINDLING TIME?"
>
> I am still nowhere near as good a programmer as I would like to be.
> I need to make my own code clearer.
> "What is hateful to you, do not do to others."
> If anyone catches me abusing short-circuit operations, my apologies
> in advance.
>
> The andalso and orelse operators are defined in section 8.14
> http://erlang.org/doc/reference_manual/expressions.html#short-circuit-expressions
> of the Erlang reference manual. It is clear from that that
> these operators originally required their right operand to yield
> true or false, and were only changed in order to allow code like
>
>
> ismember(X, [Y|Ys]) -> X == Y orelse ismember(X, Ys);
> ismember(_, [] ) -> false.
>
> to be tail recursive.
>
> It would be really nice if the Dialyzer would warn about misuses of
> these operators. What about the 'legit example' we were offered?
> It is a blemish in an otherwise pleasant file in an impressive and
> useful project. The only occurrence of 'andalso' in that 628 line
> file is a good example of when NOT to use 'andalso'.
>
> task_by_pid(Pid, #state{tasks = Tasks}) ->
> F = fun (_, #{worker_pid := WorkerPid}=Task, Acc) ->
> Pid =:= WorkerPid
> andalso throw({'task', Task}),
> Acc
> end,
> try maps:fold(F, 'undefined', Tasks)
> catch 'throw':{'task', Task} -> Task
> end.
>
> which is 9 lines. It garden-paths the reader into a
> sort of double negation. The goal of F is *not* to return Acc,
> but to find a Task, and the throw is *not* there to report
> failure, but success.
>
> This can be written, not only without 'andalso',
> but also without 'throw' and 'catch', as
>
> task_by_id(Pid, #state{tasks = Tasks}) ->
> task_with_matching_worker_pid(Pid, Tasks).
>
> task_with_matching_worker_pid(Pid, [Task = #{worker_pid := Pid}|_]) ->
> Task;
> task_with_matching_worker_pid(Pid, [_|Tasks]) ->
> task_with_matching_worker_pid(Pid, Tasks);
> task_with_matching_worker_pid(_, []) ->
> undefined.
>
> which is also 9 lines. To me this is a fairly obvious linear
> search for a matching list element, which leaves me free to
> think about things like whether a map from worker Pids to Tasks
> might not be a better data structure, and also lets me muse,
> "hmm, isn't there already a library function to look for the
> first matching list element? Oh yeah."
>
> task_by_pid(Pid, #state{tasks = Tasks}) ->
> case lists:search(fun (#{worker_pid := Id}) -> Id =:= Pid end, Tasks)
> of {value, Task} -> Task
> ; false -> undefined
> end.
>
> which is now 5 lines, and is how I'd have written it in the first place.
>
> I honestly wasn't expecting this. Given that this was Kazoo, I
> was expecting to have to mumble and shuffle and say "well, maybe
> OCCASIONALLY you can get away with it in otherwise really good
> code", but the abuse of 'andalso' DID turn out to be a 'code smell'
> pointing to contorted code that needed rewriting.
>
> If, as would not be surprising, I have misunderstood thpe original
> code, that just proves my point that it was contorted.

zx...@zxq9.com

unread,
Jul 26, 2018, 7:54:45 PM7/26/18
to Erlang Questions
On 2018年7月25日水曜日 15時09分28秒 JST Richard O'Keefe wrote:

> On 25 July 2018 at 00:06, Nathaniel Waisbrot <nath...@waisbrot.net> wrote:
>
> > if the language hands me a tool and I see a convenient use for it, why
> > should I hold back?
> >
>
> Out of consideration for anyone reading the code in the future,
> including yourself. The language hands you many tools; if you
> need a chisel and you *have* a chisel, why use a screwdriver?
>
> Or as Dr Johnson put it, "Read over your compositions, and
> wherever you meet with a passage which you think is particularly
> fine, strike it out."

This painful guideline saves me much torment every time I find the fortitude to apply it.

-Craig

Per Hedeland

unread,
Jul 27, 2018, 2:38:04 AM7/27/18
to zx...@zxq9.com, Erlang Questions
On 2018-07-27 01:52, zx...@zxq9.com wrote:
> For whatever reason, Richard's responses never made it into the archive.

Actually, it seems his messages consistently do not even reach the
*list*, and are seen only when quoted in other messages - is there some
broken filter on the list, or is he intentionally doing
reply-to-sender-only? (Or did he just switch to a mail client that needs
"Reply-To: <list>"? And no, let's not start that discussion again...)

> I believe they are worthy of preservation.

+1!:-)

--Per

zx...@zxq9.com

unread,
Jul 27, 2018, 10:08:45 PM7/27/18
to Erlang Questions
On 2018年7月27日金曜日 8時37分44秒 JST Per Hedeland wrote:
> On 2018-07-27 01:52, zx...@zxq9.com wrote:
> > For whatever reason, Richard's responses never made it into the archive.
>
> Actually, it seems his messages consistently do not even reach the
> *list*, and are seen only when quoted in other messages - is there some
> broken filter on the list, or is he intentionally doing
> reply-to-sender-only? (Or did he just switch to a mail client that needs
> "Reply-To: <list>"? And no, let's not start that discussion again...)
>
> > I believe they are worthy of preservation.
>
> +1!:-)

I'm not sure. A lot of the messages from him I wind up getting I receive
because I'm on the recipient list separately from the ML (maybe from "reply
to all"?). erlang-questions is usually just CC'd -- which should work just
fine. I can't imagine anyone would filter ROK's messages *out* of the list.
Much to the contrary, if I had the time I would put together a compilation
of his best posts/threads!

So, Richard, if you happen to read this... any idea why your mail isn't
hitting the list lately? Maybe one account or another is unsubscribed?

-Craig

Fred Hebert

unread,
Jul 27, 2018, 10:30:12 PM7/27/18
to zx...@zxq9.com, Erlang Questions
On 07/28, zx...@zxq9.com wrote:
>
>So, Richard, if you happen to read this... any idea why your mail isn't
>hitting the list lately? Maybe one account or another is unsubscribed?
>

A common cause of problems for Mailing lists is the presence or absence
of an SPF record for custom domains. I can't see ROK's e-mail address
from your reposts, but you can do a quick check by doing a DNS lookup.
Here's mine for example:

→ dig ferd.ca ANY
...
;; ANSWER SECTION:
ferd.ca. 3599 IN A 208.94.116.79
ferd.ca. 3599 IN MX 5 ALT2.ASPMX.L.GOOGLE.COM.
ferd.ca. 3599 IN MX 10 ASPMX5.GOOGLEMAIL.COM.
...
ferd.ca. 3599 IN TXT "v=spf1 include:_spf.google.com ~all"
ferd.ca. 3599 IN SOA ns.phx1.nearlyfreespeech.net. hostmaster.nearlyfreespeech.net. 1406273317 600 180 86400 180

The MX records indicate that I'm redirecting everything on gmail, but
the critical one not to be seen as spam or a spoofed e-mail is the TXT
record with the SPF entry in it.

Background info is at https://support.dnsimple.com/articles/spf-record/
or https://en.wikipedia.org/wiki/Sender_Policy_Framework
-- your mail provider should possibly be able to give a line about it so
people can configure their stuff themselves. Google's page is at
https://support.google.com/a/answer/33786?hl=en if you're using gmail.

There's a good chance that something like that could be to blame for
missing/non-forwarded e-mails.

Regards,
Fred.

Dmitry Belyaev

unread,
Jul 27, 2018, 10:54:32 PM7/27/18
to erlang-q...@erlang.org, Fred Hebert, zx...@zxq9.com, rao...@gmail.com, Erlang Questions
I believe Richard's email was provided in one of the responses:


On Mon, Jul 23, 2018 at 10:35 PM, Richard O'Keefe <rao...@gmail.com> wrote:
...

To me it looks like either mailing list configuration or usage of reply instead of reply all - I often do forget about that in Gmail web UI and even in my mobile email client.


Per Hedeland

unread,
Jul 28, 2018, 7:04:21 AM7/28/18
to Dmitry Belyaev, erlang-q...@erlang.org, Fred Hebert, zx...@zxq9.com, rao...@gmail.com
On 2018-07-28 04:54, Dmitry Belyaev wrote:
> I believe Richard's email was provided in one of the responses:
>
> On Mon, Jul 23, 2018 at 10:35 PM, Richard O'Keefe <rao...@gmail.com> wrote:
> ...
>
> To me it looks like either mailing list configuration or usage of reply instead of reply all - I often do forget about that in Gmail web UI and even in my mobile email client.

Surely you're not suggesting that ROK would ever *forget* anything?:-)
But mailing list configuration is likely - AFAIR, this list like most
others block messages from non-subscribers to cut down on spam. And the
last message directly from Richard that I still have in my inbox happens
to be this one:
http://erlang.org/pipermail/erlang-questions/2017-November/094170.html

Raimo did dutifully reply to that message, but one possibility is that
Richard didn't get around to re-subscribing, and get the list messages
forwarded from his old address, while his own messages that use the new
address are blocked. Raimo, maybe you can have a look? I know that it's
outside what can be expected from standard mailing list maintenance, but
this concerns a very special subscriber...

--Per

> On 28 July 2018 12:29:57 GMT+10:00, Fred Hebert <mono...@ferd.ca> wrote:
>
> On 07/28, zx...@zxq9.com wrote:
>
>
> So, Richard, if you happen to read this... any idea why your mail isn't
> hitting the list lately? Maybe one account or another is unsubscribed?
>
>
>
> A common cause of problems for Mailing lists is the presence or absence
> of an SPF record for custom domains. I can't see ROK's e-mail address
> from your reposts, but you can do a quick check by doing a DNS lookup.
> Here's mine for example:
>
> ’ dig ferd.ca ANY
> ...
> ;; ANSWER SECTION:
> ferd.ca. 3599 IN A 208.94.116.79
> ferd.ca. 3599 IN MX 5 ALT2.ASPMX.L.GOOGLE.COM.
> ferd.ca. 3599 IN MX 10 ASPMX5.GOOGLEMAIL.COM.
> ...
> ferd.ca. 3599 IN TXT "v=spf1 include:_spf.google.com ~all"
> ferd.ca. 3599 IN SOA ns.phx1.nearlyfreespeech.net. hostmaster.nearlyfreespeech.net. 1406273317 600 180 86400 180
>
> The MX records indicate that I'm redirecting everything on gmail, but
> the critical one not to be seen as spam or a spoofed e-mail is the TXT
> record with the SPF entry in it.
>
> Background info is athttps://support.dnsimple.com/articles/spf-record/

> orhttps://en.wikipedia.org/wiki/Sender_Policy_Framework


> -- your mail provider should possibly be able to give a line about it so
> people can configure their stuff themselves. Google's page is at
> https://support.google.com/a/answer/33786?hl=en if you're using gmail.
>
> There's a good chance that something like that could be to blame for
> missing/non-forwarded e-mails.
>
> Regards,
> Fred.

> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


>
> erlang-questions mailing list
> erlang-q...@erlang.org
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
> --
> Kind regards,
> Dmitry Belyaev
>
>

> _______________________________________________

_______________________________________________

Joe Harrison

unread,
Aug 3, 2018, 6:58:42 AM8/3/18
to Pierre Fenoll, zx...@zxq9.com, erlang-q...@erlang.org
Let's not forget what happens in the Core Erlang compilation pass:

In Erlang:

f() ->
other:check_db_ok() andalso other:do_db_transaction().

After compilation with +to_core:

f'/0 =
fun () ->
( case call 'other':'check_db_ok'
() of
( <( 'true'
-| ['compiler_generated'] )> when 'true' ->
call 'other':'do_db_transaction'
()
-| ['compiler_generated'] )
( <( 'false'
-| ['compiler_generated'] )> when 'true' ->
'false'
-| ['compiler_generated'] )
( <_@c0> when 'true' ->
( call ( 'erlang'
-| ['compiler_generated'] ):( 'error'
-| ['compiler_generated'] )
(( {( 'badarg'
-| ['compiler_generated'] ),_@c0}
-| ['compiler_generated'] ))
-| ['compiler_generated'] )
-| ['compiler_generated'] )
end
-| ['compiler_generated'] )

Which, as we've all been discussing, is the same as a case expression, and furthermore is de-sugared as such.


24.07.2018, 08:20, "Pierre Fenoll" <pierre...@gmail.com>:

> ,

Reply all
Reply to author
Forward
0 new messages