Xah Talk Show 2026-07-27 Ep810. on why ocaml fsharp are best langs. cpp worst.

xah talk show ep810 2026-07-28 193ef
xah talk show ep810 2026-07-28 193ef

highlights

Video Summary (Generated by AI, Edited by Human.)

In this video, Xah Lee shares his perspectives on programming languages, focusing on his belief that ML and its descendants—specifically OCaml and F#—are superior languages compared to mainstream ones like C, C++, JavaScript, and PHP (1:07, 21:54, 47:08).

Key themes and discussions include:

The superiority of ML/OCaml/F#: Xah Lee argues that the Hindley-Milner type system (introduced in the 1970s) provides the best approach to type inference, which he contrasts with the "idiocy" of manually declaring types for the machine in languages like C and C++ (5:25, 14:00-15:35).

The legacy of Lisp: He emphasizes that many essential modern programming features—such as automatic memory management, functional programming, interpreted environments (REPLs), and exception handling—originated from Lisp (9:37-13:20).

Social forces in language adoption: Xah Lee posits that the popularity of languages like JavaScript, PHP, and C++ is driven by corporate and social forces rather than technical excellence (21:34, 29:37).

Personal background and learning: He discusses his 30-year history as a coder, starting with the Wolfram Language (which he considers a magnitude more advanced than other languages) and his long-time experience with Emacs Lisp (23:13, 34:55).

Practical coding explorations: Throughout the video, he attempts to explore how to call shell commands from F# (20:19, 54:00) and discusses the challenges of finding native ways to get image dimensions (width/height) on Windows compared to macOS (113:28-115:36).

# call shell command
print qx("dir")
open System
open System.Diagnostics
open System.Text

type ProcessResult = {
    ExitCode: int
    StdOut: string
    StdErr: string
}

let executeProcess (processName: string) (processArgs: string) =
    let psi = ProcessStartInfo(processName, processArgs)
    psi.UseShellExecute <- false
    psi.RedirectStandardOutput <- true
    psi.RedirectStandardError <- true
    psi.CreateNoWindow <- true

    use proc = Process.Start(psi)
    let output = StringBuilder()
    let error = StringBuilder()

    proc.OutputDataReceived.Add(fun args ->
        if not (isNull args.Data) then output.AppendLine(args.Data) |> ignore)
    proc.ErrorDataReceived.Add(fun args ->
        if not (isNull args.Data) then error.AppendLine(args.Data) |> ignore)

    proc.BeginOutputReadLine()
    proc.BeginErrorReadLine()
    proc.WaitForExit()

    {
        ExitCode = proc.ExitCode
        StdOut = output.ToString()
        StdErr = error.ToString()
    }

// s------------------------------

// let result = executeProcess "uptime" "-p" // Linux/macOS
// or
// let result = executeProcess "cmd.exe" "/c dir" // Windows

let result = executeProcess "dir"

printfn "Exit code: %d" result.ExitCode
printfn "Stdout:\n%s" result.StdOut
if result.StdErr <> "" then
    eprintfn "Stderr:\n%s" result.StdErr

How to call shell commands in Fsharp?

ai answer

In F#, you call shell commands (or any external process) using the .NET System.Diagnostics.Process class. This is the standard, built-in approach—no extra packages required.

Basic synchronous example (capture stdout, stderr, and exit code)

open System
open System.Diagnostics
open System.Text

type ProcessResult = {
    ExitCode: int
    StdOut: string
    StdErr: string
}

let executeProcess (processName: string) (processArgs: string) =
    let psi = ProcessStartInfo(processName, processArgs)
    psi.UseShellExecute <- false
    psi.RedirectStandardOutput <- true
    psi.RedirectStandardError <- true
    psi.CreateNoWindow <- true

    use proc = Process.Start(psi)
    let output = StringBuilder()
    let error = StringBuilder()

    proc.OutputDataReceived.Add(fun args ->
        if not (isNull args.Data) then output.AppendLine(args.Data) |> ignore)
    proc.ErrorDataReceived.Add(fun args ->
        if not (isNull args.Data) then error.AppendLine(args.Data) |> ignore)

    proc.BeginOutputReadLine()
    proc.BeginErrorReadLine()
    proc.WaitForExit()

    {
        ExitCode = proc.ExitCode
        StdOut = output.ToString()
        StdErr = error.ToString()
    }

Usage:

let result = executeProcess "uptime" "-p"          // Linux/macOS
// or
let result = executeProcess "cmd.exe" "/c dir"     // Windows

printfn "Exit code: %d" result.ExitCode
printfn "Stdout:\n%s" result.StdOut
if result.StdErr <> "" then
    eprintfn "Stderr:\n%s" result.StdErr

Simpler version (when you mainly care about exit code + full output)

open System.Diagnostics

let run (cmd: string) (args: string) =
    let startInfo = ProcessStartInfo(
        FileName = cmd,
        Arguments = args,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        UseShellExecute = false,
        CreateNoWindow = true
    )
    use p = Process.Start(startInfo)
    let stdout = p.StandardOutput.ReadToEnd()
    let stderr = p.StandardError.ReadToEnd()
    p.WaitForExit()
    p.ExitCode, stdout, stderr

Running a full shell command (e.g. with pipes, redirects, etc.)

On Linux/macOS you typically invoke a shell:

// Using bash
let result = executeProcess "/bin/bash" "-c \"ls -la | head -5\""

// Or more portably with env
let result = executeProcess "/usr/bin/env" "bash -c \"echo Hello from shell\""

On Windows:

let result = executeProcess "cmd.exe" "/c \"dir & echo Done\""
// or
let result = executeProcess "powershell.exe" "-Command \"Get-Process | Select-Object -First 5\""

Asynchronous version (recommended for modern code)

open System.Diagnostics
open System.Threading.Tasks

let executeCommandAsync executable (args: string list) = async {
    let startInfo = ProcessStartInfo()
    startInfo.FileName <- executable
    startInfo.RedirectStandardOutput <- true
    startInfo.RedirectStandardError <- true
    startInfo.UseShellExecute <- false
    startInfo.CreateNoWindow <- true
    args |> List.iter startInfo.ArgumentList.Add

    use p = new Process(StartInfo = startInfo)
    p.Start() |> ignore

    let! stdoutTask = p.StandardOutput.ReadToEndAsync() |> Async.AwaitTask
    let! stderrTask = p.StandardError.ReadToEndAsync() |> Async.AwaitTask
    do! p.WaitForExitAsync() |> Async.AwaitTask

    return p.ExitCode, stdoutTask, stderrTask
}

Important notes

Higher-level library (optional)

If you prefer a more F#-idiomatic API with computation expressions, consider the Fli library:

dotnet add package Fli
open Fli

cli {
    Shell BASH          // or CMD, PWSH, etc.
    Command "ls -la | head -3"
}
|> Command.execute
|> Output.toText
|> printfn "%s"

For most cases the built-in System.Diagnostics.Process approach is sufficient and has zero dependencies.