[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Write a macro which defines a procedure
Re: Write a macro which defines a procedure
Sun, 21 Jul 2019 13:56:20 +0200
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.2
On 7/21/19 4:56 AM, Mark H Weaver wrote:
> Hi Zelphir,
> Zelphir Kaltstahl <address@hidden> writes:
>> At first I had the macro use `define`, but then I thought: "What if I
>> want to conditionally define a route procedure?". My guess is, that then
>> the define form would be inside some `cond` or `if` form and then it
>> would not work
> You're right, it would not work. Nonetheless, I would strongly
> discourage you from doing this kind of thing unless there's a very
> compelling reason for it.
To be honest there are not really any compelling reasons and I did think
about such consequences that you mention below, only the thought of not
being able to use the macro conditionally and wanting it to be usable
everywhere and fear of possibly making a mistake later on in my code,
trying to use it somewhere, where it cannot be used. However, now that I
think about it, there might not be a real need inside that project after
all, as the API route are predefined in the docker docs.
> Note that we have 'cond-expand' from SRFI-0 for conditional inclusion of
> definitions, if you need it. 'cond-expand' is roughly analogous to #if
> in C. It's less general than plain 'if', but there's an important
> reason for that, and it has to do with the distinction between compile
> time and run time.
Aha! I did not know that : )
I will read about the `cond-expand` in the SRFI 0. Thanks for mentioning
SRFI 0. I guess I am still a little uneducated with regard to SRFIs and
what they contain. Zero seems like an important number.
> If you use 'cond-expand', the condition is checked at compile time, and
> consequently it is known at compile time which branch was taken and
> therefore which definitions were chosen.
> If you use 'cond', then the condition will be checked at run time, which
> will normally rule out the possibility of optimization opportunities
> such as inlining and partial evaluation. At present, Guile is not able
> to perform these optimizations for toplevel level definitions in any
> case, but it might be possible in the future, at least for modules that
> are not explicitly mutated using low-level operations like this.
> Also, it's possible that a future version of Guile may be more
> disciplined in its handling of phases, i.e. expand-time
> (i.e. compile-time) vs run-time phases. See section 7.2 (Import and
> export levels) of the R6RS for details on one approach, which would
> bring many advantages. It's been a while since I looked at this
> closely, and at this point I would need some time to refresh my memory
> of the details, but it seems to me that the code you've written would
> likely cause problems with such an approach.
> Both the R6RS and R7RS have more declarative module systems, which bring
> many benefits. Added freedom in one area often implies a loss of
> freedom somewhere else. In this case, the freedom to treat modules as
> arbitrarily mutable objects implies a loss of freedom in the compiler to
> make any assumptions about what's in the module or even its set of
> bindings. That freedom carries a very significant cost.
Thank you for your explanations. That's great feedback! It seems asking
on the Guile user list saved me again from doing something not so good
in my code. I will improve my code accordingly then, either by making
use of SRFI 0 or reverting to simple `define`, knowing that I can only
use it at the top level of a module or top level of the scope where I
want things to be available, as with normal `define` forms.
… *goes and reads SRFI 0* …
OK, so the limitations are, that `cond-expand` is restricted to the top
level, unless Guile implements it differently. Not sure what kind of
useful condition I can come up with inside the `cond-expand` and simply
putting a `#t` seems silly. I guess it is really for checking things you
can know at expand time. I do not have any such conditions in mind to
check. Perhaps I will stick with normal `define` forms for now and just
need to remember, that it will be expanded to a `define` form and thus
needs to be used like one. Actually, that would still make it possible
to return the created procedures and then I could still conditionally
return another procedure instead, so it is still somewhat flexible.