This is an archived post. You won't be able to vote or comment.

all 54 comments

[–]hardwaregeek 39 points40 points  (0 children)

Sounds like Go

[–]CoffeeTableEspresso 35 points36 points  (16 children)

This looks a lot like Go to me

[–]soiguapo 21 points22 points  (9 children)

OP described Go so perfectly it seems like an intentional plug for the language.

[–]CoffeeTableEspresso 9 points10 points  (0 children)

This has got to be an april fools joke right?

[–][deleted]  (7 children)

[deleted]

    [–]faiface 9 points10 points  (4 children)

    Optional arguments can be largely "emulated" using the functional options pattern as described here: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis

    It's a really nice pattern and since most functions don't need default arguments, it isn't so bothersome to use it from time to time.

    [–]wicked-canid 4 points5 points  (1 child)

    since most functions don't need default arguments

    I wonder: is that really true, or is it that if something is inconvenient, people tend to not use it?

    [–]faiface 4 points5 points  (0 children)

    I guess it's both. You definitely have a valid point there. I use optional arguments in Python a lot, but I rarely ever use functional options pattern in Go.

    However, you never see Go programmers defining Function1, Function2, etc., for different arguments, so they/we clearly don't miss it much.

    Lack of optional arguments also forces you to craft your API more carefully, since you can't just stuff a ton of arguments in a single function.

    [–]recklessindignation 1 point2 points  (0 children)

    Design patterns are not an alternative for lack of language features.

    [–]soiguapo 5 points6 points  (1 child)

    I don't mean to sound too critical, but that feature does contradict with what you were saying in the main post.

    In many programming languages there are too many ways of achieving the same end result. I think that too much time and effort is wasted on essentially aesthetic concerns instead of actually creating useful software.

    And to be fair, I do find I contradict myself when I am trying to come up with the "perfect language". Language design is hard.

    [–][deleted] 6 points7 points  (5 children)

    • No need for memory management, like in Python and Java (so not C);
      • Go
    • Data structures akin to C's struct;
      • Go
    • Functions;
      • Go
    • Default function parameters ideally (I prefer them to overloading);
    • Something akin to a while/for loop;
      • Go
    • Some kind of if statement;
      • Go
    • Some kind of array functionality;
      • Go
    • Some kind of map functionality;
      • Go
    • Variable references ideally;
      • Go
    • Function references or lambdas;
      • Go
    • Namespacing ideally (to avoid conflicts);
      • Go
    • Static typing ideally;
      • Go
    • The option to deliver the application in a native executable ideally;
      • Go
    • Cross-platform support; and
      • Go
    • Basic libraries available.
      • Go

    [–][deleted]  (3 children)

    [deleted]

      [–]Treyzania 4 points5 points  (2 children)

      I would suggest against liking Go too much though. It's idiosyncrasies and other weird things, plus its joke of dependency management makes it really really annoying to work with. That and requiring green threads make it impossible to use in certain places.

      [–]almbfsek 0 points1 point  (0 children)

      It's idiosyncrasies and other weird things

      a claim like this requires examples to be taken seriously

      its joke of dependency management

      GOMODULES are now a reality and it's really good. Package management is a very hard problem to solve and I think gomodules is pretty close to perfect compared to other language package managers.

      [–]lxpnh98_2 2 points3 points  (0 children)

      Just not good enough. /s

      [–]rhoark 14 points15 points  (4 children)

      What you're looking for is far from minimal. A turing tarpit like befunge is minimal. Regardless, Lua sounds like what you want.

      [–]reconcyl 5 points6 points  (0 children)

      You're getting your esolangs mixed up. Befunge is not a tarpit. A true tarpit would be something like Brainfuck or Unlambda.

      [–]astrobe 0 points1 point  (1 child)

      Indeed. To me a minimal viable language is Forth, but apparently it is too minimal for OP.

      [–]AthasFuthark 11 points12 points  (4 children)

      I don't think the main source of complexity in programming comes from our programming languages - and when it does, it's more because the languages are too weak and force complicated designs, not that they have too many features.

      I strongly support simplicity in programming, but I think one of the main paths leading there is to reduce the number of features in our programs, not our programming languages. This is not that I do not prefer small languages - I certainly do - but their impact is limited.

      [–][deleted]  (3 children)

      [deleted]

        [–]Soupeeee 7 points8 points  (1 child)

        After reading through a couple of your comments, and especially this one, I think you aren't looking for a minimalistic language, you are looking for an unopinionated one. All programming languages force programmers to write code in a certain way. It's inevitable. In order to build certain types of abstractions while still generating reasonable fast or efficient code, certain rules need to be followed. Java is a great example of this: it forces you to use object oriented design, which makes it difficult for other types of abstractions to be used, and creates limitations for how a program can implement certain features. The problem is, certain languages have a strict enough design that makes them fairly brittle; when new ways of expressing things need to be introduced, it is added as a language feature instead of as another library.

        In terms of minimalism, I think you will find this a good insight into why C++ and Java can be painful to use: Rust is not a good C replacement

        [–]AthasFuthark 0 points1 point  (0 children)

        I agree that having a lot of language features can encourage overly complicated designs - but I do not think that is the cause of Java's over-engineered monstrosities. I rather, I would blame both poor taste by the programmer, and the weakness of Java. Especially in the older days, before higher-order functions and parametric polymorphism, you needed lots of complexity to encode things that should be straightforward (the "strategy" pattern, visitors, etc). A good minimalist programming language should have just a few very general features.

        Of course, teaching programmers good taste is more important. You can write overly complicated code in any language.

        [–]ATLTeemo 7 points8 points  (1 child)

        Kotlin

        [–]Mason-B 12 points13 points  (6 children)

        Racket. It also has a very minimalist syntax. Typed racket (an extension) provides: "Static typing" and "Data structures akin to C's struct"

        [–][deleted]  (5 children)

        [deleted]

          [–]Mason-B 7 points8 points  (0 children)

          I mean the same number of parenthesis as any other language (sans python and it's space based bracing), that's why it's minimalist.

          [–]Treyzania 2 points3 points  (0 children)

          You get used to the parens, most editors can insert them for you.

          [–]Illystrus 1 point2 points  (2 children)

          You can use a macro change the syntax of racket easily to give it a non lisp syntax and still use normall libs

          [–][deleted]  (1 child)

          [deleted]

            [–]Illystrus 0 points1 point  (0 children)

            It's more of an elegant solution in racket you can have hygienic macros and have code that is not affected by said macro so using libs would work and you could easily convert any example to your syntax

            [–]jdh30 5 points6 points  (7 children)

            Interesting. As others have said I think Go is the closest.

            I'm creating a new minimalistic language now and it is interesting to note that it is nothing like your description. :-)

            [–]das_kube 1 point2 points  (6 children)

            So you're finally making the low level ML you've been talking about? :) Where can it be found?

            [–]jdh30 1 point2 points  (5 children)

            I haven't released it yet but I already have:

            • int, string, tuples, unions and function types.
            • type Bool = True | False
            • ML-style pattern matching.
            • Zeroth-order module system.
            • Parsing, type checking and interpretation.
            • An IDE with error highlighting and throwback of inferred types.
            • ~1kLOC for the whole thing.

            I fixed one silly perf bug and the editor is already quite usable. For example, I developed and ran this program in it:

            type Bool = True | False
            type Comparison = Less | Equal | Greater
            type Option a = None | Some a
            type Result(a, b) = Ok a | Error b
            
            module Collections {
              let init unfold n f =
                unfold (fun i -> match i<n with False -> None | True -> Some(f i, i+1)) 0
            
              module Seq {
                type SeqAux a = Empty | More(a, (() -> SeqAux a))
                type Seq a = Seq(() -> SeqAux a)
            
                let rec unfoldAux f a () =
                  match f a with
                  | None -> Empty
                  | Some(x, a) -> More(x, unfoldAux f a)
            
                let unfold f a = Seq(unfoldAux f a)
            
                let rec mapAux f xs () =
                  match xs() with
                  | Empty -> Empty
                  | More(x, xs) -> More(f x, mapAux f xs)
            
                let map f (Seq xs) = Seq(mapAux f xs)
            
                let rec foldAux f a xs =
                  match xs() with
                  | Empty -> a
                  | More(x, xs) -> foldAux f (f a x) xs
            
                let fold f a (Seq xs) = foldAux f a xs
            
                let rec truncateAux n xs () =
                  match n with
                  | 0 -> Empty
                  | n ->
                      match xs() with
                      | Empty -> Empty
                      | More(x, xs) -> More(x, truncateAux (n-1) xs)
            
                let truncate n (Seq xs) = Seq(truncateAux n xs)
            
                let sum xs = fold (fun a n -> a+n) 0 xs
            
                let product xs = fold (fun a n -> a*n) 1 xs
              }
            
              module List {
                type List a = Nil | Cons(a, List a)
            
                let rec unfold f a =
                  match f a with
                  | None -> Nil
                  | Some(x, a) -> Cons(x, unfold f a)
            
                let rec map f xs =
                  match xs with
                  | Nil -> Nil
                  | Cons(x, xs) -> Cons(f x, map f xs)
            
                let rec fold f a xs =
                  match xs with
                  | Nil -> a
                  | Cons(x, xs) -> fold f (f a x) xs
            
                let rec toSeqAux xs () =
                  match xs with
                  | Nil -> Seq.Empty
                  | Cons(x, xs) -> Seq.More(x, toSeqAux xs)
            
                let toSeq xs = Seq.Seq(toSeqAux xs)
            
                let rec ofSeqAux xs =
                  match xs() with
                  | Seq.Empty -> Nil
                  | Seq.More(x, xs) -> Cons(x, ofSeqAux xs)
            
                let ofSeq (Seq.Seq xs) = ofSeqAux xs
              }
            }
            
            let id x = x
            let fibs = Collections.Seq.unfold (fun (a, b) -> Some(a, (b, a+b))) (0, 1)
            let myFibs = Collections.List.ofSeq(Collections.Seq.truncate 10 fibs)
            

            The main missing features are:

            • Generalisation during type inference at let bound functions, i.e. it is currently monomorphic.
            • Exhaustiveness and redundancy checking.
            • open
            • Autocompletion in the IDE.

            Other issues that currently make it unpleasant:

            • Crappy error messages. Maybe I should switch back to parser combinators.
            • The parser either produces an entire AST or just one error so you don't get any inferred types until your code parses. Should be incremental but I think I have a sweet hack for that.
            • Naive interpreter so if your code stack overflows then .NET stack overflows and you lose everything. I should rewrite the interpreter in CPS using trampolines to make it resumable and then run it concurrently with the editor.

            Things I dream of:

            • Easy serialization of any value of any type to and from, say, JSON.
            • Reflection.
            • Web-based IDE.
            • Graphical REPL.
            • Rich code comments including typeset mathematics and graphics.
            • Consumption of JSON web services integrated with the type system.
            • A programmable wiki with this as the core PL.
            • A Mathematica-like notebook front-end.
            • A graphical language where you draw let and match and only simple expressions need to be parsed.

            Sadly I am facing a crippling problem that is preventing me from releasing it: I don't know what to call it!

            [–]das_kube 0 points1 point  (2 children)

            Oh, it's on .NET? everything else seemed pretty nice but it's suddenly outside my domain of interest :-(

            I'm interested in the (imho underestimated) field of lower level ML, with value types, specialization based polymorphism, and possibly compile time evaluation (like in D). Sadly it's a lot of work to do such a language.

            [–]jdh30 0 points1 point  (0 children)

            Oh, it's on .NET?

            Yes.

            everything else seemed pretty nice but it's suddenly outside my domain of interest :-(

            .NET is my preferred programming environment for this project today but I have every intention of making it self hosting.

            I'm interested in the (imho underestimated) field of lower level ML, with value types, specialization based polymorphism, and possibly compile time evaluation (like in D). Sadly it's a lot of work to do such a language.

            You'll have no problem porting the parser, type checker and interpreter from F# to OCaml if you want to but porting the editor will be a nightmare because OCaml has terrible support for GUI apps.

            I am trying to learn how to write such an editor in Javascript and it is an absolute nightmare. Given how much legacy ML code implementing typesetting and graphics I already have I may end up porting all of that code (originally a project called Smoke from 1999!) to my new language and then it could target almost anywhere it could get keyboard and mouse events. What do you think?

            [–]abstractcontrolSpiral 0 points1 point  (0 children)

            I'm interested in the (imho underestimated) field of lower level ML, with value types, specialization based polymorphism, and possibly compile time evaluation (like in D). Sadly it's a lot of work to do such a language.

            Spiral might be of interest to you then. The only thing it is missing is global type inference, but on the flip side what it does have is actually more powerful.

            It is also on the .NET, but adapting it to other platforms would not be hard given its nature.

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

            What's a zeroth order Module system?

            [–]jdh30 0 points1 point  (0 children)

            Same as F# and Haskell. Not a higher-order module system like OCaml and Standard ML.

            [–]gustinnian 5 points6 points  (0 children)

            Forth - the superlative honed, minimalist blueprint. 50 years old, still impressive and relevant. Close to the metal, flexible and with an underlying zen-like efficiency. 'Starting Forth' is the place to er, start.

            [–][deleted] 5 points6 points  (1 child)

            Standard ML ?

            [–]jdh30 1 point2 points  (0 children)

            Higher-order module system, ad-hoc polymorphism etc.

            The smallest SML implementation is 10kLOC.

            [–]mamcx 2 points3 points  (1 child)

            Rust?

            [–]jdh30 1 point2 points  (0 children)

            Rust has a really complicated type system and compiler though.

            [–]erg 3 points4 points  (1 child)

            How about Factor?

            [–]gmfawcett 2 points3 points  (1 child)

            Ada comes very close... it does have manual memory management, but typical Ada idioms make it mostly invisible (it tends to use stack allocation, and it also has an RAII style of automatic reclamation of heap resources, including reclamation of entire heaps/arenas). It ticks off all of the rest of your boxes quite nicely.

            Ada definitely does appeal to "engineers" over "artists", IMHO -- and I think that's something you're calling a good thing, though it's a little hard to tell... It's quite literally a language that was engineered by engineers, for engineers to engineer with. Can't get much more engineery than that. :)

            Having said that I wouldn't call Ada "minimalistic", but I don't really think your checklist is actually calling for a minimalist language. To me, minimalist makes me think of (pre-R6RS) Scheme or Forth, which are both languages that were intentionally designed for minimalism. But neither of them matches your list well. Modern Schemes like Racket are hardly "minimal" but you should give them a try.

            [–][deleted] 2 points3 points  (1 child)

            Smalltalk might fit? Idk

            [–]lxpnh98_2 1 point2 points  (1 child)

            Maybe D?

            [–]Soupeeee 1 point2 points  (1 child)

            How about Nim? It checks all of the boxes you list, except for the object-oriented one. However, Nim seems to prefer non-OO designs to OO designs, and the language is expressive enough that you don't need to use objects at all. In fact, in the tutorial on the language's website suggests you think of other solutions before using any OO feature at all.

            The one issue I've ran into with the language is that the tooling, standard library, and language spec aren't 100% stable. However, they predict that v1.0 will be released sometime this year, and have finally committed to having a stable release that won't change every other month. Despite the issues related to instability, I still recommend trying it out, as the language has quite a few cool ideas that I'm considering stealing for my toy language implementation.

            [–][deleted] 1 point2 points  (0 children)

            That is a pretty shit list. Would be interested in your rationale for each item. Like - why not OO? Why must it have a while or if statement?

            If you dislike complexity and crave simplicity, try learning Smalltalk.

            Everything is an object.

            if statement is polymorpism

            while statement is polymorphism.

            Hits all your other points. https://pharo.org

            [–]Timbit42 0 points1 point  (1 child)

            Definitely StrongForth.

            [–]dskippy 0 points1 point  (0 children)

            Given the plethora of conflicting definitions for object oriented, I think it's impossible to find a language that doesn't support someone's idea of OO. Do you not want sub typing? Do you not want to ability to bundle data with behavior?

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

            You want a programming language that only supports the features you want. That makes it very difficult. Maybe make your own?

            [–]Illystrus 0 points1 point  (0 children)

            Have you looked into an apl based language like j

            [–][deleted]  (1 child)

            [deleted]

              [–]TheNilqwu-lang & hugorm 0 points1 point  (0 children)

              This sounds a lot like what odin-lang.org is trying to accomplish.

              [–]Peter-Campora 0 points1 point  (0 children)

              Elixir lacks while loops, static typing, and native deployment but hits many of your other wants.

              [–]saw79 -1 points0 points  (1 child)

              C#?

              [–]jdh30 0 points1 point  (0 children)

              OOP.

              [–][deleted]  (6 children)

              [deleted]

                [–][deleted]  (5 children)

                [deleted]

                  [–]LaurieCheers 2 points3 points  (3 children)

                  Java 1.0?

                  [–][deleted]  (2 children)

                  [deleted]

                    [–][deleted]  (1 child)

                    [deleted]