On Feb 16, 8:27 pm, Yaron <ygol...@gmail.com> wrote: > Sean and Richard perhaps I can address both of your mails in a single > go. Here is an example of one of the functions from my calculator: > > (defn tax_deductible_expenses > "The total expenses incurred in business month m that are deductible > from federal income tax" > [m] > (let > [prepHouse (inflate *Prep_House_0* m) > fixedMonthlyCost (if (= m (months_in_business)) 0 > (fixed_monthly_cost m))] > (condp = (house_state m) > :ForLease (+ fixedMonthlyCost (if (= > (month_in_rental_cycle m) 0) > prepHouse 0)) > :Leased (+ fixedMonthlyCost (* (rental_income m) (+ > *Management_Fee* (if (= (month_in_rental_cycle m) > *Months_To_Find_Tenant*) *Tenant_Finding_Fee* 0)))) > :ForSale (+ fixedMonthlyCost (if (= m > (months_actively_renting)) > prepHouse 0)) > :Sold (house_sales_expenses m)))) > > Right now the function takes a single argument, m which is the month > that tax deductible expenses are being calculated for. All the other > values it needs are "constants" (e.g. either values provided at the > start by the user or derived values).
First, a style nitpick: use foo-bar instead of fooBar or foo_bar secondly, yes, you really should pass in a map of all the relevant information. It might help to split up your calculator into multiple functions, each of which deals with only part of the map. It might even make sense to group the arguments a bit and pass in multiple maps, or just some args outside of a map. The ideal is that a function depends only on its parameters. Having many rebindable globals is certainly *not* the way to go. :) For "derived" values, you might be able to use let-bound locals. > > Now please look at a test I wrote to make sure the function does what > I think it does: > > (deftest tax_deductible_expenses_basic > (binding > [*Months_To_Find_Tenant* 5 > *Months_In_Lease* 5 > *Lease_Cycles* 1 > *House_Sales_Price_0* 300 > *Monthly_Inflation_Rate* 0.002 > *Buying_Agent_Fee_Type* :Percentage > *Buying_Agent_Fee_Number* 0.05 > *Selling_Agent_Fee_Type* :FlatFee > *Selling_Agent_Fee_Number* 1000 > *Other_Sales_Fee_0* 100 > *Excise_Tax* 0.5 > *Original_Loan_Amount* 10000 > *Monthly_Loan_Interest* (/ 0.05 12) > *Months_In_Loan* (* 10 12) > *Loan_Month_At_Start* 3 > *Prep_House_0* 100 > *Management_Fee* 2 > *Tenant_Finding_Fee* 0.5 > *Months_To_Sell* 3] > (is (= (tax_deductible_expenses 0) (+ (fixed_monthly_cost 0) > 100))) > (is (= (tax_deductible_expenses 1) (fixed_monthly_cost 1))) > (is (= (tax_deductible_expenses 5) (+ (fixed_monthly_cost 5) (* > (rental_income 5) 2.5)))) > (is (= (tax_deductible_expenses 7) (+ (fixed_monthly_cost 7) (* > (rental_income 7) 2)))) > (is (= (tax_deductible_expenses 10) (+ (fixed_monthly_cost 10) > (inflate 100 10)))) > (is (= (tax_deductible_expenses 12) (fixed_monthly_cost 12))) > (is (= (tax_deductible_expenses 13) (house_sales_expenses 13))))) > > For the method tax_deductible_expenses to run it ends up requiring 19 > user defined values. That's a whole lot of arguments to pass into a > function. Obviously I could wrap them up in a StructMap but then I get > expressions like (+ 1 (args :B)) which doesn't seem much better than > (+1 (B)). > > The issue I'm really trying to put my finger on is - these arguments > really and truly are 'constants' within the context of the calculator. > But they are constants whose values are not known as compile time but > rather are known at run time. Does Clojure have a way to express a > 'late bound' constant or is the 'right' solution to pass around 19+ > arguments to functions or passing around StructMaps or making > everything into thunks? > If you're passing 19 arguments to a function, it's most likely doing too much. See if you can split up the logic somewhat. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en