That's true but with comments ;)

Composing strings (packing) have two main advantages:

1. Strings may be inmutable (you can return a new different string, maybe a
copy)
2. Strings can be passed as parameter

The fexpr writing directly to stdout with print and running a program does
not returns a string with the intended result:

: (de <p> P (prin "<p>") (run P) (prin "</p>"))
-> <p>
: (<p> hallo)
<p></p>-> "</p>"
: (length (<p> hallo))
<p></p>-> 4
: (setq X (<p> hallo))
<p></p>-> "</p>"
: X
-> "</p>"

You can argue return value is nothing you must worry about because you're
only going to print the result, so better use it as a side effect. But this
is not always true, returning a string you can further compose it and make
transformations to it

So first problem with this fexpr (programmed this way) you don't have the
intended return value and thus you cannot use it as parameters to other
function invocation

Second problem is about inmutability, as you don't return the value you
cannot have a completely different memory object.

Ovbiously you can arrange the program (P) you pass to the fexpr and get
those problems solved by example packing into the result but it may become
not easy to write the function due to side effects:

: (de pp P (prin "<p>") (run P) (prin "</p>") (pack "<p>" (run P) "</p>") )

: (pp (+ 2 3))
<p></p>-> "<p>5</p>"
: (pp 2)
<p></p>-> "<p>2</p>"
: (pp (print 2))
<p>2</p>2-> "<p>2</p>"
: (pp (<p> (prin "hallo")))
<p><p>hallo</p></p><p>hallo</p>-> "<p></p></p>"
: (pp (pp (prin "hallo")))
<p><p>hallo</p>hallo</p><p>hallo</p>hallo-> "<p><p>hallo</p></p>"
: (<p> (<p> (print "hallo")))
<p><p>"hallo"</p></p>-> "</p>"

so you must code carefully the fexpr, and anyway if you're going to return
a string then side effects are often innecesary.

More interesting is last use of fexpr which is the true reason of existence
of fexpr's, being able to write macros

But even when being needed as the only way to write certain functions (aka
macros), most of the time are not needing, like the intended use with <div>
showed as an example by Alex.

Given:

: (de p (t) (pack "<p>" t "</p>"))
: (de d (c t) (pack "<div class=\"" c "\">" t "</div>"))

the example given by Alex to get a multiline div is simply this one-liner:

: (prinl (d "red" (glue "^J" (mapcar p '("ABC" "DEF" "GHI")))))

<div class="red"><p>ABC</p>
<p>DEF</p>
<p>GHI</p></div>






El sáb., 13 mar. 2021 8:32, Alexander Burger <a...@software-lab.de> escribió:

> Hi all,
>
> at PilCon three days ago we discussed about FEXPRs like
>
>    (de <p> Prg
>       (prin "<p>")
>       (run Prg)
>       (prin "</p>") )
>
>    (de <div> (Col . Prg)
>       (prin "<div class=\"" Col "\">")
>       (run Prg)
>       (prin "</div>") )
>
> which can be called as
>
>    (<div> "red" (<p> (prin "Text")))
>
> giving such output:
>
>    <div class="red"><p>Text</p></div>
>
>
> One question that came up was why FEXPRs could not be replaced with normal
> functions (EXPRs), simply 'pack'ing strings:
>
>    (de <p> (Str)
>       (pack "<p>" Str "</p>") )
>
>    (de <div> (Col Str)
>       (pack
>          "<div class=\""
>          Col
>          "\">"
>          Str
>          "</div>" ) )
>
>    : (<div> "red" (<p> "Text"))
>    -> "<div class=\"red\"><p>Text</p></div>"
>
> While this would surely work, I answered that it is a big overhead to
> generate
> the whole page as strings just to print them.
>
>
> But I forgot to explain: The real reason for FEXPRs goes beyond that. They
> have
> the power of passing executable code bodies, with arbitrary flow control,
> to the
> function.
>
> To pick just a minimal example:
>
>    (<div> "red"
>       (for S '("ABC" "DEF" "GHI")
>          (prinl)
>          (<p> (prin S)) )
>       (prinl) )
>
>    <div class="red">
>    <p>ABC</p>
>    <p>DEF</p>
>    <p>GHI</p>
>    </div>
>
> This cannot be done with EXPRs.
>
> ☺/ A!ex
>
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>
>

Reply via email to