4 ms·
Show HN: The U Programming Language
- EGreg 1y agoHere is some example code // U Demo Program: “Ledger & Fibers” // Showcases every language feature in a cohesive file. /* Notes: - Tabs only for indentation - All statements are expressions - Nested block comments work: /* inside here */ still fine */ /* 1) Globals and base values */ versionMajor:I := 1 versionMinor:I := 0 applicationName:S := "Ledger & Fibers" noValue:N := N userIdList:[I] := [1, 2, 3, 5, 8, 13] weightList:[D] := [0.5, 1.5, 2.5] idByName:{I} := {"alice": 1, "bob": 2} matrixValues:[[I]] := [[1,2,3],[4,5,6],[7,8,9]] userCount:I := userIdList.l() matrixCopy:[[I]] := matrixValues.c() maybeCount:I := noValue ?? userCount ?? 0 arithResult:I := (2 ^ 3 * 2 + 1 ; 7 * 3) bitMask:I := (~| 0 ~| 0) logicValue:L := !true | true & !false != false isLedgerType:L := N : Ledger /* 2) Modifiers */ initialBudget:D-M := 100.00 sharedRemotePool:D+R+M := 1000.00 localCounter:I-R := 0 mandatoryId:I-N := 1 globalRemoteValue:D+R globalRemoteValue := sharedRemotePool /* 3) Functions */ doubleValue := f(number) => number * 2 f clampValue(input:D, minValue:D := 0.0, maxValue:D := 1.0):D clampValue => input < minValue ? minValue : (input > maxValue ? maxValue : input) f addAndSubtract(first:I, second:I) addAndSubtract => (first + second, first - second) sumResult:I; diffResult:I [sumResult, diffResult] := addAndSubtract(10, 3) f calculateStats(values:[I]) totalSum:I := 0 values.x(f(item) => totalSum += item) calculateStats => {sum: totalSum, count: values.l()} {sum: totalUsers, count: totalCount} := calculateStats([2,3,5,7]) f nextUniqueId() nextUniqueId := ++nextUniqueId.counterValue nextUniqueId.counterValue := 100 /* 4) Errors */ d ErrorType { f n(message:S, code:I) () } f parseIntOrFail(stringValue:S):I (stringValue == "bad") ? e => ErrorType.n("invalid int", 400) parseIntOrFail => 42 d ConsoleErrorHandler { f ErrorType(message:S, code:I) () } f tryParseInt(stringValue:S):I handlerObject := ConsoleErrorHandler.n() resultValue:I := parseIntOrFail(stringValue) : handlerObject resultValue === N ? 0 : resultValue /* 5) Generators and .x */ f fibonacciGenerator() fibonacciGenerator := fibonacciGenerator.previousValue + fibonacciGenerator.beforePrevious fibonacciGenerator.beforePrevious := fibonacciGenerator fibonacciGenerator.previousValue := fibonacciGenerator.beforePrevious fibonacciGenerator.beforePrevious := 1; fibonacciGenerator.previousValue := 1 f collectFibonacciBelow(limitValue:I):[I] fibList:[I] := [] indexValue:I := 0 w nextFib:I := fibonacciGenerator() (nextFib >= limitValue) ? b => fibList fibList := fibList + [nextFib] c f dictionaryToPairs(dictValues:{I}):[[S]] outputPairs:[[S]] := [] dictValues.x(f(pair) isBig:L := pair.value > 10 ? true : false outputPairs := outputPairs + [[pair.key, isBig ? "big" : "small"]] ) dictionaryToPairs => outputPairs /* Yield example: create an infinite sequence of even numbers */ f evenNumberGenerator() counterValue:I := 0 w y => counterValue counterValue += 2 /* 6) Classes */ d Money { amountValue:D-M currencyCode:S-M f n(amount:D, currency:S) () f addAmount(extra:D):Money () Money => Money.n(amountValue + extra, currencyCode) } Money.zeroUSD := Money.n(0.0, "USD") Money.addAll := f(moneyList:[Money]) => moneyList.l() == 0 ? Money.zeroUSD : ( totalAmount:D := 0.0; moneyList.x(f(moneyItem) => totalAmount += moneyItem.amountValue); Money.n(totalAmount, moneyList[0].currencyCode) ) d Ledger { titleText:S-M totalAmount:D-M remoteMirror:D+R entryList:[[S]] f n(title:S, startAmount:D) () f postEntry(entryDate:S, entryMemo:S+R) () entryList := entryList + [[entryDate, entryMemo]] Ledger => title f balance():Money () Ledger.balance => Money.n(totalAmount + remoteMirror, "USD") } Ledger.createUSD := f(title:S, startAmount:D):Ledger ( ledgerInstance:Ledger := Ledger.n(title, startAmount); ledgerInstance.remoteMirror := startAmount * 0.0; ledgerInstance ) f isLedgerInstance(value):L value : Ledger ? true : false /* 7) Remote rules */ globalLedger:Ledger+R f setGlobalLedger(ledgerValue:Ledger+R) globalLedger := ledgerValue f linkRemotePoolToLedger(ledgerValue:Ledger+R, poolValue:D+R) ledgerValue.remoteMirror := poolValue linkRemotePoolToLedger => ledgerValue f addEntryAndClampAmount(ledgerValue:Ledger+R, entryDate:S, entryMemo:S+R, deltaAmount:D):Money clampedAmount:D := clampValue(deltaAmount, -1000.0, 1000.0) resultMoney:Money := ledgerValue.postEntry(entryDate, entryMemo).balance() (resultMoney ; Money.n(resultMoney.amountValue + clampedAmount, resultMoney.currencyCode)) /* 8) Arrays & math */ f sumMatrixRow(matrixData:[[I]], rowIndex:I):I rowSum:I := 0 matrixData[rowIndex].x(f(value) => rowSum += value) sumMatrixRow => rowSum f exponentMix(first:I, second:I):I exponentMix => 2 ^ first * second + 1 /* 9) While-generator */ f sumValuesUnderLimit(values:[I], limit:I):I accumulator:I := 0 indexValue:I := 0 w indexValue >= values.l() ? b => accumulator currentValue:I := values[indexValue]; ++indexValue currentValue >= limit ? c : 0 accumulator += currentValue /* 10) Error in practice */ f recordAmountFromString(stringValue:S, ledgerValue:Ledger+R):Money parsedAmount:I := tryParseInt(stringValue) addEntryAndClampAmount(ledgerValue, "2025-08-13", "parsed", parsedAmount) /* 11) Main */ f main():I operationsLedger:Ledger := Ledger.createUSD("Ops", 10.0) setGlobalLedger(operationsLedger) linkRemotePoolToLedger(operationsLedger, sharedRemotePool) [plusValue, minusValue] := addAndSubtract(8, 5) {sum: sumUsers, count: countUsers} := calculateStats(userIdList) fibNumbers:[I] := collectFibonacciBelow(200) dictPairs:[[S]] := dictionaryToPairs({"a": 1, "b": 22, "c": 5}) moneyOne:Money := Money.n(12.5, "USD") moneyTwo:Money := moneyOne.addAmount(7.5) moneyTotal:Money := Money.addAll([moneyOne, moneyTwo]) bookedOne:Money := recordAmountFromString("bad", operationsLedger) bookedTwo:Money := recordAmountFromString("123", operationsLedger) sumSmallValues:I := sumValuesUnderLimit([1,2,50,3,4], 10) secondRowSum:I := sumMatrixRow(matrixValues, 1) mixedValue:I := exponentMix(3, 2) fibCount:I := fibNumbers.l() ?? 0 sumFibs:I := 0 fibNumbers.x(f(numValue) => sumFibs += numValue) isLedgerInstance(operationsLedger) ? sumFibs += 1 : sumFibs += 0 // Use yield-based even number generator for first 5 evens firstEvens:[I] := [] evensGen := evenNumberGenerator() counterIndex:I := 0 w counterIndex >= 5 ? b => firstEvens firstEvens := firstEvens + [evensGen.y()] counterIndex += 1 main => (fibCount + secondRowSum + mixedValue + sumFibs + sumUsers + countUsers)
- CureYooz 1y agoHow about an example that is actually readable and easy to follow?
- EGreg 1y agoHere, I will write one by hand right now: d IntegerMath : SomeInterface, SomeOtherInterface someProperty:I someOtherProperty:I-M referenceProperty:IntegerMath+R+N // nullable recursiveProperty:IntegerMath+N // error! needs +R f stuff(myObj: IntegerMath+M+R, newValue: I+M) newValue = 4 // modifies caller's reference myObj.someProperty = newValue // error, need newValue.c() myObj.someOtherProperty = 4 // error, immutable property IntegerMath.max = f(first:I, second:I):I r => first > second ? first : second IntegerMath.min = f(first:I, second:I):I => first < second ? first : second // let's use the class im = IntegerMath.n({someOtherProperty: 4}) // infers im:IntegerMath im.someProperty = 3 im.stuff(im, someInteger) // modifies both result = Math.sort([1,2,3], IntegerMath.max) // infers result:[I] another = Math.sort(result, f(first:I, second:I):I => first > second ? first : second) // conditional code [1,2,3].x( f(k) k > 2 ? console.log(k) : ( result = k console.log(k-2) ) // this is a closure but doesn't assign // anything to +R variables, so it's not +R itself // in Swift language, it's not "escaping"
- Someone 1y agof addAndSubtract(first:I, second:I) addAndSubtract => (first + second, first - second) sumResult:I; diffResult:I [sumResult, diffResult] := addAndSubtract(10, 3) Weird choice to create a tuple with (a,b), but destructure it with [a,b], even more so given f calculateStats(values:[I]) totalSum:I := 0 values.x(f(item) => totalSum += item) calculateStats => {sum: totalSum, count: values.l()} {sum: totalUsers, count: totalCount} := calculateStats([2,3,5,7]) There, creating and destructuring a hash use matching syntax {} I also don’t like single character names for length, iteration, and don’t understand the type system. :I is an integer, but :I-R? I can’t figure out what that means from this example.
- EGreg 1y ago