From: Scott Sauyet on
Thomas 'PointedEars' Lahn wrote:
> A helper function that by design makes it hard for it to be reused, that
> makes code less legible and less reliable than if it was not used, a
> function that is not generally applicable, is not a goal to be attained.

I can buy this: "A helper function that by design makes it hard for
it to be reused, that makes code less legible and less reliable than
if it was not used, is not a goal to be attained." But I'm not buying
your "generally applicable" clause. Code needs to have an reasonable
domain. It should be clear as to what it accepts and handle errors
consistently, but it does not have to be able to give reasonable
results for unreasonable input. Defining what is and is not
reasonable is a large part of designing an API.


But I find myself in an odd position here. I'm defending something I
don't really support, only to say that the problems aren't as bad as
stated. I think that Matt probably should use a multiple-string API,
with the main reason being the sort of problems many of us have
pointed out, but may best be seen in your response to one of my code
snippets:

|> $prop(obj, "longer.path.with.some[0].brackets.included");
| So, is `some' the property name or is it `some[0]', which is
entirely
| possible and realistic with DOM scripting?

Matt made it clear that he wants to use his function for searching DOM
nodes. Simply because of that, I find it reasonable to complicate the
API with multiple strings.


But still I see issues. The technique I used when I did this was to
search first using the entire string ("some[0]") for a property name,
and if that wasn't found to try "some", then 0 on the results. It
worked and it never turned around and bit us. But I was never happy
with it. When we found this need (when we switched server framework
and now had to deal with brackets as attribute values) we were already
invested in the single-string API. We never did have to introduce a
delimiter, but we did have a slightly more complex API that allows
brackets to contain additional hierarchies:

$prop(obj, "prop1.prop2[current.left.size].color");

I suppose the way to do that with the multiple string array would be
something like this:

$prop(obj, "prop1", "prop2", $prop(current, "left", "size"),
"color");

But that clearly is neither as convenient nor as legible as the
original. So again I want to argue both sides of this issue. I think
I'd better just stop here! :-)

--
Scott
From: Thomas 'PointedEars' Lahn on
Scott Sauyet wrote:

> Thomas 'PointedEars' Lahn wrote:
>> A helper function that by design makes it hard for it to be reused, that
>> makes code less legible and less reliable than if it was not used, a
>> function that is not generally applicable, is not a goal to be attained.
>
> I can buy this: "A helper function that by design makes it hard for
> it to be reused, that makes code less legible and less reliable than
> if it was not used, is not a goal to be attained." But I'm not buying
> your "generally applicable" clause.

Perhaps you are misunderstanding, then.

> Code needs to have an reasonable domain.

The domain is property access.

> It should be clear as to what it accepts and handle errors
> consistently, but it does not have to be able to give reasonable
> results for unreasonable input. Defining what is and is not
> reasonable is a large part of designing an API.

Property names that contain what property names may contain are not
unreasonable input.

> But I find myself in an odd position here. I'm defending something I
> don't really support, only to say that the problems aren't as bad as
> stated.

Without giving a good reason for your opinion that they are not, so you
should ask yourself if you are trying to defend something that is worth
defending.


PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
From: nick on
On May 12, 3:57 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
> Stefan Weiss wrote:

> > This may be obvious, but did you consider simply catching and ignoring
> > the ReferenceError?

> >   try { var color = body.firstChild.style.backgroundColor; } catch(e) {}

This seems like the most obvious way to do it.

> Starting a statement that way isn't "not as nice" it is a failure of the
> code to express its intent. The try statement misleads the reader.

True, it would be nice if we could wrap it in a function.

> Someone may also mention that using try/catch is inefficient, and it is,
> but that is the least of the problems.

It's probably at least as efficient as executing a bunch of other code
to get around it as in the OP...

Matt, I've been using a build script and putting C++ preprocessor
directives in my js source to keep things manageable (initially just
for includes and ifdefs). I've been playing with a header file
containing some function macros; they can be useful for inlining and
doing things you can't do with normal functions (like pass in a non-
existing variable). "Error-free deep property access" might make a
good candidate for that header file:

#define CAN_ACCESS(v) \
(function(){ \
try{void(v); return true;} \
catch(e){return false;}})();

