[erlang-questions] If you are homesick for object.selector

Olav Frengstad olav@REDACTED
Thu Jan 24 10:12:55 CET 2013


An alternative syntax for working with (nested) records is functional
lenses, the downside being evaluated at runtime opposed to a compiled
parse transform solution.
However this does not save you any keystrokes for Obj.selector type expressions.

Taking Loïc's example:

{Get,Set} = compose([#char.cur_weapon, #weapon.ability, #ability.points_req]),
Character2 = S(123, Character),
123 = G(Character2).

Jesper Louis Andersen wrote a simple Erlang implementation which can
be found here: https://github.com/jlouis/erl-lenses

Olav

2013/1/24 Loïc Hoguin <essen@REDACTED>:
> Richard,
>
> There is already this:
>   https://github.com/esl/parse_trans/blob/master/src/exprecs.erl
>
> But I think their point is that Person.name does not require extra
> keystrokes to get the value, as opposed to Person#person.name or
> person:name(Person).
>
> They're incorrect when claiming it makes things harder, it's just a lot more
> tedious, especially if you have a lot of different values to manipulate. A
> simple example would be an RPG video game character, which has various kinds
> of state, a name, a class, stats, equipped items, inventory, unlocks,
> friends, quickchat, options and more. Erlang makes programming this kind of
> thing a nightmare, and all that simply because you can't do something like:
>
>   Character.current_weapon.ability.points_req
>
> Or
>
>   Character.inventory[0].name
>
> Or at least, not without a lot more keystrokes. And let's not even speak
> about actually modifying these values or adding an item to the inventory. In
> a language as horrible as PHP, adding an item to the inventory can be
> written as:
>
>   Character->inventory[] = Item;
>
> You of course have to know what [] means, but it makes the code incredibly
> easier to read. Erlang lacks all these easy data manipulation facilities. I
> am not sure this can be fully resolved.
>
> Of course, perhaps one could use some Lua behind Erlang to do the game
> logic, but that's not really a good selling point for people to use Erlang,
> it's at best a compromise.
>
>
> On 01/24/2013 02:52 AM, Richard O'Keefe wrote:
>>
>> We've had a claim recently that using
>>         Person#person_name
>> instead of
>>         Person.name
>> is so horrible that it's scaring off people who would otherwise
>> use Erlang.
>>
>> What would be _Erlangish_ approach to this look like?
>> (Apart from implementing frames, of course.)
>>
>> I think PL/I was the first language to use "." for
>> field selection.  COBOL and Algol 68 used (selector OF record).
>>
>> In the statement
>>
>>         x = thingy.selector;
>>
>> what is ".selector"?
>>
>> It is nothing other than a function, applied to the argument
>> "thingy" to yield a result.
>>
>> What's the Erlang syntax for applying a function to an argument?
>>
>>         X = selector(Thingy)
>>
>> In the statement
>>
>>         thingy.selector = y;
>>
>> what is ".selector ="?
>>
>> It is nothing other than a function, applied to two arguments.
>> What's the Erlang syntax for applying a function to two arguments?
>>
>>         Thingy1 = set_selector(Thingy0, Y)
>>
>> Now we can define these things manually.  We just have to include
>> a clause for each visible record type.
>>
>> What's the Erlang way to generate functions automatically from
>> declarative information?
>>
>> Use attributes to provide the information and a parse transform
>> to do the generation.
>>
>> For example, you might write
>>
>> -record(person,     {id,name,department_id,manager_id,age,job}).
>> -record(department, {id,name,              manager_id}).
>> -record(project,    {id,name,department_id}).
>> -getters([id,name]).
>> -setters([name]).
>>
>>  From that, you might like to get automatically generated code like
>>
>> id({person,F,_,_,_,_,_}) -> F;
>> id({department,F,_,_}) -> F;
>> id({project,F,_,_}) -> F.
>>
>> name({person,_,F,_,_,_,_}) -> F;
>> name({department,_,F,_}) -> F;
>> name({project,_,F,_}) -> F.
>>
>> set_name({person,X1,_,X3,X4,X5,X6}, F) ->
>>      {person,X1,F,X3,X4,X5,X6};
>> set_name({department,X1,_,X3}, F) ->
>>      {department,X1,F,X3};
>> set_name({project,X1,_,X3}, F) ->
>>      {project,X1,F,X3}.
>>
>> Well, as it happens, that code _was_ automatically generated, and
>> it was automatically generated from those lines.  This was just a
>> quick prototype, so I whipped it up in AWK.  Two pages with comments,
>> one page without.  The _right_ way is a parse transform, of course.
>>
>> I don't regard this design as settled, so there's no EEP.
>> For example, it's reasonable to want automatically generated -spec
>> declarations as well, which would generally look like
>>
>>         -spec <field>(#<record 1>{}) -> <field type 1>
>>                    ; (#<record 2>{}) -> <field type 2>
>>               ... .
>>         -spec set_<field>(R, <field type 1>) -> R when R :: #<record 1>{}
>>                        ; (R, <field type 2>) -> R when R :: #<record 2>{}
>>                ... .
>>
>> but this is tedious rather than difficult.
>>
>> For another thing, you might want to give the selector function a
>> different
>> name from the field and you might not want all possible records for some
>> selector function.
>>
>> The nice thing is that code generators like this can be written entirely
>> in Erlang using existing features.
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>
> --
> Loïc Hoguin
> Erlang Cowboy
> Nine Nines
> http://ninenines.eu
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions



-- 
Med Vennlig Hilsen
Olav Frengstad

Systemutvikler // FWT
+47 920 42 090



More information about the erlang-questions mailing list