or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdcollections.mdcore-promises.mdflow-control.mdfunctional.mdindex.mdnodejs.mdpromise-chains.mdproperty-access.mdqueue.mdstate-inspection.md

functional.mddocs/

0

# Functional Programming

1

2

Function wrappers and utilities for integrating promises with functional programming patterns, including async/generator support and promise-based functional composition.

3

4

## Capabilities

5

6

### Function Wrapping

7

8

Utilities for wrapping regular functions to work seamlessly with promises.

9

10

```javascript { .api }

11

/**

12

* Wraps function to return promises

13

* @param wrapped - Function to wrap for promise compatibility

14

* @returns Function that returns promises

15

*/

16

function Q.function(wrapped);

17

18

/**

19

* Decorator ensuring promise arguments and return value

20

* @param callback - Function to wrap with promise handling

21

* @returns Function that handles promise arguments and returns promises

22

*/

23

function Q.promised(callback);

24

```

25

26

**Usage Examples:**

27

28

```javascript

29

const Q = require("q");

30

31

// Wrap regular function to return promises

32

const syncAdd = (a, b) => a + b;

33

const asyncAdd = Q.function(syncAdd);

34

35

asyncAdd(5, 3)

36

.then(result => console.log("Result:", result)) // 8

37

.catch(error => console.error(error));

38

39

// Wrap function that may throw

40

const riskyFunction = (data) => {

41

if (!data) throw new Error("No data provided");

42

return data.toUpperCase();

43

};

44

45

const safeRiskyFunction = Q.function(riskyFunction);

46

47

safeRiskyFunction("hello")

48

.then(result => console.log(result)) // "HELLO"

49

.catch(error => console.error(error));

50

51

safeRiskyFunction(null)

52

.catch(error => console.error("Caught:", error.message));

53

54

// Q.promised for promise-aware functions

55

const promisedProcessor = Q.promised((data, config) => {

56

// Both data and config can be promises or values

57

return `Processed: ${data} with ${config.mode}`;

58

});

59

60

// Use with mixed promise/value arguments

61

promisedProcessor(

62

Q.delay("user data", 100),

63

{ mode: "strict" }

64

).then(result => console.log(result));

65

66

// Chain with other promise operations

67

const processUser = Q.promised((user, settings) => {

68

return {

69

id: user.id,

70

name: user.name.toUpperCase(),

71

theme: settings.theme

72

};

73

});

74

75

fetchUser(123)

76

.then(user => processUser(user, getSettings()))

77

.then(processedUser => console.log(processedUser));

78

```

79

80

### Value Comparison and Joining

81

82

Functions for comparing and joining promise values.

83

84

```javascript { .api }

85

/**

86

* Resolves to value if both promises fulfill to same value

87

* @param x - First promise or value

88

* @param y - Second promise or value

89

* @returns Promise that resolves if both values are equal

90

*/

91

function Q.join(x, y);

92

```

93

94

**Usage Examples:**

95

96

```javascript

97

const Q = require("q");

98

99

// Join with identical values

100

Q.join(Q.resolve("same"), Q.resolve("same"))

101

.then(value => console.log("Both resolved to:", value))

102

.catch(() => console.log("Values were different"));

103

104

// Join with different values (will reject)

105

Q.join(Q.resolve("first"), Q.resolve("second"))

106

.then(value => console.log("Unexpected success:", value))

107

.catch(() => console.log("Values were different, as expected"));

108

109

// Real-world example: verify consistency

110

function verifyDataConsistency(primarySource, backupSource) {

111

return Q.join(

112

fetchDataFromPrimary(primarySource),

113

fetchDataFromBackup(backupSource)

114

).then(consistentData => {

115

console.log("Data is consistent:", consistentData);

116

return consistentData;

117

}).catch(error => {

118

console.warn("Data inconsistency detected, investigating...");

119

return investigateInconsistency(primarySource, backupSource);

120

});

121

}

122

123

// Permission verification

124

function verifyUserPermissions(userId, requiredRole) {

125

return Q.join(

126

fetchUserRole(userId),

127

Q.resolve(requiredRole)

128

).then(role => {

129

console.log(`User has required role: ${role}`);

130

return true;

131

}).catch(() => {

132

console.log("User does not have required permissions");

133

return false;

134

});

135

}

136

```

137

138

### Async/Generator Support

139

140

Advanced support for ES6 generator functions and async patterns.

141

142

```javascript { .api }

143

/**

144

* Decorator for generator functions to work with promises

145

* @param makeGenerator - Generator function that yields promises

146

* @returns Function that returns promise for generator completion

147

*/

148

function Q.async(makeGenerator);

149

150

/**

151

* Runs async generator immediately with error handling

152

* @param makeGenerator - Generator function to execute

153

* @returns Promise for generator completion result

154

*/

155

function Q.spawn(makeGenerator);

156

```

157

158

**Usage Examples:**

159

160

