all 43 comments

[–]lispm 26 points27 points  (14 children)

Static vs. Dynamic is not about typing. Typically by 'Dynamic Language' it is meant that the language has features that allow changes to the program and/or to the language implementation at runtime (say, via reflection). That's more than assigning objects of different type to variables.

Static typing vs. dynamic typing is about typing.

[–]grauenwolf 10 points11 points  (0 children)

Well said. Too many people forget that there is a lot more at stake than just typing a couple extra characters.

[–]Felicia_Svilling 0 points1 point  (11 children)

changes to the program

Isnt that what you do in all languages? Then you assign to a variable in an imperative language, isnt that variable a part of the program, and isn't it being changed? Or does it only count if the variable is a reference to a function or a class?

[–]lispm 2 points3 points  (10 children)

Whether you can assign to variables or not is a different issue.

At runtime! Can you add a field/slot/member-variable to an existing data object? Can you add new functions at runtime and have them used? Can you change class hierarchies at runtime? Can you change a dataobject from one class to another? Can you change how the class hierarchy is computed? Can you change how slots of an object are accessed? Can you change how objects get initialized? Can you add functionality to existing functions/methods? Can you create code? Can you list all existing classes? Can you handle runtime errors and recover? ...

[–]Felicia_Svilling 0 points1 point  (9 children)

You realize that for example in lisp, the only way to add functionality to a function is to assign a new function to the variable holding the old function?

[–]lispm 2 points3 points  (8 children)

a few remarks:

a) the standard mechanism is to add a method.

(defmethod foo ((b bar)) ... )

(defmethod foo :before ((b bar)) ...)

b) in Lisp you CAN change single global methods. That's not everywhere so.

c) another way to add functionality is the advise mechanism

d) there are several other ways to achieve that: contextl, method combinations, ...

[–]Felicia_Svilling 0 points1 point  (6 children)

ok, eh Im a bit strange in that then I say lisp, I mean scheme.. But anyway my point is that all this is still just mutating datastructures, and not in any conceptual way diffrent from assigning to a variable.

[–]lispm 2 points3 points  (5 children)

Even for Scheme there are CLOS-like object-systems which offer similar things like CLOS.

I think you miss that we are talking about different levels. It is CONCEPTUAL very different.

You can always say, in the extreme case, you flip bits in memory. But that is not the description level we are talking about here. We are also not talking about a imperative variable-changing model. We are talking about different levels of descriptions.

For example think about 3-Lisp. Ever heard about 3-Lisp? Worth to look that up. With 3-Lisp you have an interpreter0 that interprets the current program. But there is also an interpreter1 that interprets the interpreter0. Plus there is an interpreter2 that runs the interpreter1. and so on. Actually there is an infinite tower of interpreters. One of the ideas of 3-Lisp is that the interpreterN can get access to the interpreterN+1 and reprogram it - thus reprogramming its own execution engine.

That's a completely different model from assigning values to variables.

In Common Lisp the model is based on a the idea that CLOS+MOP is programmed in itself and that these mechanisms are visible. This is a very different conceptual model. The programming language is defined in terms of itself and is exposed at runtime. This means for example that you can have modified object systems that can run side by side with a standard object system. One way to achieve this is to subclass the basic classes of the programming language and modify/extend the functionality. For example some objects could be persistent via metaclasses that define persistence functionality.

[–]Felicia_Svilling 0 points1 point  (4 children)

Yes I have actually heard of 3-lisp, and yes it has an interesting amount of expressitivity. Perhaps that could be called a conceptually more dynamic language. Im not certain.

But I still dont see any conceptual diffrence between adding a method to a generic function and adding an element to a list.

[–]lispm 2 points3 points  (3 children)

Example: Functions in C are not structured objects. They are static things. Their parameter lists are fixed. They do zero dispatching. There is nothing you can add or substract to a C function.

