• Website
  • Search
  • Member List
  • Help
  • Old Forum
  • Social Media
    •   @Wings3dOfficial
    •   @Wings3dOfficial
    •   Wings3dOfficial
    •   Wings3dOfficial
  • Register
  • Login
  • Website
  • Search
  • Member List
  • Help
  • Old Forum
  • Register
  • Login
Wings 3D Development Forum Wings 3D Programming v
« Previous 1 2 3 4
Tidy recursion

 
  • 0 Vote(s) - 0 Average
Tidy recursion

nemyax
Offline

Member

Posts: 128
Threads: 14
Joined: Nov 2012
#1
05-17-2013, 12:22 PM (This post was last modified: 05-17-2013, 12:57 PM by nemyax.)
Which is the best recursion method?
I like the first one, but does it introduce too much overhead?

1)
Code:
get_indices(<<>>) ->
    [];
get_indices(Bin) ->
    {<<I:16/unsigned-little-integer>>,NewBin} = split_binary(Bin, 2),
    [I|get_indices(NewBin)].

2)
Code:
get_indices(<<>>) ->
    [];
get_indices(Bin) ->
    {<<I:16/unsigned-little-integer>>,NewBin} = split_binary(Bin, 2),
    [I] ++ get_indices(NewBin).

3)
Code:
get_indices(Bin) ->
    get_indices(Bin, []).
get_indices(<<>>, Result) ->
    lists:reverse(Result);
get_indices(Bin, Result) ->
    {<<I:16/unsigned-little-integer>>,NewBin} = split_binary(Bin, 2),
    get_indices(NewBin, [I|Result]).
micheus
Offline

Forum's Admin and Support | Bug fixer
Posts: 3,675
Threads: 183
Joined: Jun 2012
#2
05-18-2013, 06:22 AM
nemyax Wrote:I like the first one, but does it introduce too much overhead?
Considering what we have here I prefer the 2nd one.
In some situations the 1st can result in a list of list that would require to use lists:flatten to make it a plain list - depending on how you will use it.

(05-17-2013, 12:22 PM)nemyax Wrote: Which is the best recursion method?
Always as possible try to use List Comprehensions or - in this case - Bit String Comprehensions - it's faster!

In your case:
Code:
get_indices(Bin) ->
    [ I || <<I:16/little>> <= Bin ].
Simple like that!

p.s.
1) you don't need to write this full declaration: I:16/unsigned-little-integer
writing just I:16/little will produce the same result and would make your code easy to read.
In accord with Bit Syntax Expressions documentation, unsigned and integer are default value for the type specifier list.

2) It's good see someone else coding for Wings3d. Smile
nemyax
Offline

Member

Posts: 128
Threads: 14
Joined: Nov 2012
#3
05-19-2013, 09:14 PM
micheus
Thanks for the tips.
My doubts are due to Joe Armstrong saying this in Programming Erlang in a section about tail recursion:
Quote:if you write a function F that never returns (such as loop()), make sure that you never call anything after calling F, and don’t use F in a list or tuple constructor.
In both 1 and 2, the last expression looks like a list constructor, so it might inflate the stack noticeably if the binary is huge (I don't know for sure — no idea how these expressions would be compiled).
I think I picked up the trick with the arity bump and the introduction of an accumulator from the Wings source, so there must be a reason why this is used.
By contrast, the Haskell examples I've seen don't make a fuss about using the x:myFunction xs notation, and it really does look neat.

(05-18-2013, 06:22 AM)micheus Wrote: It's good see someone else coding for Wings3d. Smile
Well, what's the use. No one seems to be using my crap =)
dgud
Offline

Grumpy Dev
Posts: 692
Threads: 37
Joined: Nov 2012
#4
05-20-2013, 01:50 PM (This post was last modified: 05-20-2013, 01:57 PM by dgud.)
Micheus is right, the binary comprehension is the best for this code.

So example is kind of bad, for the question.
And the answer is that it depends, you will have to measure which one is fastest,
in current release, previously example 3 was always best and will be always be
if you don't need the lists:reverse at the end.
Now (since Björn have made some optimizations in erlang) if you really want
the fastest implementation you will have to measure, but for most of the
cases it doesn't matter if you use 1) or 3)
Number 2 is ugly and creates an unnecessary extra list.

If you want to return more than one thing only 3) is possible.

What I think Joe is saying is to avoid doing something like this.

init() ->
Result = loop(),
{ok, Result}.

loop() ->
receive
quit -> 42;
Msg -> io:format("Msg ~p~n",[Msg]),
loop()
end.

Which must save init function on the stack until loop returns.
See: http://en.wikipedia.org/wiki/Tail_call for a better explanation :-)
micheus
Offline

Forum's Admin and Support | Bug fixer
Posts: 3,675
Threads: 183
Joined: Jun 2012
#5
05-20-2013, 01:58 PM
(05-20-2013, 01:50 PM)dgud Wrote: Number 2 is ugly and creates an unnecessary extra list.
Good to know, even I prefer it to the 1st. Thanks.
« Next Oldest | Next Newest »

Users browsing this thread: 1 Guest(s)



  • View a Printable Version
  • Subscribe to this thread
Forum Jump:

© Designed by D&D - Powered by MyBB

Linear Mode
Threaded Mode