> I am not sure I understand why we have them. For instance I can take the following code
> is_greater_than(X, Y) ->
> if
> X>Y ->
> true;
> true -> % works as an 'else' branch
> false
> end.
> And make it
> is_true(true) ->
> true;
> is_true(false) ->
> false.
> is_greater_than(X, Y) ->
> is_true(X>Y).
> I can do the same thing with case statements
> is_valid_signal(Signal) ->
> case Signal of
> {signal, _What, _From, _To} ->
> true;
> {signal, _What, _To} ->
> true;
> _Else ->
> false
> end.
> Becomes
> switch_signal({signal, _What, _From, _To}) ->
> true;
> switch_signal({signal, _What, _To}) ->
> true;
> switch_signal(_Else) ->
> false.
> I know that the control structures are a little bit faster, not much, but I find that the function form is more readable. > _______________________________________________
> erlang-questions mailing list
> erlang-questi...@erlang.org
> http://erlang.org/mailman/listinfo/erlang-questions
That is interesting. I didn't know that. I wonder why over 100 million
iterations I consistently get between 1 to 2 second differences in timing.
I know that there will be differences due to garbage collection, other
processes running, etc, but the is_greater_than_control/2 function always
outperforms the is_greater_than/2 function. Am I making a wrong assumption
and eventually the opposite would be true? Could you test the below code on
your system and let me know if you get similar results?
-module(test).
-compile(export_all).
is_true(true) ->
true;
is_true(false) ->
false.
is_greater_than(X, Y) ->
is_true(X>Y).
is_greater_than_control(X, Y) ->
if
X>Y ->
true;
true -> % works as an 'else' branch
false
end.
> is compiled internally to one function with case
> so code speed is equal
> there is only difference in readability.
> On Aug 27, 2012, at 10:56 PM, Jayson Barley <jayson.bar...@gmail.com>
> wrote:
> > I am not sure I understand why we have them. For instance I can take the
> following code
> > is_greater_than(X, Y) ->
> > if
> > X>Y ->
> > true;
> > true -> % works as an 'else' branch
> > false
> > end.
> > And make it
> > is_true(true) ->
> > true;
> > is_true(false) ->
> > false.
> > is_greater_than(X, Y) ->
> > is_true(X>Y).
> > I can do the same thing with case statements
> > is_valid_signal(Signal) ->
> > case Signal of
> > {signal, _What, _From, _To} ->
> > true;
> > {signal, _What, _To} ->
> > true;
> > _Else ->
> > false
> > end.
> > Becomes
> > switch_signal({signal, _What, _From, _To}) ->
> > true;
> > switch_signal({signal, _What, _To}) ->
> > true;
> > switch_signal(_Else) ->
> > false.
> > I know that the control structures are a little bit faster, not much,
> but I find that the function form is more readable.
> > _______________________________________________
> > erlang-questions mailing list
> > erlang-questi...@erlang.org
> > http://erlang.org/mailman/listinfo/erlang-questions
module 'test' ['is_greater_than'/2,
'is_greater_than_control'/2,
'is_true'/1,
'module_info'/0,
'module_info'/1]
attributes []
'is_true'/1 =
%% Line 5
fun (_cor0) ->
case _cor0 of
<'true'> when 'true' ->
%% Line 6
'true'
%% Line 7
<'false'> when 'true' ->
%% Line 8
'false'
( <_cor1> when 'true' ->
( primop 'match_fail'
({'function_clause',_cor1})
-| [{'function_name',{'is_true',1}}] )
-| ['compiler_generated'] )
end
'is_greater_than'/2 =
%% Line 10
fun (_cor1,_cor0) ->
let <_cor2> =
%% Line 11
call 'erlang':'>'
(_cor1, _cor0)
in %% Line 11
apply 'is_true'/1
(_cor2)
'is_greater_than_control'/2 =
%% Line 13
fun (_cor1,_cor0) ->
%% Line 15
case <> of
%% Line 16
<>
when call 'erlang':'>'
(_cor1,
_cor0) ->
%% Line 17
'true'
%% Line 18
<> when 'true' ->
%% Line 19
'false'
end
'module_info'/0 =
fun () ->
call 'erlang':'get_module_info'
('test')
'module_info'/1 =
fun (_cor0) ->
call 'erlang':'get_module_info'
('test', _cor0)
end
On Mon, Aug 27, 2012 at 5:44 PM, Jayson Barley <jayson.bar...@gmail.com>wrote:
> That is interesting. I didn't know that. I wonder why over 100 million
> iterations I consistently get between 1 to 2 second differences in timing.
> I know that there will be differences due to garbage collection, other
> processes running, etc, but the is_greater_than_control/2 function always
> outperforms the is_greater_than/2 function. Am I making a wrong assumption
> and eventually the opposite would be true? Could you test the below code on
> your system and let me know if you get similar results?
>> is compiled internally to one function with case
>> so code speed is equal
>> there is only difference in readability.
>> On Aug 27, 2012, at 10:56 PM, Jayson Barley <jayson.bar...@gmail.com>
>> wrote:
>> > I am not sure I understand why we have them. For instance I can take
>> the following code
>> > is_greater_than(X, Y) ->
>> > if
>> > X>Y ->
>> > true;
>> > true -> % works as an 'else' branch
>> > false
>> > end.
>> > And make it
>> > is_true(true) ->
>> > true;
>> > is_true(false) ->
>> > false.
>> > is_greater_than(X, Y) ->
>> > is_true(X>Y).
>> > I can do the same thing with case statements
>> > is_valid_signal(Signal) ->
>> > case Signal of
>> > {signal, _What, _From, _To} ->
>> > true;
>> > {signal, _What, _To} ->
>> > true;
>> > _Else ->
>> > false
>> > end.
>> > Becomes
>> > switch_signal({signal, _What, _From, _To}) ->
>> > true;
>> > switch_signal({signal, _What, _To}) ->
>> > true;
>> > switch_signal(_Else) ->
>> > false.
>> > I know that the control structures are a little bit faster, not much,
>> but I find that the function form is more readable.
>> > _______________________________________________
>> > erlang-questions mailing list
>> > erlang-questi...@erlang.org
>> > http://erlang.org/mailman/listinfo/erlang-questions
On Mon, Aug 27, 2012 at 3:35 PM, Paul Oliver <puzza...@gmail.com> wrote:
> You can use erlc +to_core to get the core erlang:
> module 'test' ['is_greater_than'/2,
> 'is_greater_than_control'/2,
> 'is_true'/1,
> 'module_info'/0,
> 'module_info'/1]
> attributes []
> 'is_true'/1 =
> %% Line 5
> fun (_cor0) ->
> case _cor0 of
> <'true'> when 'true' ->
> %% Line 6
> 'true'
> %% Line 7
> <'false'> when 'true' ->
> %% Line 8
> 'false'
> ( <_cor1> when 'true' ->
> ( primop 'match_fail'
> ({'function_clause',_cor1})
> -| [{'function_name',{'is_true',1}}] )
> -| ['compiler_generated'] )
> end
> 'is_greater_than'/2 =
> %% Line 10
> fun (_cor1,_cor0) ->
> let <_cor2> =
> %% Line 11
> call 'erlang':'>'
> (_cor1, _cor0)
> in %% Line 11
> apply 'is_true'/1
> (_cor2)
> 'is_greater_than_control'/2 =
> %% Line 13
> fun (_cor1,_cor0) ->
> %% Line 15
> case <> of
> %% Line 16
> <>
> when call 'erlang':'>'
> (_cor1,
> _cor0) ->
> %% Line 17
> 'true'
> %% Line 18
> <> when 'true' ->
> %% Line 19
> 'false'
> end
> 'module_info'/0 =
> fun () ->
> call 'erlang':'get_module_info'
> ('test')
> 'module_info'/1 =
> fun (_cor0) ->
> call 'erlang':'get_module_info'
> ('test', _cor0)
> end
> On Mon, Aug 27, 2012 at 5:44 PM, Jayson Barley <jayson.bar...@gmail.com>wrote:
>> That is interesting. I didn't know that. I wonder why over 100 million
>> iterations I consistently get between 1 to 2 second differences in timing.
>> I know that there will be differences due to garbage collection, other
>> processes running, etc, but the is_greater_than_control/2 function always
>> outperforms the is_greater_than/2 function. Am I making a wrong assumption
>> and eventually the opposite would be true? Could you test the below code on
>> your system and let me know if you get similar results?
>>> is compiled internally to one function with case
>>> so code speed is equal
>>> there is only difference in readability.
>>> On Aug 27, 2012, at 10:56 PM, Jayson Barley <jayson.bar...@gmail.com>
>>> wrote:
>>> > I am not sure I understand why we have them. For instance I can take
>>> the following code
>>> > is_greater_than(X, Y) ->
>>> > if
>>> > X>Y ->
>>> > true;
>>> > true -> % works as an 'else' branch
>>> > false
>>> > end.
>>> > And make it
>>> > is_true(true) ->
>>> > true;
>>> > is_true(false) ->
>>> > false.
>>> > is_greater_than(X, Y) ->
>>> > is_true(X>Y).
>>> > I can do the same thing with case statements
>>> > is_valid_signal(Signal) ->
>>> > case Signal of
>>> > {signal, _What, _From, _To} ->
>>> > true;
>>> > {signal, _What, _To} ->
>>> > true;
>>> > _Else ->
>>> > false
>>> > end.
>>> > Becomes
>>> > switch_signal({signal, _What, _From, _To}) ->
>>> > true;
>>> > switch_signal({signal, _What, _To}) ->
>>> > true;
>>> > switch_signal(_Else) ->
>>> > false.
>>> > I know that the control structures are a little bit faster, not much,
>>> but I find that the function form is more readable.
>>> > _______________________________________________
>>> > erlang-questions mailing list
>>> > erlang-questi...@erlang.org
>>> > http://erlang.org/mailman/listinfo/erlang-questions
"if" is indeed a special case of "case",
and "case" is basically an in-lined function call.
And there is a hint: if you are going to inline
a function call, what are you going to inline it
*as*? The possibility must exist in the core
syntax, if nowhere else.
But "try" and "receive" couldn't be anything else.
Without "receive", we'd have to use channels.
> is_greater_than(X, Y) ->
> is_true(X>Y).
That would never have worked in the Good Old Days,
where X > Y was a guard test and not usable in an
ordinary expression.
> I know that the control structures are a little bit faster, not much, but I find that the function form is more readable.
> I know that the control structures are a little bit faster, not much, but
> I find that the function form is more readable.
A case structure is like an *anonymous* function in this. The use case for
them is the same as the use case for funs.
You had to come up with, even in your trivial example, two module-global
symbols: is_valid_signal/1 and switch_signal/1. Take a non-trivial module,
now, and multiply it by the number of public API functions. You'll start
getting name clashes as you go on. For example, with your code above, what
happens if I want to tell a device to change the signal it's sending? I
can't use switch_signal/1 any longer, so I have to use something like
change_signal/1 instead. Now I've got two functions, switch_signal/1 and
change_signal/1, that look very similar by name. I have to dig deeper to
figure out which does what if I'm maintaining the code base. You could
argue that this is because switch_signal/1 is poorly named, but then it
falls right back into why case structures are useful: they're *anonymous*.
Anonymous constructs (cases, funs, etc.) are quite often very useful.
Further, your version of is_valid_signal/1 has a larger cognitive load. In
the first case, if I want to know what is_valid_signal does and how it
works, I look up one function. All the information I need to understand
the function is in one place. With your solution this is now divided up
into multiple places. There's more work to decode what's going on. This
being a trivial function disguises the effect somewhat, but in a larger,
less trivial function this can be an impediment, again, to understanding
the code and reasoning about its behaviour.
-- "Perhaps people don't believe this, but throughout all of the discussions
of entering China our focus has really been what's best for the Chinese
people. It's not been about our revenue or profit or whatnot."
--Sergey Brin, demonstrating the emptiness of the "don't be evil" mantra.
On Mon, Aug 27, 2012 at 10:56 PM, Jayson Barley <jayson.bar...@gmail.com> wrote:
> I am not sure I understand why we have them. For instance I can take the
> following code
> is_greater_than(X, Y) ->
> if
> X>Y ->
> true;
> true -> % works as an 'else' branch
> false
> end.
> Your is_true/1 means that it may meet either true, false, or other values.
However, 'if' statement means that it would meet two cases definitely.
is_true/1 is an identity function (fun(X) -> X end) working on Boolean
values.
Then it may be is_true(X>Y) or is_true(is_true(X>Y)) or
is_true(is_true(is_true(is_true(is_true(is_true(X>Y)))))).
Eventually, It is (X > Y).
In my opinion, 'if' block limits the domain, and 'case' block provides
a way more writable than to write many function heads to pick its
matching patterns.
> On 28/08/12 7:04 PM, Volodymyr Kyrychenko wrote:
>> Jayson Barley wrote:
>>> I am not sure I understand why we have them. For instance I can take the
>>> following code
>>> is_greater_than(X, Y) ->
>>> if
>>> X>Y ->
>>> true;
>>> true -> % works as an 'else' branch
>>> false
>>> end.