Skip to content

Commit 2ac4963

Browse files
committed
Added with special form implementation in javascript
1 parent 4b2ee9e commit 2ac4963

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

src/javascript/lib/core/special_forms.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,35 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function)
140140
}
141141
}
142142

143+
function _with(...args){
144+
let argsToPass = [];
145+
146+
for(let i = 0; i < args.length; i++){
147+
if(i === args.length - 1){
148+
return args[i].apply(null, argsToPass);
149+
}else{
150+
let [pattern, func] = args[i];
151+
152+
let result = func.apply(null, argsToPass);
153+
154+
let patternResult = Patterns.match_no_throw(pattern, result);
155+
156+
if(patternResult == null){
157+
return result;
158+
}else{
159+
argsToPass = argsToPass.concat(patternResult);
160+
}
161+
}
162+
}
163+
164+
return null;
165+
}
166+
143167
export default {
144168
_case,
145169
cond,
146170
map_update,
147171
_for,
148-
_try
172+
_try,
173+
_with
149174
};

src/javascript/tests/with.spec.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Core from "../lib/core";
2+
const Patterns = Core.Patterns;
3+
const SpecialForms = Core.SpecialForms;
4+
const Tuple = Core.Tuple;
5+
6+
import Enum from "../lib/enum";
7+
8+
import chai from 'chai';
9+
var expect = chai.expect;
10+
11+
const $ = Patterns.variable();
12+
13+
function map_fetch(map, key){
14+
if(key in map){
15+
return new Tuple(Symbol.for('ok'), map[key]);
16+
}
17+
18+
return Symbol.for('error');
19+
}
20+
21+
describe('with', () => {
22+
23+
it('normal', () => {
24+
/*
25+
opts = %{width: 10, height: 15}
26+
27+
with {:ok, width} <- Map.fetch(opts, :width),
28+
{:ok, height} <- Map.fetch(opts, :height),
29+
do: {:ok, width * height}
30+
31+
{:ok, 150}
32+
*/
33+
34+
let opts = { width: 10, height: 15 };
35+
36+
let value = SpecialForms._with(
37+
[new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")],
38+
[new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")],
39+
(width, height) => new Tuple(Symbol.for('ok'), width * height)
40+
);
41+
42+
expect(value).to.eql(new Tuple(Symbol.for('ok'), 150));
43+
});
44+
45+
46+
it('without match', () => {
47+
/*
48+
opts = %{width: 10}
49+
50+
with {:ok, width} <- Map.fetch(opts, :width),
51+
{:ok, height} <- Map.fetch(opts, :height),
52+
do: {:ok, width * height}
53+
54+
:error
55+
*/
56+
57+
let opts = { width: 10 };
58+
59+
let value = SpecialForms._with(
60+
[new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")],
61+
[new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")],
62+
(width, height) => new Tuple(Symbol.for('ok'), width * height)
63+
);
64+
65+
expect(value).to.eql(Symbol.for('error'));
66+
});
67+
68+
69+
it('bare expression', () => {
70+
/*
71+
opts = %{width: 10}
72+
73+
with {:ok, width} <- Map.fetch(opts, :width),
74+
double_width = width * 2,
75+
{:ok, height} <- Map.fetch(opts, :height),
76+
do: {:ok, double_width * height}
77+
78+
{:ok, 300}
79+
*/
80+
81+
let opts = { width: 10, height: 15 };
82+
83+
let value = SpecialForms._with(
84+
[new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")],
85+
[$, (width) => width * 2],
86+
[new Tuple(Symbol.for('ok'), $), (width, double_width) => map_fetch(opts, "height")],
87+
(width, double_width, height) => new Tuple(Symbol.for('ok'), double_width * height)
88+
);
89+
90+
expect(value).to.eql(new Tuple(Symbol.for('ok'), 300));
91+
});
92+
93+
});
94+

0 commit comments

Comments
 (0)