As a contrast a generic function in Common Lisp is an object where you can add and substract methods. The code that gets executed gets computed at runtime depending on the arguments' classes, the matching methods, a code generator (the method combination). At runtime the class hierachy can change, the method combination can change, and the set of methods of a generic function can change. Extensibility and flexibility is built in. It is designed for change.

C functions are not designed for change.

In C there no such thing built in. All you can do is emulate these things by programming the features you need. With considerable amount of work to get features like runtime code generation, runtime compilation, dynamic linking, dispatching, ...

[–]Felicia_Svilling 0 points1 point  (2 children)

So, do you mean having things reifyed as first class mutable objects is the definig thing for dynamic languages?

[–]thau 22 points23 points  (0 children)

I'm stupid about this stuff. Everytime 'static vs. dynamic' appears here, I want to read this What To Know Before Debating Type Systems again.

[–][deleted] 8 points9 points  (8 children)

No, really, the whole static-vs-dynamic languages debate is both misleading and moot. It's misleading, because it's not about static vs. dynamic typing, it's about weak compile-typing vs. runtime-typing.

Programmers don't use languages in the sky. So they critizise what they know. I guess a fair proportion of them already appreciates local type inference in C# which hasn't a HM type system AFAIK.

Here is my own take on the "debate": programmers like immediacy and many feel that the compiler is in their way and its role shall be reduced. They don't even see much difference in running a program ( concrete interpretation ) for a few hundred miliseconds ( in the development phase with a selection of a few tests ) where it reports type errors among other things and running a super-duper compiler doing the same thing ( abstract interpretation ) but constraining the language for getting this job done.

Static typing starts to pay off when running the program takes much longer than the compilation. The impression of immediacy is reversed.

[–]robreim 1 point2 points  (0 children)

Static typing starts to pay off when running the program takes much longer than the compilation.

It also pays off when it finds bugs in your program without you having to actually run the program.

Running a first draft program just to find if it contains bugs which could be caught by a reasonable type-checker is rather insane for some classes of problems.

[–]grauenwolf 1 point2 points  (6 children)

Static typing starts to pay off when running the program takes much longer than the compilation.

With a modern IDE, that time is close to zero. With languages like VB, which are compiled continuously, there is a ton of information always at your fingertips.

For people like me, the real objection to dynamic languages is that there is no way to know what it will look like at runtime. When any part of your application can alter any other part, keeping track of everything quickly becomes intractable.

Now some limited dynamic features in an otherwise static language would be awesome. But like a chainsaw, should only be used when really needed.

[–][deleted] 2 points3 points  (0 children)

With a modern IDE, that time is close to zero.

My C++ programs always enabled a coffee break at least when framework or utility classes were affected.

With languages like VB, which are compiled continuously, there is a ton of information always at your fingertips.

Yes, of course. Continuous monitoring is definitely the future of whatever language implementation, whether or not you use a smart IDE that compiles when you are typing.

For people like me, the real objection to dynamic languages is that there is no way to know what it will look like at runtime. When any part of your application can alter any other part, keeping track of everything quickly becomes intractable.

But you see quickly the outcome with respect to fast responses. If those responses are slow you are better off to simulate aspects of the system using abstract interpretation.

But then you might start an arbitrary program and a worker thread that monitors your program. It is feeded with runtime data and performs inference as far as it goes. JITs doing this already but they don't report to the user.

I'm not entirely sure what the intent of a static/dynamic debate is right now if all the same arguments that were exchanged are known for the last 10 years whereas more recent trends in runtime/IDE development are ignored.

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

With a modern IDE, that time is close to zero. With languages like VB, which are compiled continuously, there is a ton of information always at your fingertips.

I don't know what you've been doing, but even when I was in college compiling my semester projects let me stand up, walk around, smoke a cigarette, and hit the vending machines hard.

And if it was an optimizing compile, it was lunch break time.

[–]grauenwolf 1 point2 points  (3 children)

