[erlang-questions] Feedback for my first non-trivial Erlang program
Dmitry Kolesnikov
dmkolesnikov@REDACTED
Tue Dec 15 10:03:05 CET 2015
Hello,
One quick suggestion to get rid of `case`
-define(workingTimeUnits, 60).
-define(is_working(X, Y), X < Y).
investement(T)
when ?is_working(T, ?workingTimeUnits) ->
salary(T) - expenses(T) - transactionFee();
investement(T) ->
-expenses(T) - tax(expenses(T),T) - transactionFee().
I think function level guards improves readability. However, you might implement independent “path” to calculate meetings for working and non-working human beans.
Best Regards,
Dmitry
> On Dec 15, 2015, at 2:45 AM, Paul Wolf <paul.wolf23@REDACTED> wrote:
>
> Hi,
>
> I am totally new to Erlang and functional programming in general and
> tried to build a little program, after I read most of the "sequential
> programming" part of the Joe Armstrong book. While my program seems to
> work, I have still _big_ troubles in two departments:
> - my program is crazy slow as it seems to do a lot of redundant
> calculations. To me it seems functional and I don't really know how to
> solve this kind of (performance) issue
> - while I was able to program the logic in a mostly functional style,
> I had a hard time writing it and even some minutes after writing it,
> it is quite hard to read for me
>
> As I am totally knew to this stuff (while being an experienced Java
> developer/software engineer in general), I would highly appreciate
> some feedback to the following code:
>
> The programm basically takes some parameters (hardcoded... i know...)
> and tells you what your financial possesions are, if you save your
> money in stocks which in turn have an expected yield, etc., pp.
> The major part (first ~50 lines) seems fine to me and don't cause me
> much headache. However as soon as I start considering taxes (which in
> my country you pay on realized profits), stuff gets worriesome. Could
> you please review and comment the "tax" functions in particular (on a
> technical level - not functional)? For calculating the profit you have
> to keep track of when you bought how much and you have to sell your
> oldest positions first. For simplification I didn't model stocks, but
> instead you basically just put money (without consideration of stock
> quantities) into the security account and it yields. The tax method
> gets called by the way twice, but also gets evaluated twice (why? is
> there no cache? is my approach wrong?) and takes up a lot of
> performance!
>
> Any feedback is much appreciated! Here is the code without further ado:
>
> -module(pension2).
>
> -export([totalBalance/1]).
>
> %% total of what you own:
> totalBalance(T) -> caBalance(T) + saBalance(T).
>
> %% balance of cash account - is constant since all money not spend is invested:
> caBalance(0) -> caBalanceStart();
> caBalance(T) -> caBalance(T-1) + salary(T-1) - expenses(T-1) - tradingFees(T-1).
>
> %% balance of security account - rises while working - can rise while
> not working if yield > expenses
> saBalance(0) -> saBalanceStart();
> saBalance(T) -> (saBalance(T-1)*yieldRate() + investments(T-1)).
>
> %% everything spend on securities - in case of not working fees and
> taxes are directly offset by sells
> tradingFees(T) ->
> case working(T) of
> true -> investments(T) + transactionFee();
> false -> investments(T) + tax(expenses(T),T) + transactionFee()
> end.
>
> %% what is actually spend on stocks:
> investments(T) ->
> case working(T) of
> true-> salary(T) - expenses(T) - transactionFee();
> false-> -expenses(T) - tax(expenses(T),T) - transactionFee()
> end.
>
> %% salary:
> salary(0) -> netIncome();
> salary(T) ->
> case working(T) of
> true -> salary(T-1)*inflationRate();
> false -> 0
> end.
>
> %% expenses
> expenses(0) -> expensesStart();
> expenses(T) -> expenses(T-1)*inflationRate().
>
> %% still working?
> working(T) -> T<workingTimeUnits().
>
> %% lots of constants - in respect to months
> transactionFee() -> 10.
> workingTimeUnits() -> 60. %%months
> caBalanceStart() -> 10000.
> saBalanceStart() -> 10000.
> netIncome() -> 3000.
> expensesStart() -> 2000.
> inflationRate() -> 1.0017.
> yieldRate() -> 1.004.
> taxRate() -> 0.2638.
>
> %% ------------HERE STARTS THE HEAVY LIFTING-----------------
>
> %% used to calc taxes payed on profits
> tax(X,T) -> profit(X,T,portfolio(T))*taxRate().
>
> %% what is in the security account at time T:
> portfolio(T) ->
> case working(T) of
> true -> [{investments(X),X} || X <- lists:seq(0,T)];
> false -> remove(investments(T-1),T,portfolio(T-1))
> end.
>
> %% a helper method for removing positions from the portfolio
> remove(X,T,[{Amount,Time}|Tail]) ->
> case currentValue(Amount,T-Time) > X of
> true -> [{Amount-originalValue(X,T-Time),T}|Tail];
> false -> remove(X-currentValue(Amount,T-Time),T,Tail)
> end.
>
> %% tells you what is the actual profit for an amount/revenue generated
> by selling at a time T
> profit(X,T,[{Amount,Time}|Tail]) ->
> case currentValue(Amount,T-Time) > X of
> true -> X - originalValue(X,T-Time);
> false -> X - (Amount + profit((X - currentValue(Amount,T-Time)),T,Tail))
> end.
>
> %% helper functions for calculation the current and original value of a position
> currentValue(X,TD) -> X * math:pow(yieldRate(),TD).
> originalValue(X,TD) -> X / math:pow(yieldRate(),TD).
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list