Threads for b3n

  1. 2

    Another very powerful option is the Emacs calculator.

    1. 1

      This is what I use, though I know I’ve barely scratched the surface; I just use it as a plain RPN calcluator.

    1. 2

      Is this a security risk? If you’re using your doas function rather than /usr/bin/doas then anyone who gains access to the current user has permission to modify the function and trivially capture the root password.

      1. 10

        Anyone who gains access to the current user could define their own function and trivially capture the root password.

      1. 18

        The article conflates two questions. Will Nix be more popular than Docker? Probably not. Will Nix be able to do everything Docker does? It has been able to do that for a couple years now!

        1. 1

          Does Nix let you build a single file package that AWS (for example) can spin up in response to a network event?

          1. 8

            You can build OCI container using Nix, so my answer would be - probably yes.

            1. 3

              So I guess another question to put is, will nix replace the docker file?

              1. 6

                Nix replaced Dockerfiles for my team at work.

                Atlassian Marketplace is a big Scala application, the jar is built via a Nix shell and then we use Nix to build an OCI container image. The image is pushed to a registry where the internal Atlassian PaaS is able to deploy to production. Every release is completely reproducible, bit for bit!

              2. 2

                neat, and i didn’t know that. thanks.

              3. 6

                Guix (which I think of as a better Nix) lets you do this. You can even produce a pack in the Docker image format directly from Guix.

                1. 2

                  I had not seen that; thank you.

            1. 3

              Do any of these shortcomings also exist in Guix?

              1. 5

                Sort of…

                They share the issue that unlike apt where if you get an option wrong, some C code tells you that you got an option wrong, nix and guix just pass the wrong option down into interpreted code where you eventually get “string found where integer expected” or some such.

                The difference is: guix’s error messages come from guile, a much more mature language runtime than nix.

                I try nix once or twice a year, but I have to learn in all over again each time, and it’s rough.

                I tried guix for the first time this past week, and even though I hit many issues, I found it much easier to diagnose and address them.

                Full disclosure: I do have years of scheme/lisp experience, though none of it very recent. I have also done a non-trivial amount of Haskel/ocaml work. I like ocaml more than scheme. But I hate “programming” shell scripts.

                In guix, I see much less occasion to drop down out of scheme to shell scripting.

              1. 3

                What does “only HTML” mean here?

                1. 1

                  Before it was just a google form for collecting url. Got too many of them. Bow there is simple php script.

                1. 7

                  This is a fascinating read! I had no idea this was possible.

                  However, I would caution against generalizing here to lisps more broadly; the ability to embed a function value directly in a macroexpansion seems to be a quirk of CL and Janet as far as I can tell; even other lisps sharing close ancestry with CL like Emacs Lisp don’t support it.

                  1. 6

                    Turns out I had made a typo and it does in fact work in Clojure.

                    However, the rationale for doing it does not really apply in Clojure since the macro system integrates smoothly with the namespace system, and backquote fully-qualifies all symbols by default with the namespace in which the intended function is found, so while it’s possible to use this technique, it’s a solution for a problem that doesn’t exist; introducing shadowed names in the context of the macro caller cannot cause the macroexpansion to resolve to the wrong function.

                    1. 3

                      Or is the implicit namespace-qualification a solution to a problem that doesn’t exist? :)

                      Common Lisp does the same thing, actually — maybe Clojure copied this from Common Lisp (?). It is a totally valid solution, but (at least in Common Lisp; not sure if Clojure does something more clever) you can still run into issues if your macros are defined in your own package, reference functions in that same package, and are also expanded in that same package — everything is in the same namespace. Which like… yeah then you oughtta know what your macros look like, I guess. But “lexically scoped macros” or whatever work regardless of the namespace structure.

                      (Also, strong caveat: I have no idea what I’m actually talking about and am basing those statements on what I read in On Lisp and have never written production lisp in my life.)

                      1. 5

                        It is a totally valid solution, but (at least in Common Lisp; not sure if Clojure does something more clever) you can still run into issues if your macros are defined in your own package, reference functions in that same package, and are also expanded in that same package — everything is in the same namespace.

                        Yeah, this doesn’t happen at all in Clojure. Even if you’re referencing something from the current namespace it gets fully expanded into an unambiguous reference in the quoted form. It’s basically impossible to write an unhygenic macro in Clojure unintentionally.

                        1. 6

                          It has its weird issues, though. You can unintentionally write a macro that doesn’t want to expand due to hygiene errors:

                          (ns foobar)
                          
                          (def x 10)
                          
                          ;; ...Perhaps a lot of code...
                          
                          (defmacro foo [arg]
                            `(let [x 1]
                               (+ x 1)))
                          

                          If you try to use foo, it will complain that the x in the let bindings is not a “simple symbol” (because it gets expanded to (let [foobar/x 1] (+ foobar/x 1)) which is thankfully not valid). And fair enough, you will hit this issue as soon as you try to use the macro, so it should be relatively easy to debug.

                          Also, the system breaks down when you’re trying to write macro-writing macros. Something like this simply fails with the same error, that foo is not a “simple symbol”:

                          (defmacro make-foo []
                            `(defmacro foo [arg]
                               `(let [y 1]
                                  (+ y 1))))
                          

                          The same happens if you change make-foo to accept the name of the macro but still use quasiquotation (not exactly sure why that is, though). The only thing that seems to work is if you convert the let to a manual list building exercise:

                          (defmacro make-foo [name]
                            (let [y-name 'y]
                              (list 'defmacro name ['arg]
                                 (list 'let [,y-name 1]
                                       (list '+ y-name 'arg)))))
                          
                          (make-foo bar)
                          (bar 2) => 3
                          

                          But this breaks down as soon as you try to pass in identifiers as arguments:

                          (let [x 1] (bar x)) ;; Error: class clojure.lang.Symbol cannot be cast to class java.lang.Number
                          
                          1. 2

                            You can unintentionally write a macro that doesn’t want to expand due to hygiene errors:

                            That’s kind of the whole point; you made an error (bound a symbol without gensym) and the compiler flagged it as such. Much better than an accidental symbol capture.

                            Something like this simply fails with the same error, that foo is not a “simple symbol”

                            Yeah, because it’s anaphoric. The entire system is designed around getting you to avoid this. (Though you can fight it if you are very persistent.) The correct way to write that kind of macro is to accept the name as an argument (as you did in the second version) but your second version is much uglier than it needs to be because you dropped quasiquote unnecessarily:

                            (defmacro make-foo [name]
                              `(defmacro ~name []
                                 `(let [y# 1]
                                    (+ y# 1))))
                            
                            1. 3

                              Thanks for explaining how to make this work, I stand corrected!

                          2. 3

                            That’s an elegant solution to hygene. I might have to give this Clojure language a try, it sounds pretty great!

                            Are there other Lisps that work this way, or is Clojure unique in this regard?

                            1. 4

                              Both Clojure and Common Lisp’s Macro systems seem like a huge kludge after learning syntax-case.

                              1. 2

                                Fennel works similarly in that it prevents you from using quoted symbols as identifiers without gensym/auto-gensym. However, it does not tie directly into the namespace system (because Fennel is designed to avoid globals and its modules are very different from Clojure namespaces anyway) but works entirely lexically instead, so if you want a value from a module, your macroexpansion has to locally require the module.

                                https://fennel-lang.org/macros

                            2. 1

                              What happens in Janet if you rebind the injected variable to a different value? It seems to me that this shouldn’t work in the general case. Also, I don’t see how this could work if you inject a variable which is declared later in the file.

                              1. 1

                                Janet inline values, you can’t redefine something that isn’t specifically a var - if it is a var, it is accessed via indirection.

                        1. 3

                          Unicode. Seriously, I’d rewrite Unicode specifications from scratch.

                          1. 2

                            What would you change?

                            1. 7

                              I would go back much further and redesign the alphabet and English spelling rules.

                              1. 4

                                I for one would not admit emojis into unicode. Maybe let whatever vendors want standardize something in the private use areas. But reading about new versions of unicode and the number of emojis added has me wondering about the state of progress in this world.

                                1. 5

                                  Customers demand emojis. Software vendors have to implement Unicode support to accommodate that. Unicode support is more widespread.

                                  I take that as a win.

                                  Besides, sponsoring emoji funds Unicode development to some extent.

                                  1. 3

                                    MSN Messenger had emoji-like things 20+ years ago, but they were encoded as [[:picture name:]]. This works, because they are pictures, not characters. Making them characters causes all sorts of problems (what is the collation order of lower-case lambda, American flag and poop in your locale? In any sane system, the correct answer is ‘domain error’).

                                    Computers have been able to display small images for at least a decade before Unicode even existed, trying to pretend that they’re characters is a horrible hack. It also reinvents the problems that Chinese and other idiographic languages have. A newspaper in a phonographic language can introduce a neologism by rearranging existing letters, one in an ideographic language has to either make a multi-glyph word or wait for their printing press to be updated with the new symbols. If I want a new pictogram in a system that communicate images, I can send you a picture. If I want to encode it as unicode then I need to wait for a new unicode standard to add it, then I need to wait for your and my software to support it.

                                  2. 1

                                    On the contrary, shipping new emoji is a great way to trick people into upgrading something when they might not otherwise be motivated. If you have some vulnerability fixes that you need to roll out quickly, bundle them alongside some new emoji and suddenly the update will become much more attractive to your users. Works every time. All hail the all-powerful emoji.

                                    1. 1

                                      Sure, let software vendors push security updates with emojis. Unicode the standard doesn’t need to do that.

                              1. 1

                                Tuning your browser’s default styling (hyperlink colour, default font face and size, etc) is underrated. There are couple of sites I use that insist on being unstyled and it greatly improves my experience of them. I’m often surprised how often I stumble across another.

                                1. 1

                                  I’m curious what modifications you make. Any tips for improvements to the defaults?

                                  1. 1

                                    I change hyperlink colour to a green which is just a personal preference but feels “fresh”. I also change the default font to sans serif and bump the size up four points or more. That’s about it.

                                1. 12

                                  I’m confused by the distinction between Emacs and an IDE. In what way is Emacs not an IDE? It’s more of an integrated environment than any other IDE I have used, IntelliJ included. Hell in Emacs I can read my emails and browse the web.

                                  1. 19

                                    That’s a sad terminology confusion: when people say IDE today, they often don’t have the original “integrated” meaning. Rather, they mean “that, which understands the exact semantics of the code and provides semantic-driven code assistance”. PostIntelliJ is the canonical post which captures the essence of this new IDE meaning. As I work on IDEs (in the modern sense), I tried to invent a better term here (code understander) but it doesn’t stick even with me. So I resorted to just re-defining IDE as Intelligent Development Environment.

                                    While Emacs is indeed probably the most integrated of them all, it doesn’t fare too well on the intelligent bits. There were attempts to add semantic understanding to emacs: CEDET had some grand vision, js2-mode a real parser for JavaScript, but they are nowhere close to the level of semantic support you get in IntelliJ.

                                    Today, there’s a trend for separating the semantic engine from the editor front-end (LSP), so we might see Emacs as intelligent environment in the future. Qualitatively, I think that Emacs + lsp-mode for a language which has an OK LSP implementation passes as IDE. Quantitatively, today LSP capabilities are inferior to those of IntelliJ.

                                    1. 2

                                      Totally agree that our development tooling still has a lot of areas to improve, “intelligent bits” as you call it but also better support in terms of debugging, tracing, and insights into a programs runtime. The existing stepping debugger support in emacs & most other tools are just very basic and haven’t really changed on what existed 25, 30 years ago. A “live development” experience such as with the Smalltalk debugger is still missing in most other tooling (except for Common Lisp / Scheme to some degree).

                                      In any case, thank you & the rust-analyzer team in particular that Emacs + rust-analyzer is my favorite Rust development environment that is getting better every week!

                                    2. 2

                                      I’ve used Vim since the early 2000s. Each tool has a purpose. In Intellij IDEA for example, you can create a kotlin based spring boot project and start debugging or start writinh some test cases and run them to see the coverage. It will underline code where you need to add null checks. It will auto-install dependencies in your pom or gradle files. This is supported out of the box as expected from any IDE. It is a time saver. I install emacs and stare at a blank page. No “create project” menus, no “project options” it just stares with its gray, listless, lifeless terminal screen.

                                      1. 1

                                        Good point. “Specialized IDE” would have been more accurate but would have been more verbose

                                      1. 7

                                        I agree with the comment; this is pretty light on how the author actually uses it.

                                        1. 11

                                          Yeah, it’s a really weird choice to conclude what is ultimately no more than a tutorial on setting up syntax highlighting in nano with a comment about how you’ve proven nano is as capable an editor as vim or emacs. It is and has for years been beyond me how nano could ever be useful outside of making trivial config file changes in a system you don’t have root access on – these days it seems more ubiquitous than vim or ed. I was hoping this article would clear that up.

                                          Then again, maybe there’s nothing to clear up; maybe there really are people who have no further requirements for an editor than being able to type text and save it to a file. I don’t know.

                                          1. 3

                                            Some people can work perfectly fine with a minimal editor. For example Linus Torvalds with MicroEMACS.

                                            1. 7

                                              When I learned C, I decided to only use vi (not vim) without colors and without any custom config.

                                              It’s a little weird at first, but the brain adapts (quickly) and recognizes the patterns. Now I don’t care which editor is on a system, or how it’s formatted on the web or in an e-mail.

                                              1. 4

                                                Instead of vi, I use vis. But, in there, I do the same: I disable the syntax highlight, and I only use the default settings of the editor.

                                                I read somewhere, someday, that working with disabled syntax highlight makes the programmer more attentive to the code, and consequently make less mistakes.

                                                I actually never measured it, but I instinctively feel that I read more carefully the code base, and therefore I learned the code base I work on better than before.

                                                I also started to appreciate the [Open|Net]BSD code style, because it helps to work on this style, and to use default UNIX tools to find parts of the code I am interested at.

                                                In other words, it leverages UNIX as IDE.

                                                1. 2

                                                  I am thinking about switching from vim to vi + tmux for Go.

                                                  So far the most challenging was:

                                                  • block edit;
                                                  • go to definition;
                                                  • copy/paste;

                                                  Especially copy/paste. It turns out I heavily relied on yanking from one vim tab to another.

                                                  1. 1

                                                    Which vi? nvi?

                                                    1. 1

                                                      The version that came with the OS. Seems like nvi or at least based on nvi.

                                                2. 2

                                                  It’s ubiquitous because it’s just what I’d expect from a debian system that some non-vim professional might have to administrate via CLI. And for anything that isn’t changing configs on remote systems / rescue mode I’ve got an IDE or Kate if it’s supposed to be simpler.

                                              1. 17

                                                The critique of other editors is very weak here, was expecting something more.

                                                The argument against Emacs is that Emacs Lisp is not fun? What makes nano’s configuration more fun?

                                                1. 1

                                                  The author claims this is shortest:

                                                  b=( "${a[@]}" ) # copy array
                                                  

                                                  But this is 27 characters (including the comment).

                                                  The following is quite a bit shorter, and clearer:

                                                  copy_of_a=( "${a[@]}" )
                                                  

                                                  If you want it clearer still, define a function. Then you don’t need “# copy array” every time you want to copy an array. DRY.

                                                  1. 7

                                                    Then you don’t need “# copy array” every time you want to copy an array. DRY.

                                                    I highly recommend you read the post more carefully. It really seems like you have missed the point here.

                                                    1. 5

                                                      But this is kind of a low-hanging fruit, isn’t it? Now assume that a and b bear some semantic context, say, about the problem domain. So you are basically replacing b by a potentially confusing variable name just for the sake of removing the comments.

                                                      I agree that this might be a better option in some cases—maybe most of them—but it is not a silver bullet.

                                                    1. 14

                                                      Using fish has the benefit of being able to use a real programming language to define helper functions and having all of those neatly stored in .config/fish, so there is no random mess in my $HOME.

                                                      1. 4

                                                        I have switched to fish this year and it has been a game changer for me. My configuration is now simple and I got a lot of features that I was missing out of the box.

                                                        1. 1

                                                          Also, the features that fish has built-in are usually implemented in a better way than those added on via scripting in zsh/bash.

                                                        2. 2

                                                          \o/ yay for fish

                                                          I particularly like being able to ‘save’ variables to my config within the shell.

                                                          1. 1

                                                            Eshell also has this benefit. It’s great!

                                                          1. 3

                                                            Really interesting. Anything preventing it from being distributed/build for Windows?

                                                            1. 7

                                                              Nothing. If you can compile it, we’ll be happy to publish it :-)

                                                              1. 1

                                                                I may be misunderstanding, but are you offering to publish a binary compiled by a stranger?

                                                                Is this browser intended to be useful for things like online banking?

                                                                1. 1

                                                                  Let me rephrase; if you can provide a recipe to compile it, I will be happy to publish.

                                                            1. 2

                                                              What I really want is something like Python (or like Haskell, depending on the circumstances) where running shell commands is a “first-class” language construct, with ergonomic piping of stdout/stdin/files. Oil seems much-improved compared to Bash, but it (intentionally, for good reason) borrows many of the same bad design choices with regard to control flow and cryptic naming schemes.

                                                              The best solution I’ve found so far is to call subprocess.run from a Python script and use string interpolation to pass arguments to the commands I want to run. But this is far from ideal.

                                                              1. 8

                                                                Why not Perl? It’s the obvious choice for a language where shell commands are a “first-class” language construct.

                                                                1. 3

                                                                  Totes agreed!

                                                                  I find shell logic and data structures impenetrable and error prone, so I write all my “shell scripts” in Perl. It’s easy to pull shell output into Perl data structures using backticks, e.g. print the names of files in $TMPDIR iff they are directories

                                                                  chomp(my @out = `ls $ENV{TMPDIR}`); for (@out) { print "$_\n" if -d qq[$ENV{TMPDIR}/$_]; }
                                                                  

                                                                  For non-perl users, the backticks above mean “run this shell command”, chomp removes the newlines, qq[] means “wrap this in double quotes and handle the annoying escaping for me”, and $ENV{X} is how you access env var X, etc.

                                                                  The book Minimal Perl for UNIX and Linux People has a lot of information about how perl can be used to do everything on unices that awk, grep, sed, etc. can do

                                                                  also with Perl you get a real debugger (see also perldoc perldebtut or the book Pro Perl Debugging)

                                                                  1. 3

                                                                    I think it easily gets overlooked these days, since it is no longer hip and therefore less on the frontpage news

                                                                    1. 5

                                                                      Apropos of “no longer hip”, tcl is a nice scripting language with a clean syntax.

                                                                      1. 1

                                                                        I used to mess with tcl scripts all the time in the early 2000s when I ran eggdrop irc bots. Good old days…

                                                                        1. 4

                                                                          Sqlite started as a tcl extension and still has a good tcl interface: https://sqlite.org/tclsqlite.html

                                                                          1. -2

                                                                            TIL!

                                                                  2. 3

                                                                    Depending on your use cases, have you ever tried Fish, or more on the programming side, Raku/Perl? Raku is awesome for shell-style scripting.

                                                                    1. 2

                                                                      Hm what do you mean by control flow? I’m working on more docs so it probably isn’t entirely clear, but control flow looks like this

                                                                      if test --dir $x {
                                                                        echo "$x is a dir"
                                                                      }
                                                                      

                                                                      And you can use expressions with ()

                                                                      if (x > 0) {
                                                                        echo "$x is positive"
                                                                      }
                                                                      

                                                                      For loops are like bash with curly braces

                                                                      for x in a b c { echo $x }  # usually written on 3 lines, being compact here
                                                                      for x in *.py { echo $x }
                                                                      for x in @(seq 3) { echo $x }  # explicit splitting rather than $(seq 3)
                                                                      

                                                                      I’m also interested in feedback on naming. Oil has long flags like test --dir instead of test -d. I am trying to get rid of all the one letter obscureness (or at least ALLOW you to avoid it if desired).


                                                                      It’s accurate to describe Oil as “Python where running shell commands is first class” (and pipelines and more).

                                                                      Although I would take care to call it perhaps the “David Beazley” subset of Python :) That is a prominent Python author who has been lamenting the complexity of Python.

                                                                      He writes some great code with just numbers, strings, lists, dicts, and functions. Oil is like Python in that respect; it’s not like Python in the sense that it has a meta-object protocol (__iter__ and __enter__ and __zero__ and all that).

                                                                      I’m interested in language feedback and if that matches your perception of Oil :) Does the code look cryptic?

                                                                      1. 3

                                                                        I’ve only had a cursory look at Oil, so forgive me if I have the wrong idea :). I really admire the effort, and I can really relate to what you’ve written about your motivations for creating Oil!

                                                                        Oil is also aimed at people who know say Python or JavaScript, but purposely avoid shell

                                                                        It seems like Oil will be great for people who spend a lot of time maintaining shell scripts and want to work with something a little more sane. However, the Oil docs impression that Oil will be just as confusing as Bash for someone like me who wants to spend as little time as possible writing / reading / maintaining shell scripts and who only finds occasion to do so once every few months. For someone like me, I wish there were some syntax-level construct in Python or Haskell for running shell commands that lets me take advantage of my existing knowledge of the language, rather than having to learn something entirely new.

                                                                        I took another look at the Oil docs, and the control flow actually seems ok, even if minimal. It would be cool to see some more tools to map / flatmap / fold commands, especially when I have a bunch of parameters that are used to generate a sequence of commands.

                                                                        I think the biggest improvement a new shell-scripting language can offer is an alternative syntax for specifying command-line flags. Now that I think of it, this is actually the main reason I wrap all my CLI calls in Python scripts. For instance, here are some commands I had to run at work last week:

                                                                        docker run -itd --name container_name --rm -e CUDA_VISIBLE_DEVICES=0 -e API_KEY="..." -v /home/ben:/ben/ -v /data/v2/:/data image_name
                                                                        
                                                                        docker exec -d container_name sh -c 'mkdir -p /ben/train/train_2021-05-16_144614 && python /ben/project_name/train.py \
                                                                                        --batchSize 16 --loadSize 160 \
                                                                                        --alpha 1.0 \
                                                                                        --annotations /data/project_name/sourceA/v3/really_long_name.txt \
                                                                                        --annotations /data/project_name/sourceB/v1/really_long_name.txt \
                                                                                        --annotations /data/project_name/sourceC/v4/really_long_name.txt \
                                                                                        --data-path /data/project_name/images \
                                                                                        --output-path /ben/train/train_2021-05-16_144614/checkpoints \
                                                                                        --gpu_ids 2 \
                                                                                        2>&1 > /ben/train/train_2021-05-16_144614/log_2021-05-16_144614_outer.txt'
                                                                        

                                                                        I actually had to run the exec command four different times with different arguments. I wrote a Python script to generate the Python command, wrap it in the docker command, and pass in all the necessary parameters with string interpolation. But to me this seems like a pretty silly to glue together different programs, when we already have familiar syntax for function calls! I would love to write instead:

                                                                        var env_variables = [
                                                                          CUDA_VISIBLE_DEVICES=0,
                                                                          API_KEY="..."
                                                                        ];
                                                                        
                                                                        var volumes = [
                                                                          /home/ben/:/ben/,
                                                                          /data/commondata/v2, /data
                                                                        ];
                                                                        
                                                                        docker.run(
                                                                          flags="interactive, tty, remove",
                                                                          env=env_variables,
                                                                          name="container_name",
                                                                          image="image_name",
                                                                          volume=volumes
                                                                        );
                                                                        
                                                                        ...
                                                                        
                                                                        image_annotations=[ /data/project_name/sourceA/v3/really_long_name.txt, ... ]
                                                                        
                                                                        python_command=python(train.py,
                                                                          batchSize=16, loadSize=160, alpha=1.0,
                                                                          annotations=image_annotations,
                                                                          data-path=/data/project_name/images,
                                                                          output_path=...
                                                                          gpu_ids=2,
                                                                        )
                                                                        
                                                                        docker.exec(
                                                                          detached=True,
                                                                          container=container_name,
                                                                          command=python_command
                                                                        )
                                                                        

                                                                        This should work, automatically, for ANY command line interface, not just docker. It should work without writing any custom wrapper code. Without actually running the command, I want some kind of TypeScript-style static type-checking to know if the flag/argument I provided does not match what the CLI expects.

                                                                        1. 1

                                                                          Thanks this is useful feedback!

                                                                          Yes I understand that Oil feels like it’s for the “shell expert” now. Because I do frame many things in terms of an upgrade path from bash, and that requires knowing bash (lots of people don’t!).

                                                                          But it’s absolutely the goal for a Python/JS programmer to be able to pick up Oil with minimal shell knowledge. You have to understand argv, env, stdin/stdout/stderr, and exit code, and that’s it hopefully. Maybe file descriptors for the advanced.

                                                                          I have an upcoming “Tour of Oil” doc that should help with this. It will document Oil without the legacy stuff.

                                                                          It would be cool to see some more tools to map / flatmap / fold commands, especially when I have a bunch of parameters that are used to generate a sequence of commands.

                                                                          Yes, great feedback, there is a pattern for this but it’s probably not apparent to newcomers. In shell map / flatmap are generally done by filtering streams of lines, and I think that pattern will help.

                                                                          https://github.com/oilshell/oil/issues/943

                                                                          There is also splicing of arrays, which are natural for command line args

                                                                          var common = %( --detached=1 --interactive )
                                                                          var args1 = %( --annotations /data/1 )
                                                                          var args2 = %( --annotations /data/2 )
                                                                          
                                                                          # Run 2 variants of the command
                                                                          docker run @common @args1
                                                                          docker run @common @args2
                                                                          
                                                                          # Run 4 variants
                                                                          for i in @(seq 4) {
                                                                            docker run @common --index=$i
                                                                          }
                                                                          

                                                                          Does that make sense as applied to your problem? You can also apply to env vars with “env”:

                                                                          var env_args = %( PYTHONPATH=. FOO=bar )
                                                                          env @env_args python -c 'print('hi')
                                                                          

                                                                          There is no static checking, but Oil’s philosophy is to give errors earlier in general. It will be possible to write your own argv validators if you like.

                                                                          A useful pattern will be to define “subsets” of Docker as “procs”. As in, you can just accept the flags you use and validate them:

                                                                          proc mydocker {
                                                                             argparse @ARGV %OPT {   # not implemented yet
                                                                                -v --verbose "Verbose flag"
                                                                             }
                                                                             docker @myarray
                                                                          }
                                                                          mydocker --oops  # syntax error
                                                                          

                                                                          Thanks for the feedback, let me know if that makes sense, and if you have other questions. And feel free to follow the issue on Github!

                                                                      2. 1

                                                                        Golang exec’s module is much better for piping in the classic shell way. You might consider that.

                                                                        1. 1

                                                                          The best solution I’ve found so far is to call subprocess.run from a Python script and use string interpolation to pass arguments to the commands I want to run. But this is far from ideal.

                                                                          I do a similar thing. What sort of improvements can you envision?

                                                                        1. 6

                                                                          There are a few elements that seem redundant. The legend element represents a caption for a fieldset element, the caption element represents a caption for a table element, and the figcaption element represents a caption for a figure element. I don’t know why one element couldn’t do the job for all three, since the meaning could be derived from the parent element.

                                                                          Now I’m curious, too. Is it an ambiguity thing? A historical thing? Does HTML have any elements that derive meaning from their parent?

                                                                          1. 18

                                                                            Does HTML have any elements that derive meaning from their parent?

                                                                            <li> changes when it’s in a <ul> vs <ol>. At least to me, “list-item that has order” and “list-item that lacks order” seem like different meanings.

                                                                            1. 4

                                                                              Oh duh yeah that’s a perfect example I didn’t think of

                                                                              1. 3

                                                                                Isn’t order the property of the container?

                                                                                1. 1

                                                                                  Maybe that’s how the designers of HTML thought about it? But that property is displayed by changing how the items appear (numbers vs bullets). When I’m reading a web page or editing a Google doc, it feels like the individual items are either bullets or numbered steps.

                                                                                  1. 3

                                                                                    How things are displayed is a matter of style, and the style cascades through all children elements.

                                                                                    For example to style an ordered list so it uses roman numerals, you add list-style:upper-roman to the <ol>, not to each <li>.

                                                                              2. 3

                                                                                summary is also caption for details. all captions are equivalent to an h1 ina section around the item. img/picture/video/iframe vs object redunancy, etc

                                                                                1. 3

                                                                                  Unsure about figcaption.

                                                                                  But for legend and caption, there was one perhaps-subtle difference in HTML 4: legend, as a form element, supported the accesskey attribute, while caption did not. Different attribute lists, different elements.

                                                                                  As of HTML5 I believe they also have different permitted content, but in HTML 4 they both allowed any %inline content.

                                                                                1. 1

                                                                                  As a general programming language, I just can’t get over the JVM and all its Java trappings, which is just not my cup of tea.

                                                                                  If this is the gripe, why not use ClojureScript?

                                                                                  1. 4

                                                                                    I have only started using Clojurescript a couple of days ago but it seems to me like a much worse experience. For instance, Clojurescript (or cljs?) itself is written in Clojure, so you have the Java overhead. Then, error traces tend to include compiled JS source lines and while debugging, I’ve often run into the dreaded [object Object]. Also, having to use (and know when to use!) promises makes the experience qualitatively worse.

                                                                                    Basically, the JS runtime seeps into the language usage experience. Because you’re dealing with both Clojure itself and JS, you end up having to know about the intricacies of two ecosystems. I.e., more yak shaving than I care to do.

                                                                                  1. 37

                                                                                    My favorite aspect (mentioned in the article) is that files that use this (logs, whatever) automatically sort sensibly!

                                                                                    1. 9

                                                                                      Only until we get to year 10000. :-(

                                                                                      1. 8

                                                                                        I vote that when that happens, we change the first digit of the year to hexadecimal so we can put off figuring out a real fix until the year 16000.

                                                                                        1. 6

                                                                                          At that point we switch to ISO 08601

                                                                                          1. 2

                                                                                            The Long Now Foundation hasn’t tried to update the ISO standard (that I’m aware of), but they’ve been using 5 digit years for a while now.

                                                                                            1. 2

                                                                                              There’s already a solution for that: RFC2550

                                                                                          1. 12

                                                                                            I typically write user-visible dates as “26 Feb 2021”: this way it’s always clear for pretty much anyone who can speak English (and also many who don’t, since month names tend to be very similar across languages). You could argue that “2021-02-26” is better, but many people aren’t used to it so I don’t think it’s very user-friendly.

                                                                                            For databases and other technical (non-user visible) there is no discussion that ISO 8601(-ish) dates formatted as “2021-02-25” is the only acceptable format.

                                                                                            This is also why I often use (thin) spaces for thousands separators by the way: “64 737” instead of “64,737”.

                                                                                            1. 17

                                                                                              I’m using ISO8601 whenever i have to sign something. Never had any complaints or problems.

                                                                                              1. 1

                                                                                                Same, but I wonder if that’s because I’m in the US where everyone expects the month to come before the day anyway. I’m moving the year to the beginning but otherwise it is a normal human-readable date. Does it go over as well in countries that use DD/MM dates normally?

                                                                                                1. 1

                                                                                                  Always has for me! (Australia.) I think people here are more sensitive to different date formats, given we use the less popular of the two and everyone’s online.

                                                                                              2. 7

                                                                                                I do the same when communicating professionally. We use English mostly and I tend to refer to dates as “26 Feb 2021 12:00 CET (UTC+1)” because spending a couple of seconds writing usually saves hours of confusion when scheduling meetings etc.

                                                                                                How do you output thin spaces? It’s part of Swedish typographical standard to use for thousands separators but it’s a pain online because of bad support for thin spaces (that also have to be non-breaking).

                                                                                                1. 7

                                                                                                  I have it set up in XCompose:

                                                                                                  <Multi_key> <space> <space> : " " U202F # NARROW NO-BREAK SPACE
                                                                                                  

                                                                                                  So pressing right alt + space + space will insert U+202F.

                                                                                                  1. 2

                                                                                                    I have this:

                                                                                                    <Multi_key> <space> <t> : " "   U2009    # Thin space
                                                                                                    <Multi_key> <space> <m> : " "   U2003    # Wide (em) space
                                                                                                    

                                                                                                    Is U202F a thin space too?

                                                                                                    1. 2

                                                                                                      I think they render pretty much identical, although this depends on the font. The advantage of the non-breaking space is that it shouldn’t be used as a line-break: https://imgur.com/a/tbVnamc

                                                                                                      Neither is “more correct”, in English at least, and using just a thin space is fine too, but I think the first looks a bit nicer.

                                                                                                  2. 3

                                                                                                    It’s part of Swedish typographical standard to use for thousands separators but it’s a pain online because of bad support for thin spaces (that also have to be non-breaking).

                                                                                                    I thought the thousands separator was just a non-breaking space, not a thin non-breaking space.

                                                                                                    1. 3

                                                                                                      No, it’s a thin one. Source: Typografisk handbok.

                                                                                                      1. 2

                                                                                                        Huh – thanks for the tip. Just made my life a tiny bit harder… :-)

                                                                                                        1. 1

                                                                                                          You only have to care when typesetting professionally. The web is a lost cause.

                                                                                                          1. 1

                                                                                                            It’s kind of been a lost cause ever since the printing press was invented 🙃 I don’t think simplification is necessarily a bad thing though.

                                                                                                            1. 1

                                                                                                              OK, so I tried to implement this on my blog, with an idea of adding a filter so that I could use commas as thousands separators in Markdown, then they would be replaced by non-breaking thin spaces during rendering.

                                                                                                              But while it works in the main matter, it does not work in headings for some reason.

                                                                                                  3. 13

                                                                                                    many people aren’t used to it

                                                                                                    My approach is that they will have to deal with it.

                                                                                                    1. 3

                                                                                                      “26 Feb 2021” is often recommended or even required, to avoid confusion between dd/mm/yyyy and mm/dd/yyyy when dealing with cases across borders.

                                                                                                      1. 2

                                                                                                        For databases and other technical (non-user visible) there is no discussion that ISO 8601(-ish) dates formatted as “2021-02-25” is the only acceptable format.

                                                                                                        Depending on application, unix timestamp may also be the way to go.

                                                                                                        1. 11

                                                                                                          Unix timestamps is the worst of both worlds - not human readable and affected by leap seconds.

                                                                                                          Use TAI timestamps instead.

                                                                                                          1. 3

                                                                                                            Except usually I want leap seconds in there so my time isn’t wrong?

                                                                                                            1. 4

                                                                                                              Then you implement a lookup table with historical leapseconds, and use that to display the current UTC time.

                                                                                                              If you are ambitious, you can amend the lookup table as soon as a new leapsecond is announced.

                                                                                                              The point is that from the point of view of your code (or database), there’s only a monotonical increase of seconds. You effectively treat the difference between TAI and UTC as a sort of timezone.

                                                                                                              Of course, to be really useful, each clock in your system that emits events needs to use TAI (or some other time scale without leap seconds, like GPS time). Then it’s up to the user-facing interface to translate to civil time.

                                                                                                        2. 1

                                                                                                          “thin spaces” has really made me stop and wonder…

                                                                                                          1. 4

                                                                                                            Unicode has spaces for many tastes - http://jkorpela.fi/chars/spaces.html

                                                                                                            1. 1

                                                                                                              I like the idea of “taste” in a field so normally strict. I should look for more of that sort of thing…

                                                                                                        1. 6

                                                                                                          I’m sure this is tongue-in-cheek:

                                                                                                          If you’re smart enough, you’ve probably also noticed that the American one makes no sense and is just awful.

                                                                                                          but for clarity, the reason it’s month-day-year is because most Americans say “January 2nd, 2012” as an example, not “2 January” or “the 2nd of January” or whatever else. The date format follows how we say it rather than size of the time unit.

                                                                                                          I personally use yyyy-mm-dd because it’s more clear to me and I deal with international folks, but I don’t think the general American way is stupid or wrong either.

                                                                                                          1. 8

                                                                                                            That’s interesting. Do Americans say “$2” as “dollar two”?

                                                                                                            In the UK I pronounce “14:00” as “two PM”, “£2” as “two pounds”, and “2021-02-28” as “tomorrow”.

                                                                                                            1. 1

                                                                                                              That’s interesting. Do Americans say “$2” as “dollar two”?

                                                                                                              No, but a depressingly large number of us write it as “$2 dollars.”

                                                                                                              1. 1

                                                                                                                No but I have seen a ton of people write it as “2$” instead of “$2” because of that.