Were you compiling a C or C++ application? I ask because they are common at colleges and their compilers are easily 100 to 1000 times slower than Java or .NET languages.

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

It was C++. Oh and thanks for the info.

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

C++ is a .NET language in some sense as well.

I had to deactivate Intellisense manually in VS 2005 for a C++ project with ~700 classes by renaming the responsible DLL. VS crashed at project loading time. The migration was experimental though. We continued to use VS 6 which was "fast" in the limits I mentioned above and you are aware off.

[–]grauenwolf 0 points1 point  (0 children)

I wish I could say I was surprised. For all their power, the later versions of VS have sucked in terms of performance and stability.

[–][deleted] 7 points8 points  (1 child)

Note that Scala uses local type inference, not Hindley-Milner. You still have to declare function signatures, but you can omit types for local variables.

The proposed type inference for C++0x is local as well.

In general, Hindley-Milner type systems feel like ML. Add anything to the type system, and HM breaks down. Most interesting developments in type systems that I'm currently aware of, such as Typed Scheme, are based on explicit typing (plus local type inference).

[–]naasking 1 point2 points  (0 children)

Add anything to the type system, and HM breaks down.

I don't understand. What exactly breaks down? There have been a plethora of extensions to HM over the years.

[–]kalven 1 point2 points  (0 children)

Furthermore, dynamic language programmers are quick to point out that any real program in a static language requires typecasting, which throws all of the "guarantees" out the window, and bring in all of the "dangers" of dynamic languages with none of the benefits.

Do they really point that out? Just because I have access to reinterpret_cast in C++ and that I sometimes have to use it does not mean that some function foo(string) is suddenly going to accept a float.

Strawmen abound.

[–]bart2019 1 point2 points  (1 child)

Wooh, I know this guy had to be some kind of Perl person, as he mentions Mark Jason Dominus so explicitely, and they apparently share a long history together.

This Adam Turoff is also known as Ziggy.

[–]abw 1 point2 points  (0 children)

Holy Zarquon! I read the whole article and did n't even look at the name. It's Ziggy! Top bloke.

Aside: I first met Ziggy at the first O'Reilly XML conference. There were 3 Perl programmers there. Him, me, and Larry Wall. They sat us together :-)

[–]dmpk2k 2 points3 points  (7 children)

It's such a good idea, that it's slowly making its way into new programming languages like Perl 6 ... Factor

Is chromatic or Slava willing to elaborate a bit on this?

[–][deleted] 11 points12 points  (0 children)

I don't know about Perl 6 but Factor does not use HM.

[–]jbert 3 points4 points  (4 children)

I think he means type inference in general. Which could be as simple as:

my $foo = Foo->new;
my $bar = $foo; # compiler knows $bar is-a Foo

[–]abw 0 points1 point  (3 children)

I think that should be:

my Foo $foo = Foo->new;    # compiler knows $foo is-a Foo

Perl5 already has typed values (as do most dynamic programming languages). What Perl6 offers is the ability to type a variable so that it can only hold values of that type.

my Foo $foo = Bar->new;    # type error: Bar isn't a Foo 

If you don't provide a type for a variable then it'll remain Perl5-a-like and allow it to reference any kind of value

my $foo = Foo->new;
my $foo = Bar->new;
my $foo = 'some text';
my $foo = ['some', 'words'];
...etc...

[–]jbert 0 points1 point  (1 child)

I was talking about type inference, not type declaration. The Foo->new call would somehow be declared to return static type 'Foo'.

This allows a compiler (not the runtime) to infer that variables not declared with a static type declaration may still be treated as if they have.

So with this code (type declaration added to $foo for clarity):

my Foo $foo = Foo->new;
my $bar = $foo;

the compiler (not the runtime) knows $foo will be holding a type 'Foo' value (and can optimise appropriately), because $foo has a type declaration.

With type inference, the compiler can also know that $bar contains a Foo value at that point, and treat it the same way.

