Re: Data structure design again

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
Hi Richard,

I'm afraid I misunderstood your example, also because you thought
someone `might freak out'.   As an internal representation I'm
completely happy with it.

Wondering what goes wrong with term-size computation. I guess this is
something like (being lazy using a findall):

term_size(T, S) :-
	compound(T), !,
	findall(AS, (arg(_,T,A),term_size(A,AS)), L),
	sum_list(L, S1),
	S is 2+S1.
term_size(T, S) :-
	string(T), !,
	string_length(T, L),
	S is 3+(L+7)//8.	% 64-bit machine
term_size(T, 4) :-
	float(T), !.
term_size(T, S) :-
	integer(T), !,
	<got to puzzle a bit here>.
term_size(T, 1).		% all simple atomic stuff and vars.

	Cheers --- Jan


On 12/12/2013 01:59 AM, [email protected] wrote:
>> 2013/12/11 Jan Wielemaker <[email protected]>
>>
>>> On 12/11/2013 05:52 AM, Richard A. O'Keefe wrote:
>>>
>>>> Someone is bound to freak out at the idea of representing
>>>>
>>>
>>> +1
>>>
>>>
>>>  [:x | x + 1] as block(lambda([x],[],call(+,var(x),[integer(1)])))
>>>> but I've tried it without the outer discriminator and it makes
>>>> writing the code so error prone it's not worth it.  In any case,
>>>>
>>>
>>> Languages are in my opinion always a compromise between the human and
>>> the machine. Humans like something concise and intuitive.
>
> But we are not designing a language for people!
> Smalltalk was designed long ago and I'm not trying to change it.
>
> This is the *ABSTRACT SYNTAX TREE* we are talking about,
> *NOT* a source language for people to enter.
>
>>> Having to write
>>> "integer(1)" is a lot of work as well as hard to read as you have to
>>> process all this text and brackets.
>
> "Having to write integer(1)" is a gross misunderstanding.
> THIS IS THE OUTPUT OF A PARSER, not the input to it.
>
>> It also makes it hard to give a
>>> good layout to larger structures.
>
> Not in the least.  Remember, THIS IS AN INTERNAL *PROCESSING*
> FORMAT, NOT SOMETHING PEOPLE ACTUALLY READ OR WRITE.
>
> portray(nil) :-
>     write('nil').
> portray(false) :-
>     write('false').
> portray(true) :-
>     write('true').
> portray(integer(I)) :-
>     write(I).
> portray(float(F)) :-
>     write(F).
> portray(symbol(S)) :-
>     write('#'), write(S).
> portray(string(S)) :-
>     write('"'), write(S), write('"').
> portray(array(_)) :-
>     write('#(...)').
> portray(bytes(_)) :-
>     write('#[...]').
> portray(const(X)) :-
>     print(X).
> portray(var(V)) :-
>     write(V).
> portray(if(E,B1,B2)) :-
>     write('('),
>     print(E),
>     write(' ifTrue: '), print(B1),
>     write(' ifFalse: '), print(B2),
>     write(')').
> portray(while(B1,E,B2)) :-
>     write('('),
>     B1 = lambda(Vs,Es,Ef),
>     append(Es, [Ef], El),
>     print(lambda(Vs,El,E)),
>     write(' whileTrue: '),
>     print(B2),
>     write(')').
> portray(let(B,[])) :- !,
>     write('('),
>     print(B), write(' value'),
>     write(')').
> portray(let(B,Es)) :-
>     write('('),
>     print(B),
>     (   member(E, Es),
>         write(' value: '), print(E),
>         fail ; true
>     ),
>     write(')').
> portray(call(F,E,[])) :- !,
>     write('('),
>     print(E),
>     write(' '),
>     write(F),
>     write(')').
> portray(call(F,E,[E2])) :- !,
>     write('('),
>     print(E),
>     write(' '), write(F), write(' '),
>     print(E2),
>     write(')').
> portray(call(F,E,Es)) :-
>     write('('),
>     print(E),
>     write('perform: #'), write(F),
>     (   member(E, Es),
>         write(' with: '), print(E),
>         fail ; true
>     ),
>     write(')').
> portray(block(B)) :-
>     print(B).
> portray(lambda(Vs,Es,E)) :-
>     write('['),
>     (   member(V, Vs),
>         write(':'), write(V), write(' '),
>         fail ; true
>     ),
>     (   Vs == [] -> true
>     ;   write('| ')
>     ),
>     (   member(S, Es),
>         print(S), write('. '),
>         fail ; true
>     ),
>     print(E),
>     write(']').
>
> It should be obvious how to combine that with the pretty-printer
> of your choice.  (Mind you, the documentation of pretty-printing
> libraries is generally so bad that it's hard to plug *anything*
> into them.)
>
> Load that into SWI Prolog, and
>
> ?- E = block(lambda([x],[],call(+,var(x),[integer(1)]))), print(E).
> [:x | (x + 1)]
>
> Remember the mantra:
>
>     AN I/O FORMAT IS NOT A PROCESSING FORMAT IS NOT AN I/O FORMAT.
>
> Processing formats *shouldn't* be designed to let human beings
> read and write large amounts of the stuff because human beings
> *shouldn't* be reading and writing large amounts of the stuff.
> You use parsers to convert human-oriented stuff into processing
> formats (source code => abstract syntax trees) and unparsers
> to convert processing formats to human-oriented stuff.
>
> The cuts in the code above exist *only* because of non-uniform
> quirks in Smalltalk syntax.  (Given a valid input, the output
> here is valid Smalltalk.)  For example, the syntax of blocks is
>
>     block --> '[' {statement '.'}* [expression] ']'
>             | '[' (':' argument)+ '|' {statement '.'}* [expression] ']'
>
> where the '|' must be present if and only if there is at least one
> argument.  The *processing* format does not include that weirdness,
> making it much easier to *process*.
>
>
>
>>> Well, we already knew we disagree on these things when discussing mark
>>> down ...
>
> There was an interesting discussion of Markdown in the blog
> of the science fiction author Charles Stross.  The conclusion is
> that Markdown is *way* better for writing than Microsoft Word
> but there are *way* too many incompatible dialects of it.
>
>>> All I want to achieve is to reduce the number of cases where we
>>> _force_ people to use this verbose syntax to define their data or DSL
>>> representation.
>
> You are once again confusing an *I/O FORMAT* (what people read and
> write) with a *PROCESSING FORMAT*.
>
> I am *ONLY* talking about *PROCESSING* formats.
>
>>>  the *proportional* overhead is slight.
>>>>
>>>
>>> For atomic data about a factor 3.
>
> Remember, I was *specifically* talking about the example
> block(lambda([x],[],call(+,var(x),[integer(1)]))),
> which is an unusually small block.
>
> Unfortunately, the code I wrote for determining the size of a term
> has been broken by SWI 7.  However, the code I wrote for SWI  tells
> me that
>
>     FOR THE EXAMPLE I SPECIFICALLY REFERRED TO,
>     wrapping block(...) around the lambda(...) term
>     increased its size by
>
>         TEN PERCENT.
>
> As for atomic data, the parser caches these things,
> so that all occurrences of integer(1) are the *same* term,
> so the space overhead is 3*0 for a total of 0.
>
>> The leafs often atomic and that is
>>> where most of the space goes.
>
> Which is why it pays for the parser to cache them so
> that there is no duplication.  As it happens, the parser
> caches
>  - all numbers
>  - all strings
>  - all symbols
> so the amortised space overhead is *ZERO*.
>
> Unfortunately it is impossible to express this in the type language.
>
> Before you say "but oh, people aren't going to factor out all
> occurrences of integer(1)", remember that I am talking specifically
> and only about *PROCESSING* formats.
>
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.