mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-17 23:05:21 +00:00
Estimated hours taken: 3 Branches: main, release Fix a problem where different packages in the `extras' distribution were being installed in different directories when you specified INSTALL_PREFIX in the Mmake.params file. Some honoured the INSTALL_PREFIX setting, some appended "/extras", and some ignored it completely. Also, add `clean' and `realclean' targets for the extras directory hierarchy, and fix a few other minor bugs. extras/lazy_evaluation/Mmakefile: Include Mmake.params, which previously wasn't included at all in this file. extras/logged_output/Mmakefile: extras/odbc/Mmakefile: extras/quickcheck/Mmakefile: Append "/extras" to INSTALL_PREFIX, which previously wasn't done at all in these directories. extras/cgi/Mmakefile: extras/complex_numbers/Mmakefile: extras/concurrency/Mmakefile: extras/curs/Mmakefile: extras/curses/Mmakefile: extras/dynamic_linking/Mmakefile: extras/moose/Mmakefile: extras/posix/Mmakefile: Move the line `INSTALL_PREFIX := $(INSTALL_PREFIX/extras)' to before the include of Mmake.params, so as not to override the user's setting (only override the default setting). extras/Mmakefile: extras/concurrency/Mmakefile: Add `clean' and `realclean' targets. extras/posix/Mmakefile: Add MGNUCFLAGS = --no-ansi, since this is needed on some systems. extras/quickcheck/Mmakefile: Add "depend", "all", and "install" targets. Ensure that the "check" target runs the test program. extras/quickcheck/qcheck.m: Set the exit status to non-zero if a test fails. extras/references/Mmakefile: Adjust the setting of LIBGRADES to account for the fact that $(GRADE) is no longer implicitly included in $(LIBGRADES).
This directory contains support for optional lazy evaluation. Using the modules defined here, you can write Mercury code that makes use of lazily evaluated data structures. Our implementation of lazy evaluation requires you to use a different type, lazy(T), whenever you want things to be lazily evaluated, and requires you to insert explicit calls to delay/1 or force/1 whenever lazy evaluation requires the creation or evaluation of closures. This directory contains the following files: lazy.m: This module defines the lazy(T) type, and the force/1 and delay/1 functions. lazy_list.m: This module defines a type lazy_list(T) using the lazy(T) type, and also defines a few functions and predicates that operate on lazy lists. lazy_list_test.m: This is just a very simple example showing the use of lazy lists. In comparison with lazy functional languages, the disadvantage of our approach is that inserting the lazy(T) types and the explicit calls to force/1 and delay/1 requires additional work when you are writing your code. Fortunately the Mercury compiler's static type checking will ensure that the calls to force/1 and delay/1 are consistent with the use of lazy(T) types. But even so, putting all the calls to force/1 and delay/1 in the right place can still be rather tedious. In return, however, we get several important advantages. The first is that there are absolutely no efficiency costs resulting from lazy evaluation if you don't use it. This is in contrast to many implementations of lazy functional languages, where you often pay a significant efficiency cost simply because things *might* be lazy, even when in actual fact they are not. Compilers for lazy functional languages often try to avoid these costs by performing strictness analysis, but current compilers can only infer strictness of functions, not data types; using lazy data types rather than strict data types can have a very large impact on efficiency (e.g. a factor of 5). Also, in the presence of separate compilation, compilers may need to make conservative assumptions about strictness. The second advantage is that the creation and evaluation of closures is explicit in the source code, which makes it much easier to reason about the performance of your programs. Programs in languages where laziness is the default often suffer from space leaks or unexpectedly high memory usage, and these problems can be _extremely_ difficult to track down and understand, even for very experienced programmers. The third advantage is that supporting lazy evaluation via a library module keeps the language and its semantics simple. We're not really providing lazy evaluation per se, we just _emulating_ it by passing lambda expressions as arguments. So the "Semantics" chapter of the language reference manual does not need to be modified at all. Supporting lazy evaluation via a library module also keeps the implementation simple -- the module lazy.m requires only a very small amount of implementation-dependent code, and none of the rest of the implementation need change. Our current implementation of lazy evaluation is not very efficient. There are several reasons for this. One is that promise_only_solution/1, which is used in the implementation of force/1, is currently implemented rather inefficiently. Another is that the lazy(T) type currently uses two levels of indirection, whereas it really ought to use only one. Finally, for maximum efficiency, we would need to inline delay/1, but that is not possible in the current implementation. Solving these latter two issues would require a bit more compiler support.