← Back to context

Comment by dev_l1x_be

2 days ago

I would love to have a scripting language has typed features and you can replace bash with.

What comes close is:

    #! /usr/bin/env elixir

    Mix.install([:jason])

    defmodule JsonPrettyPrinter do
      def get_stdin_data do
        :stdio
        |> IO.read(:all)
        |> Jason.decode()
        |> case do
          {:ok, json_data} -> json_data
          _ -> raise "Invalid JSON payload was provided"
       end
     end
    end

    JsonPrettyPrinter.get_stdin_data()
    |> JsonPrettyPrinter.pretty_print_json()
    |> IO.puts()

Have you seen nushell? It lets me one-liner so many things that would have previously taken breaking out a "real" language to do

Contrived example:

  ls | where type == 'file' | sort-by size | take 4  | each {|f| {n: $f.name, s: ($f.size | format filesize MB) }} | to json

outputs

  {
    "n": "clippy.toml",
    "s": "0.000001 MB"
  },
  {
    "n": "README.md",
    "s": "0.000009 MB"
  },
  {
    "n": "rustfmt.toml",
    "s": "0.000052 MB"
  },
  {
    "n": "typos.toml",
    "s": "0.00009 MB"
  }

  • With this:

        E = Struct.new(:name, :size, :type)
        def ls = Dir.children('.').map{ s=File::Stat.new(_1); E.new(_1, s.size, s.file? ? 'file' : 'dir') }
    

    This becomes valid Ruby:

        ls.find_all{_1.type == 'file'}.sort_by(&:size).take(4).map{ {n: _1.name, s: _1.size } }.each { puts JSON.pretty_generate(_1) }
    

    (drops your size formatting, so not strictly equivalent)

    Which isn't meant to "compete" - nushell looks nice -, but to show that the lower-threshold option for those of us who don't want to switch shells is to throw together a few helpers in a language... (you can get much closer to your example with another helper or two and a few more "evil" abuses of Ruby's darker corners, but I'm not sure it'd be worth it; I might a wrapper for the above in my bin/ though)

  • I've tried nushell and other shell replacements and it just feels like I'm learning a new programming language for no good reason

    • To be fair the example above is easier to remember than:

        ls -l --sort=size | head -n 5 | tail -n 4 | awk '{print $5 " = " $9}' | numfmt --to iec | jq --raw-input --null-input 'inputs | gsub("\r$"; "") | split(" = "; "") | select(length == 2) | {"s": (.[0]), "n": .[1]}'

      9 replies →

    • Yeah... https://www.sophiajt.com/case-for-nushell/ makes a really good case for Nushell as an alternative to Bash.

      Unfortunately, I don't think Nushell brings much benefit for folks who already know Bash enough to change directories and launch executables and who already know Python enough to use more complicated data structures/control flow/IDE features

      I'm still rooting for Nushell as I think its a really cool idea.

      1 reply →

    • Ok if it's not for you. But there is of course a very good reason — work with objects in the pipeline instead of "dumb text". Also PowerShell and nushell are quite nice to learn, whereas Bash is absolutely horrible.

      2 replies →

    • Well, the reason is you can stop using Bash. If you never write Bash scripts already then you probably don't need it (and also congratulations on doing things right), but most people at least have lazy colleagues that write shell scripts. One day I'd like them to be not awful.

  • In PowerShell:

      gci -file | sort-object size | select name, size -first 4 | % { $_.size /= 1MB; $_ } | ConvertTo-Json

    • i dont think you need to select name and size, you can just remove it and use `select -first 4`, but cool, I never knew about `/=` syntax

      1 reply →

  • For me the best benefit of nushell is not the easier syntax, but the static type checks. It catches most typos before running the script, which is a godsend when the script is slow and/or has destructive operations.

  • Was just about to suggest nushell. I love programming in nushell, the out of the box features are excellent.

OCaml is a scripting language in this sense. No need to compile an executable ahead of time, just have a `#!/usr/bin/env ocaml` shebang (or more realistically: `#!/usr/bin/env -S ocaml -I +unix unix.cma`) at the top of a source file.

Though, I don't think it has the capability for single-file scripts to declare 3rd-party dependencies to be automatically installed.

  • It also has poor support for Windows.

    The best option I've found for this use case (ad-hoc scripting with third party dependencies) is Deno.

    I'm hoping Rust will get there in the end too.

Two interesting options for everyday scripting are Python and Powershell.

  • I am unhappy with python. It degrades fast. It deprecates libraries every minor release and that tends to break the applications I use. Recent examples are distutils and opsaudio.

    • For everyday scripting -- the types of things where I'd be writing in bash but get frustrated with it and switch to python -- I nearly always only need what's in the stdlib.

      Sure, for "applications", the ecosystem can be frustrating at times, but I don't think that's what we're talking about here.

  • Python is actually kind of awkward for this use case since you can't import from other files easily unless you are in a proper Python package, which isn't usually the case for everyday scripting.

  • you won't believe how powerful Python is with libraries. ChatGPT and Claude made a brand new browser, that isn't based on Chromium or Firefox, and yet still follows many aspects of layout correctly. I read the article we're discussing ("stop designing languages") on this browser and I'm currently using it to post this reply.

If you just wait a few months, then that program will be written in a typed language. The type checker for Elixir is coming along nicely and every release brings more checks.

Suggest you take a look at https://raku.org for a strongly (but gradual) typed scripting language.

I wanted to say Haskell with shh[^1] and stack's or nix's shebangs[^2][^3], but interpreted haskell is not particularly fast.

Also I think a Python script is reasonable if you use a type-checker with full type annotations, although they are not a silver bullet. For most scripts I use fish, which is my preferred interactive shell too.

[1]: https://hackage.haskell.org/package/shh

[2]: https://docs.haskellstack.org/en/v3.9.1/topics/scripts/

[3]: https://wiki.nixos.org/wiki/Nix-shell_shebang. On a side note, if you were to use nix's shebang for haskell scripts with dependencies, you should be using https://github.com/tomberek/- instead of impure inputs, because it allows for cached evaluation. I personally cloned the repo to my personal gitlab account, since it's small and should never change

@dev_l1x_be: The answer isn't a new typed scripting language. It's recognizing what the interpreter already is.

LLMs are eval(). Skills are programs. YAML is the motherboard.

@unkulunkulu nails it -- "library as the final language", languages all the way down. Exactly. Skills ARE languages. They teach the interpreter what to understand. When the interpreter understands intent, the distinction dissolves.

@conartist6: "DSL is fuzzy... languages and libraries don't have to be opposing" -- yes. Traditional DSL: parse -> AST -> evaluate. LLM "DSL": read intent -> understand -> act. All one step. You can code-switch mid-sentence and it doesn't care.

The problem with opinionated frameworks like ROR and their BDFLs like DHH is that one opinion is the WRONG number!

The key insight nobody's mentioned: SPEED OF LIGHT vs CARRIER PIGEON.

Carrier pigeon: call LLM, get response, parse it, call LLM again, repeat. Slow. Noisy. Every round-trip destroys precision through tokenization.

Speed of light: ONE call. I ran 33 turns of Stoner Fluxx -- 10 characters, many opinions, game state, hands, rules, dialogue, jokes -- in a single LLM invocation. The LLM simulates internally at the speed of thought. No serialization overhead. No context-destroying round trips.

@jakkos, @PaulHoule: nushell and Python are fine. But you're still writing syntax for a parser. What if you wrote intent for an understander?

Bash is a tragedy -- quoting footguns, jq gymnastics, write-only syntax. Our pattern: write intent in YAML, let the LLM "uplift" to clean Python when you need real code.

Postel's Law as type system: liberal in what you accept. Semantic understanding catches nonsense because it knows what you MEANT, not just what you TYPED.

Proof and philosophy: https://github.com/SimHacker/moollm/blob/main/designs/stanza...

  • Holy slop!

    • That's a trite, low effort, worthless, content free comment, which totally misses the point and fails to engage. You haven't made any other comments contributing to this discussion, except that one shallow drive by complaint. If you're going to whine about using llms as a shell, then at least try to do better than an llm or redditor yourself.

      So do you disagree with any of my points, or my direct replies to other people's points, or is that all you can think of to say, instead of engaging?

      Do you prefer to use bash directly? Why? If not, then what is your alternative?

      What do you think of Anthropic Skills? Have you used or made any yourself, or can you suggest any improvements? I've created 50+ skills, and I've suggested, implemented, and tested seven architectural extensions -- do you have any criticism of those?

      https://github.com/SimHacker/moollm/tree/main/skills

      Obviously you use llms yourself, so you're not a complete luddite, and you must have some deeper more substantial understanding and criticism than those two words from your own experience.

      How do your own ideas that you blogged about in "My LLM System Prompt" compare to my ideas and experience, in your own "professional, no bullshit, scientific" opinion?

      https://mahesh-hegde.github.io/posts/llm_system_prompt/

      Your entire blog post on LLM prompts is "I don't like verbiage" in five sentences. Ironic, then, that your entire contribution here is two empty words. I made specific technical points, replied to real people, linked proof. 'Slop' is the new 'TL;DR' -- a confession of laziness dressed as critique. Calling substance slop while contributing nothing? That's actual slop.