Following is my knowledge base:
parent(claudia, taiane).
parent(wl, cris).
parent(cris, jim).
parent(cris, pedro).
man(jim).
man(pedro).
man(w).
man(wl).
woman(taiane).
woman(claudia).
woman(cris).
When my main has just one print:
main:-
man(M),
print(M), nl,
fail.
main:- halt.
when I execute it with swipl -q -s exercise-family-tree.pl -g main I get nonduplicated results (all good).
On the other hand, when I query more in my main and have print two times with two different variables as its arguments in my main:
main:-
%which women have both a father and a son in the database?
woman(X), parent(X, S), parent(F, X), man(F), man(S), print(X), nl,
man(M),
print(M), nl,
fail.
main:- halt.
than the results get duplicated. Why does my code duplicate all the answers in the second case?
The issue is different from the one I raised earlier. Please let any interactive solutions that involve REPL be outside of the scope of this question.
than the results get duplicated. Why does my code duplicate all the answers in the second case?
I don't think your problem is anything to do with the top level or way you're running it from the command line, it's that you don't really understand Prolog search, choice points and backtracking and have written a nested loop which prints the same results twice.
The first code acts like (pseudocode):
for M in [jim, pedro, w, wl]:
print(M)
The second code acts like a nested loop:
for _Child in [jim, pedro]:
print(chris) % NB: same 'chris'
% for both choices of _Child
for M in [jim, pedro, w, wl]:
print(M)
In more detail, the first code with man(M), print(M), nl, fail runs like this:
man(jim), print(jim), fail, % backtrack to man(M)
man(pedro), print(pedro), fail, % backtrack to man(M)
man(w), print(w), fail, % backtrack to man(M)
man(wl), print(wl), fail. % backtrack to man(M)
% no more man(M) choices
The second case, this code:
woman(X), parent(X, S), parent(F, X), man(F), man(S), print(X), nl,
man(M),
print(M), nl,
fail.
runs like this:
woman(taiane), parent(taiane, ???) % implicit fail
woman(claudia), parent(claudia, ???) % implicit fail
woman(chris),parent(chris, jim),parent(wl, chris),man(wl),man(jim),print(chris)
% ~~~
% found a solution, now go forward through the man(M) code:
man(jim), print(jim), fail, % backtrack to man(M)
man(pedro), print(pedro), fail, % backtrack to man(M)
man(w), print(w), fail, % backtrack to man(M)
man(wl), print(wl), fail, % backtrack to man(M)
% no more man(M) choices, now the last choicepoint was
% at parent(chris, S) which had choice S=jim or S=pedro.
% Redo that:
woman(chris),parent(chris, pedro),parent(wl, chris),man(wl),man(jim),print(chris)
% ~~~~~
% found a solution, now go forward through the man(M) code:
man(jim), print(jim), fail, % backtrack to man(M)
man(pedro), print(pedro), fail, % backtrack to man(M)
man(w), print(w), fail, % backtrack to man(M)
man(wl), print(wl), fail. % backtrack to man(M)
% no more man(M) choices, now parent(chris, S) has
% no more choices, so end.
So you make two different choices for S from [jim,pedro] by X=chris, parent(X, S) but do not report them, and only report the other choices, for X and M, which are the same in both cases, so it looks like duplication.
Your problem is not where you think it is. First, let me show you how to run a program from the command line. This one is a "hello world":
Contents of hello.pl:
main :-
format("hello~n").
The way to run it from the command line without entering the top level:
$ swipl -g main -t halt hello.pl
hello
Now here is a program that on the interactive top level would backtrack and have multiple solutions. Just to demonstrate, here is the program, in a file print.pl:
main :-
between(1, 3, X),
format("~w~n", [X]).
and if you do it from the top level, you get:
?- [print].
true.
?- main.
1
true ;
2
true ;
3
true.
Fine. If we do it as the "hello world" above however:
$ swipl -g main -t halt print.pl
1
Now, I will add a "fail" like you did. Here is my new program in a file printfail.pl:
main :-
between(1, 3, X),
format("~w~n", [X]),
fail.
When I run this from the command line:
swipl -g main -t halt printfail.pl
1
2
3
ERROR: -g main: false
Bottom line: throwing away solutions by running the program non-interactively is throwing you off.
And a footnote: The fail causes your program to backtrack even when a solution was found. The backtracking undoes the bindings but cannot undo the side effect.
Try it with main as:
main:-
%which women have both a father and a son in the database?
%trace,
woman(X), parent(X, S), parent(F, X), man(F), man(S), print(X), nl,
%man(M),
%print(M), nl,
fail.
main:- halt.
This shows the duplicate:
$ swipl -q -s parent3.pl -g main
cris
cris
Can use https://www.swi-prolog.org/pldoc/doc_for?object=distinct/2 to remove the duplicate, i.e.:
distinct(X, (woman(X), parent(X, S), parent(F, X), man(F), man(S))), print(X), nl,
I am looking at the tests in TCL source tree and I see this one in compExpr-old.test:
test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} {
expr $
} $
It looks wrong to me: the test runs the script expr $ and expects the return value is "$". Is my interpretation right?
It cannot be right because expr $ is wrong syntactically.
I checked out tcltest.tcl, the definition of tcltest::test is so long, wish someone can help me over here.
I don't know what version of the test suite you are looking at (probably some 8.4 variant?), but when I look at the whole of that test in the Tcl trunk, I see this:
test compExpr-old-14.17 {CompilePrimaryExpr: string primary that looks like var ref} -body {
expr $
} -returnCodes error -match glob -result *
In this case, it is checking that the result is an error and that the value of the result (i.e., the content of the error message) glob matches with *, i.e., is anything (effectively ignoring it). That is, the test checks that an error is obtained from expr $ and otherwise doesn't care.
The test you posted (which uses an older syntax for tcltest) won't pass on modern versions of Tcl. But in 8.4, it did pass; this was an area where Tcl's semantics changed between 8.4 and 8.5:
dkf$ tclsh8.4
% expr $
$
% exit
dkf$ tclsh8.5
% expr $
invalid character "$"
in expression "$"
% exit
Quick guide to Tcltest test cases: The -body describes a scrip to run, the -returnCode can be used to select whether normal results or errors are expected, the -result can be used to say what string to expect as a result of the body script, and -match can be used to pick an alternate matching scheme than the default (exact string equality). There's also -constraints for specifying preconditions on a test, -setup for doing setup code, and -cleanup for cleanup code. The two leading mandatory arguments are the name of the test (which must be unique within a test suite for your own sanity) and a short description of the test, used in reporting of failures.
In the old syntax (used in much of Tcl's test suite because updating it is a ton of boring work), you instead had the same two mandatory arguments, then an optional list of constraints (as for -constraints), then a mandatory body (as for -body), then the mandatory string to match for equality (as for -result). Less flexible, but not too hard to understand.
Readers:
I’ve spent a few days investigating the following incidents without successfully identifying the cause. I’m writing in regard to ksh scripts I wrote to the ksh88 standards which have run for years on many HP-UX/PA-RISC and Solaris/Sparc platforms, and, even a few Linux/x86_64) platforms … until this week. Upon running the scripts on CentOS 6.4/x86-x64 with Korn shell “Version AJM 93u+ 2012-08-01”, non-null values being returned to the Caller by some functions are retrieved by the Caller as null values.
Specifically, in the edited excerpts following, the variable ToDo always contains a value in fSendReqToSvr prior to fSendReqToSvr returning. When fSendReqToSvr returns in fGetFileStatusFromSvr, Todo is assigned a null value. The context of this script is as a child invoked by another ksh script run from cron. I’ve included the code reassigning stdout and stderr on the chance this is somehow significant.
What don’t I understand?
OS:
CentOS-6.4 (x86-64) Development Installation
Korn Shell:
Version: AJM 93u+ 2012-08-01
Package: Ksh.x86_64 20120801-10.el6
...
function fLogOpen
{
...
exec 3>$1 #C# Assigned Fd 3 to a log file
#C# stdout and stderr are redirected to log file as insurance that
#C# no “errant” output from script (1700 lines) “escapes” from script.
#C# stdout and stderr restored in fLogClose.
exec 4>&1
exec 1>&3
exec 5>&2
exec 2>&3
...
}
...
#C# Invokes curl on behalf of caller and evaluates
function fSendReqToSvr
{
typeset Err=0 ... \
ToDo=CONTINUE ... \
CL=”$2” ...
...
curl $CL > $CurlOutFFS 2>&1 &
gCurlPId=$!
while (( iSecsLeft > 0 )) ; do
...
#C# Sleep N secs, check status of curl with “kill -0 $gCurlPId”
#C# and if curl exited, get return code from “wait $gCurlPId”.
...
done
...
#C# Evaluate curl return code and contents of CurlOutFFS file to
#C# determine what to set ToDo to.
...
print –n -– “$ToDo” #C# ToDo confirmed to always have a value here
return $Err
}
...
function fGetFileStatusFromSvr
{
typeset Err=0 ... \
ToDo=CONTINUE ... \
...
...
ToDo=$( fSendReqToSvr “$iSessMaxSecs” “$CurlCmdLine” )
Err=$?
#C# ToDo contains null here
...
return $Err
}
One problem here is that we don't see the code responsible for the ToDo result.
If this worked properly with ksh88 before, you may have a problem if you don't have good tests for the individual functions, as ksh88 and ksh93 have many subtle and not so subtle differences.
Paradoxically, ksh93 is easier to drop in as a replacement for /bin/sh (The mythical Bourne shell :-) than for ksh88.
The reason for this is that ksh88 introduced extensions to the shell that were further enhanced and changed in ksh93.
One example that may touch on your question is arithmetic, which is limited to integer arithmetic in ksh88 and got extended to floating point in ksh93.
Any utility expecting integer values can be fed results from arithmetic expressions in ksh88.
It may choke on the floating point results returned in ksh93.
Please supply a proper code sample that shows how the ToDo value is determined.
Good morning fellow programmers!
i'm working on a project using haskell, and i've wanted to know how to run a haskell function without having to type two lines on ghci, for example
ghci filename.hs function
This can only be done doing:
ghci filename.hs
function
????
I'm looking for something like the main () in C,which runs automatically when you compile the program
Is there something like that?
I've been checking the -e option on ghci, but i cant seem to get it to work!
Thank you very much!
Cheers!
You're probably looking for ghc -e instead:
> echo 'foo x y z = x+y*z' > foo.hs % let's make a foo.hs file
> ghc foo.hs -e 'foo 1 2 3' % call the function in foo.hs
=> 7
Also, note that you can also use the :reload command in ghci. Load the file in ghci, edit, type :reload and test again. Also, if this seems too tedious, you can also define a ghci macro which allows you to reload and test your function at the same time:
> :def test \x -> return (":reload\n" ++ x)
> :test foo 1 2 3
=> Ok, modules loaded: Foo.
7
If you're looking to build real programs instead of quickly testing
your functions, then you'd better read the other answers on writing
main functions.
I assume function has the type IO (). Then you can just let main = function, and use for example runhaskell modulename from the command line. As in C, main is a special function.
To clarify a bit, just in case: If your function is a pure one, i.e. one whose type does not invovle IO, you can't really "run it". I guess it's a simplification to say this, but essentially what GHCi does is to call print function. If you want to mimic this, you can use something like main = print function and use runhaskell. This assumes function's type is an instance of Show.
Wanted to understand the example line of code given # perldoc.perl.org for getlogin
$login = getlogin || getpwuid($<) || "Kilroy";
It seems like it tries to get the user name from getlogin or getpwuid, but if either fails, use Kilroy instead. I might be wrong, so please correct me. Also, I've been using getlogin() in previous scripts - is there any difference between getlogin() and getlogin?
What is this code safeguarding against? Also, what purpose does $< serve? I'm not exactly sure what to search for when looking up what $< is and what it does.
EDIT
found this in the special variables section - still don't know why it is needed or what is does in the example above
$<
The real uid of this process.
(Mnemonic: it's the uid you came from,
if you're running setuid.) You can
change both the real uid and the
effective uid at the same time by
using POSIX::setuid(). Since changes
to $< require a system call, check $!
after a change attempt to detect any
possible errors.
EDIT x2
Is this line comparable to the above example? (it is currently what I use to avoid any potential problems with "cron" executing a script - i've never run into this problem, but i am trying to avoid any theoretical problem)
my $username = getlogin(); if(!($username)){$username = 'jsmith';}
You're exactly right. If getlogin returns false it will test getpwuid($<) if that returns false it will set $login to "Kilroy"
$< is the real uid of the process. Even if you're running in a setuid environment it will return the original uid the process was started from.
Edit to match your edit :)
getpwuid returns the user's name by the UID (in scalar context, which would be the case here). You would want $< as an argumnent in case the program switched UID at some point ($< is the original one it was started with)
The only thing it's guarding against is the fact that on some systems, in some circumstances, getlogin can fail to return anything useful. In particular, getlogin only does anything useful when the process it's in has a "controlling terminal", which non-interactive processes may not. See, e.g., http://www.perlmonks.org/?node_id=663562.
I think the fallback of "Kilroy" is just for fun, though in principle getpwuid can fail to return anything useful too. (You can have a user ID that doesn't have an entry in the password database.)