I'm trying to get a better handle on what it really means for a language to be "dynamic". I have quite a bit of experience with Lingo, which is the scripting language for the Adobe (formerly Macromedia) Director product line, and I'm just wondering if it would be considered a "dynamic language".
The way variables and lists are handled seems very "dynamic language"-ish to me.
With variables, you would just write foo = 3
or bar = "Hello World"
. You don't declare a variable as an int
or string
--it figures that out as is goes.
With lists, you can just write something like miscCollection = [3, "Hello World", #helloWorld, ["Embedded List", "Goes Here", 3], [#phrase: "Property List goes here", #value: 3]]
. Would this not be similar to a tuple
?
Are these features enough to qualify for "dynamic language" status?
Interestingly, I've been using C# a lot more and Director/Lingo a lot less, but with all the excitement over dynamic languages these days, I wonder if I'm actually going against the grain.
EDIT
Regarding Mark Rushakoff answer, below, here's an attempt to analyze whether Lingo qualifies as "dynamic" using this Wikipedia article:
Eval
- Lingo hasdo
andvalue
keywords.do
will execute an entire command, e.g.,do "foo = 23"
ordo "foo = sum(20, 3)"
.value
attempts to convert a string into a numeric, but it is more than just a parsing operator--it can actually convert a string representation of a variable into its number, e.g., assumingfoo = 23
, the statementvalue("foo")
will evaluate to 23.Higher-Order Functions - If I'm understanding this right, this is basically what I would be called a "delegate" in C#. Lingo doesn't support this directly as far as I know, although you could create a type (called a "parent script") that has a function and pass an instance of the type.
Closures - No support for this as far as I know.
Continuation - No support for this as far as I know.
Reflection - In a sense at least, yes. You actually create new instances of types using a string, e.g.,
fooInstance = script("Foo").new(bar)
. It is also possible to convert an instance of a type into a string that contains the name of the type (so you can sort of mimic c#'sGetType()
functionality). You can also query the properties of a type without knowing the names of the properties (e.g., look up a property by index) and find out the names of the properties by index.Macros - The way the Wikipedia article describes a macro, I don't believe so. It is possible to edit scripts at runtime, however, so maybe that counts.
So, it seems that Lingo scores a 2 to 3 out of 6 on dynamic features, but I'm not clear enough on closures and continuations to know for sure that Lingo doesn't support them. I guess I'm not sure what to conclude. Comments welcome.
"dynamic" is one of those words that's fashionable, but really means little more than "What I do is cool"... it doesn't have a precise definition.
Having said that, I can answer your question about types, or at least try and explain the difference between typed and untyped (what some people call dynamic, or dynamically typed) languages better.
A typed language checks that you will never end up trying to do something with a variable that you cannot do before you run the program. An untyped language does not do this check - it simply hopes for the best and, if it any point it has a value that is unsuitable for what it needs, gives an error.
Those are two extremes. Like everything in life, in practice languages lie somewhere between the two theoretical extremes. So it's sometimes hard to say that a language is typed or untyped - often all you can say is something like "language X has better type checking at compile time than language Y because these errors are caught in X but not in Y:...."
Given that definition you might worry that (1) a typed language requires a lot more text in the program (because you need to say what type each value is) and (2) that a typed language might restrict what you can do unnecessarily (because the type system isn't smart enough to allow something that you can see would work).
Both of those can be problems. BUT they are both problems that are getting less important as typed languages get better. For example, why have code like:
when it's obvious with just
that "s" must be a String? Languages that are "smart" like this, and where you don't need to say what all the types are, but they are still checked, are often called "Hindley Milner" because those are the people that first worked out how to do that in detail.
So when you look at a program written for a language with a Hindley Milner type system it may look like it doesn't have types. But that's a mistake. It will still, before the program is run, work out what all the types of all the variables must be, and check that you cannot get any errors for trying to do something with the wrong type (I think this is amazing - it's close to a kind of artificial intelligence...)
That means that sometimes the only way to know whether a language is typed or not it to know how it is implemented. It may not be obvious from just looking at the source.
Edit: I just re-read the above, and I could have been a little clearer. The distinction I was trying to make was between languages that have a type system and languages that don't. A type system includes two things: types themselves and logic to check that the types are correct.
The languages I was calling "untyped" (or dynamically typed) do have types. In Python, for example (which is an untyped, dynamic language), there is still a difference between a String and an Integer. But they don't have the extra logic that checks the program before it runs. So it would be more accurate to say that they have types, but don't have a type system.
In contrast "typed" languages, as I said, do check before the program runs, and so must have not just types, but the extra logic to do that work.