---
category: tutorial
title: list 
layout: post
---

The `list` type, augments the standard JavaScript arrays, making them immutable and adding additional functionality to them

<!--more-->





To use the `list` monad constructor, you can require it using node:
		
		var list = require("../library/list")


Where the `../` is the location of the module.

Then you will be able to create a `list` from array like this
		var my_list = list([1,2,3])
or like this:
		var my_list = list(1,2,3)


`map(funk)`
----
Standard array method. Executes `funk` for each of the values in the list and wraps the result in a new list.

***


	var people = list( {name:"john", age:24, occupation:"farmer"}, {name:"charlie", age:22, occupation:"plumber"})
	var names = people.map((person) => person.name )
	assert.deepEqual(names, ["john", "charlie"])




`phatMap(funk)`
----
Same as `map`, but if `funk` returns a list or an array it flattens the results into one array

***



	
	var occupations = list([ 
		{occupation:"farmer", people:["john", "sam", "charlie"] },
		{occupation:"plumber", people:["lisa", "sandra"] },
	])
	
	var people = occupations.phatMap((occupation) => occupation.people)
	assert.deepEqual(people,["john", "sam", "charlie", "lisa", "sandra"])



under the hood
--------------
Let's see how the type is implemented










the `of` method, takes a value and puts it in a list.

		//a.of(b) -> b a
		of: val => list(val),

`map` applies a function to each element of the list, as the one from the Array prototype
		
`flat` takes a list of lists and flattens them with one level 

		//(b -> (b -> c)).join() = a -> b
		flat:function(){
			return list( this.reduce((list, element) => [...list, ...element], []) )
		},
		
finally we have `tryFlat` which does the same thing, but checks the types first. The shortcut to `map().tryFlat()` is called `phatMap`
and with it, your funk can return both a list of objects and a single object

		tryFlat:function(){
			return list( this.reduce((list, element) => 
				element.constructor === Array? [...list, ...element] : [...list, element] , [])
			)
		},


	})

Some functions are directly lifted from the Array prototype

var immutableFunctions = ['map', 'concat']

immutableFunctions.forEach((funk) => { 
	listMethods[funk] = function(...args){
			return list(Array.prototype[funk].apply(this, args))
	}
})

The type also wraps some Array functions in a way that makes them immutable

var mutableFunctions = ['splice', 'reverse', 'sort']

mutableFunctions.forEach((funk) => { 
	listMethods[funk] = function(...args){
			var newArray = this.slice(0)
			Array.prototype[funk].apply(newArray, args)
			return newArray
	}
})

This is the list constructor. It takes normal array and augments it with the above methods
	
	var list = (...args) => {
		if(args.length === 1 && args[0].funktionType === "list"){
			return args[0]
		//Accept an array
		}else if(args.length === 1 && args[0].constructor === Array ){
			return  Object.freeze(extend(args[0], listMethods))
		//Accept several arguments
		}else{
			return Object.freeze(extend(args, listMethods))
		}
	}

Here is the function with which the list object is extended
	function extend(obj, methods){
		return Object.keys(methods).reduce(function(obj, method_name){obj[method_name] = methods[method_name]; return obj}, obj)
	}

