1. 12

    A realization I recently had:

    Why don’t we abstract away all display affordances from a piece of code’s position in a file? That is, the editor reads the file, parses its AST, and displays it according to the programmer’s preference (e.g., elastic tabstops, elm-like comma-leading lists, newline/no-newline before opening braces, etc). And prior to save, the editor simply runs it through an uncustomized prettier first.

    There are a million and one ways to view XML data without actually reading/writing pure XML. Why not do that with code as well?

    1. 4

      This idea is floating around the interwebz for a long time. I recall it being stated almost verbatim on Reddit, HN, probably on /.

      1. 6

        And once you take it a step further, it’s clear that it shouldn’t be in a text file in the first place. Code just isn’t text. If you store it as a tree or a graph in some sort of database, it becomes possible to interact with it in much more powerful ways (including displaying it any way you like). We’ve been hobbled by equating display representation with storage format.

        1. 7

          This talk touches on this issue, along with some related ones and HCI in general: Bret Victor: The Future of Programming

          1. 2

            God, I have been trying to recall the name of this talk for ages! Thank you so much, it is a great recommendation

          2. 5

            Text is great when (not if) your more complicated tools fail or do something you can’t tolerate and you need to use tools which don’t Respect The Intent of designers who, for whatever reason, don’t respect your intent or workflow. Sometimes, solving a problem means working around a breakage, whether or not that breakage is intentional on someone else’s part.

            Besides, we just (like, last fifteen or so years) got text to the point where it’s largely compatible. Would be a shame to throw that away in favor of some new AST-database-thing which only exists on a few platforms.

            1. 1

              I’m not sure I get your point about about intent. Isn’t the same already true of, say, compilers? There are compiler bugs that we have to work around, there are programs that seem logical to us but the compiler won’t accept, and so on. Still, everybody seems to be mostly happy to file a compiler bug or a feature request, and live with a workaround for the present. Seems like it works well enough in practice.

              I understand your concern about introducing a new format but it sounds like a case of worse-is-better. Sure, we get a lot of convenience from the ubiquity of text, but it would nevertheless be sad if we were stuck with it for the next two centuries.

              1. 1

                With compilers, there are multiple of them for any given language, if the language is important enough, and you can feed the same source into all of them, assuming that source is text.

                1. 2

                  I’ve never seen anyone casually swap out the compiler for production code. Also, for the longest time, if you wrote C++ for Windows, you pretty much had to use the Microsoft compiler. I’m sure that there are many embedded platforms with a single compiler.

                  If there’s a bug in the compiler, in most casss you work around it, then patiently wait for a fix from the vendor.

                  So that’s hardly a valid counterpoint.

                  1. 1

                    Re: swapping out compiler for production code: most if not all cross-platform C++ libraries can be compiled on at least llvm, gcc and msvc.

                    1. 1

                      Yes, I’m aware of that, but what does it have to do with anything I said?

                      EDIT: Hey, I went to Canterbury :)

                      1. 1

                        “I’ve never seen anyone casually swap out the compiler for production code” sounded like you were saying people didn’t tend to compile the same production code on multiple compilers, which of course anyone that compiles on windows and non-windows does. Sorry if I misinterpreted your comment!

                        My first comment is in response to another Kiwi. Small world. Pretty cool.

            2. 1

              This, this, a thousand times this. Text is a good user-interface for code (for now). But it’s a terrible storage and interchange format. Every tool needs its own parser, and each one is slightly different, leaving begging the amount of cpu and programmer time we waste going from text<->ast<->text.

              1. 2

                Yeah, it’s obviously wasteful and limiting. Why do you think we are still stuck with text? Is it just sheer inertia and incrementalism, or does text really offer advantages that are challenging to recreate with other formats?

                1. 7

                  The text editor I use can handle any computer language you can throw at it. It doesn’t matter if it’s BASIC, C, BCPL, C++, SQL, Prolog, Fortran 77, Pascal, x86 Assembler, Forth, Lisp, JavaScript, Java, Lua, Make, Hope, Go, Swift, Objective-C, Rexx, Ruby, XSLT, HTML, Perl, TCL, Clojure, 6502 Assembler, 68000 Assembler, COBOL, Coffee, Erlang, Haskell, Ocaml, ML, 6809 Assembler, PostScript, Scala, Brainfuck, or even Whitespace. [1]

                  Meanwhile, the last time I tried an IDE (last year I think) it crashed hard on a simple C program I attempted to load into it. It was valid C code [2]. That just reinforced my notion that we aren’t anywhere close to getting away from text.

                  [1] APL is an issue, but only because I can’t type the character set on my keyboard.

                  [2] But NOT C++, which of course, everybody uses, right?

                  1. 0

                    To your point about text editors working with any language, I think this is like arguing that the only tool required by a carpenter is a single large screwdriver: you can use it as a hammer, as a chisel, as a knife (if sharpened), as a wedge, as a nail puller, and so on. Just apply sufficient effort and ingenuity! Does that sound like an optimal solution?

                    My preference is for powerful specialised tools rather than a single thing that can be kind of sort of applied to a task.

                    Or, to approach from the opposite direction, would you say that a CAD application or Blender are bad tools because they only work with a limited number of formats? If only they also allowed you to edit JPEGs and PDFs, they would be so much better!

                    To your point about IDEs: I think that might even support my argument. Parsing of freeform text is apparently sufficiently hard that we’re still getting issues like the one you saw.

                    1. 9

                      I use other tools besides the text editor—I use version control, compilers, linkers, debuggers, and a whole litany of Unix tools (grep, sed, awk, sort, etc). The thing I want to point out is that as long as the source code is in ASCII (or UTF-8), I can edit it. I can study it. I might not be able to compile it (because I lack the INRAC compiler but I can still view the code). How does one “view” Smalltalk code when one doesn’t have Smalltalk? Or Visual Basic? Last I hear, Microsoft wasn’t giving out the format for Visual Basic programs (and good luck even finding the format for VB from the late 90s).

                      The other issue I have with IDEs (and I will come out and say I have a bias against the things because I’ve never had one that worked for me for any length of time without crashing, and I’ve tried quite a few over 30 years) is that you have one IDE for C++, and one for Java, and one for Pascal, and one for Assembly [1] and one for Lua and one for Python and man … that’s just too many damn environments to deal with [2]. Maybe there are IDEs now that can work with more than one language [3] but again, I’ve yet to find one that works.

                      I have nothing against specialized tools like AutoCAD or Blender or PhotoShop or even Deluxe Paint, as long as there is a way to extract the data when the tool (or the company) is no longer around. Photo Shop and Deluxe Paint work with defined formats that other tools can understand. I think Blender works with several formats, but I am not sure about AutoCAD (never having used it).

                      So, why hasn’t anyone stored and manipulated ASTs? I keep hearing cries that we should do it, but yet, no one has yet done it … I wonder if it’s harder than you even imagine …

                      Edited to add: Also, I’m a language maven, not a tool maven. It sounds like you are a tool maven. That colors our perspectives.

                      [1] Yes, I’ve come across several of those. Never understood the appeal …

                      [2] For work, I have to deal with C, C++, Lua, Make and Perl.

                      [3] Yeah, the last one that claimed C/C++ worked out so well for me.

                      1. 1

                        For your first concern about the long term accessibility of the code, you’ve already pointed out the solution: a defined open format.

                        Regarding IDEs: I’m not actually talking about IDEs; I’m talking about an editor that works with something other than text. Debugging, running the code, profiling etc. are different concerns and they can be handled separately (although again, the input would be something other than text). I suppose it would have some aspects of an IDE because you’d be manipulating the whole code base rather than individual files.

                        Regarding the language maven post: I enjoyed reading it a few years ago (and in practice, I’ve always ended up in the language camp as an early adopter). It was written 14 years ago, and I think the situation is different now. People have come to expect tooling, and it’s much easier to provide it in the form of editor/IDE plugins. Since language creators already have to do a huge amount of work to make programs in their languages executable in some form, I don’t think it would be an obstacle if the price of admission also included dealing with the storage format and representation.

                        To your point about lack of implementations: don’t Smalltalk and derivatives such as Pharo qualify? I don’t know if they store ASTs but at least they don’t store text. I think they demonstrate that it’s at least technically possible to get away from text, so the lack of mainstream adoption might be caused by non-technical reasons like being in a local maximum in terms of tools.

                        The problem, as always, is that there is such a huge number of tools already built around text that it’s very difficult to move to something else, even if the post-transition state of affairs would be much better.

                        1. 1

                          Text editors are language agnostic.

                          I’m trying to conceive of an “editor” that works with something other than text. Say an AST. Okay, but in Pascal, you have to declare variables at the top of each scope; you can declare variables anywhere in C++. In Lua, you can just use a variable, no declaration required. LISP, Lua and JavaScript allow anonymous functions; only the latest versions of C++ and Java allow anonymous functions, but they they’re restricted in that you can’t create closures, since C++ and Java have no concept of closures. C++ has exceptions, Java has two types of exceptions, C doesn’t; Lua kind of has exceptions but not really. An “AST editor” would have to somehow know that is and isn’t allowed per language, so if I’m editing C++ and write an anonymous function, I don’t reference variables outside the scope of said function, but that it can for Lua.

                          Okay, so we step away from AST—what other format do you see as being better than text?

                          1. 1

                            I don’t think it could be language agnostic - it would defeat the purpose as it wouldn’t be any more powerful than existing editors. However, I think it could offer largely the same UI, for similar languages at least.

                            1. 1

                              And that is my problem with it. As stated, I use C, C++ [1], Lua, Make and a bit of Perl. That’s at least what? Three different “editors” (C/C++, Lua/Perl (maybe), Make). No thank you, I’ll stick with a tool that can work with any language.

                              [1] Sparingly and where we have no choice; no one on my team actually enjoys it.

                            2. 1

                              Personally, I’m not saying you should need to give up your editor of choice. Text is a good (enough for now) UI for coding. But it’s a terrible format to build tools on. If the current state of the code lived in some sort of event-based graph database for example, your changes could trigger not only your incremental compiler, but source analysis (only on what’s new), it could also maintain a semantic changelog for version control, trigger code-generation (again, only what’s new).

                              There’s a million things that are currently “too hard” which would cease to be too hard if we had a live model of the code as various graphs (not just the ast, but call graphs, inheritance graphs, you-name-it) that we could subscribe to, or even write purely-functional consumers that are triggered only on changes.

                    2. 4

                      Inertia, arrogance, worse-is-better; Working systems being trapped behind closed doors at big companies; Hackers taking their language / editor / process on as part of their identity that needs to be defended with religious zeal; The complete destruction of dev tools as a viable business model; Methodologies-of-the-week…. The causes are numerous and varied, and the result is software dev is being hamstrung and we’re all wasting countless hours and dollars doing things computers should be doing for us.

                      1. 2

                        I think that part of the issue is that we haven’t seen good structured editor support outside of Haskell and some Lisps.

                        Having a principled foundation for structured editor + a critical mass by having it work for a language like Javascript/Ruby, would go a long way to making this concept more mainstream. After which we could say “provide a grammar for favorite language X and get structured editor support!”. This then becomes “everything is structured at all levels!”

                        1. 3

                          I think it’s possible that this only works for a subset of languages.

                          Structured editing is good in that it operates at a higher level than characters, but ultimately it’s still a text editing tool, isn’t it? For example, I think it should be trivial to pull up a list of (editable) definitions for all the functions in a project that call a given function, or to sort function and type definitions in different ways, or to substitute function calls in a function with the bodies of those functions to a given depth (as opposed to switching between different views to see what those functions do). I don’t think structured editing can help with tasks like that.

                          There are also ideas like Luna, have you seen it? I’m not convinced by the visual representation (it’s useful in some situations but I’m not sure it’s generally effective), but the interesting thing is they provide both a textual and a visual representation of the code.

                      2. 1

                        Python has a standard library module for parsing Python code into an AST and modifying the AST, but I don’t know of any Python tools that actually use it. I’m sure some of them do, though.

                      3. 1

                        Smalltalk. The word you’re looking for is Smalltalk. ;)

                        1. 2

                          Lisp, in fact. Smalltalk lives in an image, Lisp lives in the real world. ;)

                          Besides, Lisp already is the AST. Smalltalk has too much sugar, which is a pain in the AST.

                          1. 1

                            Possibly, but I’m only talking about a single aspect of it: being able to analyse and manipulate the code in more powerful ways than afforded by plain text. I think that’s equally possible for FP languages.

                        2. 1

                          Ultimately I think this is the only teneble solution. I feel I must be in the minority in having an extreme dislike of columnar-style code, and what I call “white space cliffs” where a column dictates a sudden huge increase in whitespace. But I realize how much it comes down to personal aesthetics, so I wish we could all just coexist :)

                          1. 1

                            Yeah, I’ve been messing around with similar ideas, see https://nick.zoic.org/art/waste-web-abstract-syntax-tree-editor/ although it’s only vapourware so far because things got busy …

                            1. 1

                              Many editors already do this to some extent. They just render 4-space tabs as whatever the user asks for. Everything after the indent, though, is assumed to be spaced appropriately (which seems right, anyway?)

                              1. 1

                                You can’t convert to elastic-tabstop style from that, and without heavy language-grammar knowledge you can’t do this for 4-space “tabs” generally.

                                Every editor ever supports this for traditional indent style, though: http://intellindent.info/seriously/

                                1. 1

                                  To be clear, you can absolutely render a file that doesn’t have elastic tabstops as if it did. The way a file is rendered has nothing to do with the actual text in the file.

                                  It’s like you’re suggesting that you can’t render a file containing a ton of numbers as a 3D scene in a game engine. That would be just wrong.

                                  Regardless, my point is specifically that this elastic tabstops thing is not necessary and hurts code readability more than it helps.

                                  The pefantics of clarifying between tabs and tabstops is a silly thing as well. Context gives more than enough information to know which one is being talked about.

                                  It sounds like this concept is creating more problems than it solves, and is causing your editor to solve problems that only exist in the seveloper’s imagination. It’s not “KISS” at all, quite the opposite.

                              2. 1

                                Because presentation isn’t just a function of the AST. Indentation usually is, but alignment can be visually useful for all kinds of reasons.

                              1. 2

                                Hey @dan_manges, great article. Thanks for writing.

                                One thing I’d like clarified a bit: if you keep business logic out of the ActiveRecord models, where do you enforce relations (e.g., belongs_to and its ilk) and validations?

                                1. 2

                                  We define relationships on our models. We put some simple validations in the models as well, but the more complex domain validations go in our services. Our services generally always return an object that has a .success? attribute, and if success is false, we’ll include a message with any validation errors.

                                  1. 1

                                    Not the original poster, but I think it’s fairly common to treat validations and relations as richer schema information. As opposed to model instance methods that query or update records.

                                  1. 2

                                    One marginal improvement—even though it still uses 2 round-trips—is to put the <script> tag in the <head>, make it async, and ensure the JS it serves knows to wait for DOMContentLoaded.

                                    <head>
                                      <script async src="..."></script>
                                    </head>
                                    <body>
                                      <div ...></div>
                                    </body>
                                    

                                    At the very least, this causes the browser to start downloading the script earlier without halting the rendering.

                                    1. 2

                                      But what I really should have said was: benchmark, benchmark, benchmark.

                                      Is 2 roundtrips actually bad compared to other things? What if you use a CDN for the widget? What would be the extra load on your application server to essentially concatenate the widget and the id-based response?

                                      You probably don’t know the answers to all of these without significant benchmarking, especially taking into account geography and disparate network bandwidths. Maybe you do, and that’s great! But that’s where I’d start, other than the async trick above.

                                      1. 8

                                        There’s only one rule that I know of, babies—God damn it, you’ve got to be kind.

                                        In honor of Kurt Vonnegut, I propose we add an “unkind” tag. It feels like it encompasses the types of interactions that aren’t constructive.

                                        1. 3

                                          “unkind” is a good sentiment, though I worry that “unkind” could also be applied to content that shouldn’t necessarily be downvoted. :/

                                          1. 5

                                            If someone wants to downvote something for a reason that isn’t “accepted,” then they’re not going to give up because the exact sentiment they feel isn’t in the tag list. Already, I assume the default is gonna be “troll” for those situations.

                                            If we want this to be a kind place, then maybe we ought to have an “unkind” flag.

                                            1. 4

                                              An “unkind” flag seems like a good idea, and makes more sense to me than “unkind” as a reason for downvoting.

                                          2. 1

                                            “Big meanie”

                                          1. 2

                                            It’s possible, but why would you do that?

                                            1. [Comment removed by author]

                                              1. 1

                                                So when a stray cosmic ray flips a bit in your storage device’s firmware, rendering it inoperable, at 3am, do you want to fix that yourself, or would you rather have an on-call Amazon tech calmly replace the drive while your data has already been replicated to another drive?

                                                Sometimes, it’s better to just throw money at the problem instead of time. Here’s another example: do you draft your company’s own articles of incorporation? Or did you use a service? Or did you hire a lawyer? What if you need to sue someone… are you gonna go to law school before bringing suit?

                                                1. 1

                                                  How about just calmly replacing it yourself the next day? Surely no one sets things up so a single drive failure is an emergency. Or a single entire machine, for that matter.

                                            1. 1

                                              The idea’s cute, but they didn’t actually do the divisions properly; my bracket ended up in a Duke/Gonzaga final, but the first Final Four game is an East/West matchup, meaning that’s not possible. I can obviously tweak it (if Duke would beat Gonzaga, and Kentucky would beat Oregon, I can opt for a Kentucky/Duke final instead), but it makes me a bit dubious about the rest of the algorithm.

                                              [Edit: actually, a lot in the bracket’s just flat-out wrong. This isn’t actually usable.]

                                              1. 1

                                                Ugh. Yeah. Sorry about that. I was going off some difficult-to-interpret brackets that came out during the Selection Show. I mean honestly… who shows a bracket with the two regions on the top meet each other in the Final Four rather than the Championship?!?

                                                I’ve fixed this issue, btw.

                                              1. 13

                                                I’m generally not a fan of coupling cryptographic libraries to language or stdlib release cycles. If there’s a bug in the crypto library, you wanna be able to push a change as quickly as possible, and bumping a language’s version is not typically ideal.

                                                1. 8

                                                  I have a connection at YT. I was able to repro, so I sent it along. Fingers crossed!

                                                  1. 2

                                                    Thanks!

                                                  1. 3

                                                    If we wanted to truly solve the problem of codebase-exhaustiveness, however, I posit that it is impossible to create a fully robust type checker for Ruby.

                                                    I don’t have any proof, but I don’t believe this to be true. The example given (a function with a block) could be type checked if blocks can have types specified, for instance. I think the problems of having type checked dynamic languages is hard for a number of reasons(that are more complicated than dealing with blocks) but I don’t think it is impossible.

                                                    1. 9

                                                      I don’t have any proof, but I don’t believe this to be true.

                                                      Oh, I do! http://erlang.org/doc/man/dialyzer.html

                                                      Anyway type checking aside you can definitely benefit from Maybe in a dynamic language. The requirement is actually not so much to have a static type system as it is to have pervasive pattern matching and buy-in from the standard library. Erlang is dynamic but often returns tuples of {ok, Value} or {error, Reason} from functions which could fail; the presence of the wrapper indicates you need to match against it to separate out the happy path from the failure. Obviously you can defy it, but you basically have to go out of your way to do this.

                                                      1. 2

                                                        Agreed on Maybe. I do not much care for nil/null.

                                                      2. 4

                                                        My observation is that people from dynamic programming backgrounds usually imagine things like String and Int when talking about types. Even though these are the kinds of types that appear the most often in your codebase, they’re not the things that determine the power of a type system. Whenever you want to reuse code and express patterns, you need abstractions, and that progressively demands more and more from the type system. So,

                                                        • you start with a String but then you need a function String -> Int
                                                        • then you want to work with such functions so you need (String -> Int) -> [String] -> [Int]
                                                        • then you want this to work for all types so you need forall a b. (a->b) -> [a] -> [b]
                                                        • then you want this to work for many kinds of data structures, so you need forall f a b. Functor f => (a->b) -> f a -> f b
                                                        • then you want to interleave side effects, so you need forall t f a b. (Traversible t, Applicative f) => (a -> f b) -> t a -> f (t b)

                                                        And this is really just the tip of the iceberg. So, please take a moment to think about a metaprogramming utility you use in Ruby, and try to express its type completely (not just “this takes boring stuff and returns cool stuff”), in any type system you can imagine. I think this exercise quickly demonstrates how easily types get intractable once you try to model the creative things people do in dynamic languages.

                                                        1. 2

                                                          First off, I find your “observation” and overall tone a bit condescending but it probably is true for many dynamic programmers. Myself, I’ve used typed languages enough to not have this simplistic view but I’m not well versed enough to be able to discuss it at a formal level. I plan to learn a lot more, but my list of learning projects is miles long so I don’t know when I’ll get to it.

                                                          Typing some forms of metaprogramming actually seems quite easy to me. If you are doing lisp macros for metaprogramming, a lisp macro takes a code form and returns a code form so you need a type representing a code form (which basically would be a list of literals and symbols) and then you can have a super generic type definition for macros. Since code forms are lists in lisp, each macro would be taking a specific “shape”(or shapes) of list and returning another specific “shape”(or shapes) of list so that should be able to be typed as well. That being said, depending on the implementation of the type system some things that we currently do in macros might not be possible simply due to being hard/impossible to express the type. I haven’t played with shen much yet, but I assume it must be doing something with types and macros.

                                                          For Ruby it is harder/possibly impossible to type metaprogramming since everything is basically side effect based from what I understand. For that matter, due to Ruby’s overall design of side effects everywhere ruby in specific may be not possible to build a robust type system for. There might be a way but I have no idea what it’d look like.

                                                          I don’t think that applies to “dynamic programming languages” in general though.

                                                          1. 6

                                                            I’ll say that “Typing Ruby” is probably a pretty difficult endeavor. I come at this from a lot of strongly typed programming experience, significant experience with gradually-typed systems, and the experience of having written a few type systems. On top of that all, I used to use Ruby in anger quite a lot a long while ago. That said, I haven’t tried to actually write a type system for Ruby, so what follows is speculation.

                                                            There are at least two technical challenges. Broadly, applying types to dynamic languages refines them and adds more information. The complexity curve of this new information can be quite high since it’ll be describing a system that was designed outside of the influence of the refinement.

                                                            Firstly, this will make inference a really, really tricky proposition. Inference is very delicate in type systems and can go from complete-and-easy to completely inoperable in a flash. Annotation of methods and procs is a good first step—it sidesteps the need for inference by demanding that the programmer provides intent—but a practical type system will allow you to elide these types at least some of the time.

                                                            Secondly, there will be a tradeoff between complexity of the type language and the set of features which can be given types both at all and in practice. Since rising complexity makes the type system harder to use and breaks inference even more this will probably instead be interpreted at the cost of loss of Ruby features.

                                                            Both of these technical challenges apply pretty much only if your goal is to build a New Ruby With Types and are willing to lose the entire Ruby community and existing codebase. If that’s not your goal then you additionally need to handle code which is untyped alongside code which isn’t. There are roughly two approaches here that I know of:

                                                            • Give all untyped code the any type and be forced into doing manual value-shape checks at the boundaries between typed and untyped code (a la Typescript)
                                                            • Do the above semi-automatically by extending a contract system into the untyped fragment of the language (a la Typed Scheme)

                                                            You’ll also run into the question of “Can we give types to existing code?” which again you can follow Typescript’s lead here, but note that this is extra burden on either the community or the original maintainer and it gets a little dicey.

                                                            Finally, after all that we can scratch the surface a little bit of interesting Ruby features which would be difficult to typecheck. Assuming we don’t have a dependently typed system (which is a good assumption since those are still heavy research subjects) you’ve already struck the motherlode in naming Ruby’s runtime metaprogramming features. The easiest target is “eval”. This is pretty much right out. With dependent types we could add a new function “check” which, given a runtime type representation that reflects its compile-time type could link up a successful checking process with an option to evaluate the expression into that type… but let’s leave that for now.

                                                            Idiomatic Ruby makes heavy use of method_missing. There are worse offenders used popularly, but this one is simple to analyze and crushingly difficult to type. Let’s just leave on the table its relationship to respond_to? which allows even more dynamic use of the functionality (and room for error when respond_to? and method_missing don’t align). Under the presence of method_missing the fragment

                                                            x.method arg1, arg2, arg2
                                                            

                                                            can take essentially any type whatsoever. It also provides zero information about what the types of arg1, arg2, and arg3 are. We can special case this to first infer x’s type and then read out its known methods via its class hierarchy so that at least if a known method exists we can easily do the right thing statically, but the level of runtime shenanigans available to change the type of x.method when method_missing is in use is extreme.

                                                            A sophisticated type language could constrain method_missing at least some of the time by constraining what sort of overloaded methods are allowed to exist, but this is (a) restricting its power to the point that it’s really almost completely defunct and (b) breaking most idiomatic use-cases of method_missing.

                                                            You could make it so that method_missing just accepts any types and returns an any type, but again this breaks inference since you often will want method calls to put constraints on their arguments so that type information can “flow backwards” and, additionally, it will force manual runtime type guards in places which are normally elided. The common practice is to just “know” that method_missing calls have certain behaviors without any static description amenable to the language.


                                                            So, where does this leave things? Really, there are a lot of great examples of type systems which are sufficiently rich and generic to make meaningful dents in dynamic languages today: Typed Scheme, Typescript, and Flow come immediately to mind. Additionally, Erlang’s Dialyzer should be studied although it tries to do a slightly different thing. All of them (except Dialyzer) face really enormous difficulties though in that they splinter the community. Javascript programmers are not immediately Typescript programmers, although Typescript programmers do sometimes get the opportunity to reuse some Javascript code.

                                                            These examples are probably the best leaders for any Typed Ruby exploration. They also set the limits for what people have figured out how to do with respect to gradual type systems in practice.

                                                            1. 2

                                                              I’m sorry if that sounded condescending, it wasn’t my intention.

                                                              1. 1

                                                                Yeah, I wasn’t offended and I figured it wasn’t intentional. It still bugged me slightly though :).

                                                          2. 4

                                                            I’m pretty sure you can do heinous tricks with class objects and VM to defeat even the most earnest attempt at type checking.

                                                            1. 3

                                                              Ugh. I meant to say eval instead of define_function. Does that change anything?

                                                              1. 3

                                                                I’d have to think about that one. My first instinct is that eval breaks type systems but not 100% sure.

                                                                Edit: found that haskell has an eval. http://hackage.haskell.org/package/plugins-1.5.1.3/docs/System-Eval-Haskell.html. So they were able to do limited type checking it looks like but not “robust”.

                                                                1. 5

                                                                  Notice the way that Haskell’s eval works

                                                                  • It constrains the return type with a Typeable constraint meaning that we have access to runtime type representatives
                                                                  • It can fail Maybe
                                                                  • The IO is incidental to Haskell’s pure nature—an impure language won’t suffer too much here

                                                                  Typeable and Maybe here are providing the structure for what’s known as a type safe cast. You can think of eval as working in stages:

                                                                  Here, Dynamic represents a value which can take any type whatsoever—the specific type information is not known at compile time, but it’s guaranteed that Dynamic values will be stored alongside runtime type representations which match their actual type. Stage 2 is the type-safe cast (and actually already has a definition as Data.Dynamic.fromDynamic).

                                                                  Stage 1 is just a hook into the Haskell compiler. It typechecks the code and if that check succeeds produces a runtime representation of the result type. It runs the code fragment and obtains the result and then packages that result up with its runtime type information into a Dynamic value.

                                                                  Stage 2 is a trick. Since a is left generic, it’s up to the caller of stage2 (and ultimately eval) to pick what a they want. In effect, it’s a guess by the user of eval as to what the return type of their fragment will be. We use Typeable to obtain a runtime type representation of the caller’s “guessed” type and then compare that representation with the type we inferred/checked in stage1. If they match then we coerce the result into the “guessed” type and things are OK. If they don’t match, we fail and return Nothing.

                                                                  Really, the stages probably ought to be mixed so that if the caller guesses the wrong type then perhaps the string fragment shouldn’t be run at all.

                                                                  Finally, as the docs note, there is a limit to how much this guess-and-check game can be played with real code in that the eval’d fragment more-or-less has to be monomorphic.

                                                                  Also worth noting is the unsafeEval variant there. As always in Haskell, unsafe means really, really unsafe and requires that the user is carefully checking invariants. It is equivalent to a call to unsafeCoerce and can be used to break type invariants in a completely arbitrary fashion. It also doesn’t provide much more power than normal eval.

                                                                  1. 2

                                                                    article updated. thanks for pointing it out!

                                                              1. 7

                                                                After last year’s “stuff,” I can’t say I’m particularly interested. I’ll likely spend my time and effort elsewhere.

                                                                1. 1

                                                                  Cool! I’ve been hoping for something like this. I mean, I love 1Password, but it ain’t cheap.

                                                                  The database is SQL Server.

                                                                  Welp, 1Password it is.

                                                                  1. 1

                                                                    The core DAL is written in a way that can very easily be swapped out to your database engine of choice. See https://github.com/bitwarden/core/issues/10

                                                                  1. 2

                                                                    Elm: Higher Kinded Types. I appreciate that Evan wants to keep them out of the language during the early days, so that people see them as an “extra feature” rather than a “core necessity.” I even agree with him, but I’m still wistful.

                                                                    1. 9

                                                                      It brought us such revolutionary innovations as null, a value that crashes your program.

                                                                      ?

                                                                      1. 3

                                                                        ML-style freedom from null is the optimal scenario IMO. But, to be fair, among languages that have null, some handle it more gracefully than others. For instance, Common Lisp’s NIL (similarly Python’s None, Ruby’s nil, etc.) is nicer than Java’s null, since NIL is an actual object, it has a class, etc.

                                                                      1. 32

                                                                        This title sounds like GitHub is preventing it when it’s just Docker lawyers sending boringly common requests to avoid names that are confusingly similar to their trademark and unauthorized use of their name/logos.

                                                                        1. 30

                                                                          I was asked in the chat room to elaborate on why I think this is a non-story, so here’s a quick reformatting:

                                                                          Docker Inc owns a trademark for software named “docker” and doesn’t want random coders to name random projects “docker” (the next-to-last example in the story) because that’s confusing to anyone who runs into it when looking for the real docker. So a lawyer sends a “hey, please stop using our trademark for your project” note, which probably uses the legal terms “cease and desist” which mean “we’re formally asking you to stop it”.

                                                                          There’s also projects related to docker using their name/logo (for example docker-charm) and the lawyer is asking “Hey, please do X/Y/Z to make it explicit to the public that you’re not officially affiliated with us”. That can mean removing logos, adding disclaimers, and sometimes renaming entirely depending on what the project is doing and how paranoid the lawyer is. I specifically noticed in the docker-charm issue that the lawyer only asked that they remove the logo, not that they rename the entire projects. That’s pretty chill of Docker to recognize that someone seeing “docker-charm” will understand that this project integrates docker and charm, rather than sending “omg you can’t even say our name in your name” which a lot of laywers do.

                                                                          So I really think this is nothing. Docker is being polite, restrained, and using issues to fit into projects' standard workflows. GitHub surfers won’t run into projects and be unsure if they’re seeing an official docker project or not. This looks like a model story of trademark protection to me.

                                                                          1. 13

                                                                            It’s also worth noting that the letter says “as the first part of a repo name” (emphasis mine). So, a repo named “docker-existdb” is unacceptable to the Docker, Inc folks, but “existdb-docker” or “existdb-on-docker” might be fine.

                                                                            As far as I’m concerned, this is kinda eye-roll-y but perfectly within my Realm of Acceptable Behavior by an Institution.

                                                                          2. 0

                                                                            Sure, but Github will enforce the request

                                                                            1. 16

                                                                              It’s never gotten that far.

                                                                              1. 10

                                                                                citation needed

                                                                                  1. 11

                                                                                    DMCA is for copyright, not trademarks.

                                                                                    This is a non-story. This is normal, polite trademark enforcement.

                                                                                    1. 5

                                                                                      As far as I understand this would only apply if I reuse Docker’s logo or other artwork for my own project.

                                                                              1. 3

                                                                                I play lots of ultimate frisbee; I just got back from my first master’s tournament where I learned that I have much to improve upon in my game.

                                                                                1. 1

                                                                                  Veteran ultimate player here. I played hard from 1997 to 2009. Moved away from the team I was most recently playing with, then I threw out my back and got out of shape. If there is one thing I’d love to do again, its get back on the field.

                                                                                1. 1

                                                                                  After trying a bunch of CRMs, I ended up on PipelineDeals. It’s $24/month per user (twice that if you use their “Accelerator” thingy, which I don’t). It’s pretty straightforward and has both private and public (e.g., web form directly POSTing to them) APIs. Their customer support/onboarding is really good.

                                                                                  Prior to pipeline deals, I had tried a few things: Highrise, SugarCRM (self-install), and SugarCRM (hosted).

                                                                                  1. 5

                                                                                    Between team members we sometimes share secrets via keybase.io encrypted messages.

                                                                                    Most of our secrets we keep in text files on various remote servers (which sucks, don’t do this), but we are working towards a Vault system.

                                                                                    One of our ultra secure projects keeps its secrets in a custom-built thing based on Parliament which itself is based on Shamir’s Secret Sharing algorithm. I -really- would like to open source that at some point, but in fairness it is a hassle and beyond what I think is reasonable for most use cases. Think of it like having to turn multiple keys (in the physical sense) at the same time to unlock something.

                                                                                    Also we do other things… which is a secret (who doesn’t use security through obscurity as some layer somewhere? haha)

                                                                                    1. 2

                                                                                      I’ve also found keybase.io to be pretty useful, especially with technical 3rd parties.

                                                                                    1. 4

                                                                                      First, some context: We’re a consulting company, so we don’t have one app/suite to run…. we have many that are run at different clients, each of whom have very different preferences. And they actually shouldn’t share secrets with each other, in general.

                                                                                      So, with that said, we use 1Password for Teams. It’s strictly a non-automated secret sharing mechanism. That is, servers wouldn’t be able to use it, only users. It’s also not cheap, but I really like it.

                                                                                      That’s my experience. I have researched the “servers sharing secrets” problem a bit, and I’ve decided that we’d go with Vault if we ever need it… but we’re not there right now. Also, I have no experience to share with it, so take such a recommendation with a gigantic grain of salt.

                                                                                      1. 5

                                                                                        this might be nice, even if just as a reminder that the article is talking about the contemporary, haskel-ey, web framework and not the email client. (laugh if you must, but the latter is still my default lookup for ‘elm’)

                                                                                        1. 2

                                                                                          Heh, I recently gave a talk at Moonconf on Elm, and my very first slide was subtitled “no, not the mail client”

                                                                                          1. 1

                                                                                            Hehe, I thought I was the only one whose first thought is always the email client.