Structs (was RE: Record selectors)

Joe Armstrong <>
Wed Jan 15 11:01:25 CET 2003


On Wed, 15 Jan 2003, Ulf Wiger wrote:
> 
> -struct(guru, {name = "joe",
>                footSize = 42,
>                likes = "motorbikes"}).
> 
> Then, one could create a named struct just like a new
> record:
> 
> C = ~guru{name = "robert", likes="water rockets"}.
> 
> But this would of course not solve the compile-time
> dependencies that now plague records.
> 
> 
> On the other hand, if one writes a module that is the "home"
> of a struct, and makes sure to instantiate a struct using a
> dedicated function, the issue of defaults is not a big one:
> 
> -module(mystructs).
> -export([new/1]).
> 
> new(guru) ->
>   ~guru{name, footSize, likes}.
> 
> ...introducing some syntactic sugar that allows us to avoid
> having to type "= undefined" for all fields that should have
> a default value.
> 
> D = (mystructs:new(guru))~{name="klacke",
>                            likes="whitewater rafting"}
> 

  Brilliant ... (this is (essentially) what Robert and I came up with a
while ago, and I'd forgotten) - can I change the syntax a bit:

In the module that defines the struct

	-module(xx)

	-export_structs([guru]).

	-struct(guru, {name = "uffe", likes = "opera"}).

	C = ~guru{name = "robert", likes="water rockets"}.
	
In an external module

	-module(yy).

	-import_struct(xx, [guru]).

	C = ~guru{name="jim"}        % if guru is imported
	
	D = ~yy:anotherStruct{env="abc", count=0}

In this scheme the tag checking is done at run-time *not* compile time
and structs are represented as in my paper.

If you want more control you could add guards to the structs

	-struct1(foo,
		{on_create, fun(X) -> check_it(X) end},
		{on_set,
		    [{name, fun(I) -> check_name(I) end},
		     {likes, fun(J) -> check_likes(I) end}}	
		).

Then every time you call

	~foo{name="joe", links="aaaa"}

check_name("joe") would be called, then
check_likes("aaaa") would be called, then
check_it(~foo{name="joe", linkes="aaaa"}) would be called



> This would also perhaps make it possible to introduce real
> handling of undefined fields:
> 
> erlang:is_nil(D.footSize) -> true | false.
> 
> (where accessing a non-initialized field is an error.
> I'm not totally convinced that this is a good idea, but
> then again, we could stick to the heretic practice of
> using the legal value 'undefined')
> 
> Anonymous structs could perhaps be kept super-dynamic. I
> don't know if this would complicate the implementation or
> compromise efficiency.
> 

  I  don't thing  so  -  it's a  hash  lookup the  first  time you  do
anything, thereafter you can cache  the result (yes the object code is
self-modifying)  the second  time  you  check to  see  if things  have
changed. (Like how they do dispatches in smalltalk :-)

/Joe


> /Uffe
> 




More information about the erlang-questions mailing list