summaryrefslogtreecommitdiffhomepage
path: root/tests/custom/00_syntax/19_arrow_functions
blob: 761705b1b2b1405e982cad3fd5bab79f18502452 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
Besides the ordinary ES5-like function declarations, ucode supports ES6 inspired
arrow function syntax as well. Such arrow functions are useful for callbacks to functions such as replace(), map() or filter().

-- Expect stdout --
() => { ... }
test
(a, b) => { ... }
3
(...args) => { ... }
15
(a) => { ... }
10
(a) => { ... }
36
-- End --

-- Testcase --
{%

	// assign arrow function to variable
	test1_fn = () => {
		return "test";
	};

	// assign arrow function with parameters
	test2_fn = (a, b) => {
		return a + b;
	};

	// nesting functions is legal
	test3_fn = (...args) => {
		nested_fn = (a, b) => {
			return a * b;
		};

		return args[0] + nested_fn(args[0], args[1]);
	};

	// parentheses may be omitted if arrow function takes only one argument
	test4_fn = a => {
		return a * 2;
	};

	// curly braces may be omitted if function body is a single expression
	test5_fn = a => a * a;

	print(join("\n", [
		test1_fn,
		test1_fn(),
		test2_fn,
		test2_fn(1, 2),
		test3_fn,
		test3_fn(3, 4),
		test4_fn,
		test4_fn(5),
		test5_fn,
		test5_fn(6)
	]), "\n");
%}
-- End --


While the main advantage of arrow functions is the compact syntax, another
important difference to normal functions is the "this" context behaviour -
arrow functions do not have an own "this" context and simply inherit it from
the outer calling scope.

-- Expect stdout --
this is set to obj: true
arrow function uses outher this: true
normal function has own this: true
arrow function as method has no this: true
-- End --

-- Testcase --
{%
	obj = {
		method: function() {
			let that = this;
			let arr = () => {
				print("arrow function uses outher this: ", that == this, "\n");
			};
			let fn = function() {
				print("normal function has own this: ", that != this, "\n");
			};

			print("this is set to obj: ", this == obj, "\n");

			arr();
			fn();
		},

		arrowfn: () => {
			print("arrow function as method has no this: ", this == null, "\n");
		}
	};

	obj.method();
	obj.arrowfn();
%}
-- End --


Due to the difficulty of recognizing arrow function expressions with an LR(1)
grammar the parser has to use a generic expression rule on the lhs argument list
and verify that it does not contain non-label nodes while building the ast. The
subsequent testcase asserts that case.

-- Expect stderr --
Syntax error: Unexpected token
Expecting ';'
In line 2, byte 10:

 `    (a + 1) => { print("test\n") }`
  Near here --^


-- End --

-- Testcase --
{%
	(a + 1) => { print("test\n") }
%}
-- End --


Arrow functions consisting of a single expression implicitly return the expression
results. Arrow functions having a statement block as body do not return any result
by default but may return explictly.

-- Expect stdout --
[
	4,
	null,
	4
]
-- End --

-- Testcase --
{%
	printf("%.J\n", [
		(() => 2 * 2)(),
		(() => { 2 * 2 })(),
		(() => { return 2 * 2 })()
	]);
%}
-- End --