Skip to content

Commit ae3e717

Browse files
committed
fixes #764
1 parent 244a97d commit ae3e717

File tree

2 files changed

+1679
-1350
lines changed

2 files changed

+1679
-1350
lines changed

xml/chapter3/section3/subsection3.xml

+125
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,131 @@ const put = operation_table("insert");
686686
</SPLITINLINE>
687687
should take as input a list of keys used to access the table.
688688
<LABEL NAME="ex:3_25"/>
689+
<SOLUTION>
690+
<SNIPPET>
691+
<NAME>solution_3_25</NAME>
692+
<EXAMPLE>solution_3_25_example</EXAMPLE>
693+
<JAVASCRIPT>
694+
// contributed by GitHub user tttinkl
695+
696+
function assoc(key, records, same_key) {
697+
return is_null(records)
698+
? undefined
699+
: same_key(key, head(head(records)))
700+
? head(records)
701+
: assoc(key, tail(records), same_key);
702+
}
703+
704+
705+
function make_table(same_key) {
706+
const local_table = list("*table");
707+
708+
const get_value = tail;
709+
710+
function is_table(t) {
711+
return is_pair(t) &amp;&amp; head(t) === "*table";
712+
}
713+
714+
function lookup(keys) {
715+
function lookup_generic(keys, table) {
716+
if (is_null(keys)) {
717+
return table;
718+
}
719+
const key_1 = head(keys);
720+
const key_rest = tail(keys);
721+
const record = assoc(key_1, tail(table), same_key);
722+
if (is_undefined(record)) {
723+
return undefined;
724+
}
725+
if (is_null(key_rest)) {
726+
return get_value(record);
727+
} else if (is_table(get_value(record))) {
728+
return lookup_generic(key_rest, get_value(record));
729+
} else {
730+
error('invalid key');
731+
}
732+
}
733+
return lookup_generic(keys, local_table);
734+
}
735+
736+
737+
function insert(keys, value) {
738+
function insert_generic(keys, value, table) {
739+
const key_1 = head(keys);
740+
const key_rest = tail(keys);
741+
const record = assoc(key_1, tail(table), same_key);
742+
if (is_undefined(record)) {
743+
if (is_null(key_rest)) {
744+
set_tail(
745+
table,
746+
pair(pair(key_1, value), tail(table)));
747+
} else {
748+
const new_subtable = list("*table");
749+
set_tail(
750+
table,
751+
pair(pair(key_1, new_subtable), tail(table))
752+
);
753+
insert_generic(key_rest, value, new_subtable);
754+
}
755+
} else {
756+
if (is_null(key_rest)) {
757+
set_tail(record, value);
758+
} else {
759+
if (is_table(get_value(record))) {
760+
insert_generic(key_rest, value, get_value(record));
761+
} else {
762+
const new_subtable = list("*table");
763+
set_tail(record, new_subtable);
764+
insert_generic(key_rest, value, new_subtable);
765+
}
766+
}
767+
}
768+
}
769+
insert_generic(keys, value, local_table);
770+
}
771+
772+
function dispatch(m) {
773+
return m === "lookup"
774+
? lookup
775+
: m === "insert"
776+
? insert
777+
: m === "show"
778+
? () => {
779+
display(local_table);
780+
return local_table;
781+
}
782+
: error(m, "unknow operation -- table");
783+
}
784+
return dispatch;
785+
}
786+
787+
const table = make_table(equal);
788+
789+
const get = table('lookup');
790+
const put = table('insert');
791+
const show = table('show');
792+
</JAVASCRIPT>
793+
</SNIPPET>
794+
<SNIPPET HIDE="yes">
795+
<NAME>solution_3_25_example</NAME>
796+
<JAVASCRIPT>
797+
put(list("a"), 1);
798+
put(list("b", "c"), 2);
799+
put(list("d", "e", "f"), 3);
800+
801+
display(get(list("a")));
802+
display(get(list("b", "c")));
803+
display(get(list("d", "e", "f")));
804+
805+
put(list("a", "b"), 1);
806+
display(get(list("a")));
807+
put(list("b", "c", "d"), 2);
808+
display(get(list("b", "c")));
809+
put(list("b"), 1);
810+
display(get(list("b")));
811+
</JAVASCRIPT>
812+
</SNIPPET>
813+
</SOLUTION>
689814
</EXERCISE>
690815

691816
<EXERCISE>

0 commit comments

Comments
 (0)