I am creating a simple chatterbot program like ELIZA.
I'm taking questions from the terminal and sending reply with dialog, but my program takes only the first input and repeats.
For example, when I run my script the output may be something like this:
[Eliza]: Hi, I'm a psychotherapist. What is your name?
user Input: hello my name is adam.
[Eliza]: hello adam, how are you?
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam
[Eliza]: your name is adam
And it repeats endlessly.
I don't know where I am doing wrong. How can I get my program to read the next line from the keyboard?
sub hello {
print "[Eliza]: Hi, I'm a psychotherapist. What is your name? \n";
}
sub getPatientName {
my ($reply) = @_;
my @responses = ( "my name is", "i'm", "i am", "my name's" );
foreach my $response ( @responses ) {
if ( lc($reply) =~ /$response/ ) {
return "$'";
}
}
return lc($reply);
}
sub makeQuestion {
my ($patient) = @_;
my %reflections = (
"am" => "are",
"was" => "were",
"i" => "you",
"i'd" => "you would",
"i've" => "you have",
"i'll" => "you will",
"my" => "your",
"are" => "am",
"you've"=> "I have",
"you'll"=> "I will",
"your" => "my",
"yours" => "mine",
"you" => "me",
"me" => "you"
);
if ( $count == 0 ) {
$patientName = getPatientName($patient);
$count += 1;
print "Hello $patientName , How are you? \n";
}
my @toBes = keys %reflections;
foreach my $toBe (@toBes) {
if ($patient =~/$toBe/) {
$patient=~ s/$toBe/$reflections{$toBe}/i;
print "$patient? \n";
}
}
}
sub eliza {
hello();
my $answer = <STDIN>;
while ($answer) {
chomp $answer;
#remove . ! ;
$answer =~ s/[.!,;]/ /;
makeQuestion($answer);
}
}
eliza();
Your while
loop never reads input. The $answer
got STDIN
before the loop and presumably has a string, that evaluates true in the while
condition. The regex in the loop cannot change that.
Thus not only is no new input assigned to $answer
, but after the first iteration nothing at all changes in the loop. So it keeps running forever, printing the question based on the same $answer
.
You need
while (my $answer = <STDIN>) {
chomp $answer;
# ...
}
instead.
Every time the condition of while (...)
is evaluated the new input is read via <STDIN>
and is assigned to $answer
. Then each new question uses the new $answer
. Note how a variable may be declared inside the while
condition so to exist only inside the loop body (and in the condition after its declaration). This is a nice way to keep its scope restricted to where it is needed, inside the loop.
The filehandle read <...>
returns undef
when it gets EOF
(or on error) and the loop terminates. See I/O Operators in perlop. A user at the terminal can normally achieve this by Ctrl-d
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With