Re: FEXPRs / PilCon

2021-03-16 Thread Tomas Hlavaty
On Sun 14 Mar 2021 at 09:34, Alexis  wrote:
> My guess is that Tomas is using the latter meaning, and wants 
> 'pure' functions that simply return strings, without sending them 
> to an output device. The final string to be output would be 
> created by combining the return values of multiple functions, 
> possibly performing transformations on them along the way, then 
> sending _that_ string to an output device. Is that correct, Tomas?

Pretty much, except instead of strings the values should be cons trees.
Strings do not "compose" but cons trees do.  Also with strings, the
structure is lost but cons trees preserve the structure making it
possible to know what exactly is being output and automatically escape
accordingly.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-15 Thread pd
On Sun, Mar 14, 2021 at 10:19 PM Alexander Burger 
wrote:

> Hi pd,
>
> > They're are not intended to be right implementations, too bad for that
> ;-)
>
> No no, I did not say that :)
>

:)  ok  but *I* say that,   it's really not a code to show, only intended
to show output


> Right. The point is that FEXPRs allow you to write flow control in a way
> not
> possible with EXPRs.
>

exactly,



> OK. But please don't mix up the issue with side effects. They have nothing
> to do
> with FEXPRs.
>

that's true, you can code for side-effects using fexprs or exprs. I simply
said I prefer to code not using side-effects (even when sometimes are
needed or the better solution)


>
> And in most cases you can get both (beauty and performance).
>
>
touché! ;-)


regards


Re: FEXPRs / PilCon

2021-03-14 Thread Alexander Burger
Hi pd,

> > > : (de pp P (prin "") (run P) (prin "") (pack "" (run P)
> > "") )
> > ...
> > This is a bit problematic, because the body in P is executed twice. Not
> > only is ...
> >(de pp P
> >   (prin (pack "" (run P) "")) )
> yes, all my examples in my previous email are bad code, just  for output
> only, trying to offer examples of how things can go weird
> They're are not intended to be right implementations, too bad for that ;-)

No no, I did not say that :)

I just wanted to show the obvious shortcut.


> yes sure, I think the PilCon and this email thread are good examples of an
> interesting use of fexprs  but  even complex and large programs may be
> arranged in a way fexpr are not needed, it's a kind of condig style.

Right. The point is that FEXPRs allow you to write flow control in a way not
possible with EXPRs.


> My point is you can do with fexprs everything you do with exprs but the
> opposite is not true, fexprs have it own role in lisp. But I prefer to code
> in a more functional style working composing functions with inmutable
> objects and without side-effects.

OK. But please don't mix up the issue with side effects. They have nothing to do
with FEXPRs.


> It's always a balance between performance and logical beauty (from my point
> of view), but performance is not only about computing performarce but also
> logic and conceptual performarce and even profiling or debugging
> performance.

And in most cases you can get both (beauty and performance).

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-14 Thread pd
On Sat, Mar 13, 2021 at 2:05 PM Alexander Burger 
wrote:

>
> Yes. (And strings are always immutable in PicoLisp anyway)
>

this is pretty interesting to be rembered, good for newbies to discover why
it is that way ;-)


> > : (de pp P (prin "") (run P) (prin "") (pack "" (run P)
> "") )
>
> This is a bit problematic, because the body in P is executed twice. Not
> only is
> this slower, but may create havoc because in a typical GUI program *all*
> logic
> happens in these bodies. This logic would be executed several times, doing
> lots
> of unexpecyed things. Better then:
>
>(de pp P
>   (prin (pack "" (run P) "")) )
>
>
yes, all my examples in my previous email are bad code, just  for output
only, trying to offer examples of how things can go weird
They're are not intended to be right implementations, too bad for that ;-)


> For such a simple example it works. But keep in mind that typically 'P'
> is a large program, with lots of 'if's, 'while's  and arbitrarily deeply
> nested other HTML tags.
>
>
yes sure, I think the PilCon and this email thread are good examples of an
interesting use of fexprs  but  even complex and large programs may be
arranged in a way fexpr are not needed, it's a kind of condig style.