```javascript

161

const Q = require("q");

162

163

// Q.async for reusable async generators

164

const fetchUserProfile = Q.async(function* (userId) {

165

const user = yield fetchUser(userId);

166

const preferences = yield fetchUserPreferences(userId);

167

const activity = yield fetchUserActivity(userId);

168

169

return {

170

user,

171

preferences,

172

activity,

173

lastUpdated: new Date()

174

};

175

});

176

177

// Use the async function

178

fetchUserProfile(123)

179

.then(profile => console.log("Complete profile:", profile))

180

.catch(error => console.error("Profile fetch failed:", error));

181

182

// Q.spawn for immediate execution

183

Q.spawn(function* () {

184

try {

185

console.log("Starting data migration...");

186

187

const sourceData = yield connectToSourceDatabase();

188

const targetDb = yield connectToTargetDatabase();

189

190

const users = yield sourceData.query("SELECT * FROM users");

191

console.log(`Migrating ${users.length} users...`);

192

193

for (let user of users) {

194

yield targetDb.insert("users", transformUser(user));

195

console.log(`Migrated user: ${user.name}`);

196

}

197

198

yield sourceData.close();

199

yield targetDb.close();

200

201

console.log("Migration completed successfully");

202

} catch (error) {

203

console.error("Migration failed:", error);

204

throw error;

205

}

206

}).done();

207

208

// Complex async workflow

209

const processOrderWorkflow = Q.async(function* (orderId) {

210

const order = yield fetchOrder(orderId);

211

212

// Validate order

213

const validation = yield validateOrder(order);

214

if (!validation.valid) {

215

throw new Error(`Order validation failed: ${validation.errors.join(", ")}`);

216

}

217

218

// Process payment

219

const paymentResult = yield processPayment(order.payment);

220

if (!paymentResult.success) {

221

throw new Error(`Payment failed: ${paymentResult.error}`);

222

}

223

224

// Update inventory

225

yield updateInventory(order.items);

226

227

// Schedule shipping

228

const shipping = yield scheduleShipping(order);

229

230

// Send confirmations

231

yield Q.all([

232

sendCustomerConfirmation(order.customerId, order),

233

sendMerchantNotification(order.merchantId, order),

234

logOrderProcessing(orderId, "completed")

235

]);

236

237

return {

238

orderId,

239

status: "processed",

240

paymentId: paymentResult.transactionId,

241

shippingId: shipping.trackingNumber,

242

processedAt: new Date()

243

};

244

});

245

246

// Usage

247

processOrderWorkflow("order-123")

248

.then(result => console.log("Order processed:", result))

249

.catch(error => console.error("Order processing failed:", error));

250

```

251

252

### Higher-Order Promise Functions

253

254

Advanced functional programming patterns with promises.

255

256

```javascript

257

const Q = require("q");

258

259

// Promise-based map function

260

function promiseMap(array, mapper) {

261

const mappedPromises = array.map(item => Q.resolve(item).then(mapper));

262

return Q.all(mappedPromises);

263

}

264

265

// Promise-based filter function

266

function promiseFilter(array, predicate) {

267

const filterPromises = array.map(item =>

268

Q.resolve(item).then(predicate).then(passed => ({ item, passed }))

269

);

270

271

return Q.all(filterPromises).then(results =>

272

results.filter(result => result.passed).map(result => result.item)

273

);

274

}

275

276

// Promise-based reduce function

277

function promiseReduce(array, reducer, initialValue) {

278

return array.reduce((promise, item) => {

279

return promise.then(accumulator =>

280

Q.all([accumulator, item]).spread(reducer)

281

);

282

}, Q.resolve(initialValue));

283

}

284

285

// Usage examples

286

const numbers = [1, 2, 3, 4, 5];

287

288

// Map with async operation

289

promiseMap(numbers, num => Q.delay(num * 2, 50))

290

.then(doubled => console.log("Doubled:", doubled));

291

292

// Filter with async predicate

293

promiseFilter(numbers, num => Q.delay(num > 3, 10))

294

.then(filtered => console.log("Filtered:", filtered));

295

296

// Reduce with async reducer

297

promiseReduce(numbers, (acc, num) => Q.delay(acc + num, 10), 0)

298

.then(sum => console.log("Sum:", sum));

299

```

300

301

### Composition Utilities

302

303

Utilities for composing promise-based functions.

304

305

```javascript

306

const Q = require("q");

307

308

// Function composition for promises

309

function composeAsync(...functions) {

310

return function(input) {

311

return functions.reduce((promise, fn) => {

312

return promise.then(fn);

313

}, Q.resolve(input));

314

};

315

}

316

317

// Pipeline for sequential processing

318

function pipeline(...stages) {

319

return function(input) {

320

return stages.reduce((promise, stage) => {

321

return promise.then(stage);

322

}, Q.resolve(input));

323

};

324

}

325

326

// Usage

327

const processData = composeAsync(

328

data => Q.delay(data.trim(), 10),

329

data => Q.delay(data.toUpperCase(), 10),

330

data => Q.delay(`Processed: ${data}`, 10)

331

);

332

333

processData(" hello world ")

334

.then(result => console.log(result)); // "Processed: HELLO WORLD"

335

336

// Data processing pipeline

337

const dataPipeline = pipeline(

338

data => validateInput(data),

339

data => enrichWithMetadata(data),

340

data => applyBusinessRules(data),

341

data => formatForOutput(data)

342

);

343

344

dataPipeline(rawData)

345

.then(processedData => console.log("Pipeline result:", processedData))

346

.catch(error => console.error("Pipeline failed:", error));

347

```