I feel really stupid, and feel like I'm missing something.
I've basically got two files:
module.pl for the universal logic rules (meant to be reusable)
state.pl one for the current scenario
In the module file (module.pl) I've declared:
inside(Food,Eater,T) :-
isTime(T),
injestEvent(InjEvent),
justAfter(T,InjEvent),
actorOfEvent(InjEvent, Eater),
objectOfEvent(InjEvent, Food).
Q1) I've had to declare all those other predicates with singleton variables (in the same file), just to stop module.pl complaining they don't exist:
isTime(_T).
justAfter(_Time,_Event).
actorOfEvent(_Event, _ActorOfEvent).
objectOfEvent(_Event,_ActorOfEvent).
Is that right?
Q2) I can't use those predicates like justAfter/2 my other file without it saying:
Local definition of user:justAfter/2 overrides weak import from module
How can I use the predicates I've imported from my module, rather redefining it?
Prolog modules were designed to hide auxiliary predicates. They don't provide a concept of interface that allows separating predicate declarations from predicate definitions. That's why the compiler complains if you export predicates that are not defined. From your description, I assume you tried something like:
----- module.pl -----
:- module(module, [
inside/3, isTime/1, injestEvent/1, justAfter/2, actorOfEvent/2, objectOfEvent/2
]).
inside(Food,Eater,T) :-
isTime(T),
injestEvent(InjEvent),
justAfter(T,InjEvent),
actorOfEvent(InjEvent, Eater),
objectOfEvent(InjEvent, Food).
---------------------
which results in:
?- [module].
ERROR: Exported procedure module:justAfter/2 is not defined
ERROR: Exported procedure module:isTime/1 is not defined
ERROR: Exported procedure module:injestEvent/1 is not defined
ERROR: Exported procedure module:objectOfEvent/2 is not defined
ERROR: Exported procedure module:actorOfEvent/2 is not defined
true.
You attempted to workaround this error by adding local definitions. But this just result in the second problem you describe. When you do something like:
?- use_module(module).
You import all the predicates exported by module, including those that you want to define in state.pl. Therefore, the compiler warns you, when loading state.pl, that this file is overriding those predicates. E.g. with:
----- state.pl -----
isTime(1).
injestEvent(injEvent).
justAfter(1, injEvent).
actorOfEvent(injEvent, eater).
objectOfEvent(injEvent, food).
--------------------
we get:
?- [state].
Warning: /Users/pmoura/Desktop/state.pl:1:
Local definition of user:isTime/1 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:2:
Local definition of user:injestEvent/1 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:3:
Local definition of user:justAfter/2 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:4:
Local definition of user:actorOfEvent/2 overrides weak import from module
Warning: /Users/pmoura/Desktop/state.pl:5:
Local definition of user:objectOfEvent/2 overrides weak import from module
true.
Although these are warnings and not errors, calling the inside/3 predicate will not give you what you want:
?- inside(Food,Eater,T).
true.
Where are the bindings?!? Let's trace the call to highlight the cause:
?- trace.
true.
[trace] ?- inside(Food,Eater,T).
Call: (8) module:inside(_2508, _2510, _2512) ? creep
Call: (9) module:isTime(_2512) ? creep
Exit: (9) module:isTime(_2512) ? creep
Call: (9) module:injestEvent(_2804) ? creep
Exit: (9) module:injestEvent(_2804) ? creep
Call: (9) module:justAfter(_2512, _2806) ? creep
Exit: (9) module:justAfter(_2512, _2806) ? creep
Call: (9) module:actorOfEvent(_2804, _2510) ? creep
Exit: (9) module:actorOfEvent(_2804, _2510) ? creep
Call: (9) module:objectOfEvent(_2804, _2508) ? creep
Exit: (9) module:objectOfEvent(_2804, _2508) ? creep
Exit: (8) module:inside(_2508, _2510, _2512) ? creep
true.
The trace makes it clear that the "state" predicates are being called in the wrong context.
A clean solution is to use Logtalk objects instead of Prolog modules. Logtalk extends Prolog and supports most systems, including SWI-Prolog. It supports interfaces/protocols as first-class entities (which solve the first problem you mention) and supports inheritance and calling predicates in their usage context (which solves the second problem). You could use e.g.
----- common.lgt -----
:- object(common).
:- public([
inside/3, isTime/1, injestEvent/1, justAfter/2, actorOfEvent/2, objectOfEvent/2
]).
inside(Food,Eater,T) :-
% call the next predicates in "self", i.e. in the
% object that received the inside/3 message
::isTime(T),
::injestEvent(InjEvent),
::justAfter(T,InjEvent),
::actorOfEvent(InjEvent, Eater),
::objectOfEvent(InjEvent, Food).
:- end_object.
----------------------
and then represent "state" as:
----- state.lgt -----
:- object(state, extends(common)).
isTime(1).
injestEvent(injEvent).
justAfter(1, injEvent).
actorOfEvent(injEvent, eater).
objectOfEvent(injEvent, food).
:- end_object.
---------------------
A quick test (after installing Logtalk):
$ swilgt
...
?- {common, state}.
...
true.
?- state::inside(Food,Eater,T).
Food = food,
Eater = eater,
T = 1.
As a bonus, you can define as many "state" objects as you need. You can also have default definitions for the "state" predicates in the common object. These will be inherited and used when the "state" objects don't provide a definition for a particular predicate. For example, let's add to common the clause:
objectOfEvent(injEvent, drink).
and delete (or comment out) the clause objectOfEvent(injEvent, food). from state. Save and reload and retrying the query will give you:
?- {*}. % abbreviation for Logtalk's make
% Redefining object common
...
% Redefining object state
...
true.
?- state::inside(Food,Eater,T).
Food = drink,
Eater = eater,
T = 1.
If needed, you can also dynamically create new state objects instead of defining them in source files. For example:
?- create_object(s2, [extends(common)], [], [isTime(42), ...]).
This may not be the answer you were looking for but this is also the case where the best answer is to use the right tool^H^H^H^H encapsulation mechanism for the job. Your programming pattern is also a quite common one (and one of the reasons Logtalk was developed).
It's very simple to add a basic form of 'object orientation'.
Let's say we have a clause in a module logic:
:- module(logic, [inside/4]).
% apply the rule to a specified module (expected to be a state object)
inside(M,Food,Eater,T) :-
M:isTime(T),
M:injestEvent(InjEvent),
M:justAfter(T, InjEvent),
M:actorOfEvent(InjEvent, Eater),
M:objectOfEvent(InjEvent, Food).
and we have a lot of state objects pertinent: in a file state1.pl
isTime(10).
injestEvent(eat).
justAfter(10, eat).
actorOfEvent(eat, mick).
objectOfEvent(eat, food).
and in a file state2.pl
isTime(20).
injestEvent(sleep).
justAfter(20, sleep).
actorOfEvent(sleep, everyone).
objectOfEvent(sleep, dream).
then a possible session:
?- [logic].
true.
?- s1:consult(state1).
true.
?- s2:consult(state2).
true.
?- inside(s1,Food,Eater,T).
Food = food,
Eater = mick,
T = 10.
?- inside(s2,What,Who,T).
What = dream,
Who = everyone,
T = 20.
A small generalization, worth to try:
inside(M,Food,Eater,T) :-
resolve(M),
M:isTime(T),
...
where resolve/1 could be
resolve(M) :- var(M) -> current_module(M), catch(M:isTime(_),_,fail) ; true.
this trick enable 'browsing the objects':
?- inside(M,X,Y,Z).
M = s2,
X = dream,
Y = everyone,
Z = 20 ;
M = s1,
X = food,
Y = mick,
Z = 10 ;
false.
An alternative to CapelliC is the use of Prolog dicts. They have been introduced by SWI-Prolog and since release 1.3.0 they are also available in Jekejeke Prolog. If the receiver is not needed, one can simply use an underscore.
File state1.pl:
:- module(state1, [isTime/2, injestEvent/2, justAfter/3,
actorOfEvent/3, objectOfEvent/3]).
:- reexport(logic).
_.isTime() := 10.
_.injestEvent() := eat.
_.justAfter(10) := eat.
_.actorOfEvent(eat) := mick.
_.objectOfEvent(eat) := food.
File state2.pl:
:- module(state2, [isTime/2, injestEvent/2, justAfter/3,
actorOfEvent/3, objectOfEvent/3]).
:- reexport(logic).
_.isTime() := 20.
_.injestEvent() := sleep.
_.justAfter(20) := sleep.
_.actorOfEvent(sleep) := everyone.
_.objectOfEvent(sleep) := dream.
File logic.pl:
:- module(logic, [inside/4]).
M.inside(Food,Eater) := T :-
T = M.isTime(),
InjEvent = M.injestEvent(),
InjEvent = M.justAfter(T),
Eater = M.actorOfEvent(InjEvent),
Food = M.objectOfEvent(InjEvent).
To make the logic also visible in state1 and state2 use reexport/1. This allows sending a message to state1 or state2, but nevertheless a method from logic will be processed. Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 7.7.19)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
?- T = state1{}.inside(Food,Eater).
T = 10,
Food = food,
Eater = mick.
?- T = state2{}.inside(Food,Eater).
T = 20,
Food = dream,
Eater = everyone.
The exports of isTime/2, injestEvent/2, etc.. will go away with the upcoming release 1.3.1 of Jekejeke Prolog when we have made ('.')/3 call-site aware. But the result for Jekejeke Prolog is the same:
Jekejeke Prolog 3, Runtime Library 1.3.0
(c) 1985-2018, XLOG Technologies GmbH, Switzerland
?- T = state1{}.inside(Food,Eater).
T = 10,
Food = food,
Eater = mick
?- T = state2{}.inside(Food,Eater).
T = 20,
Food = dream,
Eater = everyone
When using emacs or my android app I run
(defun big (num) (setf num2 5)(little num)))
(defun little (num)(+ num2 num))
Little happily accepts num2 but when I run it in my SBCL repl (with sublimetext3) it does not.
Is this correct?
What is a workaround without creating a global variable for num2?
I could just pass a second argument (little num num2)
But this wont work when I am trying to mapcar little over a list. Because I can only have one argument when mapcaring correct?
Please read ยง6. Variables from Practical Common Lisp.
Unlike Emacs Lisp, Common Lisp relies on lexical scope by default (Emacs Lisp is dynamic by default). Dynamic scope (i.e. indefinite scope and dynamic extent) is provided by declaring variables special, and by convention, they are written with asterisks around their names (named "earmuffs"), like *standard-output*. You use defparameter or defvar to declare those variables. Since it has a global effect, you should never use them from inside functions; likewise, your usage of setf is not defined in Common Lisp: no variable named num2 was declared previously in the scope; besides, even if it did, using a global/special variable for local variable is bad style.
Dynamic scope
With special variables, you can for example locally rebind the standard output: the new value is only visible while the code is inside the body of the let binding:
(let ((*standard-output* *error-output*))
(print "Stream redirection"))
By default, print writes to the stream bound to *standard-output*; here, the stream is locally bound to the one given by *error-output*. As soon as you escape the let, *standard-output* reverts to its previous value (imagine there is a stack).
Lexical scope
With lexical scope, your code can only access the bindings that are visible in the text surrounding your code (and the global scope), and the extent is indefinite: it is possible to access a binding (sometimes indirectly) even after the code returns from the let:
(let ((closure
(let ((count 0))
(lambda () (print (incf count))))))
(funcall closure)
(funcall closure))
;; prints:
;; 1
;; 2
The lambda expression creates a closure, which captures the variable named count. Every time you call it, it will increase the count variable and print it. If you evaluate the same code another time, you define another closure and create another variable, with the same name.
Mapcar
Because I can only have one argument when mapcaring correct?
Not exactly; the function called by mapcar should be able to accept at least as many elements as the number of lists that are given to it (and it should also not require more mandatory arguments):
(mapcar (lambda (x y) (* x y))
'(1 2 3)
'(0 3 6))
=> (0 6 18)
(mapcar #'list '(1 2) '(a b) '(+ /))
=> ((1 a +) (2 b /))
The function can also be a closure, and can use special variables.
... with a closure
(defun adder (x)
(lambda (y) (+ x y)))
(mapcar (adder 10) '(0 1 2))
=> (10 11 12)
The adder functions takes a number x and returns a closure which accepts a number y and returns (+ x y).
... with a special variable
If you prefer dynamic scope, use earmuffs and give it a meaningful name:
(defparameter *default-offset* 0)
... and define:
(defun offset (x)
(+ x *default-offset*))
You can then mapcar too:
(let ((*default-offset* 20))
(mapcar #'offset '(1 2 3)))
=> (21 22 23)
As said by jkiiski in comments, you can also declare special variables with (declare (special ...)) where you usually put declarations (when entering a let, a defun, ...). You could also use the special operator progv. This can be useful to have "invisible" variables that are only known by a set of functions to exchange information. You rarely need them.
If eval with (interaction-environment) should have access to everything that's defined within the lexical scope of when it's called, then why am I getting this error when I try to run the below code?
Welcome to DrRacket, version 6.3 [3m].
Language: R5RS; memory limit: 128 MB.
why does this work? object_function: undefined;
cannot reference undefined identifier
Code:
(define (disp x)
(display x))
(eval '(disp "why does this work?") (interaction-environment))
;The below doesn't work
((lambda ()
(define (object_function x)
(display x))
(eval '(object_function "But not this?") (interaction-environment))))
(define (object)
(define (object_function x)
(display x))
(eval '(object_function "And not this?") (interaction-environment)))
(object)
If I change it like so:
;The below does work
(define (object_function x)
(display x))
((lambda ()
(eval '(object_function "Why does it work now?") (interaction-environment))))
(define (object)
(eval '(object_function "And now?") (interaction-environment)))
(object)
Output:
Welcome to DrRacket, version 6.3 [3m].
Language: R5RS; memory limit: 128 MB.
Why does it work now?And now?
With eval by itself it works just fine, but wrap it in a defined function or a lambda and it can't find the locally defined function that is within the same scope that the eval function is called.
I may be misunderstanding how eval or interaction-environment deal with lexical scope, but if someone can shed some light on this that would be helpful.
When eval evaluates data it does so at top level. The lexical depth from where you call eval is not leaked into the evaluation. The second argument only changes between the three different global environments you can access.
define inside a procedure or let is just a fancy letrec and thus a lexical binding. It will not be available from eval. Top level define makes a global binding and it will be available from eval iff interaction-environment is used.
Implementations don't have to implement interaction-environment, as it is optional. The required environments are null-environment, that only have special forms, and scheme-report-environment, which is the initial environment of the system.
eval is a powerful feature that is usually the wrong solution. Usually you are doing it wrong if you need to use eval.
I'm a noob at lisp, have only been using it for two weeks or so...
I have some global variable declared with setq:
(setq myvar '(WHATEVER))
and a function that is supposed to modify whatever variable I tell it to:
(defun MYFUN (varname)
(setq varname '(POOP))
)
but when I make the call: (MYFUN 'myvar)
and check the value of myvar now it still is (WHATEVER) how do I make the changes that are made in MYFUN persist?
There is no such thing as "declaring a global variable with setq", there is only "set the value of a variable with setq" and if you're doing that in the top lexical environment, the results are amusingly under-defined.
If you look at what the variable varname contains, it may well be the list (poop).
Also, the "q" at the end of setq actually means "quoted" (that is, the setq special form will not evaluate the first (and third, and fifth...) argument, but will do so for the second (and fourth, and sixth...).
It was, historically, used as a convenience, where (set (quote var) value) was less convenient than (setq var value). However, (set var value) has exactly the same effect as (setf (symbol-value var) value) and you should use that.
You're setting the value of the local variable varname, not the global variable whose name it contains. To do what you want you need to use the symbol-value accessor to indirect through it to get the global value's variable.
(defun myfun (varname)
(setf (symbol-value varname) '(poop)))
EDIT: didn't notice this first:
You have local varname and global varname both in the scope of the function body. Local name shadows the global name. So, if you change the local name to var it should work the way you wrote (checked in SBCL 1.2.13). But consider the following stylistic corrections:
For global variables, please use ear-muffs * around the name, so it should be *myvar*. Global variables are special (there is a way to make them normal, but it is not necessarily a good idea). Special variables have dynamic scope, in contrast to lexical scope of normal variables.
The variable must be declared with defvar or defparameter. You can use setq for this but the compiler is going to complain that the variable is not defined. Also, with setq the variable is not going to be special.
For a variable *myvar* to appear special inside the body of the function, it either needs to be declared (with defvar or defparameter) before function definition, or it needs to be declared special in the body of the function with (declare (special *myvar*)) and then declared with defvar or defparameter.
Here is the code of possible combinations of declarations and respective outputs:
;; This is a model solution:
(defvar *myvar* 'a)
*MYVAR*
(defun foo (var)
(setq *myvar* var))
(foo 'b)
*myvar*
B
;; Not using DEFVAR or DEFPARAMETER
(setq myvar 'a)
A
(defun bar (var)
(setq myvar var))
;; The value of the global MYVAR is still changed
(bar 'b)
myvar
B
(defun show-myvar ()
myvar)
;; But MYVAR is not special
(let ((myvar 'z))
(show-myvar))
B
;; Also can assign value to undeclared variable
(defun bar2 (var)
(setq myvar-1 var))
BAR2
(setq myvar-1 'a)
A
;; And it works
(bar2 'b)
myvar-1
B
;; Finally: show special undeclared (yet) variable
(defun show-special ()
(declare (special *special-var*))
*special-var*)
(defvar *special-var* 'a)
*SPECIAL-VAR*
(let ((*special-var* 'z))
(show-special))
Z
;; The same but with SETQ: variable is still not special
(defun show-special-setq ()
(declare (special *special-var-setq*))
*special-var-setq*)
(setq *special-var-setq* 'a)
A
(let ((*special-var-setq* 'z))
(show-special-setq))
A
In Rebol 2:
>> foo: make object! [a: 10 b: 20]
>> foo/a
== 10
>> foo/b
== 20
>> first foo
== [self a b]
>> second foo
== [make object! [
a: 10
b: 20
] 10 20]
>> third foo
== [a: 10 b: 20]
>> fourth foo
** Script Error: fourth expected series argument of type:
series date port tuple event
** Near: fourth foo
So you can pick out of it as if it were a block for values 1, 2, 3. But doing positional selection is right out in Rebol 3:
>> first foo
** Script error: cannot use pick on object! value
** Where: first
** Near: first foo
I gather that this is deprecated now (like picking out of a function to get its parameter list). However, I'm trying to translate some code that says something like:
bar: construct/with (third foo) mumble
(a) What is the point of that code?
(b) How would I translate it to Rebol 3?
This usage of first, second, third, etc for reflection is indeed deprecated (and it's probably quite obvious why).
The general replacement is REFLECT, which takes a FIELD parameter to specify what information is to be extracted.
REFLECT is in turn wrapped by a group of functions (referred to by some as "reflectors") for convenience: SPEC-OF, BODY-OF, WORDS-OF, VALUES-OF, etc. Those are the preferred replacement for reflection using FIRST et al. Luckily, those "reflectors" have been backported to R2 (2.7.7+) as well.
How to translate third foo to Rebol 3?
The counterpart to reflective THIRD on an object is BODY-OF.
What is the point of the construct/with (third a) b idiom?
It allows you to construct a new object by merging A and B (with values from A taking precedence over B).
So you could, for example, use this idiom to create a full "options" object by merging actual user-provided options with an object of defaults.
a) Construct builds the object without evaluating the spec block. This implies that the spec is of some [set-word! any-type!] form (which it would always be if you are using the body of another object). Construct/with uses a second object (mumble) as the prototype.
b) Object operations appear to have changed as follows:
i) first object is replaced by words-of object
ii) second object is replaced by values-of object
iii) third object is replaced by body-of object or to block! object
Therefore your code can be replaced with:
bar: construct/with body-of foo mumble