My point is you can do with fexprs everything you do with exprs but the
opposite is not true, fexprs have it own role in lisp. But I prefer to code
in a more functional style working composing functions with inmutable
objects and without side-effects.
It's always a balance between performance and logical beauty (from my point
of view), but performance is not only about computing performarce but also
logic and conceptual performarce and even profiling or debugging
performance.

At the end the smart decision is to choose the better tool for the job ;-)

 greets


Re: FEXPRs / PilCon

2021-03-13 Thread Alexis



Alexander Burger  writes:


On Sat, Mar 13, 2021 at 06:48:22PM +0100, Tomas Hlavaty wrote:

   (de  (Col . Prg)
  (prin "")
  (run Prg)
  (prin "") )

prin has side-effect.


Nonsense! 'prin' *is* the only and desired effect.


Mm, it seems to me that there might be a mutual misunderstanding 
here, due to two different meanings of 'side-effect'.


The lay meaning of 'side-effect' is "an effect in addition to the 
one that was intended/desired".


A technical meaning of 'side-effect', in functional programming, 
is "something which changes state":


   https://en.wikipedia.org/wiki/Side_effect_(computer_science)

In this context, printing something to an output device changes 
global state; the 'state of the world' has been changed to one 
that includes the content output.


My guess is that Tomas is using the latter meaning, and wants 
'pure' functions that simply return strings, without sending them 
to an output device. The final string to be output would be 
created by combining the return values of multiple functions, 
possibly performing transformations on them along the way, then 
sending _that_ string to an output device. Is that correct, Tomas?



Alexis.

--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 21:13, Alexander Burger  wrote:
> On Sat, Mar 13, 2021 at 08:59:37PM +0100, Tomas Hlavaty wrote:
>> On Sat 13 Mar 2021 at 19:09, Alexander Burger  wrote:
>> > On Sat, Mar 13, 2021 at 06:48:22PM +0100, Tomas Hlavaty wrote:
>> >>(de  (Col . Prg)
>> >>   (prin "")
>> >>   (run Prg)
>> >>   (prin "") )
>> >> 
>> >> prin has side-effect.
>> >
>> > Nonsense! 'prin' *is* the only and desired effect.
>> 
>> see https://en.wikipedia.org/wiki/Side_effect_(computer_science)
>> for explanation what side-effect means
>
> I think I know what a side effect is ...
>
> But OK, "In computer science, an operation, function or expression is said to
> have a side effect if it modifies some state variable value(s) outside its 
> local
> environment".
>
> Please where does  have a side effect?

prin performs I/O

 calls prin

   Example side effects include [...] performing I/O or calling other
   side-effect functions.

> Again: This discussion is Kindergarten. I wonderhow many members of this list 
> we
> drive off.

hmm

> Haha, come on! Don't be picky! In this case 'Cls' is a simple class name.
> Garbage in garbage out.

Similar attitude have developers of beA - Das besondere elektronische
Anwaltspostfach - BRAK.  They do not escape their XML properly but use
string concatenations.  The result is that their XML responses are
invalid and I cannot use proper validating XML parser but have to
extract relevant data ad-hoc using text search.  And using this software
is mandated by German law!  I would not be surprised if the whole thing
is totally insecure.  Goodbye mandant/lawyer confidentiality.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 19:09, Alexander Burger  wrote:
> On Sat, Mar 13, 2021 at 06:48:22PM +0100, Tomas Hlavaty wrote:
>>(de  (Col . Prg)
>>   (prin "")
>>   (run Prg)
>>   (prin "") )
>> 
>> prin has side-effect.
>
> Nonsense! 'prin' *is* the only and desired effect.

see https://en.wikipedia.org/wiki/Side_effect_(computer_science)
for explanation what side-effect means

>> Col is not properly escaped!
>
> How so? It generates
>
>
>
> What kind if escape do you want?

( "\">") -> ">

which is invalid html.

>> So will I see the generated html in stderr?
>
> Sigh! Please think a little. I said the output goes to the current stream and
> debug info to stderr. Good old Unix style.

