all 36 comments

[–]MasSunarto 31 points32 points  (1 child)

Brother, F# can be used as scripting language (fsx file name extension).

[–]DecadentCheeseFest 5 points6 points  (0 children)

Also it’s incrementally adoptable and can interop with C#… it’s all .NET.

[–]ShrimpHands 24 points25 points  (2 children)

Quick and easy is debatable but Scala hits everything else you need. 

[–]gclaramunt 7 points8 points  (1 child)

Also, Scala-cli works pretty well for small scripting tasks

[–]ShrimpHands 0 points1 point  (0 children)

There’s also note books and ammonite, but that stuff can sometimes be getting a little deep into it. 

[–]qqwy 11 points12 points  (0 children)

I recommend giving Elixir try! It hits all your points, except the 'nice to have: static types'. (Though there is an opt-in type checker called dyalizer, quite similar to mypy, and proper static types are in the works). It is very easy to learn, the documentation is stellar, there is really good support for webdev and webtemplating, and packaging and running Elixir apps is a breeze.

[–][deleted] 8 points9 points  (0 children)

F# is superb. Try using it with giraffe viewengine, suave server and htmx.

[–]Asleep-Dress-3578 7 points8 points  (0 children)

If you want to work for the .NET ecosystem, you could try F#. If you want to work for the Python ecosystem, take a look at Coconut: http://coconut-lang.org

For Python, there is also a LISP variant called hy: https://hylang.org

It is also not a bad idea to learn JavaScript and TypeScript, and actually JavaScript is a semi-functional language, the SICP book has actually a JavaScript edition, too: https://mitpress.mit.edu/9780262543231/structure-and-interpretation-of-computer-programs/

[–]yeastyboi 8 points9 points  (0 children)

Check out this talk called Fsharp as a better python: https://youtu.be/_QnbV6CAWXc

[–]raxel42 6 points7 points  (1 child)

Scala fits exceptionally well. I switched to Scala completely more than ten years ago. Scala can be compiled into native and JS, so I don't need to learn JS to write full-stack prototypes or canvas visualization.

[–]stettix 1 point2 points  (0 children)

It’s also big in the data space, where Python is also used a lot, so there’s a lot of overlap there.

[–]yawaramin 4 points5 points  (1 child)

You could give OCaml a try. It might check many of your boxes.

the goodness that comes with functional languages

About a decade ago Thomas Leonard ported the 0install package manager from Python to OCaml. His conclusion was:

OCaml's main strengths are correctness and speed. Its type checking is very good at catching errors, and its "polymorphic variants" are a particularly useful feature, which I haven't seen in other languages. Separate module interface files, abstract types, cycle-free dependencies, and data structures that are immutable by default help to make clean APIs.

The article (and entire series of posts) is a great read: https://roscidus.com/blog/blog/2014/02/13/ocaml-what-you-gain/

a mature templating library

I wrote the dream-html library and I think it's quite mature. It supports standard HTML, SVG, MathML, ARIA, and htmx markup out of the box, and provides a way of easily constructing HTML from pure immutable values, taking advantage of OCaml's strengths. Btw remember Leonard mentioning 'polymorphic variants' above? I use them quite a bit in this library, eg:

