[m-users.] boiler plate reduction, or leave it alone as 'self documenting code' ?

Sean Charles (emacstheviking) objitsu at gmail.com
Sat Nov 5 19:44:52 AEDT 2022


Hi,

As I produce more syntax checking code I am seeing a lot of repetition but I am unsure if I should attempt to reduce it and if so, how best to do it? 

Initially I created a predicate, tr_inclusions/3 but then after calling it the code was almost the same, a disjunction around the return type and the saving in code noise was minimal so I aborted and posted here for some advice instead!

Here is one check predicate, the bold lines are basically the only lines that differ for syntax_require_once/3, syntax_include/3 and syntax_include_once/3, I think you can see my dilemma...


:- pred syntax_require(location::in, lsnode::in, checked::out) is det.

syntax_require(Pos, Body, Out) :-
    Len = list.length(Body),
    ( if Len > 0 then
        convert_terms(Body, Res),
        (
            Res = ok(TrInst),
            Out = ok(t_require(Pos, TrInst))
            Out = ok(t_require_once(Pos, TrInst))
            Out = ok(t_include(Pos, TrInst))
            Out = ok(t_include_once(Pos, TrInst))
        ;
            Res = error(Errors),
            Out = error(Errors)
        )
    else
        Out = checkfail(Pos, require_form_error)
    ).


If I could pass in the argument `t_require_once(Pos, TrInst)` that would be good but I think in the past when I have tried things like this that the compiler doesnt like it because you can't use holes in data structures.
The idea was to take the above function and refactor like this, passing in the term...

tr_inclusions(Pos, Body, Term, Out) :-
    Len = list.length(Body),
    ( if Len > 0 then
        convert_terms(Body, Res),
        (
            Res = ok(TrInst),
            Out = ok(Term)
        ;
            Res = error(Errors),
            Out = error(Errors)
        )
    else
        Out = checkfail(Pos, require_form_error)
    ).

... tr_inclusions(Pos, Body, t_require(Pos, HOLE), Out)

but I can't use an unbound variable on those constructors as they have to be fully instatiated and how would I know where to put TrInst anyway when composing the returned value?

:- type lsinst == list(tr_inst).
:- type gps == location.
:- type tr_inst
    --->    t_defun(gps, acl, ps, list(fn_sig), lsinst)
    ;       t_defvar1(gps, ps)
    ;       t_defvar2(gps, ps, tr_inst)
    ;       t_if1(gps, tr_inst, tr_inst)
    ;       t_if2(gps, tr_inst, tr_inst, tr_inst)
    ;       t_include(gps, lsinst)
    ;       t_include_once(gps, lsinst)
    ;       t_unary(gps, uop_type, lsinst)
    ;       t_binary(gps, bop_type, lsinst)
    ;       t_gencall(gps, ps, lsinst)
    ;       t_nary(gps, nop_type, lsinst)
    ;       t_progn(gps, lsinst)
    ;       t_require(gps, lsinst)
    ;       t_require_once(gps, lsinst)
    ;       t_return0(gps)
    ;       t_return(gps, lsinst)
    ;       t_literal(ps)  % or does it need to be more refined?
    ;       t_keyword(ps)
    ;       t_string1(ps)
    ;       t_string2(ps)
    .

I've been thinking about wether or not in this instance, the refactoring effort is in fact a waste of time?

Thanks,
Sean.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurylang.org/archives/users/attachments/20221105/70026762/attachment.html>


More information about the users mailing list