vincentntang / Free-Code-Camp-Projects

🏕️ Freecodecamp Curriculum Work
0 stars 0 forks source link

JS-Calc Refactor 1 → Semi FP-style to Pure FP-Style #6

Open vincentntang opened 6 years ago

vincentntang commented 6 years ago

Goals for refactoring

vincentntang commented 6 years ago

I'll just write out my thought process on what I think how everything should work.

!(4/7/2018 19:10)

e.g.... write my requirements for the refactor.

I need to watch a course on functional programming in Javascript.

Maybe, I should just learn a real FP language like Haskell, to understand principles better? http://learnyouahaskell.com/starting-out repl.it for testing

Possibly learn a javascript compiler, (TypeScript or Clojurescript), I think its too verbose to do simple things. Codepen only supports typescript so probably typescript

The order in which I learn this will be

vincentntang commented 6 years ago

Now that I think about it more...

A function which takes an object and an input to return an object is sloppy. It also makes the unit tests rather lengthy...

image

My variables defined

1zdn1b2 1

are technically dependent on each other. The view function doesn't need both, the storage variable can be processed as an array.

The last element in the array is always the cache.

So really, I need just one variable passed around

This also invalidates a lot of my tests, they need to be rewritten. Unit testing.... should be done after initial coding is done IMO, or when a roadblock is hit when attempting to debug.

vincentntang commented 6 years ago

Even C++ apparently doesn't let you return full arrays either on a function, just the array reference.

https://stackoverflow.com/questions/3473438/return-array-in-a-function

Using functions... to expect an array returned back is normal something similar to map , filter, reduce, etc. Those are generally better to bind onto the prototype object. Possibly look into lodash and see what other types of specialized funcs out there

Functions like stringify takes an object and makes it a string. Working with strings is a good way to reason about things I would say. Its clean and straight forward.

vincentntang commented 6 years ago

On 2nd thought I could probably get find a really clean library, and emulate it. Probably should learn some design patterns along the way, addy osmani.

https://www.reddit.com/r/javascript/comments/83qroe/what_are_the_most_welldesigned_javascript/

Some searches on reddit indicate the following is beautifully written FP-style JS code

Small libraries

Popular mentions

Lesser Mentions

A few things worth mentioning.

Some libraries don't even show the final build (e.g. jQuery) probably because people might treat it as a CDN on the github repo

vincentntang commented 6 years ago

On another note, I find it much better to write more tiny - functions. For instance, I adopted this style after looking at Lodash's source code.

Pure FP style. No private variables. One input, one output, no iteration.

image

This is the support controller

image

It does assume the controller passes an operator though, so it doesn't have any sort of error checks.

vincentntang commented 6 years ago

Some other issues I've come across. I finished doing everything except refactor calculate and views, which are the most complex functions to write.

I can't quite figure out how to stop / prevent / trycatch infinite loops inside of my calculate method, very few good articles on it

JS hint suggests not to make function calls within loops

p07djht 1

Lodash implements many callback functions instead... i think. Callback recursion? I mean, native array reduce does do this as well I think

More precisely, it implements a callback function recursively

svofd9c 1

My thinking is the following:

  1. Throw out while loops all together. They are bad practice to begin with, leaves a gaping hole for infinite looping
  2. Implement my own variant of a reduce function. Or just use native reduce. I am working on arrays, no?

In any case... I need a function. That has a callback function as an argument.

The problem with javascript reduce... is that it only iterates through elements from start to finish. That's not what I want. calculatePartials is still a solid function to use though. I have no idea what I'm doing at this point to fix issue

vincentntang commented 6 years ago

how i implemented model.calculated thus far

This model.calculate method is very hard to reason about. Let's write down what I know for sure...

  1. I need to loop a dictionary reference const orderOper = ["x","÷","+","-"];. 100% sure of this
  2. It might need to be looped multiple times. For instance, "55+55x55" would need to be looped twice. Once for "x & +" and again for "+".
  3. When the operator is found, it knows what operation to do at that index.
  4. Scrape the adjacent values and calculatePartial at that location.
  5. Return it

That's exactly what I am doing though. Still, its going to use 2 while loops.

Looking up answers

https://forum.freecodecamp.org/t/javascript-calculator-order-of-operations/84293/3

"... Put them in order to perform the calculation".

That reminds me of some algorithms. They need to be presorted... before it can be executed. That's not a terrible answer either, it simplifies a lot of things.

I'll have to just dig around for an answer.

look there's a codereview for a calculator

Also which sorting algorithm works best here anyways?


https://codereview.stackexchange.com/questions/150510/beginners-javascript-calculator

Notes on that post


https://stackoverflow.com/questions/32292231/how-to-code-a-calculator-in-javascript-without-eval

First, it is convenient to turn the string into an array of numbers and operators.

Figured as much, was on right track.

Then, we go through the array looking for each operator in order of precedence, and applying the operator to the numbers preceding and following the it.

thats what I did though...except my implementation is still cleaner. Plus the author still used two for loops, similar to using two while loops.


other solutions on the web

summary of research

I will use dijkstras algorithm shuntyard algorithm

Plus wikipedia says this is a common algorithm for calculators https://en.wikipedia.org/wiki/Operator-precedence_parser

Or I can use a simple sort algorithm and use what I have right now. (Probably won't use this though)

vincentntang commented 6 years ago

I've added the shuntyard algorithm which works fine, but my current struggle is doing the following

As a side note, the issue tracker should be only limited to short-sweet steps instead of my long ardulous thought process

vincentntang commented 6 years ago

I started to theorize some of the approaches in making my code semantic and easy to read. This commit 50 details my thought process. https://github.com/Kagerjay/Free-Code-Camp-Projects/commit/948008bf799a26a0f56c8f164c279aee8b5496ef

jhee6zl 1

The approach I used to model my calculator follows a MVVM approach