[comp.lang.prolog] simple question

wayne@cs.odu.edu (C Wayne Huling) (03/20/91)

I am attempting to build a simple list, but can't seem to get it to work.
Could someone please help me with this problem?

writeln(S):-
	write(S),
	nl.

query:-
	writeln('Enter the verticies'),
	querytop(L),
	write(L).

querytop(L):-
	read(A),
	query(A,L).

query(end,_):-!.

query(A,L):- 
	L=[A|L],
	writeln('Another one...'),
	querytop(L).



I read the stuff, but it isn't being put in the list, it stops after entering
2 numbers.  Why isn't it working? 

Bill.Viggers@comp.vuw.ac.nz (Bill Viggers) (03/21/91)

	For starters its easiest if you give Prolog functions, names that
	describe what they do.  Personally I also dislike
	have two functions with the same name and different arity.

	Thus your program could be re-written as:

writeln(S):-
	write(S),
	nl.

makelist:-
	writeln('Enter the verticies'),
	getlist(List),
	write(List).

getlist(L):-
	read(Item),
	addtolist(Item,List).

addtolist(end,_):-!.

addtolist(Item,List):- 
	List=[Item|List],
	writeln('Another one...'),
	getlist(List).


Now it is clearer what is happening.
	The first time though an item is got, and the list is set equal to it.
	The second time though, another item is got, and then the line:

	List=[Item|List],

	is executed, and it will fail as List is not equal to the new item 
	followed by the previous item.

	An example:
		| ?-makelist.
		Enter the verticies
		|: 3.
		Another one...
		|: 4.
		
		no

	We can se getlist is called, it reads 3, and calls addtolist
	addtolist sets List equal to [3], then sends that list on to another
	call to getlist.  This time getlist reads a 4, and sends that, along
	with the current list to addtolist.  Addtolist trys to set
	[3] = [4|3]. 
	Which it fails to do.

	A solution then could be:


writeln(String):-
	write(String),
	nl.

makelist:-
	writeln('Enter the verticies'),
	getlist(List),
	write(List).

getlist(Thelist):-
	read(Item),
	addtolist(Item,_,Thelist).

addtolist(end,_,end):-!.

addtolist(Item,List,Thelist):- 
	Thelist=[Item|List],
	writeln('Another one...'),
	getlist(List).


	This returns a list, with the last item being an 'end'
	eg:


	| ?- makelist.
	Enter the verticies
	|: bill.
	Another one...
	|: viggers.
	Another one...
	|: end.
	[bill,viggers|end]
	yes


	I hope this helps.
 
B.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/21/91)

In article <1991Mar20.225013.21372@comp.vuw.ac.nz>, Bill.Viggers@comp.vuw.ac.nz (Bill Viggers) writes:
> 	For starters its easiest if you give Prolog functions, names that
> 	describe what they do.  Personally I also dislike
> 	have two functions with the same name and different arity.

Prolog has no functions, only predicates.
I very much *like* using the same symbol at different arities,
as it reduces the need for inventing names whose only raison d'etre
is to be different.

There are some improvements that can be made to Viggers' version.

> writeln(String):-
> 	write(String),
> 	nl.

Why "String"?  The argument can be *any* term, and in the actual
program it isn't any kind of string, it's an atom.  Better:

	writeln(Message) :-
		write(Message),
		nl.

> makelist:-
> 	writeln('Enter the verticies'),
> 	getlist(List),
> 	write(List).

When an identifier is made out of several words, it is a good idea
to make it clear to the reader where the word divisions are
(contrast	lighthouse_keeper
		light_housekeeper).
It is also a good idea to spell everything right, including comments,
and most especially text which is displayed to users.  'vertexes'
would do at a pinch, but it's 'verticies'.  It is far from clear to
me why writeln/1 is used here.  It would be nice to use a message
like this as a prompt.

The predicate doesn't make a list.  It reads it in and then writes it.
What's more, "list" is rather too vague to be useful.  The ISO crowd
even used "list" with the specific meaning "list of characters".  If
this is a list of vertices, call it Vertices.

