Why do we need modules at all?<br><br>This is a brain-dump-stream-of-consciousness-thing. I've been<br>thinking about this for a while.<br><br>I'm proposing a slightly different way of programming here<br>The basic idea is <br>
<br> - do away with modules<br> - all functions have unique distinct names<br> - all functions have (lots of) meta data<br> - all functions go into a global (searchable) Key-value database<br> - we need letrec<br>
- contribution to open source can be as simple as<br> contributing a single function<br> - there are no "open source projects" - only "the open source<br> Key-Value database of all functions"<br>
- Content is peer reviewed<br><br>These are discussed in no particular order below:<br><br>Why does Erlang have modules?<br><br>There's a good an bad side to modules:<br><br>Good: Provides a unit of compilation, a unit of code<br>
distribution. unit of code replacement<br><br>Bad: It's very difficult to decide which module to put an individual<br>function in. Break encapsulation (see later)<br><br>Aside: lib_misc.erl<br><br>When I'm programming I often get to the point were I say there should<br>
a function foo/2 in lists.erl but their isn't. There should be but<br>there isn't - foo/2 is a small self contained thing. Why should it be<br>in lists.erl because it "feels right".<br><br>Strings are lists, so why do we have two modules lists.erl and<br>
string.erl how should I decide in which module my new string/list<br>processing function should go.<br><br>To avoid all mental anguish when I need a small function that<br>should be somewhere else and isn't I stick it in <br>
a module elib1_misc.erl.<br><br>My elib1_misc exports the following:<br><br>added_files/2 make_challenge/0<br>as_bits/1 make_response/2<br>as_bits_test/0 make_response_test/0<br>
bdump/2 make_test_strings/1<br>bin2hex/1 make_test_strings_test/0<br>bin2hex_test/0 make_tmp_filename/2<br>check_io_list/1 merge_kv/1<br>collect_atom/1 merge_kv_test/0<br>
collect_atom_test/0 mini_shell/0<br>collect_int/1 module_info/0<br>collect_int_test/0 module_info/1<br>collect_string/1 ndots/1<br>collect_string_test/0 nibble_to_hex_char/1<br>
collect_word/1 nibble_to_hex_char_test/0<br>complete/2 odd/1<br>complete_test/0 on_exit/2<br>dos2unix/1 out_of_date/2<br>downcase_char/1 outfile/2<br>
dump/2 padd/2<br>dump_tmp/2 perms/1<br>duplicates/1 perms_test/0<br>ensure_started/2 pmap/2<br>eval_file/1 pmap1/2<br>eval_file_test/0 pmap1_test/0<br>
eval_string/1 pmap_test/0<br>eval_string_test/0 priority_receive/0<br>every/3 random_seed/0<br>expand_env_vars/1 random_string/1<br>expand_file_template/3 random_string/2<br>
expand_string_template/2 read_at_most_n_lines/2<br>expand_tabs/1 read_at_most_n_lines_test/0<br>expand_tabs_test/0 remove_duplicates/1<br>expand_template/2 remove_duplicates_test/0<br>
extract_attribute/2 remove_leading_and_trailing_whitespace/1<br>extract_attribute_test/0 remove_leading_and_trailing_whitespace_test/0<br>extract_prefix/2 remove_leading_whitespace/1<br>fetch/2 remove_prefix/2<br>
fetch_test/0 remove_prefix_test/0<br>file2lines/1 remove_trailing_whitespace/1<br>file2lines_test/0 replace/3<br>file2md5/1 root_dir/0<br>file2numberedlines/1 rpc/2<br>
file2numberedlines_test/0 safe/1<br>file2paras/1 show_loaded/1<br>file2stream/1 signed_byte_to_hex_string/1<br>file2string/1 signed_byte_to_hex_string_test/0<br>file2template/1 skip_blanks/1<br>
file2term/1 skip_blanks_test/0<br>file_size_and_type/1 skip_to_nl/1<br>find_src/1 skip_to_nl_test/0<br>first/1 sleep/1<br>flatten_io_list/1 spawn_monitor/3<br>
flush_buffer/0 split_at_char/2<br>for/3 split_at_char_test/0<br>force/1 split_list/2<br>foreach_chunk_in_file/3 split_list_test/0<br>foreach_word_in_file/2 string2exprs/1<br>
foreach_word_in_string/2 string2exprs_test/0<br>forever/0 string2html/1<br>get_erl_section/2 string2latex/1<br>get_line/1 string2lines/1<br>get_line/2 string2lines_test/0<br>
have_common_prefix/1 string2stream/1<br>have_common_prefix_test/0 string2stream_test/0<br>hex2bin/1 string2template/1<br>hex2bin_test/0 string2template_test/0<br>hex2list/1 string2term/1<br>
hex2list_test/0 string2term_test/0<br>hex_nibble2int/1 string2toks/1<br>hex_nibble2int_test/0 string2toks_test/0<br>id/1 sub_binary/3<br>include_dir/0 template2file/3<br>
include_file/1 term2file/2<br>interleave/2 term2string/1<br>is_alphanum/1 test/0<br>is_blank_line/1 test1_test/0<br>is_prefix/2 test_function_over_substrings/2<br>
is_prefix_test/0 tex2pdf/1<br>is_response_correct/3 time_fun/2<br>keep_alive/2 time_stamp/0<br>lines2para/1 to_lower/1<br>list2frequency_distribution/1 to_lower_test/0<br>
list2frequency_distribution_tetrim/1<br>longest_common_prefix/1 trim_test/0<br>longest_common_prefix_test/0 unconsult/2<br>lookup/2 unsigned_byte_to_hex_string/1<br>lorem/1 unsigned_byte_to_hex_string_test/0<br>
ls/1 which/1<br> which_added/1<br><br>Now I find this very convenient when I write a new small utility function<br>I stick in in elib1_misc.erl - no mental anguish in choosing a module<br>
name is involved.<br><br>The observation that I find this very-convenient is telling me something<br>about modules - I like my elib1_misc it feels right.<br><br>(aside - It seems many development projects have their own private<br>
lib_miscs ...)<br><br>Which brings me to the point of my question.<br><br>Do we need module's at all? Erlang programs are composed of lots of small<br>functions, the only place where modules seem useful is to hide a letrec.<br>
<br>The classic example is fibonacci. We want to expose fib/1 but hide the<br>helper function fib/3. Using modules we say<br><br>-module(math).<br>-export([fib/1]).<br><br>fib(N) -><br> fib(N, 1, 0).<br><br>fib(N, A, B) when N < 2 -> A;<br>
fib(N, A, B) -> fib(N-1, A+B, A).<br><br>The downside is we have had to *invent* one module name math - whose *only*<br>purpose is to hide the definition of fib/3 which we don't want to be made <br>callable.<br><br>
If we put a second function into the module math, then this second function<br>could call fib/3 which breaks the encapsulation of fib/3.<br><br>We could say:<br><br>let fib = fun(N) -> fib(N, 1, 0) end<br>in<br> fib(N, A, B) when N < 2 -> A;<br>
fib(N, A, B) -> fib(N-1, A+B, A).<br>end.<br><br>I hardly dare suggest a syntax for this since I've been following<br>another thread in this forum where syntax discussion seem to encourage<br>much comment.<br><br>
** Please do suggest alternative syntax's here - but do not comment on<br>other peoples suggestions ...<br><br>I would like to just talk about why we have modules.<br><br>Another question:<br><br>Does the idea of a module come from the idea that functions have to be<br>
stored somewhere, so we store them in a file, and we slurp the<br>file (as a unit) into the system, so the file becomes a module?<br><br>If all the files were store by themselves in a database would this<br>change things.<br>
<br>I am thinking more and more that if would be nice to have *all* functions in<br>a key_value database with unique names.<br><br>lookup(foo,2) would get the definition foo foo/2 from a database.<br><br>The unique names bit is interesting - is this a good idea. Qualified<br>
names (ie names like xxx:foo/2) or (a.b.c.foo/2) sounds like a good<br>idea but but when I'm programming I have to invent the xxx or the<br>a.b.c which is very difficult. It also involves the "decision problem"<br>
if the namespaces xxx and a.b.c already exist I have to *choose* which<br>to put my new function in.<br><br>I think there might be a case for alises here joe:foo/2 could be used<br>while developing "joe" would expand to a horrible random local string the<br>
real name being ab123aZwerasch123123_foo/2 but I would not be able to<br>publish my code or make it available to a third_part before I had<br>chosen a sensible name.<br><br>(( managing namespaces seems really tricky, a lot of peoople seem<br>
to thing that the problem goes away by adding "." 's to the name<br>but managing a namespace with namees like foo.bar.baz.z is just as complex<br>as managing a namespace with names like foo_bar_baz_z or names like<br>
0x3af312a78a3f1ae123 - the problem is that we have to go from a symbolic<br>name like www.a.b to a reference like 123.45.23.12 - but how do we discover<br>the initial name www.a.b? - there are two answers - a) we are given the name<br>
(ie we click on a link) - we do not know the name but we search fo it )) <br><br><br>When programs are small we can live with "just the code" in "a few<br>modules" the ratio of code to meta data is high.<br>
<br>When programs are large we need a lot of meta-data to understand them.<br><br>I would like to see all functions with all meta-data in a data base.<br><br>I'd like to say:<br><br> lookup(foo,2,Attribute) when Attribute = <br>
<br> code|source|documentation|type signatures|revision history|authors|...<br><br>The more I think about it the more I think program development should<br>viewed as changing the state of a Key-Value database.<br><br>
So I imagine:<br><br> 1) all functions have unique names<br> 2) there are no modules<br> 3) we discover the name of a function by searching metadata<br> describing the function in a database<br> 4) all public functions (think open source) are in the same<br>
database<br><br>We could make a system to do this.<br><br>I think this would make open-source projects easier, since the<br>granularity of contribution goes down. You could contribute<br>a single function - not an entire application.<br>
<br>(( A problem with GUT style open source projects is there is<br> not one database of functions, I often what one function from<br> this project, another function from another project -- the<br> granularity of reusable parts should be the individual function.<br>
<br> functions are really easy to reuse<br> modules are more difficult to reuse<br> entire applications are very difficult to reuse<br> (Unless there are isolated through a communication channel))<br><br>Possible extensions.<br>
<br> 1) Voting for promotion<br> 2) A review process<br><br>Given a raw database will *all* functions in it - we could derive an<br>"approved" functions database.<br><br>Popular functions could be moved to the approved database - the <br>
review process would need to be discussed - so kind of peer-review/wiki<br>stuff.<br><br>Comments?<br><br>Volunteers?<br><br>/Joe<br><br><br><br>