Show HN: The U Programming Language

1 EGreg 3 8/13/2025, 4:26:13 PM gist.github.com ↗

Comments (3)

EGreg · 1h ago
Here 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)
Someone · 58m ago

  f 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.

CureYooz · 1h ago
How about an example that is actually readable and easy to follow?