I've seen this style of library come up quite a few times whilst hacking away in JavaScript where developers try to introduce a sense of strict typing (I even wrote a similar one myself when I first moved over from ActionScript). In the end I learned to stop worrying and love the <strike>bomb</strike> duck typing[0].
For me; one of the "joys" of coding JavaScript is the expressiveness that comes with a dynamic languages; should you throw an ArgumentError when your function that expects a number is invoked with a String? Maybe - sure it can help catch problems early and effectively "stop-the-line" in your public API, but then again it will probably end up throwing the classic `TypeError: Object foo has no method 'bar'` for you anyway.
For "public" methods which form part of an API (especially when that API is going to be shared outside of my team) I try to make my functions handle failure early (before they delegate off to the "private" internal methods), even better if the public methods can repair any unexpected usage, ie:
function convertToHex(value) {
var result;
if (typeof value !== "number") {
result = convertToHex(parseInt(value, 10));
}
else {
result = "0x" + value.toString(16);
}
return result;
}
Also, with regards to default argument values, I've always felt the "native" JavaScript approach was fairly compact and descriptive when required:
function doFoo(bar) {
bar = (bar !== undefined) ? bar : "default_value";
}
I'm not sure that embracing a languages dynamic nature should get in the way of leveraging libraries to write more readable code. One advantage of using a standard approach (be it a third party library, or something bespoke) is that you could enable / disable the 'type checking' depending on the build environment. I wouldn't be surprised if your existing toolchain isn't already bringing some static inference to your development - are you using jsdoc and an IDE with autocomplete, for example?
Trusting you find Dart, Typescript, et al agreeable you have to concede that some people are working with legacy code and can only make iterative changes to their codebase?
For me it was partly about providing type errors, but also very much about providing easy to write and easy to read type testing and sorting. Type testing in javascript can be a bit tough on the eye and this hopefully makes it easy to see what parameter types a function will accept.
'Args.caller.arguments' gives me the willies. That's a non-standardized extension combined with a deprecated one [0][1]. I'd have to be itching quite a lot to scratch it like this.
"Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."
That and I'm not understanding from the page how this is used in the first place. Is the `arguments` implicit variable being passed in some place? (EDIT: yes, via `Function.caller`.) Are the argument values accessed through the result of calling `Args`?
For a non-macro implementation of this, it might be interesting to use function decorator syntax instead, to put the argument processing outside the function body entirely. Basically, the argument processor decorator function would take an options array and a target function, which has all possible parameters, explicitly named. The decorator would spit out a new function that invisibly does all of the wrangling of `arguments` and then finally calls the target function. An advantage is that I think this would be the most minimal pure JS solution from a syntax perspective, and it would keep the actual function body uncluttered. A disadvantage is that it could only really be used with function expressions (not declarations).
More than that, macros would be a static solution, expanding to sensible arguments parsing code at compile time. So much metaprogramming these days is dynamic where you pay excessive interpretive cost to evaluate the little DSL every time the function is called. JavaScript programmers are guilty of this, but not nearly as guilty as Ruby programmers...
Seen lots of these at this point. I still don't really understand their purpose.
Its not hard, and doesn't require much, if any, more code than the config options for libraries like this to just handle your arguments normally.
required arguments get defined in your function signature. You assign optional args to local variables defined within your function body via the arguments object. It's pretty easy.
The original motivation was providing a single way to deal with a combination of default arguments, optional arguments and the sort of homebrew polymorphism that a lot of libraries use, where a function takes 4 different types of thing and runs through a bunch type tests before doing anything.
For functions with longer parameter lists this should hopefully be more readable too. It's clear what types can be passed to a function.
Out of interest, what other libraries like this have you seen? I did a quick check myself and couldn't find anything comparable.
Another good reason to assign everything to a local variable ASAP is that if I leave everything in the args object then jshint can't help me prevent typos when accessing fields from that object.
I experimented with something similar a while ago, however my main focus was strictness and not default and optional parameters. I did end up adding it though.
[+] [-] callum85|12 years ago|reply
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
[+] [-] Touche|12 years ago|reply
[+] [-] phase_9|12 years ago|reply
For me; one of the "joys" of coding JavaScript is the expressiveness that comes with a dynamic languages; should you throw an ArgumentError when your function that expects a number is invoked with a String? Maybe - sure it can help catch problems early and effectively "stop-the-line" in your public API, but then again it will probably end up throwing the classic `TypeError: Object foo has no method 'bar'` for you anyway.
For "public" methods which form part of an API (especially when that API is going to be shared outside of my team) I try to make my functions handle failure early (before they delegate off to the "private" internal methods), even better if the public methods can repair any unexpected usage, ie:
Also, with regards to default argument values, I've always felt the "native" JavaScript approach was fairly compact and descriptive when required: [0] http://en.wikipedia.org/wiki/Duck_typing[+] [-] simon_renoult|12 years ago|reply
[+] [-] ifuller1|12 years ago|reply
Trusting you find Dart, Typescript, et al agreeable you have to concede that some people are working with legacy code and can only make iterative changes to their codebase?
[+] [-] adam-a|12 years ago|reply
[+] [-] curveship|12 years ago|reply
0 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
1 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
[+] [-] prezjordan|12 years ago|reply
[+] [-] nebulous1|12 years ago|reply
"Non-standard This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."
[+] [-] gnud|12 years ago|reply
Args([/* argument definition */], arguments);
[+] [-] mmastrac|12 years ago|reply
[+] [-] gosukiwi|12 years ago|reply
[+] [-] acjohnson55|12 years ago|reply
That and I'm not understanding from the page how this is used in the first place. Is the `arguments` implicit variable being passed in some place? (EDIT: yes, via `Function.caller`.) Are the argument values accessed through the result of calling `Args`?
For a non-macro implementation of this, it might be interesting to use function decorator syntax instead, to put the argument processing outside the function body entirely. Basically, the argument processor decorator function would take an options array and a target function, which has all possible parameters, explicitly named. The decorator would spit out a new function that invisibly does all of the wrangling of `arguments` and then finally calls the target function. An advantage is that I think this would be the most minimal pure JS solution from a syntax perspective, and it would keep the actual function body uncluttered. A disadvantage is that it could only really be used with function expressions (not declarations).
[+] [-] brandonbloom|12 years ago|reply
[+] [-] andrey-p|12 years ago|reply
https://github.com/andrey-p/arg-err
[+] [-] jdc0589|12 years ago|reply
Its not hard, and doesn't require much, if any, more code than the config options for libraries like this to just handle your arguments normally.
required arguments get defined in your function signature. You assign optional args to local variables defined within your function body via the arguments object. It's pretty easy.
[+] [-] adam-a|12 years ago|reply
For functions with longer parameter lists this should hopefully be more readable too. It's clear what types can be passed to a function.
Out of interest, what other libraries like this have you seen? I did a quick check myself and couldn't find anything comparable.
[+] [-] ufo|12 years ago|reply
[+] [-] K0nserv|12 years ago|reply
https://github.com/k0nserv/Strict.js
[+] [-] zephjc|12 years ago|reply
[+] [-] muskalek|12 years ago|reply
[+] [-] Rygu|12 years ago|reply
[+] [-] michaelwww|12 years ago|reply
[+] [-] abimaelmartell|12 years ago|reply