You can use it in your source something like this:

if (CAN_ACCESS(document.forms[2]))
document.forms[2].submit();
else
notifyUser("Swing and a miss.");

....And it will expand to... well, something fairly ugly. But, your
source code is still plenty readable, and you have less code to
support :)
From: David Mark on
nick wrote:
> On May 12, 3:57 pm, Garrett Smith <dhtmlkitc...(a)gmail.com> wrote:
>> Stefan Weiss wrote:
>
>>> This may be obvious, but did you consider simply catching and ignoring
>>> the ReferenceError?
>
>>> try { var color = body.firstChild.style.backgroundColor; } catch(e) {}
>
> This seems like the most obvious way to do it.

The trouble is that it is ham-fisted. You will have no idea why the
exception is thrown, so the pattern has very limited potential in
anything but the simplest of contexts.
From: Scott Sauyet on
Thomas 'PointedEars' Lahn wrote:
> Scott Sauyet wrote:
>> Thomas 'PointedEars' Lahn wrote:
>>> A helper function that by design makes it hard for it to be reused, that
>>> makes code less legible and less reliable than if it was not used, a
>>> function that is not generally applicable, is not a goal to be attained..
>
>> I can buy this:  "A helper function that by design makes it hard for
>> it to be reused, that makes code less legible and less reliable than
>> if it was not used, is not a goal to be attained."  But I'm not buying
>> your "generally applicable" clause.
>
> Perhaps you are misunderstanding, then.

Maybe, but I think it's more that I disagree.


>> Code needs to have an reasonable domain.
>
> The domain is property access.

Not to my mind. And perhaps that is the crux of the matter. The
language already has '[]' for property access, and a shortcut for some
simpler cases: '.'. I have little need to use a function that has the
same domain as those language constructs.

The reason I created my version -- and I really wish I still had it
available -- was that doing all the error checking on something that
would otherwise be very simple made the source code much harder to
read. The goal of the function was to make the source code simpler to
read without actually sacrificing safety.

So the domain was limited to replacing the sorts of source code that I
would like to use except that it wasn't safe, something like

obj.prop1.[key1.prop2.prop3].prop4

with a similar looking construct that gained the required safety.
Part of the goal of my code was the very similarity to the desired
source code above. If I remember correctly, unlike Matt, I didn't
separate out the initial object, so mine looked something like

fetch('obj.prop1[key1.prop2.prop3].prop4');

The whole point of mine was to make it look like as much as possible
like the desired source code.


>> It should be clear as to what it accepts and handle errors
>> consistently, but it does not have to be able to give reasonable
>> results for unreasonable input.  Defining what is and is not
>> reasonable is a large part of designing an API.
>
> Property names that contain what property names may contain are not
> unreasonable input.

So are you saying that all functions should be written to work
seamlessly with any values of their parameters that the language might
allow? Or are we allowed to write functions whose behavior is only
well-defined for some specified subset of the allowed values? I've
have always believed the latter. Do you really believe the former?
That's got to be hard to do in a loosely typed language.


>> But I find myself in an odd position here.  I'm defending something I
>> don't really support, only to say that the problems aren't as bad as
>> stated.
>
> Without giving a good reason for your opinion that they are not, so you
> should ask yourself if you are trying to defend something that is worth
> defending.

My code was not originally intended to work with DOM nodes. The data
structures I used were built in other JS code, and I'm quite certain
they never contained property names that wouldn't be allowed as an
identifier. When I had to support "[]" as well, it was not a hard
extension. Had my requirements grown further, I might have had to
abandon some of the initial simplicity. But I wouldn't do so unless
circumstances forced it on me. The overriding goal was to simplify my
code and make it more readable.

It's easy enough to defend the decisions I made. But Matt seems to
have somewhat different requirements, and I don't think my approach
would suit those requirements as well. I have stated the reasons for
both sides of this argument several times. I think the categorical
statements that string parsing is wrong here are overblown. But if I
were writing the code for him under my understanding of his
requirements, I probably would use the multiple parameter approach.
For my own requirements, I think string parsing is clearly better.
It's all about the simplicity of the API.

--
Scott