Exactly, so debug info will not show me the generated html which means
trace does not show me what I need.  Trace is useful for pure functions.
Trace is less useful for functions with side-effects because those
side-effects are not captured by trace.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 18:48, Tomas Hlavaty  wrote:
>  would be better written as:
>
>(de p @ (cons 'p (args)))

s/args/rest:

(de p @ (cons 'p (rest)))

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 19:09, Alexander Burger  wrote:
> On Sat, Mar 13, 2021 at 06:48:22PM +0100, Tomas Hlavaty wrote:
>>(de  (Col . Prg)
>>   (prin "")
>>   (run Prg)
>>   (prin "") )
>> 
>> prin has side-effect.
>
> Nonsense! 'prin' *is* the only and desired effect.

see https://en.wikipedia.org/wiki/Side_effect_(computer_science)
for explanation what side-effect means

>> Col is not properly escaped!
>
> How so? It generates
>
>
>
> What kind if escape do you want?

( "\">") -> ">

which is invalid html.

>> So will I see the generated html in stderr?
>
> Sigh! Please think a little. I said the output goes to the current stream and
> debug info to stderr. Good old Unix style.

Exactly, so debug info will not show me the generated html which means
trace does not show me what I need.  Trace is useful for pure functions.
Trace is less useful for functions with side-effects because those
side-effects are not captured by trace.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 07:09:24PM +0100, Alexander Burger wrote:
> > prin has side-effect.
> 
> Nonsense! 'prin' *is* the only and desired effect.
> ...
> This discussion is useless.

Now I think I understand why.

Tomas misunderstood my initial mail. He did not attend PilCon, and seems to
believe we discussed implementation strategies for libraries.

This was not the case.

I talked about binding mechanisms in FEXPRs. The two functions '' and ''
are minimal printing abstractions. An expression like

   (prin "" "Text" "")

can be abstracted as

   (de  Prg
  (prin "")
  (run Prg)
  (prin "") )

   ( (prin "Text"))

and this was used then in nested calls to demonstrate the behavior of 'Prg's.

In a digression, the question about 'pack'ing strings came up, and I felt I had
not fully answered the question, so I clarified it in the above mail.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 06:48:22PM +0100, Tomas Hlavaty wrote:
>(de  (Col . Prg)
>   (prin "")
>   (run Prg)
>   (prin "") )
> 
> prin has side-effect.

Nonsense! 'prin' *is* the only and desired effect.


> Col is not properly escaped!

How so? It generates

   

What kind if escape do you want?



> This example:
> 
>(de  Prg
>   (prin "")
>   (run Prg)
>   (prin "") )
> 
> These functions output the formatted html immediatelly, which is too
> early for reasons I wrote about already.

This is the last time I repeat: It is the PURPOSE! Nothing else is there
which might be "too early".

This discussion is useless.


> So will I see the generated html in stderr?

Sigh! Please think a little. I said the output goes to the current stream and
debug info to stderr. Good old Unix style.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 16:04, Alexander Burger  wrote:
> I don't get your problem with side effects!

in your example:

   (de  (Col . Prg)
  (prin "")
  (run Prg)
  (prin "") )

prin has side-effect.

Col is not properly escaped!

This example:

   (de  Prg
  (prin "")
  (run Prg)
  (prin "") )

These functions output the formatted html immediatelly, which is too
early for reasons I wrote about already.

 would be better written as:

   (de p @ (cons 'p (args)))

This has no side-effects.  It also allows me to postpone serialisation
to a better point in time, when I call a function called html.  Similar
to xml function in picolisp, this html function serializes cons tree
into a stream with html syntax.  This way I never have to care about
escaping and other issues.  Separating p, div etc and html function
opens new possibilities.

> Why do you open new issues like like SVG and PDF generation, when the
> task is to print a page to to a socket?

Because cons trees can brilliantly represent pretty much anything, from
lisp code to html, xml, svg, pdf, docx, odt, der, json etc.  You can
easily construct them, pretty-print them, trace them, transform them and
serialize them.  Picolisp way of implementing  has fundamental flaws
which the cons tree approach solves elegantly.

>> > If you want output with a pre-calculated width, you can still do it in the
>> > FEXPR.
>> 
>> Not pre-calculated.  The bounding box is known after the thing is drawn.
>
> That's trivial. Just calculate while printing then.

That does not work, because with and height are not known yet at that
time!  They are known after the printing is finished, which is too late.

>> If my code outputs html to /tmp/a.html and I trace it, where would the
>> arguments and return values be written to?  Where would the side-effect
>> be written to?
>
> I already explained that tracing goes to stderr.

So will I see the generated html in stderr?

If yes then /tmp/a.html is empty and tracing breaks my program.

If no then stderr will not contain the generated html and tracing is
useless.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 04:04:56PM +0100, Alexander Burger wrote:
> I don't get your problem with side effects!

Anyway, we are completely off-topic now :)

You started with critics about FEXPRs, but never said anything relevant about
them. Your code examples like

   (de  (Str) `(p ,Str))

are EXPRs.

My example of

   (de printWidthAndPrint Prg
  (let ( pWidth   divWidth  prin length)
 (msg (run Prg)) )
  (run Prg) )

is BTW a very good case demonstrating the power of FEXPRs combined with dynamic
binding.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 03:33:23PM +0100, Tomas Hlavaty wrote:
> On Sat 13 Mar 2021 at 15:03, Alexander Burger  wrote:
> I am talking about an example which shows how inconvenient the standard
> picolisp your solution with side-effect is.
> 
> Yet another example, writing out pdf.

I don't get your problem with side effects! Why do you open new issues like like
SVG and PDF generation, when the task is to print a page to to a socket? It was
a minimal example for didactic purposes in PilCon.

So what is the side effect? The printing??? Printing is all we are talking about
here.

And even besides this simple example, I want output of an HTML server as fast as
possible, and the way the PicoLisp server does it is surely optimal. Both from
the speed of page generation as also the simplicity of the HTML functions, and
the readability of the source code (please show me a source code which generates
a report in HTML in a cleaner way than the example of the Sales report in my
last mail!).


> Cons trees and garbage collection are one of the best things about lisp.

Sure. But not an issue here! We want output, not a data structure.


> > If you want output with a pre-calculated width, you can still do it in the
> > FEXPR.
> 
> Not pre-calculated.  The bounding box is known after the thing is drawn.

That's trivial. Just calculate while printing then.


> So optimal means writing to a file is cheaper than consing a cell?  I am
> not convinced.

We NEED the output, but we DON'T need the cell.


> If my code outputs html to /tmp/a.html and I trace it, where would the
> arguments and return values be written to?  Where would the side-effect
> be written to?

I already explained that tracing goes to stderr.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 15:03, Alexander Burger  wrote:
> On Sat, Mar 13, 2021 at 02:09:30PM +0100, Tomas Hlavaty wrote:
>> Avoiding allocations is wrong thing to do for this use-case.  Printing
>> directly is severely inconvenient.  Do you have a neat solution to the
>> svg viewBox problem I wrote about?
>
> You are talking about a different problem domain. Width calculations
> were not an issue in that discussion.

I am talking about an example which shows how inconvenient the standard
picolisp your solution with side-effect is.

Yet another example, writing out pdf.
https://logand.com/sw/emacs-pdf/file/emacs-pdf.el.html#l110 creates cons
tree and implements insert-pdf function to serialize it in the right
format.  One of the issues here are pdf object references, which need to
output "before" being known, making side-effect solution unuseable.

Cons trees and garbage collection are one of the best things about lisp.
Trading allocations for side-effects is a bad trade off.

> If you want output with a pre-calculated width, you can still do it in the
> FEXPR.

Not pre-calculated.  The bounding box is known after the thing is drawn.

> But if you insist, just switch function pointers to do width
> calculation instead of printing. Given our example
>
>(de  Prg
>   (prin "")
>   (run Prg)
>   (prin "") )
>
>(de  (Col . Prg)
>   (prin "")
>   (run Prg)
>   (prin "") )
>
> we add a width-calculating function for each tag:
>
>(de pWidth Prg
>   (+ 3 (run Prg) 4) )
>
>(de divWidth (Col . Prg)
>   (+ 12 (length Col) 2 (run Prg) 6) )

Why separate and duplicate functions.  What if the drawing is not so
trivial?  This is not a good solution.  Generally, I want to update *W
and *H during arbitrarily complex drawing without all those extra
functions you suggest.

> Note that this again does not produce a single cell. Optimal.

So optimal means writing to a file is cheaper than consing a cell?  I am
not convinced.

> I do not understand. We are talking about the 'trace' of function calls for
> debugging, showing whe called function, and its arguments, then recursively
> indented the trace of sub-function calls, and then the return of the function
> and its value, right? Works fine with FEXPRs.
>
> 'trace' prints to stderr, so it does not interfer with other printing.

If my code outputs html to /tmp/a.html and I trace it, where would the
arguments and return values be written to?  Where would the side-effect
be written to?

>> In reality it is misoptimisation because it optimizes for irrelevant
>> advantage of no allocation but it severely criples what one can do.
>
> No. It cripples nothing. It is the most powerful concept. You can
> express anything with it.

I am not disputing that FEXPRs are the most powerful concept.

I am saying that using it for html output is using wrong tool for the
job.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 03:13:13PM +0100, Tomas Hlavaty wrote:
> Another example:  you have to be careful not to get an error in the
> middle of the side-effect otherwise you get partial output.

Hmm, sure, as in all kinds of programming. How does that relate to FEXPRs and/or
tracing?

Or do I misunderstand something? What do you mean with side-effect? The printing
to the stream?

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 14:09, Tomas Hlavaty  wrote:
>> But the FEXPR solution explained at PilCon allocates no new cells at all. It
>> prints directly.
>
> Avoiding allocations is wrong thing to do for this use-case.  Printing
> directly is severely inconvenient.  Do you have a neat solution to the
> svg viewBox problem I wrote about?

Another example:  you have to be careful not to get an error in the
middle of the side-effect otherwise you get partial output.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 02:09:30PM +0100, Tomas Hlavaty wrote:
> Avoiding allocations is wrong thing to do for this use-case.  Printing
> directly is severely inconvenient.  Do you have a neat solution to the
> svg viewBox problem I wrote about?

You are talking about a different problem domain. Width calculations were not an
issue in that discussion.

If you want output with a pre-calculated width, you can still do it in the
FEXPR. No need to build a separate "tree", the FEXPR body *is* one already.


But if you insist, just switch function pointers to do width calculation instead
of printing. Given our example

   (de  Prg
  (prin "")
  (run Prg)
  (prin "") )

   (de  (Col . Prg)
  (prin "")
  (run Prg)
  (prin "") )

we add a width-calculating function for each tag:

   (de pWidth Prg
  (+ 3 (run Prg) 4) )

   (de divWidth (Col . Prg)
  (+ 12 (length Col) 2 (run Prg) 6) )

For demonstration, say we want first print the width to stderr, and then the
HTML to the current stream

   (de printWidthAndPrint Prg
  (let ( pWidth   divWidth  prin length)
 (msg (run Prg)) )
  (run Prg) )

Test:

   (printWidthAndPrint
  ( "red" ( (prin "Text"))) )

Output:
   34
   Text


Note that this again does not produce a single cell. Optimal.



> > Also, needing two separate functions for every HTML function is ugly, 
> > tedious
> > and error-prone.
> 
> Not sure what do you mean.

I meant '' and 'p' in your example.


> > Side-effects like printing? No problem! In PicoLisp, you can trace,
> > break and single-step FEXPRs (with or without side-effects) like any
> > other function (unlike macros in e.g. Common Lisp).
> 
> You can trace it but the trace does not show the side-effect thus making
> trace useless.

I do not understand. We are talking about the 'trace' of function calls for
debugging, showing whe called function, and its arguments, then recursively
indented the trace of sub-function calls, and then the return of the function
and its value, right? Works fine with FEXPRs.

'trace' prints to stderr, so it does not interfer with other printing.


> >> Using FEXPRs for html output is misoptimisation.
> >
> > Wrong.
> 
> In reality it is misoptimisation because it optimizes for irrelevant
> advantage of no allocation but it severely criples what one can do.

No. It cripples nothing. It is the most powerful concept. You can express
anything with it.

You can see this from the fact that *all* primitives in the PicoLisp interpreter
itself are FEXPRs (FSUBRs to be exact).

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 01:57:58PM +0100, Alexander Burger wrote:
> For such a simple example it works. But keep in mind that typically 'P'
> is a large program, with lots of 'if's, 'while's  and arbitrarily deeply
> nested other HTML tags.

For a short real-world example, take the "Sales" report from the PicoLisp Demo
application (https://software-lab.de/demoApp.tgz).

I include the source below. Functions like 'menu', '', 'form', '',
'csv', '', '' and '' are FEXPRs. The report runs through,
generates the page, and gets garbage-collected.

☺/ A!ex

# 08oct20 Software Lab. Alexander Burger

(must "Sales" Report)

(menu ,"Sales"
   ( NIL ,"Sales")
   (form NIL
  ( "-.-"
 ,"Date" NIL
 (prog
(gui '(+Var +DateField) '*SalFrom 10)
(prin " - ")
(gui '(+Var +DateField) '*SalTill 10) )
 ,"Customer" (choCuSu 0)
 (gui '(+Var +Obj +TextField) '*SalCus '(nm +CuSu) 30) )
  (--)
  (gui '(+ShowButton) NIL
 '(csv ,"Sales"
( 'chart NIL
   (
  (quote
 (align)
 (NIL ,"Date")
 (NIL ,"Customer")
 NIL
 (NIL ,"Zip")
 (NIL ,"City")
 (align ,"Total") ) )
   (catch NIL
  (let Sum 0
 (pilog
(quote
   @Rng (cons *SalFrom (or *SalTill T))
   @Cus *SalCus
   (select (@Ord)
  ((dat +Ord @Rng) (cus +Ord @Cus))
  (range @Rng @Ord dat)
  (same @Cus @Ord cus) ) )
(with @Ord
   (let N (sum> This)
  ( (alternating)
 (<+> (: nr) This)
 (<+> (datStr (: dat)) This)
 (<+> (: cus nm) (: cus))
 (<+> (: cus nm2))
 (<+> (: cus plz))
 (<+> (: cus ort))
 (<-> (money N)) )
  (inc 'Sum N) ) )
(at (0 . 1) (or (flush) (throw))) )
 ( 'nil
( ,"Total") - - - - -
( (prin (money Sum))) ) ) ) ) ) ) ) )

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 13:33, Alexander Burger  wrote:
> It does. Just the syntax is different:
>
>(de  (@Str) (fill '(p @Str)))
>
> This also creates just 2 cells.

True, I forgot about fill.

> But the FEXPR solution explained at PilCon allocates no new cells at all. It
> prints directly.

Avoiding allocations is wrong thing to do for this use-case.  Printing
directly is severely inconvenient.  Do you have a neat solution to the
svg viewBox problem I wrote about?

> Also, needing two separate functions for every HTML function is ugly, tedious
> and error-prone.

Not sure what do you mean.  There would be only one function, lets call
it html which takes a cons tree and prints it using html syntax.
Opposite of tedious and error-prone.  Similar to the xml function in
picolisp.

> Side-effects like printing? No problem! In PicoLisp, you can trace,
> break and single-step FEXPRs (with or without side-effects) like any
> other function (unlike macros in e.g. Common Lisp).

You can trace it but the trace does not show the side-effect thus making
trace useless.

>> Using FEXPRs for html output is misoptimisation.
>
> Wrong.

In reality it is misoptimisation because it optimizes for irrelevant
advantage of no allocation but it severely criples what one can do.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
On Sat, Mar 13, 2021 at 01:30:27PM +0100, pd wrote:
> 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

Yes. (And strings are always immutable in PicoLisp anyway)


> : (setq X ( hallo))
> -> ""
> : X
> -> ""
> 
> 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

Right. The examples were for output only.


> 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 "") (run P) (prin "") (pack "" (run P) "") )

This is a bit problematic, because the body in P is executed twice. Not only is
this slower, but may create havoc because in a typical GUI program *all* logic
happens in these bodies. This logic would be executed several times, doing lots
of unexpecyed things. Better then:

   (de pp P
  (prin (pack "" (run P) "")) )

'prin' returns the argument string.


> 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")
> 
> ABC
> DEF
> GHI

For such a simple example it works. But keep in mind that typically 'P'
is a large program, with lots of 'if's, 'while's  and arbitrarily deeply
nested other HTML tags.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread Alexander Burger
Hi Tomas,

> > While this would surely work, I answered that it is a big overhead to
> > generate the whole page as strings just to print them.
> 
> Packing strings is not a good idea.

Right.


> It would be much better to create a cons tree instead, something like:
> 
> (de  (Str) `(p ,Str))
> 
> and have a separate function to print the cons tree into a stream
> formatted as html.  Notice how little memory such  function allocates
> -- 2 cons cells -- compared to the version with pack.
> 
> Unfortunatelly, picolisp does not have a convenient way of creating cons
> tree templates with backquote.

It does. Just the syntax is different:

   (de  (@Str) (fill '(p @Str)))

This also creates just 2 cells.


But the FEXPR solution explained at PilCon allocates no new cells at all. It
prints directly.

Also, needing two separate functions for every HTML function is ugly, tedious
and error-prone.



> > 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.
> 
> This also nicely shows how the power of FEXPRs can easily lead one
> astray.

Right. FEXPRs are dangerous when used the wrong way.

This was what the last PilCon was all about ("hazards"). But I explained also
how these hazards disappear when you follow 2 or 3 simple rules in writing
libraries.


> Another drawback is that side-effects break tracing and make debugging
> much harder.

Side-effects like printing? No problem! In PicoLisp, you can trace, break and
single-step FEXPRs (with or without side-effects) like any other function
(unlike macros in e.g. Common Lisp).


> Using FEXPRs for html output is misoptimisation.

Wrong.

☺/ A!ex

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs / PilCon

2021-03-13 Thread pd
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 (prin "") (run P) (prin ""))
-> 
: ( hallo)
-> ""
: (length ( hallo))
-> 4
: (setq X ( hallo))
-> ""
: X
-> ""

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 "") (run P) (prin "") (pack "" (run P) "") )

: (pp (+ 2 3))
-> "5"
: (pp 2)
-> "2"
: (pp (print 2))
22-> "2"
: (pp ( (prin "hallo")))
hallohallo-> ""
: (pp (pp (prin "hallo")))
hallohallohallohallo-> "hallo"
: ( ( (print "hallo")))
"hallo"-> ""

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 
showed as an example by Alex.

Given:

: (de p (t) (pack "" t ""))
: (de d (c t) (pack "" t ""))

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")

ABC
DEF
GHI






El sáb., 13 mar. 2021 8:32, Alexander Burger  escribió:

> Hi all,
>
> at PilCon three days ago we discussed about FEXPRs like
>
>(de  Prg
>   (prin "")
>   (run Prg)
>   (prin "") )
>
>(de  (Col . Prg)
>   (prin "")
>   (run Prg)
>   (prin "") )
>
> which can be called as
>
>( "red" ( (prin "Text")))
>
> giving such output:
>
>Text
>
>
> One question that came up was why FEXPRs could not be replaced with normal
> functions (EXPRs), simply 'pack'ing strings:
>
>(de  (Str)
>   (pack "" Str "") )
>
>(de  (Col Str)
>   (pack
>  "  Col
>  "\">"
>  Str
>  "" ) )
>
>: ( "red" ( "Text"))
>-> "Text"
>
> 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:
>
>( "red"
>   (for S '("ABC" "DEF" "GHI")
>  (prinl)
>  ( (prin S)) )
>   (prinl) )
>
>
>ABC
>DEF
>GHI
>
>
> This cannot be done with EXPRs.
>
> ☺/ A!ex
>
> --
> UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe
>
>


Re: FEXPRs / PilCon

2021-03-13 Thread Tomas Hlavaty
On Sat 13 Mar 2021 at 08:27, Alexander Burger  wrote:
>(de  Prg
>   (prin "")
>   (run Prg)
>   (prin "") )
>
> [...]
>
> One question that came up was why FEXPRs could not be replaced with normal
> functions (EXPRs), simply 'pack'ing strings:
>
>(de  (Str)
>   (pack "" Str "") )
>
> [...]
>
> While this would surely work, I answered that it is a big overhead to
> generate the whole page as strings just to print them.

Packing strings is not a good idea.

It would be much better to create a cons tree instead, something like:

(de  (Str) `(p ,Str))

and have a separate function to print the cons tree into a stream
formatted as html.  Notice how little memory such  function allocates
-- 2 cons cells -- compared to the version with pack.

Unfortunatelly, picolisp does not have a convenient way of creating cons
tree templates with backquote.

> 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.

This also nicely shows how the power of FEXPRs can easily lead one
astray.

For example:

(let (*X NIL *Y NIL)
   (draw-svg-thing-and-determine-width-and-height)
   `(svg (@viewBox "0 0 " ,*W " " ,*H) ...))

The above will not work when  is not pure and does side-effect write.
One has to draw it twice, once to /dev/null to determine width and
height and then second time inside the three dots.

When draw-svg-thing-and-determine-width-and-height is pure and returns
cons tree, it does not need to be called second time but the return
value can be used inside the three dots.  If consing and garbage
collecting a cons tree is cheaper than calling
draw-svg-thing-and-determine-width-and-height once again, it is already
a win.

Another drawback is that side-effects break tracing and make debugging
much harder.

Using FEXPRs for html output is misoptimisation.

-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe



Re: FEXPRs

2012-05-23 Thread Alexander Burger
Hi Tomas,

  to keep in mind that in typical PicoLisp code, almost *everything* runs
  in a FEXPR. Take a simple HTML form like
 
  Without FEXPRS, this example would look like
 
 (action
'(html 0 Form @lib.css NIL
   '(h2 NIL Title)
   '(div 'cls
  '(form NIL
 '(gui '(+TextField) 10 Text)
 '(gui '(+NumField) 10 Number)
 '(gui '(+Button) Action
''(doSomething) ) ) ) ) )
 
 Not necessarily, you could use macros if you didn't want to write the
 quotes.

