1. 21

Hmmmm. Not entirely sure I agree, but it’s an interesting pitch nonetheless.

  1.  

  2. 2

    I’m going to be nitpicky:

    Clojure is a dynamic language. No matter where you stand on the static vs. dynamic typing debate, knowing languages in both camps is important. Clojure has a kind of optional typing, but in essence it’s dynamic.

    There is no such thing as a dynamic language. I’ll repeat: there is no such thing as a dynamic language. There are many axes along which a language can be dynamic, including:

    • Scope
    • Name binding
    • Types
    • Continuations

    Dynamicity is a property of these concepts. You can have a language with dynamic scope and types. That doesn’t make it a “dynamic language.” The first has a technical meaning, the other is marketing speak.


    The same should be said of “strong typing” which is an utter nonsense phrase.

    1. 8

      can you think of a single common use of “dynamic language” that does not refer to dynamic types? it’s a perfectly fine shorthand for “dynamically typed language”; the other properties you mention may be there in addition but they are not the motivation for the term

      1. 1

        Yes, for example I’ve heard the term used to refer both to Perl and Common Lisp’s use of dynamic scope.

        Even if it’s correct by usage (which I do not think it is), it’s imprecise. In fact, even the thing it stands for is imprecise. “Dynamic types” aren’t types. They follow completely different rules and work completely differently.

        There’s a lot of imprecision in the terms used by laypeople to discuss programming languages, and there’s no reason for it when perfectly good and precise terms exist.

        1. 2

          And dynamic scope isn’t scope either. So-called “dynamic scope” is just syntactic sugar for inserting and removing everything into and from a single table that exists in the global scope.

          1. 2

            Well, all scope is just syntactic sugar. A single global table that maintains a stack of past bindings and unwinds them automatically as you leave a binding scope seems pretty scope-like to me, in the sense of being a programming abstraction.

            1. 1

              No, scope is not syntactic sugar. You can’t reproduce multiple (lexical, there is no other kind) scopes in a uniscoped language. Just like you can’t reproduce multiple (static, there is no other kind) types in a unityped language.

              1. 1

                (I’m going to ignore the Church of Bob Harper newspeak and bite anyway.)

                Do you have some specific sense in which you mean “reproduce”, beyond simply being able to program in a style where you have lexical variable name resolution, and can’t refer to variable names not in the lexical scope they’re in? Unless I’m missing what you mean, you can implement that notion of scope in a Lisp that doesn’t have it by using macros to statically resolve names. Several possible strategies for that, just like there are a number of strategies for implementing lexical scoping in a compiler. For example, you can name-mangle every scoped variable to a distinct global variable name, and then have a pile of macros statically resolve the bindings. Some older Algol-style languages’ compilers did almost exactly something like that, although not implemented as macros within the language.

                Granted, this isn’t “safe” in the sense that someone with some effort can get around the scoping, but that’s also true of other languages that are conventionally said to have scopes, like C.

                1. 1

                  beyond simply being able to program in a style where you have lexical variable name resolution, and can’t refer to variable names not in the lexical scope they’re in?

                  Well, that’s the whole point: to deem non-closed expressions meaningless outside of a context where their free variables are resolved.

                  For example, you can name-mangle every scoped variable to a distinct global variable name, and then have a pile of macros statically resolve the bindings.

                  Have fun implementing recursive procedures that way.

                  1. 1

                    Have fun implementing recursive procedures that way.

                    There is no problem with recursion if said global mangled variable is bound to stack of values :)

                    1. 1

                      So then you need a hardcoded stack abstraction, which is somehow immune to being wrongly manipulated by users. For instance, if the operation “push into a stack” uses a local variable, then the user can’t mess with that variable.

                      1. 1

                        Lisp provides you with facilities for generation of names that do not collide with user code. This is what hygiene is in context of macros.

                        But you are technically correct - every abstraction can be broken by sufficiently motivated user :)

                      2. 1

                        And if you don’t want to bother, there’s always the copout C uses: restrict recursive procedures to the top level. I think C is still normally considered to have scoped variables despite this limitation, though maybe some disagree, and it makes the implementation of scoping particularly simple.

                        1. 1

                          C doesn’t allow nested procedures so in that sense, yes, C restricts recursive procedures to the top level. And yes, C does have scoped variables. In this example:

                          int x; /* global x */
                          void foo()
                          {
                            int x; /* local x */
                            /* ... */
                          }
                          

                          Each x variable will have a different address. Further more, the address of x inside of foo() can change from call to call. They are distinct variables—C does not “save” the previous version of the global variable x when foo() is called. It can’t—because foo() could call a function bar() that does reference the global x and things would get mighty confused otherwise.

                          1. 1

                            Yes, I agree with that. My point was that if you accept that C’s scoping arrangement really counts as (lexical) scoping (I’m unclear whether @pyon would), then it becomes easier to say that you can implement (lexical) scoping in a language lacking it, which was the bone of contention above— because the C approach to scoping is pretty straightforward to implement in terms of name-mangling the scoped variables into global variables and using some macros to statically resolve the nested bindings.