func PMapInt64PtrErr(f func(*int64) (*int64, error), list []*int64, optional ...Optional) ([]*int64, error) {
	if f == nil {
		return []*int64{}, nil
	}
	var worker = len(list)
	if optional != nil && len(optional) > 0 {
		if optional[0].FixedPool > 0 && optional[0].FixedPool < worker {
			worker = optional[0].FixedPool
		}
		if optional[0].RandomOrder == true {
			return pMapInt64PtrErrNoOrder(f, list, worker)
		}
	}
	return pMapInt64PtrErrPreserveOrder(f, list, worker)
}
PMapInt64PtrErr applies the function(1st argument) on each item in the list and returns a new list and error.
Order of new list is guaranteed. This feature can be disabled by passing: Optional{RandomOrder: true} to gain performance
Run in parallel. no_of_goroutines = no_of_items_in_list or 3rd argument can be passed to fix the number of goroutines.

Takes 3 inputs. 3rd argument is optional
1. Function - takes 1 input
2. List
3. optional argument - fp.Optional{FixedPool: <some_number>}
package fp
import "sync"
func PMapIntPtrErr(f func(*int) (*int, error), list []*int, optional ...Optional) ([]*int, error) {
	if f == nil {
		return []*int{}, nil
	}
	var worker = len(list)
	if optional != nil && len(optional) > 0 {
		if optional[0].FixedPool > 0 && optional[0].FixedPool < worker {
			worker = optional[0].FixedPool
		}
		if optional[0].RandomOrder == true {
			return pMapIntPtrErrNoOrder(f, list, worker)
		}
	}
	return pMapIntPtrErrPreserveOrder(f, list, worker)
}
func pMapIntPtrErrPreserveOrder(f func(*int) (*int, error), list []*int, worker int) ([]*int, error) {
	chJobs := make(chan map[int]*int, len(list))
	go func() {
		for i, v := range list {
			chJobs <- map[int]*int{i: v}
		}
		close(chJobs)
	}()
	chResult := make(chan map[int]*int, worker/3)
	errCh := make(chan error, len(list))
	var wg sync.WaitGroup
	for i := 0; i < worker; i++ {
		wg.Add(1)
		go func(chResult chan map[int]*int, chJobs chan map[int]*int, errCh chan error) {
			defer wg.Done()
			if len(errCh) > 0 {
				return
			}
			for m := range chJobs {
				for k, v := range m {
					r, err := f(v)
					if err != nil {
						errCh <- err
						return
					}
					chResult <- map[int]*int{k: r}
				}
			}
		}(chResult, chJobs, errCh)
	}
	go func() {
		wg.Wait()
		close(chResult)
	}()
	newListMap := make(map[int]*int, len(list))
	newList := make([]*int, len(list))
	for m := range chResult {
		select {
		case err := <-errCh:
			return []*int{}, err
		default:
		}
		for k, v := range m {
			newListMap[k] = v
		}
	}
	if len(errCh) > 0 {
		return []*int{}, <-errCh
	}
	for i := 0; i < len(list); i++ {
		newList[i] = newListMap[i]
	}
	return newList, nil
}
func pMapIntPtrErrNoOrder(f func(*int) (*int, error), list []*int, worker int) ([]*int, error) {
	chJobs := make(chan *int, len(list))
	go func() {
		for _, v := range list {
			chJobs <- v
		}
		close(chJobs)
	}()
	chResult := make(chan *int, worker/3)
	errCh := make(chan error, len(list))
	var wg sync.WaitGroup
	for i := 0; i < worker; i++ {
		wg.Add(1)
		go func(chResult chan *int, chJobs chan *int, errCh chan error) {
			defer wg.Done()
			if len(errCh) > 0 {
				return
			}
			for v := range chJobs {
				r, err := f(v)
				if err != nil {
					errCh <- err
					return
				}
				chResult <- r
			}
		}(chResult, chJobs, errCh)
	}
	go func() {
		wg.Wait()
		close(chResult)
	}()
	newList := make([]*int, len(list))
	i := 0
	for v := range chResult {
		select {
		case err := <-errCh:
			return []*int{}, err
		default:
		}
		newList[i] = v
		i++
	}
	if len(errCh) > 0 {
		return []*int{}, <-errCh
	}
	return newList, nil
}