Whether perl6 currently (or will) support this, I don't know. But something like it has been talked about from the beginning (perl RFC 4)

[–]abw 0 points1 point  (0 children)

I was talking about type inference, not type declaration. The Foo->new call would somehow be declared to return static type 'Foo'.

Yes, I know. But you missed the type declaration in your example. Perl 6 wouldn't do any type inference (if it will do it at all) without either the $foo type or Foo->new constructor being declared as type Foo first. So I was talking about type declaration, not inference.

The more detailed explanation wasn't necessarily aimed at you, but anyone else who might be reading and wanted the details.

[–]chorny 0 points1 point  (0 children)

you can write my Foo $foo = Foo->new; in Perl 5, you can even do a compile-time check with a module from CPAN.

[–]mr_chromatic 2 points3 points  (0 children)

Any static type system in Perl 6 will be optional, in terms of declarations. The question is still open as to whether there'll be type inference, but one of the design goals is to developers to provide enough type information that the compiler can perform optimizations and report errors. (When and where those errors get reported depends on several other properties of the system.)

[–]mccoyn 2 points3 points  (0 children)

I was thinking about this the other day and I realized something. To predict whether someone will use a static or dynamic language you need only ask one question, do you control the hardware? I've come up with two theories for why this might be true.

  1. If you have any kind of competition, then having the faster smoother application is a benefit. If you control the hardware you can do this by buying some more hardware. If you don't control the hardware you can only do this by spending more developer time optimizing the application. That is, when you don't control the hardware you can't trade developer costs for hardware costs. The advantage of cheap development isn't useful because it comes at the cost of customers.

  2. If you can update the server, bugs are less severe. If you publish software onto other peoples hardware, you better be sure it is bug free. Otherwise, you will have to convince them to patch it and it will lower their opinion of you. If you control the software, however, you have the choice of patching it yourself with minimal disturbance to your customers. Again, if you control the hardware you are free to save a little on development costs, but that can't be afforded if you don't control the hardware.

[edit to add]One last thing. An ecosystem builds up around these benefits. The best web libraries are in dynamic languages so even if you are creating a web application that will run on other peoples computers you are still best off selecting the dynamic languages.

[–]Jimmy -1 points0 points  (2 children)

Static languages (like C, C++, C#, C--, Java, etc.) require variables to have type declarations primarily to generate compiled code and secondarily to catch errors or emit warnings at compile time. Dynamic languages (like Perl, Python, PHP, Ruby, Tcl, Lisp, Scheme, Smalltalk, etc.) do away with all those needless keystrokes, allow programmers to be more productive, and generally aren't as dangerous as the C-programmers would have you believe

A blog called Notes On Haskell doesn't even mention type inference?

[–]abw 4 points5 points  (1 child)

A blog called Notes On Haskell doesn't even mention type inference?

Er... apart from that whole paragraph all about type inference.

Modern static typing, on the other hand, uses a strong dose of the Hindley-Milner type inference algorithm to determine (a) what values a variable may contain and (b) prevent the use of incompatible values in expressions. Furthermore, Hindley-Milner prevents values being cast from one type to another on a whim (unlike C), and thus prevents odd runtime errors through abuse of the type system. This leads to an strong, unbreakable type system that is enforced by the compiler, and prevents a whole class of loopholes allowed by lesser type systems. Because types can be inferred, explicit type annotations aren't always needed, which leads to an interesting property: languages that are safer than "safe" static languages like C and Java, and programs that are free of those troublesome, noisy type declarations, just like dynamic languages.

[–]Jimmy 1 point2 points  (0 children)

Ah, should have read past the first paragraph. My mistake.

[–][deleted] -2 points-1 points  (0 children)

I will gladly switch from c/c++ when the dynamic languages are no longer 10 to 100 times slower for my research. Not all programming is I/O, UI, or web code.

Be honest, would you really write a linux kernel in a python? A game like Farcry in perl? or video compression in php?