[erlang-questions] Trying to learn the Erlang Way

Anthony Ramine <>
Fri Feb 7 17:59:18 CET 2014


Hello,

Good luck with your learning.

Replied inline.

Regards,

-- 
Anthony Ramine

Le 7 févr. 2014 à 17:45, kraythe . <> a écrit :

> So now the fixed code is: 
> 
> %% Subtract the second vector from the first
> subtract({X1, Y1, Z1}, {X2, Y2, Z2}) -> {(X1 - X2), (Y1 - Y2), (Z1 - Z2)}.

The parentheses are not required here but you seem to like to use them with arithmetic, won't argue against that.

> %% Compute the magnitude of the vector
> magnitude({X, Y, Z}) -> math:sqrt((X * X) + (Y * Y) + (Z * Z)).
> 
> %% Compute whether the vector with components X, Y and Z has greater magnitude then the passed scalar M. 
> %% Note that this method avoids the expensive sqrt operation. 
> is_magnitude_greater(M, {X, Y, Z}) when is_number(M), is_number(X), is_number(Y), is_number(Z) ->
>   Msq = M * M,
>   Magsq = (X * X) + (Y * Y) + (Z * Z), 
>   Msq > Magsq.

All the guards here are useless as M * M will crash with badarith if M isn’t a number.

> %% Determines if any coordinate in the given vector is bigger than the passed in value M
> has_coordinate_greater_than(V, {X, Y, Z}) when X > V; Y > V; Z > V -> true; 
> has_coordinate_greater_than(V, Coordinate) when is_number(V), is_tuple(Coordinate) -> false.

You can make that function in one clause:

has_coordinate_greater_than(V, {X, Y, Z}) ->
    X > V orelse Y > V orelse Z > V.

As an aside, your second clause would traditionally be written as:

has_coordinate_greater_than(_, {_, _, _}) -> false

or, to document better the code sometimes:

has_coordinate_greater_than(_V, {_X, _Y, _Z}) -> false

> %% Culls the list of vectors X to only those that are in the sphere devined by vector C as a center and R as a radius. 
> cull(C, R, Vectors) when is_number(R), is_tuple(C), is_list(Vectors) -> cull(C, R, Vectors, []).
> cull(C, R, [], Culled) -> Culled; 
> cull(C, R, [Head|Tail], Culled) -> 
>   D = subtract(C, Head),
>   case has_coordinate_greater_than(R, Head) of
>     true -> cull(C, R, Tail, Culled);
>     false -> cull(C, R, D, Head, Tail, Culled)
>   end.
> cull(C, R, D, Head, Tail, Culled) when is_tuple(D), is_number(R) ->
>   case is_magnitude_greater(R, D) of 
>      true -> cull(C, R, Tail, [Head | Culled]);
>      false -> cull(C, R, Tail, Culled)
>   end.

Newlines are usually inserted between different functions.

In cull/6, I would pass Head last, generally new arguments are always inserted last in recursive functions to make the code more efficient and avoid moving around register values in the VM.

> Now the question is the resolution of the followup question of how to integrate this in a solution. Do we return a list of trues and falses and zip that with the objects to form a candidate list? How would you do it?

Given that your function returns a boolean per value in the given list, why does it work on a list to begin with? Why doesn’t it take just one vector?




More information about the erlang-questions mailing list