Really? I don't think I would want to do that.

How much overhead would this involve? The above expression (without the
added quotes) has a size of 41 cells. Now look at the called functions
and their current sizes

   html   79 cells
   h2   11 cells
   div  11 cells
   form  150 cells

Does this mean that the above expression would expand to about 292
cells? Building such huge structures, just to execute them and then
throw them away? Expanding those macros would take much longer than the
direct functional execution (not to talk about compilation).



 An example, the following 'off' works exactly like in PicoLisp,
 i.e. removes the need for quoting:
 
 (defmacro off (rest vars)
   `(setq ,@(loop for x in vars appending `(,x nil

Besides for the overhead of expanding this every time 'off' appears in
the code, compare that to a clean FEXPR definition:

   (de off Lst
  (mapc set Lst) )

This confirms what I said in my last mail, that in CL things usually
looks bigger and uglier ;-)



  Macros make only sense if you compile the code
 
 Yes.  On the other hand, fexprs only make sense if you don't compile the
 code:-)

True. Again, same as I said in my last mail: The compiler imposes so
many restrictions upon Common Lisp, and makes it such a heavy and
inflexible dinosaur.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe


Re: FEXPRs

2012-05-22 Thread Tomas Hlavaty
Hi Alex,

 FEXPRs a not so very important. They just allow you to avoid having to
 quote everything.

 I don't understand all the fuss that is made about them. It is perhaps
 because they are more powerful than the holy macros.

