Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request 'feat(sheets): LAMBDA user-defined functions (#88)' (#115) from feat/lambda-function into main

scott 9911daf0 7256e4ba

+31 -1
+6 -1
src/sheets/formulas.ts
··· 353 353 if (t.value === 'LET') { 354 354 return this.parseLet(); 355 355 } 356 + // Special handling for LAMBDA — user-defined functions (#88) 357 + if (t.value === 'LAMBDA') { 358 + return this.parseLambda(); 359 + } 356 360 // Special handling for INDIRECT — needs access to getCellValue and crossSheetResolver 357 361 if (t.value === 'INDIRECT') { 358 362 return this.parseIndirect(); ··· 585 589 this.expect(TokenType.RPAREN); 586 590 587 591 // Evaluate body with params bound to call args 588 - const prevScope = { ...this._letScope }; 592 + const prevScope = this._letScope ? { ...this._letScope } : {}; 593 + this._letScope = this._letScope || {}; 589 594 for (let i = 0; i < paramNames.length; i++) { 590 595 this._letScope[paramNames[i]] = callArgs[i] ?? 0; 591 596 }
+25
tests/formulas.test.ts
··· 821 821 expect(result).toBe('#N/A'); 822 822 }); 823 823 }); 824 + 825 + // --- LAMBDA (#88) --- 826 + 827 + describe('LAMBDA', () => { 828 + it('basic: two params, addition', () => { 829 + expect(evalWith('LAMBDA(x, y, x+y)(2, 3)')).toBe(5); 830 + }); 831 + 832 + it('single param', () => { 833 + expect(evalWith('LAMBDA(x, x*2)(7)')).toBe(14); 834 + }); 835 + 836 + it('three params', () => { 837 + expect(evalWith('LAMBDA(a, b, c, a+b+c)(10, 20, 30)')).toBe(60); 838 + }); 839 + 840 + it('works with cell references in call args', () => { 841 + const cells = { A1: 5, B1: 3 }; 842 + expect(evalWith('LAMBDA(x, y, x-y)(A1, B1)', cells)).toBe(2); 843 + }); 844 + 845 + it('returns #VALUE! when not immediately invoked', () => { 846 + expect(evalWith('LAMBDA(x, x+1)')).toBe('#VALUE!'); 847 + }); 848 + });