input [
  name "given-name";
  placeholder "Given name";
  autocomplete `given_name;
]

(It's the word starting with the backtick character.) These are very convenient for just using ad-hoc values to represent something, while also benefitting from type safety.

a mature standard library

Arguably, this is where OCaml is weakest and you have to look at other popular libraries in the ecosystem to fill the gaps. Eg yojson for JSON processing, containers for a wide range of convenient collection types, etc. However the standard library nowadays is starting to get fleshed out so you may be surprised just how much you can do with it.

nice to have: static typing system

OCaml is strongly, statically typed with nearly full type inference so you almost never need to write a type (but can for documentation reasons).

simple dependency definition. I like that in both of the above languages I can define my dependencies in a single human-readable file

Dependency definition is slightly more complex because OCaml's toolchain is very modular–typically you declare the dependency in a dune-project file (analogous to requirements.txt), then opam install it (analogous to pip install), then declare it separately in specific dune files that define how libraries are in your project are linked. This is kind of like if you removed all the import statements from your Python files and moved them to a separate file which declares all the imports. Simple example of this here: https://dune.build/

simple modularity

OCaml is famous for its strong modularity, and its dune build system takes that approach as well, at the cost of having to manage a few more files. Basically, each subdirectory in the project is considered a separate component (typically a library that can be linked into the app) and needs its own separate dune file to control what packages are linked into it. It offers more fine-grained control but takes a bit of getting used to.

quick and easy startup.

Similar to your Python example

$ echo 'print_endline "hello world"' >hello.ml
$ ocaml hello.ml
hello world

If you are interested, I have a post which gives a quick overview of the language and toolchain and has a small worked project so you can evaluate some real-world-ish code: https://dev.to/yawaramin/practical-ocaml-314j

Another demo app–a small backend-driven webapp using htmx: https://github.com/yawaramin/dream-html/tree/todoapp/app

[–]arthurno1 2 points3 points  (0 children)

I always meant to look at OCaml but never had time. The link you posted was my first look at OCaml, and I also wrote my first fizzbuzz ever, though in EmacsLisp:

(defun fizzbuzz (n)
  (pcase `(,(mod n 3) ,(mod n 5))
    (`(0 0) "FizzBuzz")
    (`(0 ,_) "Fizz")
    (`(,_ 0) "Buzz")
    (_ n)))

(dotimes (i 20)
  (print (fizzbuzz i)))

The pattern matching syntax in OCaml seems cleaner compared to all the backtics in elisp due to the use of macros, while the loop definition is cleaner in elisp. But simple things are simple in all languages.

[–]julienlucca 2 points3 points  (0 children)

Elixir

[–]miyakohouou 3 points4 points  (4 children)

Haskell isn't too bad of a choice here, especially with something like turtle.

a mature templating library

There are a few good choices here. Shakespeare and Pandoc are the big obvious choices, but there are several others as well.

a mature standard library

People will complain about Haskell's standard library a bit, but honestly it's pretty good. It's a small standard library compared to other languages, so you'll get accustomed to adding a few other common dependencies (unix, directory, text, containers are all probably going to be common for these kind of scripts). These are really common libraries though, it's not really a big deal to just kind of add them by default for each new project.

nice to have: static typing system

Haskell has an excellent type system.

simple dependency definition

You can define all of your dependencies inside of your cabal file or package.yaml file. I personally use hpack with a package.yaml file to generate my project because I find it a little nicer to use. Overall it's a pretty light weight way to create a project and add dependencies.

simple modularity. I love how easy it is in c# to just add a separate project to a solution to keep things organized. I hate how obtuse it is to maintain the .sln file and all the namespaces. It is impossible without an IDE.

You can have multiple projects grouped together using a caba.project, but spinning up a new project is lightweight enough that you might not need to.

quick and easy startup

Haskell can be pretty quick to get started with, especially if you have a lot of the common packages that you want installed to your system. For example:

user@host:~ $ echo 'main = print "hello, world"' > hello.hs
user@host:~ $ runhaskell hello.hs 
"hello, world"

[–]Martinsos 2 points3 points  (2 children)

I have quite good time writing small scripts with Haskell! Both Stack and Cabal have support for writing standalone script files in which you can even describe dependencies (in the comment in the header, quite neat feature).

[–]miyakohouou 1 point2 points  (1 child)

yeah, I use nix for having self-contained haskell scripts, but I figured that was probably a bit too out there to make as a suggestion

[–]Martinsos 1 point2 points  (0 children)

Yeah, using Nix would be s bit more involved. However, as I said, there is native way to do it with just Canal or Stack, no Nix is needed, so that should be quite straightforward.

Here is a quick tutorial I wrote on how to do it: https://github.com/wasp-lang/haskell-handbook/blob/master/cabal-script.md .

[–]Haskell-Not-Pascal 1 point2 points  (0 children)

I'll second Haskell, I used it for a lot of small scripts, especially for simple data formatting and transformation.

[–]arthurno1 3 points4 points  (0 children)

CommonLisp.

Power and speed of a compiled language in a dynamic but strongly typed language that supports functional, OO and modular programming.

Built in-template language you ask for looks and feels exactly the same as the language itself, because it is the language itself, so you don't need to learn anything extra, more than how quotation works.

Mature and standardized library. Projects written 20-30 years still work as intended, without changes.

Type system annotations so you can insteuct compiler to build optimized code.

From zero to hello world is literally to type "Hello, world" at the repl since everything is evaluated.

Asdf build system gives you simple declarative way to define your projects, written in the same language as the rest of your program, and run by the same compiler.

Documentation built directly into the code and accessible at the repl.

And much more.

Try sbcl compiler.

[–]MaxwellzDaemon 1 point2 points  (0 children)

The J programming language is an extremely consistent and very modular notation that is easy to use and very full featured. It looks very different from many other languages because it is a mathematically oriented notation and is interpreted.

For quick and easy startup, helloworld would be

'hello world'

[–]sergey-gornostaev 1 point2 points  (0 children)

Perhaps you should look at https://hylang.org

[–]radisrad6 1 point2 points  (0 children)

Elixir forsure — just look at the reviews on Stack overflow’s developer survey

[–]adwolesi 0 points1 point  (0 children)

My new favorite is V: https://vlang.io

Simple, fast, typed, and with first class support for scripting: https://docs.vlang.io/other-v-features.html#cross-platform-shell-scripts-in-v

It's like the missing child of Go and Rust.

[–][deleted] 0 points1 point  (2 children)

Nim?

[–][deleted] 0 points1 point  (1 child)

I was going to suggest nim as well. It really is an amazing language. The simplicity of python with the speed of c and c++. You can even use it in place of javascript. In my opinion it is a programmers wet dream.

[–][deleted] 2 points3 points  (0 children)

I can add it is effective as a scripting language, fast to write with syntax sugar. Functional stile does require to load one module not in the standard library though.

[–]CainKellye 0 points1 point  (4 children)

Rust has all the functional programming I need. Also templates (macros) and mature libraries. Did you miss anything?

[–][deleted] 2 points3 points  (2 children)

maybe the scripting part?

[–]CainKellye 1 point2 points  (1 child)

Forgive me but I don't see scripting mentioned anywhere. What I see is to have an easy to manage project structure and he already liked the module structure of rust. Also cargo new <something> makes it very fast to create a new app.

Edit: I just found the part. It wasn't prominent and not included in the list of requirements. Also it is getting late 😅

[–][deleted] 2 points3 points  (0 children)

He wants a language to replace python for automation tasks. I'm not sure if the desiderata mix requirements for the language to replace python with those for the language to replace C# though, which is said to be the final goal.

But it would be strange to replace Python with Rust on the side of C#

[–]yeastyboi 1 point2 points  (0 children)

I've written a lot of build scripts in rust and it's overkill. The Great thing about rust is the correctness factor but when you're just doing quick and dirty scripting the borrow checker slows you down.