Skip to content

Commit

Permalink
freed from dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
nikita-volkov committed Apr 6, 2012
1 parent 9d3af3a commit edb746e
Show file tree
Hide file tree
Showing 23 changed files with 247 additions and 45 deletions.
2 changes: 1 addition & 1 deletion monitor-specs
@@ -1 +1 @@
jasmine-node --autotest --coffee --verbose spec
jasmine-node spec --coffee --autotest
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -3,7 +3,7 @@
"name": "Fuell",
"description": "A library for purely declarative functional programming with support for async actions",
"keywords": ["functional", "declarative", "async", "library", "haskell", "coffeescript"],
"version": "0.1.1",
"version": "0.1.2",
"homepage": null,
"repository": {
"type": "git",
Expand All @@ -17,7 +17,6 @@
"test": "jasmine-node spec --coffee"
},
"dependencies": {
"HOFU": "0.1.1"
},
"devDependencies": {
"jasmine-node": "1.0.x"
Expand Down
23 changes: 23 additions & 0 deletions spec/FunctionComposing/Function.spec.coffee
@@ -0,0 +1,23 @@
describe "Function", ->
{composableByPositions} = require "../../src/FunctionComposing/Function"

describe "composableByPositions", ->
it "works", ->
d = [[matches, isEven], [mapped, [sum, 2]]]
f = composableByPositions [0], result
expect(f d, [0, 1, 2, 3]).toEqual [2, 4]





sum = (y, x) -> x + y
difference = (y, x) -> x - y
product = (y, x) -> x * y
quotient = (y, x) -> x / y
isEven = (x) -> x % 2 == 0
isOdd = (x) -> x % 2 == 1
times = (y, x) -> y for i in [0...x]
matches = (f, xs) -> x for x in xs when f x
mapped = (f, xs) -> f x for x in xs
result = (f, x) -> f x if x?
49 changes: 49 additions & 0 deletions spec/FunctionComposing/FunctionTemplate.spec.coffee
@@ -0,0 +1,49 @@
describe "FunctionTemplate", ->
{func} = require "../../src/FunctionComposing/FunctionTemplate"

describe "func", ->

it "fails when first element is inappropriate", ->
(expect -> func [2, sum, 3]).toThrow()

it "returns a fully-applied function when all parameters are provided", ->
(expect (func [difference, 17, 3])()).toEqual -14
(expect (func [product, 3, 6])()).toEqual 18

it "returns a partially applied function on lesser arguments", ->
f = func [difference, 12]
(expect f instanceof Function).toBeTruthy()
expect(f 7).toBe -5

it "filter on a function works", ->
f = func [matches, isEven]
expect(f [0, 1, 2, 3, 4]).toEqual([0, 2, 4])

it "works on nested declarations", ->
f = func [mapped, [sum, 2]]
expect(f [0, 1, 2]).toEqual([2, 3, 4])

it "works on uber-nested declarations", ->
f = func [mapped, [mapped, [sum, 3]]]
expect(f [[2, 3], [4]]).toEqual([[5,6], [7]])

it "works on nested functions", ->
f = func [[matches, isEven], [mapped, [sum, 2]]]
expect(f [2, 3, 4]).toEqual [4, 6]
expect(f [0, 1, 2, 3]).toEqual [2, 4]

# it "passes the function unchanged", ->
# expect((func difference) 7, 4).toEqual -3



sum = (y, x) -> x + y
difference = (y, x) -> x - y
product = (y, x) -> x * y
quotient = (y, x) -> x / y
isEven = (x) -> x % 2 == 0
isOdd = (x) -> x % 2 == 1
times = (y, x) -> y for i in [0...x]
matches = (f, xs) -> x for x in xs when f x
mapped = (f, xs) -> f x for x in xs
result = (f, x) -> f x if x?
3 changes: 3 additions & 0 deletions src/Async.coffee
@@ -0,0 +1,3 @@
exports[name] = require "./Async/#{name}" for name in [
"Function"
]
20 changes: 20 additions & 0 deletions src/Async/Function.coffee
@@ -0,0 +1,20 @@
BasicFunctionComposing = require "../BasicFunctionComposing"

exports.Function = Function

exports.async =
async = (f) ->
-> callAsync BasicFunctionComposing.Function.partiallyApplied arguments, f

exports.callAsync =
callAsync = (f) ->
if process? && process.nextTick then process.nextTick f
else setTimeout f, 0
return

exports.action =
action = (f) ->
async (args..., cb) ->
cb f.apply this, args


3 changes: 3 additions & 0 deletions src/BasicFunctionComposing.coffee
@@ -0,0 +1,3 @@
exports[name] = require "./BasicFunctionComposing/#{name}" for name in [
"Function"
]
33 changes: 33 additions & 0 deletions src/BasicFunctionComposing/Function.coffee
@@ -0,0 +1,33 @@

exports.Function = Function

exports.nested =
nested = (container, f) ->
-> container.call this, f.apply this, arguments

# exports.partiallyApplied =
# partiallyApplied = (args, f) ->
# args = members args unless args instanceof Array
# -> f.apply this, union (members arguments), args

# union = (ys, xs) -> if not ys then xs else xs.concat ys
# members = (x) -> v for _, v of x

exports.partiallyApplied =
partiallyApplied = (args, f) ->
->
args1 = []
args1.push(arg) for arg in args
args1.push(arg) for arg in arguments
f.apply this, args1


exports.withLength =
withLength = (length, f) ->
args = ("a" + i for i in [0...length])
body = """
return function(#{args.join(", ")}) {
return f.apply(this, arguments);
}
"""
(new Function "f", body) f
4 changes: 4 additions & 0 deletions src/Fuell.coffee
@@ -1,10 +1,14 @@
# TODO: all the composing and async declarations could be done here
exports[name] = require "./Fuell/#{name}" for name in [
"Action"
"Actions"
"Array"
"Arrays"
"Environment"
"Function"
"FunctionByLengthMap"
"FunctionByTypesPairs"
"FunctionTemplate"
"Keys"
"Map"
"Number"
Expand Down
6 changes: 3 additions & 3 deletions src/Fuell/Actions.coffee
@@ -1,8 +1,8 @@
HOFU = require "../HOFU"
Async = require "../Async"

# deprecated in favor of `parallel`
exports.callParallelly =
callParallelly = HOFU.async (fs, cb) ->
callParallelly = Async.Function.async (fs, cb) ->
results = []
for f in fs
f (result) ->
Expand All @@ -21,7 +21,7 @@ callConsecutively = (actions, cb) ->
else cb()
callNext()
return
# throw "todo: Actions.callConsecutively"
# throw "Unimplemented: Actions.callConsecutively"



Expand Down
31 changes: 16 additions & 15 deletions src/Fuell/Array.coffee
@@ -1,5 +1,6 @@
Async = require "../Async"
FunctionComposing = require "../FunctionComposing"
Object = require "./Object"
HOFU = require "../HOFU"

exports.Array = Array

Expand All @@ -9,7 +10,7 @@ ASYNC ACTIONS
###
# processBy
exports.collect =
collect = HOFU.async (action, xs, cb) ->
collect = Async.Function.async (action, xs, cb) ->
zs = []
for x in xs
action x, (z) ->
Expand All @@ -29,7 +30,7 @@ collectResults = (action, xs, cb) ->
return

exports.each =
each = HOFU.async (action, xs, cb) ->
each = Async.Function.async (action, xs, cb) ->
if xs.length > 0
finished = 0
for x in xs
Expand Down Expand Up @@ -75,34 +76,34 @@ spread = (f, xs) ->
[r1, r2]

exports.resultPairs =
resultPairs = HOFU.composable (f, keys) ->
resultPairs = FunctionComposing.Function.composable (f, keys) ->
[k, f k] for k in keys

exports.leftReduction =
leftReduction = HOFU.composable (f, r, xs) ->
leftReduction = FunctionComposing.Function.composable (f, r, xs) ->
for x in xs
r = f r, x
r

exports.rightReduction =
rightReduction = HOFU.composable (f, y0, xs) ->
rightReduction = FunctionComposing.Function.composable (f, y0, xs) ->
y = y0
for i in [(xs.length - 1)..0]
y = f xs[i], y
y

# not `reduced` since the returned type changes
exports.reduction =
reduction = HOFU.composable (f, xs) ->
reduction = FunctionComposing.Function.composable (f, xs) ->
rightReduction f, (last xs), (allButLast xs) if xs.length > 0


exports.firstResult =
firstResult = HOFU.composable (f, xs) ->
firstResult = FunctionComposing.Function.composable (f, xs) ->
return z for x in xs when (z = f x)?

exports.result =
result = HOFU.composable (f, xs) ->
result = FunctionComposing.Function.composable (f, xs) ->
###
Get either the same array or null if it contains a null
###
Expand All @@ -113,33 +114,33 @@ result = HOFU.composable (f, xs) ->

# processed
exports.results =
results = HOFU.composable (f, xs) ->
results = FunctionComposing.Function.composable (f, xs) ->
###
###
z for x in xs when (z = f x)?

exports.allMatch =
allMatch = HOFU.composable (f, xs) ->
allMatch = FunctionComposing.Function.composable (f, xs) ->
return false for x in xs when not f x
true

exports.someMatch =
someMatch = HOFU.composable (f, xs) ->
someMatch = FunctionComposing.Function.composable (f, xs) ->
return true for x in xs when f x
false

exports.noneMatch =
noneMatch = HOFU.composable (f, xs) ->
noneMatch = FunctionComposing.Function.composable (f, xs) ->
return false for x in xs when f x
true

exports.matches =
matches = HOFU.composable (f, xs) ->
matches = FunctionComposing.Function.composable (f, xs) ->
x for x in xs when f x

exports.firstMatch =
firstMatch = HOFU.composable (f, xs) ->
firstMatch = FunctionComposing.Function.composable (f, xs) ->
return x for x in xs when f x


Expand Down
20 changes: 6 additions & 14 deletions src/Fuell/Function.coffee
@@ -1,11 +1,13 @@
Array = require "./Array"
Object = require "./Object"
Pair = require "./Pair"
HOFU = require "../HOFU"
Set = require "./Set"

exports.Function = Function
exports[k] = v for k, v of require "../BasicFunctionComposing/Function"
exports[k] = v for k, v of require "../FunctionComposing/Function"
exports[k] = v for k, v of require "../Async/Function"

exports[k] = v for k, v of HOFU
exports.Function = Function

exports.disposable =
disposable = (f) ->
Expand All @@ -26,21 +28,11 @@ memoized = (f) ->
f.cache.push [arguments, r]
r

exports.withLength =
withLength = (length, f) ->
args = ("a" + i for i in [0...length])
body = """
return function(#{args.join(", ")}) {
return f.apply(this, arguments);
}
"""
(new Function "f", body) f

exports.flipped =
flipped = (f) -> (x, y) -> f y, x

exports.remapped =
remapped = (m, f) ->
throw "Incorrect map" if not Array.empty Array.symmetricDifference m, [0...f.length]
throw "Incorrect map" if not Set.equals [0...f.length], m
->
f.apply this, (arguments[i] for i in m)
6 changes: 6 additions & 0 deletions src/Fuell/FunctionByLengthMap.coffee
@@ -0,0 +1,6 @@
exports.func =
func = (template) ->
->
ln0 = arguments.length.toString()
return f.apply this, arguments for ln, f of template when ln == ln0
throw "Function does not support #{arguments.length} arguments"
14 changes: 14 additions & 0 deletions src/Fuell/FunctionByTypesPairs.coffee
@@ -0,0 +1,14 @@
exports.func =
func = (template) ->
->
for [types, f] in template
return f.apply this, arguments if argsMatchTypes types, arguments
throw "Function does not support types of supplied arguments: #{(type arg)?.name for arg in arguments}"

argsMatchTypes = (types, args) ->
return false if args.length != types.length
return false for t, i in types when t? && !instanceOf t, args[i]
true

instanceOf = (t, x) -> (x instanceof t) || (t == type x)
type = (x) -> x?.constructor
1 change: 1 addition & 0 deletions src/Fuell/FunctionTemplate.coffee
@@ -0,0 +1 @@
exports[k] = v for k, v of require "../FunctionComposing/FunctionTemplate"
5 changes: 2 additions & 3 deletions src/Fuell/Keys.coffee
@@ -1,6 +1,6 @@
# Most probably a useless module

HOFU = require "../HOFU"
FunctionComposing = require "../FunctionComposing"

exports.pairs =
pairs = (values, keys) -> [k, values[i]] for k, i in keys
Expand All @@ -13,6 +13,5 @@ map = (values, keys) ->

# Fits fine in Array
exports.resultPairs =
resultPairs = HOFU.composable (f, keys) ->
resultPairs = FunctionComposing.Function.composable (f, keys) ->
[k, f k] for k in keys

0 comments on commit edb746e

Please sign in to comment.