[erlang-questions] Dynamically access record fields

Loïc Hoguin essen@REDACTED
Tue Feb 12 03:04:31 CET 2013


On 02/12/2013 02:06 AM, ok@REDACTED wrote:
> "Loïc Hoguin" <essen@REDACTED> wrote
>
>> - Micro optimization. Most applications wouldn't care for it either
>    Applications cannot care or not care for anything.
>    If people are willing to pay the price, fine;
>    my problem was that I saw no evidence that any proponent
>    realised that there _was_ a price "I just don't see the harm".

Pedantic point. If execution speed isn't an application requirement, 
then there's no need to even concern yourself about it, because 
everything else is more important.

You'll also most likely improve the execution speed of your system by 
improving inter-process communication and application architecture 
rather than having to execute one less instruction here and there.

>> - That's a developer's choice
>    Making code less readable may be a developer's _choice_,
>    but if anyone else might be required to read the code,
>    it isn't a developer's _right_.

You seem to think code readability isn't subjective.

>> - BS, you have the same issue with Var = #rec.field, no difference there
>    Reducing the effectiveness of type checking?
>    Yes, we do have the same issue with Var = #rec.field,
>    BUT I don't say that using that is a good idea either.

Sometimes there's no good solution and you still have to get things 
done. However, as far as "bad" solutions go, #rec.field is worse than 
'field', because you'll get a meaningless integer when you output the 
value when debugging, instead of what could have been an atom.

>> - See previous point
>    Inadvertently providing wider access?  No, this one is
>    quite different from #rec.field.  You can only use
>    #rec.field within the compile-time scope of a -record
>    declaration for 'rec'.  If #rec.Field were allowed,
>    Field could be created at a point where the record
>    declaration was _not_ visible.  #rec.field has to be
>    inside the module; use of it is not inadvertent; and
>    you can _find_ it trivially with a text editor, so
>    you can very easily check which fields might be accessed
>    that way.  As far as I can see, that's not true of
>    #rec.Field, where Field comes from some unknown arbitrary
>    module.

Well, #rec.Field is not possible to begin with, and wouldn't make sense 
for records. But it would definitely be good for another data type, as 
I'll explain.

> The key point is that we just plain DON'T NEED #rec.Field;
> anything we could do with it can be done without it more
> clearly using existing mechanisms, with better control over
> access and all sorts of other programmer-liked goodness.

There's nothing clear in having to write:

g(bindings, #http_req{bindings=Ret}) -> Ret;
g(body_state, #http_req{body_state=Ret}) -> Ret;
g(buffer, #http_req{buffer=Ret}) -> Ret;
g(connection, #http_req{connection=Ret}) -> Ret;
g(cookies, #http_req{cookies=Ret}) -> Ret;
g(fragment, #http_req{fragment=Ret}) -> Ret;
g(headers, #http_req{headers=Ret}) -> Ret;
g(host, #http_req{host=Ret}) -> Ret;
g(host_info, #http_req{host_info=Ret}) -> Ret;
g(meta, #http_req{meta=Ret}) -> Ret;
g(method, #http_req{method=Ret}) -> Ret;
g(multipart, #http_req{multipart=Ret}) -> Ret;
g(onresponse, #http_req{onresponse=Ret}) -> Ret;
g(p_headers, #http_req{p_headers=Ret}) -> Ret;
g(path, #http_req{path=Ret}) -> Ret;
g(path_info, #http_req{path_info=Ret}) -> Ret;
g(peer, #http_req{peer=Ret}) -> Ret;
g(pid, #http_req{pid=Ret}) -> Ret;
g(port, #http_req{port=Ret}) -> Ret;
g(qs, #http_req{qs=Ret}) -> Ret;
g(qs_vals, #http_req{qs_vals=Ret}) -> Ret;
g(resp_body, #http_req{resp_body=Ret}) -> Ret;
g(resp_headers, #http_req{resp_headers=Ret}) -> Ret;
g(resp_state, #http_req{resp_state=Ret}) -> Ret;
g(socket, #http_req{socket=Ret}) -> Ret;
g(transport, #http_req{transport=Ret}) -> Ret;
g(version, #http_req{version=Ret}) -> Ret.

Instead of

g(Field, Req) -> Req#http_req.Field.

Better control over access? You can still do it in the guard if you need to.

I'm sure you'll tell me this should be generated? That's neither clear 
nor practical. And the generated code would likely not give good control 
over access either anyway.

> Erlang needs dynamic field access like oysters need shooting-sticks.

For records I agree, for almost anything else (dict | sets | proplists | 
maps | ...) I don't. Especially more so in Erlang.

You're being very affirmative over what people do or don't need, but you 
seem to forget the one thing that people need the most: getting things 
done. Perhaps a solution is slightly more prone to some kinds of bugs, 
however making it harder to do something is as likely to create bugs. 
Erlang is wonderful in that you can easily contain bugs to the local 
process or group of processes, so I don't really see why we wouldn't 
want to have more productive solutions. (And yes, productivity is also 
subjective.)

-- 
Loïc Hoguin
Erlang Cowboy
Nine Nines
http://ninenines.eu



More information about the erlang-questions mailing list