read_then_write_vertices :-
	writeln('Please enter the vertices.'),
	read_vertices(Vertices),
	writeln(Vertices).

> getlist(Thelist):-
> 	read(Item),
> 	addtolist(Item,_,Thelist).
> 
> addtolist(end,_,end):-!.
> 
> addtolist(Item,List,Thelist):- 
> 	Thelist=[Item|List],
> 	writeln('Another one...'),
> 	getlist(List).

This *HAS* to be a joke.  Why end a list with 'end'?  Why not end it
with [], which is what lists usually end with?

read_vertices(Vertices) :-
	write('Next vertex: '),
	read(Vertex),
	read_vertices(Vertex, Vertices).

read_vertices(end, Vertices) :- !,
	Vertices = [].
read_vertices(Vertex, [Vertex|Vertices]) :-
	read_vertices(Vertices).

% sicstus
SICStus 0.7 #1: Tue Sep 4 21:39:16 EST 1990
| ?- [foo].
{consulting /r/staff/ok/foo...}
{/r/staff/ok/foo consulted, 116 msec 1480 bytes}
yes

| ?- read_then_write_vertices.
Please enter the vertices.
Next vertex: tom.
Next vertex: tom.
Next vertex: the.
Next vertex: pipers.
Next vertex: son.
Next vertex: end.
[tom,tom,the,pipers,son]
yes

One more point:  it might be even better to use 'end_of_file'
as the end marker, then the user can just use his <EOF> to end
the input, instead of having to know what the special magic marker
is.  If you _don't_ do that, then you really should remind the user
what to type when s/he wants to stop:

read_then_write_vertices :-
	writeln('Please enter the vertices.  Use 'end' to stop.'),
	read_vertices(Vertices),
	writeln(Vertices).

-- 
Seen from an MVS perspective, UNIX and MS-DOS are hard to tell apart.

felkl@aste16.Berkeley.EDU (Feliks Kluzniak) (03/21/91)

The following seems even simpler:


writeln( String ):-
	write( String ),
	nl.

make_list:-
	writeln( 'Enter the vertices' ),      % spelling!
        read( Item ),
	get_list( Item, List ),
	write( List ).


get_list( Item, [ Item | RestOfItems ] ):-
        Item \== end,
        writeln( 'Another one (or end)...' ),
	read( NextItem ),
	get_list( NextItem, RestOfItems ).

get_list( end, [] ).


| ?- make_list.
Enter the vertices
|: one.
Another one (or end)...
|: two.
Another one (or end)...
|: V.
Another one (or end)...
|: end.
[one,two,_141]
yes


-- F.

Bill.Viggers@comp.vuw.ac.nz (Bill Viggers) (03/22/91)

In article <5021@goanna.cs.rmit.oz.au>, ok@goanna.cs.rmit.oz.au (Richard
A. O'Keefe) writes:

|> In article <1991Mar20.225013.21372@comp.vuw.ac.nz>,
|> Bill.Viggers@comp.vuw.ac.nz (Bill Viggers) writes:
|> > 	For starters its easiest if you give Prolog functions, names that
|> > 	describe what they do.  Personally I also dislike
|> > 	have two functions with the same name and different arity.
|> 
|> Prolog has no functions, only predicates.
|> I very much *like* using the same symbol at different arities,
|> as it reduces the need for inventing names whose only raison d'etre
|> is to be different.


	You have me on the predicates, but I find having predicates with the same
	name and different arity hard to locate when I'm looking though the 
	program, so I like to give them different names, I guess thats a
	matter of personal preference.

|> 
|> This *HAS* to be a joke.  Why end a list with 'end'?  Why not end it
|> with [], which is what lists usually end with?
|> 

	I finished the list with 'end' as thats how the origional poster ended 
	his list. I assume there is a reason why he wanted it this way.

	On everything else, I stand corrected.

B.