Dynamic programming and tools have their place. Things like medical applications and accounting probably are not among them, but that does not mean there is no place for dynamic techniques. Features of dynamic techniques include:
- Weak-typed or type-free languages.
- ImplicitTyping and DynamicTyping and SoftTyping work just as well. The only thing WeaklyTyped languages allow you to do that these do not is to break your program. And 'type-free' languages force you to treat everything as just one type (since there is no such thing as truly 'type free') which makes it difficult to describe operations over complex data (or even simple data... ever try writing a simple math library for untyped lambda calculus? or a language where 'EverythingIsa string'?)
- "Scriptish" in nature.
- There are two aspects of being 'scriptish': one is the ReadEvalPrintLoop. This has been possessed by a great many strict, strongly typed, even statically typed languages (including Haskell and Ocaml). The other is runtime extension of application and data. This is more difficult to do with statically typed languages, but can (and has) be done via use of FirstClassTypes and well-defined 'objects' with strictly typed interfaces; one extends applications, thus, in a well-structured manner that remains consistent with existing objects. If one is limited only to 'StrongTyping', this is trivial; only 'StaticTyping' provides a stumbling block.
- Interpreted instead of compiled
- This isn't a feature of dynamism in programming. Getting rid of the distinct CompileTime 'stage' is useful (and techniques on how to do so are described on that page) but there is never an advantage to being interpreted instead of compiled. Think of it this way: any interpreter can contain a compiler, and (unless told) you'd never know it. Many scripting languages, like Perl, are compiled; they simply don't force the programmer to perform a distinct compilation or 'build'.
- Interpretable. That better?
- Not really. Even C language is interpretable. 'Scriptish' is better, if you wish to ensure access to the ReadEvalPrint loop and execute-and-extend-as-it-goes capability. You simply don't need 'interpretable'. There is no reason for it. Maybe: no distinct CompileTime or build time would be a good specification. Keep in mind that 'interpreter' is a mechanism for language implementation, which really is outside the purview of language definition or language properties. When describing a what makes a language 'dynamic', one should try to do so in terms of properties the language should possess rather than in terms of how that language is to be implemented.
- Use of "Meta" techniques such as a DataDictionary
- To address a little confusion, do you intend 'MetaProgramming' (macros, templates, MetaObjectProtocol, etc.) or keeping 'MetaData' in the runtime (e.g. keeping explicit type information around). Both are useful. Both can be done with statically typed languages. Keeping certain MetaData is necessary for runtime debugging and useful for runtime extension of application. However, nothing about strict or static typing precludes maintenance of such MetaData. (In a sense, DSOs and binaries that associate function-names with code-locations are already lesser forms of such MetaData; one could take it much, MUCH further.)
Situations where they may be appropriate:
- Rapid prototyping - Demos, tests, or experimental apps
- RapidApplicationDevelopment - Where development time and/or budget is limited due to business constraints
- Output-oriented applications - Dynamic, interactive reporting. Since there is little or no data-entry, the type checking and validation has already been done.
- Tools for power-users - Expensive development not justified if there are only a few users of such tools. Often these are to relieve the technical staff of repetitious items that power-users are knowledgeable enough to perform.
In the "typing debates", there seems to be an all-or-nothing assumption such that one should always use dynamic languages or always use "strict" languages. But I believe it to be a matter of
PickTheRightToolForTheJob. It may also be that different personalities are suited to the different approaches.
- In the "typing debates", you too often assume all-or-nothing when it comes to 'strict' languages. Strict, strongly typed, compiled languages can provide every single dynamic feature you describe above. It seems you automatically associate with 'strong typing' all things you consider barbaric about a few mainstream languages that happen to feature strong typing among their other properties. A more discerning person would carefully determine which properties should be attributed to strictness and strong typing and which should be attributed to other aspects of language design.
Luckily, many strict languages offer an escape system - such as using a variant type, or even a simple pointer (untyped or typed). Other techniques used in strict languages when one needs an escape, are structs or records with several types stored inside the struct or record. An enumeration can be used to classify what type is currently set in the struct.
- To some extent I agree, but in my experience such languages are not really "optimized" for a dynamic style feature-wise. They are still more coding than the equivalent in a truly dynamic language. (I am not saying a good double-duty language couldn't be created or doesn't exist in an obscure language somewhere.) Here's some such features off the top of my head:
- On-the-fly declarations without a declaration statement.
- Isn't that an OxyMoron? Any statement with an on-the-fly declaration is a declaration statement, is it not?
- Without the need for a "var" or "dim" indicator and not required to be first "mentioned" at the top of the routine.
- Ah, you mean a bit like Python? I'm not certain where I stand on that; it makes it very easy to accidentally create variables by means of typographical error, and it makes it more difficult to properly access declarations that aren't in the 'local scope' (which can be difficult to easily predict when dealing with functional programming features). I can see how this allows a bit more dynamism insofar as sloppiness is very dynamic, but the cost may not be worth three or four saved keystrokes. However, I do agree that being forced to put them at the top of a procedure is irritating.
- Yes, I have seen as many as 50 erroneously handled variables and method parameters in less than 1000 lines of code in languages that allow this kind of feature, I have even seen code that ifs, and loops working with non existent variables, patched with extra ifs a variables that by typographica good luck fix them... I do not wish anyone to have to give maintenance to that kind of code.
- Sloppy programmers exist. That is not news. By the way, it's nice to have some kind of code profiling tool, kind of like C "lint", that can point out suspicious areas of the code.
- Oh, yes, sloppy programmers exist. In fact, every human programmer is a sloppy programmer. The only human programmers that don't introduce bugs into programs are those that have been promoted to management. So we shouldn't make it easier to make mistakes and simultaneously make it harder to find them. (Have you ever tried finding your own typographical errors?)
- {What is so hard about just declaring something like v i: int = 1; since you are going to assign it to 1 or similar at some point anyway? The v is less verbose than DIM or VAR and is prototype friendly.}
- Needing to declare types is a bad idea the moment you start doing TypefulProgramming in any language, but just local i = 1 (or var i = 1) wouldn't bother most programmers. Reducing it to one letter is doable too.
- Option of using dot notation instead of quotes and square brackets for associative arrays (but still use quotes-and-brackets for indexes with "funny characters" if needed.)
- A pretty syntax is always nice, but is hardly what distinguishes a dynamic from a static language. I, too, would prefer 'x.attr = y' instead of 'x["attr"]=y' if I was stuck with using mutable objects. For a functional language, I'd prefer: 'x with attr=y' to create a new value that is the same as x but with 'x.attr' having the value the result of evaluating that which is described by 'y'.
- Syntax sugar, but how hard is it to type x['attr'] especially single quotes make it nicer ;-)
- The need to enclose things with braces or quotes is, in and of itself, painful and irritating. And don't underestimate the power of SyntacticSugar; it won't save a bad language, but it can take a good language and make it sweet. See GoodNotationIsValuable.
- My philosophy is simplify the things you use the most. Since I use a lot of map arrays in scriptish languages, I want the map-related syntax to be as simple as possible to both reduce typing and volume of code that has to be read. Lack of dot notation for maps is not a show-stopper, but it does ding points off.
- I wonder if it would conflict with the other dot notation in the language.. such as dots for modules or dots for accessing namespaces or methods and such.. It is also going to change readability of the code since people will think "that is just a method or namespace, right?" but they would get used to it surely after some time. However, how will people distinguish in the code, whether what they are using is really an array? It is not visible, unless you have a type system that says "this is an array" or unless people just get used to it.
- Sure, syntaxes can possess reduce-reduce ambiguities due to context-sensitivity; this makes them a slower parse, but ultimately the benefits are worth the slower parse if one has an easier time describing his or her ideas to the computer. And while it would be harmful to a purely interpreted language (slowing it down) one can simply do the interpreter-is-actually-a-compiler thing (a'la Perl) and, if desirable, cache compiled objects so you don't need to parse them again in future runs until such a time as the source is updated. And don't underestimate human ability to work with context-sensitive or even context-rich code; humans are very adaptive, and ALL human natural-language communications are context-sensitive. Most people would get used to it very fast, and smart RefactoringBrowsers that color-code syntactic interpretations or otherwise annotate the code would help the rest.
- Perhaps another way of saying this is "map-friendly syntax and operations". Lists and sets (as operations?) friendliness should probably be included. (Needs a rewording.)
- Associative arrays and objects are essentially the same thing.
- Haven't they always been?
- Philosophically, it has been argued that ObjectsAreDictionaries, but languages don't always treat them as he same.
- One can implement an associative array in a language that doesn't even support objects. Using a hashlist function (see Algorithms and Data Structures Equal Programs, it may contain an example). One can implement an associative array with object indexes too, like object.items[][]. So it can be either or.
- "Eval()" function(s)
- What I really want is a good set of 'parse' functions... with full support for EBNF or something even more generic, and the ability to leverage any particular declarations->values list you wish to start with (allowing you to control evaluation context). That would make it easy to parse strings then decide what to do with them from there. I'm not fond of generic 'eval' due to concerns for security and its tendency to keep the evaluation targets opaque even to the programmer. Further, I don't believe that generic 'eval' is at all better for dynamic programming styles than would be a well formalized parser system (strictly, one could use a parser to take a string and create an executable object that one can then examine or manipulate).
- Nested subroutine scope (rare these days)
- Sweet feature; again, can be done in strictly typed languages. Some languages are moving back towards this, such as D from DigitalMars, TutorialDee, and the Boost lambdas and the various functional programming in C++ objects you'll see from JohnFletcher.
- Also known as (limited forms of) lexical closures which ModernPascal supports
- Input parameters can be optionally accessed via an associative array. Positional ones use are indexed with a sequence "1...2...3" etc. and named parameters with the parameter name.
- Keyword parameters with the ability to describe defaults are nice, though one must often choose between them and the ability to easily curry functions. (function on defaults with x=1,z=3). It is difficult to justify the need for a mutable associative array for this purpose (i.e. where you start the call to the function then manipulate the parameters at runtime from another function), so this can easily be done in static languages.
- ModernPascal uses a similar idea, see ArrayOfConst
- Interpreted
- Not necessary. See above.
- Interpretable as an option.
- Not necessary. See above.
- Well Rapid prototyping is done in DelphiLanguage (Borland significantly popularised RAD, which was developed by James Martin). Prototyping also involves terseness, hence why Ruby and Perl are used for quick prototyping. Delphi solves the verbosity issue with IDE tools that do the code insertions for you when you click things (creating events). My solution is to tersen the language more, since I don't always use or want to rely on my IDE to put text into my editor for me when I clicky dicky the buttons in GUI's, esp. since I don't build GUI's much any more. But Borland did invent a lot of RAD tools while still sticking with the strong static family of languages. Some argue that one reason they can build tools such as delphi are because of the rich type system available (but I've seen RAD python tools, so not so sure if it is of key importance)
If anyone is interested, I can post some example programs of where I have defeated the strong/strict/static type system using several methods. Another form of dynamism in languages is when one has built in compiler magic to pass in several types such as a varargs or array of any type parameter. I feel that the best compromise is the be safe by default philosophy. Allow a (convenient) escape in emergency, but aim to be safe by default. Humans make mistakes, humans are not perfect. I have similar views on security. In addition, strings themselves in databases can be used as an escape.. or blob fields and similar.
Perhaps the problem is that there should be a way to offer a constraint system for usually dynamic languages. Why? well, because, as stated before by someoneelse, dynamic languages are typically used for RapidPrototyping and/or RapidApplicationDevelopment, and a typical problem that arises after the very nice demostration of the prototype is that it will have to become a SeriousSolution?, and often the only way to do that is to start coding from scratch
Maybe what we need is a SuperLanguage? like XMF (ExtensibleProgrammingLanguage)
Generic programming, templates, polymorphism et al also help escape the strict/strong/static nature of languages but that is somewhat of a different topic.. although still it involves a bit of dynamism at say compile time or even run time in some implementations.
Just compile it with a special flag that requires it to have explicit types and declarations:
compile myprog.prg -anal=on
Sorry, couldn't resist ;-P
That's something some programmers don't understand. In this industry, being anally retentive is far better than being easy going. I mean, the whole idea of fixing a bug.. is being up tight. Why fix it? Programmers are anal retentive, critical, precise people. As for compiling it with a switch.. it isn't that easy. Consider an array of strings in a dynamic language which you also wish to write the same routines for with numbers. With numbers you do not want to allow zeros into the array. With strings you do not want to allow empty strings ("") into the array. In both the dynamic and the static language, you still have to write routines to check whether the string is empty or not, and whether the integer is zero or not. Horribly, you could get mixed up whether you were dealing with a zero string ("0") or a zero integer (0), because you don't know what type is coming in as a parameter. For example if you wanted to allow zero (0) strings in to your string array, but not your integer array.... you cannot easily do this without confusing the fsck out of yourself in a dynamic/weak/loose language.. because darn dang it I can't remember if "0" is a string or if "0" is a number. See also IncludeFileParametricPolymorphism. So with a list of "any type", if I want to store "0" strings, but not "0" numbers, then which is it? What am I passing in and how can I remember, especially when humans make mistakes? How am I really sure that "0" is a number or a string?
- Most languages are not powerful enough for necessary final validation anyhow. Some columns may be required to be a minimum length, capitalized, no leading spaces, no punctuation, etc. etc. A DataDictionary, perhaps with regular-expressions and call-backs, is more powerful and easier to control in that regard. Scattering all that info over app space is not a good thing. And there is no use specifying such checks at each routine; its a violation of OnceAndOnlyOnce, making changes more difficult and the code bloated. --top
- Then use only languages that are powerful enough (perhaps EiffelLanguage ?) to define constraints preconditions, postconditions, invariants, etc, etc. If the language is well designed it will help achieve OnceAndOnlyOnce... the real question should be: If a language only has partial support for good validation, it is better to use another language that has no validation at all?
- Or maybe what we need is a language that can be used to prototype in a "not strict mode" and that can be configured to incrementally increase its strictness level step by step, until the final product is released... that could even be use as metric (how much strictness did you (should you) reach before final release?)
- So we agree that we should strive to keep validation/type rules of a given "field" in one and only one place? Okay. So now comes the issue of *how* to represent that. I find it easier to work with most of such info in tabular form instead of app code. That's one of the advantages of relational: you can transform the view of something, such as validation info, to be what you want it to. App code does not easily allow that. (Ideally, app code and tablized info could be readily interchangeable, but that's far off dreaming right now.) Also, I find that one generally only needs to validate it "coming in and going out". There's little if any advantage of checking it over and over. That's one way how dynamic languages keep the declaration size down, making the code less cluttered. --top
- {I'd think you'd want to represent it near wherever the field is 'officially' declared. A DataDictionary is okay so long as manipulation thereof is the 'official' mechanism for adding and removing tables and columns in an RDBMS. Validation information should also be provided for each routine, however, but those would be type rules for inputs to the routine... not for tables outside the routine. And it is certainly the case that validation for stuff in a database shouldn't be scattered through a bunch of application code found outside the database, which is one reason that databases ought to be strongly typed. The moment you need to add a test to a query or to application code that reads the database, you violate OnceAndOnlyOnce.}
- {As far as 'app code' and 'tabilized info' being readily interchangeable: I think it's a silly little PipeDream, not a 'far off' thing. Most application code isn't even vaguely 'table shaped'; further, most code contains abstractions in the form of incomplete variables, and the RelationalModel is not at all designed to support abstractions of data of any sort, much less the executable sort. Perhaps we will one day have a database designed for it (something similar would be likely for a KnowLedge database) but it will likely not be Relational. Mercury and Prolog-style databases would probably be a better start.}
- RE: "There's little if any advantage of checking it over and over. That's one way how dynamic languages keep the declaration size down, making the code less cluttered." - {Actually, that's an advantage of static languages. Dynamic languages do exactly this: check it over and over and over. Perhaps you are concerned with ManifestTyping, but if you confuse ManifestTyping with StrongTyping or StaticTyping even one more time, I'm going to be seriously pissed off with you and I'm going to put it directly into ObjectiveEvidenceAgainstTopDiscussion.}
- Re: "Dynamic languages do exactly this: check it over and over and over." Please elaborate. This is flat false as stated. If specific individuals do it, then spank them, not me. --top
- {Dynamic languages don't track types across operations. As a consequence, every single operation within a function needs to examine its parameters to see if they make sense, whether it be by (for DynamicTyping) reviewing a tag or (for 'type-free' or 'single-typed' programming) examining the value structure - e.g. checking each character to see if it is a digit when doing numerical operations, or attempting a 'as number' operation with a special return value or exception in case of error. As a consequence, dynamic languages check inputs over and over and over. If you had even a rudimentary understanding of language implementations, you'd already know this. The ability to practically eliminate these redundant checks is one of the great optimization advantages of statically typed languages.}
- There is no "need to". For many situations, that is too "anal", for lack of a better word.
- {You are wrong, on a fundamental computation level. Maybe someday you'll design and implement your own dynamic language and libraries and even learn why.}
- If I don't put type checks against function parameters, they are simply not there, period. (Well, languages that use type-flags may check for some operations, depending on the language, but I am not talking about relying on that here.)
- {Why do you believe "they are simply not there, period" simply because you "don't [explicitly] put type checks against function parameters"?}
- If I don't put them there, and the language does not put them there, then they are not there. What 3rd force of nature would place them? (Sometimes there is implicit validation going on due to the operations that take place. But that is not a guarantee.)
- {It is true that if the language did not put them there, they would not be there. But the language does put them there - and it happens over and over and over due to the implicit validation going on due to the operations that take place. This is true for so-called 'type-free' languages and for dynamically typed languages both. It doesn't happen for statically weakly typed languages, which will hard-crash if you get it wrong. But dynamically typed languages are defined by this property (i.e. they, by definition, aren't dynamically typed if they don't check types at operations), and 'type-free' languages necessitate it for any non-trivial operation.}
- Consider Example "Ted" below. No operations in the function itself check types or crash based on types. A "length" function works in most type-flag-free languages no matter what.
- {To the contrary. length(a) implicitly checks whether 'a' is something that has a length and dispatches based on the underlying structure (or on a type-tag in a dynamically typed language) on how to compute said length. The '>' operation then takes two inputs, and (even if one can assume these must be numbers) will need to (in a dynamically typed language) check the number types and whether the input happens to be a number, and (in a so-called 'type-free' language) will implicitly require said check while performing structural examination of lengths and characters within expected ranges as part of testing the '>' (e.g. comparing two integer-strings by examination of lengths and characters and search for a negation indicator). Finally, the 'if' statement requires either (in a type-free language) a structural comparison against the set of values that might constitute falsehood (e.g. in a string based type-free language this might be "", "0", "false") whereas in a dynamically typed language the value will be checked to see if it is a boolean then coerced to a boolean. All this will happen every single time Ted runs - over and over and over. You seem to be unaware of the amount of checking actually occurring in these languages - have you ever looked into how a "length" function works in most type-tag free languages? Or is it voodoo compiler/interpreter magic to you?}
- Moving the discussion from a simple list of integers/strings to a database is showing signs of pushing aside the issue that was originally at hand. But as for databases requiring such things as capitalization.. maybe this is a discussion for ConstraintType where we plug in a function check into the database. The only issue I have with this is that.. how do you check for problems? Say that there is an invalid input from a user. You do not want to make a connection to the database just to check for errors... that still has to be lightweight application logic that checks for user input failures.
- {My own choice would be meta-programming - have the application-language ask the database for the field types, and have it transform those types into the necessary validation code, and probably have it cache this code someplace so it doesn't execute every single time the application is run (an optimization). Then use this for application-side validation, or even push it forward to the client-side.}
- Now, with something like capitalization, you don't have to warn the user that he didn't capitalize his First and Last name; but for other invalid inputs such as "wrong phone number format, please try again", you'd have to build application logic to warn the user. Connecting to a database with a ConstraintType would mean that each time you simply want to check an input error, you have to have a full DB connection open. Capitalization and databases had little to do with the original issue though (although a list is reinventing a relvar, I see your point). The issue was how to make a simple list of integers and strings, that didn't allow zero (0) in the integer list, but did allow zero ("0") in the string list. This is easy to do generically oncee with parametric polymorphism and strong/static typing, but in dynamic/loose/weak typing, I'm not so sure I'm clear as to whether "0" is a string or an integer, because I haven't fricking declared it as either, and I don't know what it ends up being (I could read the manuals, but it just ends up confusing the fsck out of me trying to think about it (unless you use an isString check, which is my point: hypocrisy. That isString check bloats the code, and is just a fake typecast, reinventing one.))
- {Human input to forms and such will generally be in strings. You'll always need to apply a parser to these strings, and you'll always need to (eventually) know which field was the original target for the string, so I'm not clear on why you believe there would be difficulty figuring out whether any particular string was intended for one list or the other. If you're saying there is just one list, you may need to resolve the ambiguity based on further entries and some heuristics. Ambiguity has its place in programming - it's easier to work with a language that resolves ambiguities in a sane and predictable manner than it is to deal with one that forces you to inject all sorts of additional punctuation just to avoid potential ambiguity. So, make a heuristic and keep it simple and very predictable.}
- I was just speaking of a simple array of integers in a program, not a full database app that deals with forms. Like an integerList versus stringList.... in a strong language it is easy to filter out strings from going into your integerlist since it simply doesn't allow strings into your integerlist. For example if someone enters OOOOO (oh's), you better be damn sure that your integerlist doesn't allow those in since the letter Oh is not a number. Users do stupid things, I've seen people enter "o" instead of "0" (note difference, look closely). So consider a simple app that is managing a bunch of numbers with an integer list that stores them (yes it should be in a relvar, I know)... how the heck are you really sure that "o" is not going to end up corrupting your data when it is supposed to be "0" in your list? In a dynamic language, an array doesn't define any types.. so it thinks that is okay! It's what you intended! So you have to insert isInteger checks which I doubt people remember to do ... and this is hypocrisy, since it bloats up the code with isInteger checks, which defeats the purpose of a dynamic/weak/loose language being non bloated! Your program is flooded with "flag checks" that you have to write as a human. Flag checks, in my opinion, are something people forget to do - hence why people think that dynamic/loose/weak languages are so non bloated.. because they forgot to code their app properly with integrity checks.. those integrity checks bloat up the application and are needed in any language! Unless, of course, your data is just a "blob of mud" where data has no meaning.
- {I think I'd appreciate it if, when you went off on your little rants, you took some TimeToMakeItShort. As far as 'o' and '0', given their relative position on the QWERTY keyboard, it hardly surprises. And dynamic language doesn't require 'no types' - it only requires that typing not need to be made manifest and duplicate all over the program; ImplicitTyping and SoftTyping for the most part with a little explicit (manifest) typing at the edges (e.g. at the database or I/O layers, or in this case at the array or list if that is the final destination for the data) will be just as dynamic and will provide correctness.}
You are thinking.. does it matter? What's the difference? That's where you JustDontGetIt probably. Oh Oh, but is there a IsString?() function that tells you the type being passed in, or the current type flag as you call them? And when you call this IsString?() function, is not that a Cast, bloating up your code just like with typecasts? And is not that more error prone, for you to have to remember to do all these checks (if you even know what checks to do, which many programmers don't).. versus designing your programs automatically this way since the system doesn't work without designing it that way.. Really, it is easy to mix up a zero string with a zero integer and forget to check it.. or other similar things.. because you don't always know what your flags really are.. it is all done behind your back similar to how encapsulated OOP is done behind your back. I'd argue that dynamic/weak/loose typing is a form of encapsulation, OOP-ish. Everything is just a "dynamic loose object" and not a precise "string, apple, integer, banana, etc". Next time someone asks you what type of fruit you would like to eat for a snack.. tell them I want you to surprise me.. blindfold me. But remember that eating fruit is fairly safe even with a blind fold on.. whereas, data, not so much as safe. Unless you take extra efforts to remove the blindfold each and every time - but humans are too lazy.
Eating fruit blindfold is not safe at all, after all Habanero chili with 1,000,000 Scoville units (http://en.wikipedia.org/wiki/Habanero_chili) is a fruit... Opuntia (http://en.wikipedia.org/wiki/Opuntia) is also a fruit (with spines ) and you wouldn't want to be given one while blindfolded.
You took my point and proved it further. Someone anal retentive (just like me) says.. wait! Even that can be unsafe. And you're right.
Example "Ted"
function foo(a, b, c) {
if(length(a) > 2) {
bar(a, b);
} else {
bar(b, c);
}
}
What the hell is that? PHP without dollar signs? Nice pseudo language.
And how are you going to inform your users that the above Foo function accepts only certain kinds of parameters if it is working with numbers only? What does it return? Nothing, or something? Does it modify strings? Check strings? Check numbers only? Where is your
contract?
- Usually one can tell by the title or description of the routine. For example, "Price" is usually a number. And sometimes type does not matter. ID numbers are rarely checked beyond equality such that their "type" does not mean much. That makes dynamic routines flexible because one has fewer places to change if say an ID is changed from a number to a string to accommodate ID changes. If you scatter "Long" everywhere the damned ID is used, then you have to change gazillion places. And occasionally I will have the routine require a specific type if it clarifies things. (Granted EcmaScript is not very friendly for such, but a language like ColdFusion is.)
Is your contract in the source comments and do people find out what the incoming parameters are by reading the source comments? Where is your
interface? In the documentation? In
your mind hidden somewhere from other people? Does the function return anything? Is it a procedure or a function? Do I have to look in the source code implementation just to find this info out? Did you even mark the source so I could find out in the first place? Or did you just assume people would know by playing guessing games and reading the non existent docs that you didn't write yet?
(these are all rhetorical questions by the way)
Oh, and that above function is just so clear and saves you so much more red tape and typing (and time) than:
pro foo(a, b, c: astr);
b
if length(a) > 2 do bar(a, b) els bar(b, c);
e;
--
QompVandal
The example was not meant to illustrate brevity and the above is probably not representative of the verbosity that type-heaviness can result in.
AprilZeroEight