If you don't have a compiler, then it doesn't matter.  However, they
make compilation impossible.

For example, you wrote a compiler from picolisp64 assembly to gas
assembly.  The compiler is a function that transforms input to output,
which are quoted arguments.  Now you could not do the compilation if
the values were not quoted, i.e. the compilation process would depend on
some user input at the point where he's already using the result of the
compilation.  Similar problem arises when trying to compile 'if', but in
that case, there is a finite set of choises that the compiler can list
them and delay the actual choosing one of them to run-time.

 Right. As I said above, they are mainly a cosmetic issue. But you have
 to keep in mind that in typical PicoLisp code, almost *everything* runs
 in a FEXPR. Take a simple HTML form like

 Without FEXPRS, this example would look like

(action
   '(html 0 Form @lib.css NIL
  '(h2 NIL Title)
  '(div 'cls
 '(form NIL
'(gui '(+TextField) 10 Text)
'(gui '(+NumField) 10 Number)
'(gui '(+Button) Action
   ''(doSomething) ) ) ) ) )

Not necessarily, you could use macros if you didn't want to write the
quotes.  An example, the following 'off' works exactly like in PicoLisp,
i.e. removes the need for quoting:

(defmacro off (rest vars)
  `(setq ,@(loop for x in vars appending `(,x nil

Not everything you think is a fexpr is needs to be _fundamentally_
fexpr.  However, for some things, e.g. 'if', macros are not expressive
enough.  Because 'if' needs an input at runtime so macros themselves are
not general enough.

 Macros make only sense if you compile the code

Yes.  On the other hand, fexprs only make sense if you don't compile the
code:-)

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe